import { describe, test, expect } from 'vitest' import { createMemoryStores } from '../src/store/memory.js' import { createAuditLog, MAX_META_VALUE_LEN } from '../src/audit/log.js' import { createAccountRegistry } from '../src/registry/accounts.js' import { createHostRegistry } from '../src/registry/hosts.js' import { fingerprint } from '../src/ca/fingerprint.js' import { generateEd25519 } from '../src/util/crypto.js' describe('T14 audit log (INV10 zero payload)', () => { test('rejects a meta value carrying control/ANSI bytes (terminal payload guard)', async () => { const { audit } = createMemoryStores() const log = createAuditLog(audit) await expect( log.writeAuditEvent({ action: 'attach', principalId: 'p', accountId: 'a', hostId: null, ts: new Date().toISOString(), meta: { out: 'ls\r\noutput' }, // looks like shell output }), ).rejects.toThrow(/payload guard/) }) test('rejects an over-long meta value', async () => { const { audit } = createMemoryStores() const log = createAuditLog(audit) await expect( log.writeAuditEvent({ action: 'manage', principalId: 'p', accountId: 'a', hostId: null, ts: new Date().toISOString(), meta: { blob: 'x'.repeat(MAX_META_VALUE_LEN + 1) }, }), ).rejects.toThrow(/payload guard/) }) test('append-only: entries are queryable, no update/delete surface exists', async () => { const { audit } = createMemoryStores() const log = createAuditLog(audit) await log.writeAuditEvent({ action: 'kill', principalId: 'p', accountId: 'acct', hostId: 'h', ts: new Date().toISOString(), meta: {} }) const rows = await log.queryAudit('acct', '1970-01-01T00:00:00.000Z', '2999-01-01T00:00:00.000Z') expect(rows.length).toBe(1) expect(Object.keys(log)).not.toContain('update') expect(Object.keys(log)).not.toContain('delete') }) test('control-plane mutations emit audit entries (create + bind)', async () => { const stores = createMemoryStores() const log = createAuditLog(stores.audit) const accounts = createAccountRegistry({ accounts: stores.accounts, audit: log }) const hosts = createHostRegistry({ hosts: stores.hosts, audit: log }) const acct = await accounts.createAccount('pro') const { publicKeyRaw } = generateEd25519() await hosts.bindHost({ accountId: acct.accountId, subdomain: 'alice', agentPubkey: publicKeyRaw, enrollFpr: fingerprint(publicKeyRaw) }) const rows = await log.queryAudit(acct.accountId, '1970-01-01T00:00:00.000Z', '2999-01-01T00:00:00.000Z') expect(rows.map((r) => r.action).sort()).toEqual(['account.create', 'host.bind']) }) })