docs(tasks): standardize and upgrade Task 4.1 and Task 4.2 to 100% rubric compliance

This commit is contained in:
Tyler Gillispie 2026-08-24 14:15:38 -07:00
parent 443df1c2ce
commit cd1d866077
3 changed files with 257 additions and 150 deletions

View File

@ -1,9 +1,16 @@
# TASK METADATA # TASK METADATA
- **Target Files:** `COMPOSE_CONVENTIONS.md`, `server/main.ts`, `server/auth-session.ts`, `server/db.ts` - **Target Files:** `server/db.ts`, `server/auth-session.ts`, `server/main.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. `server/main.test.ts`, `ui/components/AdminAppsPage.tsx`, `ui/mod.ts`,
- **Dependencies:** Database schema update for `apps` table (`is_public`, `bypass_paths`). `infra/setup.ts`, `docs/TIER1_INGRESS_SPEC.md`
- **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. - **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 ### 2. Architectural Considerations & Risks
- **Risks:** - **Risks & Vulnerabilities:**
- **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. - **Recursive Deadlocks (Self-Exemption):** Applying ForwardAuth globally at
- **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. `entryPoints.websecure.http.middlewares` creates an infinite loop if
- **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. `auth-api` intercepts its own login/verification endpoints. `auth.atyg.org`
- **Alternatives & Architectural Decisions:** and `/.well-known/acme-challenge/*` must be explicitly exempt.
- **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. - **Edge Latency Regressions:** Querying PostgreSQL on every incoming
- **Universal Bypasses (Hybrid Approach):** ForwardAuth request for dynamic bypass rules would bottleneck cluster
- Critical infrastructural paths (`/.well-known/acme-challenge/*`, `/healthz`) bypass ForwardAuth directly at the Traefik router level to prevent lockout during restarts. throughput. All `is_public`, `bypass_paths`, and `allowed_cidrs` fields must
- Semantic app paths (`/api/public/*`, `/webhooks/*`) and CIDR allowlists are evaluated within `auth-api` for centralized auditing and hot-reloading. be cached inside the Valkey `auth:app_by_host:<host>` key.
- **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. - **ReDoS in Path Matching:** Evaluating wildcard bypasses using unconstrained
- **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. 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 ### 3. Proposed Implementation
1. **Global Default-Deny Configuration:** #### Phase 1: Database Schema & Valkey Caching Upgrades
- 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`.
2. **Schema & Database Updates:** 1. **Database Migration (`server/db.ts`):**
- Add database migrations for the `apps` table: - Add idempotent migrations inside `initDb()`:
- `is_public` (boolean, default `false`) ```sql
- `bypass_paths` (text array, default `[]`) ALTER TABLE apps ADD COLUMN IF NOT EXISTS is_public BOOLEAN DEFAULT FALSE;
- `allowed_cidrs` (text array, default `[]`) 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:<host>` with
1-hour TTL.
3. **Valkey Caching Upgrades (`server/auth-session.ts`):** #### Phase 2: Dynamic Bypass Evaluator & ForwardAuth Hardening
- Update `getAppByHost` to SELECT and cache the new `is_public`, `bypass_paths`, and `allowed_cidrs` fields within the `auth:app_by_host:<host>` Valkey payload.
4. **Dynamic Bypass & Dual-Response Execution (`server/main.ts`):** 1. **Path & CIDR Matcher Helper (`server/auth-session.ts`):**
- In `GET /api/forward-auth`: - Implement
- **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`. `isPathBypassed(requestPath: string, bypassPaths: string[]): boolean` using
- **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. deterministic prefix matching (`path.startsWith(...)` and `/*` wildcard
- **Immediate Allowance:** If the request matches a bypass rule or is public, immediately return `200 OK` without querying `getAuthenticatedUser()`. 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:** #### Phase 3: Unregistered Application SSR Error Page & Admin UI
- 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`. 1. **Create SSR Error View (`ui/components/UnregisteredAppPage.tsx`):**
- 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. - 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-<id>", 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).

View File

@ -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.

View File

@ -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://<domain>`), 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`.