'use strict'; const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const { SecretsStore } = require('../../src/security/secrets-store'); const { canonical, signEnvelope, createEnvelopeVerifier } = require('../../src/services/etahen-link-agent'); const { createFileJobJournal, createEtahenLinkOrchestrator } = require('../../src/services/etahen-link-orchestrator'); const { createEtahenLinkKeyring, createEtahenLinkAuditLedger, createEtahenLinkRecoverySupervisor, openManagedEtahenLinkJournal, } = require('../../src/services/etahen-link-operations'); const runtimeEpoch = 'runtime_12345678'; function fixture(t, options = {}) { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-link-operations-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); let clock = options.now ?? 1_000_000; const secrets = new SecretsStore({ filePath: path.join(root, 'secrets', 'secrets.enc.json'), keyFile: path.join(root, 'secrets', 'master.key') }); const audits = []; const keyring = createEtahenLinkKeyring({ secrets, stateFile: path.join(root, 'link', 'keyring.json'), root: path.join(root, 'link'), now: () => clock, randomBytes: size => Buffer.alloc(size, options.randomByte ?? 0x11), audit: (event, details) => audits.push({ event, details }), }); return { root, secrets, keyring, audits, now: () => clock, advance: ms => { clock += ms; } }; } function job(id = 'job_rotate1234') { return { jobId: id, type: 'package.install', runtimeEpoch, confirmationEpoch: runtimeEpoch, input: { artifactId: 'artifact_12345678' } }; } test('keyring bootstraps encrypted material and exposes identifiers only', t => { const f = fixture(t); const status = f.keyring.status(); assert.match(status.activeKeyId, /^key_[a-f0-9]{24}$/); assert.equal(status.pending, null); assert.deepEqual(status.previousKeyIds, []); assert.doesNotMatch(JSON.stringify(status), /1111111111111111/); const publicState = fs.readFileSync(path.join(f.root, 'link', 'keyring.json'), 'utf8'); assert.doesNotMatch(publicState, /1111111111111111/); assert.doesNotMatch(publicState, /journal\.[A-Za-z0-9_-]+/); assert.match(fs.readFileSync(path.join(f.root, 'secrets', 'secrets.enc.json'), 'utf8'), /"data"/); }); test('staged rotation atomically rekeys a journal without changing jobs', t => { const f = fixture(t); const opened = openManagedEtahenLinkJournal({ file: path.join(f.root, 'link', 'jobs.json'), root: path.join(f.root, 'link'), keyring: f.keyring, now: f.now }); opened.journal.begin(job(), 'a'.repeat(64)); const before = opened.journal.get('job_rotate1234'); const oldKeyId = opened.journal.integrity().keyId; const pending = f.keyring.prepareRotation({ reason: 'scheduled-maintenance' }); const rotated = f.keyring.commitRotation(opened.journal); assert.equal(rotated.activeKeyId, pending.keyId); assert.notEqual(rotated.activeKeyId, oldKeyId); const after = opened.journal.get('job_rotate1234'); assert.deepEqual({ ...after, recordHash: null }, { ...before, recordHash: null }); assert.notEqual(after.recordHash, before.recordHash); assert.equal(openManagedEtahenLinkJournal({ file: path.join(f.root, 'link', 'jobs.json'), root: path.join(f.root, 'link'), keyring: f.keyring, now: f.now }).journal.integrity().keyId, pending.keyId); assert.throws(() => f.keyring.resolveJournalKey(oldKeyId), /retired/i); }); test('rotation fails before retiring a key shared by multiple durable journals', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const first = openManagedEtahenLinkJournal({ file: path.join(directory, 'jobs-one.json'), root: directory, keyring: f.keyring, now: f.now }).journal; const second = openManagedEtahenLinkJournal({ file: path.join(directory, 'jobs-two.json'), root: directory, keyring: f.keyring, now: f.now }).journal; first.begin(job('job_multijrnl1'), '1'.repeat(64)); second.begin(job('job_multijrnl2'), '2'.repeat(64)); assert.throws(() => f.keyring.prepareRotation({ reason: 'must-rekey-all-journals' }), error => error?.code === 'ETAHEN_KEYRING_JOURNAL'); assert.equal(f.keyring.status().pending, null); assert.equal(openManagedEtahenLinkJournal({ file: path.join(directory, 'jobs-one.json'), root: directory, keyring: f.keyring, now: f.now }).journal.get('job_multijrnl1').status, 'accepted'); assert.equal(openManagedEtahenLinkJournal({ file: path.join(directory, 'jobs-two.json'), root: directory, keyring: f.keyring, now: f.now }).journal.get('job_multijrnl2').status, 'accepted'); }); test('rotation target binding prevents an unrelated journal from aborting an in-flight rekey', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const firstFile = path.join(directory, 'jobs-target.json'); const secondFile = path.join(directory, 'jobs-racer.json'); const first = openManagedEtahenLinkJournal({ file: firstFile, root: directory, keyring: f.keyring, now: f.now }).journal; first.begin(job('job_targetbind'), '3'.repeat(64)); const pending = f.keyring.prepareRotation({ reason: 'bind-rekey-target' }); const hooked = { integrity: () => first.integrity(), rotateIntegrityKey(descriptor) { const result = first.rotateIntegrityKey(descriptor); assert.throws(() => openManagedEtahenLinkJournal({ file: secondFile, root: directory, keyring: f.keyring, now: f.now }), error => error?.code === 'ETAHEN_KEYRING_JOURNAL'); return result; } }; const committed = f.keyring.commitRotation(hooked); assert.equal(committed.activeKeyId, pending.keyId); assert.equal(committed.pending, null); assert.equal(openManagedEtahenLinkJournal({ file: firstFile, root: directory, keyring: f.keyring, now: f.now }).journal.get('job_targetbind').status, 'accepted'); }); test('a durable rotation binding cannot be retargeted before its first journal write', t => { const f = fixture(t); const activeKeyId = f.keyring.status().activeKeyId; const firstId = `journal_${'a'.repeat(24)}`; const secondId = `journal_${'b'.repeat(24)}`; f.keyring.prepareRotation({ reason: 'bind-empty-target' }); const interrupted = { integrity: () => ({ keyId: activeKeyId, commitmentId: firstId }), rotateIntegrityKey() { throw Object.assign(new Error('simulated rekey interruption'), { code: 'REKEY_INTERRUPTED' }); } }; assert.throws(() => f.keyring.commitRotation(interrupted), error => error?.code === 'REKEY_INTERRUPTED'); const bound = f.keyring.status().pending; assert.equal(bound.phase, 'rekeying'); assert.equal(bound.targetJournalId, firstId); const unrelated = { integrity: () => ({ keyId: activeKeyId, commitmentId: secondId }), rotateIntegrityKey() { throw new Error('must not run'); } }; assert.throws(() => f.keyring.commitRotation(unrelated), error => error?.code === 'ETAHEN_KEYRING_JOURNAL'); assert.equal(f.keyring.status().pending.targetJournalId, firstId); assert.equal(f.keyring.reconcileJournalKey(activeKeyId, firstId).outcome, 'pending-aborted'); }); test('empty managed journals register durably and block unsafe single-target rotation', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const firstFile = path.join(directory, 'jobs-empty-a.json'); const secondFile = path.join(directory, 'jobs-empty-b.json'); const first = openManagedEtahenLinkJournal({ file: firstFile, root: directory, keyring: f.keyring, now: f.now }).journal; const second = openManagedEtahenLinkJournal({ file: secondFile, root: directory, keyring: f.keyring, now: f.now }).journal; assert.equal(f.keyring.journalAnchor(first.integrity().commitmentId).generation, 0); assert.equal(f.keyring.journalAnchor(second.integrity().commitmentId).generation, 0); assert.throws(() => f.keyring.prepareRotation({ reason: 'must-not-strand-empty-writer' }), error => error?.code === 'ETAHEN_KEYRING_JOURNAL'); assert.equal(second.begin(job('job_emptywriter'), '4'.repeat(64)).status, 'accepted'); assert.equal(openManagedEtahenLinkJournal({ file: secondFile, root: directory, keyring: f.keyring, now: f.now }).journal.get('job_emptywriter').status, 'accepted'); }); test('journal and audit commitment caps reject before corrupting keyring state', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); for (let index = 0; index < 32; index += 1) openManagedEtahenLinkJournal({ file: path.join(directory, `jobs-cap-${index}.json`), root: directory, keyring: f.keyring, now: f.now }); assert.throws(() => openManagedEtahenLinkJournal({ file: path.join(directory, 'jobs-cap-overflow.json'), root: directory, keyring: f.keyring, now: f.now }), error => error?.code === 'ETAHEN_KEYRING_RETENTION'); assert.doesNotThrow(() => createEtahenLinkKeyring({ secrets: f.secrets, stateFile: path.join(directory, 'keyring.json'), root: directory, now: f.now, randomBytes: size => Buffer.alloc(size, 0x34) })); for (let index = 0; index < 32; index += 1) createEtahenLinkAuditLedger({ file: path.join(directory, `audit-cap-${index}.json`), root: directory, keyring: f.keyring, now: f.now }).append('etahen.link.audit.cap', { index, outcome: 'allowed' }); const overflow = createEtahenLinkAuditLedger({ file: path.join(directory, 'audit-cap-overflow.json'), root: directory, keyring: f.keyring, now: f.now }); assert.throws(() => overflow.append('etahen.link.audit.cap', { index: 32, outcome: 'denied' }), error => error?.code === 'ETAHEN_KEYRING_RETENTION'); const publicState = JSON.parse(fs.readFileSync(path.join(directory, 'keyring.json'), 'utf8')); assert.equal(Object.keys(publicState.journalAnchors).length, 32); assert.equal(Object.keys(publicState.auditAnchors).length, 32); assert.doesNotThrow(() => createEtahenLinkKeyring({ secrets: f.secrets, stateFile: path.join(directory, 'keyring.json'), root: directory, now: f.now, randomBytes: size => Buffer.alloc(size, 0x35) })); }); test('failed rotation persistence does not advance in-memory key state', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'keyring.json'); const initialBytes = fs.statSync(file).size; const constrained = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: file, root: path.dirname(file), now: f.now, randomBytes: size => Buffer.alloc(size, 0x22), maxBytes: initialBytes + 8 }); assert.throws(() => constrained.prepareRotation({ reason: 'quota-interruption' }), error => error?.code === 'ETAHEN_OPERATIONS_QUOTA'); assert.equal(constrained.status().pending, null); const reopened = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: file, root: path.dirname(file), now: f.now, randomBytes: size => Buffer.alloc(size, 0x33) }); assert.equal(reopened.status().pending, null); assert.equal(reopened.status().activeKeyId, constrained.status().activeKeyId); }); test('stale keyring writers cannot overwrite newer authenticated state', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'keyring.json'); const stale = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: file, root: path.dirname(file), now: f.now, randomBytes: size => Buffer.alloc(size, 0x44) }); const prepared = f.keyring.prepareRotation({ reason: 'authoritative-rotation' }); assert.throws(() => stale.prepareRotation({ reason: 'stale-rotation' }), error => error?.code === 'ETAHEN_KEYRING_CONCURRENT'); const reopened = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: file, root: path.dirname(file), now: f.now, randomBytes: size => Buffer.alloc(size, 0x55) }); assert.equal(reopened.status().pending.keyId, prepared.keyId); assert.equal(reopened.status().pending.reason, 'authoritative-rotation'); }); test('key rotation audit intent survives a sink interruption and replays idempotently', t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-link-key-audit-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const secretOptions = { filePath: path.join(root, 'secrets', 'secrets.enc.json'), keyFile: path.join(root, 'secrets', 'master.key') }; const stateFile = path.join(root, 'link', 'keyring.json'); const events = []; const dedupe = new Set(); let interruptPrepared = true; const audit = (event, details, options = {}) => { if (event === 'etahen.link.keyring.rotation-prepared' && interruptPrepared) { interruptPrepared = false; throw Object.assign(new Error('audit unavailable'), { code: 'AUDIT_DOWN' }); } if (options.dedupeKey && dedupe.has(options.dedupeKey)) return; if (options.dedupeKey) dedupe.add(options.dedupeKey); events.push({ event, details, options }); }; const first = createEtahenLinkKeyring({ secrets: new SecretsStore(secretOptions), stateFile, root: path.dirname(stateFile), now: () => 1_000_000, randomBytes: size => Buffer.alloc(size, 0x61), audit }); assert.throws(() => first.prepareRotation({ reason: 'durable-audit-replay' }), error => error?.code === 'AUDIT_DOWN'); assert.ok(first.status().pending); const reopened = createEtahenLinkKeyring({ secrets: new SecretsStore(secretOptions), stateFile, root: path.dirname(stateFile), now: () => 1_000_000, randomBytes: size => Buffer.alloc(size, 0x62), audit }); assert.equal(reopened.status().pending.reason, 'durable-audit-replay'); createEtahenLinkKeyring({ secrets: new SecretsStore(secretOptions), stateFile, root: path.dirname(stateFile), now: () => 1_000_000, randomBytes: size => Buffer.alloc(size, 0x63), audit }); assert.equal(events.filter(item => item.event === 'etahen.link.keyring.rotation-prepared').length, 1); }); test('stale independent secret stores cannot erase a committed pending key', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'keyring.json'); const secretOptions = { filePath: path.join(f.root, 'secrets', 'secrets.enc.json'), keyFile: path.join(f.root, 'secrets', 'master.key') }; const staleSecrets = new SecretsStore(secretOptions); const stale = createEtahenLinkKeyring({ secrets: staleSecrets, stateFile: file, root: path.dirname(file), now: f.now, randomBytes: size => Buffer.alloc(size, 0x66) }); const prepared = f.keyring.prepareRotation({ reason: 'retain-pending-secret' }); assert.throws(() => stale.prepareRotation({ reason: 'stale-secret-store' }), error => error?.code === 'ETAHEN_KEYRING_CONCURRENT'); const reloadedSecrets = new SecretsStore(secretOptions); assert.equal(reloadedSecrets.has(`etahen.link.journal.${prepared.keyId}`), true); const reopened = createEtahenLinkKeyring({ secrets: reloadedSecrets, stateFile: file, root: path.dirname(file), now: f.now, randomBytes: size => Buffer.alloc(size, 0x77) }); assert.equal(reopened.resolvePendingKey(prepared.keyId).keyId, prepared.keyId); }); test('concurrent bootstrap cannot overwrite the winning encrypted key material', t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-link-bootstrap-race-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const stateFile = path.join(root, 'link', 'keyring.json'); const secretOptions = { filePath: path.join(root, 'secrets', 'secrets.enc.json'), keyFile: path.join(root, 'secrets', 'master.key') }; const staleSecrets = new SecretsStore(secretOptions); const winningSecrets = new SecretsStore(secretOptions); let winner; let triggered = false; const hookedSecrets = { get: name => staleSecrets.get(name), set: (name, value) => staleSecrets.set(name, value), has(name) { if (!triggered) { triggered = true; winner = createEtahenLinkKeyring({ secrets: winningSecrets, stateFile, root: path.dirname(stateFile), now: () => 1_000_000, randomBytes: size => Buffer.alloc(size, 0xb1) }); } return staleSecrets.has(name); }, }; assert.throws(() => createEtahenLinkKeyring({ secrets: hookedSecrets, stateFile, root: path.dirname(stateFile), now: () => 1_000_000, randomBytes: size => Buffer.alloc(size, 0xb2) }), error => error?.code === 'ETAHEN_KEYRING_CONCURRENT'); const reopened = createEtahenLinkKeyring({ secrets: new SecretsStore(secretOptions), stateFile, root: path.dirname(stateFile), now: () => 1_000_000, randomBytes: size => Buffer.alloc(size, 0xb3) }); assert.equal(reopened.status().activeKeyId, winner.status().activeKeyId); assert.equal(reopened.activeKey().keyId, winner.status().activeKeyId); }); test('orphaned writer locks are reclaimed without bypassing malformed locks', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const keyringFile = path.join(directory, 'keyring.json'); const orphan = file => fs.writeFileSync(`${file}.lock`, JSON.stringify({ schemaVersion: 1, pid: process.pid, threadId: require('node:worker_threads').threadId, token: require('node:crypto').randomUUID(), createdAt: Date.now() })); orphan(keyringFile); assert.doesNotThrow(() => f.keyring.prepareRotation({ reason: 'orphan-lock-recovery' })); const journalFile = path.join(directory, 'jobs.json'); const journal = openManagedEtahenLinkJournal({ file: journalFile, root: directory, keyring: f.keyring, now: f.now }).journal; orphan(journalFile); assert.doesNotThrow(() => journal.begin(job('job_lockreclaim'), '9'.repeat(64))); const auditFile = path.join(directory, 'audit.json'); const ledger = createEtahenLinkAuditLedger({ file: auditFile, root: directory, keyring: f.keyring, now: f.now }); orphan(auditFile); assert.doesNotThrow(() => ledger.append('etahen.link.lock.reclaimed', { outcome: 'allowed' })); fs.writeFileSync(`${auditFile}.lock`, '{"schemaVersion":1,"pid":"tampered"}'); assert.throws(() => ledger.append('etahen.link.lock.blocked', { outcome: 'denied' }), error => error?.code === 'ETAHEN_AUDIT_BUSY'); fs.rmSync(`${auditFile}.lock`); if (process.ppid > 0 && process.ppid !== process.pid) { fs.writeFileSync(`${auditFile}.lock`, JSON.stringify({ schemaVersion: 1, pid: process.ppid, threadId: 0, token: require('node:crypto').randomUUID(), createdAt: Date.now() })); assert.throws(() => ledger.append('etahen.link.lock.active', { outcome: 'denied' }), error => error?.code === 'ETAHEN_AUDIT_BUSY'); } }); test('failed orphan verification restores a canonical fail-closed lock', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'keyring.json'); fs.writeFileSync(`${file}.lock`, JSON.stringify({ schemaVersion: 1, pid: process.pid, threadId: require('node:worker_threads').threadId, token: require('node:crypto').randomUUID(), createdAt: Date.now() })); const originalRead = fs.readFileSync; fs.readFileSync = function injectedRead(target, ...args) { if (String(target).includes('.lock.reclaim.')) throw Object.assign(new Error('simulated lock read failure'), { code: 'EIO' }); return originalRead.call(this, target, ...args); }; try { assert.throws(() => f.keyring.prepareRotation({ reason: 'must-stay-fail-closed' }), error => error?.code === 'ETAHEN_KEYRING_BUSY'); } finally { fs.readFileSync = originalRead; } assert.equal(fs.existsSync(`${file}.lock`), true); fs.rmSync(`${file}.lock`); }); test('lock release failure preserves committed journal state and forces reopen', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'jobs-release.json'); const options = { file, root: path.dirname(file), keyring: f.keyring, now: f.now }; const journal = openManagedEtahenLinkJournal(options).journal; const originalUnlink = fs.unlinkSync; let interrupt = true; fs.unlinkSync = function injectedUnlink(target, ...args) { if (interrupt && String(target) === `${file}.lock`) { interrupt = false; throw Object.assign(new Error('simulated release failure'), { code: 'EACCES' }); } return originalUnlink.call(this, target, ...args); }; try { assert.throws(() => journal.begin(job('job_releaseerr'), '5'.repeat(64)), error => error?.code === 'EACCES'); } finally { fs.unlinkSync = originalUnlink; } assert.throws(() => journal.get('job_releaseerr'), error => error?.code === 'ETAHEN_JOURNAL_RESTART_REQUIRED'); fs.rmSync(`${file}.lock`); const reopened = openManagedEtahenLinkJournal(options).journal; assert.equal(reopened.get('job_releaseerr').status, 'accepted'); assert.equal(reopened.list().length, 1); }); test('restart reconciles both rotation crash windows deterministically', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'jobs.json'); const opened = openManagedEtahenLinkJournal({ file, root: path.dirname(file), keyring: f.keyring, now: f.now }); const oldKeyId = opened.journal.integrity().keyId; const pending = f.keyring.prepareRotation({ reason: 'crash-window' }); assert.throws(() => f.keyring.reconcileJournalKey(pending.keyId), error => error?.code === 'ETAHEN_KEYRING_JOURNAL'); assert.equal(f.keyring.reconcileJournalKey(oldKeyId).outcome, 'pending-aborted'); assert.equal(f.keyring.status().pending, null); const second = f.keyring.prepareRotation({ reason: 'crash-after-rekey' }); const interrupted = { integrity: () => opened.journal.integrity(), rotateIntegrityKey(descriptor) { opened.journal.rotateIntegrityKey(descriptor); throw Object.assign(new Error('simulated crash after rekey'), { code: 'REKEY_COMMITTED' }); } }; assert.throws(() => f.keyring.commitRotation(interrupted), error => error?.code === 'REKEY_COMMITTED'); assert.equal(f.keyring.status().pending.phase, 'rekeying'); const restarted = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: path.join(f.root, 'link', 'keyring.json'), root: path.join(f.root, 'link'), now: f.now, randomBytes: size => Buffer.alloc(size, 0x33) }); const commitmentId = opened.journal.integrity().commitmentId; assert.throws(() => restarted.reconcileJournalKey(oldKeyId, commitmentId), error => error?.code === 'ETAHEN_KEYRING_JOURNAL'); assert.equal(restarted.status().pending.keyId, second.keyId); assert.equal(restarted.reconcileJournalKey(second.keyId, commitmentId).outcome, 'pending-committed'); assert.equal(restarted.status().activeKeyId, second.keyId); }); test('an interrupted pending-key cleanup cannot roll back the committed abort', t => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-link-abort-cleanup-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const secretOptions = { filePath: path.join(root, 'secrets', 'secrets.enc.json'), keyFile: path.join(root, 'secrets', 'master.key') }; const store = new SecretsStore(secretOptions); let rejectDelete = false; const secrets = { get: name => store.get(name), has: name => store.has(name), set(name, value) { if (rejectDelete && name.startsWith('etahen.link.journal.') && value === '') throw Object.assign(new Error('cleanup unavailable'), { code: 'CLEANUP_DOWN' }); return store.set(name, value); } }; const stateFile = path.join(root, 'link', 'keyring.json'); const keyring = createEtahenLinkKeyring({ secrets, stateFile, root: path.dirname(stateFile), now: () => 1_000_000, randomBytes: size => Buffer.alloc(size, 0x71) }); const activeKeyId = keyring.status().activeKeyId; const pending = keyring.prepareRotation({ reason: 'abort-cleanup-crash' }); rejectDelete = true; assert.throws(() => keyring.reconcileJournalKey(activeKeyId), error => error?.code === 'CLEANUP_DOWN'); assert.equal(keyring.status().pending, null); const reopened = createEtahenLinkKeyring({ secrets: new SecretsStore(secretOptions), stateFile, root: path.dirname(stateFile), now: () => 1_000_000 }); assert.equal(reopened.status().pending, null); assert.equal(reopened.status().activeKeyId, activeKeyId); assert.throws(() => reopened.resolveJournalKey(pending.keyId), /unknown/i); }); test('stale managed journal writers cannot erase durable replay evidence', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'jobs.json'); const options = { file, root: path.dirname(file), keyring: f.keyring, now: f.now }; const current = openManagedEtahenLinkJournal(options).journal; const stale = openManagedEtahenLinkJournal(options).journal; current.begin(job('job_current123'), 'a'.repeat(64)); assert.throws(() => stale.begin(job('job_stale12345'), 'b'.repeat(64)), error => error?.code === 'ETAHEN_JOURNAL_CONCURRENT'); const reopened = openManagedEtahenLinkJournal(options).journal; assert.deepEqual(reopened.list().map(item => item.jobId), ['job_current123']); }); test('journal rejects non-object audit details without mutating reopenable state', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'jobs-audit-shape.json'); const options = { file, root: path.dirname(file), keyring: f.keyring, now: f.now }; const journal = openManagedEtahenLinkJournal(options).journal; assert.throws(() => journal.recordAudit({ event: 'etahen.link.audit.invalid', dedupeKey: 'invalid_primitive', details: 'primitive' }), error => error?.code === 'ETAHEN_JOURNAL_AUDIT'); assert.throws(() => journal.begin(job('job_auditshape1'), 'a'.repeat(64), { event: 'etahen.link.audit.invalid', dedupeKey: 'invalid_array', details: [] }), error => error?.code === 'ETAHEN_JOURNAL_AUDIT'); journal.begin(job('job_auditshape2'), 'b'.repeat(64)); assert.throws(() => journal.transition('job_auditshape2', 'completed', { installed: false }, { event: 'etahen.link.audit.invalid', dedupeKey: 'invalid_transition', details: 42 }), error => error?.code === 'ETAHEN_JOURNAL_AUDIT'); assert.equal(journal.get('job_auditshape2').status, 'accepted'); assert.equal(journal.auditEvidence().length, 0); const reopened = openManagedEtahenLinkJournal(options).journal; assert.equal(reopened.get('job_auditshape2').status, 'accepted'); assert.equal(reopened.auditEvidence().length, 0); }); test('journal validates the durable job identity before accepting it', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'jobs-identity-shape.json'); const options = { file, root: path.dirname(file), keyring: f.keyring, now: f.now }; const journal = openManagedEtahenLinkJournal(options).journal; assert.throws(() => journal.begin({ ...job('job_badepoch1'), runtimeEpoch: 'x' }, 'c'.repeat(64)), error => error?.code === 'ETAHEN_JOURNAL_JOB'); const deceptive = job('job_deceptive1'); Object.defineProperty(deceptive, 'toJSON', { value: () => ({ ...deceptive, jobId: 'job_changed123' }) }); assert.throws(() => journal.begin(deceptive, 'd'.repeat(64)), error => error?.code === 'ETAHEN_JOURNAL_JOB'); assert.equal(journal.list().length, 0); journal.begin(job('job_identityok'), 'e'.repeat(64)); const reopened = openManagedEtahenLinkJournal(options).journal; assert.equal(reopened.get('job_identityok').job.jobId, 'job_identityok'); assert.equal(reopened.list().length, 1); }); test('managed journal commitment detects valid-record truncation and deletion', t => { const first = fixture(t); const firstFile = path.join(first.root, 'link', 'jobs.json'); const firstOptions = { file: firstFile, root: path.dirname(firstFile), keyring: first.keyring, now: first.now }; const journal = openManagedEtahenLinkJournal(firstOptions).journal; journal.begin(job('job_retained123'), 'a'.repeat(64)); journal.begin(job('job_removed123'), 'b'.repeat(64)); const truncated = JSON.parse(fs.readFileSync(firstFile, 'utf8')); truncated.jobs.pop(); fs.writeFileSync(firstFile, JSON.stringify(truncated)); assert.throws(() => openManagedEtahenLinkJournal(firstOptions), error => ['ETAHEN_JOURNAL_CORRUPT', 'ETAHEN_JOURNAL_ANCHOR'].includes(error?.code)); const second = fixture(t); const secondFile = path.join(second.root, 'link', 'jobs.json'); const secondOptions = { file: secondFile, root: path.dirname(secondFile), keyring: second.keyring, now: second.now }; openManagedEtahenLinkJournal(secondOptions).journal.begin(job('job_deleted123'), 'c'.repeat(64)); fs.rmSync(secondFile); assert.throws(() => openManagedEtahenLinkJournal(secondOptions), error => error?.code === 'ETAHEN_JOURNAL_ANCHOR'); }); test('combined public journal rollback and encrypted commitment deletion fails closed', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const file = path.join(directory, 'jobs.json'); const keyringFile = path.join(directory, 'keyring.json'); const options = { file, root: directory, keyring: f.keyring, now: f.now }; const journal = openManagedEtahenLinkJournal(options).journal; journal.begin(job('job_first12345'), 'a'.repeat(64)); const oldJournal = fs.readFileSync(file); const oldKeyring = fs.readFileSync(keyringFile); journal.begin(job('job_second1234'), 'b'.repeat(64)); fs.writeFileSync(file, oldJournal); fs.writeFileSync(keyringFile, oldKeyring); const anchorId = `journal_${require('node:crypto').createHash('sha256').update(path.resolve(file)).digest('hex').slice(0, 24)}`; f.secrets.set(`etahen.link.journal-anchor.${anchorId}`, ''); const rolledBackKeyring = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: keyringFile, root: directory, now: f.now, randomBytes: size => Buffer.alloc(size, 0xab) }); assert.throws(() => openManagedEtahenLinkJournal({ ...options, keyring: rolledBackKeyring }), error => error?.code === 'ETAHEN_JOURNAL_ANCHOR'); }); test('newer encrypted journal commitment rejects public keyring and file rollback', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const file = path.join(directory, 'jobs.json'); const keyringFile = path.join(directory, 'keyring.json'); const options = { file, root: directory, keyring: f.keyring, now: f.now }; const journal = openManagedEtahenLinkJournal(options).journal; journal.begin(job('job_first67890'), 'a'.repeat(64)); const oldJournal = fs.readFileSync(file); const oldKeyring = fs.readFileSync(keyringFile); journal.begin(job('job_second6789'), 'b'.repeat(64)); fs.writeFileSync(file, oldJournal); fs.writeFileSync(keyringFile, oldKeyring); const rolledBackKeyring = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: keyringFile, root: directory, now: f.now, randomBytes: size => Buffer.alloc(size, 0xac) }); assert.throws(() => openManagedEtahenLinkJournal({ ...options, keyring: rolledBackKeyring }), error => error?.code === 'ETAHEN_JOURNAL_ANCHOR'); }); test('staged encrypted journal commitment reconciles before keyring commit', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const file = path.join(directory, 'jobs.json'); const keyringFile = path.join(directory, 'keyring.json'); const options = { file, root: directory, keyring: f.keyring, now: f.now }; const journal = openManagedEtahenLinkJournal(options).journal; journal.begin(job('job_first24680'), 'a'.repeat(64)); const oldKeyring = fs.readFileSync(keyringFile); journal.begin(job('job_second2468'), 'b'.repeat(64)); fs.writeFileSync(keyringFile, oldKeyring); const interruptedKeyring = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: keyringFile, root: directory, now: f.now, randomBytes: size => Buffer.alloc(size, 0xad) }); const reopened = openManagedEtahenLinkJournal({ ...options, keyring: interruptedKeyring }).journal; assert.deepEqual(reopened.list().map(item => item.jobId), ['job_first24680', 'job_second2468']); assert.equal(reopened.integrity().generation, 2); }); test('staged empty-journal registration reconciles after a mirror-only crash', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const file = path.join(directory, 'jobs-empty-crash.json'); let mirrorWritten = false; let interruptRegistry = true; const interruptedSecrets = { has: name => f.secrets.has(name), get: name => f.secrets.get(name), set(name, value) { if (String(name).startsWith('etahen.link.journal-anchor.')) { f.secrets.set(name, value); mirrorWritten = true; return; } if (name === 'etahen.link.commitment-registry' && mirrorWritten && interruptRegistry) { interruptRegistry = false; throw Object.assign(new Error('simulated registry interruption'), { code: 'REGISTRY_INTERRUPTED' }); } f.secrets.set(name, value); }, }; const interrupted = createEtahenLinkKeyring({ secrets: interruptedSecrets, stateFile: path.join(directory, 'keyring.json'), root: directory, now: f.now, randomBytes: size => Buffer.alloc(size, 0x36) }); assert.throws(() => openManagedEtahenLinkJournal({ file, root: directory, keyring: interrupted, now: f.now }), error => error?.code === 'REGISTRY_INTERRUPTED'); assert.equal(fs.existsSync(file), false); const restarted = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: path.join(directory, 'keyring.json'), root: directory, now: f.now, randomBytes: size => Buffer.alloc(size, 0x37) }); const journal = openManagedEtahenLinkJournal({ file, root: directory, keyring: restarted, now: f.now }).journal; assert.equal(restarted.journalAnchor(journal.integrity().commitmentId).pending, false); journal.begin(job('job_emptycrash'), '7'.repeat(64)); assert.equal(openManagedEtahenLinkJournal({ file, root: directory, keyring: restarted, now: f.now }).journal.get('job_emptycrash').status, 'accepted'); }); test('managed open adopts a valid legacy schema-two journal before upgrading it', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const file = path.join(directory, 'jobs-legacy-two.json'); const descriptor = f.keyring.activeKey(); const legacyWriter = createFileJobJournal({ file, root: directory, integrityKey: descriptor.key, integrityKeyId: descriptor.keyId, now: f.now }); legacyWriter.begin(job('job_legacytwo1'), '8'.repeat(64)); const legacy = JSON.parse(fs.readFileSync(file, 'utf8')); legacy.schemaVersion = 2; delete legacy.integrity; fs.writeFileSync(file, JSON.stringify(legacy, null, 2)); const managed = openManagedEtahenLinkJournal({ file, root: directory, keyring: f.keyring, now: f.now }).journal; assert.equal(managed.get('job_legacytwo1').status, 'accepted'); assert.equal(managed.integrity().generation, 0); managed.begin(job('job_legacytwo2'), '9'.repeat(64)); const reopened = openManagedEtahenLinkJournal({ file, root: directory, keyring: f.keyring, now: f.now }).journal; assert.deepEqual(reopened.list().map(item => item.jobId), ['job_legacytwo1', 'job_legacytwo2']); assert.equal(reopened.integrity().generation, 1); }); test('missing, wrong and retired journal keys fail closed', t => { const f = fixture(t); const old = f.keyring.status().activeKeyId; assert.throws(() => f.keyring.resolveJournalKey('key_' + 'f'.repeat(24)), /unknown/i); const journal = openManagedEtahenLinkJournal({ file: path.join(f.root, 'link', 'jobs.json'), root: path.join(f.root, 'link'), keyring: f.keyring, now: f.now }).journal; const pending = f.keyring.prepareRotation({ reason: 'retire-old' }); f.keyring.commitRotation(journal); assert.equal(f.keyring.status().activeKeyId, pending.keyId); assert.throws(() => f.keyring.resolveJournalKey(old), /retired/i); f.secrets.set(`etahen.link.journal.${pending.keyId}`, ''); assert.throws(() => f.keyring.resolveJournalKey(pending.keyId), /missing/i); }); test('tampered or symlinked keyring metadata cannot select keys', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'keyring.json'); const state = JSON.parse(fs.readFileSync(file, 'utf8')); state.active.keyId = 'key_' + 'f'.repeat(24); fs.writeFileSync(file, JSON.stringify(state)); assert.throws(() => createEtahenLinkKeyring({ secrets: f.secrets, stateFile: file, root: path.dirname(file) }), /keyring/i); if (process.platform !== 'win32') { fs.rmSync(file); fs.symlinkSync(path.join(f.root, 'secrets', 'secrets.enc.json'), file); assert.throws(() => createEtahenLinkKeyring({ secrets: f.secrets, stateFile: file, root: path.dirname(file) }), /symlink/i); } }); test('missing public keyring state recovers from the registry while a missing root fails closed', t => { const first = fixture(t); const firstFile = path.join(first.root, 'link', 'keyring.json'); const activeKeyId = first.keyring.status().activeKeyId; fs.rmSync(firstFile); const recovered = createEtahenLinkKeyring({ secrets: first.secrets, stateFile: firstFile, root: path.dirname(firstFile) }); assert.equal(recovered.status().activeKeyId, activeKeyId); assert.equal(fs.existsSync(firstFile), true); const second = fixture(t); const secondFile = path.join(second.root, 'link', 'keyring.json'); second.secrets.set('etahen.link.keyring.root', ''); assert.throws(() => createEtahenLinkKeyring({ secrets: second.secrets, stateFile: secondFile, root: path.dirname(secondFile) }), error => error?.code === 'ETAHEN_KEYRING_ROOT'); assert.equal(second.secrets.has('etahen.link.keyring.root'), false); }); test('legacy registry recovery preserves its authenticated shape across restarts', t => { const f = fixture(t); const stateFile = path.join(f.root, 'link', 'keyring.json'); const legacy = JSON.parse(fs.readFileSync(stateFile, 'utf8')); delete legacy.auditAnchors; delete legacy.journalAnchors; delete legacy.auditEvidence; const digestValue = { ...legacy }; delete digestValue.stateHash; legacy.stateHash = require('node:crypto').createHmac('sha256', Buffer.from(f.secrets.get('etahen.link.keyring.root'), 'hex')).update(canonical(digestValue)).digest('hex'); f.secrets.set('etahen.link.commitment-registry', JSON.stringify({ schemaVersion: 1, previousStateHash: '0'.repeat(64), state: legacy })); fs.rmSync(stateFile); const first = createEtahenLinkKeyring({ secrets: f.secrets, stateFile, root: path.dirname(stateFile), now: f.now }); assert.equal(first.status().activeKeyId, legacy.active.keyId); const second = createEtahenLinkKeyring({ secrets: f.secrets, stateFile, root: path.dirname(stateFile), now: f.now }); assert.equal(second.status().activeKeyId, legacy.active.keyId); }); test('encrypted keyring registry is mandatory and detects genesis rollback', t => { const missing = fixture(t); const missingFile = path.join(missing.root, 'link', 'keyring.json'); missing.secrets.set('etahen.link.commitment-registry', ''); assert.throws(() => createEtahenLinkKeyring({ secrets: missing.secrets, stateFile: missingFile, root: path.dirname(missingFile), now: missing.now }), error => error?.code === 'ETAHEN_KEYRING_REGISTRY'); const f = fixture(t); const directory = path.join(f.root, 'link'); const keyringFile = path.join(directory, 'keyring.json'); const bootstrapState = fs.readFileSync(keyringFile); const jobFile = path.join(directory, 'jobs.json'); openManagedEtahenLinkJournal({ file: jobFile, root: directory, keyring: f.keyring, now: f.now }).journal.begin(job('job_genesis123'), 'e'.repeat(64)); const auditFile = path.join(directory, 'audit.json'); createEtahenLinkAuditLedger({ file: auditFile, root: directory, keyring: f.keyring, now: f.now }).append('etahen.link.genesis', { outcome: 'allowed' }); fs.writeFileSync(keyringFile, bootstrapState); fs.rmSync(jobFile); fs.rmSync(auditFile); const journalAnchorId = `journal_${require('node:crypto').createHash('sha256').update(path.resolve(jobFile)).digest('hex').slice(0, 24)}`; const auditAnchorId = `audit_${require('node:crypto').createHash('sha256').update(path.resolve(auditFile)).digest('hex').slice(0, 24)}`; f.secrets.set(`etahen.link.journal-anchor.${journalAnchorId}`, ''); f.secrets.set(`etahen.link.audit-anchor.${auditAnchorId}`, ''); assert.throws(() => createEtahenLinkKeyring({ secrets: f.secrets, stateFile: keyringFile, root: directory, now: f.now }), error => error?.code === 'ETAHEN_KEYRING_REGISTRY'); }); test('authenticated audit ledger redacts secrets and deduplicates decisions', t => { const f = fixture(t); const ledger = createEtahenLinkAuditLedger({ file: path.join(f.root, 'link', 'audit.json'), root: path.join(f.root, 'link'), keyring: f.keyring, now: f.now }); const first = ledger.append('etahen.link.dispatch.denied', { jobId: 'job_audit1234', outcome: 'denied', token: 'raw-token', reason: 'bad-signature' }, { dedupeKey: 'deny_job_audit1234_r1' }); const duplicate = ledger.append('etahen.link.dispatch.denied', { jobId: 'job_audit1234', outcome: 'denied' }, { dedupeKey: 'deny_job_audit1234_r1' }); assert.deepEqual(duplicate, first); assert.equal(ledger.list().length, 1); assert.equal(first.details.token, '[REDACTED]'); assert.doesNotMatch(fs.readFileSync(path.join(f.root, 'link', 'audit.json'), 'utf8'), /raw-token/); }); test('public audit identifiers are derived from redacted details', t => { const first = fixture(t); const second = fixture(t); const firstEntry = createEtahenLinkAuditLedger({ file: path.join(first.root, 'link', 'audit.json'), root: path.join(first.root, 'link'), keyring: first.keyring, now: first.now }).append('etahen.link.secret.test', { outcome: 'denied', token: 'short-secret-one' }); const secondEntry = createEtahenLinkAuditLedger({ file: path.join(second.root, 'link', 'audit.json'), root: path.join(second.root, 'link'), keyring: second.keyring, now: second.now }).append('etahen.link.secret.test', { outcome: 'denied', token: 'short-secret-two' }); assert.equal(firstEntry.eventId, secondEntry.eventId); assert.deepEqual(firstEntry.details, secondEntry.details); }); test('audit ledger detects record tampering and tail truncation', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'audit.json'); const options = { file, root: path.dirname(file), keyring: f.keyring, now: f.now }; const ledger = createEtahenLinkAuditLedger(options); ledger.append('etahen.link.one', { outcome: 'allowed' }); ledger.append('etahen.link.two', { outcome: 'denied' }); const tampered = JSON.parse(fs.readFileSync(file, 'utf8')); tampered.entries[0].details.outcome = 'allowed-after-tamper'; fs.writeFileSync(file, JSON.stringify(tampered)); assert.throws(() => createEtahenLinkAuditLedger(options), /audit/i); const f2 = fixture(t); const file2 = path.join(f2.root, 'link', 'audit.json'); const options2 = { file: file2, root: path.dirname(file2), keyring: f2.keyring, now: f2.now }; const fresh = createEtahenLinkAuditLedger(options2); fresh.append('etahen.link.one', { outcome: 'allowed' }); fresh.append('etahen.link.two', { outcome: 'denied' }); const truncated = JSON.parse(fs.readFileSync(file2, 'utf8')); truncated.entries.pop(); truncated.entryCount = truncated.entries.length; truncated.headHash = truncated.entries.at(-1).recordHash; fs.writeFileSync(file2, JSON.stringify(truncated)); assert.throws(() => createEtahenLinkAuditLedger(options2), /audit/i); }); test('audit ledger detects reordered records and sequence gaps', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'audit.json'); const options = { file, root: path.dirname(file), keyring: f.keyring, now: f.now }; const ledger = createEtahenLinkAuditLedger(options); ledger.append('etahen.link.one', { outcome: 'allowed' }); ledger.append('etahen.link.two', { outcome: 'denied' }); const reordered = JSON.parse(fs.readFileSync(file, 'utf8')); reordered.entries.reverse(); fs.writeFileSync(file, JSON.stringify(reordered)); assert.throws(() => createEtahenLinkAuditLedger(options), /audit/i); const f2 = fixture(t); const file2 = path.join(f2.root, 'link', 'audit.json'); const options2 = { file: file2, root: path.dirname(file2), keyring: f2.keyring, now: f2.now }; const fresh = createEtahenLinkAuditLedger(options2); fresh.append('etahen.link.one', { outcome: 'allowed' }); fresh.append('etahen.link.two', { outcome: 'denied' }); const gap = JSON.parse(fs.readFileSync(file2, 'utf8')); gap.entries[1].sequence = 3; fs.writeFileSync(file2, JSON.stringify(gap)); assert.throws(() => createEtahenLinkAuditLedger(options2), /audit/i); }); test('encrypted audit anchor detects complete ledger deletion', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'audit.json'); const options = { file, root: path.dirname(file), keyring: f.keyring, now: f.now }; createEtahenLinkAuditLedger(options).append('etahen.link.retained', { outcome: 'allowed' }); fs.rmSync(file); assert.throws(() => createEtahenLinkAuditLedger(options), /missing.*anchor/i); }); test('deleting the encrypted anchor mirror cannot hide ledger rollback', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'audit.json'); const options = { file, root: path.dirname(file), keyring: f.keyring, now: f.now }; const ledger = createEtahenLinkAuditLedger(options); ledger.append('etahen.link.first', { outcome: 'allowed' }); const oldLedger = fs.readFileSync(file); ledger.append('etahen.link.second', { outcome: 'allowed' }); const anchorId = `audit_${require('node:crypto').createHash('sha256').update(path.resolve(file)).digest('hex').slice(0, 24)}`; f.secrets.set(`etahen.link.audit-anchor.${anchorId}`, ''); fs.writeFileSync(file, oldLedger); assert.throws(() => createEtahenLinkAuditLedger(options), /anchor/i); }); test('newer encrypted anchor rejects authenticated keyring and ledger rollback', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const file = path.join(directory, 'audit.json'); const keyringFile = path.join(directory, 'keyring.json'); const ledger = createEtahenLinkAuditLedger({ file, root: directory, keyring: f.keyring, now: f.now }); ledger.append('etahen.link.first', { outcome: 'allowed' }); const oldLedger = fs.readFileSync(file); const oldKeyring = fs.readFileSync(keyringFile); ledger.append('etahen.link.second', { outcome: 'allowed' }); fs.writeFileSync(file, oldLedger); fs.writeFileSync(keyringFile, oldKeyring); const rolledBackKeyring = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: keyringFile, root: directory, now: f.now, randomBytes: size => Buffer.alloc(size, 0x88) }); assert.throws(() => createEtahenLinkAuditLedger({ file, root: directory, keyring: rolledBackKeyring, now: f.now }), error => error?.code === 'ETAHEN_AUDIT_ANCHOR'); }); test('combined public rollback and encrypted anchor deletion fails closed', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const file = path.join(directory, 'audit.json'); const keyringFile = path.join(directory, 'keyring.json'); const ledger = createEtahenLinkAuditLedger({ file, root: directory, keyring: f.keyring, now: f.now }); ledger.append('etahen.link.first', { outcome: 'allowed' }); const oldLedger = fs.readFileSync(file); const oldKeyring = fs.readFileSync(keyringFile); ledger.append('etahen.link.second', { outcome: 'allowed' }); fs.writeFileSync(file, oldLedger); fs.writeFileSync(keyringFile, oldKeyring); const anchorId = `audit_${require('node:crypto').createHash('sha256').update(path.resolve(file)).digest('hex').slice(0, 24)}`; f.secrets.set(`etahen.link.audit-anchor.${anchorId}`, ''); const rolledBackKeyring = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: keyringFile, root: directory, now: f.now, randomBytes: size => Buffer.alloc(size, 0x99) }); assert.throws(() => createEtahenLinkAuditLedger({ file, root: directory, keyring: rolledBackKeyring, now: f.now }), error => error?.code === 'ETAHEN_AUDIT_ANCHOR'); }); test('staged encrypted anchor reconciles a crash before public commitment', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const file = path.join(directory, 'audit.json'); const keyringFile = path.join(directory, 'keyring.json'); const ledger = createEtahenLinkAuditLedger({ file, root: directory, keyring: f.keyring, now: f.now }); ledger.append('etahen.link.first', { outcome: 'allowed' }); const oldKeyring = fs.readFileSync(keyringFile); ledger.append('etahen.link.second', { outcome: 'allowed' }); fs.writeFileSync(keyringFile, oldKeyring); const interruptedKeyring = createEtahenLinkKeyring({ secrets: f.secrets, stateFile: keyringFile, root: directory, now: f.now, randomBytes: size => Buffer.alloc(size, 0xaa) }); const reopened = createEtahenLinkAuditLedger({ file, root: directory, keyring: interruptedKeyring, now: f.now }); assert.equal(reopened.verify().entries, 2); assert.equal(reopened.list()[1].event, 'etahen.link.second'); }); test('stale audit writers fail before forking anchored evidence', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'audit.json'); const options = { file, root: path.dirname(file), keyring: f.keyring, now: f.now }; const current = createEtahenLinkAuditLedger(options); const stale = createEtahenLinkAuditLedger(options); current.append('etahen.link.current', { outcome: 'allowed' }); assert.throws(() => stale.append('etahen.link.stale', { outcome: 'allowed' }), error => error?.code === 'ETAHEN_AUDIT_CONCURRENT'); const reopened = createEtahenLinkAuditLedger(options); assert.equal(reopened.verify().entries, 1); assert.equal(reopened.list()[0].event, 'etahen.link.current'); }); test('restart reconciles the single audit write-before-anchor crash window', t => { const f = fixture(t); const file = path.join(f.root, 'link', 'audit.json'); let interrupted = true; const flakyKeyring = { ...f.keyring, writeAuditAnchor(anchorId, value) { if (interrupted) { interrupted = false; throw Object.assign(new Error('simulated anchor interruption'), { code: 'SIMULATED_ANCHOR_STOP' }); } return f.keyring.writeAuditAnchor(anchorId, value); }, }; const interruptedLedger = createEtahenLinkAuditLedger({ file, root: path.dirname(file), keyring: flakyKeyring, now: f.now }); assert.throws(() => interruptedLedger.append('etahen.link.before-anchor', { outcome: 'checkpointed' }), /anchor interruption/i); assert.throws(() => interruptedLedger.append('etahen.link.must-reopen', { outcome: 'blocked' }), error => error?.code === 'ETAHEN_AUDIT_RESTART_REQUIRED'); const reopened = createEtahenLinkAuditLedger({ file, root: path.dirname(file), keyring: f.keyring, now: f.now }); assert.equal(reopened.verify().entries, 1); assert.equal(reopened.list()[0].event, 'etahen.link.before-anchor'); }); test('audit history remains verifiable across journal key rotation', t => { const f = fixture(t); const journal = openManagedEtahenLinkJournal({ file: path.join(f.root, 'link', 'jobs.json'), root: path.join(f.root, 'link'), keyring: f.keyring, now: f.now }).journal; const auditFile = path.join(f.root, 'link', 'audit.json'); const ledger = createEtahenLinkAuditLedger({ file: auditFile, root: path.dirname(auditFile), keyring: f.keyring, now: f.now }); const oldKeyId = ledger.append('etahen.link.before', { outcome: 'allowed' }).keyId; f.keyring.prepareRotation({ reason: 'audit-continuity' }); f.keyring.commitRotation(journal); const newKeyId = ledger.append('etahen.link.after', { outcome: 'allowed' }).keyId; assert.notEqual(newKeyId, oldKeyId); assert.equal(createEtahenLinkAuditLedger({ file: auditFile, root: path.dirname(auditFile), keyring: f.keyring, now: f.now }).verify().entries, 2); }); test('recovery supervisor emits bounded idempotent alerts without retrying or installing', t => { const f = fixture(t); const journal = openManagedEtahenLinkJournal({ file: path.join(f.root, 'link', 'jobs.json'), root: path.join(f.root, 'link'), keyring: f.keyring, now: f.now }).journal; journal.begin(job('job_unknown123'), 'b'.repeat(64)); journal.transition('job_unknown123', 'applying', { installed: false }); journal.recover(runtimeEpoch); const calls = []; const supervisor = createEtahenLinkRecoverySupervisor({ journal, now: f.now, alertAfterMs: 1000, escalateAfterMs: 5000, maxAlerts: 10, audit: (event, details, options) => { calls.push({ event, details, options }); return { event }; } }); assert.equal(supervisor.inspect().alerts.length, 0); f.advance(1000); const attention = supervisor.inspect(); assert.equal(attention.alerts[0].severity, 'attention'); assert.equal(attention.alerts[0].installed, false); supervisor.inspect(); f.advance(4000); const expired = supervisor.inspect(); assert.equal(expired.alerts[0].severity, 'expired'); assert.equal(journal.get('job_unknown123').status, 'outcome_unknown'); assert.equal(journal.get('job_unknown123').result.installed, false); assert.deepEqual(calls.map(item => item.options.dedupeKey), ['recovery_job_unknown123_attention_r3', 'recovery_job_unknown123_attention_r3', 'recovery_job_unknown123_expired_r3']); }); test('repeated recovery does not revise already paused work or advance its journal', t => { const f = fixture(t); const journal = openManagedEtahenLinkJournal({ file: path.join(f.root, 'link', 'jobs.json'), root: path.join(f.root, 'link'), keyring: f.keyring, now: f.now }).journal; journal.begin(job('job_pauseonce1'), '7'.repeat(64)); const first = journal.recover(runtimeEpoch)[0]; const generation = journal.integrity().generation; const second = journal.recover(runtimeEpoch)[0]; assert.equal(first.status, 'paused'); assert.equal(second.revision, first.revision); assert.equal(journal.integrity().generation, generation); }); test('recovery supervision is bounded and validates timing policy', t => { const f = fixture(t); const fakeJournal = { list: () => Array.from({ length: 5 }, (_, index) => ({ jobId: `job_bound${index}0000`, status: 'outcome_unknown', revision: 2, updatedAt: 1, result: { installed: false }, history: [{ status: 'outcome_unknown', at: 1 }] })) }; assert.throws(() => createEtahenLinkRecoverySupervisor({ journal: fakeJournal, alertAfterMs: 5000, escalateAfterMs: 1000 }), /timing policy/i); const report = createEtahenLinkRecoverySupervisor({ journal: fakeJournal, now: () => 10000, alertAfterMs: 1, escalateAfterMs: 2, maxAlerts: 2 }).inspect(); assert.equal(report.alerts.length, 2); assert.equal(report.truncated, true); assert.equal(report.totalAmbiguous, 5); }); test('recovery supervision preserves epoch-zero transition timestamps', () => { const fakeJournal = { list: () => [{ jobId: 'job_epochzero1', status: 'outcome_unknown', revision: 2, updatedAt: 0, result: { installed: false }, history: [{ status: 'accepted', at: 0 }, { status: 'outcome_unknown', at: 0 }] }] }; const report = createEtahenLinkRecoverySupervisor({ journal: fakeJournal, now: () => 10_000, alertAfterMs: 1_000, escalateAfterMs: 5_000 }).inspect(); assert.equal(report.alerts[0].enteredAt, 0); assert.equal(report.alerts[0].ageMs, 10_000); assert.equal(report.alerts[0].severity, 'expired'); }); test('orchestrator mirrors denials, mutation checkpoints and recovery into authenticated audit', t => { const f = fixture(t); const journal = openManagedEtahenLinkJournal({ file: path.join(f.root, 'link', 'jobs.json'), root: path.join(f.root, 'link'), keyring: f.keyring, now: f.now }).journal; const ledger = createEtahenLinkAuditLedger({ file: path.join(f.root, 'link', 'audit.json'), root: path.join(f.root, 'link'), keyring: f.keyring, now: f.now }); const consoleId = 'console_12345678'; const sessionKey = 'a'.repeat(64); const capabilities = [{ name: 'package.install.etahen-dpi-v1', available: true, authorized: true, healthy: true }]; const verifier = createEnvelopeVerifier({ consoleId, runtimeEpoch, sessionKey, now: f.now }); const orchestrator = createEtahenLinkOrchestrator({ consoleId, runtimeEpoch, capabilities, verifyEnvelope: verifier, journal, handlers: { 'package.install': () => { throw Object.assign(new Error('simulated stop'), { code: 'SIMULATED_STOP' }); } }, audit: (event, details, options) => ledger.append(event, details, options), now: f.now }); const deniedJob = { jobId: 'job_denied1234', type: 'package.install', runtimeEpoch, confirmationEpoch: runtimeEpoch, input: { artifactId: 'artifact_12345678', token: 'must-not-leak' } }; const envelopeFor = (value, nonce) => signEnvelope({ jobId: value.jobId, nonce, consoleId, runtimeEpoch, issuedAt: f.now(), expiresAt: f.now() + 1000, job: value }, sessionKey); assert.throws(() => orchestrator.dispatch(envelopeFor(deniedJob, 'nonce_denied123')), /unknown typed job field/i); const activeJob = { jobId: 'job_audited1234', type: 'package.install', runtimeEpoch, confirmationEpoch: runtimeEpoch, input: { artifactId: 'artifact_12345678' } }; assert.throws(() => orchestrator.dispatch(envelopeFor(activeJob, 'nonce_active123')), /simulated stop/i); orchestrator.recover(); const events = ledger.list(); assert.deepEqual(events.map(item => item.event), ['etahen.link.dispatch.denied', 'etahen.link.dispatch.accepted', 'etahen.link.mutation.applying', 'etahen.link.dispatch.failed']); assert.doesNotMatch(JSON.stringify(events), /must-not-leak|aaaaaaaaaaaaaaaa/); assert.equal(journal.get(activeJob.jobId).status, 'outcome_unknown'); }); test('rejected asynchronous post-scan evidence is authenticated and remains uninstalled', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const journal = openManagedEtahenLinkJournal({ file: path.join(directory, 'jobs.json'), root: directory, keyring: f.keyring, now: f.now }).journal; const ledger = createEtahenLinkAuditLedger({ file: path.join(directory, 'audit.json'), root: directory, keyring: f.keyring, now: f.now }); const consoleId = 'console_12345678'; const sessionKey = 'b'.repeat(64); const capabilities = [{ name: 'package.install.etahen-dpi-v1', available: true, authorized: true, healthy: true }]; const verifier = createEnvelopeVerifier({ consoleId, runtimeEpoch, sessionKey, now: f.now }); const orchestrator = createEtahenLinkOrchestrator({ consoleId, runtimeEpoch, capabilities, verifyEnvelope: verifier, journal, handlers: { 'package.install': () => ({ status: 'acknowledged', acknowledged: true, installed: false, postScanRequired: true }) }, verifyInstallation: () => Promise.resolve({ status: 'verified', installed: true }), audit: (event, details, options) => ledger.append(event, details, options), now: f.now }); const activeJob = { jobId: 'job_asyncscan12', type: 'package.install', runtimeEpoch, confirmationEpoch: runtimeEpoch, input: { artifactId: 'artifact_12345678' } }; const envelope = signEnvelope({ jobId: activeJob.jobId, nonce: 'nonce_asyncscan1', consoleId, runtimeEpoch, issuedAt: f.now(), expiresAt: f.now() + 1000, job: activeJob }, sessionKey); assert.equal(orchestrator.dispatch(envelope).status, 'acknowledged'); assert.throws(() => orchestrator.applyPostScan(activeJob.jobId, {}), error => error?.code === 'ETAHEN_POST_SCAN_ASYNC'); assert.equal(journal.get(activeJob.jobId).status, 'outcome_unknown'); assert.equal(journal.get(activeJob.jobId).result.installed, false); assert.deepEqual(ledger.list().slice(-2).map(item => item.event), ['etahen.link.post-scan.started', 'etahen.link.post-scan.failed']); }); test('verified install audit evidence survives a sink interruption without replaying the mutation', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const journal = openManagedEtahenLinkJournal({ file: path.join(directory, 'jobs.json'), root: directory, keyring: f.keyring, now: f.now }).journal; const ledger = createEtahenLinkAuditLedger({ file: path.join(directory, 'audit.json'), root: directory, keyring: f.keyring, now: f.now }); const consoleId = 'console_12345678'; const sessionKey = 'c'.repeat(64); const capabilities = [{ name: 'package.install.etahen-dpi-v1', available: true, authorized: true, healthy: true }]; const verifier = createEnvelopeVerifier({ consoleId, runtimeEpoch, sessionKey, now: f.now }); let handlerCalls = 0; let verifierCalls = 0; let interruptVerified = true; const orchestrator = createEtahenLinkOrchestrator({ consoleId, runtimeEpoch, capabilities, verifyEnvelope: verifier, journal, handlers: { 'package.install': () => { handlerCalls += 1; return { status: 'acknowledged', acknowledged: true, installed: false, postScanRequired: true }; } }, verifyInstallation: () => { verifierCalls += 1; return { status: 'verified', installed: true, scanRunId: 'scanrun_audit123' }; }, audit: (event, details, options) => { if (event === 'etahen.link.post-scan.verified' && interruptVerified) { interruptVerified = false; throw Object.assign(new Error('audit unavailable'), { code: 'AUDIT_DOWN' }); } return ledger.append(event, details, options); }, now: f.now }); const activeJob = { jobId: 'job_auditverify', type: 'package.install', runtimeEpoch, confirmationEpoch: runtimeEpoch, input: { artifactId: 'artifact_12345678' } }; const envelope = signEnvelope({ jobId: activeJob.jobId, nonce: 'nonce_auditverify', consoleId, runtimeEpoch, issuedAt: f.now(), expiresAt: f.now() + 1000, job: activeJob }, sessionKey); assert.equal(orchestrator.dispatch(envelope).status, 'acknowledged'); assert.throws(() => orchestrator.applyPostScan(activeJob.jobId, { coverage: 'complete' }), error => error?.code === 'AUDIT_DOWN'); assert.equal(journal.get(activeJob.jobId).status, 'verified'); assert.equal(journal.get(activeJob.jobId).result.installed, true); const reopenedJournal = openManagedEtahenLinkJournal({ file: path.join(directory, 'jobs.json'), root: directory, keyring: f.keyring, now: f.now }).journal; const restarted = createEtahenLinkOrchestrator({ consoleId, runtimeEpoch, capabilities, verifyEnvelope: verifier, journal: reopenedJournal, handlers: { 'package.install': () => { handlerCalls += 1; throw new Error('must not replay'); } }, verifyInstallation: () => { verifierCalls += 1; throw new Error('must not rescan'); }, audit: (event, details, options) => ledger.append(event, details, options), now: f.now }); assert.doesNotThrow(() => restarted.reconcileAudit()); assert.doesNotThrow(() => restarted.reconcileAudit()); assert.equal(ledger.list().filter(item => item.event === 'etahen.link.post-scan.verified').length, 1); assert.equal(handlerCalls, 1); assert.equal(verifierCalls, 1); }); test('recovery audit retries idempotently after an audit sink interruption', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const journal = openManagedEtahenLinkJournal({ file: path.join(directory, 'jobs.json'), root: directory, keyring: f.keyring, now: f.now }).journal; const ledger = createEtahenLinkAuditLedger({ file: path.join(directory, 'audit.json'), root: directory, keyring: f.keyring, now: f.now }); journal.begin(job('job_reaudit123'), 'd'.repeat(64)); journal.transition('job_reaudit123', 'applying', { installed: false, postScanRequired: true }); let interrupted = true; const orchestrator = createEtahenLinkOrchestrator({ consoleId: 'console_12345678', runtimeEpoch, capabilities: [], verifyEnvelope: value => value, journal, handlers: {}, audit: (event, details, options) => { if (event === 'etahen.link.runtime.recovered' && interrupted) { interrupted = false; throw Object.assign(new Error('audit unavailable'), { code: 'AUDIT_DOWN' }); } return ledger.append(event, details, options); }, now: f.now }); assert.throws(() => orchestrator.recover(), error => error?.code === 'AUDIT_DOWN'); assert.equal(journal.get('job_reaudit123').status, 'outcome_unknown'); assert.doesNotThrow(() => orchestrator.recover()); assert.doesNotThrow(() => orchestrator.recover()); const recovered = ledger.list().filter(item => item.event === 'etahen.link.runtime.recovered'); assert.equal(recovered.length, 1); assert.equal(recovered[0].details.fromStatus, 'applying'); assert.equal(recovered[0].details.status, 'outcome_unknown'); }); test('denial reason survives audit outage after nonce consumption', t => { const f = fixture(t); const directory = path.join(f.root, 'link'); const journal = openManagedEtahenLinkJournal({ file: path.join(directory, 'jobs.json'), root: directory, keyring: f.keyring, now: f.now }).journal; const ledger = createEtahenLinkAuditLedger({ file: path.join(directory, 'audit.json'), root: directory, keyring: f.keyring, now: f.now }); const consoleId = 'console_12345678'; const sessionKey = 'd'.repeat(64); const verifier = createEnvelopeVerifier({ consoleId, runtimeEpoch, sessionKey, now: f.now }); let interrupt = true; const orchestrator = createEtahenLinkOrchestrator({ consoleId, runtimeEpoch, capabilities: [{ name: 'console.inventory.read', available: true, authorized: true, healthy: true }], verifyEnvelope: verifier, journal, handlers: {}, audit: (event, details, options) => { if (event === 'etahen.link.dispatch.denied' && interrupt) { interrupt = false; throw Object.assign(new Error('audit unavailable'), { code: 'AUDIT_DOWN' }); } return ledger.append(event, details, options); }, now: f.now }); const invalidJob = { jobId: 'job_denyretain1', type: 'inventory.scan', runtimeEpoch, input: { path: '/forbidden' } }; const envelope = signEnvelope({ jobId: invalidJob.jobId, nonce: 'nonce_denyretain', consoleId, runtimeEpoch, issuedAt: f.now(), expiresAt: f.now() + 1000, job: invalidJob }, sessionKey); assert.throws(() => orchestrator.dispatch(envelope), error => error?.code === 'AUDIT_DOWN'); assert.equal(journal.list().length, 0); assert.doesNotThrow(() => orchestrator.reconcileAudit()); const denial = ledger.list().find(item => item.event === 'etahen.link.dispatch.denied'); assert.equal(denial.details.reasonId, 'ETAHEN_LINK_FORBIDDEN_FIELD'); assert.equal(denial.details.installed, false); }); test('backwards clocks fail before corrupting journal or keyring state', t => { let clock = 100; const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-link-clock-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const secrets = new SecretsStore({ filePath: path.join(root, 'secrets', 'secrets.enc.json'), keyFile: path.join(root, 'secrets', 'master.key') }); const keyring = createEtahenLinkKeyring({ secrets, stateFile: path.join(root, 'link', 'keyring.json'), root: path.join(root, 'link'), now: () => clock, randomBytes: size => Buffer.alloc(size, 0x81) }); clock = 90; assert.throws(() => keyring.prepareRotation({ reason: 'clock-must-not-rewind' }), error => error?.code === 'ETAHEN_KEYRING_TIME'); assert.equal(keyring.status().pending, null); clock = 100; const journal = openManagedEtahenLinkJournal({ file: path.join(root, 'link', 'jobs.json'), root: path.join(root, 'link'), keyring, now: () => clock }).journal; journal.begin(job('job_clockbound'), '6'.repeat(64)); clock = 50; assert.throws(() => journal.transition('job_clockbound', 'applying', { installed: false }), error => error?.code === 'ETAHEN_JOURNAL_TIME'); assert.equal(journal.get('job_clockbound').status, 'accepted'); });