ruvnet/ruflo · error · Error

both Ed25519 private and public PEM keys are required

Error message

both Ed25519 private and public PEM keys are required

What it means

Key-material guard in createFlywheelReceipt(): signing a receipt requires both an Ed25519 private and public PEM key, and at least one is missing. Receipt creation aborts rather than producing an unsigned (unverifiable) receipt.

Solutions

  1. Generate an Ed25519 keypair and supply both PEM keys
  2. Point the config at existing private and public PEM files

Example fix

Supply both the Ed25519 private PEM and public PEM keys when signing a flywheel receipt; generate a keypair if one is missing.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at v3/@claude-flow/cli/src/services/flywheel-receipt.ts:398 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of ruvnet/ruflo@2602b642d9 (2026-08-18). Data as JSON: /api/errors/1f0f1d14ce2efab7. Report an issue: GitHub.

Appendix: source

Thrown at v3/@claude-flow/cli/src/services/flywheel-receipt.ts:578

    evidence: input.evidence ?? {
      corpusRoles: {
        selectionTaskIds: [],
        promotionHoldoutTaskIds: [],
        guardTaskIds: [],
      },
      verification: {},
      canary: {},
    },
    termVerification: input.termVerification ?? [],
    decision,
    issuedAt: new Date(now).toISOString(),
    expiresAt: new Date(now + (input.ttlMs ?? 24 * 60 * 60 * 1000)).toISOString(),
  } satisfies Omit<FlywheelReceiptPayload, 'receiptId'>;
  const receiptId = sha256Ref(canonicalizeJcs(receiptIdentityPayload(base)));
  const payload: FlywheelReceiptPayload = { ...base, receiptId };
  const receipt: FlywheelEvaluationReceipt = { payload };
  if (input.privateKeyPem || input.publicKeyPem) {
    if (!input.privateKeyPem || !input.publicKeyPem) throw new Error('both Ed25519 private and public PEM keys are required');
    receipt.signature = {
      algorithm: 'ed25519',
      domain: RECEIPT_DOMAIN,
      publicKeyPem: input.publicKeyPem,
      signatureBase64: edSign(null, signedBytes(payload), input.privateKeyPem).toString('base64'),
    };
  }
  return receipt;
}

export interface ReceiptVerification {
  valid: boolean;
  signed: boolean;
  errors: string[];
}

export function verifyFlywheelReceipt(receipt: FlywheelEvaluationReceipt, trustedPublicKeys?: Set<string>): ReceiptVerification {
  // The enforcement half of #3229. Before this, ruflo verified its own

View on GitHub (pinned to 2602b642d9)