Skip to content

feat(parser_http_server): real bootProof from NSM - #452

Draft
pepe-anchor wants to merge 1 commit into
pepefigueira/prs-581-05-xstamp-authfrom
pepefigueira/prs-581-06-boot-proof
Draft

feat(parser_http_server): real bootProof from NSM#452
pepe-anchor wants to merge 1 commit into
pepefigueira/prs-581-05-xstamp-authfrom
pepefigueira/prs-581-06-boot-proof

Conversation

@pepe-anchor

Copy link
Copy Markdown
Contributor

Why

Turnkey's gateway attaches bootProof to every response today. Once the pivot is the front door it has to produce that itself, or every attestation-verifying consumer breaks. The x402 branch's HTTP envelope has no bootProof field at all, so this is the piece that closes the wallet contract on the new path.

What

Reproduces qos_core's post-boot attestation call directly against /dev/nsm: manifest hash in user_data, ephemeral pubkey in public_key, nonce: None. Same shape as qos_core/src/protocol/services/attestation.rs, which is what production serves today.

  • NsmBootProof implementing the BootProofSource trait from feat(parser_http_server): HTTP+JSON pivot for TVC public ingress #450, with a with_attestor seam so the behavior is testable without an enclave.
  • The document is generated once at startup and reused. nonce: None means it is not request-bound, and our reference verifier does not check its timestamp (visualsign-turnkeyclient cmd/verify.go sets SkipTimestampCheck: true), so there is no freshness window to satisfy. No TTL, no refresh.
  • --boot-proof-source <static|nsm> / BOOT_PROOF_SOURCE, defaulting to static, so local dev and CI are untouched and NsmBootProof::new failing outside an enclave cannot break the default path.

The manifest fields are borsh, not the JSON at /qos.manifest. The Go verifier borsh-deserializes both and compares sha256(borsh(manifest)) against the doc's user_data, so base64-ing the file bytes would produce fields nothing can verify.

Test evidence

cargo test -p parser_http_server -> 3 passed
  nsm_boot_proof_generates_once_and_reuses_the_document  (asserts exactly one attestor call)
cargo test -p integration --test http_server -> 1 passed
cargo build -p parser_http_server --features vsock -> compiles
make -C src test / fmt / lint -> clean

qos_core's mock feature is enabled only under [dev-dependencies] (needed for ManifestEnvelope::default() in the test fixture). Verified with cargo tree that resolver 3 keeps it out of the normal build: a non-test build resolves qos_core with vm only, and mock,vm appears exclusively in test builds. Upstream labels that feature "never use in production", so this was worth checking rather than assuming.

DO NOT MERGE until the NSM reachability probe passes

This implements option A: the pivot calls /dev/nsm itself. Whether a pivot process can reach that device under TVC, and whether concurrent use alongside qos_core is safe, has not been verified against a real deployment. Nsm does nsm_init/nsm_exit per call so it is probably fine, but it needs a real observation.

If the probe fails, this approach is replaced by option B: ask Turnkey to expose the attestation doc to the pivot (a unix socket route or a file written post-boot), which is an upstream QOS change and should ride with the QOS bump.

Two acceptance criteria also remain outstanding because they need a live enclave, not a mock:

  • boot-proof latency delta measured and recorded (expected to be zero per request given startup generation, but the number should be taken rather than assumed)
  • visualsign-turnkeyclient verify passing against a real Nitro doc, including "Raw manifest hash matches UserData in attestation". If that hash mismatches, the V1/V2 manifest layout is wrong for this QOS rev.

Rollback

Revert the commit, or leave --boot-proof-source at its static default: the NSM path is opt-in and unused unless explicitly selected.

Linear

PRS-581

Stacked on #450. #337.

🤖 Generated with Claude Code

Turnkey's gateway attaches bootProof today; the pivot has to produce it
once it is the front door, or every attestation-verifying consumer breaks.

Reproduces qos_core's post-boot attestation call directly against
/dev/nsm: manifest hash in user_data, ephemeral pubkey in public_key,
nonce None. Generated once at startup, because nonce: None means the doc
is not request-bound and our reference verifier does not check its
timestamp.

The manifest fields are borsh, not the JSON sitting at /qos.manifest. The
Go verifier borsh-deserializes both and compares sha256(borsh(manifest))
against user_data, so base64-ing the file bytes would produce a field
nothing can verify.

Co-Authored-By: Claude <noreply@anthropic.com>
@pepe-anchor
pepe-anchor force-pushed the pepefigueira/prs-581-06-boot-proof branch from 14c12e9 to b201bb1 Compare August 6, 2026 17:12
@pepe-anchor
pepe-anchor changed the base branch from pepefigueira/prs-581-03-pivot-v1 to pepefigueira/prs-581-05-xstamp-auth August 6, 2026 17:12
@pepe-anchor pepe-anchor added the CI label Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant