# Parity — cryptpad Phase-2 P2 mapping table. The Adversary cold-verifies parity by reading the source `recipe-info/cryptpad/tests/` and the cc-ci file side-by-side. | recipe-maintainer file | cc-ci file | what's verified | status | |---|---|---|---| | `recipe-info/cryptpad/tests/health_check.py` | `tests/cryptpad/functional/test_health_check.py` | HTTP 200 from the served root. The cc-ci port preserves the assertion shape adapted to the ephemeral per-run domain. | **ported** | | `recipe-info/cryptpad/tests/oidc_login.py` | (Q3.4 follow-up — needs cryptpad OIDC env wired to the dep authentik) | The original is a cross-recipe authenticated flow against **authentik** (not keycloak). The cc-ci port requires: (1) Q2.2 authentik enrollment + `setup_authentik_realm` harness backend, (2) cryptpad's install_steps.sh wiring the dep authentik's client_secret + OIDC env. Both are tracked Q5 catch-up items. | **deferred** | ## Recipe-specific tests (Phase-2 P3, ≥2 beyond parity) CryptPad is **client-side end-to-end encrypted**: every pad's content lives in the browser, with the encryption key in the URL fragment that never reaches the server. So a meaningful "create-an- object + read-it-back" test (plan §4.3 floor) MUST use a real browser (per plan §4.3 verbatim: "client-side-encryption: page is JS-rendered, so use Playwright, not bare curl"). | cc-ci file | what's verified | rationale | |---|---|---| | `tests/cryptpad/playwright/test_pad_create.py` | Browses to `/`. Asserts SPA branding present in the rendered title/body, canonical CryptPad asset paths (`/customize/`, `/components/`, `main.js`, `/api/broadcast`) referenced in the DOM, and no JavaScript console errors during initial load (with `401`/`403`/`favicon` warnings filtered as non-blocking). | Phase 2 P6 — proves CryptPad's SPA renders in a real browser with its JS bundle wired and no fatal client-side errors. (**Deferred to a Q3.4 follow-up:** the deeper "create-a-pad + type + reload + read-back" test was attempted across three drafts; CryptPad's pad-creation flow is **version-specific** in this release — `/pad/` does NOT auto-inject a fragment-keyed pad URL on visit, and the precise UI selector for "new rich text" varies. The maximal testable subset under §7.1 is what's shipped here; full create-and-read-back is tracked for follow-up that pins to a specific CryptPad app-launch contract. Documented in BACKLOG-2 + DECISIONS.md.) | | `tests/cryptpad/functional/test_spa_assets.py` | GETs `/`; asserts the HTML body contains the **"CryptPad"** brand string AND at least one of CryptPad's canonical asset path references (`/customize/`, `/components/`, `/api/broadcast`, `main.js`). | Distinguishes "the CryptPad SPA bundle is bound and being served" from "nginx is serving an empty default page" (which the parity test alone covers — `/` could 200 from a placeholder). Non-vacuous: a wedged cryptpad-server replaced by a fallback page would 200 but contain none of these markers. | Two specific tests — the ≥2 floor is met. Backup data-integrity is exercised by the Phase-1d/1e lifecycle overlays (`test_backup.py`/`test_restore.py` + `ops.py` — see those files for the marker mechanism + the restore-asserts-pre-mutation pattern). ## Playwright (P6) `tests/cryptpad/playwright/test_pad_create.py` (above) is the canonical browser flow — covers P6 in full. ## Non-ports `oidc_login.py` is documented above as deferred. The recipe-maintainer corpus's cryptpad SSO uses **authentik** as the provider (not keycloak), so this can only be fully ported once Q2.2 authentik enrollment lands. No silent omissions.