"use strict";
/**
 * test_governance_scope_ledger.ts — Story 14.2 (v1.5)
 *
 * Asserts:
 *   1. Append + read round-trip produces well-formed entries.
 *   2. SHA chain is valid for an append-only sequence (verify ok=true).
 *   3. Tampering with an existing entry's `decision` field is detected
 *      by verify() (ok=false, brokenAt = tampered index).
 *   4. Tampering with `prevHash` is detected.
 *   5. GovernanceLayer.evaluate() with the new ledger writes one entry
 *      per call; OPENLIFE_GOVERNANCE_LEDGER=off disables the write.
 *   6. PII protection: the persisted entry stores `goalHash`, NOT the
 *      raw goal text.
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
function assertTrue(cond, label) {
    if (!cond)
        throw new Error(`ASSERT_FAILED[${label}]`);
}
async function main() {
    const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'gov-ledger-'));
    process.env.OPENLIFE_STATE_DIR = tmp;
    delete process.env.OPENLIFE_GOVERNANCE_LEDGER;
    try {
        const { GovernanceScopeLedger } = require('./orchestrator/GovernanceScopeLedger');
        const { GovernanceLayer } = require('./orchestrator/GovernanceLayer');
        const ledger = new GovernanceScopeLedger();
        // ── 1 + 2: append + verify ─────────────────────────────────────────
        const decision = {
            allowed: true,
            riskLevel: 'low',
            rationale: 'baseline',
            requiresConsent: false,
            scope: 'safe',
            matchedPolicies: ['baseline-safe-scope'],
            blockedCapabilities: [],
            redactionRequired: false,
            auditSummary: 'ok',
        };
        const e1 = ledger.append('do thing 1', 'demo', decision);
        const e2 = ledger.append('do thing 2', 'demo', decision);
        const e3 = ledger.append('do thing 3', 'demo', decision);
        assertTrue(e1.index === 0 && e1.prevHash === 'GENESIS', '[14.2] first entry chains from GENESIS');
        assertTrue(e2.prevHash === e1.entryHash, '[14.2] second entry chains from first');
        assertTrue(e3.prevHash === e2.entryHash, '[14.2] third entry chains from second');
        const v1 = ledger.verify();
        assertTrue(v1.ok && v1.entries === 3, `[14.2] verify ok on clean chain (got ${JSON.stringify(v1)})`);
        console.log('[14.2] append + verify clean chain ✓');
        // ── 6: goal text NOT stored, only hash ─────────────────────────────
        const allEntries = ledger.read();
        assertTrue(!allEntries.some((e) => JSON.stringify(e).includes('do thing 1')), '[14.2] raw goal not persisted');
        assertTrue(allEntries[0].goalHash && allEntries[0].goalHash.length === 64, '[14.2] goalHash present and sha256-length');
        console.log('[14.2] PII protection: only goalHash is persisted ✓');
        // ── 3: tamper with decision → entryHash mismatch ───────────────────
        const ledgerFile = ledger.path();
        const lines = fs.readFileSync(ledgerFile, 'utf-8').split('\n').filter((l) => l.trim());
        const parsed = JSON.parse(lines[1]);
        parsed.decision.scope = 'restricted'; // attacker mutates a past decision
        lines[1] = JSON.stringify(parsed);
        fs.writeFileSync(ledgerFile, lines.join('\n') + '\n', 'utf-8');
        const v2 = ledger.verify();
        assertTrue(!v2.ok && v2.brokenAt === 1 && v2.reason === 'entryHash_mismatch', `[14.2] tampered decision detected (got ${JSON.stringify(v2)})`);
        console.log('[14.2] tamper detection: mutated decision → entryHash_mismatch ✓');
        // ── 4: tamper with prevHash → prevHash mismatch ────────────────────
        const lines2 = fs.readFileSync(ledgerFile, 'utf-8').split('\n').filter((l) => l.trim());
        const parsed2 = JSON.parse(lines2[0]);
        const orig2 = parsed2.decision.scope;
        parsed2.decision.scope = orig2; // restore from previous mutation
        lines2[1] = JSON.stringify({ ...JSON.parse(lines2[1]), decision }); // reset entry 1 too
        // Now break prevHash on entry 2
        const p3 = JSON.parse(lines2[2]);
        p3.prevHash = '0'.repeat(64);
        lines2[2] = JSON.stringify(p3);
        fs.writeFileSync(ledgerFile, lines2.join('\n') + '\n', 'utf-8');
        const v3 = ledger.verify();
        assertTrue(!v3.ok, '[14.2] tampered prevHash detected (chain broken)');
        console.log('[14.2] tamper detection: bad prevHash flagged ✓');
        // Reset file for next scenarios
        fs.unlinkSync(ledgerFile);
        // ── 5a: GovernanceLayer.evaluate writes one entry per call ─────────
        const layer = new GovernanceLayer();
        const d1 = layer.evaluate('refactor the auth flow', 'default');
        const d2 = layer.evaluate('audit the audit logs', 'default');
        assertTrue(d1.allowed && d2.allowed, '[14.2] safe goals returned allowed');
        const after = new GovernanceScopeLedger().read();
        assertTrue(after.length === 2, `[14.2] one entry per evaluate call (got ${after.length})`);
        const verifyAfter = new GovernanceScopeLedger().verify();
        assertTrue(verifyAfter.ok, '[14.2] auto-appended entries pass verify');
        console.log('[14.2] GovernanceLayer.evaluate writes ledger entries ✓');
        // ── 5b: OPENLIFE_GOVERNANCE_LEDGER=off short-circuits the append ───
        fs.unlinkSync(ledger.path());
        process.env.OPENLIFE_GOVERNANCE_LEDGER = 'off';
        const layer2 = new GovernanceLayer();
        layer2.evaluate('safe goal under disabled ledger', 'default');
        const afterOff = new GovernanceScopeLedger().read();
        assertTrue(afterOff.length === 0, `[14.2] OFF flag prevents ledger write (got ${afterOff.length})`);
        delete process.env.OPENLIFE_GOVERNANCE_LEDGER;
        console.log('[14.2] OPENLIFE_GOVERNANCE_LEDGER=off honored ✓');
    }
    finally {
        delete process.env.OPENLIFE_STATE_DIR;
        delete process.env.OPENLIFE_GOVERNANCE_LEDGER;
        fs.rmSync(tmp, { recursive: true, force: true });
    }
    console.log('TEST_GOVERNANCE_SCOPE_LEDGER_OK');
}
main().catch((err) => {
    console.error('[governance-scope-ledger] FAILED:', err instanceof Error ? err.message : err);
    process.exit(1);
});
