This document maps the eight SEED-001 human GA items to merge-blocking CI substitutes, library/integration tests, and residual risk that still needs occasional human or vendor-assisted verification.
| SEED | Topic | CI / automated substitute | Residual (not replaced by CI) |
|---|---|---|---|
| 1 | Lockout + suspicious-login email HTML | Example.Accounts.EmailsSecurityHtmlTest — structure, CTAs, IP/device copy | Gmail / Outlook / Apple Mail rendering, dark mode, clipping |
| 2 | Seven account-lifecycle templates | Example.Accounts.EmailsLifecycleHtmlTest — headings, CTAs, security footer strings | Same as SEED-1 in real clients |
| 3 | mix sigra.gen.oauth greenfield | install_smoke CI job → scripts/ci/install-smoke.sh (mix phx.new + mix sigra.install + mix sigra.gen.oauth, path + migration + router checks) | Subjective “reads well” in generated files; major Phoenix generator churn |
| 4 | Google OAuth E2E | Sigra.OAuthTest (+ related) — MockStrategy round-trip: authorize URL, HMAC state, handle_callback/4 without HTTP; see § OA-01 / OA-02 — library_tests + oauth_ceremony machine baseline for the OA-01 audit persistence story. | Google consent UX, token refresh against live Google |
| 5 | Provider linking / last-method unlink | Sigra.OAuth.OAuthSettingsTemplateContractTest — template strings for D-03 last-provider + “Set a password first” | Live tooltip timing, exact disabled-button styling in host CSS |
| 6 | Email-match confirmation / invitation lock | ga-uat-shift-left.spec.ts — invitation signup path: tamper locked email → server-side email_mismatch form error | Other email-match surfaces (non-invitation) if added later |
| 7 | Backup code regenerate wiring | example_unit_smoke (ci.yml) runs mix test --include example_app, including test/example/test/example_web/smoke/backup_code_rotation_test.exs — proves old backup plaintext fails after Accounts.mfa_regenerate_backup_codes/3 with a valid TOTP. ga-uat-shift-left.spec.ts (same workflow’s Playwright job) covers MFA settings UX shell only. | Live browser timing, copy tweaks |
| 8 | Clean-machine getting started | scripts/ci/getting-started-contract.sh — internal doc links + required command strings | Wall-clock “< 30 min” for unfamiliar human; prose friction |
OA-01 / OA-02 — library_tests + oauth_ceremony machine baseline
This subsection is the grep-friendly hub for OA-01 (merge-blocking ceremony audit assertions) and OA-02 (how we describe machine vs human coverage). It complements the SEED table row SEED-4 and the GA-03 bullet under v1.4 GA — those stay scannable; depth lives here.
Machine (merge-blocking)
Sigra.OAuthCeremonyAuditTest(test/sigra/oauth/oauth_ceremony_audit_test.exs) proves persistedaudit_eventsforoauth.register_via_oauth(registration ceremony) andoauth.authorizeon the successfulSigra.OAuth.authorize_url/3path, using Postgres + Sandbox, an in-process mock strategy, and no live IdP HTTP.Sigra.Planning.Phase58OauthOa01CiContractTest(test/sigra/planning/phase_58_oauth_oa01_ci_contract_test.exs) is a structural CI gate: thelibrary_testsGitHub Actions job runs plainmix testand asserts the OA-01 modules stay wired into CI — it does not replace the integration assertions in the audit test.Sigra.OAuthTest(test/sigra/oauth/oauth_test.exs) covers the authorize/callback contract with Assent-shaped mock behavior (complement to the audit persistence proof above, not a duplicate).
Discoverability: see .github/workflows/ci.yml job library_tests (“Run library tests”).
Human / live-provider residual
- Live Google (consent UX, refresh flows, tenant-specific policy) is not asserted by the modules above.
- Anything outside those named contracts remains occasional human or vendor-assisted verification.
- Machine proofs above are scoped to the named tests; IdP-specific end-to-end behavior is not exhaustively automated in CI.
v1.4 GA (GA-02..GA-05)
Human vs machine boundaries for v1.4 are recorded in .planning/v1.4-GA-UAT.md (canonical Executed / Waived / Blocked table). This section cross-links that matrix only — it does not replace the SEED-1..8 table above or duplicate merge-blocking job lists.
- GA-01 (pointer): Product proof lives in Phase 41 +
example_unit_smoke; see.planning/uat-evidence/v1.4/GA-01-pointer/README.mdand the GA-01 row in.planning/v1.4-GA-UAT.md— no rotation re-run in Phase 42. - GA-02: Human = real MUAs when templates change; machine =
library_tests/ example HTML tests (EmailsSecurityHtmlTest,EmailsLifecycleHtmlTest) +example_unit_smokeper SEED-1/2. - GA-03: Human = live Google OAuth; machine =
Sigra.OAuthTest+MockStrategycontract path (SEED-4) andSigra.OAuthCeremonyAuditTestfor persisted audit rows — see § OA-01 / OA-02 —library_tests+oauth_ceremonymachine baseline (subsection owns depth). - GA-04: Human = witnessed
guides/introduction/getting-started.mdrun; machine =getting_started_uat_contract+scripts/ci/getting-started-contract.sh(SEED-8). - GA-05: Consolidated matrix ownership — links
.planning/v1.4-GA-UAT.mdhere and defers full CI graph to this file’s SEED rows.
v1.12 launch evidence (attestation)
v1.12 records per-SEED outcomes (Executed / Waived with substitute / Deferred) in the planning-only index v1.12-UAT-EVIDENCE.md on main (UAT-01). That file is intentionally not a second SEED×CI matrix — the machine substitute vs residual catalog and merge-blocking Policy for SEED-1..8 remain in this document (table above + § Policy).
- Catalog vs outcomes: the SEED table above names what CI proves and what humans might still check; v1.12-UAT-EVIDENCE records what we assert happened for release engineering.
- Governance: if an outcome row disagrees with § Policy below, edit
.planning/v1.12-UAT-EVIDENCE.mdfirst, then align prose here. - Downstream: phase 75 links
upgrading-to-v1.12.mdto this path (TRN-01) — keep the filename stable.
Where to run this
- GitHub Actions:
.github/workflows/ci.yml— jobslibrary_tests,example_unit_smoke,example_playwright_smoke(includesga-uat-shift-left.spec.ts),install_smoke,getting_started_uat_contract. - Installer golden / idempotency contract: locally run
mix ci.install_golden(seeMAINTAINING.md); CI mirrors it with jobinstall_golden_contractin.github/workflows/ci.yml(path-filtered on PRs, always onmainpushes). - Local: same as CI:
PGUSER=postgres PGPASSWORD=postgres PGHOST=localhostfor Elixir tests; Playwright fromtest/example/priv/playwrightwith example app on port 4000.
Policy
- Merge-blocking: Rows SEED-1–2, 3, 4, 5, 6, 7 (example smoke + Playwright UX), and 8 (doc contract) are considered machine-closed for GA posture when the jobs above are green.
- Residual: Real mail clients and live Google OAuth remain optional pre-announcement spot checks; track separately (e.g. quarterly) if desired.