/** * Local Trust Ledger — hash-chained JSONL audit trail for code intelligence. * * Binary-compatible with the Python ledger.py implementation. * * Each ForgeOS project maintains a local append-only ledger at * `.forgeos/ledger.jsonl`. Entries are hash-chained using SHA-256 over * the canonical fields "seq:prev_hash:payload_hash:timestamp", producing * a tamper-evident record of every analysis run, review, and metric change. * * Chain hash formula: * chain_hash = SHA-256("{seq}:{prev_hash}:{payload_hash}:{timestamp}") * * JSONL format: one JSON object per line, keys sorted (sort_keys=True), * written with appendFileSync. Matches Python's json.dumps(..., sort_keys=True). * * File locking: Node.js single-threaded event loop provides safe sequential * writes within one process. For cross-process safety, a .ledger.lock file * is created (advisory lock, best-effort) — same approach as Python's * fcntl.LOCK_EX. Full POSIX flock is not available in pure Node stdlib; * the lock file is written atomically and removed after use. * * Entry field order in JSONL (matches Python's sort_keys=True output): * chain_hash, entry_type, payload, payload_hash, prev_hash, schema_version, * seq, signature, source_tree_hash, timestamp */ /** * A single entry in the trust ledger. * * Field names and types match the Python ledger schema exactly. * The JSONL serialization sorts these keys alphabetically (sort_keys=True). */ export interface LedgerEntry { schema_version: string; seq: number; timestamp: string; entry_type: string; payload: Record; payload_hash: string; prev_hash: string; chain_hash: string; source_tree_hash: string | null; signature: string | null; } export interface VerifyResult { valid: boolean; total_entries: number; first_break_at: number | null; message: string; } export interface ChainStats { entry_count: number; first_timestamp: string | null; last_timestamp: string | null; chain_valid: boolean; by_type: Record; shareable_chain_hash: string | null; } export declare class LedgerError extends Error { constructor(message: string); } export declare class ChainIntegrityError extends LedgerError { seq: number; constructor(seq: number, message: string); } /** * Append-only, hash-chained ledger for local code intelligence data. * * The ledger lives at {projectPath}/.forgeos/ledger.jsonl. * * Example: * const ledger = new TrustLedger('/my/project'); * const entry = ledger.append('analysis_snapshot', { quality_score: 82.4 }); * const result = ledger.verifyChain(); * const stats = ledger.getChainStats(); */ export declare class TrustLedger { private ledgerPath; private lockPath; private keyManager; constructor(projectPath: string); /** * Append a new entry to the ledger and return the complete record. * * Optionally binds to git state (sourceTreeHash) and signs the entry * (signature) if keys are available. * * @param entryType - One of the 7 canonical entry types. * @param payload - Arbitrary JSON-serializable payload dict. * @param repoPath - Optional repo path for git binding. * @param signature - Optional pre-computed Ed25519 signature (base64). * If null, the ledger will attempt to self-sign if keys exist. * @returns The complete ledger entry. * @throws LedgerError if the ledger directory does not exist. * @throws Error if entryType is not in ENTRY_TYPES. */ append(entryType: string, payload: Record, repoPath?: string, signature?: string | null): LedgerEntry; /** * Verify the integrity of the entire hash chain. * * Walks every entry in order, recomputing each chain_hash and checking * that it matches the stored value, and that prev_hash matches the * chain_hash of the preceding entry. * * @returns VerifyResult with validity, entry count, and first break location. */ verifyChain(): VerifyResult; /** * Read entries from the ledger with optional filtering. * * @param entryType - If set, only return entries of this type. * @param since - If set, only return entries with timestamp >= this ISO string. * @param limit - Maximum number of entries to return. * @returns Array of entry dicts in chronological order. */ readEntries(entryType?: string, since?: string, limit?: number): LedgerEntry[]; /** * Return the most recent ledger entry, or null if empty. */ getLatest(): LedgerEntry | null; /** * Return aggregate statistics about the ledger chain. * * Matches Python's get_chain_stats() return structure exactly. */ getChainStats(): ChainStats; /** * Write a new entry. * * Advisory file locking via .ledger.lock is used for cross-process safety. * Node.js is single-threaded so within one process this is sequential. */ private appendLocked; /** Read all non-empty lines from the ledger file. */ private readRawLines; /** * Acquire advisory lock by creating .ledger.lock. * Returns true if lock was created (should be released), false if lock * already existed (proceeding anyway — this is advisory only). */ private acquireLock; private releaseLock; } //# sourceMappingURL=ledger.d.ts.map