ruvnet/ruflo · error

ArtifactLedger requires an explicit signingKey — hardcoded d

Error message

ArtifactLedger requires an explicit signingKey — hardcoded defaults are not secure

What it means

ArtifactLedger signs and content-hashes every artifact envelope at creation, so it refuses to construct without an explicit `signingKey`. The error message states the design intent: a hardcoded default key would let anyone forge artifact signatures, so there is deliberately no fallback. Constructing `new ArtifactLedger()` or omitting signingKey in the config throws immediately.

Source

Thrown at v3/@claude-flow/guidance/src/artifacts.ts:226

  tags?: string[];
}

/**
 * A tamper-evident ledger for production artifacts.
 *
 * Every artifact is signed and content-hashed on creation. The ledger
 * supports retrieval by ID, run, kind, cell, and arbitrary search queries.
 * Full lineage traversal allows tracing any artifact back through its
 * entire ancestry chain.
 */
export class ArtifactLedger {
  private artifacts: Map<string, Artifact> = new Map();
  private readonly signingKey: string;
  private readonly maxArtifacts: number;

  constructor(config: ArtifactLedgerConfig = {}) {
    if (!config.signingKey) {
      throw new Error('ArtifactLedger requires an explicit signingKey — hardcoded defaults are not secure');
    }
    this.signingKey = config.signingKey;
    this.maxArtifacts = config.maxArtifacts ?? DEFAULT_MAX_ARTIFACTS;
  }

  /**
   * Record a new artifact in the ledger.
   *
   * Computes the content hash, signs the envelope, and stores the artifact.
   * If the ledger exceeds maxArtifacts, the oldest artifact is evicted.
   *
   * @param params - Artifact creation parameters
   * @returns The fully signed and stored Artifact
   */
  record(params: RecordArtifactParams): Artifact {
    const contentHash = this.computeContentHash(params.content);
    const contentSize = this.computeContentSize(params.content);

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Pass an explicit key: `new ArtifactLedger({ signingKey: process.env.ARTIFACT_SIGNING_KEY! })`
  2. Resolve secrets from your secret manager BEFORE constructing the ledger
  3. Fail fast at boot: assert required env vars are present before any component construction
  4. Never add a fallback default key — generate one per environment if needed (`node -e "console.log(crypto.randomBytes(32).toString('hex'))"`)

Example fix

// before
const ledger = new ArtifactLedger({ maxArtifacts: 1000 }); // throws

// after
const signingKey = requiredEnv('ARTIFACT_SIGNING_KEY');
const ledger = new ArtifactLedger({ signingKey, maxArtifacts: 1000 });
Defensive patterns

Strategy: validation

Validate before calling

if (!process.env.ARTIFACT_SIGNING_KEY) {
  throw new Error('ARTIFACT_SIGNING_KEY must be set before creating ArtifactLedger');
}

Prevention

When it happens

Trigger: `new ArtifactLedger()` with no config; `new ArtifactLedger({ maxArtifacts: 500 })` — any config object without signingKey; key read from `process.env` in an environment where the variable is unset (CI, fresh clone).

Common situations: Following older examples that predate the required-key hardening; CI pipelines missing the env var; secrets loaded asynchronously (vault fetch) after the ledger is constructed; local dev without a .env entry.

Related errors


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