37 lines
1.9 KiB
JavaScript
37 lines
1.9 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* judge-card-guard (§11 #5 — страж карточки) — прежде чем опереться на карточку
|
|
* навыка, проверь: она ЕСТЬ + (для чужих карточек) хеш сходится. Иначе судья громко
|
|
* помечает «сужу вслепую» (не падает, но фиксирует, что опора ненадёжна). Свои
|
|
* карточки доверенны без хеша; чужие — только при совпадении ожидаемого хеша.
|
|
*/
|
|
import { createHash } from 'node:crypto';
|
|
import { canonicalJson } from './receipt-sign.mjs';
|
|
|
|
export function cardHash(card) {
|
|
return createHash('sha256').update(canonicalJson(card)).digest('hex');
|
|
}
|
|
|
|
/** Страж одной карточки. expectedHash задаётся для ЧУЖИХ карточек (хеш-сверка). */
|
|
export function guardCard(card, { expectedHash } = {}) {
|
|
if (!card || typeof card !== 'object') {
|
|
return { ok: false, blind: true, reason: 'карточка отсутствует — сужу вслепую' };
|
|
}
|
|
if (expectedHash && cardHash(card) !== expectedHash) {
|
|
return { ok: false, blind: true, reason: 'хеш карточки не сошёлся — сужу вслепую' };
|
|
}
|
|
return { ok: true, blind: false };
|
|
}
|
|
|
|
/** Страж набора карточек. expectedHashes: { [skill]: hash } для чужих. */
|
|
export function guardCards(cards = [], { expectedHashes = {} } = {}) {
|
|
const blindOn = [];
|
|
(cards || []).forEach((card, i) => {
|
|
const skill = card && card.skill;
|
|
const expectedHash = skill ? expectedHashes[skill] : undefined;
|
|
const r = guardCard(card, { expectedHash });
|
|
if (r.blind) blindOn.push({ index: i, skill: skill ?? null, reason: r.reason });
|
|
});
|
|
return { ok: blindOn.length === 0, blindOn };
|
|
}
|