UNPKG

noa-receipt

Version:

NOA Agent Action Receipt — open, offline-verifiable provenance for AI-agent actions. The governance/receipt organ only; the NOA brain is separate and proprietary.

190 lines (189 loc) • 4.86 kB
import { strCharCodeAt } from "./intrinsics.js"; const ZERO = 0x30; const NINE = 0x39; const LOWER_A = 0x61; const LOWER_F = 0x66; const UPPER_A = 0x41; const UPPER_F = 0x46; const COLON = 0x3a; const DASH = 0x2d; const PLUS = 0x2b; const DOT = 0x2e; const T_UPPER = 0x54; const T_LOWER = 0x74; const Z_UPPER = 0x5a; const Z_LOWER = 0x7a; function at(s, i) { return strCharCodeAt(s, i); } function isDigit(c) { return c >= ZERO && c <= NINE; } function isLowerHex(c) { return (c >= ZERO && c <= NINE) || (c >= LOWER_A && c <= LOWER_F); } function isAnyHex(c) { return (c >= ZERO && c <= NINE) || (c >= LOWER_A && c <= LOWER_F) || (c >= UPPER_A && c <= UPPER_F); } function lowerHexRun(s, from, n) { for (let i = 0; i < n; i++) { if (!isLowerHex(at(s, from + i))) return false; } return true; } function digitRun(s, from, n) { for (let i = 0; i < n; i++) { if (!isDigit(at(s, from + i))) return false; } return true; } function hasPrefix(s, lit) { const n = lit.length; if (s.length < n) return false; for (let i = 0; i < n; i++) { if (at(s, i) !== at(lit, i)) return false; } return true; } export function isSha256Hash(s) { if (typeof s !== "string") return false; if (s.length !== 71) return false; if (!hasPrefix(s, "sha256:")) return false; return lowerHexRun(s, 7, 64); } export function isParamsHash(s) { if (typeof s !== "string") return false; if (s.length === 71 && hasPrefix(s, "sha256:")) return lowerHexRun(s, 7, 64); if (s.length === 76 && hasPrefix(s, "hmac-sha256:")) return lowerHexRun(s, 12, 64); return false; } export function isHex64(s) { if (typeof s !== "string") return false; if (s.length !== 64) return false; return lowerHexRun(s, 0, 64); } export function isHex4(s) { if (typeof s !== "string" || s.length !== 4) return false; for (let i = 0; i < 4; i++) { if (!isAnyHex(at(s, i))) return false; } return true; } export function isRfc3339(s) { if (typeof s !== "string") return false; const n = s.length; if (n < 20) return false; if (!digitRun(s, 0, 4)) return false; if (at(s, 4) !== DASH) return false; if (!digitRun(s, 5, 2)) return false; if (at(s, 7) !== DASH) return false; if (!digitRun(s, 8, 2)) return false; const t = at(s, 10); if (t !== T_UPPER && t !== T_LOWER) return false; if (!digitRun(s, 11, 2)) return false; if (at(s, 13) !== COLON) return false; if (!digitRun(s, 14, 2)) return false; if (at(s, 16) !== COLON) return false; if (!digitRun(s, 17, 2)) return false; let i = 19; if (at(s, i) === DOT) { i++; let frac = 0; while (i < n && isDigit(at(s, i))) { frac++; i++; } if (frac < 1 || frac > 9) return false; } const z = at(s, i); if (z === Z_UPPER || z === Z_LOWER) return i === n - 1; if (z !== PLUS && z !== DASH) return false; if (n - i !== 6) return false; if (!digitRun(s, i + 1, 2)) return false; if (at(s, i + 3) !== COLON) return false; return digitRun(s, i + 4, 2); } function num2(s, from) { return (at(s, from) - ZERO) * 10 + (at(s, from + 1) - ZERO); } function num4(s, from) { return ((at(s, from) - ZERO) * 1000 + (at(s, from + 1) - ZERO) * 100 + (at(s, from + 2) - ZERO) * 10 + (at(s, from + 3) - ZERO)); } function isLeapYear(y) { if (y % 4 !== 0) return false; if (y % 100 !== 0) return true; return y % 400 === 0; } function daysInMonth(year, month) { if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) return 31; if (month === 4 || month === 6 || month === 9 || month === 11) return 30; if (month === 2) return isLeapYear(year) ? 29 : 28; return 0; } export function isRfc3339Instant(s) { if (!isRfc3339(s)) return false; const year = num4(s, 0); const month = num2(s, 5); const day = num2(s, 8); if (month < 1 || month > 12) return false; if (day < 1 || day > daysInMonth(year, month)) return false; if (num2(s, 11) > 23) return false; if (num2(s, 14) > 59) return false; if (num2(s, 17) > 60) return false; const n = s.length; const last = at(s, n - 1); if (last === Z_UPPER || last === Z_LOWER) return true; if (num2(s, n - 5) > 23) return false; if (num2(s, n - 2) > 59) return false; return true; }