54 lines
3.9 KiB
JavaScript
54 lines
3.9 KiB
JavaScript
|
|
import { describe, it, expect } from 'vitest';
|
||
|
|
import { commitGrantOpenForSession } from './commit-grant.mjs';
|
||
|
|
import { freezePlan } from './plan-lock.mjs';
|
||
|
|
import { classifyGitCommand } from './shell-content-rules.mjs';
|
||
|
|
|
||
|
|
describe('D2 критерий §5 — канал коммита под ревью (сквозной)', () => {
|
||
|
|
const K = 'k-d2e2e';
|
||
|
|
const plan = freezePlan({ steps: [{ op: 'Write', object: 'tools/x.mjs' }], judgeMode: 'live-block', key: K, nowMs: 1 });
|
||
|
|
it('опечатанный план + commit:<hash> → git commit allow', () => {
|
||
|
|
const open = commitGrantOpenForSession('S', { loadGrantsImpl: () => [{ action: `commit:${plan.plan_id}`, ts: 1 }], loadPlanImpl: () => plan, keyImpl: () => K, verifyImpl: () => true });
|
||
|
|
expect(open).toBe(true);
|
||
|
|
expect(classifyGitCommand('git commit -m x', { commitGrantOpen: open }).result).toBe('allow');
|
||
|
|
});
|
||
|
|
it('грант на ЧУЖОЙ хеш → git commit block (default-deny держит)', () => {
|
||
|
|
const open = commitGrantOpenForSession('S', { loadGrantsImpl: () => [{ action: 'commit:OTHER', ts: 1 }], loadPlanImpl: () => plan, keyImpl: () => K, verifyImpl: () => true });
|
||
|
|
expect(open).toBe(false);
|
||
|
|
expect(classifyGitCommand('git commit -m x', { commitGrantOpen: open }).result).toBe('block');
|
||
|
|
});
|
||
|
|
it('force-push блокируется даже под открытым commit-грантом (качество держит)', () => {
|
||
|
|
const open = commitGrantOpenForSession('S', { loadGrantsImpl: () => [{ action: `commit:${plan.plan_id}`, ts: 1 }], loadPlanImpl: () => plan, keyImpl: () => K, verifyImpl: () => true });
|
||
|
|
expect(classifyGitCommand('git push --force', { commitGrantOpen: open }).result).toBe('block');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('commitGrantOpenForSession (D2 — gated: нет гранта → план не грузим)', () => {
|
||
|
|
const K = 'k-cg';
|
||
|
|
it('нет commit-грантов → false, план НЕ грузится', () => {
|
||
|
|
let planLoaded = false;
|
||
|
|
const r = commitGrantOpenForSession('S', { loadGrantsImpl: () => [], loadPlanImpl: () => { planLoaded = true; return null; }, keyImpl: () => K, verifyImpl: () => true });
|
||
|
|
expect(r).toBe(false);
|
||
|
|
expect(planLoaded).toBe(false);
|
||
|
|
});
|
||
|
|
it('грант на хеш + sealed live-block план → true', () => {
|
||
|
|
const plan = freezePlan({ steps: [{ op: 'Write', object: 'a.mjs' }], judgeMode: 'live-block', key: K, nowMs: 1 });
|
||
|
|
const r = commitGrantOpenForSession('S', { loadGrantsImpl: () => [{ action: `commit:${plan.plan_id}`, ts: 1 }], loadPlanImpl: () => plan, keyImpl: () => K, verifyImpl: () => true });
|
||
|
|
expect(r).toBe(true);
|
||
|
|
});
|
||
|
|
it('грант на ЧУЖОЙ хеш → false', () => {
|
||
|
|
const plan = freezePlan({ steps: [{ op: 'Write', object: 'a.mjs' }], judgeMode: 'live-block', key: K, nowMs: 1 });
|
||
|
|
expect(commitGrantOpenForSession('S', { loadGrantsImpl: () => [{ action: 'commit:OTHER', ts: 1 }], loadPlanImpl: () => plan, keyImpl: () => K, verifyImpl: () => true })).toBe(false);
|
||
|
|
});
|
||
|
|
it('judge_mode не live-block → false', () => {
|
||
|
|
const plan = freezePlan({ steps: [{ op: 'Write', object: 'a.mjs' }], judgeMode: 'shadow', key: K, nowMs: 1 });
|
||
|
|
expect(commitGrantOpenForSession('S', { loadGrantsImpl: () => [{ action: `commit:${plan.plan_id}`, ts: 1 }], loadPlanImpl: () => plan, keyImpl: () => K, verifyImpl: () => true })).toBe(false);
|
||
|
|
});
|
||
|
|
it('печать невалидна (verifyImpl→false) → false', () => {
|
||
|
|
const plan = freezePlan({ steps: [{ op: 'Write', object: 'a.mjs' }], judgeMode: 'live-block', key: K, nowMs: 1 });
|
||
|
|
expect(commitGrantOpenForSession('S', { loadGrantsImpl: () => [{ action: `commit:${plan.plan_id}`, ts: 1 }], loadPlanImpl: () => plan, keyImpl: () => K, verifyImpl: () => false })).toBe(false);
|
||
|
|
});
|
||
|
|
it('нет плана → false', () => {
|
||
|
|
expect(commitGrantOpenForSession('S', { loadGrantsImpl: () => [{ action: 'commit:x', ts: 1 }], loadPlanImpl: () => null, keyImpl: () => K, verifyImpl: () => true })).toBe(false);
|
||
|
|
});
|
||
|
|
});
|