About Compass
Bounded disclosure, on the wire.
Compass is a private eligibility firewall on 0G. Clinics extend service. Subpoenas reach bucketed timestamps and cryptographic commitments. No name, HKID, employer, or document fields.
Architecture
0G integration
| Component | 0G layer | Role |
|---|---|---|
| Agent ID | 0G Chain (AgentRegistry) | Soulbound INFT bound to the user's EOA; Privy embedded wallet wires the EOA when NEXT_PUBLIC_PRIVY_APP_ID is set, fixture mode otherwise |
| Encrypted vault | 0G Storage | AES-256-GCM ciphertext of SD-JWT VC bundle; root hash on-chain |
| Sealed inference | 0G TeeML / Phala dstack TDX | Receives selectively-disclosed claims; evaluates policy; signs receipt with sealed key |
| Receipt log | 0G Chain (CompassHub) | ReceiptIssued: receiptId, policyId, nullifier, agentIdCommitment, resultHash, attestationDigest, expiry, 15-min timestamp bucket — no name, HKID, employer, or document fields |
How Compass differs from adjacent projects
| Project | What it proves | Where Compass differs |
|---|---|---|
| Worldcoin / World ID | Proof of personhood via iris scan; one-human-one-vote primitive. | Compass proves eligibility for a specific service, not personhood. We don't take biometrics; the worker's claims live in an SD-JWT VC she controls, encrypted with a key only she holds. |
| Polygon ID | ZK-proof-based verifiable credentials; selective disclosure of issuer-signed claims. | Compass v1 uses SD-JWT + sealed TEE inference instead of in-browser ZK proofs — sub-second receipt mint vs ~5-30s ZK proving. The v2 dual-path roadmap adds an optional ZK route for higher-threat contexts; see docs/zk-future-work.md. |
| Anon Aadhaar | ZK proofs over India's Aadhaar ID; prove residency / age without revealing the Aadhaar number. | Compass is not tied to a specific issuer-of-record. Any NGO with an Ed25519 key can issue a credential that Compass verifies; the trust list is governed separately. The migrant-worker context typically has no trusted government issuer; NGO-issued credentials are the only available path. |
| zkPass | Web2 data → ZK proofs; prove claims about your bank account, social profile, etc. without revealing the underlying account. | Compass operates on NGO-issued attestations of physical-world status (visa, employment, residency), not Web2 scraped data. The threat model — subpoena resistance for already-issued credentials — is different from "import my Web2 attribute privately." |
| Privacy Pools / Tornado Cash v2 | Anonymous transactions with optional inclusion proofs into a set of "honest" deposits. | Compass is not a transaction-privacy primitive — it's a credential-privacy primitive. The on-chain receipt is the audit trail the system wants; the privacy property is on the inputs the receipt commits to, not on hiding the receipt itself. |
We respect every project in this table — most of Compass' primitives were inspired by their work. The differentiation is in the migrant-worker threat model: asynchronous subpoena resistance for NGO-issued service eligibility, optimised for interactive intake at clinic kiosks.
Standards alignment
Compass' selective-disclosure path uses SD-JWT VC (draft-ietf-oauth-sd-jwt-vc, advanced to -16 in April 2026; Compass v0.5 pins -15 for the hackathon cycle with a v0.6 roll-forward planned). This is the same wire format the EU Digital Identity Wallet (eIDAS 2.0, in effect 2025) standardised for member-state digital credentials. The underlying SD-JWT selective-disclosure primitive shipped as RFC 9601 in December 2024.
What this buys us: a Compass-issued credential can be presented to any verifier built against the EUDIW reference stack, and conversely an NGO running Compass alongside an eIDAS-compliant wallet can interoperate without re-issuance. The honest caveat: until the IETF draft hits RFC, every implementation is tracking a moving target — Compass tracks it openly in docs/honest-limits.md §6.
What's real / what's mocked
| Component | Status | Note |
|---|---|---|
| AgentRegistry contract | real | ERC-7857 stripped; deployed to both 0G Galileo testnet (0x461e…c2D8) and 0G Aristotle mainnet (0xf1FA…0Bf9, 2026-05-11) |
| CompassHub contract | real | policies + Authwit + receipts; deployed to both 0G Galileo testnet (0x60Bb…7c3b) and 0G Aristotle mainnet (0xe42f…C58b, 2026-05-11) |
| Browser AES-256-GCM encryption | real | live on /onboard step 3 — non-extractable AES-256 in IndexedDB encrypts the issued SD-JWT VC before localStorage persist; plaintext never enters localStorage |
| 0G Storage ciphertext upload | draft | AES-256-GCM round-trip on Node CLI; live 0G upload behind COMPASS_LIVE_STORAGE=1; browser-side upload is v2 |
| Receipt-signer service | real | dstack TDX dual-boot; per-receipt quote freshness binding |
| Phala Cloud TDX deploy | real | live: ethAddress 0xaba6...a7e7, composeHash 0x1884...cea0 — see docs/notes/phala-deployment.md |
| SD-JWT VC issuers (HELP, Bethune, Hospital) | mocked | real NGOs; signing keys are local Ed25519 fixtures, not endorsed by the NGOs |
| SD-JWT VC live issuer service | draft | POST /api/issue signs Ed25519 SD-JWT VC when ISSUER_PRIVATE_KEY env set; rendered in /vault from localStorage. v2 adds browser AES-256-GCM + 0G Storage upload |
| Trust list governance | draft | v1 owner-managed via docs/policies/*.json; v2 DAO design specced at docs/trust-list-governance.md (5-of-7 quorum for adds, 3-of-7 for revokes, 7-day timelock with 24h revoke expedite, on-chain TrustList contract on Aristotle) |
| On-chain verifyAttestation | stubbed | real RA quote verification is gas-prohibitive on-chain (cert chain + ECDSA + 4KB quote); off-chain verifier in enclave/src/verify-attestation.ts + verify-receipt CLI does the heavy lift |
| RA-quote-bound attestationDigest in receipts | real | /api/consume calls live Phala TDX enclave (composeHash 0x1884…cea0, signer 0xaba6…a7e7); attestationDigest is sha256 of canonicalized receipt + per-receipt TDX quote whose report_data binds (signer, image, receiptId). Live state surfaced at /api/tee-status; falls back to stub digest if the enclave is stopped between demo cycles |
| 0G broker processResponse co-signature | draft | out of scope for v1; receipt has its own signature chain |
| Privy embedded wallet | draft | wired in /onboard step 1; live behind NEXT_PUBLIC_PRIVY_APP_ID, fixture timer in default build |
| /onboard step 2 — live mintAgent | draft | Privy embedded wallet → AgentRegistry.mintAgent on Galileo (chainId 16602), gated on user-funded gas; fixture timer when Privy is unset |
| Authwit grant — browser-side EIP-712 signing | real | Privy embedded wallet signs the Compass Grant typed data on /onboard step 4 (Galileo chainId 16602, CompassHub verifying contract), no popup-required sub-flow |
| CompassHub.consumeGrantAndIssueReceipt — atomic on-chain | real | POST /api/consume relays Maria's signed grant; PROVIDER_PRIVATE_KEY-held wallet calls Galileo CompassHub; emits GrantConsumed + ReceiptIssued in one tx; nullifier + receiptId stored as used |
| Aristotle mainnet (chainId 16661) deploy | real | deployed 2026-05-11 — AgentRegistry 0xf1FA…0Bf9, CompassHub 0xe42f…C58b. All 3 demo policies registered on-chain (HELP, Bethune, Hospital); provider relayer 0xaD7…b0a funded 0.05 OG. Funding path: MoonPay → ETH on Ethereum L1 → hub.0g.ai TokenFlight Cross-Chain Swap (Hyperstream/Khalani) → native OG on Aristotle. /api/consume reads NEXT_PUBLIC_COMPASS_USE_MAINNET=1 and routes the relayer to Aristotle; unset routes it to Galileo. |
| Kiosk mode for NGO drop-in centres | draft | live at /kiosk — locked nav, 4-step welcome→sign-in→mint→credential→request-eligibility flow with large touch targets + plain-language labels + receipt-as-intake-artifact ending. Reuses Privy + on-chain primitives from /onboard, restyled for shared tablet use. v2 adds auto-reset timer + audio cues for low-literacy assistance |
| Kiosk localization (5 languages) | draft | live at /kiosk welcome screen — language picker for English, Filipino (Tagalog), Bahasa Indonesia, Bahasa Malaysia, 廣東話 (Cantonese). All non-English strings are AI-generated baseline pending native-speaker review (gated on C.4 outreach replies). String table at app/src/lib/i18n/kiosk-strings.ts; current scope is kiosk-only — the rest of the app stays English. Honest-limits disclosure in the file header |
| Spline 3D scene on /about | real | activated 2026-05-10. @splinetool/react-spline + @splinetool/runtime installed; <SplineScene /> renders below the architecture diagram when NEXT_PUBLIC_COMPASS_SPLINE_SCENE_URL is set. Lazy-imported behind Suspense so the runtime (~530KB) loads off the critical path. Falls back to null when env var is unset, so the route stays unchanged on a clean clone with no env file. R13 LCP guard still in force: if Lighthouse mobile drops below 85, swap to environmental SVG. |
| HLS / MP4 hero video background on / | draft | scaffolded at app/src/components/primitives/VideoBackground.tsx; renders null until NEXT_PUBLIC_COMPASS_HERO_VIDEO_URL env var points at an HLS playlist (.m3u8) or MP4 URL. Default hero uses AmbientSphere SVG. Asset prep + Pexels sourcing + ffmpeg recipe documented in docs/notes/hero-video-sourcing.md. R16 LCP guard: Lighthouse mobile floor 85; rollback is unsetting the env var |
| 3D force-graph view of public audit log | real | live at /audit-graph.html — standalone HTML using 3d-force-graph CDN; bucket-clustered receipt nodes with no inter-receipt edges (cannot suggest correlation between disclosures). Gentle camera orbit + per-policy color. v2 swaps the fixture node list for live Galileo ReceiptIssued event queries |
Cryptographic chain
- 01
SD-JWT VC encrypted in the browser
Per-device AES-256-GCM key generated in WebCrypto with extractable=false, persisted as an opaque CryptoKey handle in IndexedDB; only ciphertext + IV land in localStorage. 0G Storage upload (Merkle-root committed to AgentRegistry.encryptedURI) is on the v0.6 roadmap.
- 02
Receipt-signer derives sealed key inside TDX
dstack.getKey('compass-receipt-signer') returns a deterministic secp256k1 priv sealed to the attested image; composeHash is the externally-verifiable binding.
- 03
Per-receipt quote binds (signer, image, receiptId)
report_data = sha256(ethAddress || composeHash || receiptId). Defeats archived-quote replay across deployments.
- 04
Receipt signed with sealed key, digest covers quoteCommitment
secp256k1 lowS over canonicalized receipt; verifier recovers signer, matches against quote, validates the chain.
- 05
ReceiptIssued event on 0G Chain
receiptId, policyId, nullifier, agentIdCommitment, resultHash, attestationDigest, expiry, 15-min timestampBucket. No name, HKID, employer, or document fields.
Honest limits
Compass narrows disclosure but does not eliminate it. Coercion, deniable encryption, full k-anonymity against statistical re-identification, and SD-JWT VC draft churn all remain open issues. See docs/honest-limits.md for the full list.
Credits
Persona narrative inspired by the work of Mission for Migrant Workers, HELP for Domestic Workers, and Bethune House Migrant Women's Refuge in Hong Kong. Compass does not represent any real worker; the demo flow is a composite. Built solo by Stephen Sookra for the 0G APAC Hackathon (Track 5).