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 ID | Human label | CASA role | CASA appGrants | Airlock tier | relationshipType | Intended use |
|---|---|---|---|---|---|---|
AM-GUEST | Guest tester | member | [landing, manual] | ORBITER | community | Share a demo link with a stranger |
AM-FRIEND | Friend tester | member | [landing, manual, pebble-public, hubble-readonly] | LANDER | community | ”Remember me from before? Try this” |
AM-CONTRIB | Contributor | member | [hatch, hubble, ares, pebble, manual] | BEACON | collaborator | Trusted external helper |
AM-FAMILY | Family / core | admin | [*] | CORE | team | Sibling, co-owner — full CASA admin |
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 againstEcosystemApp[]- Migrate
metadata.appGrantspopulation to derive fromarchetypeIdwhen present (backwards-compatible: directappGrantsstill wins) - Extend
POST /api/admin/invitationsbody 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
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.archetypeIdis set, forceorganization_members.tierto the mapped value - Extend
/api/admin/app-chain-status(shipped 2026-04-21) to also reportarchetypeDrift— apps whoseallowedRolesdon’t match what any archetype grants
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 existingtests/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 → redirectassertCrossApexAccess(page, expectedGrants)— visits each app inexpectedGrants, 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
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|manualagainst staging
auth-e2e-results.json contains a parseable failure row with traceUrl pointing at the uploaded Playwright trace.
TS-5 — ARES /verification surface (2d) — recommended placement
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" }inares/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
- Top strip: four archetype cards (
- Data: new endpoint
ares/api/app/routers/auth_verification.py→GET /api/v1/auth/e2e/runs,GET /api/v1/auth/e2e/matrix- Ingests
auth-e2e-results.jsonartifacts via GitHub Actions API (extendares/dashboard/src/lib/api/github.tswith artifact-download) - Caches in Postgres table
auth_e2e_runs(migrate via existing ARES migration pattern)
- Ingests
- Dashboard tile:
ares/dashboard/src/components/widgets/auth-verification-tile.tsxon/— compact 4-dot status + link - React Query hook:
use-auth-e2e-runs.tspattern-matched touse-ares-dora.ts
/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)
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/appson 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
Diagnoseper consumer row → callsairlock/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
Non-goals for this phase
- Multi-factor / passkey coverage — add archetype
AM-FAMILY+2FAin 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
- Test user pollution: running nightly against prod creates account churn. Mitigation: dedicated
@e2e.devarno.cloudsubdomain for test inboxes, nightly teardown script. - Invite token TTL (7d): if a scheduled run reuses an invite past expiry, false-negative. Mitigation: every run creates a fresh invite in
inviteFactory. - 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
archetypeDriftcheck in chain-status fails CI.