27 lines
1.3 KiB
JavaScript
27 lines
1.3 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* judge-goal-anchor (§11 #2 — цель приколочена) — исходная цель пинится НЕИЗМЕННЫМ
|
|
* якорем (frozen + хеш); судья меряет против неё на каждом гейте. Анти-дрейф
|
|
* «цель → мой пересказ»: если на гейт подали перефразированную цель, хеш не сойдётся
|
|
* → дрейф → флаг. Судья опирается на pinned.goal, не на возможно-искажённую текущую.
|
|
*/
|
|
import { createHash } from 'node:crypto';
|
|
import { canonicalJson } from './receipt-sign.mjs';
|
|
|
|
function goalHash(goal) {
|
|
return createHash('sha256').update(canonicalJson(String(goal ?? ''))).digest('hex');
|
|
}
|
|
|
|
/** Приколотить цель: неизменная запись {goal, goal_hash}. */
|
|
export function pinGoal(goal) {
|
|
return Object.freeze({ goal: String(goal ?? ''), goal_hash: goalHash(goal) });
|
|
}
|
|
|
|
/** Сверить текущую цель с приколоченной. Хеш не сошёлся → дрейф (флаг). */
|
|
export function checkGoalIntegrity(pinned, currentGoal) {
|
|
const actual = goalHash(currentGoal);
|
|
const expected = pinned && pinned.goal_hash;
|
|
const drifted = actual !== expected;
|
|
return { ok: !drifted, drifted, expected, actual };
|
|
}
|