Cohort-canonical regulator-grade cold-verifier for L43 Mirror-Mark v1 Re-Derivable-Receipts.
Single Go static binary. Zero external module dependencies. Zero Limitless cohort source dependencies. Wraps the Tier-0 cold-verify primitive (HMAC-SHA256 + base64.RawURLEncoding) behind a stable flag/stdin/stdout/exit-code contract.
This is Phase 1 of the five-phase plan in
reviews/CROSS_POLL_2026-05-21_POST-SWEEP/synthesis/E24_LORE_MARK_VERIFY_CLI.md.
git clone https://github.com/davly/lore-mark-verify.git
cd lore-mark-verify
go build -o lore-mark-verify ./cmd/lore-mark-verify
No network access required at build time:
GOPROXY=off go build ./...
Re-derives the KAT-1 HMAC-SHA256 digest from canonical inputs
(key=[], message=0x01||32×0x00) and compares against the embedded
literal. Answers a single question — "is this binary itself correct?"
— in one line with no flags or inputs.
$ lore-mark-verify kat-1-check
expected: 239a7d0d3f1bbe3a98aede01e2ad818c2db60b7177c02e2f015035b2b5b7dbca
reproduced: 239a7d0d3f1bbe3a98aede01e2ad818c2db60b7177c02e2f015035b2b5b7dbca
match: YES
Exits 0 on match, 5 on drift.
Re-derives a lore@v1: mark from (corpus-sha, payload, key) and
compares against the supplied mark string.
lore-mark-verify verify <payload-file> <mark>
--corpus-sha-hex HEX64
(--key-file PATH | --key-stdin)
[--quiet]
On success prints VERIFIED + corpus-prefix + payload-sha256 + mark to
stdout, exits 0. On failure prints exactly one R115 closed-enum verdict
string to stdout and exits with a stable code.
| Exit | Verdict (stdout) | Meaning |
|---|---|---|
| 0 | VERIFIED |
round-trip succeeded |
| 1 | ErrCorpusMismatch |
corpus prefix in mark != --corpus-sha-hex |
| 2 | ErrSignatureMismatch |
HMAC re-derivation differs from mark digest |
| 3 | ErrMalformedMark |
prefix wrong / base64 fails / body length wrong |
| 4 | ErrUnknownMarkVersion |
lore@v1: prefix missing |
| 5 | KAT-1 DRIFT |
kat-1-check failed (cohort broken) |
| 6 | (usage banner) | bad CLI args / missing flag / unreadable file |
The verify chain runs cheap-to-expensive:
- Prefix check →
ErrUnknownMarkVersion - Base64 decode →
ErrMalformedMark - Body-length check →
ErrMalformedMark - Corpus prefix comparison (constant-time, 8 bytes) →
ErrCorpusMismatch - HMAC re-derivation (constant-time compare, 32 bytes) →
ErrSignatureMismatch
The corpus-prefix short-circuit at step 4 fires before the more- expensive HMAC re-derivation, giving an operator a useful diagnostic ("you have the wrong lore corpus") instead of a generic HMAC failure.
The cohort-canonical KAT-1 digest is reproducible from a non-Limitless shell with only OpenSSL:
printf '\x01' > /tmp/kat1.bin
printf '\x00%.0s' {1..32} >> /tmp/kat1.bin
openssl dgst -sha256 -mac hmac -macopt key: /tmp/kat1.bin
# -> HMAC-SHA256(stdin)= 239a7d0d3f1bbe3a98aede01e2ad818c2db60b7177c02e2f015035b2b5b7dbca
The internal/kat/kat1_openssl_parity_test.go test (build-tagged
behind -tags openssl_parity) pins this property in CI on dev hosts
where OpenSSL is available.
This binary MUST NOT import any Limitless cohort package. Three structural checks enforce the firewall:
# 1. zero require lines beyond go directive
grep -c '^require' go.mod # → 0
# 2. no cohort-package imports
grep -rE 'github.com/davly/(reality|foundation|aicore|oracle|folio|nexus|pulse|baseline)' --include="*.go" .
# → empty
# 3. builds without module fetch
GOPROXY=off go build ./... # → exit 0
The cold-verify algorithm is transcribed (algorithm-byte-identical)
from engines/oracle/internal/mirrormark/{mark,verify}.go. Transcription
is intentional: importing oracle's package would create a cohort
dependency that defeats the regulator-grade "no Limitless source trust
required" property.
The transcription is verified by cross-substrate KAT-1 parity at multiple pin sites (each independently committing to byte-identical output for the same canonical inputs).
Algorithm-canonical Go source:
engines/oracle/internal/mirrormark/{mark,verify}.goinfrastructure/nexus/src/api/internal/mirrormark/{mark,verify}.go
KAT-1 literal pin source-of-truth:
engines/oracle/internal/mirrormark/kat_test.goline 366
Cross-language port (cohort 11th member):
flagships/foundry/src/mirror_mark/{sha256,hmac,base64url,parity}.rs
Sibling binaries (different exit-code numbering — see below):
flagships/folio/backend/cmd/folio-mark-verify/main.goinfrastructure/nexus/src/api/cmd/lore-mark-verify/main.go
The cohort-canonical lore-mark-verify (this binary, apps/) uses the
lens-26 canonical numbering verbatim. Two earlier sibling binaries use
different exit-code maps:
| Verdict | apps/lore-mark-verify (this) |
folio-mark-verify |
Earlier Nexus cmd/lore-mark-verify |
|---|---|---|---|
| VERIFIED | 0 | 0 | 0 |
| Usage | 6 | 2 | 1 |
| MalformedMark | 3 | – | 2 |
| UnknownVersion | 4 | – | 3 |
| CorpusMismatch | 1 | 6 | 4 |
| SignatureMismatch | 2 | 5 | 5 |
| KeyFormat | – | 3 | – |
| PayloadRead | – | 4 | – |
| CorpusWalkFailed | – | – | 6 |
| KAT-1 Drift | 5 | – | – |
Operators consuming more than one verifier MUST branch on
(binary-name, exit-code) tuples, not exit alone.
What ships in Phase 1:
verify+kat-1-checksub-commands- Embedded KAT-1 hex literal (
KAT1Digest) - Embedded KAT-1 canonical mark string (
KAT1Mark) - OpenSSL parity test (build-tagged behind
-tags openssl_parity) - Folio-DSAR-receipt-shaped testdata fixture (placeholder dev key — not a production key)
What does NOT ship in Phase 1:
inspectsub-command (decode + structural diagnosis) — Phase 1.5kat-N-check --num {1|6}extension — Phase 4- Five cohort consumer integration tests (pulse, baseline, foundry, oracle, iris) — Phase 2
- Docs site + GitHub release tag + multi-platform static binaries — Phase 3
- Cohort-wide doc-comment audit + FW-Torque C# verification + KMM JVM independent KAT + cohort-sabotage pre-commit hook — Phase 5
- Wrapping in an MCP tool
- Key generation / rotation / storage / KMS integration
- Payload canonicalisation (the CLI takes whatever bytes the operator
hands it; canonical-form drift surfaces as
ErrSignatureMismatch)
- No production HMAC keys ship in this repo. The
testdata/ dev_receipt_key.binfile is a placeholder dev byte sequence (iik_dev_lore_mark_verify_phase1), documented as such here and intestdata/README.md. - The corpus SHA is supplied as a flag. Phase 1 does not walk a lore tree to derive the corpus SHA — that's Phase 2 cohort-integration work. A regulator with only the binary + a published corpus SHA + a payload + a key + a mark can verify; a regulator who needs to compute the corpus SHA from a published lore archive uses any tool that walks the archive in canonical order and SHA-256s the result.
- Transcription parity is unverified for Phase 1. Phase 2 wires
cohort-consumer integration tests proving
internal/verify/verify.goand each cohort's in-processVerifyproduce the same R115 verdict for the same(mark, corpus, payload, key)quadruple.
# Default suite — pure Go, no external deps.
go test ./...
# Include OpenSSL parity (requires openssl on PATH).
go test -tags openssl_parity ./...
Apache-2.0 — same as the rest of the davly cohort.