#!/usr/bin/env node /** * verify-receipt (G1, Level A) — чистое ядро подписанной verify-расписки (домен VERIFY_PASS). * Зеркало floor-signer.mjs. Подлинность — подпись подписанта; свежесть — совпадение * code_fingerprint с ТЕКУЩИМ staged-diff (считает consumer/producer, инъекция currentFingerprint). * occurrence — структурный positive-int (анти-двойной-зачёт = Level B). Δ4: ключ не защищён от * мотивированного контроллера (см. план G1 §Forge); подпись даёт out-of-env + шов под HSM. */ import { signPayload, verifyReceipt, RECEIPT_DOMAINS } from './receipt-sign.mjs'; export function signVerifyReceipt({ code_fingerprint, occurrence }, key) { if (!key) return null; const body = { code_fingerprint, occurrence }; const sig = signPayload(body, key, RECEIPT_DOMAINS.VERIFY_PASS); if (!sig) return null; return { ...body, sig }; } export function verifyReceiptSig(record, key) { return verifyReceipt(record, key, RECEIPT_DOMAINS.VERIFY_PASS); } /** * Принять расписку: подпись валидна И occurrence — целое >0 И (если задан currentFingerprint) * code_fingerprint совпадает с ним. Любое нарушение → {accepted:false, reason}. */ export function acceptVerifyReceipt(record, key, { currentFingerprint = null } = {}) { if (!verifyReceiptSig(record, key)) return { accepted: false, reason: 'bad-signature' }; const occ = record.occurrence; if (!Number.isInteger(occ) || occ <= 0) return { accepted: false, reason: 'bad-occurrence' }; if (currentFingerprint !== null && record.code_fingerprint !== currentFingerprint) { return { accepted: false, reason: 'stale-fingerprint' }; } return { accepted: true, reason: 'ok' }; }