Live demos · no signup

Don’t take our word for it. Click it.

A running reference deployment in production mode, in two tiers. Tier 1 — bring your own EUDI wallet for the standard issue-and-present round-trip any conformant wallet can do. Tier 2 — the PSDP-protocol demos a generic wallet can’t run: an unlinkable cross-site age proof, a capped AI agent that gets denied at its limit, a real zero-knowledge over-18 proof, a passkey step-up, and a signed-credential login. Each demo says what it shows, and what it deliberately mocks.

Tier 1 · standard rails

Try it with your own EUDI wallet

The plain OID4VCI + OID4VP round-trip, by QR — any conformant EUDI wallet can do this. Issue a PID into your wallet, then present back just age_over_18 with selective disclosure. Nothing here is PSDP-specific; the interoperability is the point.

The full wallet round-trip, by QR

PSDP’s reference issuer mints a demo EU PID (SD-JWT VC) over standard OID4VCI; you scan it into a real EUDI wallet, then present it back over OID4VP disclosing only age_over_18 — no date of birth. This is the standard, interoperable flow: any conformant EUDI wallet can run it (Sphereon and Lissi complete the round-trip on this stack today).

Honest scope: this is a per-presentation check with holder key-binding — it is not the cross-relying-party-unlinkable PSDP proof. That one lives in Tier 2 below. Demo issuer, demo data — real signatures, no real-world proofing.

Tier 2 · the PSDP protocol

What a stock wallet can’t do

These run PSDP’s own circuits and protocol — they show what a generic wallet can’t. Each one is keyless, runs on this same stack under PSDP_PRODUCTION=1, and says what it shows and what is simulated.

Same you, two sites — and they still can’t link you

Enter a date of birth, then “visit” Site A and Site B. The page fires two real Groth16/BN254 proofs against POST /verify/age — same birthdate, two different relying parties. Both come back over_age: true, but the two rp_nullifier values are visibly different.

Each proof reveals only {issuer root, site-scoped nullifier, age ≥ 18} — never your date of birth — so even if Site A and Site B collude they cannot tell it’s the same person. Reference-grade: a single-party deterministic setup (not a ceremony), and in this self-contained demo the reference holder’s secret is reconstructed in-process server-side. The unlinkability property itself is modeled and machine-checked but partial overall — not “unlinkability-certified”. Two real proofs take about 10–20 seconds.

Sent once to build each witness; a production deployment proves on the holder’s device. Either way the proofs and receipts disclose only the boolean and a per-site nullifier.

Prove you’re over 18 — real zero-knowledge

Pick a date of birth and mint a real Groth16/BN254 zero-knowledge proof against POST /verify/age, right here, with no API key. The relying party learns one boolean — age_over_18 — and a per-site nullifier; the proof and receipt reveal no date of birth.

Reference-grade: the proving system uses a single-party deterministic trusted setup — not a multi-party ceremony — so it is not production-secure against a determined forger. A real proof takes about 10–15 seconds; that is the honest cost of real ZK.

In this self-contained demo the server mints the proof for the date you enter, so the date is sent to build the witness; a production deployment proves on the holder’s device. Either way the proof and receipt disclose only the boolean.

Hand an AI agent a capped wallet — watch it get denied at the cap

Issue a key-bound, attenuating delegation chain — principal → team-lead → worker — where the worker gets a tighter metered spend cap (€40) than its parent (€100). The page then runs two purchase.execute spends of €30 each against /agent/chain/demo: the first is authorized, the second is denied cap_exceeded because the running total (€60) > €40.

Real crypto: each sub-delegation is cryptographically signed by its parent (attenuating, accountable), the cap is enforced at action time (not advisory), and every attempt — allowed and denied — is recorded in an auditor-only sealed audit record. The credentials are demo-issued with ephemeral keys (reference-grade).

Step up to multi-factor — your real device passkey

Sign in at the demo OpenID provider for a password-tier credential (AAL1), then add a passkey from this device and step up to AAL2. The step-up runs a real navigator.credentials.get() assertion (ECDSA P-256) that proves possession of the passkey you just enrolled — a same-holder proof, not a matching email — and the upgraded credential is Ed25519-signed and carries a faithful assurance vector (IAL/AAL/FAL).

This uses your real device passkey — Touch ID, Windows Hello, or a security key — doing real ECDSA P-256; the same-holder proof and the upgraded credential are real. The identity provider is a clearly-labelled simulation that does no real-world identity proofing, so a passkey raises only the authenticator-assurance axis (AAL) and never unlocks identity claims. No personal data is shown. [MFA-1]

Bring your own login

Sign in at an OpenID provider and walk out with a signed PSDP credential. The page shows its work: the id_token is validated against the provider’s published JWKS, and the minted credential’s Ed25519 issuer signature is verified in front of you — the response comes back verified: true, no API key needed.

The built-in identity provider is a simulated OpenID provider served by this same app, and it does no real-world identity proofing — its RS256 signatures are real, its identities (demo-user-001) are not.

Raw endpoints

If you’d rather curl

The same stack serves machine endpoints that stay open in production. Two to start with — no key, no signup.

Payment-authorization verifier, sample run
$ curl -s https://psdp-eudi.fly.dev/verify/payment/demo
{"sample": "sepa_instant_50eur", "accepted": true,
 "errors": [], "receipt": {"authorized_payee": "MERCHANT:DE-…",
   "amount": "50.00", "currency": "EUR",
   "sca_method": ["possession", "inherence"],
   "risk_decision": "allow", …}}

Runs the payment-authorization verifier over a bundled SEPA-Instant sample credential and returns the JSON receipt. The sample is canned — verification time is pinned inside the sample’s validity window, and no money moves. It is an API response, not a page.

Issuer metadata
$ curl -s https://psdp-eudi.fly.dev/.well-known/openid-credential-issuer
{"credential_issuer": "…",
 "authorization_servers": […],
 "credential_endpoint": "…",
 "credential_configurations_supported": {…}}

The live OID4VCI issuer metadata this deployment serves to wallets — the same document a wallet fetches before asking for a credential. Nothing is mocked: it is the real metadata document this deployment serves (the issuer identity is a demo one).

What you’re looking at

Reference deployment — what runs, and what’s simulated

Every demo on this page runs on this same host, against the same reference stack that produces the numbers on the rest of this site — there is no separate demo environment.

PSDP is a reference implementation; production hardening is in progress. These demos exist so you can check our claims, not so we can make new ones. Where a path uses demo crypto or a demo issuer, the response says so explicitly. In production mode (PSDP_PRODUCTION=1) the verifier refuses mock proofs — submissions are rejected with mock_crypto_rejected_in_production — and startup checks enforce production configuration before serving. The Tier 2 demos are exactly the ones that pass end to end under that flag: a real (reference-grade) zero-knowledge age proof and its cross-site unlinkable variant, a key-bound metered-cap agent delegation, a real passkey step-up, and a real signed-credential login.

The numbers behind this stack — conformance runs, wallet interop, the theorem map — live on the evidence page, each with its source artifact.

Seen enough to have questions?

Bring what you saw to a 30-minute gap scan — engineering to engineering, no deck.

Talk to us →