Skip to main content

Goal

Every invite archetype a CASA admin can send MUST have a named, seeded, e2e-tested path from invite-creation through cross-apex app-gating — and the pass/fail status of each path MUST be visible on ARES without leaving the dashboard.

Named invite archetypes (the “default auth modes”)

Canonicalise the two-system mess into four named archetypes stored as invite presets in CASA:
Archetype IDHuman labelCASA roleCASA appGrantsAirlock tierrelationshipTypeIntended use
AM-GUESTGuest testermember[landing, manual]ORBITERcommunityShare a demo link with a stranger
AM-FRIENDFriend testermember[landing, manual, pebble-public, hubble-readonly]LANDERcommunity”Remember me from before? Try this”
AM-CONTRIBContributormember[hatch, hubble, ares, pebble, manual]BEACONcollaboratorTrusted external helper
AM-FAMILYFamily / coreadmin[*]COREteamSibling, co-owner — full CASA admin
Preset = one config object consumed by POST /api/admin/invitations; UI surfaces a one-click picker.

Tasksets

TS-1 — Canonicalise archetypes (CASA-side, 0.5d)

Why: Without a named archetype, there’s nothing to test, trace, or display.
  • family-hub/src/lib/invite-archetypes.ts — constant map of the four rows above, typed against EcosystemApp[]
  • Migrate metadata.appGrants population to derive from archetypeId when present (backwards-compatible: direct appGrants still wins)
  • Extend POST /api/admin/invitations body to accept { archetypeId } as shorthand
  • Seed script: idempotently ensure the four archetypes’ app sets are consistent with app_registry.allowedRoles — fails CI if drift
  • Surface archetype picker on /admin/invitations/new
Acceptance: curl POST … {email, archetypeId:"AM-FRIEND"} creates an invite whose metadata.appGrants matches the table above.

TS-2 — Airlock archetype parity (airlock-side, 0.5d)

Why: Airlock’s tier ladder must align with CASA archetypes so cross-apex behaviour is deterministic.
  • airlock/src/lib/invite-archetypes.ts — mirror of TS-1 map (tier + relationshipType)
  • On invite acceptance, if incoming metadata.archetypeId is set, force organization_members.tier to the mapped value
  • Extend /api/admin/app-chain-status (shipped 2026-04-21) to also report archetypeDrift — apps whose allowedRoles don’t match what any archetype grants
Acceptance: Running chain-status after TS-1 seed reports zero drift; manually corrupting seeds surfaces a drift row on HATCH.

TS-3 — Playwright harness at repo root (infra, 1d)

Why: Auth flows span submodules; the test harness can’t live inside any one of them.
  • tests/auth-e2e/ (new top-level, pattern sibling to existing tests/auth-contract/)
  • playwright.config.ts — projects per archetype (AM-GUEST, AM-FRIEND, AM-CONTRIB, AM-FAMILY), targets resolvable per env (TARGET_ENV=staging|preview|prod)
  • Fixtures:
    • inviteFactory(archetypeId) — hits airlock CLI / CASA admin API with an ops-scope token, returns {inviteUrl, expectedGrants}
    • acceptInvite(page, inviteUrl, creds) — drives browser through /invite/[token] → signup → redirect
    • assertCrossApexAccess(page, expectedGrants) — visits each app in expectedGrants, asserts 200; visits one app not in grants, asserts denied
  • Spec per archetype: invite-{archetype}.spec.ts — full flow + negative assertions
  • Test user pool: seed 4 reusable test accounts (one per archetype) in airlock stratt-hq-outposts.ts-style seed, creds in GitHub secrets
Acceptance: pnpm -C tests/auth-e2e test against staging passes all four specs; deleting an allowedRoles entry makes the negative assertion flip and the spec fails loudly.

TS-4 — CI workflow + structured result feed (infra-ci, 0.5d)

Why: ARES needs machine-readable output; humans need Allure.
  • infra-ci/.github/workflows/ci-auth-e2e.yml — reusable, inputs: target_env, archetypes (comma-list, default all). Outputs Playwright JSON reporter + Allure.
  • Publish two artifacts per run:
    • auth-e2e-results.json — slim schema: {runId, commit, timestamp, archetype, status, durationMs, failureReason?, traceUrl?}[]
    • Allure HTML → cicd.devarno.cloud/auth-e2e/ (reuse ares/verify.yml pattern)
  • Schedule: cron nightly against prod + on every PR touching family-hub|airlock|hatch|hubble|pebble|landing|ares|manual against staging
Acceptance: A failed run’s auth-e2e-results.json contains a parseable failure row with traceUrl pointing at the uploaded Playwright trace. Why (best-practice recommendation): An inline dashboard widget (Option A) buries auth under DORA/reconciliation. A new top-level /verification route (Option B) mirrors how mission control treats pre-flight checks — separable, history-aware, and linkable from incident reports. This matches ARES’ existing OPERATIONS grouping semantics (incidents, metrics, reports, history) — verification is operational, not just diagnostic. Add an auxiliary tile on / that summarises status and deep-links into /verification; that way the dashboard stays lean but status is visible on landing.
  • Sidebar: add { href: "/verification", label: "Auth Verification", icon: ShieldCheckIcon, section: "operations" } in ares/dashboard/src/components/layout/sidebar.tsx
  • New route /verification:
    • Top strip: four archetype cards (AM-GUEST, AM-FRIEND, AM-CONTRIB, AM-FAMILY) with pass/fail + last-run timestamp + drift count from /api/admin/app-chain-status
    • Table below: last 30 runs, expandable row reveals step-by-step (invite-create → signup → handoff → grant-check → negative-check) with trace link
    • Matrix view: archetype × app grid, cell = last verification status
  • Data: new endpoint ares/api/app/routers/auth_verification.pyGET /api/v1/auth/e2e/runs, GET /api/v1/auth/e2e/matrix
    • Ingests auth-e2e-results.json artifacts via GitHub Actions API (extend ares/dashboard/src/lib/api/github.ts with artifact-download)
    • Caches in Postgres table auth_e2e_runs (migrate via existing ARES migration pattern)
  • Dashboard tile: ares/dashboard/src/components/widgets/auth-verification-tile.tsx on / — compact 4-dot status + link
  • React Query hook: use-auth-e2e-runs.ts pattern-matched to use-ares-dora.ts
Acceptance: With CI green, /verification shows 4 green archetype cards + matrix all-green. Break an allowedRoles entry → next scheduled run flips one cell red → ARES reflects within 2 minutes of artifact upload.

TS-6 — Traceability doc in manual (0.5d)

Why: Auditors (and future-me) need one place that maps archetype → spec file → last-run.
  • manual/src/content/docs/runbooks/auth-e2e-traceability.mdx
  • Static table: archetype → spec path → CI job → ARES matrix cell
  • Embedded live status via iframe or MDX component pulling from ARES JSON endpoint
  • Supersede scattered sections in airlock-integration.mdx (cross-link only)
Acceptance: From traceability doc, two clicks to reach the Playwright trace of the last failing run for any archetype.

TS-7 — Convert hubble/pebble/ares to live CASA ecosystem endpoint (carry-over from 2026-04-21, 0.5d)

Why: Deferred from last session. Listed here so the plan captures all you asked for, but it’s orthogonal to auth-e2e and can run in parallel.
  • Replace hard-coded app lists in hubble/pebble/ares landing components with fetches to GET /api/ecosystem/apps on family-hub
  • Pattern already proven on airlock landing (2026-04-21)

TS-8 — Per-apex diagnose probe from HATCH (carry-over, 1d)

Why: Also deferred. Closes the chain-integrity loop by letting HATCH actively test an apex rather than just reconcile two registries.
  • HATCH button Diagnose per consumer row → calls airlock/api/admin/diagnose?apex=X
  • Airlock performs: (a) resolve consumer, (b) probe /api/auth/validate, (c) dry-run handoff token, (d) fetch consumer’s declared scopes
  • Security gate: outbound HTTP from airlock admin context only, allow-list = registered consumers, no open-redirect vectors, 5s timeout, rate-limited per apex
  • Render step-by-step result on HATCH row

Sequencing + effort

Day 1: TS-1 ──┐
Day 1: TS-2 ──┴→ TS-3 (Day 2) → TS-4 (Day 3 AM)
                                    └→ TS-5 (Days 3–4)
                                    └→ TS-6 (Day 5 AM)
Parallel track: TS-7 (Day 1 PM), TS-8 (Day 4, gated on security review)
Total: ~5 working days for TS-1 through TS-6 (the core auth-traceability ask). TS-7/TS-8 add ~1.5 days in parallel.

Non-goals for this phase

  • Multi-factor / passkey coverage — add archetype AM-FAMILY+2FA in a follow-up once 2FA lands in airlock
  • Social OAuth provider regression — separate campaign; harness supports it but specs not included here
  • Load testing — orthogonal

Risks

  1. Test user pollution: running nightly against prod creates account churn. Mitigation: dedicated @e2e.devarno.cloud subdomain for test inboxes, nightly teardown script.
  2. Invite token TTL (7d): if a scheduled run reuses an invite past expiry, false-negative. Mitigation: every run creates a fresh invite in inviteFactory.
  3. Archetype drift between CASA and airlock: if one side ships a new tier/role and the other doesn’t, silent breakage. Mitigation: TS-2’s archetypeDrift check in chain-status fails CI.