fuin 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. fuin-1.0.0/.gitignore +14 -0
  2. fuin-1.0.0/LICENSE +21 -0
  3. fuin-1.0.0/PKG-INFO +223 -0
  4. fuin-1.0.0/README.md +204 -0
  5. fuin-1.0.0/evidence/2026-11-03-fixtures/README.md +9 -0
  6. fuin-1.0.0/evidence/2026-11-03-fresh-clone-rehearsal/README.md +17 -0
  7. fuin-1.0.0/evidence/2026-11-03-provenance-probe/README.md +20 -0
  8. fuin-1.0.0/evidence/2026-11-03-round-near-dev-60-r1/README.md +23 -0
  9. fuin-1.0.0/evidence/2026-11-03-testnet-deploy/README.md +23 -0
  10. fuin-1.0.0/evidence/2026-11-03-thin-path/README.md +13 -0
  11. fuin-1.0.0/evidence/2026-11-04-blind-review/README.md +36 -0
  12. fuin-1.0.0/evidence/2026-11-04-external-review/README.md +13 -0
  13. fuin-1.0.0/evidence/2026-11-04-qwen-redeploy/README.md +12 -0
  14. fuin-1.0.0/evidence/2026-11-04-round-near-dev-300-r3/README.md +31 -0
  15. fuin-1.0.0/evidence/2026-11-04-round-near-dev-60-r2/README.md +21 -0
  16. fuin-1.0.0/evidence/2026-11-05-all-attestations-probe/README.md +19 -0
  17. fuin-1.0.0/evidence/2026-11-05-deepseek-review/README.md +12 -0
  18. fuin-1.0.0/evidence/2026-11-05-e2ee-probe/README.md +24 -0
  19. fuin-1.0.0/evidence/2026-11-05-reverify-tee-score/README.md +68 -0
  20. fuin-1.0.0/evidence/2026-11-05-reverify-tee-v2/README.md +24 -0
  21. fuin-1.0.0/evidence/2026-11-05-reverify-with-provenance/README.md +15 -0
  22. fuin-1.0.0/evidence/2026-11-05-round-near-dev-155-r4/README.md +36 -0
  23. fuin-1.0.0/evidence/2026-11-05-round-near-dev-96-r5/README.md +47 -0
  24. fuin-1.0.0/evidence/2026-11-05-scorer-v4-unreadable-count/README.md +29 -0
  25. fuin-1.0.0/evidence/2026-11-05-zero-reveal-rehearsal/README.md +16 -0
  26. fuin-1.0.0/evidence/2026-11-06-blind-review-fixes/README.md +49 -0
  27. fuin-1.0.0/evidence/2026-11-06-outside-pilot/README.md +56 -0
  28. fuin-1.0.0/evidence/2026-11-06-registry-rebuild/README.md +27 -0
  29. fuin-1.0.0/evidence/2026-11-07-answer-key-grounding/README.md +28 -0
  30. fuin-1.0.0/evidence/2026-11-07-blind-review-3/README.md +21 -0
  31. fuin-1.0.0/evidence/2026-11-07-round-near-dev-96-r6/README.md +40 -0
  32. fuin-1.0.0/evidence/2026-11-08-external-review/README.md +27 -0
  33. fuin-1.0.0/evidence/2026-11-08-round-near-dev-37-r7/README.md +52 -0
  34. fuin-1.0.0/policy/attestation-v1.json +24 -0
  35. fuin-1.0.0/policy/attestation-v2.json +42 -0
  36. fuin-1.0.0/policy/attestation-v3.json +56 -0
  37. fuin-1.0.0/policy/attestation-v4.json +70 -0
  38. fuin-1.0.0/policy/attestation-v5.json +102 -0
  39. fuin-1.0.0/policy/attestation-v6.json +128 -0
  40. fuin-1.0.0/policy/attestation-v7.json +232 -0
  41. fuin-1.0.0/policy/attestation-v8.json +254 -0
  42. fuin-1.0.0/policy/attestation-v9.json +298 -0
  43. fuin-1.0.0/policy/sigstore-trusted-root.json +126 -0
  44. fuin-1.0.0/policy/tee-v2.json +85 -0
  45. fuin-1.0.0/pyproject.toml +40 -0
  46. fuin-1.0.0/src/fuin/__init__.py +5 -0
  47. fuin-1.0.0/src/fuin/asker.py +161 -0
  48. fuin-1.0.0/src/fuin/attestation.py +235 -0
  49. fuin-1.0.0/src/fuin/cli.py +220 -0
  50. fuin-1.0.0/src/fuin/core.py +195 -0
  51. fuin-1.0.0/src/fuin/diagnose.py +46 -0
  52. fuin-1.0.0/src/fuin/e2ee.py +92 -0
  53. fuin-1.0.0/src/fuin/inference.py +114 -0
  54. fuin-1.0.0/src/fuin/near.py +176 -0
  55. fuin-1.0.0/src/fuin/owner.py +311 -0
  56. fuin-1.0.0/src/fuin/policy.py +97 -0
  57. fuin-1.0.0/src/fuin/policyupdate.py +73 -0
  58. fuin-1.0.0/src/fuin/provenance.py +245 -0
  59. fuin-1.0.0/src/fuin/py.typed +0 -0
  60. fuin-1.0.0/src/fuin/scorer.py +46 -0
  61. fuin-1.0.0/src/fuin/scorer_v1.py +45 -0
  62. fuin-1.0.0/src/fuin/tee.py +548 -0
  63. fuin-1.0.0/src/fuin/tooling.py +180 -0
  64. fuin-1.0.0/src/fuin/verify.py +568 -0
fuin-1.0.0/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ .env
2
+ .env.*
3
+ .venv/
4
+ __pycache__/
5
+ *.pyc
6
+ .pytest_cache/
7
+ target/
8
+ private/
9
+
10
+ # TEE scorer build output
11
+ tee/target/
12
+ tee/dist/
13
+ .fuin-cache/
14
+ ask/dist/
fuin-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 fexx301
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
fuin-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,223 @@
1
+ Metadata-Version: 2.5
2
+ Name: fuin
3
+ Version: 1.0.0
4
+ Summary: Sealed benchmark results with verifiable NEAR AI Cloud TEE signatures and a re-scorable audit sample
5
+ Project-URL: Homepage, https://github.com/fexx301/fuin
6
+ Project-URL: Repository, https://github.com/fexx301/fuin
7
+ Project-URL: Documentation, https://github.com/fexx301/fuin#readme
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Requires-Python: >=3.13
11
+ Requires-Dist: cryptography>=50.0.2
12
+ Requires-Dist: dcap-qvl==0.7.0
13
+ Requires-Dist: eth-account>=0.13
14
+ Requires-Dist: pyyaml>=6.0.3
15
+ Requires-Dist: requests>=2.32
16
+ Requires-Dist: rfc8785==0.1.4
17
+ Requires-Dist: sigstore>=4
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Fūin
21
+
22
+ Fūin (封印, pronounced *foo-een*) is Japanese for "seal": the test set is sealed on NEAR before any result is committed.
23
+
24
+ <picture>
25
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/fexx301/fuin/main/assets/fuin-logo-dark.svg">
26
+ <img src="https://raw.githubusercontent.com/fexx301/fuin/main/assets/fuin-logo.svg" alt="Fūin logo" width="320">
27
+ </picture>
28
+
29
+ Fūin publishes a private benchmark result that a stranger can check **without an account and without the test set**. Every answer carries a signature from the model's attested TEE key on NEAR AI Cloud, the set and results are committed on NEAR, and every answer is scored inside a TEE on OutLayer. A round can also reveal a sample picked by a future NEAR block, or reveal nothing at all. In round 7 a TEE made every model call itself and recorded one answer per question and counted every retry (round 7 had one), so no owner could quietly re-ask and keep the best answer.
30
+
31
+ Built at NEAR HACKATHON (Nov 1–14, 2026), tracks `privacy` and `open`.
32
+
33
+ ![The browser verifier refusing a real round-3 certificate whose revealed answer was edited after signing: REFUSED signature_text_mismatch](https://raw.githubusercontent.com/fexx301/fuin/main/assets/verify-refused.png)
34
+
35
+ *The browser verifier on a real round-3 certificate after "Edit an answer": the checks pass until the revealed sample is re-scored, where the edited answer no longer matches what the model signed.*
36
+
37
+ ## The problem
38
+
39
+ A benchmark owner has two bad options:
40
+
41
+ - **Publish the test set.** It leaks into the next model's training data, and the benchmark stops measuring anything.
42
+ - **Keep it private.** Then everyone has to take the owner's word for the scores: which model ran, whether answers were edited, and whether the grading was honest.
43
+
44
+ Fūin is a third option. The owner keeps the questions private. Anyone can check that the published score came from real, unedited answers by a named model running in a TEE, committed before any sample was drawn, and scored correctly against the owner's sealed answer key, over every answer. Whether the questions are any good stays with the owner. Private eval sets are already in use: NEAR's Delta League, for example, ranks fine-tuned models on one ([Illia Polosukhin, Nov 6, 2026](https://x.com/ilblackdragon/status/2118591003368296561)). Fūin certifies models that NEAR AI Cloud serves in an attested TEE, so certifying fine-tuned submissions like those would need them served the same way.
45
+
46
+ ## How it works
47
+
48
+ <picture>
49
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/fexx301/fuin/main/assets/fuin-flow-dark.svg">
50
+ <img src="https://raw.githubusercontent.com/fexx301/fuin/main/assets/fuin-flow.svg" alt="The six steps of a Fūin round: seal on NEAR, run (the model in a TEE signs each answer), commit on NEAR, close, check (a future block picks a sample, or a TEE scores every answer), verify (anyone gets VERIFIED, REFUSED or CAN'T CERTIFY)" width="940">
51
+ </picture>
52
+
53
+ **seal → run → commit → close → check → verify.**
54
+ 1. **Seal:** the owner seals a Merkle root over the salted questions, and a policy (request template, settings, scorer, audit size), on the NEAR registry.
55
+ 2. **Run:** each answer comes from NEAR AI Cloud, signed by the model's TEE key.
56
+ 3. **Commit:** the owner commits each run's root and total.
57
+ 4. **Close:** no more runs can join the round.
58
+ 5. **Check:** a future NEAR block picks a sample to reveal, or a TEE on OutLayer scores every answer.
59
+ 6. **Verify:** anyone rebuilds everything from the chain and the certificate, and gets one of three outcomes: **VERIFIED**; **REFUSED** with a reason code, when the evidence is wrong; or **CAN'T CERTIFY**, when evidence is missing or unsupported or a service didn't answer. An outage never decides a verdict.
60
+
61
+ The rounds come in three kinds, each a trade-off:
62
+
63
+ | | Sampled (`fuin seal`) | TEE-scored (`fuin seal --tee`) | Asked once (`fuin seal --ask`) |
64
+ |---|---|---|---|
65
+ | Questions revealed | a sample, picked by a future NEAR block | none | none |
66
+ | Who calls the model | the owner | the owner | a TEE, once per question, after the seal |
67
+ | How scores are checked | anyone re-scores the sample; a TEE re-scores every answer | a TEE re-scores every answer | the TEE scores each answer as it asks |
68
+ | Can the owner re-ask a question and keep the best answer? | yes (a printed limit) | yes (a printed limit) | no: the TEE keeps one answer per question and counts any retry |
69
+ | Models and token cap | all seven, 8,192 | all seven, 8,192 | fast models only, a smaller cap (DeepSeek-V4.1-Flash at 4,096) |
70
+ | Rounds here | 1–3 | 4–6 | 7 |
71
+
72
+ Every step in detail, with the deployment trace, the answer-key check and end-to-end encryption: [docs/HOW-IT-WORKS.md](https://github.com/fexx301/fuin/blob/main/docs/HOW-IT-WORKS.md).
73
+
74
+ ## Result: which NEAR AI Cloud model answers NEAR developer questions correctly?
75
+
76
+ Seven rounds of private questions, each answer cited to a line of [near/docs](https://github.com/near/docs) at commit `e2d2ea17`. They produced 20 certificates covering 2,302 answers from seven models. Every model ran with reasoning on and temperature 0. Every committed score was computed over every answer inside a TEE:
77
+
78
+ | Round | Kind | Questions | Committed score |
79
+ |---|---|---|---|
80
+ | 7 | asked once, end-to-end encrypted, 4,096 tokens | 37 | DeepSeek-V4.1-Flash **19** |
81
+ | 6 | TEE-scored, end-to-end encrypted | 96 | DeepSeek-V4.1-Flash abliterated **40** · DeepSeek-V4.1-Flash **38** · GLM-5.3-flash **33** · Qwen3.6-35B-A3B **22** · Qwen3.8-27B **22** · Qwen3.8-27B abliterated **21** · Qwen3-VL-30B-A3B **11** |
82
+ | 5 | TEE-scored, end-to-end encrypted | 96 | DeepSeek-V4.1-Flash **48** · GLM-5.3-flash **42** · Qwen3.8-27B **27** |
83
+ | 4 | TEE-scored | 155 | DeepSeek-V4.1-Flash **84** · GLM-5.3-flash **64** · Qwen3.8-27B **39** |
84
+ | 3 | sampled, 28 revealed | 300 | GLM-5.3-flash **122** · Qwen3.8-27B **77** |
85
+ | 2 | sampled, 23 revealed | 60 | GLM-5.3-flash **32** · Qwen3.8-27B **17** |
86
+ | 1 | sampled, 23 revealed, 4,096 tokens | 60 | GLM-5.3-flash **25** · Qwen3.8-27B **17** |
87
+
88
+ **What the scores show:**
89
+ - Rounds 2–6 used 8,192 tokens.
90
+ - DeepSeek-V4.1-Flash, in its base or abliterated version, leads rounds 4–6.
91
+ - GLM-5.3-flash beats Qwen3.8-27B in all six rounds they share.
92
+ - The rounds use different questions, so compare models within a round, not across rounds.
93
+
94
+ **Answer keys:** in rounds 4–7, which reveal nothing, a TEE checked each answer key against the near/docs line it cites. 374 of 384 appear there, and 10 are flagged as unchecked.
95
+
96
+ **More detail:**
97
+ - [docs/RESULTS.md](https://github.com/fexx301/fuin/blob/main/docs/RESULTS.md): the full table (served builds, revealed breakdowns, cut-offs), what each round disclosed, and how disclosure shrinks as suites grow.
98
+ - `evidence/*/README.md`: the transactions for every round.
99
+
100
+ ## For judges
101
+
102
+ **Quick check (about 2 minutes once dependencies are installed; the first `uv sync` can take 10 minutes on a slow connection; needs [uv](https://docs.astral.sh/uv/) and network, no account or API key):**
103
+
104
+ ```sh
105
+ git clone https://github.com/fexx301/fuin && cd fuin
106
+ uv sync # first run downloads the dependencies
107
+ env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-96-r6-deepseek-v4.1-flash-1017.json # about 1 minute: VERIFIED, every check printed
108
+ uv run pytest -q # 5 seconds, offline: 157 passed
109
+ uv run python scripts/check_fixtures.py examples/tampered/manifest.json # optional, about 4 minutes: 39 ok lines
110
+ ```
111
+
112
+ CAN'T CERTIFY with `evidence_unavailable` means a public service (NEAR's RPC, Intel or NVIDIA) didn't answer, not that the certificate is wrong: run the same command again.
113
+
114
+ **Full review (optional):**
115
+ - Run `scripts/review.sh` in the background. It takes about 30 minutes (allow 45).
116
+ - It waits on Intel, NVIDIA, NEAR, OutLayer, GitHub and Docker Hub, and retries when a public service rate-limits it.
117
+ - It exits 0 with `ALL CHECKS PASSED`.
118
+ - `AGENTS.md` lists the exit codes, what not to run and where the evidence lives.
119
+
120
+ Every claim maps to a command:
121
+
122
+ | Claim | Check | Expected |
123
+ |---|---|---|
124
+ | A stranger can verify a result without an account or the test set | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-60-r1-qwen3.8-27b.json` | `VERIFIED`, 10 `[pass]` lines, exit 0 |
125
+ | Each answer is signed by the model's TEE-attested key | same output, `signatures` and `attestation` lines | `60/60 provider_tee …`; `quote UpToDate, NRAS True` |
126
+ | The served container and weights are traced to NEAR's public deployment repo | same output, `deployment trace` line | `… nearai/cvm-compose-files: model-sg-qwen38-27b-fp8-tp1-coloc …` |
127
+ | The set and results were committed on NEAR, with the seal before the commit and the commit before the close | same output, `registry` line | `seal … < commit … < close …` |
128
+ | The owner can't choose which items a committed round reveals | same output, `audit sample` line; fixture `changed-audit` | `first final block ≥ close+2`; `REFUSED audit_sample_mismatch` |
129
+ | Tampering is refused with a specific reason | `uv run python scripts/check_fixtures.py examples/tampered/manifest.json` | 39 `ok` lines, exit 0 |
130
+ | Round 3's totals were re-scored over every answer inside a TEE, not only the sample | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-300-r3-glm-5.3-flash.json` | `[pass] tee score: all 300 items rebuilt and re-scored inside an OutLayer TDX enclave … total 122/300 and both roots match` |
131
+ | A round can reveal nothing and still be checked, with no answer predating its seal | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-155-r4-deepseek-v4.1-flash-1017.json` | `VERIFIED`; `[pass] reveals: none: a TEE-scored round reveals nothing …`; `[pass] tee score: all 155 items rebuilt and re-scored …: total 84/155 …`; fixtures `zero-reveal-unscored`, `zero-reveal-scorer-swapped` |
132
+ | A zero-reveal round's answer keys appear in the docs line they cite (a string match, not a check that the key is the right answer) | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-96-r6-glm-5.3-flash.json` | `[pass] answer keys: 92/96 answer keys appear in their cited line of near/docs at e2d2ea17, checked inside an OutLayer TDX enclave …; 4 flagged, not checked …: items 14, 35, 46, 94`; fixtures `ground-other-round`, `ground-hidden-flag`, `ground-fork-commit`, `ground-unpinned-build` |
133
+ | Each answer was asked once, by a TEE, not by the owner (no re-asking to keep the best answer) | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-37-r7-deepseek-v4.1-flash-1017.json` | `VERIFIED`; `[pass] asked once: all 37 answers asked once inside an OutLayer TDX enclave by asker dbbb286b744c… in ask.fuin.testnet/asker … 1 retried ask … every request rebuilt with the seal block's hash … equals the signed one, so every ask came after the seal … ask.fuin.testnet/asker was locked at the seal …`; fixtures `asked-unscored`, `asked-unchecked`, `asked-other-project`, `asked-total-edited`, `asked-check-edited`, `asked-hidden-retry` |
134
+ | Questions and answers can stay end-to-end encrypted, so NEAR's gateway never sees them | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-96-r5-glm-5.3-flash.json` | `VERIFIED`; the policy line ends `fuin-request-v3 (end-to-end encrypted)`, and the limits print the end-to-end-encryption line; probe: `evidence/2026-11-05-e2ee-probe/` |
135
+ | The TEE scorer that ran is this repository's code | `tee/build-docker.sh` (any host with Docker; about 1.5 minutes once the image is pulled) | prints `b301d22b…`, the current pin in `policy/tee-v2.json` (scorer v9: scores as v7, grounds answer keys, runs the asked-check); `ask/build-docker.sh aaa2083` prints `dbbb286b…`, the asker locked in `ask.fuin.testnet/asker`. The earlier accepted builds rebuild the same way from their recorded commits: v8 `bb0d9a5d…` (round 7's grounding, `39a2da3`), v7 `acd9286f…` (groundings of rounds 4–6, `58523c7`), v2 `dabae968…` (rounds 1–4, `6381ee9`), v3 `2614ddaa…` (round 5, `907aec0`), v4 `cd36c486…` (the v4 rehearsal, `54a5b6e`), v5 `86db8213…` (`170c488`), v6 `67c2292e…` (round 6, `6b0705c`) |
136
+ | The registry's code can't be replaced (its seal and commit values are also checked against the owner's signed transactions) | `curl -s https://archival-rpc.testnet.fastnear.com -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"query","params":{"request_type":"view_access_key_list","finality":"final","account_id":"registry.fuin.testnet"}}'` | `"keys":[]` |
137
+
138
+ ## Try it (no account, no API key, no test set)
139
+
140
+ You need uv and network access to these services:
141
+ - Intel PCS;
142
+ - NVIDIA NRAS;
143
+ - an archival NEAR testnet RPC (FastNEAR's by default; set `FUIN_TESTNET_RPC` to pin another);
144
+ - the NEAR AI model catalog;
145
+ - raw.githubusercontent.com;
146
+ - Docker Hub.
147
+
148
+ One verification takes about 40 seconds.
149
+
150
+ 1. **Verify a real certificate:** `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-60-r1-qwen3.8-27b.json`.
151
+ - You see `VERIFIED` with ten passing checks: rows, commitments, policy, signatures, reveals, attestation, deployment trace, registry, audit sample and TEE score.
152
+ - It also prints the scope line, the warnings and the limits that apply.
153
+ - The other 19 certificates in `examples/` verify the same way.
154
+ 2. **Watch tampering get refused:** `uv run python scripts/check_fixtures.py examples/tampered/manifest.json` prints 39 `ok` lines.
155
+ - Each fixture is a real certificate with one change.
156
+ - 29 are REFUSED, 9 are CAN'T CERTIFY, and 1 tricky but valid one must stay VERIFIED.
157
+ - Each fixture and its expected verdict: [docs/REFUSALS.md](https://github.com/fexx301/fuin/blob/main/docs/REFUSALS.md).
158
+ 3. **Read an audit:** `uv run fuin show examples/cert-near-dev-60-r2-glm-5.3-flash.json --audit` prints each of the 23 revealed questions with its expected answer, docs source, what the model said and its score.
159
+ 4. **Run the tests:**
160
+ - `uv run pytest`: 157 offline tests.
161
+ - `cd contract && cargo test`: 15 tests.
162
+ - `cd tee && cargo test`: the TEE scorer against Python on 3,600 generated cases, plus signed synthetic rounds.
163
+ 5. **Try it in a browser:** open [fexx301.github.io/fuin](https://fexx301.github.io/fuin/), or `site/index.html` from the clone. The page verifies certificates in the browser and lets you tamper with one live. It runs every local check, the live NEAR and OutLayer checks, the Intel TDX quote and the deployment trace. NVIDIA's GPU verdict can't run in a browser, so a published certificate shows `fuin verify`'s recorded result for it, matched to its exact bytes, and an uploaded one gets PARTLY CHECKED.
164
+
165
+ ## NEAR tools used
166
+
167
+ - **NEAR AI Cloud:**
168
+ - TEE-hosted open models through the gateway (`/v1/chat/completions` with `x-no-aliasing`);
169
+ - end-to-end encryption to the model's attested key (`X-Signing-Algo: ecdsa`, `X-Client-Pub-Key`, `X-Model-Pub-Key`);
170
+ - `provider_tee` response signatures (`/v1/signature`);
171
+ - model attestation reports (Intel TDX quote, NVIDIA GPU evidence, event log, compose-manager attestation);
172
+ - the public model catalog (`verifiable`, `attestationSupported`).
173
+ - **NEAR testnet contract** [`registry.fuin.testnet`](https://testnet.nearblocks.io/address/registry.fuin.testnet) (Rust, near-sdk 5.30, built with cargo-near):
174
+ - methods: `seal`, `commit_run`, `close_round`, `get_benchmark`, `get_run`;
175
+ - records can't be overwritten, runs are numbered per model, and callers pay for their own storage;
176
+ - **the account has no access keys**, so its code (hash `HvqaWNNceCX7AMtsanPobAt5mkAE2MsZdP2BURA2cgef`) can't be replaced. The verifier checks this.
177
+ - **OutLayer** (FastNEAR's verifiable off-chain compute on NEAR):
178
+ - `request_execution` on `outlayer.testnet` runs the TEE scorer in an Intel TDX enclave;
179
+ - an encryption key bound to the scorer's sha256 seals its private key;
180
+ - worker measurements are approved on `worker.outlayer.testnet`;
181
+ - the asker runs as the locked OutLayer project `ask.fuin.testnet/asker`, with sealed project storage and the owner's key stored as an OutLayer secret.
182
+ - **FastFS** serves the TEE scorer binary from a NEAR testnet transaction.
183
+ - **NEAR block hashes** serve as the audit seed and the seal-bound request nonce; reads go over JSON-RPC at `final` finality.
184
+ - **near-cli-rs** signs the owner's transactions; keys stay in the OS keychain.
185
+
186
+ ## Use it
187
+
188
+ ```sh
189
+ pip install fuin # or: uv tool install fuin
190
+ fuin verify cert.json # VERIFIED, REFUSED or CAN'T CERTIFY, with every check printed
191
+ ```
192
+
193
+ - **In CI:** a GitHub Action (`uses: fexx301/fuin@main`) fails the step unless every certificate is VERIFIED.
194
+ - **Your own private round** (`fuin check`, `seal`, `run`, `commit`, `close`, `reveal`, `tee-score`, `ask`): see [docs/USE.md](https://github.com/fexx301/fuin/blob/main/docs/USE.md).
195
+ - **A second person trying it:** [PILOT.md](https://github.com/fexx301/fuin/blob/main/PILOT.md) is a step-by-step kit. A fellow builder ran it unmodified on Windows 11 under WSL2.
196
+
197
+ ## Limits
198
+
199
+ Every VERIFIED prints the limits that apply to its certificate. In short:
200
+
201
+ - Scores are checked on the revealed sample, and on every answer through the TEE score. The TEE score trusts Intel TDX, OutLayer's worker approvals and its key service.
202
+ - In a round that reveals nothing, only the owner can see the questions. Answer keys are checked only against the docs line they cite, which doesn't prove a key is the right answer.
203
+ - In rounds 1–6 an owner could re-ask a sealed question and commit the best signed answer, and no certificate could show it. In round 7 a TEE asked each question itself and kept one answer; a retry (one in round 7) is counted, and a single draw per item could differ from the total by at most that count. This rests on OutLayer's storage not being rolled back.
204
+ - Instances of a model can share a signing key, so a signature doesn't identify the serving instance. Accepted configurations are recorded from NEAR's attested reports, not rebuilt from source.
205
+ - Verification is account-free but not offline: it needs the public services listed under [Try it](#try-it-no-account-no-api-key-no-test-set).
206
+
207
+ The full list, word for word as printed: [docs/LIMITS.md](https://github.com/fexx301/fuin/blob/main/docs/LIMITS.md).
208
+
209
+ ## Repository
210
+
211
+ | Path | What |
212
+ |---|---|
213
+ | `src/fuin/` | the `fuin` command: owner workflow and verifier ([map](https://github.com/fexx301/fuin/blob/main/docs/ARCHITECTURE.md)) |
214
+ | `contract/` | the registry contract and its tests |
215
+ | `tee/` | the TEE scorer (Rust, WASI P2) and its reproducible build `tee/build-docker.sh` |
216
+ | `ask/` | the asker, run as the locked OutLayer project `ask.fuin.testnet/asker`; reproducible build `ask/build-docker.sh` |
217
+ | `policy/` | what the verifier accepts: attestation policies, the pinned scorer and asker builds (`tee-v2.json`), sigstore's trust root |
218
+ | `site/` | the browser verifier and results page (`verify.js` must agree with the Python verifier on every certificate and fixture) |
219
+ | `examples/` | the 20 real certificates; `tampered/` fixtures and their manifest |
220
+ | `evidence/` | dated command output, transactions and write-ups behind every claim |
221
+ | `docs/` | [how it works](https://github.com/fexx301/fuin/blob/main/docs/HOW-IT-WORKS.md), [results](https://github.com/fexx301/fuin/blob/main/docs/RESULTS.md), [refusals](https://github.com/fexx301/fuin/blob/main/docs/REFUSALS.md), [limits](https://github.com/fexx301/fuin/blob/main/docs/LIMITS.md), [use](https://github.com/fexx301/fuin/blob/main/docs/USE.md), [architecture](https://github.com/fexx301/fuin/blob/main/docs/ARCHITECTURE.md), [costs and dependencies](https://github.com/fexx301/fuin/blob/main/docs/COSTS-AND-DEPENDENCIES.md) |
222
+
223
+ Running and fixing it: [MAINTAINING.md](https://github.com/fexx301/fuin/blob/main/MAINTAINING.md). Changes: [CHANGELOG.md](https://github.com/fexx301/fuin/blob/main/CHANGELOG.md). MIT licence.
fuin-1.0.0/README.md ADDED
@@ -0,0 +1,204 @@
1
+ # Fūin
2
+
3
+ Fūin (封印, pronounced *foo-een*) is Japanese for "seal": the test set is sealed on NEAR before any result is committed.
4
+
5
+ <picture>
6
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/fexx301/fuin/main/assets/fuin-logo-dark.svg">
7
+ <img src="https://raw.githubusercontent.com/fexx301/fuin/main/assets/fuin-logo.svg" alt="Fūin logo" width="320">
8
+ </picture>
9
+
10
+ Fūin publishes a private benchmark result that a stranger can check **without an account and without the test set**. Every answer carries a signature from the model's attested TEE key on NEAR AI Cloud, the set and results are committed on NEAR, and every answer is scored inside a TEE on OutLayer. A round can also reveal a sample picked by a future NEAR block, or reveal nothing at all. In round 7 a TEE made every model call itself and recorded one answer per question and counted every retry (round 7 had one), so no owner could quietly re-ask and keep the best answer.
11
+
12
+ Built at NEAR HACKATHON (Nov 1–14, 2026), tracks `privacy` and `open`.
13
+
14
+ ![The browser verifier refusing a real round-3 certificate whose revealed answer was edited after signing: REFUSED signature_text_mismatch](https://raw.githubusercontent.com/fexx301/fuin/main/assets/verify-refused.png)
15
+
16
+ *The browser verifier on a real round-3 certificate after "Edit an answer": the checks pass until the revealed sample is re-scored, where the edited answer no longer matches what the model signed.*
17
+
18
+ ## The problem
19
+
20
+ A benchmark owner has two bad options:
21
+
22
+ - **Publish the test set.** It leaks into the next model's training data, and the benchmark stops measuring anything.
23
+ - **Keep it private.** Then everyone has to take the owner's word for the scores: which model ran, whether answers were edited, and whether the grading was honest.
24
+
25
+ Fūin is a third option. The owner keeps the questions private. Anyone can check that the published score came from real, unedited answers by a named model running in a TEE, committed before any sample was drawn, and scored correctly against the owner's sealed answer key, over every answer. Whether the questions are any good stays with the owner. Private eval sets are already in use: NEAR's Delta League, for example, ranks fine-tuned models on one ([Illia Polosukhin, Nov 6, 2026](https://x.com/ilblackdragon/status/2118591003368296561)). Fūin certifies models that NEAR AI Cloud serves in an attested TEE, so certifying fine-tuned submissions like those would need them served the same way.
26
+
27
+ ## How it works
28
+
29
+ <picture>
30
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/fexx301/fuin/main/assets/fuin-flow-dark.svg">
31
+ <img src="https://raw.githubusercontent.com/fexx301/fuin/main/assets/fuin-flow.svg" alt="The six steps of a Fūin round: seal on NEAR, run (the model in a TEE signs each answer), commit on NEAR, close, check (a future block picks a sample, or a TEE scores every answer), verify (anyone gets VERIFIED, REFUSED or CAN'T CERTIFY)" width="940">
32
+ </picture>
33
+
34
+ **seal → run → commit → close → check → verify.**
35
+ 1. **Seal:** the owner seals a Merkle root over the salted questions, and a policy (request template, settings, scorer, audit size), on the NEAR registry.
36
+ 2. **Run:** each answer comes from NEAR AI Cloud, signed by the model's TEE key.
37
+ 3. **Commit:** the owner commits each run's root and total.
38
+ 4. **Close:** no more runs can join the round.
39
+ 5. **Check:** a future NEAR block picks a sample to reveal, or a TEE on OutLayer scores every answer.
40
+ 6. **Verify:** anyone rebuilds everything from the chain and the certificate, and gets one of three outcomes: **VERIFIED**; **REFUSED** with a reason code, when the evidence is wrong; or **CAN'T CERTIFY**, when evidence is missing or unsupported or a service didn't answer. An outage never decides a verdict.
41
+
42
+ The rounds come in three kinds, each a trade-off:
43
+
44
+ | | Sampled (`fuin seal`) | TEE-scored (`fuin seal --tee`) | Asked once (`fuin seal --ask`) |
45
+ |---|---|---|---|
46
+ | Questions revealed | a sample, picked by a future NEAR block | none | none |
47
+ | Who calls the model | the owner | the owner | a TEE, once per question, after the seal |
48
+ | How scores are checked | anyone re-scores the sample; a TEE re-scores every answer | a TEE re-scores every answer | the TEE scores each answer as it asks |
49
+ | Can the owner re-ask a question and keep the best answer? | yes (a printed limit) | yes (a printed limit) | no: the TEE keeps one answer per question and counts any retry |
50
+ | Models and token cap | all seven, 8,192 | all seven, 8,192 | fast models only, a smaller cap (DeepSeek-V4.1-Flash at 4,096) |
51
+ | Rounds here | 1–3 | 4–6 | 7 |
52
+
53
+ Every step in detail, with the deployment trace, the answer-key check and end-to-end encryption: [docs/HOW-IT-WORKS.md](https://github.com/fexx301/fuin/blob/main/docs/HOW-IT-WORKS.md).
54
+
55
+ ## Result: which NEAR AI Cloud model answers NEAR developer questions correctly?
56
+
57
+ Seven rounds of private questions, each answer cited to a line of [near/docs](https://github.com/near/docs) at commit `e2d2ea17`. They produced 20 certificates covering 2,302 answers from seven models. Every model ran with reasoning on and temperature 0. Every committed score was computed over every answer inside a TEE:
58
+
59
+ | Round | Kind | Questions | Committed score |
60
+ |---|---|---|---|
61
+ | 7 | asked once, end-to-end encrypted, 4,096 tokens | 37 | DeepSeek-V4.1-Flash **19** |
62
+ | 6 | TEE-scored, end-to-end encrypted | 96 | DeepSeek-V4.1-Flash abliterated **40** · DeepSeek-V4.1-Flash **38** · GLM-5.3-flash **33** · Qwen3.6-35B-A3B **22** · Qwen3.8-27B **22** · Qwen3.8-27B abliterated **21** · Qwen3-VL-30B-A3B **11** |
63
+ | 5 | TEE-scored, end-to-end encrypted | 96 | DeepSeek-V4.1-Flash **48** · GLM-5.3-flash **42** · Qwen3.8-27B **27** |
64
+ | 4 | TEE-scored | 155 | DeepSeek-V4.1-Flash **84** · GLM-5.3-flash **64** · Qwen3.8-27B **39** |
65
+ | 3 | sampled, 28 revealed | 300 | GLM-5.3-flash **122** · Qwen3.8-27B **77** |
66
+ | 2 | sampled, 23 revealed | 60 | GLM-5.3-flash **32** · Qwen3.8-27B **17** |
67
+ | 1 | sampled, 23 revealed, 4,096 tokens | 60 | GLM-5.3-flash **25** · Qwen3.8-27B **17** |
68
+
69
+ **What the scores show:**
70
+ - Rounds 2–6 used 8,192 tokens.
71
+ - DeepSeek-V4.1-Flash, in its base or abliterated version, leads rounds 4–6.
72
+ - GLM-5.3-flash beats Qwen3.8-27B in all six rounds they share.
73
+ - The rounds use different questions, so compare models within a round, not across rounds.
74
+
75
+ **Answer keys:** in rounds 4–7, which reveal nothing, a TEE checked each answer key against the near/docs line it cites. 374 of 384 appear there, and 10 are flagged as unchecked.
76
+
77
+ **More detail:**
78
+ - [docs/RESULTS.md](https://github.com/fexx301/fuin/blob/main/docs/RESULTS.md): the full table (served builds, revealed breakdowns, cut-offs), what each round disclosed, and how disclosure shrinks as suites grow.
79
+ - `evidence/*/README.md`: the transactions for every round.
80
+
81
+ ## For judges
82
+
83
+ **Quick check (about 2 minutes once dependencies are installed; the first `uv sync` can take 10 minutes on a slow connection; needs [uv](https://docs.astral.sh/uv/) and network, no account or API key):**
84
+
85
+ ```sh
86
+ git clone https://github.com/fexx301/fuin && cd fuin
87
+ uv sync # first run downloads the dependencies
88
+ env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-96-r6-deepseek-v4.1-flash-1017.json # about 1 minute: VERIFIED, every check printed
89
+ uv run pytest -q # 5 seconds, offline: 157 passed
90
+ uv run python scripts/check_fixtures.py examples/tampered/manifest.json # optional, about 4 minutes: 39 ok lines
91
+ ```
92
+
93
+ CAN'T CERTIFY with `evidence_unavailable` means a public service (NEAR's RPC, Intel or NVIDIA) didn't answer, not that the certificate is wrong: run the same command again.
94
+
95
+ **Full review (optional):**
96
+ - Run `scripts/review.sh` in the background. It takes about 30 minutes (allow 45).
97
+ - It waits on Intel, NVIDIA, NEAR, OutLayer, GitHub and Docker Hub, and retries when a public service rate-limits it.
98
+ - It exits 0 with `ALL CHECKS PASSED`.
99
+ - `AGENTS.md` lists the exit codes, what not to run and where the evidence lives.
100
+
101
+ Every claim maps to a command:
102
+
103
+ | Claim | Check | Expected |
104
+ |---|---|---|
105
+ | A stranger can verify a result without an account or the test set | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-60-r1-qwen3.8-27b.json` | `VERIFIED`, 10 `[pass]` lines, exit 0 |
106
+ | Each answer is signed by the model's TEE-attested key | same output, `signatures` and `attestation` lines | `60/60 provider_tee …`; `quote UpToDate, NRAS True` |
107
+ | The served container and weights are traced to NEAR's public deployment repo | same output, `deployment trace` line | `… nearai/cvm-compose-files: model-sg-qwen38-27b-fp8-tp1-coloc …` |
108
+ | The set and results were committed on NEAR, with the seal before the commit and the commit before the close | same output, `registry` line | `seal … < commit … < close …` |
109
+ | The owner can't choose which items a committed round reveals | same output, `audit sample` line; fixture `changed-audit` | `first final block ≥ close+2`; `REFUSED audit_sample_mismatch` |
110
+ | Tampering is refused with a specific reason | `uv run python scripts/check_fixtures.py examples/tampered/manifest.json` | 39 `ok` lines, exit 0 |
111
+ | Round 3's totals were re-scored over every answer inside a TEE, not only the sample | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-300-r3-glm-5.3-flash.json` | `[pass] tee score: all 300 items rebuilt and re-scored inside an OutLayer TDX enclave … total 122/300 and both roots match` |
112
+ | A round can reveal nothing and still be checked, with no answer predating its seal | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-155-r4-deepseek-v4.1-flash-1017.json` | `VERIFIED`; `[pass] reveals: none: a TEE-scored round reveals nothing …`; `[pass] tee score: all 155 items rebuilt and re-scored …: total 84/155 …`; fixtures `zero-reveal-unscored`, `zero-reveal-scorer-swapped` |
113
+ | A zero-reveal round's answer keys appear in the docs line they cite (a string match, not a check that the key is the right answer) | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-96-r6-glm-5.3-flash.json` | `[pass] answer keys: 92/96 answer keys appear in their cited line of near/docs at e2d2ea17, checked inside an OutLayer TDX enclave …; 4 flagged, not checked …: items 14, 35, 46, 94`; fixtures `ground-other-round`, `ground-hidden-flag`, `ground-fork-commit`, `ground-unpinned-build` |
114
+ | Each answer was asked once, by a TEE, not by the owner (no re-asking to keep the best answer) | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-37-r7-deepseek-v4.1-flash-1017.json` | `VERIFIED`; `[pass] asked once: all 37 answers asked once inside an OutLayer TDX enclave by asker dbbb286b744c… in ask.fuin.testnet/asker … 1 retried ask … every request rebuilt with the seal block's hash … equals the signed one, so every ask came after the seal … ask.fuin.testnet/asker was locked at the seal …`; fixtures `asked-unscored`, `asked-unchecked`, `asked-other-project`, `asked-total-edited`, `asked-check-edited`, `asked-hidden-retry` |
115
+ | Questions and answers can stay end-to-end encrypted, so NEAR's gateway never sees them | `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-96-r5-glm-5.3-flash.json` | `VERIFIED`; the policy line ends `fuin-request-v3 (end-to-end encrypted)`, and the limits print the end-to-end-encryption line; probe: `evidence/2026-11-05-e2ee-probe/` |
116
+ | The TEE scorer that ran is this repository's code | `tee/build-docker.sh` (any host with Docker; about 1.5 minutes once the image is pulled) | prints `b301d22b…`, the current pin in `policy/tee-v2.json` (scorer v9: scores as v7, grounds answer keys, runs the asked-check); `ask/build-docker.sh aaa2083` prints `dbbb286b…`, the asker locked in `ask.fuin.testnet/asker`. The earlier accepted builds rebuild the same way from their recorded commits: v8 `bb0d9a5d…` (round 7's grounding, `39a2da3`), v7 `acd9286f…` (groundings of rounds 4–6, `58523c7`), v2 `dabae968…` (rounds 1–4, `6381ee9`), v3 `2614ddaa…` (round 5, `907aec0`), v4 `cd36c486…` (the v4 rehearsal, `54a5b6e`), v5 `86db8213…` (`170c488`), v6 `67c2292e…` (round 6, `6b0705c`) |
117
+ | The registry's code can't be replaced (its seal and commit values are also checked against the owner's signed transactions) | `curl -s https://archival-rpc.testnet.fastnear.com -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"query","params":{"request_type":"view_access_key_list","finality":"final","account_id":"registry.fuin.testnet"}}'` | `"keys":[]` |
118
+
119
+ ## Try it (no account, no API key, no test set)
120
+
121
+ You need uv and network access to these services:
122
+ - Intel PCS;
123
+ - NVIDIA NRAS;
124
+ - an archival NEAR testnet RPC (FastNEAR's by default; set `FUIN_TESTNET_RPC` to pin another);
125
+ - the NEAR AI model catalog;
126
+ - raw.githubusercontent.com;
127
+ - Docker Hub.
128
+
129
+ One verification takes about 40 seconds.
130
+
131
+ 1. **Verify a real certificate:** `env -u NEARAI_API_KEY uv run fuin verify examples/cert-near-dev-60-r1-qwen3.8-27b.json`.
132
+ - You see `VERIFIED` with ten passing checks: rows, commitments, policy, signatures, reveals, attestation, deployment trace, registry, audit sample and TEE score.
133
+ - It also prints the scope line, the warnings and the limits that apply.
134
+ - The other 19 certificates in `examples/` verify the same way.
135
+ 2. **Watch tampering get refused:** `uv run python scripts/check_fixtures.py examples/tampered/manifest.json` prints 39 `ok` lines.
136
+ - Each fixture is a real certificate with one change.
137
+ - 29 are REFUSED, 9 are CAN'T CERTIFY, and 1 tricky but valid one must stay VERIFIED.
138
+ - Each fixture and its expected verdict: [docs/REFUSALS.md](https://github.com/fexx301/fuin/blob/main/docs/REFUSALS.md).
139
+ 3. **Read an audit:** `uv run fuin show examples/cert-near-dev-60-r2-glm-5.3-flash.json --audit` prints each of the 23 revealed questions with its expected answer, docs source, what the model said and its score.
140
+ 4. **Run the tests:**
141
+ - `uv run pytest`: 157 offline tests.
142
+ - `cd contract && cargo test`: 15 tests.
143
+ - `cd tee && cargo test`: the TEE scorer against Python on 3,600 generated cases, plus signed synthetic rounds.
144
+ 5. **Try it in a browser:** open [fexx301.github.io/fuin](https://fexx301.github.io/fuin/), or `site/index.html` from the clone. The page verifies certificates in the browser and lets you tamper with one live. It runs every local check, the live NEAR and OutLayer checks, the Intel TDX quote and the deployment trace. NVIDIA's GPU verdict can't run in a browser, so a published certificate shows `fuin verify`'s recorded result for it, matched to its exact bytes, and an uploaded one gets PARTLY CHECKED.
145
+
146
+ ## NEAR tools used
147
+
148
+ - **NEAR AI Cloud:**
149
+ - TEE-hosted open models through the gateway (`/v1/chat/completions` with `x-no-aliasing`);
150
+ - end-to-end encryption to the model's attested key (`X-Signing-Algo: ecdsa`, `X-Client-Pub-Key`, `X-Model-Pub-Key`);
151
+ - `provider_tee` response signatures (`/v1/signature`);
152
+ - model attestation reports (Intel TDX quote, NVIDIA GPU evidence, event log, compose-manager attestation);
153
+ - the public model catalog (`verifiable`, `attestationSupported`).
154
+ - **NEAR testnet contract** [`registry.fuin.testnet`](https://testnet.nearblocks.io/address/registry.fuin.testnet) (Rust, near-sdk 5.30, built with cargo-near):
155
+ - methods: `seal`, `commit_run`, `close_round`, `get_benchmark`, `get_run`;
156
+ - records can't be overwritten, runs are numbered per model, and callers pay for their own storage;
157
+ - **the account has no access keys**, so its code (hash `HvqaWNNceCX7AMtsanPobAt5mkAE2MsZdP2BURA2cgef`) can't be replaced. The verifier checks this.
158
+ - **OutLayer** (FastNEAR's verifiable off-chain compute on NEAR):
159
+ - `request_execution` on `outlayer.testnet` runs the TEE scorer in an Intel TDX enclave;
160
+ - an encryption key bound to the scorer's sha256 seals its private key;
161
+ - worker measurements are approved on `worker.outlayer.testnet`;
162
+ - the asker runs as the locked OutLayer project `ask.fuin.testnet/asker`, with sealed project storage and the owner's key stored as an OutLayer secret.
163
+ - **FastFS** serves the TEE scorer binary from a NEAR testnet transaction.
164
+ - **NEAR block hashes** serve as the audit seed and the seal-bound request nonce; reads go over JSON-RPC at `final` finality.
165
+ - **near-cli-rs** signs the owner's transactions; keys stay in the OS keychain.
166
+
167
+ ## Use it
168
+
169
+ ```sh
170
+ pip install fuin # or: uv tool install fuin
171
+ fuin verify cert.json # VERIFIED, REFUSED or CAN'T CERTIFY, with every check printed
172
+ ```
173
+
174
+ - **In CI:** a GitHub Action (`uses: fexx301/fuin@main`) fails the step unless every certificate is VERIFIED.
175
+ - **Your own private round** (`fuin check`, `seal`, `run`, `commit`, `close`, `reveal`, `tee-score`, `ask`): see [docs/USE.md](https://github.com/fexx301/fuin/blob/main/docs/USE.md).
176
+ - **A second person trying it:** [PILOT.md](https://github.com/fexx301/fuin/blob/main/PILOT.md) is a step-by-step kit. A fellow builder ran it unmodified on Windows 11 under WSL2.
177
+
178
+ ## Limits
179
+
180
+ Every VERIFIED prints the limits that apply to its certificate. In short:
181
+
182
+ - Scores are checked on the revealed sample, and on every answer through the TEE score. The TEE score trusts Intel TDX, OutLayer's worker approvals and its key service.
183
+ - In a round that reveals nothing, only the owner can see the questions. Answer keys are checked only against the docs line they cite, which doesn't prove a key is the right answer.
184
+ - In rounds 1–6 an owner could re-ask a sealed question and commit the best signed answer, and no certificate could show it. In round 7 a TEE asked each question itself and kept one answer; a retry (one in round 7) is counted, and a single draw per item could differ from the total by at most that count. This rests on OutLayer's storage not being rolled back.
185
+ - Instances of a model can share a signing key, so a signature doesn't identify the serving instance. Accepted configurations are recorded from NEAR's attested reports, not rebuilt from source.
186
+ - Verification is account-free but not offline: it needs the public services listed under [Try it](#try-it-no-account-no-api-key-no-test-set).
187
+
188
+ The full list, word for word as printed: [docs/LIMITS.md](https://github.com/fexx301/fuin/blob/main/docs/LIMITS.md).
189
+
190
+ ## Repository
191
+
192
+ | Path | What |
193
+ |---|---|
194
+ | `src/fuin/` | the `fuin` command: owner workflow and verifier ([map](https://github.com/fexx301/fuin/blob/main/docs/ARCHITECTURE.md)) |
195
+ | `contract/` | the registry contract and its tests |
196
+ | `tee/` | the TEE scorer (Rust, WASI P2) and its reproducible build `tee/build-docker.sh` |
197
+ | `ask/` | the asker, run as the locked OutLayer project `ask.fuin.testnet/asker`; reproducible build `ask/build-docker.sh` |
198
+ | `policy/` | what the verifier accepts: attestation policies, the pinned scorer and asker builds (`tee-v2.json`), sigstore's trust root |
199
+ | `site/` | the browser verifier and results page (`verify.js` must agree with the Python verifier on every certificate and fixture) |
200
+ | `examples/` | the 20 real certificates; `tampered/` fixtures and their manifest |
201
+ | `evidence/` | dated command output, transactions and write-ups behind every claim |
202
+ | `docs/` | [how it works](https://github.com/fexx301/fuin/blob/main/docs/HOW-IT-WORKS.md), [results](https://github.com/fexx301/fuin/blob/main/docs/RESULTS.md), [refusals](https://github.com/fexx301/fuin/blob/main/docs/REFUSALS.md), [limits](https://github.com/fexx301/fuin/blob/main/docs/LIMITS.md), [use](https://github.com/fexx301/fuin/blob/main/docs/USE.md), [architecture](https://github.com/fexx301/fuin/blob/main/docs/ARCHITECTURE.md), [costs and dependencies](https://github.com/fexx301/fuin/blob/main/docs/COSTS-AND-DEPENDENCIES.md) |
203
+
204
+ Running and fixing it: [MAINTAINING.md](https://github.com/fexx301/fuin/blob/main/MAINTAINING.md). Changes: [CHANGELOG.md](https://github.com/fexx301/fuin/blob/main/CHANGELOG.md). MIT licence.
@@ -0,0 +1,9 @@
1
+ # Tamper fixtures
2
+
3
+ `scripts/make_fixtures.py` writes one isolated mutation per file plus `examples/tampered/manifest.json`; `scripts/check_fixtures.py` verifies each in a fresh process and compares with the manifest. `check-output.txt` is the recorded run.
4
+
5
+ **answer-hint** is a real round, not an edit: `scripts/make_hint_fixture.py` seals a 1-item fixture benchmark (a question outside every hidden suite), has the owner append the answer to the prompt, gets the model's signature on that hinted request, and commits it honestly on chain. Every check passes except the request rebuild → REFUSED `request_policy_mismatch`. Round: `fixture-answer-hint-2`.
6
+
7
+ `fixture-answer-hint-1` (sealed, committed and closed on testnet, Nov 3) is an **unpublished** fixture round: its question turned out to be one of the hidden 60, so its certificate was deleted before any commit. The chain holds only its hashes.
8
+
9
+ The first fixture set (12 mutations of the thin-path certificate; `check-output.txt`, all 12 matching) was removed with that certificate, because it carried the same reused facts. The fixtures are rebuilt from the 60-item round's Qwen certificate, whose reveals are that round's own audited sample.
@@ -0,0 +1,17 @@
1
+ # Fresh-clone rehearsal, 2026-11-03
2
+
3
+ `git clone https://github.com/fexx301/fuin` into an empty directory (at commit `c995dc3`), then `./scripts/review.sh` with `NEARAI_API_KEY` unset. Result: **ALL CHECKS PASSED** in 243 s on the builder's Mac (uv and Rust already installed):
4
+
5
+ - both `examples/cert-near-dev-60-r1-*.json` VERIFIED;
6
+ - 14/14 tamper fixtures with their expected verdicts;
7
+ - 33 Python tests and 15 contract tests passed.
8
+
9
+ **Not yet shown:** a fresh AI-agent session (Claude Code or Codex) given only the README, and a machine without uv or Rust preinstalled.
10
+
11
+ ## Re-run, 2026-11-04 (after the review fixes and round 2)
12
+
13
+ Fresh clone at `9d68c4c`, `./scripts/review.sh` with no API key: **ALL CHECKS PASSED** in 234 s. All 4 certificates (2 models × 2 rounds) VERIFIED; 14/14 fixtures with their expected verdicts; 55 Python tests (including 21 offline hostile-input and outage tests) and 15 contract tests passed.
14
+
15
+ ## Re-run, 2026-11-04 (interactive page and in-browser verifier)
16
+
17
+ Fresh clone at `8b2d232`, `./scripts/review.sh` with no API key: **ALL CHECKS PASSED** in 311 s on Node 24. Steps: 4 certificates VERIFIED; 14/14 fixtures; 55 Python and 15 contract tests; and the in-browser verifier (`site/verify.js`, run under Node) matching the CLI on all 20 cases. Those cases cover the 4 real certificates, 13 tamper and outage cases (including a forged TDX quote, an edited app_compose and an unapproved configuration that must not hide registry tampering) and scorer parity on all 92 revealed answers.
@@ -0,0 +1,20 @@
1
+ # Image-provenance probe, 2026-11-03 (timebox 2 h; took about 1 h)
2
+
3
+ **Question:** the accepted `compose_hash` pins NEAR's compose-manager launcher, not the model containers. Can a stranger tie a signed answer to the container and weights that actually served it?
4
+
5
+ **Finding: the deployment can be traced; the container's build provenance is not checked.**
6
+
7
+ 1. Each model report carries `compose_manager_attestation`: a second TDX quote whose report data is `sha256(canonical action log) ‖ client nonce`. The log is canonical JSON (sorted keys, compact), as defined by `canonicalize_actions` in the public [nearai/compose-manager](https://github.com/nearai/compose-manager) `src/main.rs`. `fuin` recomputes the hash, checks the nonce, verifies the quote, and requires the same MRCONFIGID and RTMR3 as the model's own quote (same CVM).
8
+ 2. The measured `app_compose` pins `GITHUB_REPO=https://github.com/nearai/cvm-compose-files` as a literal, not an overridable variable. Each `compose_up` in the log names a tag, a commit, a compose file and the file's sha256.
9
+ 3. `fuin` replays the log to find which services are up, fetches each compose file at its logged commit from the public repo, checks the sha256, and reads every service that declares `--served-model-name <model>`.
10
+
11
+ Result on the `near-dev-60-r1` certificates (every file's sha256 matched):
12
+
13
+ | Model | Serving service(s) | Tag / file | Weights |
14
+ |---|---|---|---|
15
+ | Qwen/Qwen3.8-27B | `model-sg-qwen38-27b-fp8-tp1-coloc` | v0.0.539 `prod/small-models.yaml` | `Qwen/Qwen3.8-27B-FP8` rev `017b9c7a…` |
16
+ | z-ai/glm-5.3-flash | `model-sg-glm53-w4afp8-tp2-r1`…`r4` | v0.0.521 `prod/GLM-5.3-Flash-SGL-TP2x4-W4AFP8-*.yaml` | `graphistry/GLM-5.3-Flash-W4AFP8` snapshot `99f1fa70…` |
17
+
18
+ So the scores describe NEAR's deployed **quantized** weights (FP8; a W4AFP8 build), not the full-precision checkpoints that public benchmark tables usually report.
19
+
20
+ **Not covered:** the images' build provenance (cosign/SLSA attestations named in NEAR's compose README). Checking it needs tooling outside this verifier, so it stays a printed limit, and the trace does not gate the verdict (the spec gates only on verified image provenance). Contradictory trace evidence (hash, nonce, quote or file mismatch) is REFUSED `attestation_invalid` (fixture `edited-deployment-log`); an unavailable trace is a warning.
@@ -0,0 +1,23 @@
1
+ # Round `near-dev-60-r1`, 2026-11-03
2
+
3
+ 60 hidden NEAR-developer questions, each answer cited to a line of near/docs at commit e2d2ea17 (checked by `scripts/check_suite_sources.py`, 60/60). The suite is not in this repo; only the audited sample is revealed. Models: Qwen/Qwen3.8-27B and z-ai/glm-5.3-flash, both with `max_tokens` 4096, temperature 0, reasoning on (GLM cannot turn it off). Scorer `fuin-scorer-v2` (strict: the answer must be the number or term alone). Owner `fuin.testnet`; registry `registry.fuin.testnet` (locked: 0 access keys).
4
+
5
+ | Step | Transaction | Height |
6
+ |---|---|---|
7
+ | seal (n=60, D=6, k=23) | [GyvMjM5JvGKCaJR4PHdpTSp9shBFhWFNJ7z7Xr2tAaTF](https://testnet.nearblocks.io/txns/GyvMjM5JvGKCaJR4PHdpTSp9shBFhWFNJ7z7Xr2tAaTF) | 276079270 |
8
+ | commit_run Qwen3.8-27B, run 0: **17/60** | [9UTrvDF5hGPkNK8gVaGUEFV8wkUtcRYPzmtvvietrLYS](https://testnet.nearblocks.io/txns/9UTrvDF5hGPkNK8gVaGUEFV8wkUtcRYPzmtvvietrLYS) | 276088479 |
9
+ | commit_run glm-5.3-flash, run 0: **25/60** | [Dn2wWnsX2aAyXKZvu12LDXScEV5EMToxYQ2k2AMggZxL](https://testnet.nearblocks.io/txns/Dn2wWnsX2aAyXKZvu12LDXScEV5EMToxYQ2k2AMggZxL) | 276088494 |
10
+ | close_round | [6vqe9Q8q3u4WDrhhQwPRB4taPp4k8iKL1zB9sHiWS8GL](https://testnet.nearblocks.io/txns/6vqe9Q8q3u4WDrhhQwPRB4taPp4k8iKL1zB9sHiWS8GL) | 276088507 |
11
+
12
+ Seed block 276088509 (first final block ≥ close+2). Both certificates reveal the same 23 items.
13
+
14
+ | Model | Committed score | Answers cut off at the 4096-token cap (scored 0) | Owner-reported retries |
15
+ |---|---|---|---|
16
+ | Qwen3.8-27B | 17/60 | 17 | 1 |
17
+ | glm-5.3-flash | 25/60 | 21 | 1 |
18
+
19
+ Read the scores with the cap counts: a cut-off answer scores 0 whatever the model knew. The cap was sealed before the run and applies to both models.
20
+
21
+ **Disclosure:** 23 items are revealed by the audit. One more unrevealed item (index 17) cites the same docs line as revealed items 16 and 18, and its answer follows from theirs, so it is counted as disclosed: **24 disclosed, 36 hidden**. The thin-path questions, whose facts recur in this suite, are withheld from the repo (see `../2026-11-03-thin-path/`).
22
+
23
+ `verify-output.txt`: `env -u NEARAI_API_KEY uv run fuin verify …` on both certificates → VERIFIED, exit 0.
@@ -0,0 +1,23 @@
1
+ # Registry deployment, NEAR testnet, 2026-11-03
2
+
3
+ | Step | Transaction |
4
+ |---|---|
5
+ | Create `fuin.testnet` (faucet) | [CnEzSoNsYVQkQk5bKK2Xk5Ye2sAuDSzEQFK8s5FCYGSh](https://testnet.nearblocks.io/txns/CnEzSoNsYVQkQk5bKK2Xk5Ye2sAuDSzEQFK8s5FCYGSh) |
6
+ | Create `registry.fuin.testnet` (3 NEAR) | [6fUy8zfnfWxHxxLkNVBbr4hYWEZL2aFSgy699CFhftoh](https://testnet.nearblocks.io/txns/6fUy8zfnfWxHxxLkNVBbr4hYWEZL2aFSgy699CFhftoh) |
7
+ | Deploy `contract/` + `new()` | [FJGqyUNVYpecHBrKgWdPyJLHvVrS3fH9VqZhQvRuiw7w](https://testnet.nearblocks.io/txns/FJGqyUNVYpecHBrKgWdPyJLHvVrS3fH9VqZhQvRuiw7w) |
8
+
9
+ - Build: `cd contract && cargo near build non-reproducible-wasm` (cargo-near 0.22.0, rustc 1.95.0) → `fuin_registry.wasm`, sha256 `cbf03d1cf90160c803da8f30b5f08e27270c7ca46a25a3d43c2a9a2a2f89b1b9`.
10
+ - On-chain `code_hash` (base58 sha256): `Ej6EQ3yyVPL9xNLdvpZJaJWUYnyrx6T7Gw67kwTkH8BA` — matches the local build.
11
+ - Access keys: one full-access key is **still held** on `registry.fuin.testnet`, so the code can still be replaced. It is deleted before the first real sealed run; until then, records here are not append-only guaranteed.
12
+
13
+ ## Redeploy, 2026-11-03: storage paid by callers
14
+
15
+ Before this change anyone could call `seal` repeatedly and the registry paid the storage from its own balance; an owner could append runs without limit. Now `seal`, `commit_run` and `close_round` are payable: each call pays for the bytes it adds (`env::storage_byte_cost`), excess is refunded, and a benchmark holds at most 32 runs. The stored layout is unchanged, so the existing round reads as before.
16
+
17
+ - Redeploy (same account, no init): [A5pqvHDFJL5AtX6nQogeyhnfePJdZn6JULLyHT8NWEqb](https://testnet.nearblocks.io/txns/A5pqvHDFJL5AtX6nQogeyhnfePJdZn6JULLyHT8NWEqb). wasm sha256 `fb85b35fa74cce30800098ff3ee1660e29e4eafb52a755203a49136027bb99ac`; on-chain `code_hash` `HvqaWNNceCX7AMtsanPobAt5mkAE2MsZdP2BURA2cgef` matches the local build. The verifier now pins this hash.
18
+ - On-chain check: `seal` with 0 NEAR attached → `Smart contract panicked: attach at least 2740000000000000000000 yoctoNEAR to pay for 274 bytes of storage`. With 0.05 NEAR attached → sealed (`storage-check-1`, [8Dco3LWZotocaUd4xmXQ8fkPhSCZELPCr4pjssa3Uyrt](https://testnet.nearblocks.io/txns/8Dco3LWZotocaUd4xmXQ8fkPhSCZELPCr4pjssa3Uyrt)); the caller spent ≈0.003 NEAR including gas, and the rest was refunded. `storage-check-1` is a test record, not a benchmark.
19
+ - The thin-path round (`near-dev-thin-1`) was sealed under the previous code. Its certificate was re-revealed so its registry field carries the new pinned hash; the seed, sample and reveals are unchanged (a one-line diff), and it still verifies. That this was possible is the disclosed consequence of the full-access key still being held.
20
+
21
+ ## Registry locked, 2026-11-03
22
+
23
+ At the user's go-ahead, the only full-access key on `registry.fuin.testnet` was deleted: [BSzPeYQaLQeuyqBD1P1KZR1EVB8Kc57RRUQphVFchep7](https://testnet.nearblocks.io/txns/BSzPeYQaLQeuyqBD1P1KZR1EVB8Kc57RRUQphVFchep7). `view_access_key_list` now returns 0 keys, so the code (hash `HvqaWNNceCX7AMtsanPobAt5mkAE2MsZdP2BURA2cgef`) can no longer be replaced and the contract has no admin or upgrade methods. Records written from here on are append-only. The verifier checks the key count and warns if a registry still has a key. The thin-path round was sealed before the lock; its history is as disclosed above.
@@ -0,0 +1,13 @@
1
+ # Thin path, 2026-11-03 (one model, 5 items, all revealed)
2
+
3
+ Suite: 5 NEAR-developer questions, answers pinned to near/docs commit e2d2ea17. **The questions, the certificate and the fixtures built from it are withheld from this repo** (removed from its history on Nov 3): the same facts were reused in the hidden 60-item round `near-dev-60-r1`, so publishing them would disclose hidden items. The transactions and verify output below contain no question text. Owner `fuin.testnet`, registry `registry.fuin.testnet`.
4
+
5
+ | Step | Transaction | Execution height |
6
+ |---|---|---|
7
+ | seal | [5tUABH68SfnZrYgtVVd53TmQSY9QmWm6of5GsuYF336B](https://testnet.nearblocks.io/txns/5tUABH68SfnZrYgtVVd53TmQSY9QmWm6of5GsuYF336B) | 276073537 |
8
+ | commit_run (Qwen/Qwen3.8-27B, run 0, 2/5) | [3mF17GaExqBrhDLkAt1vJBgM3Z2DfUQemfzgRw7R8BbR](https://testnet.nearblocks.io/txns/3mF17GaExqBrhDLkAt1vJBgM3Z2DfUQemfzgRw7R8BbR) | 276073620 |
9
+ | close_round | [8e1QCYLDRgFqdf3xDkrvzr3vhqB6Lv5AcJRrAG8F7ZX4](https://testnet.nearblocks.io/txns/8e1QCYLDRgFqdf3xDkrvzr3vhqB6Lv5AcJRrAG8F7ZX4) | 276073646 |
10
+
11
+ Seed block 276073648. `env -u NEARAI_API_KEY uv run fuin verify …` output, recorded before the certificate was withheld: `verify-output.txt` (real cert VERIFIED; an edited-answer copy REFUSED `signature_text_mismatch`).
12
+
13
+ Not shown by this run: keeping part of the set hidden (all 5 revealed), a second model, the other refusal fixtures. The registry's full-access key was still held at the time, so its code could have been replaced.