import { describe, it, expect } from 'vitest'; import { decide } from './enforce-verify-gate.mjs'; import { signVerifyReceipt } from './verify-receipt.mjs'; const KEY = 'signer-key'; const FP = 'a'.repeat(64); const base = { toolName: 'Bash', command: 'git push origin main', key: KEY, currentFingerprint: FP, escapeOpen: false, changedPaths: ['app/x.php'], }; const receipt = () => signVerifyReceipt({ code_fingerprint: FP, occurrence: 1 }, KEY); describe('enforce-verify-gate / decide', () => { it('не git commit/push → allow', () => { expect(decide({ ...base, command: 'git status', gate: { active: true }, receipt: null }).block).toBe(false); }); it('docs-only (все .md) → allow (short-circuit)', () => { expect(decide({ ...base, changedPaths: ['a.md', 'b.md'], gate: { active: true }, receipt: null }).block).toBe(false); }); it('флаг OFF (inert) → allow $0', () => { expect(decide({ ...base, gate: { active: false, keyMissing: false }, receipt: null }).block).toBe(false); }); it('флаг ON но ключ пропал → fail-CLOSE block', () => { expect(decide({ ...base, gate: { active: false, keyMissing: true }, receipt: null }).block).toBe(true); }); it('active + нет расписки → block', () => { expect(decide({ ...base, gate: { active: true }, receipt: null }).block).toBe(true); }); it('active + валидная свежая расписка → allow', () => { expect(decide({ ...base, gate: { active: true }, receipt: receipt() }).block).toBe(false); }); it('active + расписка с устаревшим fingerprint (код изменился) → block', () => { expect(decide({ ...base, gate: { active: true }, receipt: receipt(), currentFingerprint: 'c'.repeat(64) }).block).toBe(true); }); it('active + escape владельца открыт → allow (M6 floor_escape)', () => { expect(decide({ ...base, gate: { active: true }, receipt: null, escapeOpen: true }).block).toBe(false); }); it('commit тоже гейтится (не только push)', () => { expect(decide({ ...base, command: 'git commit -m x', gate: { active: true }, receipt: null }).block).toBe(true); }); });