|
| 1 | +// SPDX-License-Identifier: MPL-2.0 OR CC-BY-SA-4.0 |
| 2 | +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk> |
| 3 | +// Author: Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk> |
| 4 | += AFFIRMATION — SNIFs (Safer NIFs), as of 2026-06-16 |
| 5 | +:toc: macro |
| 6 | +:toclevels: 2 |
| 7 | + |
| 8 | +_the No-Bullshit file: what we affirm was true and checkable at this moment_ |
| 9 | + |
| 10 | +[NOTE] |
| 11 | +==== |
| 12 | +*Genre.* An *affirmation* is a solemn declaration of the truth of a statement, |
| 13 | +made by someone who _declines to swear an oath_. That is exactly what this is: |
| 14 | +our truth-as-best-believed at a stamped instant — binding on our honesty, not a |
| 15 | +claim of infallibility. It is not the README and not the EXPLAINME: |
| 16 | +
|
| 17 | +[cols="1,3,2",options="header"] |
| 18 | +|=== |
| 19 | +| File | Answers | Tense |
| 20 | +| `README` | _Where is this going, and why?_ — what SNIF is, why care, quick start | future / aspirational |
| 21 | +| `EXPLAINME` | _How is it built, and what's the evidence?_ — claim-to-code mapping | descriptive / mechanism |
| 22 | +| *`AFFIRMATION`* (this file) | _What can we honestly affirm was *true and checkable* at a stamped moment?_ | a frozen instant, falsifiable |
| 23 | +|=== |
| 24 | +
|
| 25 | +It is deliberately small, dated, and signed, so a reader can hold us to exactly |
| 26 | +what we affirmed, when we affirmed it. |
| 27 | +==== |
| 28 | + |
| 29 | +toc::[] |
| 30 | + |
| 31 | +== What this is, and how it is designed to work |
| 32 | + |
| 33 | +*What it is.* A short, dated, jointly-signed snapshot of what we can _honestly |
| 34 | +and verifiably_ claim about this repo at one exact moment. Nothing here is |
| 35 | +marketing and nothing is a promise about the future — both of those live in the |
| 36 | +README. This file is the receipt. |
| 37 | + |
| 38 | +*How it is designed to work.* Three moving parts make it trustworthy: |
| 39 | + |
| 40 | +. *Ground truth, not memory.* Every claim below was produced by _running the |
| 41 | + tool in the session that wrote this file_ — the proof checkers, the ABI |
| 42 | + conformance gate, and the in-BEAM test suite — on 2026-06-16. If a status doc |
| 43 | + or a memory said otherwise, the live run wins and we flag the contradiction. |
| 44 | +. *A frozen anchor.* The file names the exact commit SHA, branch, UTC timestamp, |
| 45 | + working-tree delta, and toolchain (see <<Verifiable anchor>>), so "true" |
| 46 | + always means "true _at this point_". Move the SHA and the file becomes a draft |
| 47 | + until re-run. |
| 48 | +. *A real signature.* It is landed by a *signed git commit*; that signature over |
| 49 | + this content at the anchored SHA is what makes the affirmation tamper-evident |
| 50 | + and attributable — not the prose alone. |
| 51 | + |
| 52 | +*We are fallible.* We can be wrong, stale, or simply mistaken about our own |
| 53 | +work. This file is our best honest belief, not a proof of its own correctness. |
| 54 | +Treat it as a falsifiable claim, not gospel. |
| 55 | + |
| 56 | +== The epistemic contract (read this before you trust _or_ attack) |
| 57 | + |
| 58 | +This document records our *best joint belief* at the timestamp below. It is |
| 59 | +*not a guarantee of correctness.* We may be wrong. We may have missed something |
| 60 | +— a hole, a stale doc, or a proof that checks an idealised _model_ we then fail |
| 61 | +to match in the running _runtime_. |
| 62 | + |
| 63 | +*No intentional overclaim.* That is the only guarantee here: we have not |
| 64 | +_knowingly_ inflated anything. Where something is tested-but-not-proved, we say |
| 65 | +so. Where a proof covers a model and trusts the real runtime, we say so. Where |
| 66 | +something is ledgered, weak, or merely-an-interface-check, we say so. An honest |
| 67 | +claim here that turns out false is an error to fix — not a lie. |
| 68 | + |
| 69 | +*Standing invitation to refute.* You are _invited_ to bulldoze any claim in this |
| 70 | +file. The fair form of the attack is: |
| 71 | + |
| 72 | +. Read this file at the stamped commit. |
| 73 | +. Reproduce (or fail to reproduce) the checks in <<reproduce,Reproduce it yourself>>. |
| 74 | +. _Then_ tell us where the discrepancy is, against the artefact as it stood at |
| 75 | + this moment — so we can either justify it or concede it on the record. |
| 76 | + |
| 77 | +An attack that skips steps 1–2 is attacking a strawman of a different date. |
| 78 | + |
| 79 | +*No fights before the facts are cleared up.* We are not interested in a dispute |
| 80 | +over a claim until the discrepancy has actually been checked against the |
| 81 | +artefact at this commit and we have had the chance to either justify it or |
| 82 | +concede it on the record. Good faith both ways: bring a reproducible |
| 83 | +discrepancy and we will fix the claim, the doc, or the code — promptly and |
| 84 | +without defensiveness. The goal is a corrected record, not a won argument. |
| 85 | + |
| 86 | +== Verifiable anchor |
| 87 | + |
| 88 | +[cols="1,3"] |
| 89 | +|=== |
| 90 | +| *Repo* | `hyperpolymath/snifs` (Safer NIFs — native compute for the BEAM via a wasmtime sandbox) |
| 91 | +| *Branch* | `feat/snifs-2` |
| 92 | +| *Commit (HEAD / anchor)* | `a82bb311609a2580f37dbbc7c1b6687ee7a3c0b7` — the signed commit that lands the SNIFs 2 work. This AFFIRMATION is landed by that commit's signed *child*, so **parent == anchor SHA**. |
| 93 | +| *Permalink* | https://github.com/hyperpolymath/snifs/tree/a82bb311609a2580f37dbbc7c1b6687ee7a3c0b7 |
| 94 | +| *Verified (UTC)* | 2026-06-16T12:22:08Z |
| 95 | +| *Toolchain* | Idris2 0.8.0 · Lean 4.13.0 · Agda 2.8.0 · Zig 0.15.2 · wasm-tools 1.249.0 · Elixir 1.18.4 / Erlang OTP 25 · wasmex 0.14.0 · Python 3.12.3 · just 1.50.0 |
| 96 | +|=== |
| 97 | + |
| 98 | +[NOTE] |
| 99 | +==== |
| 100 | +*State at this anchor.* Unlike an earlier draft of this file (which described an |
| 101 | +uncommitted working tree), the verification affirmed here **is committed** at the |
| 102 | +anchor SHA `a82bb31` — `SnifIsolation.agda`, `SnifVerdict.agda`, `BufferAbi.idr`, |
| 103 | +the guest-aware conformance tool, the metamorphic gate, the demo, the Rust guests |
| 104 | +and the reconciled docs are all in that commit (signed, `id_ed25519_signing`). The |
| 105 | +gate results below were re-run against that committed state at the verified UTC |
| 106 | +above. Build artifacts (`priv/*.wasm`, `*.agdai`, `zig/buffer_abi_build/`) are |
| 107 | +intentionally **not** committed — CI rebuilds them. This AFFIRMATION itself is |
| 108 | +landed by the signed child commit; if its parent SHA matches the anchor and the |
| 109 | +commit verifies, the affirmation is anchored. Move HEAD past it and re-run |
| 110 | +<<reproduce>> before trusting it. |
| 111 | +==== |
| 112 | + |
| 113 | +== Companion documents and repo metadata (cross-check) |
| 114 | + |
| 115 | +This affirmation should be read against the repo's own public claims. Where they |
| 116 | +drift from what we verified, we say so here rather than leave the reader to find out. |
| 117 | + |
| 118 | +* *`README.adoc`* — present. link:README.adoc[_"SNIFs: Safer Native Implemented |
| 119 | + Functions for the BEAM via WebAssembly Sandboxing"_]. Sells the vision + the |
| 120 | + scope ceiling; this file is its receipt for one moment. |
| 121 | +* *`EXPLAINME.adoc`* — present. Maps README claims to code paths and carries the |
| 122 | + corrected "SNIF realizes _a_ cleave instance, not _the_ cleave" framing. The |
| 123 | + estate trio (README / EXPLAINME / AFFIRMATION) is *complete* for this repo once |
| 124 | + this file lands. |
| 125 | +* *`PROOF-STATUS.md` / `PROOF-NEEDS.md`* — the living ledgers this snapshot cites, |
| 126 | + reconciled to the verified state in the anchor commit: `PROOF-STATUS.md` now counts |
| 127 | + 10 gated artifacts, marks SEC-1 F1/F2 **RESOLVED** (keeping F3/F4/F5 as standing |
| 128 | + precision notes), and records ABI-7 at 15/20 + CI-1 done. |
| 129 | +* *GitHub repo description* — corrected this session to _"SNIFs: **Safer** Native |
| 130 | + Implemented Functions for the BEAM via WebAssembly Sandboxing"_ (it previously said |
| 131 | + "Safe"; the project renamed *"Safe NIFs" → "Safer NIFs"* — see `CHANGELOG` — because |
| 132 | + the end-to-end guarantee is _not_ unconditional, see <<nuance>>). |
| 133 | +* *GitHub topics* — `beam`, `elixir`, `erlang`, `fault-tolerance`, `nif`, |
| 134 | + `research`, `wasmtime`, `webassembly`, `crash-isolation`. *Under-claim:* there |
| 135 | + is no `formal-verification` topic, although the repo now carries 10 |
| 136 | + machine-checked proof artifacts + a machine-checked operational isolation |
| 137 | + theorem. The tags undersell the verification rather than oversell it. |
| 138 | + |
| 139 | +== The honest state (one breath) |
| 140 | + |
| 141 | +*SNIFs is a working, machine-verified "safer NIF" for the BEAM: native |
| 142 | +compute/buffer functions compiled to WebAssembly and run in a wasmtime sandbox, |
| 143 | +so a guest fault becomes a catchable `{:error, _}` and the BEAM survives. The |
| 144 | +in-BEAM demo is green, the formal gate is green (including an operational |
| 145 | +crash-isolation theorem with deniability and a 6-origin error taxonomy wired in), |
| 146 | +and the interface + a slice of behaviour are gated against the real built wasm — |
| 147 | +yet it remains "Safer", not "Safe": one explicit runtime-faithfulness assumption |
| 148 | +is trusted, not yet machine-discharged, and several coverage items are honestly |
| 149 | +ledgered.* |
| 150 | + |
| 151 | +=== What is solid (and how we checked) |
| 152 | + |
| 153 | +* *The formal gate is green — verified this moment.* `just proof-check-all` → |
| 154 | + *exit 0*: **7 Idris2** modules (`Types`, `ABI/{Layout,Platform,Pointers,Foreign,Compliance,BufferAbi}`), |
| 155 | + **1 Lean4** (`ApiTypes`), **2 Agda** (`SnifVerdict`, `SnifIsolation`, both |
| 156 | + `agda --safe --without-K`), plus the dangerous-pattern scan (no |
| 157 | + `believe_me`/`postulate`/`sorry`/`Admitted`). |
| 158 | +* *SEC-1 — the operational crash-isolation theorem — typechecks.* |
| 159 | + `verification/proofs/agda/SnifIsolation.agda` proves, by induction over a |
| 160 | + fuelled host↔guest small-step model: verdict ∈ ok ⊕ trap, host survives every |
| 161 | + outcome, the trap carries no guest value, and — newly wired into the |
| 162 | + operational run — the fault residue is the _redacted_ secret only, so two |
| 163 | + faults with equal redaction are host-indistinguishable (`run-deniable`). The |
| 164 | + verdict now models the real *6-origin* taxonomy (guest-fault / host-budget / |
| 165 | + pre-exec) via a `call` front-end, not a binary trap. It is proven *modulo* an |
| 166 | + explicit `FaithfulRuntime` record hypothesis (the TCB) — see <<nuance>>. |
| 167 | +* *Interface conformance is gated against the real binaries.* |
| 168 | + `just abi-conformance` → *exit 0*: **15 ABI specs** across **2 guests** |
| 169 | + (`safe_nif` 8, `buffer_abi` 7) — the built wasm's real export signatures match |
| 170 | + the verified Idris2 model exactly, including three void-returning buffer |
| 171 | + exports. |
| 172 | +* *In-BEAM behaviour runs.* `mix test` (in `demo/`) → *30 tests, 0 failures* on |
| 173 | + Erlang/OTP 25, Elixir 1.18.4, with the precompiled `wasmex` 0.14 NIF. This |
| 174 | + includes crash isolation across every failure mode (OOB / unreachable / @panic |
| 175 | + / overflow / div-zero → `{:error,_}`, BEAM alive after each) and a new |
| 176 | + dependency-free *metamorphic behaviour gate* over the numeric kernels. |
| 177 | + |
| 178 | +[#nuance] |
| 179 | +=== The honest nuance you must not lose |
| 180 | + |
| 181 | +. *"Safer", not "Safe" — the runtime TCB is trusted, not proven.* SEC-1 is proven |
| 182 | + over a model whose first argument is a `FaithfulRuntime` record bundling |
| 183 | + primitive single-step facts (wasmtime never gets stuck; a trapped step is caught |
| 184 | + and surfaced as `{:error,_}` with the scheduler preserved). The prose claim that |
| 185 | + this record is _faithful to wasmtime/wasmex_ — "wasmtime ⊨ FaithfulRuntime" — is |
| 186 | + **assumed, not discharged in a prover** (it is the named open item SEC-1-TCB, a |
| 187 | + WasmCert-Coq effort). This residual assumption is exactly _why_ the project is |
| 188 | + Safer NIFs. |
| 189 | +. *Model ↔ code faithfulness is only partly mechanised.* The proofs verify a |
| 190 | + logical model. The ABI conformance gate closes the *interface* slice of |
| 191 | + model↔code (signatures match the real wasm); the metamorphic tests close a |
| 192 | + *behaviour* slice (the kernels behave as modelled). The general claim "the Agda |
| 193 | + model mirrors the Zig/Rust/wasmex code" is argued + tested, not itself |
| 194 | + machine-verified. |
| 195 | +. *Honest proof labels (not over-claims).* In SEC-1, `okOrTrap` and `noForgery` |
| 196 | + are *structural* facts about the `Verdict` datatype (true with no runtime in |
| 197 | + scope); the load-bearing, TCB-consuming content is host *preservation* |
| 198 | + (`survives`). `noForgery` is the parametric non-existence of a total extractor, |
| 199 | + not an instance-level claim. We state these rather than dress them up. |
| 200 | + |
| 201 | +=== Known-incomplete but honestly fenced (loud failure, never silent miscompile) |
| 202 | + |
| 203 | +* The isolation thesis depends on building guests with `-OReleaseSafe`. Under |
| 204 | + `-OReleaseFast` the same faults become *silent wrong answers* — this is |
| 205 | + demonstrated, on purpose, as the negative control in the demo suite (e.g. an OOB |
| 206 | + read returns a plausible adjacent value). The shipped guests are ReleaseSafe; |
| 207 | + the ReleaseFast artifact exists only to keep that danger visible and tested. |
| 208 | + |
| 209 | +=== Outstanding / weak / refuted (no spin) |
| 210 | + |
| 211 | +* *SEC-1-TCB — open.* Discharging "wasmtime ⊨ FaithfulRuntime" in-prover |
| 212 | + (WASM trap-soundness; trap → `{:error,_}`; scheduler resumed) is the remaining |
| 213 | + half of an end-to-end isolation proof. Not started here. |
| 214 | +* *ABI-7 — partial.* 15 of ~20 Zig export sites are modelled+gated (`safe_nif` + |
| 215 | + `buffer_abi`). `burble_fft` (`fft`/`ifft`/…) is *not* built into any artifact and |
| 216 | + uses `(ptr,len)` slice marshalling = the deeper *ABI-6* obligation; it and the |
| 217 | + two Rust guests are *ledgered, not gated* (`PROOF-NEEDS.md`). |
| 218 | +* *GAP-1b — partial.* The metamorphic behaviour gate covers the *scalar* kernels |
| 219 | + (`fibonacci` recurrence/monotonicity/i64-width; `checked_add` as a wrapping i32 |
| 220 | + ring); the *buffer* kernels (`sum_f32` permutation-invariance, scale-then-sum) |
| 221 | + are the next increment. |
| 222 | +* *Finding surfaced by the new gate:* the export named `checked_add` is a |
| 223 | + **misnomer** — it is two's-complement *wrapping* addition (`a +% b`, intentional |
| 224 | + per `zig/src/safe_nif.zig`), *not* a trapping/checked add (the trapping demo is |
| 225 | + the separate `crash_overflow`). The gate characterises the real behaviour; |
| 226 | + whether to rename the export is the owner's call. |
| 227 | +* *CI.* The ABI conformance gate now runs as a CI job (`proofs.yml`), but making it |
| 228 | + a *required* status check is an owner-only branch-protection action — not done. |
| 229 | +* *Adversarial mutation re-audit — completed, verdict SOLID.* Four independent |
| 230 | + skeptics mutation-tested the SEC-1 sharpening (`--safe --without-K`): every targeted |
| 231 | + mutation was rejected as expected, so F1 (lossy redaction), F2 (the pre-exec |
| 232 | + coverage + the `guestFault` tag) and F5 (the partial `Alive`) are genuinely |
| 233 | + load-bearing — not vacuous; `--safe` is enforced (an injected `postulate` is |
| 234 | + rejected) and `run`/`drive` totality is real (a non-decreasing-fuel mutation is |
| 235 | + rejected). The only weakness it found was *stale prose*, corrected in the anchor commit. |
| 236 | +* *Required-check + Zenodo.* Making the conformance gate a **required** status check is |
| 237 | + owner-only branch-protection (pending). The paper's Zenodo DOI still carries the old |
| 238 | + "Safe" title; the rename should land on the next deposit. |
| 239 | + |
| 240 | +[#reproduce] |
| 241 | +== Reproduce it yourself |
| 242 | + |
| 243 | +From the repo root, at the anchor commit above (you need the toolchain in |
| 244 | +<<Verifiable anchor>>): |
| 245 | + |
| 246 | +[source,sh] |
| 247 | +---- |
| 248 | +just proof-check-all # expect exit 0: |
| 249 | + # 7 Idris2 OK, 1 Lean4 OK, 2 Agda OK (SnifVerdict + SnifIsolation), |
| 250 | + # dangerous-pattern scan PASS |
| 251 | +just abi-conformance # expect exit 0: builds safe_nif + buffer_abi wasm, then |
| 252 | + # "all 2 guest(s) conform (15 ABI specs verified ...)" |
| 253 | +cd demo && mix test # expect "30 tests, 0 failures" (OTP 25 / Elixir 1.18.4) |
| 254 | +---- |
| 255 | + |
| 256 | +For the SEC-1 proof on its own (the exact gate invocation): |
| 257 | + |
| 258 | +[source,sh] |
| 259 | +---- |
| 260 | +agda -i verification/proofs/agda --safe --without-K --no-libraries \ |
| 261 | + verification/proofs/agda/SnifIsolation.agda # expect exit 0 |
| 262 | +---- |
| 263 | + |
| 264 | +== One-line characterisation (quote this) |
| 265 | + |
| 266 | +[quote] |
| 267 | +____ |
| 268 | +"A working, machine-verified *Safer* NIF for the BEAM: native compute sandboxed |
| 269 | +in wasmtime so a guest fault becomes `{:error,_}` and the VM survives — with an |
| 270 | +operational crash-isolation theorem (deniability + 6-origin taxonomy, Agda |
| 271 | +`--safe`), an interface gate matching 15 export signatures to the real wasm, and |
| 272 | +a behaviour gate over the scalar kernels — all green this moment; *Safer not Safe* |
| 273 | +because one runtime-faithfulness assumption is trusted, not yet proven, and |
| 274 | +`burble_fft`/Rust/buffer-behaviour coverage is honestly ledgered. No intentional |
| 275 | +overclaim." |
| 276 | +____ |
| 277 | + |
| 278 | +== Joint attestation |
| 279 | + |
| 280 | +We, the undersigned, assert that *to the best of our joint belief at the |
| 281 | +timestamp above, every claim in this file is true and was checked as described* |
| 282 | +— with no intentional overclaim, and with the open gaps stated rather than hidden. |
| 283 | + |
| 284 | +* *Engineering party (AI):* Claude Opus 4.8 (`claude-opus-4-8[1m]`) — ran the |
| 285 | + proof gate, the ABI conformance gate, and the in-BEAM test suite recorded here |
| 286 | + on 2026-06-16T12:22:08Z (against the committed anchor state) and stands behind the |
| 287 | + wording above as a faithful report of those runs. |
| 288 | +* *Owner / maintainer:* Jonathan D.A. Jewell — _signs by committing this file with |
| 289 | + `-S` (`id_ed25519_signing`); the git commit signature over this content, whose |
| 290 | + parent is the anchor SHA recorded above, is the cryptographic form of this |
| 291 | + affirmation._ |
| 292 | ++ |
| 293 | +Signed-off-date: 2026-06-16 |
| 294 | + |
| 295 | +[TIP] |
| 296 | +The authoritative, tamper-evident signature is the *signed git commit* that lands |
| 297 | +this file; its **parent is the anchor SHA** `a82bb31`. If that parent matches |
| 298 | +<<Verifiable anchor>> and the commit verifies (`id_ed25519_signing`), this |
| 299 | +affirmation is anchored. If HEAD later moves past it, re-run <<reproduce>> and write |
| 300 | +a fresh affirmation rather than trusting a stale one. |
0 commit comments