Skip to content

Commit 2b52266

Browse files
Merge pull request #33 from hyperpolymath/reinforce/vclut-25-phase5c6-stance
vcl-ut #25 P5c (step 6): stance flip OWED->RESOLVED (Tier-1 recompute-PCC) + ADR-0002
2 parents 0a43bce + 3a6f32f commit 2b52266

4 files changed

Lines changed: 341 additions & 167 deletions

File tree

CHANGELOG.md

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,32 @@ CI-gated and green:
4343
it byte-for-byte conformant with the Rust `to_wire` encoder by `Refl`
4444
on golden fixtures (regeneration oracle:
4545
`src/interface/parse/tests/conformance_emit.rs`). The C-ABI
46-
`Statement` marshalling *decode* side is now certified. Disclosed:
46+
`Statement` marshalling *decode* side is certified. Disclosed:
4747
the NaN *payload* is not preserved across the Idris `Double` boundary
4848
(finite + infinite values bit-exact; Rust proptest remains the
49-
exhaustive float witness). OWED: **P5c — typed-wasm PCC transport**
50-
(proof term + checker kernel the consumer re-runs; *re-checkable*,
51-
TCB = checker kernel; the estate-aligned objective — the `ffi/zig`
52-
fail-closed shim is retained only as the C-ABI attestation
53-
*fallback*, not the endpoint); **P5d** — the signed-attestation
54-
fallback contract for C-only consumers. Re-checkable transport is
55-
impossible only over a C ABI, not over typed-wasm (two-tier boundary
56-
model: `verification/proofs/VERIFICATION-STANCE.adoc`).
49+
exhaustive float witness).
50+
- Phase 5 / vcl-ut#25**Tier-1 recompute-PCC RESOLVED**: P5c-1 (#30)
51+
certified `OctadSchema` codec (closes schema-marshalling OWED);
52+
P5c-2/3/4 (#31) `vcltotal_parse::decider` — a faithful Rust port of
53+
the corpus decision core (`Schema`/`Decide`/`Checker`
54+
`checkLevel0..10`/`certifiedLevel`), machine-pinned to the corpus's
55+
public deciders via `WireConformance` on shared golden bytes
56+
(find-dependent verdicts pinned Rust-side + input-value conformance,
57+
disclosed); P5c-5 (#32) the recompute **`wasm32`** artefact
58+
`src/interface/recompute-wasm` (`vcl_recompute`, fail-closed, one
59+
audited host/guest `unsafe` block; all logic in the forbid-unsafe
60+
crate); P5c-6 (this change) the `OWED→RESOLVED` stance flip + ADR
61+
`docs/decisions/0002-ffi-attestation-trust-boundary.adoc`. The
62+
consumer **re-runs** the certified decision and compares — PCC by
63+
recomputation, not proof transport. Plain `wasm32` suffices (type
64+
system not load-bearing under recompute); `affinescriptiser` N/A
65+
(resource-required + wasm-backend-pending; disclosed in
66+
`AFFINESCRIPTISER-NA.adoc`, not faked). **OWED — P5d (Tier-2
67+
fallback):** the C-ABI signed-attestation contract +
68+
`vclut_rs_verify` linkage for consumers that cannot run the wasm.
69+
A re-checkable proof is impossible *only* over the C-ABI fallback
70+
tier (canonical two-tier model:
71+
`verification/proofs/VERIFICATION-STANCE.adoc`).
5772

5873
`verification/proofs/VERIFICATION-STANCE.adoc` is the authoritative,
5974
precisely-scoped catalogue (residual OWED items disclosed, not masked).

PROOF-NEEDS.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
- **Languages**: Rust, ReScript, Idris2, Zig
88
- **Existing ABI proofs**: `src/interface/abi/*.idr` + domain-specific Idris2: `src/core/Checker.idr`, `Grammar.idr`, `Levels.idr`, `Schema.idr`, `Composition.idr`
99
- **Machine-verified**: the full `VclTotal` proof corpus — `verification/proofs/vclut-core.ipkg` builds clean under idris2 0.8.0 (`idris2 --build`, exit 0, `%default total`, **zero proof-escape symbols**, CI-gated by `.github/workflows/proof-corpus.yml`) as **12 modules** (`ABI.{Types,Layout,LayoutProofs}` + `Core.{Grammar,Schema,Decide,Levels,Checker,Composition,Epistemic}` + `Interface.{WireDecode,WireConformance}`), plus the self-contained `verification/proofs/SafetyL4Model.idr` (`--check`, exit 0). Phases 1–4 are on `origin/main` (PRs #21/#22/#23/#24); Phase 5 / vcl-ut#25 (trusted Rust parser P5a #26, wire codec P5b-step-1 #28, **certified Idris wire decoder + cross-language `Refl` conformance** P5b-step-2) reinforces the FFI boundary.
10-
- **Status (Phase 0 → 4 RESOLVED, honestly; Phase 5 boundary reinforcement in progress)**: the Phase-0 blockers are fixed, not faked — the corpus compiles and is machine-checked; `ABI.Types`/`Grammar` errors repaired; **L2/L3/L5 de-vacuized** (Phase 2, evidence-carrying predicates over `Core.Decide`); all ten levels carry `checkLevelNSound` and `Checker.certifyAt`/`certifyRequested` assemble a genuine dependent `SafetyCertificate` (Phase 3); the Zig FFI is no longer a fabricating stub — it is **fail-closed** with a proof-gated `Checker.certifiedLevel` mint (Phase 3d). **Phase 5 (vcl-ut#25)**: a trusted Rust/SPARK-grade parser + a deterministic versioned wire codec exist, and the *decode* side of the C-ABI `Statement` marshalling is now **certified** — `VclTotal.Interface.WireDecode` is a total (zero-escape) decoder proven byte-for-byte conformant with the Rust encoder by `Refl` (`WireConformance`). Remaining honest gaps are precisely scoped (P5c = typed-wasm PCC proof-transport — proof term + checker kernel the consumer re-runs, *re-checkable*, the estate-aligned objective; the C-ABI/Zig shim retained only as the fail-closed attestation fallback; P5d = signed-attestation *fallback* contract for C-only consumers; plus L3 subquery/heuristic scoping; L9/L10 predicate depth; the additive↔ceil `alignUp` sliver; the disclosed NaN-payload limitation of the Idris `Double` boundary). Re-checkable transport is impossible *only* over a C ABI, not over the estate's typed-wasm target. `verification/proofs/VERIFICATION-STANCE.adoc` is the authoritative, proof-backed catalogue and takes precedence over this file.
10+
- **Status (Phase 0 → 4 RESOLVED, honestly; Phase 5 boundary reinforcement in progress)**: the Phase-0 blockers are fixed, not faked — the corpus compiles and is machine-checked; `ABI.Types`/`Grammar` errors repaired; **L2/L3/L5 de-vacuized** (Phase 2, evidence-carrying predicates over `Core.Decide`); all ten levels carry `checkLevelNSound` and `Checker.certifyAt`/`certifyRequested` assemble a genuine dependent `SafetyCertificate` (Phase 3); the Zig FFI is no longer a fabricating stub — it is **fail-closed** with a proof-gated `Checker.certifiedLevel` mint (Phase 3d). **Phase 5 (vcl-ut#25)**: a trusted Rust/SPARK-grade parser + a deterministic versioned wire codec exist, and the *decode* side of the C-ABI `Statement` marshalling is now **certified** — `VclTotal.Interface.WireDecode` is a total (zero-escape) decoder proven byte-for-byte conformant with the Rust encoder by `Refl` (`WireConformance`). **P5c (vcl-ut#25) — Tier-1 recompute-PCC RESOLVED** (#26/#28/#29/#30/#31/#32): trusted Rust parser, certified `Statement`+`OctadSchema` decoder (`Refl`-pinned), faithful Rust decision port machine-pinned to the corpus, and a fail-closed recompute `wasm32` artefact the consumer re-runs. Remaining honest gaps precisely scoped: **P5d** = C-ABI signed-attestation *fallback* contract for non-wasm consumers (Tier-2, OWED); plus the disclosed limits (NaN-payload reconstruction; cross-module `Refl` non-reduction of `find`/`elemBy` ⇒ schema-resolution-dependent verdicts pinned Rust-side + input-value conformance; L3 subquery/heuristic scoping; L9/L10 predicate depth; additive↔ceil `alignUp` sliver). A re-checkable proof is impossible *only* over the C-ABI fallback tier; Tier-1 sidesteps it by recomputation, not proof transport. `verification/proofs/VERIFICATION-STANCE.adoc` is the authoritative, proof-backed catalogue and takes precedence over this file.
1111

1212
## What Needs Proving
1313

@@ -52,15 +52,20 @@
5252
Idris decoder into the certified `Statement`, proven byte-for-byte
5353
conformant with the Rust encoder by `Refl` in
5454
`VclTotal.Interface.WireConformance`. The marshalling seam's *decode*
55-
side is therefore now machine-verified. **P5c** (the estate-aligned
56-
objective): transport the certificate over the **typed-wasm** target
57-
as a proof term + a small checker kernel the consumer re-runs —
58-
proof-carrying code, *re-checkable*, TCB = checker kernel + typed-wasm
59-
verifier (re-checkable transport is impossible only over a C ABI; the
60-
`ffi/zig` fail-closed shim is retained only as the C-ABI attestation
61-
fallback). **P5d** (fallback tier): the signed-attestation contract
62-
for consumers reachable only over C. Both OWED; see the two-tier
63-
boundary model in `verification/proofs/VERIFICATION-STANCE.adoc`.
55+
side is machine-verified. **P5c — RESOLVED (Tier-1 recompute-PCC):**
56+
the consumer re-runs the certified decision itself from the
57+
fail-closed `wasm32` module `src/interface/recompute-wasm`
58+
(`vcl_recompute`); the decision core is a faithful Rust port of the
59+
corpus (`Schema`/`Decide`/`Checker`) machine-pinned via
60+
`WireConformance`. TCB = conformance-pinned decider image + wasm
61+
runtime + the once-proved corpus (offline-re-checkable) — *not* a
62+
trusted tag, *not* a transported proof object. Plain `wasm32`
63+
suffices (type system not load-bearing under recompute);
64+
`affinescriptiser` N/A (disclosed). **P5d — OWED (Tier-2 fallback):**
65+
the C-ABI signed-attestation contract + `vclut_rs_verify` linkage,
66+
for consumers that cannot run the wasm; the `ffi/zig` fail-closed
67+
shim is its scaffolding. See the canonical two-tier boundary model
68+
in `verification/proofs/VERIFICATION-STANCE.adoc` (authoritative).
6469
- Optional future work: prove the ReScript frontend faithfully tracks
6570
the Idris2 grammar (low priority; it is a convenience frontend, not a
6671
trust anchor).
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
= Architecture Decision Record: 0002-ffi-attestation-trust-boundary
2+
<!-- SPDX-License-Identifier: PMPL-1.0-or-later -->
3+
<!-- Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk> -->
4+
5+
# 2. FFI trust boundary: recompute-PCC over wasm32 (Tier-1), C-ABI attestation (Tier-2)
6+
7+
Date: 2026-05-19
8+
9+
## Status
10+
11+
Accepted (Tier-1 RESOLVED; Tier-2 / P5d OWED). Tracked:
12+
hyperpolymath/vcl-ut#25. Authoritative companion:
13+
`verification/proofs/VERIFICATION-STANCE.adoc` (canonical two-tier
14+
boundary model) — this ADR records *why*; the stance records *what is
15+
and is not proven*.
16+
17+
## Context
18+
19+
vcl-ut is the doubly-trusted hypatia↔verisim interface. The Idris2
20+
corpus proves, machine-checked and CI-gated, that the 10-level VCL-total
21+
decision procedure is sound (`checkLevelNSound`,
22+
`Checker.certifyAt`/`certifyRequested` assembling a dependent
23+
`SafetyCertificate`). The open question was how a *consumer* obtains
24+
that guarantee across a process/language boundary.
25+
26+
Constraints established during Phase 5:
27+
28+
- A **C ABI erases types to machine words**: a dependent
29+
`SafetyCertificate` cannot cross it as a re-checkable object. Over a
30+
C ABI the honest ceiling is *trusted-certifier attestation* (trust
31+
the minting checker; the token is unforgeable, bound to
32+
`(sha256(query), schema_id, level)`).
33+
- A **proof-term-PCC** design (ship a core proof term + a small
34+
dependent kernel the consumer runs) was considered and **rejected**:
35+
Idris2 0.8.0 ships no embeddable verified core kernel, and building
36+
one is its own subproject of unbounded scope.
37+
- The estate's `affinescriptiser` (Rust→typed-wasm wrapper) **does not
38+
apply**: it structurally requires ≥1 `[[resources]]` and the
39+
verdict entry is a pure resource-free function (fabricating a
40+
resource to satisfy the tool would violate the verification-honesty
41+
doctrine), and its wasm backend is Phase-2-pending. (Disclosed:
42+
`src/interface/recompute-wasm/AFFINESCRIPTISER-NA.adoc`.)
43+
44+
## Decision
45+
46+
Adopt a **two-tier boundary**:
47+
48+
**Tier-1 — recompute-PCC over plain `wasm32` (the achieved tier).**
49+
The consumer is shipped the `wasm32` module
50+
`src/interface/recompute-wasm` (`vcl_recompute`) + the wire bytes of a
51+
`(Statement, OctadSchema)` + the producer's claimed level, and
52+
**re-runs the certified decision itself**, comparing its verdict to
53+
the claim. This is proof-carrying code by *recomputation*, not by
54+
transporting a proof object. The consumer's TCB is:
55+
56+
1. the once-proved corpus soundness (`checkLevelNSound`),
57+
machine-checked in the CI-gated Idris corpus and *offline*
58+
re-checkable with idris2 — never in the runtime path;
59+
2. the cross-language conformance pin that
60+
`vcltotal_parse::certified_level` is a faithful image of that
61+
corpus decision (`tests/conformance_emit.rs`
62+
`VclTotal.Interface.WireConformance`, `Refl` on shared golden
63+
bytes); and
64+
3. the wasm runtime — *not* the whole certifier, *not* a level tag
65+
taken on faith.
66+
67+
Plain `wasm32-unknown-unknown` is **sufficient and not a compromise**:
68+
nothing structured crosses the boundary that needs type-preservation
69+
(opaque wire bytes in, an `i64` out; the decoder+decider run *inside*
70+
the module), so the wasm *type system* is not load-bearing. The wasm
71+
verdict equals the conformance-pinned native verdict by construction
72+
(deterministic build of pinned, pure, total source). The path is
73+
fail-closed: any malformed input or unmet level → Reject, never a
74+
fabricated level. The only `unsafe` is one audited host/guest
75+
memory-ABI block — the declared trust boundary — with all
76+
decode/decision logic in the `#![forbid(unsafe_code)]` crate.
77+
78+
**Tier-2 — C-ABI trusted-certifier attestation (fallback, P5d, OWED).**
79+
For consumers that cannot run the Tier-1 wasm: a signed token bound to
80+
`(sha256(query), schema_id, level)`, verified against the certifier's
81+
public key. Strictly weaker (pure trust in the minting certifier), and
82+
labelled as such. The fail-closed `ffi/zig` shim (Phase 3d) is its
83+
scaffolding; the signed contract + `vclut_rs_verify` linkage are OWED.
84+
85+
## Consequences
86+
87+
- The headline "no re-checkable proof across an FFI" objection is
88+
**dissolved for Tier-1**: it was only ever true of an *untyped C
89+
ABI*, and Tier-1 sidesteps it by recomputation rather than proof
90+
transport. Recompute is, in one respect, *stronger* than proof-object
91+
PCC — the consumer need not trust a transported term's provenance;
92+
its cost is recomputation, negligible for a static AST decision.
93+
- The certifier (the Idris corpus) stays the single source of
94+
verification truth, machine-checked once; the runtime never carries
95+
a proof object.
96+
- Disclosed, precisely-scoped limits remain (NaN-payload
97+
reconstruction; cross-module `Refl` non-reduction of
98+
`find`/`elemBy`, so schema-resolution-dependent verdicts are pinned
99+
Rust-side + by input-value conformance; L9/L10 predicate depth;
100+
additive↔ceil `alignUp` sliver). These are stated in
101+
VERIFICATION-STANCE.adoc, not faked.
102+
- P5d (Tier-2) is the remaining boundary work; until it lands,
103+
non-wasm consumers receive only the fail-closed shim (no fabricated
104+
level).
105+
- Revisit only if a future revision genuinely introduces a tracked
106+
resource at this boundary (none foreseen for a pure verdict
107+
function) or if a verified embeddable dependent kernel becomes
108+
available (which would enable, but is not required for, an
109+
additional proof-object tier).

0 commit comments

Comments
 (0)