/** * Tamper-evident in-session audit chain (hash-linked NDJSON rows; no persistence unless host appends). */ import bareCrypto from 'bare-crypto' const { createHash } = bareCrypto /** @type {string | null} */ let chainHeadHex = null let seq = 0 function hexU8(u8) { let s = '' for (let i = 0; i < u8.length; i++) s += u8[i].toString(16).padStart(2, '0') return s } /** * @param {Record} entry * @returns {{ seq: number, entryHash: string, prevHash: string | null }} */ export function bareOsAuditAppend(entry) { seq++ const prev = chainHeadHex const payload = JSON.stringify({ seq, ts: Date.now(), prev: prev, ...entry }) const h = createHash('sha256') h.update(prev || '') h.update('\n') h.update(payload) const digest = h.digest() const u8 = digest instanceof Uint8Array ? digest : new Uint8Array(digest) chainHeadHex = hexU8(u8) return { seq, entryHash: chainHeadHex, prevHash: prev } } export function bareOsAuditChainHead() { return chainHeadHex } export function bareOsAuditChainLength() { return seq } export function bareOsAuditChainSnapshot() { return { schema: 1, length: seq, headHex: chainHeadHex, atMs: Date.now() } }