From cd1d8660771c6f55683996f7a92084c0e8c5e6ab Mon Sep 17 00:00:00 2001 From: Tyler Gillispie Date: Mon, 24 Aug 2026 14:15:38 -0700 Subject: [PATCH] docs(tasks): standardize and upgrade Task 4.1 and Task 4.2 to 100% rubric compliance --- ...t.auth-api.traefik-ingress-control-2105.md | 162 ++++++++++++++---- ...launchpad.sso-launchpad-and-logout-2100.md | 115 ------------- ...launchpad.sso-launchpad-and-logout-2100.md | 130 ++++++++++++++ 3 files changed, 257 insertions(+), 150 deletions(-) delete mode 100644 tasks/new/2026-0824.01.jul.story.app-launchpad.sso-launchpad-and-logout-2100.md create mode 100644 tasks/new/2026-0824.02.jul.story.app-launchpad.sso-launchpad-and-logout-2100.md diff --git a/tasks/new/2026-0824.01.jul.feat.auth-api.traefik-ingress-control-2105.md b/tasks/new/2026-0824.01.jul.feat.auth-api.traefik-ingress-control-2105.md index a618396..463bce2 100644 --- a/tasks/new/2026-0824.01.jul.feat.auth-api.traefik-ingress-control-2105.md +++ b/tasks/new/2026-0824.01.jul.feat.auth-api.traefik-ingress-control-2105.md @@ -1,9 +1,16 @@ # TASK METADATA -- **Target Files:** `COMPOSE_CONVENTIONS.md`, `server/main.ts`, `server/auth-session.ts`, `server/db.ts` -- **Core Objective:** Architect and formalize the Tier 1 Universal Global Edge Ingress Protection protocol for Traefik to enforce default-deny while supporting a dynamic, multi-tier bypass and guest sandbox matrix. -- **Dependencies:** Database schema update for `apps` table (`is_public`, `bypass_paths`). -- **Additional Important Notes:** Must align closely with `docs/FORWARDAUTH_REDIRECT_SPEC.md` for dual-response handling and rely entirely on Valkey L1/L2 caching to maintain sub-millisecond edge latency for dynamic routing decisions. +- **Target Files:** `server/db.ts`, `server/auth-session.ts`, `server/main.ts`, + `server/main.test.ts`, `ui/components/AdminAppsPage.tsx`, `ui/mod.ts`, + `infra/setup.ts`, `docs/TIER1_INGRESS_SPEC.md` +- **Core Objective:** Implement Tier 1 Universal Global Edge Ingress Protection + on Traefik with dynamic Valkey-cached bypass matrix, self-exemption, CIDR + allowlisting, unregistered app SSR fallback, and ephemeral guest sandboxes. +- **Dependencies:** PostgreSQL `apps` schema, Valkey 8 cache, + `docs/FORWARDAUTH_REDIRECT_SPEC.md`. +- **Additional Important Notes:** Must guarantee $<30\mu s$ edge lookups via + Valkey L1/L2 caching and prevent infinite redirect deadlocks on `auth-api` and + ACME challenge routers. --- @@ -13,41 +20,126 @@ ### 2. Architectural Considerations & Risks -- **Risks:** - - **Recursive Deadlocks (Self-Exemption):** Applying ForwardAuth globally introduces the risk of `auth-api` protecting itself, leading to an infinite authentication loop where users cannot reach the login page to authenticate. `auth-api` must be explicitly exempted. - - **Health Probe Failures:** Traefik and orchestrator liveness/readiness probes (e.g., `/healthz`) might be blocked if they fall under the global ForwardAuth middleware, causing rolling restart failures. - - **Latency Regressions:** If `auth-api` queries PostgreSQL on every request to evaluate dynamic bypass paths (`is_public`, `bypass_paths`, or CIDRs), performance will tank. We must guarantee this data is piggybacked onto the existing Valkey app caching flow. -- **Alternatives & Architectural Decisions:** - - **Dynamic Bypass Matrix:** Evaluated inside `auth-api` with Valkey L1/L2 caching instead of dynamic Traefik HTTP providers to avoid sync overhead and polling complexity. - - **Universal Bypasses (Hybrid Approach):** - - Critical infrastructural paths (`/.well-known/acme-challenge/*`, `/healthz`) bypass ForwardAuth directly at the Traefik router level to prevent lockout during restarts. - - Semantic app paths (`/api/public/*`, `/webhooks/*`) and CIDR allowlists are evaluated within `auth-api` for centralized auditing and hot-reloading. - - **Unregistered App Handling:** Adheres to the Dual-Response protocol. Web browsers receive a `302 Redirect` to a polished Hono SSR error page (`/errors/unregistered`), while API/cURL clients receive a fast `403 Forbidden` response. - - **Guest Sandboxes:** Handled natively via a Valkey ephemeral session with an `account_status: "guest"` and `X-Forwarded-Scopes: guest,trial`. Seamless in-flight passkey promotion transitions them to full users. +- **Risks & Vulnerabilities:** + - **Recursive Deadlocks (Self-Exemption):** Applying ForwardAuth globally at + `entryPoints.websecure.http.middlewares` creates an infinite loop if + `auth-api` intercepts its own login/verification endpoints. `auth.atyg.org` + and `/.well-known/acme-challenge/*` must be explicitly exempt. + - **Edge Latency Regressions:** Querying PostgreSQL on every incoming + ForwardAuth request for dynamic bypass rules would bottleneck cluster + throughput. All `is_public`, `bypass_paths`, and `allowed_cidrs` fields must + be cached inside the Valkey `auth:app_by_host:` key. + - **ReDoS in Path Matching:** Evaluating wildcard bypasses using unconstrained + regular expressions could allow malicious paths to trigger catastrophic + backtracking. Path matching must use fast, deterministic prefix and glob + matching. + - **Open Redirects on Unregistered Apps:** When routing unregistered domains + to SSR error views, destination parameters must be strictly validated + against approved hosts to prevent phishing vectors. + +- **Alternatives & Architecture Decisions:** + - **Valkey App Caching over Traefik HTTP Dynamic Provider:** Evaluating + dynamic bypass paths inside `auth-api` via Valkey caches eliminates Traefik + config file churn, provider polling overhead, and proxy reload downtime. + - **Defense-in-Depth Universal Bypasses:** + - _Traefik Level:_ `/.well-known/acme-challenge/*` and global `/healthz` + bypass ForwardAuth entirely at the edge router level to avoid certificate + renewal failures during container restarts. + - _Auth-API Level:_ Application-specific paths (`/api/public/*`, + `raw/branch/main/sdk/*`, `/webhooks/*`) and CIDR subnets are evaluated in + `auth-api` with zero network overhead. + - **Dual-Response Protocol Compliance:** Unregistered domains receive an HTTP + `302 Redirect` to `https://auth.atyg.org/errors/unregistered?host=...` for + browsers (`Accept: text/html`) and a clean HTTP `403 Forbidden` + (`{"error": "Application not registered"}`) for APIs/cURL. + - **Ephemeral Guest Sandboxes (Use Case 11):** Ephemeral sessions are held in + Valkey with `account_status: "guest"` and promoted in-flight to full users + upon passkey enrollment without losing UUID or state. ### 3. Proposed Implementation -1. **Global Default-Deny Configuration:** - - Document how Traefik's `entryPoints.websecure.http.middlewares` should be updated to universally apply the `auth-forward@docker` middleware. - - Define the explicit router priority and empty middleware override required for `auth-api` and ACME challenge routers to guarantee self-exemption. - - Define the mechanism for explicit host-level application bypass where fully public applications (e.g. landing pages, sandboxes) can use specific Docker labels (like `traefik.http.routers.app.middlewares=`) to bypass ForwardAuth entirely at the edge without traversing to `auth-api`. +#### Phase 1: Database Schema & Valkey Caching Upgrades -2. **Schema & Database Updates:** - - Add database migrations for the `apps` table: - - `is_public` (boolean, default `false`) - - `bypass_paths` (text array, default `[]`) - - `allowed_cidrs` (text array, default `[]`) +1. **Database Migration (`server/db.ts`):** + - Add idempotent migrations inside `initDb()`: + ```sql + ALTER TABLE apps ADD COLUMN IF NOT EXISTS is_public BOOLEAN DEFAULT FALSE; + ALTER TABLE apps ADD COLUMN IF NOT EXISTS bypass_paths TEXT[] DEFAULT '{}'; + ALTER TABLE apps ADD COLUMN IF NOT EXISTS allowed_cidrs TEXT[] DEFAULT '{}'; + ``` +2. **Valkey App Cache Hydration (`server/auth-session.ts`):** + - Update `getAppByHost(host)` to select + `id, name, domain, is_public, bypass_paths, allowed_cidrs`. + - Cache the complete application metadata in `auth:app_by_host:` with + 1-hour TTL. -3. **Valkey Caching Upgrades (`server/auth-session.ts`):** - - Update `getAppByHost` to SELECT and cache the new `is_public`, `bypass_paths`, and `allowed_cidrs` fields within the `auth:app_by_host:` Valkey payload. +#### Phase 2: Dynamic Bypass Evaluator & ForwardAuth Hardening -4. **Dynamic Bypass & Dual-Response Execution (`server/main.ts`):** - - In `GET /api/forward-auth`: - - **Unregistered App Handling:** If `getAppByHost` returns null, evaluate the `Accept` header. Issue a `302 Redirect` to `https://auth.atyg.org/errors/unregistered?host=...` if it contains `text/html`, otherwise return `403 Forbidden`. - - **Path & CIDR Exemption Check:** Before checking for a valid session, evaluate the requested URI (`X-Forwarded-Uri`) and Client IP against the cached `bypass_paths`, `allowed_cidrs`, and `is_public` flags. - - **Immediate Allowance:** If the request matches a bypass rule or is public, immediately return `200 OK` without querying `getAuthenticatedUser()`. +1. **Path & CIDR Matcher Helper (`server/auth-session.ts`):** + - Implement + `isPathBypassed(requestPath: string, bypassPaths: string[]): boolean` using + deterministic prefix matching (`path.startsWith(...)` and `/*` wildcard + support). + - Implement `isIpAllowed(clientIp: string, allowedCidrs: string[]): boolean` + for subnet validation. +2. **Update `GET /api/forward-auth` (`server/main.ts`):** + - **Step 1: Unregistered App Check:** If `appRecord` is null: + - If `Accept: text/html`: Return `302 Redirect` to + `https://${loginDomain}/errors/unregistered?host=${encodeURIComponent(host)}`. + - Else: Return `403 Forbidden` (`{"error": "Application not registered"}`). + - **Step 2: Dynamic Bypass Check:** + - If `appRecord.is_public === true`, or + `isPathBypassed(uri, appRecord.bypass_paths)`, or + `isIpAllowed(clientIp, appRecord.allowed_cidrs)`: + - Immediately return `200 OK` (bypassing session checks). + - **Step 3: RFC 9421 & Session Checks:** Proceed with existing HTTP + Signatures and WebAuthn session validation. -5. **Ephemeral Guest Session Generation:** - - Expose a new endpoint (e.g., `/api/guests/sandbox`) that provisions a Valkey session ID without requiring PostgreSQL insertion. - - Attach `account_status: "guest"` to the Valkey payload and map the corresponding `X-Forwarded-Scopes`. - - Update the `/api/passkeys/register/verify` flow to detect `upgrade_session` and persist the guest's UUID and session context to the `users` table upon successful passkey verification. +#### Phase 3: Unregistered Application SSR Error Page & Admin UI + +1. **Create SSR Error View (`ui/components/UnregisteredAppPage.tsx`):** + - Pure Hono SSR JSX page explaining the domain is not registered in the + Auth-Yes catalog, with a direct 1-click button for Global Admins: + _"Register Application in IAM Console"_. +2. **Update Route in `ui/mod.ts`:** + - Mount `GET /errors/unregistered` rendering `UnregisteredAppPage`. +3. **Management Console Updates (`ui/components/AdminAppsPage.tsx` & + `server/main.ts`):** + - Expose `is_public`, `bypass_paths`, and `allowed_cidrs` in + `POST /api/admin/apps` and `PUT /api/admin/apps/:id`. + - Add toggle switches and input fields to the Admin Web UI. + +#### Phase 4: Ephemeral Guest Sandboxes (Use Case 11) + +1. **Guest Endpoint (`server/main.ts`):** + - `POST /api/guests/sandbox`: Generates a guest `sessionId`, stores + `{ uuid: guestUuid, username: "guest-", account_status: "guest" }` in + Valkey with 2-hour TTL, and returns the session cookie. +2. **In-Flight Passkey Promotion (`server/main.ts`):** + - Update `/api/register/verify` to detect `upgrade_session` parameter, + creating the PostgreSQL user with the existing `guestUuid` and changing + status to `active`. + +#### Phase 5: Documentation & Traefik Compose Guides + +1. **Author `docs/TIER1_INGRESS_SPEC.md`:** + - Document static/dynamic Traefik configurations for + `entryPoints.websecure.http.middlewares=auth-forward@docker` with + router-level self-exemption overrides for `auth.atyg.org`. + +### 4. Testing & Verification Matrix + +- [ ] **Unit Tests (`server/main.test.ts`):** + - Verify `GET /api/forward-auth` returns `200 OK` when + `appRecord.is_public === true`. + - Verify `GET /api/forward-auth` returns `200 OK` for paths matching + `bypass_paths` (e.g. `/api/public/ping`). + - Verify `GET /api/forward-auth` returns `302 Redirect` to + `/errors/unregistered` for unauthenticated browser requests to unregistered + domains. + - Verify `GET /api/forward-auth` returns `403 Forbidden` for API requests to + unregistered domains. + - Verify guest session generation and in-flight passkey promotion. +- [ ] **Quality Gates:** + - `deno fmt`, `deno task lint`, `deno task check`, `deno task test` (100% + pass). diff --git a/tasks/new/2026-0824.01.jul.story.app-launchpad.sso-launchpad-and-logout-2100.md b/tasks/new/2026-0824.01.jul.story.app-launchpad.sso-launchpad-and-logout-2100.md deleted file mode 100644 index 5794f4d..0000000 --- a/tasks/new/2026-0824.01.jul.story.app-launchpad.sso-launchpad-and-logout-2100.md +++ /dev/null @@ -1,115 +0,0 @@ -# TASK METADATA - -- **Target Files:** `ui/mod.ts`, `ui/components/AppLaunchpadPage.tsx`, - `ui/components/AuthenticatedLayout.tsx`, `server/main.test.ts`, - `docs/HYBRID_INGRESS_PLAYBOOK.md` -- **Core Objective:** Architect and formalize the specification and - implementation plan for Universal Logout Return-Path Preservation, Central SSO - Application Launchpad, Hybrid Ingress Routing Playbook, and Strict Additive - Security Audit. -- **Dependencies:** Existing UI layout system, - `docs/FORWARDAUTH_REDIRECT_SPEC.md`, `server/auth-session.ts`, Merkle Tree - Audit Ledger. -- **Additional Important Notes:** Must adhere strictly to Zero-Trust - invisibility for ungranted apps. Must maintain 100% test coverage and ensure - zero regressions across WebAuthn, SSS, and RFC 9421. - ---- - -## 2. Architectural Considerations & Risks - -Before detailing implementation steps, the following risks and constraints must -be strictly adhered to: - -- **Risks:** - - **Open-Redirect Vulnerability (CWE-601):** The `/logout?redirect=` endpoint - is a prime target for phishing if not strictly validated against an approved - whitelist. - - **RBAC Data Leakage:** Exposing ungranted applications, even visually - disabled, leaks internal network topology and service architecture. - - **Regression of Cryptographic Core:** Modifying session lifecycle hooks - (like logout) must not break the Merkle Tree Audit Ledger, WebAuthn PRF - flows, or Edge Signatures. - -- **Alternatives & Architecture Decisions:** - - **Redirect Validation:** We will strictly implement the `isSafeRedirectUrl` - logic defined in `docs/FORWARDAUTH_REDIRECT_SPEC.md` (`*.atyg.org`, - `localhost`, relative paths) for both login and logout flows. - - **Zero-Knowledge Launchpad:** Regular users will only see applications they - have explicit grants for. Global Admins (`isGlobalAdmin = true`) will see - all fleet applications. - - **Cryptographic Auditing:** Explicit audit events (`logout_success`, - `open_redirect_intercepted`) will be injected directly into the RFC 6962 - Merkle tree upon logout operations. - -## 3. Proposed Implementation - -The implementation must be executed in the following strict phases: - -### Phase 1: Logout Return-Path Preservation (`GET /logout`) - -1. **Update `ui/mod.ts`:** - - Extract the `redirect` query parameter in the `GET /logout` handler. - - Implement strict whitelist validation (`isSafeRedirectUrl`): - - Must allow relative paths (`/`). - - Must allow explicit wildcard `*.atyg.org` or `localhost`. - - **Audit Integration:** - - If validation fails, immediately log an `open_redirect_intercepted` event - to the Merkle Audit Ledger (including client IP, original requested URL, - and blocked destination), then discard the parameter. - - Upon successful session destruction (cache + DB wipe), log a - `logout_success` audit event. - - Redirect the user to `/login?redirect=${encodeURIComponent(safeRedirect)}` - (if a safe redirect exists), otherwise fallback to `/login`. - -### Phase 2: Central SSO Application Launchpad (App Switcher) - -1. **Create `ui/components/AppLaunchpadPage.tsx`:** - - Build a pure Hono SSR JSX component rendering interactive application - cards. - - Each card must display the app name, description, role indicator (e.g., - `Admin`, `Operator`), and a 1-click launch link. -2. **Update Route `GET /dashboard` in `ui/mod.ts`:** - - Change the default `/dashboard` redirect to render `AppLaunchpadPage`. - - Update navigation in `ui/components/AuthenticatedLayout.tsx` to include the - new Launchpad as the primary dashboard view. -3. **Zero-Trust Query Logic:** - - Fetch the authenticated user and their `isGlobalAdmin` status. - - **Regular Users:** Query `grants` JOIN `apps` to fetch strictly only the - applications they possess an active grant for. - - **Global Admins:** Query `apps` to fetch all applications, annotating them - with an `[Admin]` badge and providing a direct link to the IAM Management - Console. - -### Phase 3: Hybrid Ingress Routing Pattern & Playbook - -1. **Document `docs/HYBRID_INGRESS_PLAYBOOK.md`:** - - Provide concrete reference configurations for consumer web applications - requiring hybrid public splash views alongside protected private cockpits. - - Detail the dual-routing pattern: Traefik edge ForwardAuth protection for - `/control-panel`, `/ws`, `/api/*` + App/SDK-level SSR hydration on the root - `/`. - -### Phase 4: Strict Additive Security & Regression Audit - -1. **Test Coverage Additions (`server/main.test.ts`):** - - Write tests validating the open-redirect whitelist logic in `/logout`. - - Write tests verifying Zero-Knowledge visibility of the Launchpad (users see - only granted apps, admins see all). - - Write tests verifying the new audit log events (`logout_success`, - `open_redirect_intercepted`) are correctly appended. -2. **Pre/Post Hermetic Test Mandate:** - - All 42+ existing unit tests in `server/*.test.ts` and `sdk/*.test.ts` MUST - pass hermetically before and after modifications. -3. **End-to-End QA Checklist (To be included in Completion Report):** - - [ ] Verify WebAuthn PRF extension negotiation (`/api/login/challenge` & - `/api/register/verify`). - - [ ] Verify 2-of-3 SSS Wasm memory zeroization and key reconstruction - (Scenario A & Scenario B). - - [ ] Verify RFC 9421 Ed25519 signature verification against the O(1) Valkey - fingerprint set. -4. **Coverage Validation Requirement:** - - Run the following command before final submission: - `deno test -A --unstable-ffi --coverage=cov_profile && deno coverage cov_profile` - - Include the generated coverage table in the PR description / final - completion summary. diff --git a/tasks/new/2026-0824.02.jul.story.app-launchpad.sso-launchpad-and-logout-2100.md b/tasks/new/2026-0824.02.jul.story.app-launchpad.sso-launchpad-and-logout-2100.md new file mode 100644 index 0000000..888051d --- /dev/null +++ b/tasks/new/2026-0824.02.jul.story.app-launchpad.sso-launchpad-and-logout-2100.md @@ -0,0 +1,130 @@ +# TASK METADATA + +- **Target Files:** `ui/mod.ts`, `ui/components/AppLaunchpadPage.tsx`, + `ui/components/AuthenticatedLayout.tsx`, `server/audit.ts`, + `server/main.test.ts`, `docs/HYBRID_INGRESS_PLAYBOOK.md` +- **Core Objective:** Implement Central SSO Application Launchpad, Logout + Return-Path Preservation (`GET /logout?redirect=...`), SIEM Cryptographic + Merkle Auditing, and Hybrid Ingress Playbook. +- **Dependencies:** Pure Hono SSR JSX UI system, + `docs/FORWARDAUTH_REDIRECT_SPEC.md`, `server/auth-session.ts`, RFC 6962 Merkle + Audit Ledger. +- **Additional Important Notes:** Must adhere strictly to Zero-Trust + invisibility (regular users see only granted apps; Global Admins see all apps + with `[Admin]` badge). Must maintain 100% test coverage with zero regressions + across WebAuthn, SSS, and RFC 9421. + +--- + +### 1. TASK METADATA + +(Defined in the header block above) + +### 2. Architectural Considerations & Risks + +- **Risks & Vulnerabilities:** + - **Open-Redirect Attacks (CWE-601):** Unvalidated `?redirect=` parameters on + `GET /logout` present severe phishing attack vectors. All destination + targets must be strictly validated against the approved domain whitelist + (`*.atyg.org`, `localhost`, and relative paths). + - **RBAC Topology Leakage:** Displaying ungranted applications on the + Launchpad (even in a greyed-out or disabled state) leaks internal network + topology, microservice hostnames, and organizational tooling to unauthorized + users. Ungranted apps must be completely invisible to non-admin users. + - **Session Cookie Domain Duplication:** When logging out, failing to wipe + both host-scoped and parent wildcard (`.atyg.org`) cookies causes lingering + session collisions across subdomains. + - **Cryptographic Audit Gaps:** Failing to log intercepted open-redirect + attempts deprives security teams of automated anomaly detection during + phishing campaigns. + +- **Alternatives & Architecture Decisions:** + - **Zero-Knowledge Launchpad:** Regular users query `grants` JOIN `apps` to + view strictly their authorized services. Global Admins + (`isGlobalAdmin = true`) query `apps` to see all applications annotated with + an `[Admin]` badge and a 1-click link to the IAM Management Console. + - **Pure Hono SSR JSX Purity:** In strict adherence to `AGENTS.md`, + `AppLaunchpadPage.tsx` must be 100% React-free, utilizing lightweight pure + JSX templates and CSS grid layout matching `Layout.tsx`. + - **Cryptographic SIEM Auditing:** Explicit audit events (`logout_success`, + `open_redirect_intercepted`) are appended directly to the RFC 6962 Merkle + tree ledger and broadcast over Valkey channel `auth:audit:sth`. + +### 3. Proposed Implementation + +#### Phase 1: Logout Return-Path Preservation (`GET /logout`) + +1. **Update `GET /logout` Handler (`ui/mod.ts`):** + - Extract `redirect` query parameter from the request. + - Validate target using `isSafeRedirectUrl(redirect)` (allowing `*.atyg.org`, + `localhost`, and relative paths). + - **Audit Integration:** + - If validation fails, log `open_redirect_intercepted` to `audit_records` + (including client IP, raw URL, and discarded destination), then discard + the parameter. + - Upon session deletion in Valkey and PostgreSQL, log `logout_success`. + - Clear session cookies across both host and parent wildcard domain + (`getCookieDomain()`). + - If a valid `redirect` was supplied, redirect to + `/login?redirect=${encodeURIComponent(safeRedirect)}`, otherwise redirect + to `/login`. + +#### Phase 2: Central SSO Application Launchpad (App Switcher) + +1. **Create Launchpad Component (`ui/components/AppLaunchpadPage.tsx`):** + - Author a pure Hono SSR JSX page rendering responsive card tiles for + authorized applications. + - Each card displays app title, description, domain link + (`https://`), role badge (`Admin`, `Operator`, `Viewer`), and + 1-click "Launch" button. +2. **Mount Launchpad Route (`ui/mod.ts`):** + - Update `GET /dashboard` to render `AppLaunchpadPage` as the default + authenticated landing view. + - Update `ui/components/AuthenticatedLayout.tsx` navigation bar to feature + "Launchpad" alongside Sessions, Passkeys, and Admin Console. +3. **Zero-Trust Query Logic (`ui/mod.ts`):** + - Authenticate session via `getAuthenticatedUser(c)`. + - Check `isAdmin = await isGlobalAdmin(auth.userId)`. + - If `isAdmin`: Fetch all apps from `apps` table. + - Else: Fetch only apps where `grants.user_id = auth.userId`. + +#### Phase 3: Hybrid Ingress Routing Playbook + +1. **Author `docs/HYBRID_INGRESS_PLAYBOOK.md`:** + - Provide concrete reference architectures for consumer applications needing + hybrid public splash pages alongside protected private cockpits. + - Detail the dual-routing pattern: Traefik ForwardAuth on `/control-panel`, + `/ws`, `/api/*` + App/SDK-level SSR hydration on root `/`. + +#### Phase 4: Strict Additive Security & Regression Audit + +1. **Pre/Post Hermetic Test Suite Verification:** + - Execute all 42+ existing unit tests in `server/*.test.ts` and + `sdk/*.test.ts` to guarantee 0 regressions. +2. **New Unit Tests (`server/main.test.ts`):** + - Test `GET /logout` preserves valid `?redirect=https://ed-droid.atyg.org/` + and redirects to `/login?redirect=...`. + - Test `GET /logout` intercepts and discards malicious + `?redirect=https://evil.com`, logging `open_redirect_intercepted`. + - Test Launchpad Zero-Knowledge query logic (regular user sees only granted + apps; admin sees all). +3. **Manual End-to-End QA Checklist (Included in PR Summary):** + - [ ] WebAuthn PRF extension negotiation (`/api/login/challenge` & + `/api/register/verify`). + - [ ] 2-of-3 SSS Wasm memory zeroization and key reconstruction (Scenario A & + Scenario B). + - [ ] RFC 9421 Ed25519 signature verification against $O(1)$ Valkey + fingerprint set. +4. **Coverage Validation Requirement:** + - Run + `deno test -A --unstable-ffi --coverage=cov_profile && deno coverage cov_profile` + and attach the coverage report to the PR summary. + +--- + +### 4. Quality Gates & Verification Checklist + +- [ ] All 42+ unit tests passing hermetically. +- [ ] Zero lint warnings (`deno task lint`). +- [ ] Zero typecheck errors (`deno task check`). +- [ ] Code formatted with `deno fmt`.