nSealr Vault — ESP32 edition
Air-gapped ESP32-P4 camera + display signer. Behavior parity with the Pi QR vault is enforced through shared contract_ids in nSealr/specs.
Hardware target
- Board: Waveshare ESP32-P4-WIFI6-Touch-LCD-3.5 — OV5647 camera, ST7796 320×480 display, FT6336 capacitive touch.
- The onboard ESP32-C6 radio is disabled to preserve the air-gap; every request and response moves over QR, no wireless, no host link.
libwally/Kern-aligned host core with RAM-only key custody.- Production-readiness gates: real OV5647 camera ingestion, display acceptance, button/touch drivers, provisioning.
Secret lifecycle
Secret material lives in RAM only for the current signing session; nothing is persisted, so there is no device PIN. Session sources can be:
- Imported by scanning a SeedSigner-interoperable Standard SeedQR or CompactSeedQR, or a canonical NIP-19
nsec, after a secret-hidden source review. - Generated on device — BIP-39 words with optional extra entropy from dice rolls or a camera snap (the P4 board has an OV5647 camera), behind a one-time local backup/export ceremony before use.
Both SeedQR directions are supported: the vault can display back a Standard SeedQR or CompactSeedQR for interoperable backup, not only scan one in. An optional BIP-39 passphrase is supported for NIP-06 derivation. This matches the Pi edition vault lifecycle.
Current status
Real sign_event is signing_disabled in development firmware until all hardening, display, button, and provisioning gates pass. The T-Display S3 review scenario smoke — host-core review-rendering evidence from an earlier development board, retained through the ESP32-P4 retarget — confirms review frames render correctly; this is development evidence, not a production trusted-display claim. Approvals are bound to approval_digest. The firmware protocol evidence and Unicode fallback tracking are recorded in nSealr/esp32.
| Feature | Target | Current | Contract |
|---|---|---|---|
request_validation_v0 | required | implemented | signing-request-v0+implementation-limits-v0+invalid-vectors |
nostr_event_review_universal | required | implemented | trusted-review-v0+review-detail-pages-v0 |
review_detail_pages | required | implemented | review-detail-pages-v0 |
approval_digest_binding | required | implemented | approval-digest-v0 |
physical_approval | required | partial | physical-approval-v0 |
sign_event_bip340 | required | disabled_until_gates_pass | nostr-sign-event-bip340-v0 |
qr_static_request | required | partial | qr-envelope-static-v0 |
qr_animated_request | required | partial | qr-envelope-animated-v0 |
qr_response | required | planned | qr-response-v0 |
stateless_session_custody | required | planned | stateless-session-custody-v0 |
manual_only_policy | required | implemented | manual-only-approval-policy-v0 |
device_display_review | required | partial | device-display-review-v0 |
response_verification | required | planned | signed-response-verification-v0 |
secure_boot_hardening | optional | planned | firmware-boot-hardening-v0 |