<!-- SPDX-License-Identifier: Apache-2.0 -->
# PSDP Website Claims Ledger

**Status:** authoritative · built 2026-06-12 · branch `feat/marketing-site`
**Rule:** every factual claim on any page of this site MUST be one of the allowed
phrasings below (verbatim or a strict weakening — never a strengthening). Numbers,
dates and qualifiers are load-bearing. Adversarial reviewers enforce by diff against
this file. If a claim you want is not here, it does not go on the site.

Seeded from `docs/PQ_ZK_STATUS.md` (the DO-NOT-CLAIM register — its prohibitions are
absolute) and verified read-only against the artifacts in the main tree at
`/home/kaali/crazy idea/` (gitignored/untracked there; paths below are relative to
that tree unless absolute).

---

## 1. Allowed claims

### OIDF conformance

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| OIDF-1 | "Tested against the official OpenID Foundation conformance suite (local run, reproducible): **319 of 332 test modules passed, 0 failed** (11 warnings, 2 skipped), across OID4VCI, OID4VP and OpenID Federation test plans. Self-run evidence — **not** an OpenID Foundation certification." | `tier3_results/oidf_conformance/SCORECARD.json` (run `local_oidf_20260601_164224_subprojectA_STRICT`); independently reproduced by `tier3_results/local_oidf_freshrun_20260604_161726_full/summary.json` | Parsed both JSONs: total_modules 332, passed 319, failed 0, warning 11, other/skipped 2 in BOTH the 2026-06-01 and 2026-06-04 runs. Plan breakdown: OID4VCI issuer 112 + issuer-HAIP 126, OID4VP verifier/wallet (1final + id3 + HAIP) 89, OpenID Federation deployed-entity 5/5. |
| OIDF-2 | "The **FAPI 2.0 Security Profile (Final)** test modules embedded in the OID4VCI issuer plans: **78 of 80 passed, 0 failed** (2 warnings) — local run of the official OIDF suite." | `tier3_results/local_oidf_20260526_122209_mdoc_keyatt/summary.json`; re-confirmed in `tier3_results/local_oidf_freshrun_20260604_161726_full/summary.json` | Tallied modules whose names match `fapi2-security-profile-final-*`: 2026-05-26 run = 80 modules, 78 PASSED (76 FINISHED + 2 MANUAL_REVIEW_OK), 2 WARNING, 0 FAILED; 2026-06-04 run = identical 78/2/0. |
| OIDF-3 | "An earlier full-suite baseline (2026-05-26): **210 of 218 modules passed, 0 failed** (7 warnings, 1 skipped)." | `tier3_results/local_oidf_20260526_122209_mdoc_keyatt/summary.json` | Tallied all modules: 218 total; 210 PASSED (201 FINISHED + 9 MANUAL_REVIEW_OK), 7 WARNING, 1 SKIPPED, 0 FAILED. |
| OIDF-4 | "Every conformance result bundle is signed by the suite's own key and archived; runs are reproducible. We are **not** listed on openid.net/certification." | `conformance_results/test-log-*.zip` (signed suite exports); `tier3_results/oidf_conformance/SCORECARD.json` | Signed test-log zips exist on disk. No published-certification artifact exists anywhere; the suite-internal `"certified": 330` JSON field is a suite status counter, NOT a certification (see Rejected R-3). |

### Wallet interoperability

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| WAL-1 | "**22 credential types, in 43 issuer configurations** (SD-JWT VC and ISO mdoc formats), each issued **and stored** end-to-end against the walt.id wallet stack over live OID4VCI." | `auto_research/scripts/wallet_baselines.json` (`wallets.walt_id.flow_status.oid4vci.per_doctype`); per-doctype `evidence_dir` pointers into `tier3_results/`; run reports in `auto_research/reports/wallet_wire/2026-05-2*/` | Parsed baseline: 43 per-doctype entries, **all 43** status `live_wire_pass_with_storage`; 22 distinct credential-type bases (PID, mDL, EHIC, diploma, civil-status ×3, vaccination, tax, payment, etc.). Do NOT say "23 types" (see Rejected R-5). |
| WAL-2 | "Austria's **vck** library (A-SIT / the engine behind the ID-Austria Valera wallet) **presented an SD-JWT PID to the PSDP verifier over OID4VP 1.0 Final** (direct_post + DCQL); PSDP verified the issuer signature and the Key-Binding JWT and accepted (2026-06-08, reproducible harness)." | `scripts/vck-vp-holder/README.md` (run transcript + rerun instructions); harness source in `scripts/vck-vp-holder/src/` | README records the full 4-leg flow with HTTP 200 trail and `RESULT: PASS … (KB-JWT verified)`; harness is rerunnable. Scope limits MUST hold: it was the vck **library**, not the Valera app binary; dc+sd-jwt only, not JARM/mso_mdoc. |
| WAL-3 | "Tested against **real Android wallet apps on physical devices** (Paradym, Sphereon, EUDI reference, Procivis), with captured device logs (adb/logcat) against live PSDP endpoints." | `tier3_results/android_config_sweep_*` (paradym/sphereon/eudi_ref/procivis dirs with logcat captures); `tier3_results/wallet_run_analysis_2026042*_paradym_*.json` (okhttp/4.12.0 device traffic + ReactNativeJS logcat) | Run-analysis JSONs show real-device user agents and captured logcat from `id.paradym.wallet` resolving PSDP deep links over a live tunnel. Do NOT claim a completed end-to-end real-phone flow (see Rejected R-6). |
| WAL-4 | "PSDP's live issuer has served **complete OID4VCI issuance flows** (metadata → offer → token → credential, all HTTP 200) to wallet clients identifying as Paradym/Credo, Sphereon and Lissi (logged 2026-06-04)." | `tier3_results/wallet_attempts/attempts.jsonl` | Parsed JSONL for 2026-06-04: full 200-status chains for UAs `Paradym/1.0`, `Credo TS / Paradym (OpenWallet Foundation Labs)`, `Sphereon Wallet`, `Sphereon/1.0`, `Lissi/2.0`. Phrasing "identifying as" is mandatory — the log records user agents, not proof of the physical app. |
| WALLET-1 | "Try it with your own EUDI wallet runs the **standard OID4VCI issuance + OID4VP presentation flow (selective disclosure)**, by QR: the live PSDP **demo issuer** mints an EU PID (SD-JWT VC, demo data) over OID4VCI, and the verifier checks the **issuer signature** and the wallet's **Key-Binding JWT** and accepts a presentation that discloses **only `age_over_18`** — no date of birth. This is a **per-presentation check with holder key-binding, NOT the cross-relying-party-unlinkable PSDP proof.** Issuance has completed end to end (metadata → offer → token → credential, all HTTP 200) for clients identifying as **Sphereon** and **Lissi**, and an SD-JWT PID presentation has been verified from the **vck** library. **Paradym** and the stock **EUDI Reference Wallet** currently reject PSDP demo credentials at the **trust-anchor step (our demo issuer certificate is not in their built-in trust list)** — not a flaw in the proof." | live keyless routes `POST /api/v1/oid4vci/offer` (returns `openid-credential-offer://?credential_offer_uri=…`), `POST /api/v1/oid4vp/initiate?credential_format=dc+sd-jwt&response_mode=direct_post&claims_override=age_over_18` (returns `openid4vp://…` + `state`), `GET /api/v1/oid4vp/result/{state}` (the SD-JWT verify path in `demo/api.py` returns `status:"accepted"` only after issuer-sig + KB-JWT verification); evidence reuses WAL-1 (issued+stored vs walt.id), WAL-2 (vck presented + verified), WAL-3 (real Android apps incl. EUDI-ref/Paradym), WAL-4 (Sphereon/Lissi-identifying full OID4VCI); EUDI-ref trust-list dependency is coded in `demo/api.py` (`_EUDI_REF_FAMILY` warning, ~L1674) | Ran all three routes live with `PSDP_PRODUCTION=1` (port 8120, no `X-API-Key`): offer returned a real `openid-credential-offer://` URL that rebases to the public host under `X-Forwarded-Host`; initiate returned a real `openid4vp://` request with `claims_override:["age_over_18"]` + `state`; result returned `202 {"status":"pending"}`. The qualifiers are mandatory and carry the existing WAL-* limits: "identifying as" (UA strings, not the physical app, per WAL-4/R-6), the vck **library** not the Valera binary (WAL-2/R-7), and per-presentation ≠ unlinkable (FV-3). Ceiling = SEC-3; never pair with any post-quantum claim (the ZK/unlinkable path is separate, AGE-ZK-1/FV-3). |

### Formal verification

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| FV-1 | "**33 protocol theorems tracked: 15 discharged (machine-checked), 18 partial.** We publish the split — partial means exactly that." | `auto_research/knowledge/theorem_map.json` (generated 2026-05-29) | Counted `health` field across all 33 entries: `discharged` = 15, `partial` = 18, unverified = 0. |
| FV-2 | "Protocol model machine-checked in the **Tamarin prover** (Dolev-Yao adversary): **36 lemmas verified — 32 trace properties + 4 observational-equivalence proofs** (≈5,500 proof steps), across 7 theory files." | `conformance_results/EVIDENCE_PACKAGE.json` (`formal_verification` block); `.spthy` sources in `conformance_results/*.spthy` | Read JSON: tool "Tamarin Prover 1.12.0", total_verified 36 (32 trace + 4 equivalence), total_proof_steps 5517, 7 theories; the 7 `.spthy` files exist beside it. |
| FV-3 | "**Designed and machine-checked for unlinkability properties:** identifier-hiding (T10a), audit/verifier-split (T10d) and nullifier-unlinkability / private-presentation theorems are **discharged**; verifier-view unlinkability, issuer hiding and selective-disclosure privacy are modeled with machine-verified observational-equivalence lemmas but remain **partial** overall." | `auto_research/knowledge/theorem_map.json` (entries `theorem10a`, `theorem10d`, `private_presentation`, `theorem10`, `issuer_hiding`, `selective_disclosure_privacy`) | Per-entry check: theorem10a/theorem10d/private_presentation `health=discharged` (private_presentation: 10/10 lemmas verified); theorem10, issuer_hiding, selective_disclosure_privacy have all Tamarin lemmas `verified` but `health=partial`. NEVER "unlinkability-certified". |
| FV-4 | "Reference ZK circuits additionally checked with **Picus (Veridise, Z3)** — 'properly constrained' — and **Circomspect (Trail of Bits)** — 'no issues found' — plus 14/14 negative-witness tests (circom reference circuits, April 2026 evidence package)." | `conformance_results/EVIDENCE_PACKAGE.json` (`circuit_formal_verification` block) | Read JSON verbatim. Scope qualifier "(circom reference circuits)" is mandatory — the live verify path is the arkworks Groth16 backend, not these circom artifacts. |

### Post-quantum cryptography (limitation statement is MANDATORY wherever PQC appears)

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| PQ-1 | "**PQC-hybrid authentication (ML-DSA-65) + confidentiality (ML-KEM-768). The zero-knowledge layer is classical Groth16/BN254**, with a de-risked (not yet live, not yet formally sound) transparent PQ-STARK backend on the roadmap." | `docs/PQ_ZK_STATUS.md` §2, §6 ("the ONLY truthful posture") | This is the register's own ceiling sentence, quoted. Anything stronger is an overclaim. The second sentence may not be dropped when the first is used. |
| PQ-2 | "Hybrid post-quantum key establishment (**X25519 + ML-KEM-768**) and hybrid issuer signatures (**ES256/EdDSA + ML-DSA-65, FIPS 204**) are implemented in the reference stack." | `src/psdp_ref/pqc_credentials.py` (e.g. `"hybrid_id": "mlkem768-x25519-hybrid"`, `"kem_scheme": "X25519 + ML-KEM-768"`); `src/psdp_ref/issuer_signatures.py`; `docs/PQ_ZK_STATUS.md` §2 | Grepped worktree code: hybrid KEM and ML-DSA-65 identifiers present in live modules; PQ_ZK_STATUS independently confirms both layers as "real, hybrid". Must appear together with the PQ-1 ZK limitation. |
| PQ-3 | "A transparent **PQ-STARK proving spike** (hash-based, no trusted setup) is de-risked: fused proof ≈73 KB, prove time ≈16 s on 2016 laptop hardware — **not live, not formally sound, not production-ready**; the shipping ZK backend remains Groth16/BN254." | `docs/PQ_ZK_STATUS.md` §3–4 | Numbers and the triple negative are quoted from the register's "best-branch maturity" section. The three "not"s are mandatory. Never quote sub-KB "PQ" proof sizes (§5). |

### Security posture

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| SEC-1 | "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." | `src/psdp_ref/age_verification.py` (allow_mock_crypto default = `not _is_production()`, lines ~171–211); `src/psdp_ref/startup_checks.py` (PSDP_PRODUCTION gates, lines ~182–236) | Read code in this worktree (master `fe33296` lineage): default mock acceptance is inverted by the production flag; startup_checks hard-enforces at boot. |
| SEC-2 | "**Real Groth16/BN254 verification is exercised in CI:** a blocking job builds the Rust provers and runs the suite with `PSDP_REQUIRE_ZK=1`, so a missing prover is a hard failure, not a silent skip." | `.github/workflows/ci.yml` (`zk-research` job); `tests/test_zk_prover_integrity.py`; `scripts/check_zk_prover_integrity.py` | Read the workflow: builds `prover/arkworks` + `prover/bbs` with `--locked`, runs integrity check `--require` and the research suites under `PSDP_REQUIRE_ZK=1`. |
| SEC-3 | "PSDP is a **reference implementation; production hardening is in progress.**" (This is the CEILING — no stronger readiness wording anywhere.) | 2026-06-09 production-readiness audit (`~/.psdp_research/PRODUCTION_READINESS_AUDIT_2026-06-09.md`) + remediation re-verified 2026-06-12 | Audit scored master 27/100 with remediation since landed (mock-crypto, admin/SSRF, CI-real-ZK fixed; revocation partial; license + ephemeral keys open). "Production-ready" is therefore false; this sentence is the honest maximum. |
| SEC-4 | "Production-mode issuer trust is **fail-closed** (real Ed25519 issuer-signature verification, expiry, registry/revocation status — any failure rejects) and one-time-use nullifiers persist across restarts via a file-backed replay guard." | `src/psdp_ref/production.py` (require_trusted_issuer, ProductionNullifierLedger) | Read module: docstring + code implement exactly this, scoped to the production layer. Do NOT generalize to "fail-closed by default everywhere" — e.g. `require_active_status` still defaults False in demo policies (Rejected R-8). |
| LIC-1 | "**Open-core**: most of the project is **Apache-2.0** (open source) — protocol, PKI, verifier, trust-lists, BBS+, and prior-art crypto; a focused **16-file moat** (the ZK proving + optimized verify engine, the unlinkable-presentation assembly, the PQ-STARK W-OTS+ AIR, and the packaged product modules) is **Business Source License 1.1** (source-available, **not** open source; converts to Apache-2.0 on the Change Date)." | `.moat-manifest` (the 16 BUSL files); `LICENSE-BSL` (a **valid** BUSL-1.1 with a named interim Licensor); example BUSL header `src/psdp_ref/unlinkable_presentation.py`; example Apache header `src/psdp_ref/nullifier.py`; `LICENSING.md` (tier index); `LICENSE` (overview). | Read the SPDX headers + `.moat-manifest` (16/16 BUSL, SPDX guard clean). `LICENSE-BSL` is finalized (canonical BSL 1.1 body; Licensor = a named natural person on an **interim** basis, to be assigned to the EU legal entity on formation; counsel review recommended before a commercial-license sale). The 16 moat files are NOT open source; the remainder IS Apache-2.0. Blanket "fully open source" is inaccurate (R-9); the correct framing is open-core. |

### Age verification (real zero-knowledge)

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| AGE-ZK-1 | "The public `POST /verify/age` endpoint mints and verifies a **real Groth16/BN254 zero-knowledge proof** end to end: the holder proves `age_over_18` (and a per-relying-party scoped nullifier) in zero knowledge against a **trusted issuer accumulator** (a fixed shared set of **K = 6,000,000** members, folded into a depth-23 Poseidon-Merkle root, capacity 8,388,608), **revealing no date of birth** — the holder's secret is **CSPRNG-random, not derived from the birthdate**, so the DOB is **not recoverable** from the public transcript or the published root. It is **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, and an **over-18 proof is unlinkable among ~4,920,000 adults** (the over-18 members — 82 ages × 60,000 — of that 6,000,000-member set), a reference scale, **not internet-scale**. A real proof takes **about 10–15 seconds** — the honest cost of real ZK." | `src/psdp_ref/age_verification.py` (`make_demo_age_presentation` mints a real `psdp-arkworks-present` Groth16 transcript; `_verify_real_age_presentation` verifies fail-closed — pins the trusted issuer accumulator root, the canonical verifying key, and the requested `min_age`); `src/psdp_ref/age_issuer.py` (`K_ANONYMITY = 6,000,000`, generate-and-cache: the members are folded into the depth-23 root IN-PROVER and never materialized in Python; `generate_holder_secret` = CSPRNG, NOT `SHA-256(born)`; one published `trusted_age_root` shared by every holder); the per-call re-randomized proof seed in `src/psdp_ref/unlinkable_presentation.py`; `tests/test_age_real_zk.py` (acceptance matrix), `tests/test_unlinkability_fixed.py` (DOB-not-recoverable, asserts a K-anonymity floor), `tests/test_anonymity_10k.py` (asserts the published root commits to a 6M-member / depth-23 tree and a real proof verifies) | Read code in this worktree (the issuer is a shared **K = 6,000,000** accumulator with CSPRNG-seeded member secrets — fix commit `72d53ec` removed the old `root = f(born)` DOB leak, and the set was scaled up to 6,000,000 via a depth-23 generate-and-cache fold, with the members generated + folded in-prover and never materialized in Python): the real-ZK path routes on `_ZK_PRESENTATION_KEY`, runs the Groth16 prover, and rejects mock proofs in production. `test_age_real_zk.py` asserts an over-18 adult ACCEPTS and that nothing else forges an over-18 ACCEPT (underage, tampered proof bytes, forged/self-built root, foreign verifying key, mock proof, missing/malformed transcript, wrong-threshold proof). `test_unlinkability_fixed.py` adds `test_dob_not_recoverable_from_root` (the published root is identical across a spread of DOBs and member secrets are not `SHA-256(born)`) and `test_k_anonymity_set_size` (asserts the K-anonymity floor + that `K_ANONYMITY == 6,000,000`), while `tests/test_anonymity_10k.py` asserts the published root commits to a 6M-member / depth-23 / capacity-2^23 tree and that a real over-18 proof verifies against the trusted root. Re-verified in this worktree: the FULL 6,000,000-member root was built (one-time ~14-min in-prover fold, root `0x3465ed2fedc9599c30cfa01ad438b12a5d9f14cba422f2a35df2f7b9bf81f526`) and a REAL Groth16/BN254 proof VERIFIED against it end-to-end through `POST /verify/age` (`over_age: true`, root + canonical vk pinned; an under-18 rejected); the small-set closure suites (`test_anonymity_10k`, `test_unlinkability_fixed`, `test_age_real_zk`) pass with the real prover. The "reference-grade / single-party deterministic setup / 6,000,000-member issuer set (an over-18 proof is unlinkable among ~4,920,000 adults)" qualifiers and the SEC-3 ceiling are MANDATORY — never "production-secure age verification", "internet-scale", or any wording implying a ceremony. The ZK layer is still classical Groth16/BN254, so DO-NOT-CLAIM #1 applies: never pair this with any post-quantum claim. |

### Cross-relying-party unlinkability (real zero-knowledge)

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| UNLINK-1 | "The **same** holder presenting an age proof to **two different relying parties** (`POST /verify/age`, same date of birth, different `relying_party_id`) is **accepted at both** (`over_age: true`) yet produces **two different per-relying-party nullifiers**, and each show is a **freshly re-randomized** proof (byte-different every time) — so two **colluding** sites have nothing stable to correlate on. Every holder shares **one published issuer accumulator root** (a fixed set of **K = 6,000,000** CSPRNG-seeded members folded into a depth-23 Poseidon-Merkle root): the root is an **issuer-level constant identical for everyone**, NOT a per-person handle, and because member secrets are random (not derived from the birthdate) the **date of birth is not recoverable** from the root or transcript. Issuance is **issuer-hiding** — the published issuer view holds only the root + set metadata (no holder secrets, and the 6M members are never materialized), so the issuer cannot link a presentation to a holder; and the personhood path (`/uniqueness/verify`) publishes a **per-scope blinded commitment** so the same human shows DIFFERENT commitments at different sites. Each proof reveals only **{shared issuer root, site-scoped nullifier, age ≥ 18}**; a **fail-closed replay guard** rejects a captured transcript (`replay_detected`). Each is a **real Groth16/BN254** zero-knowledge proof (~10–15 s per site). **Reference-grade, honest residuals stated:** unlinkable **among ~4,920,000 adults** (the over-18 members — 82 ages × 60,000 — of a 6,000,000-member set; a reference scale, **not internet-scale**); a **single-party deterministic trusted setup — not a multi-party ceremony**; the replay guard and issuer/wallet co-location are **demo-grade (in-memory)**; `/uniqueness/verify` relies on clients using the **canonical blinded builder** (not yet server-enforced); the set holds **~60,000 members for each age** so two distinct same-age members share a nullifier with residual ~1/60,000 ≈ **0.0017%** (never de-anonymizes); note the SELF-CONTAINED demo maps every adult born to ONE cached member (the per-born member-fidelity of the old materialized set is not preserved at 6M scale — the anonymity claim is about the 6M-member set the root commits to). The unlinkability property itself is **modeled and machine-checked but partial overall** (see FV-3) — never 'unlinkability-certified'. Ceiling = SEC-3." | `src/psdp_ref/age_issuer.py` (`K_ANONYMITY = 6,000,000`; generate-and-cache depth-23 fold; shared `trusted_age_root`; `generate_holder_secret` = CSPRNG; `issuer_state` holds only `{root, k_anonymity, tree_depth, capacity}` — no secrets, no materialized members); `src/psdp_ref/unlinkable_presentation.py` (`generate_accumulator` folds the 6M set in-prover; `present_from_accumulator` proves against a cached depth-23 path and draws a fresh per-call `proof_seed` → re-randomized `proof_base64`); `src/psdp_ref/age_verification.py` (RP-scoped nullifier via `age_issuer.rp_scope_for`; fail-closed replay guard → `replay_detected`); `src/psdp_ref/proof_of_uniqueness.py` (`build_uniqueness_zk_request` proves a per-scope blinded secret `s_ctx = H(domain‖secret‖scope)`); `tests/test_unlinkability_fixed.py` + `tests/test_uniqueness_unlinkable.py` + `tests/test_anonymity_10k.py` | Read code in this worktree; fix commit `72d53ec` closed the 4 audit breaks (root/DOB leak, proof re-randomization+replay, issuer-hiding, uniqueness correlator) and an independent red-team re-verified (all_zk_breaks_closed, 44/44 acceptance tests). `test_unlinkability_fixed.py` asserts: same holder + two RPs → SAME root, DIFFERENT nullifiers, DIFFERENT (re-randomized) proof bytes; root IDENTICAL across different DOBs (carries no per-user info); DOB not recoverable; asserts a K-anonymity floor + that `K_ANONYMITY == 6,000,000`; the issuer view holds no secret material (`test_issuer_view_hides_secrets_and_members`); a replayed transcript is rejected (`replay_detected`); a minor still fails the predicate. `tests/test_anonymity_10k.py` asserts the published root commits to a 6M-member / depth-23 tree and a real over-18 proof verifies. `test_uniqueness_unlinkable.py` asserts the per-scope commitment DIFFERS for the same human across two RPs while staying a stable within-scope sybil key. Re-run in this worktree against the built `psdp-arkworks-present`/`-biometric-match` provers (small-set closure suites pass, real Groth16 proofs throughout); and the FULL 6,000,000-member root was built (one-time ~14-min in-prover fold, root `0x3465ed2fedc9599c30cfa01ad438b12a5d9f14cba422f2a35df2f7b9bf81f526`) with a REAL Groth16 proof VERIFIED against it via `/verify/age`. Builds on AGE-ZK-1 (same route, same reference-grade + K = 6,000,000 limits) and FV-3 (the unlinkability theorem split is partial). The ZK layer is classical Groth16/BN254, so DO-NOT-CLAIM #1 applies: NEVER pair with any post-quantum claim, NEVER claim "internet-scale" anonymity, and NEVER write "unlinkability-certified" / "proven unlinkable in production" (DO-NOT-CLAIM #8 → FV-3 only). |

### Multi-factor step-up (real WebAuthn passkey)

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| MFA-1 | "Real WebAuthn passkey step-up: a federated login (**AAL1**) is upgraded to passkey-bound **AAL2** via a real **ECDSA-P256** assertion + a **same-holder possession proof**; the upgraded credential is **Ed25519-signed** and carries faithful multi-axis assurance (**IAL/AAL/FAL**); the **demo IdP is simulated**. A passkey raises the authenticator axis (AAL) only — it does no identity proofing, so identity claims stay denied. Faithful labelling, not a certification or production-secure claim (ceiling = SEC-3)." | `demo/onramp.py` (`/onramp/login`, `/onramp/binding/challenge`, `/onramp/passkey/enroll`, `/onramp/stepup`); `src/psdp_ref/assurance_gateway/stepup.py` (`step_up`: passkey ⇒ AAL only, fail-closed on a non-same-holder factor); `src/psdp_ref/passkey_binding.py` (`parse_registration`, `verify_assertion` = ECDSA-P256-SHA256); `src/psdp_ref/assurance_gateway/holder_binding.py` (`bind_same_holder` = WebAuthn possession + scoped nullifier); `tests/test_onramp_stepup_linking.py`; `tests/assurance/test_stepup.py`; `tests/test_site_mfa_demo.py` | Read code in this worktree: `/onramp/stepup` re-runs the gateway against the SAME verified login behind a load-bearing same-holder gate (`_binding_proof` → `bind_same_holder`), a passkey factor maps to the AAL axis (`_FACTOR_AXIS[PASSKEY] = "AAL"`), and the upgraded credential is re-verified with `verify_assured_credential(..., allow_mock=False)` (a real Ed25519 signature check). `tests/test_site_mfa_demo.py` drives the 4 open endpoints with the pure-software WebAuthn authenticator (real `create()` + real `get()` assertion): login → enroll → stepup yields `assurance.aal == 2` while `ial` stays `1`, the credential's `signature_suite` is `REAL_SIGNATURE_SUITE` and `verified is True`, and a foreign authenticator's assertion is rejected `400` (same-holder gate). The demo IdP is the same simulated provider as the "Bring your own login" card — RS256 id_token real, identities not. NEVER pair with any "production-secure", "certified" or post-quantum wording. |

### AI-agent delegation (key-bound metered spend caps)

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| AGENT-1 | "An AI-agent delegation can carry a **metered spend cap**, enforced live. A **key-bound, attenuating** delegation chain (principal → team-lead → worker) issues the worker a **tighter cap (€40)** than its parent (€100); two metered `purchase.execute` attempts of €30 each are decided in front of you — the **first is authorized** (€30 ≤ €40), the **second is denied `cap_exceeded`** (running total €60 > €40), enforced **at action time, not advisory**. Each sub-delegation is **cryptographically signed by its parent** (attenuating, accountable), and **every attempt — authorized and denied — is recorded in an auditor-only sealed audit record**. Cap enforcement is real; the credentials are **demo-issued with ephemeral keys** (reference-grade, ceiling = SEC-3)." | `GET /agent/chain/demo` in `src/psdp_ref/agent_identity.py` (`issue_agent_delegation` with `limits={'spend':{'max':…,'currency':'EUR'}}` and `parent_credential`/`parent_sk` key-binding; `verify_chain`; `agent_act(..., consumption_ledger=ledger)`); `src/psdp_ref/delegation_caps.py` (`SqliteConsumptionLedger.reserve` — atomic per-ancestor debit, returns `cap_exceeded`); `src/psdp_ref/delegation.py` (parent-signed, attenuated sub-delegations) | Ran `GET /agent/chain/demo` live with `PSDP_PRODUCTION=1` (port 8121, no `X-API-Key`): `chain` = team-lead `limits.spend.max=100 EUR` → worker `limits.spend.max=40 EUR`; `attempts[0]` = spend 30, `authorized: true`, `decision: "authorized"`, `reasons: []`; `attempts[1]` = spend 30, `authorized: false`, `decision: "denied"`, `reasons: ["cap_exceeded"]`, `cap_reservation.allowed: false`. Each attempt carried an `audit_header` (`record_type: escrowed-audit-record`). NOTE: the audit envelope internally uses ML-KEM/X25519, but that is deliberately NOT surfaced on the page — surfacing it would trigger the mandatory PQ-1 limitation sentence (DO-NOT-CLAIM #1/#3), so AGENT-1 stays scoped to caps + parent-signing + auditor-only sealing and makes NO post-quantum claim. Ceiling = SEC-3; demo-issued ephemeral keys, never "production-secure". |

### Company / posture

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| ORG-1 | "PSDP is a **pre-incorporation, single-founder project**. No legal entity exists yet; engagements are scoped accordingly. Honesty is the brand." | Design spec `docs/superpowers/specs/2026-06-12-marketing-site-redesign-design.md` §1; owner statement | Stated by the owner; no artifact contradicts. Any wording implying an existing company, customers, team, or revenue is banned. |

### Pricing (every figure MUST carry the word "indicative")

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| PRC-1 | "Indicative: age-verification checks at **~$0.01–0.03 per check** at volume." | `products/VERIFIED_LOGIN_PRICING.md` (line ~56); `products/PRODUCTS_AND_PRICING_STATUS.md` scorecard | Both docs state $0.01–0.03 per age-predicate check. |
| PRC-2 | "Indicative: pre-certification / conformance audit engagements **€20–40k**; unlinkability / privacy-conformance audit **€30–60k**." | `/home/kaali/psdp-site/products/REVENUE_MODEL_12MO.md` (revenue-lines table); `products/PRODUCTS_AND_PRICING_STATUS.md` | Ranges read verbatim from the revenue model; STATUS doc carries compatible tiered bands ($10–75k). |
| PRC-3 | "Indicative: managed OIDF certification run **$2–5k per spec** (anchored on OIDF self-certification fees of $700–$3,500 per spec)." | `/home/kaali/psdp-site/products/REVENUE_MODEL_12MO.md`; `products/VERIFIED_LOGIN_PRICING.md` (line ~62) | Both figures present in the docs; the anchor is the public OIDF fee the docs cite. |
| PRC-4 | "Indicative: Conformance Coach subscription tiers **$199 / $799 / $2,000 per month**." | `products/PRODUCTS_AND_PRICING_STATUS.md` (2026-06-06 scorecard) | Read from the newer STATUS doc (supersedes the $99–499 row in REVENUE_MODEL_12MO.md — do not mix the two). |
| PRC-5 | "Measured (2026-06-06, developer hardware): a real Groth16/BN254 verification costs **~7–22 ms** of compute — on the order of **10–20 cents per million verifications** — so verification compute is not a pricing floor." | `products/VERIFIED_LOGIN_PRICING.md` (measured table, lines ~71–101); `products/PRODUCTS_AND_PRICING_STATUS.md` | Measured-bench tables read directly (21.8 ms loaded / 6.8 ms isolated; ~8–21¢/million). Qualifiers "measured, developer hardware" are mandatory. |

---

## 2. DO-NOT-CLAIM (absolute — from `docs/PQ_ZK_STATUS.md` plus audit rules)

Never state, write, demo, or imply ANY of the following, on any page, in any tense:

1. ❌ "PSDP has post-quantum zero-knowledge proofs" / "quantum-resistant ZK / unlinkability / predicates". The live ZK layer is Groth16/BN254 (Shor-breakable). (`docs/PQ_ZK_STATUS.md` §1, §6)
2. ❌ Any "256-byte PQ ZK" or other sub-kilobyte "post-quantum" proof-size figure — that is a Groth16-wrapped proof and NOT post-quantum. Honest PQ-STARK size ≈73 KB. (§5)
3. ❌ "In-circuit PQ issuer-signature verification" as a shipped product property — it is a spike on another branch. (§6)
4. ❌ "Certified", "conformance-signed", "OIDF-certified", "officially certified" or any phrasing implying a published OpenID Foundation certification. There is none; we are not on openid.net/certification. Allowed framing is OIDF-1/OIDF-4 only.
5. ❌ Any eIDAS legal-status claim (qualified/notified/recognized wallet or trust-service status). All PKI/trust-list/EUDI work is **interop evidence, not legal status**.
6. ❌ Entity-implying claims: "our company", "our customers", "our team", revenue, headcount. See ORG-1 for the honest posture.
7. ❌ "Production-ready", "battle-tested", "enterprise-grade". Ceiling = SEC-3.
8. ❌ "Unlinkability-certified" or "proven unlinkable in production". Allowed framing is FV-3 only.
9. ❌ Blanket "fully open source". The 16-file moat (`.moat-manifest`) is BUSL-1.1 ("NOT open source" per its own headers). The project is **open-core**: the rail is Apache-2.0 (open source), the moat is source-available. Allowed framing is LIC-1.
10. ❌ "All security findings fixed" / "0 known vulnerabilities" (the EVIDENCE_PACKAGE `security_audit: 117/117 fixed` block is superseded by the 2026-06-09 production-readiness audit, which found new criticals since remediated only in part).
11. ❌ Any number that does not appear, with source and verification note, in §1 of this ledger.

---

## 3. Rejected during audit (appendix)

| ref | candidate claim | why rejected |
|---|---|---|
| R-1 | "212 SUCCESS assertions" (old site, dynamically rendered counter) | Untraceable. The string "212" appears in no conformance artifact (`SCORECARD.json`, `EVIDENCE_PACKAGE.json`, run summaries). The old `reference-edition.html` rendered `oc.success` from a live endpoint; no artifact pins 212. |
| R-2 | "1,434" (old site figure, presumed function/assertion count) | Untraceable. Appears in no artifact searched (EVIDENCE_PACKAGE, scorecards, site sources — the only greppable "1,4xx" hits were CSS rgba values). |
| R-3 | "conformance-signed" / "330 of 332 certified" (old `reference-edition.html` ~line 657) | The `"certified": 330` field in `SCORECARD.json` is the suite's internal status counter, not a certification. Wording violates DO-NOT-CLAIM #4. Replace with OIDF-1 + OIDF-4. |
| R-4 | "FAPI 2.0 conformance-tested: 78/80, **certified**" | The 78/80 figure is verified (OIDF-2) but only as a local self-run; any "certified" framing rejected per #4. |
| R-5 | "23 credential types wire-verified against walt.id" | Artifact shows **22** distinct credential types (43 configurations, all passing). The 23rd (biometric-bound doctype) is not in `wallet_baselines.json`. Rounded down to WAL-1. |
| R-6 | "Paradym walked the full OID4VCI flow live on a real Android phone (2026-06-04)" | No on-disk artifact found for the 2026-06-04 real-phone session (searched `tier3_results/`, `auto_research/reports/`, `~/.psdp_research/`, home dir by mtime). `attempts.jsonl` shows complete flows only from clients *identifying* as Paradym (lab-harness UA strings); April real-phone artifacts (okhttp + logcat) show OID4VP request-fetch without completion. Weakened to WAL-3 + WAL-4. |
| R-7 | "OID4VP presentation received live from the vck **wallet app** (Valera)" | Harness tested the vck **library**, not the Valera app binary (per the harness README itself). Weakened to WAL-2 with mandatory scope limits. |
| R-8 | "Fail-closed defaults" (blanket) | Contradicted in part: `require_active_status` (revocation enforcement) still defaults to `False` in demo policy paths (`src/psdp_ref/age_verification.py:585`); the 2026-06-12 re-verification records revocation as "partial". Scoped to SEC-1/SEC-4. |
| R-9 | "Open source" (blanket) | The 16 moat files carry `BUSL-1.1 … NOT open source` headers (`.moat-manifest`); the rest IS Apache-2.0, so the project is **open-core**, not "fully open source". (`LICENSE-BSL` is now finalized with a named interim Licensor.) Scoped to LIC-1. |
| R-10 | "117/117 security-audit findings fixed; 0 remaining" (`EVIDENCE_PACKAGE.json` security_audit block) | Superseded/contradicted by the 2026-06-09 read-only production-readiness audit (6 criticals found later; remediation landed 2026-06-10; the license-void and ephemeral-key findings were closed 2026-06-30). Using the April figure would still be materially misleading (no "all findings fixed" claim is allowed). |
| R-11 | "902/902 unit tests pass" (EVIDENCE_PACKAGE) | Stale April 2026 snapshot of a different suite size. The only current test-count wording allowed is the dated, fully qualified TEST-1 presentation-readiness result below. |
| R-12 | "$1B opportunity" / TAM-share claims | Revenue model itself labels year-1 coverage "a rounding error" and the $1B framing a moonshot. Only the indicative price points (PRC-1..5) are allowed; no market-size claims. |
| R-13 | "EBSI / eIDAS / trusted-list recognition" | All EBSI/PKI/LOTL work is interop evidence explicitly flagged "NOT legal status" in its own documentation. Violates #5 if phrased as status. |

---

## 4. Notes for page builders

- Quote phrasings verbatim where possible; weakening (dropping a number, adding a caveat) is allowed, strengthening is not.
- Every numeric claim on a page should carry a footnote-style reference to its claim id (e.g. `[OIDF-1]`) so reviewers can diff against this ledger.
- PQC mentions REQUIRE the PQ-1 limitation sentence on the same page, visually attached.
- Pricing always inside a sentence containing the word "indicative".
- The /evidence page may reproduce the source-artifact paths from §1 as provenance.

---

## Session-2026-07-03 additions — K5 + trust-fabric (same enforcement rules apply)

### Organizational identity — K5 (ZK proof of vLEI role-membership)

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| K5-1 | "A **reference-grade zero-knowledge proof of vLEI role-membership**: a holder proves control of a **GLEIF-rooted organizational role credential without revealing the entity, LEI, or role-holder**, with a **per-verifier scoped nullifier** (unlinkable across verifiers, rate-limitable within one). It is **classical Groth16/BN254 — NOT post-quantum**, uses a **single-party trusted setup** (demonstration-grade soundness, not a multi-party ceremony), and runs on **self-minted credentials in the GLEIF *test* ecosystem**. The vLEI/KERI ecosystem has **no zero-knowledge story anywhere**; this is a **novel reference implementation — NOT adopted, endorsed, integrated, or used by GLEIF**." | `docs/superpowers/specs/2026-07-02-k5-zk-vlei-membership-design.md`; `prover/arkworks/src/bin/psdp-arkworks-vlei-membership.rs`; `src/psdp_ref/{vlei_zk_membership,vlei_accumulator,vlei_zk_route}.py`; `tests/keri/test_vlei_zk_*`, `test_vlei_accumulator.py`; `tests/keri/test_k5_real_gleif_boundary.py`; live route `GET /vlei/zk/demo` | Built + adversarially verified 2026-07-02. Mutation tests prove tier-binding (C2) and nullifier-secret-binding (C5) load-bearing (each mutant flips exactly its negative test); 9/9 circuit tests, ~205 keri tests. The K0–K4 substrate verifies a **real GLEIF-e2e-issued chain** (GEDA→QVI→LE, Sally-validated); the **ZK proof runs on self-minted role credentials** — running K5 over real GLEIF fixtures is impossible (no role credential + no holder private key), proven by `test_k5_real_gleif_boundary.py`. MANDATORY qualifiers: reference-grade / classical-not-PQ / single-party-setup / self-minted / test-ecosystem. DO-NOT-CLAIM #1 applies. **NEVER** "GLEIF uses/adopted/integrated/endorses our ZK", **NEVER** "trustless", "live GLEIF membership", or "production-secure". Ceiling = SEC-3. |

### EU trust-fabric verification (eIDAS LOTL + EBSI)

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| TRUST-1 | "In a dated live campaign, independently authenticates the EU LOTL against Official Journal notice C/2026/1944 (TLv6, sequence 389), evaluates all **31** national-list pointers, fetches **29 of 31**, accepts **28 of 31** under strict transport, profile, freshness and exact-signer checks, and parses **4,677 service records**. Hungary is accepted with 339 records and France with 355; IE fails normal TLS chain construction, SK's authenticated HTTP pointer is rejected by HTTPS-only policy, and the fetched historical UK list is rejected because freshness cannot be established without `NextUpdate`. The exact retained Danish list also replays offline against its authenticated LOTL signer set. Separately, it walks **EBSI's multi-hop accreditation chains** (Trusted Issuer → TAO → Root TAO) against the **live EBSI Pilot registries**, fail-closed per hop and adversarially tested. This is **interop evidence**: we are **NOT listed on** any trusted list, **NOT eIDAS-qualified**, and **NOT an accredited EBSI issuer**." | `pki/lotl_campaign/campaign_results-20260728T202113Z.json`; retained LOTL `certs/lotl_snapshot/20260728T202113Z.xml`; `pki/lotl_campaign/CAMPAIGN_REPORT.md`; retained DK bytes; `scripts/lotl_live_validation_campaign.py`; `src/psdp_ref/did_ebsi.py` (`verify_ebsi_accreditation_chain`); `tests/did/test_did_ebsi_real_pilot.py` | The 2026-07-28T20:21:19Z strict campaign records 31 pointers, 29 fetches, 28 full-profile acceptances and 4,677 importer records. Its embedded bootstrap verifies the OJ-rooted TLv6 sequence 389 signature and freshness; the retained LOTL SHA-256 matches the campaign report. The exact selected DK bytes replay offline; the other 27 accepted national-list byte artifacts remain report commitments only. EBSI real-pilot evidence separately verifies a Pilot chain to a pinned Root TAO and rejects a tampered TI signature and an untrusted root. MANDATORY: interop-evidence framing — verify ≠ trusted-by. **NEVER** "listed on / trusted by / eIDAS-qualified / accredited EBSI issuer / part of the ecosystem / EU-recognized". |

### Exact-action banking-to-network control (local synthetic composite)

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| ACTION-1 | "A **locally reproducible, synthetic banking-to-network control demonstration** verifies a locally signed synthetic risk artifact, binds a synthetic operator-wallet presentation to one exact CAMARA QoD-shaped **`ActionAuthorization v2`** transaction, rejects changed risk, action substitution, aggregate replay and signed-receipt tampering before provider dispatch, and emits a locally verifiable signed receipt. The ordinary-approval control dispatches no network action; the risk step-up reaches only an in-process synthetic provider (`synthetic_accepted`) and records `fulfilment_verified=false`. This is a local integration and security-control proof of concept — **NOT** ETSI/OpenOP/CAMARA conformance, live bank/wallet/operator/carrier interoperability, bank settlement, carrier fulfilment, or third-party endorsement." | `products/aadya-demo/PRESENTATION_READINESS_2026-07-28.md`; `products/aadya-demo/OBP_ETSI_QOD_COMPOSITE_DEMO.md`; `scripts/run_obp_etsi_qod_demo.sh`; sibling local checkout `/home/kaali/open-edge-agent-lab` | The 2026-07-28 rehearsals ran the `approve` and `step_up` branches in mock/offline mode. The overview and composite report an exact `ActionAuthorization v2` binding, all four negative controls rejected, a signed receipt, `provider_outcome=synthetic_accepted`, and `fulfilment_verified=false`. The commands depend on the sibling local checkout; no external provider, bank, wallet, operator, carrier or OpenOP deployment participated. MANDATORY: keep "local", "synthetic", "mock/offline", and the no-conformance/no-fulfilment boundary attached. |

### Presentation-readiness test result (dated local run)

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| TEST-1 | "In the dated **2026-07-28 local presentation-readiness run**, the complete first-party Python suite reported **7,179 passed and 0 failed**, with 158 skipped, 6 expected xfails and 198 subtests passed in 1:30:20. This is a dated local engineering result, **not** an external certification or a claim that blocked live, Android, GUI, carrier, wallet, OpenOP, QKD or offline-schema gates ran." | `products/aadya-demo/PRESENTATION_READINESS_2026-07-28.md` (`Verification matrix`, `Known gates and debt`) | The readiness report records the exact pytest totals and duration, then separately lists the external and toolchain gates that were not run. Quote the whole qualified result or a strict weakening; never collapse it to "all tests pass", "production-ready", or an externally witnessed result. |

### DO-NOT-CLAIM additions (absolute)
- **K5 / GLEIF:** never state or imply GLEIF (or any GLEIF/QVI/vLEI party) **uses, adopted, integrated, endorses, or is a customer of** the K5 ZK proof. It is a solo reference; GLEIF is unaware of it. Never "post-quantum", "trustless", "live GLEIF membership", or "production-secure" for K5.
- **Trust fabric:** never state or imply being **listed on** a trusted list, **eIDAS-qualified**, an **accredited/registered EBSI issuer**, or **recognized/trusted by** the EU trust framework. We only *verify* it.
- **Exact-action composite:** never state or imply a live bank, wallet, operator,
  carrier or OpenOP participant; ETSI/OpenOP/CAMARA conformance; settlement;
  carrier fulfilment; or third-party endorsement. It is local and synthetic.
- **Test result:** never shorten TEST-1 to "all tests passed" or use it to imply
  production readiness, external witnessing, or completion of its named blocked gates.

---

## Session-2026-07-12 addition — operational sensor evidence

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| INSPECTION-1 | "The public `GET /verify/inspection/demo` runner executes a **synthetic pressure-hold evidence control**: a locally generated instrument signature is pinned to a local test registry; a separately local-test-key-signed calibration record, a scoped/revocable technician delegation plus holder proof, exact asset/work-order nonce binding, freshness, coverage and one-time replay checks are evaluated; the resulting minimal receipt is **Ed25519-signed and tamper-evident**. This is **reference evidence only**: it proves submitted-evidence integrity and control flow, **NOT** physical-world truth, secure hardware attestation, anti-tamper resistance, certified calibration, location/asset custody, EUDI-wallet authority, regulated inspection approval or an actual workflow release. The fixture uses synthetic readings and local test keys." | `src/psdp_ref/inspection_evidence.py`; `tests/test_inspection_evidence.py`; `website/demos.html` | The reference fixture signs four distinct artefacts with real Ed25519: instrument batch, calibration certificate, authority delegation and operator holder proof. The evaluator pins instrument/lab keys out of band, binds the evidence to HMAC asset/work-order commitments plus a high-entropy nonce, consumes the batch through the replay-store protocol, and uses a strict allow-list receipt projection. Tests require pass, valid threshold failure, coverage insufficiency, signature mutation rejection, wrong anchor rejection, authority/revocation rejection, replay rejection and pinned receipt tamper/re-sign rejection. No hardware, external calibration lab, wallet or physical sensor is contacted. |

---

## Session-2026-07-26 addition — self-issued trust-chain laboratory

| id | allowed phrasing | source artifact | verified-how |
|---|---|---|---|
| TRUST-LAB-1 | "The closed local `POST /api/sandbox/trust-chain/run` runner executes **seven separately scoped technical lanes**. Six lanes generate fresh ephemeral local test artifacts: private Web TLS; a signed ETSI TS 119 612-shaped laboratory list with QWAC/QSealC-shaped leaves and a sealed JWS; ISO mdoc IACA→Document Signer→issuerAuth; a local X.509-backed SD-JWT issuer plus holder KB-JWT; a self-minted KERI/vLEI/WRPAC-shaped relying-party flow; and a QKD identity fixture that completes an in-memory TLS 1.3 mutual-authentication handshake and verifies certificate-bound, status-only authorization. A seventh read-only lane verifies bundled real GLEIF testnet GEDA→QVI→Legal Entity artifacts and is not spliced into the self-minted role lane. In the 2026-07-26 verified run, **7/7 technical lanes passed**, **14/14 isolated negative controls were denied**, and the aggregate manifest's ephemeral self-signature verified. Its embedded key proves internal consistency only; whole-manifest provenance requires an independently pinned signer or digest. The fixed endpoint accepts no caller URL, certificate, key, credential, claim set or policy; performs no network egress; requests or consumes no QKD key; and returns no private keys, raw credentials, bearer tokens or QKD key material. This is local technical evidence only: it does **not** create public WebPKI trust, qualified eIDAS/QTSP/QVI status, Member-State registration, government PID/mDL authority, a GLEIF-issued Aadya role, OIDF/ETSI certification, live KME/key delivery, QKD origin or legal authority." | `src/psdp_ref/self_issued_trust_demo.py`; `demo/self_issued_trust_routes.py`; `products/trust-chain/demo_trust_chain.py`; `website/demo-trust-chain.html`; `products/trust-chain/README.md`; `tests/test_self_issued_trust_demo.py`; `tests/test_self_issued_trust_routes.py`; `tests/test_self_issued_trust_cli.py`; `tests/test_site_pages.py` | Re-ran the CLI and focused core, route and full-application tests on 2026-07-26. The ceremony returned 7/7 technical lanes, 14/14 denied attacks, a valid ephemeral self-signature and no QKD-key request or consumption. The manifest verifier accepts an expected public key and/or digest pin and rejects the wrong digest; without such a pin the embedded key is not an identity anchor. A socket-denial test blocks Python TCP and UDP egress primitives while the complete ceremony succeeds. Negative controls cover wrong roots, signed-list/JWS/authorization tamper, wrong holder key, bridge-signer substitution, scope expansion, revocation, replay, and QKD trust-domain substitution. The separate `gleif.not_spliced` positive check and cross-domain invariant guard controlled/real-vLEI separation. The manifest projection is scanned for private-key, raw-token, raw-credential and QKD-key markers. Mandatory boundary: technical verification under local roots is not public recognition, qualification, certification or legal authority. |
