Files
brain/tools/floor-signer.test.mjs
T

91 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// tools/floor-signer.test.mjs — Пакет 3 (Блок 2): подписант GREEN + occurrence.
import { describe, it, expect } from 'vitest';
import { signGreen, verifyGreen, acceptGreen } from './floor-signer.mjs';
const KEY = 'signer-secret-key-xyz';
describe('floor-signer: signGreen (подпись GREEN в домене M5_GREEN)', () => {
it('подписывает payload и возвращает запись с 64-hex sig', () => {
const rec = signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 1 }, KEY);
expect(rec.criterion_id).toBe('c1');
expect(rec.code_fingerprint).toBe('fp1');
expect(rec.occurrence).toBe(1);
expect(rec.sig).toMatch(/^[0-9a-f]{64}$/);
});
it('без ключа подписанта возвращает null (fail-closed)', () => {
expect(signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 1 }, null)).toBe(null);
expect(signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 1 }, '')).toBe(null);
});
it('подпись пригодна только в домене M5_GREEN (verifyGreen true)', () => {
const rec = signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 1 }, KEY);
expect(verifyGreen(rec, KEY)).toBe(true);
});
});
describe('floor-signer: verifyGreen (целостность + привязка к criterion_id)', () => {
it('подделка criterion_id после подписи аннулирует проверку', () => {
const rec = signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 1 }, KEY);
const forged = { ...rec, criterion_id: 'c2' };
expect(verifyGreen(forged, KEY)).toBe(false);
});
it('подделка occurrence после подписи аннулирует проверку', () => {
const rec = signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 1 }, KEY);
const forged = { ...rec, occurrence: 2 };
expect(verifyGreen(forged, KEY)).toBe(false);
});
it('чужой ключ не проходит проверку', () => {
const rec = signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 1 }, KEY);
expect(verifyGreen(rec, 'other-key')).toBe(false);
});
it('неподписанная запись (нет sig) не проходит (fail-closed)', () => {
expect(verifyGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 1 }, KEY)).toBe(false);
});
});
describe('floor-signer: acceptGreen (occurrence монотонный, анти-пере-зачёт)', () => {
it('свежий GREEN с occurrence > lastOccurrence принимается', () => {
const rec = signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 5 }, KEY);
const r = acceptGreen(rec, KEY, { lastOccurrence: 4 });
expect(r.accepted).toBe(true);
});
it('тот же GREEN с разным criterion_id без нового occurrence отклоняется (Пакет 3 критерий)', () => {
const rec = signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 5 }, KEY);
const swapped = { ...rec, criterion_id: 'c2' };
const r = acceptGreen(swapped, KEY, { lastOccurrence: 4 });
expect(r.accepted).toBe(false);
expect(r.reason).toBe('bad-signature');
});
it('пере-зачёт того же occurrence отклоняется (occurrence <= lastOccurrence)', () => {
const rec = signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 5 }, KEY);
const r = acceptGreen(rec, KEY, { lastOccurrence: 5 });
expect(r.accepted).toBe(false);
expect(r.reason).toBe('stale-occurrence');
});
it('occurrence ниже последнего отклоняется', () => {
const rec = signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 3 }, KEY);
const r = acceptGreen(rec, KEY, { lastOccurrence: 5 });
expect(r.accepted).toBe(false);
expect(r.reason).toBe('stale-occurrence');
});
it('нецелый / неположительный occurrence отклоняется', () => {
const bad = [0, -1, 1.5, 'x', null];
for (const occ of bad) {
const rec = signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: occ }, KEY);
const r = acceptGreen(rec, KEY, { lastOccurrence: 0 });
expect(r.accepted).toBe(false);
expect(r.reason).toBe('bad-occurrence');
}
});
it('подделка GREEN без ключа подписанта не принимается', () => {
const forged = { criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 5, sig: 'a'.repeat(64) };
const r = acceptGreen(forged, KEY, { lastOccurrence: 0 });
expect(r.accepted).toBe(false);
expect(r.reason).toBe('bad-signature');
});
it('lastOccurrence по умолчанию 0 (первый GREEN occurrence=1 принимается)', () => {
const rec = signGreen({ criterion_id: 'c1', code_fingerprint: 'fp1', occurrence: 1 }, KEY);
const r = acceptGreen(rec, KEY);
expect(r.accepted).toBe(true);
});
});