@claude-flow/embeddings
Version:
V3 Embedding Service - OpenAI, Transformers.js, Agentic-Flow (ONNX), Mock providers with hyperbolic embeddings, normalization, and chunking
156 lines • 6.61 kB
TypeScript
/**
* ADR-121 Phase 18 — Chained witness manifests + benchmark ledger.
*
* Phase 15 shipped per-run signed manifests. That makes each benchmark
* number cryptographically attestable in isolation. What it doesn't
* give you: a HISTORY you can trust. If someone edits an old
* manifest, its signature still verifies (it's still a valid sign
* of the new content) — only a separate audit catches the rewrite.
*
* This module ships the missing layer: a **hash chain** over the
* witness manifests. Each new manifest signs the previous manifest's
* contentHash; any retroactive edit to a historical entry breaks
* every subsequent signature in the chain. Anyone can replay the
* ledger and detect a rewrite at any position.
*
* The chain structure mirrors git: each entry has a `prevContentHash`
* field; the genesis entry has `prevContentHash: null`. The
* canonical hash of an entry includes `prevContentHash`, so a
* historical edit forces a hash mismatch all the way down.
*
* Used together with the witness primitives from `witness.ts`. Each
* benchmark run produces one ledger entry; the script that runs
* benchmarks appends to a single `bench-witness/ledger.json` over
* time.
*/
import { type BenchmarkWitnessInput, type WitnessedManifest } from './witness.js';
import { type KeyObject } from 'node:crypto';
/**
* A chained ledger entry — a regular WitnessedManifest plus the
* `prevContentHash` field that ties it to the previous entry.
*
* Genesis entry: prevContentHash = null.
* Subsequent entries: prevContentHash = previous entry's contentHash.
*/
/**
* Phase 24 — independent third-party signature attached to an existing
* entry's contentHash. Co-signers don't change the hash; they just
* attest "I observed this entry and verified its primary signature."
*
* Threshold verification (`verifyEntry(entry, { minSignatures: N })`)
* counts the PRIMARY signature plus every valid cosignature; passes
* when N or more are valid. M-of-N adversarial benchmarking just sets
* the threshold to M.
*/
export interface CosignatureRecord {
/** Ed25519 signature over the entry's contentHash (hex). */
readonly signature: string;
/** SPKI-DER hex of the co-signer's public key. */
readonly publicKey: string;
/** ISO-8601 timestamp of when the co-signature was attached. */
readonly signedAt: string;
/** Optional human-readable label (e.g. "third-party verifier"). */
readonly signerLabel?: string;
}
export interface LedgerEntry extends WitnessedManifest {
/** sha256-hex of the previous entry's contentHash, or null for genesis. */
readonly prevContentHash: string | null;
/** 1-based position in the chain. */
readonly sequence: number;
/**
* Phase 24 — optional additional signatures from third-party verifiers.
* Backward-compatible: existing single-signer entries omit this field
* and verify at minSignatures=1 (counting just the primary signature).
*/
readonly cosignatures?: ReadonlyArray<CosignatureRecord>;
}
export interface BenchmarkLedger {
/** Schema version of the ledger format. */
readonly version: 1;
/** Append-only entries in chain order. */
readonly entries: ReadonlyArray<LedgerEntry>;
}
/**
* Append a new benchmark run to an existing ledger (or initialize a
* fresh one if the ledger is undefined). Returns the new entry plus
* the updated ledger.
*
* Each call uses the supplied keypair so a single signer attests the
* full chain. Pass `undefined` to generate an ephemeral keypair per
* call (each entry will then have its own publicKey — verifiable but
* less useful for "is this from the same signer?" queries).
*/
export declare function appendToLedger(prevLedger: BenchmarkLedger | undefined, input: BenchmarkWitnessInput, keypair?: {
privateKey: KeyObject;
publicKey: KeyObject;
}): {
ledger: BenchmarkLedger;
entry: LedgerEntry;
};
/**
* Verify a single ledger entry: checks its own signature via the
* base witness verifier (which validates the contentHash + signature
* + public-key pair).
*
* Phase 24 — pass `{ minSignatures: N }` to require N or more total
* valid signatures (primary + cosignatures). Default 1 — backward-
* compatible with single-signer entries.
*/
export declare function verifyEntry(entry: LedgerEntry, options?: {
minSignatures?: number;
}): boolean;
/**
* Add a third-party co-signature to an existing ledger entry. Returns
* a new entry (the original is not mutated). The new co-signer signs
* the entry's existing contentHash — does NOT change the hash itself,
* preserving the chain integrity.
*/
export declare function coSign(entry: LedgerEntry, keypair: {
privateKey: KeyObject;
publicKey: KeyObject;
}, options?: {
signerLabel?: string;
signedAt?: string;
}): LedgerEntry;
/**
* Verify a single co-signature against the canonical contentHash.
* Exposed for tooling that wants to per-signer validate (e.g.
* dashboards that mark each co-signer green/red individually).
*/
export declare function verifyCosignatureAgainst(contentHash: string, cs: CosignatureRecord): boolean;
export interface ChainVerifyResult {
/** True if every entry's signature verifies AND the chain links match. */
readonly valid: boolean;
/** Total entries inspected. */
readonly entryCount: number;
/** First entry index (0-based) where verification failed, or -1. */
readonly firstFailureAt: number;
/** Human-readable reason for the failure (or '' if valid). */
readonly reason: string;
}
/**
* Verify the entire ledger end-to-end. Checks:
* 1. ledger.version is recognized
* 2. each entry's signature verifies
* 3. each entry's prevContentHash matches the previous entry's contentHash
* 4. sequence numbers are monotonically increasing starting from 1
*
* Returns a structured result rather than throwing — callers want
* to know WHICH entry broke the chain (an attacker who edits entry
* N breaks signatures from N onward; a missing entry N breaks
* sequence integrity).
*/
export declare function verifyLedger(ledger: BenchmarkLedger, options?: {
minSignatures?: number;
}): ChainVerifyResult;
/**
* Generate a fresh ed25519 keypair for use across multiple ledger
* appends from the same signer. Equivalent to
* `generateEphemeralKeypair` from witness.ts; re-exported here so
* callers building ledgers don't need to import both modules.
*/
export declare function generateLedgerKeypair(): {
privateKey: KeyObject;
publicKey: KeyObject;
};
//# sourceMappingURL=witness-ledger.d.ts.map