auth-yes/docs/TIER1_INGRESS_SPEC.md
google-labs-jules[bot] 2ac6252bff feat(auth-api): implement Tier 1 Traefik Ingress Control & Bypass Matrix
- Add idempotent migrations for `is_public`, `bypass_paths`, and `allowed_cidrs` in `server/db.ts`.
- Update `AppRecord` and `getAppByHost` in `server/auth-session.ts` to cache bypass rules in Valkey.
- Implement native Deno, fast-path prefix (`isPathBypassed`) and CIDR matchers (`isIpAllowed`).
- Update `GET /api/forward-auth` to evaluate dynamic rules and properly return 302/403 for unregistered domains.
- Create `ui/components/UnregisteredAppPage.tsx` SSR view for browser fallbacks.
- Update `AdminAppsPage.tsx` to handle the new ingress settings visually and post to `/api/admin/apps`.
- Add `POST /api/guests/sandbox` to generate ephemeral Valkey guest sessions.
- Update `POST /api/register/verify` to detect `upgrade_session` and promote guests to full users in-flight.
- Add `docs/TIER1_INGRESS_SPEC.md`.
- Ensure tests run cleanly and add comprehensive unit test cases for the bypass matrix.

Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
2026-08-24 22:08:43 +00:00

92 lines
3.4 KiB
Markdown

# Tier 1 Universal Global Edge Ingress Protection Specification
**Specification ID:** RFC-SPEC-2026-INGRESS-01 **Classification:** Ingress
Security & Traefik Routing **Status:** Canonical / Implemented
---
## 1. Executive Summary
This specification outlines the Tier 1 Ingress Control strategy using Traefik's
`ForwardAuth` middleware combined with a dynamic Valkey-backed authorization
matrix within `auth-api`. The system provides highly performant (microsecond
latency) dynamic bypasses, strict SSR unregistered fallbacks, and router-level
self-exemptions.
---
## 2. Traefik Entrypoint Configuration
To enforce zero-trust global edge protection, the `ForwardAuth` middleware is
bound directly to the global HTTPS entrypoint. This ensures that _every_ service
routed through Traefik is automatically intercepted without relying on
developers to attach middleware to individual container labels.
### Global ForwardAuth Middleware
```yaml
# infra/compose.yml snippet (Traefik labels)
services:
traefik:
labels:
- "traefik.http.middlewares.auth-forward.forwardauth.address=http://auth-api:3000/api/forward-auth"
- "traefik.http.middlewares.auth-forward.forwardauth.trustForwardHeader=true"
- "traefik.http.middlewares.auth-forward.forwardauth.authResponseHeaders=X-Forwarded-User,X-Forwarded-User-Id,X-Forwarded-Scopes,X-Forwarded-App-Id"
```
---
## 3. Router-Level Self-Exemptions
Applying ForwardAuth globally creates an infinite redirect deadlock if
`auth-api` intercepts requests destined for its own login mechanisms. To resolve
this, explicit routes must be exempted at the Traefik router level by
intentionally _not_ attaching the `auth-forward` middleware or configuring a
bypass.
### Required Exemptions
1. **Authentication API / UI (`auth.atyg.org`)**
- The central Identity Provider must be explicitly bypassed.
2. **ACME Challenge (`/.well-known/acme-challenge/*`)**
- Let's Encrypt automated HTTP-01 certificate renewals must proceed
unauthenticated.
3. **Global Health Checks (`/healthz`)**
- Orchestration systems must be able to verify container readiness.
---
## 4. Auth-API Dynamic Bypass Rules
Instead of volatile Traefik HTTP Dynamic Providers, Auth-Yes maintains a
highly-performant cache in Valkey (L1/L2) under the key
`auth:app_by_host:<host>`. When a request arrives at `/api/forward-auth`, the
gateway evaluates the following dynamic properties before validating sessions:
1. **`is_public` (Boolean)**
- If true, the entire application domain bypasses session checks.
2. **`bypass_paths` (List of Strings)**
- Fast deterministic prefix matching (`/api/public/*`) and exact matching
(`/webhook`).
3. **`allowed_cidrs` (List of Strings)**
- Fast native Deno IPv4 subnet matching to allowlist specific networks (e.g.,
internal CI/CD).
If any of the above rules evaluate to true, `auth-api` immediately returns
`200 OK` (with `X-Forwarded-App-Id` injected).
---
## 5. Unregistered Application Protocol
If a domain is not registered in the central `apps` table (and therefore not in
the Valkey cache), `auth-api` strictly denies the request.
- **Browser Access (`Accept: text/html`):** The proxy returns an HTTP
`302 Redirect` to `https://auth.atyg.org/errors/unregistered?host=<domain>`.
- **API Access (Non-HTML):** The proxy returns an HTTP `403 Forbidden`
(`{"error": "Application not registered"}`).
This mechanism explicitly prevents open-redirect and infrastructure mapping
attacks.