@@ -41,6 +41,32 @@ fn clearLastError() void {
4141 last_error_len = 0 ;
4242}
4343
44+ // ──────────────────────────────────────────────────────────────────────
45+ // Tier-2 backend (P5d, vcl-ut#25) — the real `vclut_rs_verify`.
46+ //
47+ // Previously NAMED OWED ("declared in intent but not linked"). Now
48+ // implemented by the Rust `vcltotal-attest` crate
49+ // (`src/interface/attest`) and linked by build.zig. It decodes the
50+ // wire `(Statement, OctadSchema)`, runs the conformance-pinned
51+ // `vcltotal_parse::certified_level` (the same faithful image of the
52+ // Idris corpus decision Tier-1 uses), and on a genuine level mints an
53+ // Ed25519 attestation bound to `(sha256(stmt_wire), sha256(schema_wire),
54+ // level)`. Fail-closed: a Reject / decode failure yields -1 and NO
55+ // token. This is the Tier-2 *fallback* (trusted-certifier attestation)
56+ // — explicitly weaker than Tier-1 recompute-PCC; see
57+ // verification/proofs/VERIFICATION-STANCE.adoc.
58+ // ──────────────────────────────────────────────────────────────────────
59+
60+ extern fn vclut_rs_verify (
61+ stmt_ptr : [* ]const u8 ,
62+ stmt_len : usize ,
63+ schema_ptr : [* ]const u8 ,
64+ schema_len : usize ,
65+ sk_ptr : [* ]const u8 ,
66+ out_ptr : [* ]u8 ,
67+ out_cap : usize ,
68+ ) callconv (.c ) i64 ;
69+
4470// ──────────────────────────────────────────────────────────────────────
4571// C-ABI exports
4672// ──────────────────────────────────────────────────────────────────────
@@ -91,6 +117,48 @@ pub export fn vclut_verify_query(
91117/// Get the last error message. Returns an empty string when no error
92118/// is pending. Caller does not own the pointer; copy before the next
93119/// FFI call.
120+ /// Tier-2 (P5d): verify a wire-marshalled `(Statement, OctadSchema)`
121+ /// and, on a genuine certified level, emit a signed attestation.
122+ ///
123+ /// `stmt`/`schema` are the v1 wire bytes (the C-ABI marshalling, same
124+ /// shape as the Tier-1 recompute module). `sk` is the certifier's
125+ /// 32-byte Ed25519 seed (real provisioning is deployment, via the
126+ /// estate token vault). On success returns the level `0..10` and
127+ /// writes a 65-byte token `[level:1][sig:64]` into `out` (needs
128+ /// `out_cap >= 65`). Returns -1 (Rejected) — writing nothing,
129+ /// `vclut_last_error` set — on any decode failure, a Reject level, a
130+ /// null pointer, or insufficient `out_cap`. **Fail-closed:** never a
131+ /// token for a level the certifier did not establish.
132+ pub export fn vclut_verify_wire (
133+ stmt_ptr : [* ]const u8 ,
134+ stmt_len : usize ,
135+ schema_ptr : [* ]const u8 ,
136+ schema_len : usize ,
137+ sk_ptr : [* ]const u8 ,
138+ out_ptr : [* ]u8 ,
139+ out_cap : usize ,
140+ ) callconv (.c ) c_int {
141+ clearLastError ();
142+ const rc = vclut_rs_verify (
143+ stmt_ptr ,
144+ stmt_len ,
145+ schema_ptr ,
146+ schema_len ,
147+ sk_ptr ,
148+ out_ptr ,
149+ out_cap ,
150+ );
151+ if (rc < 0 ) {
152+ setLastError ("Rejected (fail-closed): no genuine certified " ++
153+ "level — Tier-2 attestation NOT minted. The verification " ++
154+ "authority is the conformance-pinned certified_level; see " ++
155+ "verification/proofs/VERIFICATION-STANCE.adoc" );
156+ return -1 ;
157+ }
158+ // 0..10 fits c_int; rc is bounded by the Rust backend.
159+ return @intCast (rc );
160+ }
161+
94162pub export fn vclut_last_error () callconv (.c ) [* :0 ]const u8 {
95163 if (last_error_len == 0 ) return "" ;
96164 return @ptrCast (& last_error_buf [0 ]);
@@ -123,3 +191,21 @@ test "verify is fail-closed: no fabricated level without a backend" {
123191 // and it never returns a "verified" (>=1) level here
124192 try std .testing .expect (rc < 1 );
125193}
194+
195+ // P5d integration: the REAL Rust Tier-2 backend is linked
196+ // (libvcltotal_attest.a via build.zig). Garbage wire bytes must
197+ // decode-fail in the conformance-pinned decoder ⇒ no attestation ⇒
198+ // -1, end-to-end across the Zig↔Rust boundary. (A positive path needs
199+ // a valid wire (Statement,OctadSchema), exhaustively covered by the
200+ // Rust crate's own roundtrip/tamper suite; this asserts the
201+ // fail-closed contract through the actual linked symbol.)
202+ test "vclut_verify_wire fail-closed on garbage via the linked Rust backend" {
203+ _ = vclut_init ();
204+ var out : [65 ]u8 = [_ ]u8 {0xAA } ** 65 ;
205+ const sk = [_ ]u8 {7 } ** 32 ;
206+ const bad = [_ ]u8 {0xFF } ** 8 ;
207+ const rc = vclut_verify_wire (& bad , bad .len , & bad , bad .len , & sk , & out , out .len );
208+ try std .testing .expectEqual (@as (c_int , -1 ), rc );
209+ // out untouched on the fail-closed path
210+ for (out ) | byte | try std .testing .expectEqual (@as (u8 , 0xAA ), byte );
211+ }
0 commit comments