Fingerprint Interchange Format 指紋交換格式
Every chart this site produces carries a fingerprint: engine version + ruleset id + SHA-256 input digest. The digest is computed over the RFC 8785 (JCS) canonicalisation of the kernel request — which makes any chart byte-for-byte reproducible by anyone, on any machine, forever.
Why it exists: "trust me" is not an API contract. A digest is.
The verification triple
engine_version— semantic version of the computation kernel (from the crate manifest).ruleset_id— the rule set the computation ran under (year conventions, day boundaries, chart kinds). Different school = different ruleset id, never silently merged.input_digest— SHA-256 (hex, 64 chars) over the JCS-canonicalised request JSON.
A result without its triple is unattributable; a triple without a replay path is decoration. Both halves ship with every response.
How the digest is computed
- Take the kernel request object (e.g.
{"beijing":[1985,2,20,12,0,0],"year_convention":"lichun","day_boundary":"midnight"}). - Canonicalise per RFC 8785 (JCS): keys sorted by UTF-16 code units, minimal JSON number serialization, no whitespace.
- SHA-256 the UTF-8 encoding; hex-encode.
The kernel is the single implementation of this normalisation (both the WASM and the Python binding share it — verified byte-for-byte identical across 400 cross-language cases). A known-answer test pins the empty-object vector (SHA-256("{}") = 44136fa3…) so a broken canonicaliser cannot pass silently.
Replay: using a fingerprint
Three interchangeable ways to verify, in increasing order of zero-trust:
- API replay —
POST /v1/replaywith the original request and expected digest; the verdict isMATCH — byte-identical reproductionor an honest mismatch (plus 409 on engine-version mismatch). - MCP replay — the
replaytool does the same for AI agents. - Local replay — the browser verifier runs the same WASM kernel locally: your input never leaves the device and the server is not involved at all.
Design rules (the honest constraints)
- Digests cover inputs, not outputs. The input determines the output deterministically (the kernel has no IO, no clock, no randomness), so signing the input signs everything.
- Floating-point is rounded to declared precision before serialization — a digest that depends on the last ULP of a transcendental function would differ between wasm32 and x86-64 and be worthless as an interchange format. Published numbers are reproducible numbers.
- School differences change the digest — deliberately. A Lichun-convention chart and a Lunar-New-Year chart are different facts and must not share a fingerprint.
- No chaining, no ledger. This is a verification format, not a blockchain claim; see our methodology for the line we draw.
Worked example
request = {"beijing":[1985,2,20,12,0,0],
"year_convention":"lichun",
"day_boundary":"midnight"}
jcs = {"beijing":[1985,2,20,12,0,0],"day_boundary":"midnight","year_convention":"lichun"}
digest = sha256_hex(jcs) → (run it: https://fengshuicalculator.com/v1/replay)
Try it: take the fingerprint shown on any chart here (e.g. the front-page calculator prints the first 32 hex chars), reconstruct the request from the visible fields, and replay it. If the digests match, you have reproduced our chart from public information alone — that is the entire point.
Related
Docs home · POST /v1/replay reference · MCP replay tool · Input digest (glossary) · Browser verifier