# Hypermedia & Vertical Slicing Architecture Blueprint This document defines the architectural specification and plan of record for Auth-Yes's transition to a server-driven hypermedia paradigm (Datastar + Deno 2 + Hono SSR JSX) and vertical feature slicing. --- ## 1. System Architecture Overview ```mermaid graph TD subgraph Client ["Browser Client (Zero-Build)"] HTML["DOM (Morph Targets)"] Ignored["Vanilla Subtree (data-ignore)
[WebAuthn Ceremony & Copy Feedback]"] DS["Datastar Engine (~12kB Pinned)"] Sig["data-signals (Transient UI Toggles ONLY)"] end subgraph Security ["Ingress & Invariant Guards"] RL["Rate Limiter & 16KB Payload Cap"] CSRF["Origin / Sec-Fetch-Site Check"] CN["Content Negotiator (HTML vs JSON vs Shell)"] end subgraph Server ["Deno 2 + Hono SSR Engine"] subgraph Slices ["Vertical Feature Slices (src/features/)"] Sess["sessions/ (routes.ts, queries.ts, fragments.tsx)"] Evt["events/ (routes.ts, queries.ts, fragments.tsx)"] Adm["admin/ (routes.ts, queries.ts, fragments.tsx)"] end end subgraph Data ["Authoritative Data Layer (Zero Client Cache)"] PG[(PostgreSQL 18 - Authoritative State)] VK[(Valkey 8 - Pub/Sub & L1 Cache)] end HTML -->|data-on-click / data-on-submit| DS DS -->|Standard HTTP POST/PATCH with 16KB limit| RL RL --> CSRF --> CN CN -->|Browser Context| Slices Slices --> PG & VK Slices -->|Success 200: JSX View Fragment| HTML Slices -->|Failure 400/500: JSX Error Toast Fragment| HTML VK -.->|Targeted SSE Stream (Live Seats/Killswitch)| DS DS -.->|Morphs DOM, preserves data-ignore| HTML ``` --- ## 2. Core Architectural Standards #### Standard A: Dual-Transport & Right-Sized Delivery - **Mutations & User Interactions (`POST` / `PATCH`):** Return standard, stateless `text/html` JSX fragments. Zero long-lived connection overhead. - **Live Multi-User Broadcasts:** Targeted Server-Sent Events (SSE) bound to Valkey Pub/Sub with `X-Accel-Buffering: no` for real-time seat counts and remote session invalidation. - **Abstracted Protocol Strings:** SSE event formatting is strictly encapsulated in a typed adapter/SDK (`core/sse_adapter.ts`) rather than string-concatenation in route handlers. - **Headless Terminal & SDK Consumers:** Standard REST / ConnectRPC returning JSON/shell strings via `Content-Negotiation`. ### Standard B: Hypermedia Unhappy Path & Error Protocol - **Never return raw JSON errors to Datastar.** If a validation fails, a seat limit is exceeded, or an internal error occurs: - The server returns an HTTP 422/400/500 status with an **HTML error fragment** targeting `#field-error-${name}` or `#status-banner`. - Datastar morphs the error toast into place seamlessly without breaking the hypermedia loop. - **Mid-Stream Error Handling:** Because SSE streams open with `200 OK`, any error occurring after connection initialization cannot return a 500 status. The stream handler must yield an error toast fragment before cleanly closing the connection. ### Standard C: Signal Boundaries & The Durable State Invariant - **Authoritative Server Rule:** PostgreSQL and Valkey are the _only_ sources of truth. Datastar `data-signals` are strictly transient (e.g. `{ isDrawerOpen: false, activeTab: 'single' }`). - **Zero Secrets in Signals:** Never place session tokens, passkeys, or permission claims in client signals. ### Standard D: Vanilla DOM Isolation (`data-ignore`) - Any DOM element touched by browser-native micro-helpers (WebAuthn passkey ceremony indicators or clipboard feedback) MUST carry `data-ignore` or `data-ignore-morph`. Datastar will bypass diffing on these nodes. ### Standard E: Rate Limiting & Signal Payload Caps - All Datastar action endpoints are protected by `core/auth_guards.ts`: - Max request body size capped at **16KB** (rejecting oversized signal payloads). - Sliding-window rate limiting on interactive triggers to prevent button-mashing denial-of-service. --- ## 3. Directory Taxonomy (Vertical Feature Slicing) ``` src/ ├── core/ <-- Core Invariants & Shared Infrastructure │ ├── db.ts (PostgreSQL 18 pool & DDL) │ ├── valkey.ts (Valkey 8 connection & Pub/Sub broker) │ ├── sse_adapter.ts (Typed Datastar SSE streaming helper) │ ├── auth_guards.ts (Rate limiter, 16KB payload cap, CSRF/Origin check) │ ├── content_negotiation.ts (Detects Datastar HTML vs CLI/JSON clients) │ └── spire_ffi.ts (Rust SPIFFE/mTLS FFI bindings) │ ├── features/ <-- Self-Contained Domain Feature Slices │ ├── sessions/ │ │ ├── routes.ts (Hono router: /dashboard/sessions, /api/sessions/delegate) │ │ ├── queries.ts (Session DB/Valkey queries) │ │ ├── fragments.tsx (Hono JSX: SessionTable, SessionDeck, HandoffCard) │ │ └── sessions.test.ts │ │ │ ├── events/ │ │ ├── routes.ts (Hono router: /events, /join, /rotate-pin, /extend) │ │ ├── queries.ts (Event passes, claimed seats, attendees queries) │ │ ├── fragments.tsx (Hono JSX: EventCockpit, WorkshopDrawer, GuestDrawer) │ │ ├── stream.ts (Targeted SSE stream handler for live seat counters) │ │ └── events.test.ts │ │ │ ├── admin/ │ │ ├── routes.ts (Hono router: /admin/users, /admin/apps, /admin/audit) │ │ ├── queries.ts (Admin management SQL) │ │ └── fragments.tsx (Hono JSX: AdminTables, RoleModals) │ │ │ └── auth/ │ ├── routes.ts (Hono router: /login, /register, /recovery) │ ├── webauthn.ts (Isolated ceremony micro-scripts with data-ignore) │ └── fragments.tsx (Hono JSX: PasskeyLogin, Onboarding) │ ├── shared/ <-- STRICTLY Domain-Agnostic UI Atoms │ └── ui/ │ ├── Layout.tsx (Global shell, strict CSP, loads /public/datastar-v1.x.js) │ ├── Navbar.tsx (Top navigation bar) │ ├── Toast.tsx (Target fragment for #status-banner error/success morphs) │ ├── DrawerShell.tsx (Slide-over overlay, backdrop, and header) │ ├── PillGroup.tsx (Selection button groups for hours, seats) │ └── Accordion.tsx (Clean
wrapper without double-arrow regressions) │ └── tests/arch/ <-- Persistent Architectural & Network Test Harness ├── transport_efficiency.test.ts (Asserts routine mutations return text/html in <2ms) ├── sse_lifecycle.test.ts (Asserts Valkey SSE connection limits and drain cleanup) ├── proxy_buffering.test.ts (Asserts Traefik X-Accel-Buffering: no bypass headers) ├── error_fragment.test.ts (Asserts 4xx/5xx responses return valid JSX error fragments) ├── xss_fuzzing.test.ts (Fuzzes fragment rendering with malicious script payloads) └── content_negotiation.test.ts (Asserts CLI curl vs Datastar browser request isolation) ``` --- ## 4. Persistent Architectural & Network Test Suite (`tests/arch/`) To guarantee efficiency and prevent regressions as the system evolves, we maintain a dedicated **Architectural Test Harness**: 1. **Transport Efficiency & Latency Tests:** - Asserts that routine point-to-point actions (`/extend`, `/rotate-pin`, form submissions) return standard `text/html` in $<2\text{ms}$ without opening or leaking SSE stream connections. 2. **SSE Stream Lifecycle & Capacity Tests:** - Simulates 100+ concurrent live cockpit clients listening to Valkey Pub/Sub; asserts proper connection draining, explicit disconnect cleanup, and memory ceiling stability. 3. **Reverse Proxy & Buffering Invariant Tests:** - Validates that SSE stream endpoints emit `X-Accel-Buffering: no` and `Cache-Control: no-cache` headers to prevent reverse proxies (Traefik/Nginx) from choking or buffering streams. 4. **Dual-Mode Content Negotiation Tests:** - Asserts that `curl -sSL ... /join/:slug?format=env` returns a valid shell string, `Accept: application/json` returns pure JSON DTOs, and browser requests return clean Datastar HTML fragments. 5. **XSS & Escape Fuzzing Harness:** - Feeds script injection strings (``, `">`) into event names and attendee usernames and asserts the rendered JSX fragment outputs properly escaped entities (`<script>`). --- ## 5. AI-Optimized Code Organization & Engineering Principles 1. **Bounded Files & Concise Functions:** - Target small, focused functions (4–20 lines) and keep files bounded (under 300–500 lines) so agents can read, reason, and edit full units in a single turn without context fragmentation. 2. **Strict Single Responsibility Principle (SRP):** - Every module must do exactly one thing well. Independent modules allow agents to isolate and modify code without loading unrelated context. 3. **Flat Call Chains Over Clever DRY Abstractions:** - Prefer a flat, shallow 1–2 hop call chain over deep, multi-level abstraction hierarchies. Shallow boilerplate is vastly superior to a 5-file hop for AI reasoning. 4. **Highly Distinctive, Searchable Naming:** - Avoid generic identifiers (`Manager`, `DataHandler`, `process()`). Use explicit, searchable domain names (`SessionPinRotator`, `streamGuestDrawerTelemetry`, `SessionHandoffCard`). 5. **Deterministic Tooling Enforcement:** - All code quality standards must be enforced by automated tooling (`deno fmt`, `deno task lint`, `deno task check`, `deno test`). Agents must verify passing gates before completing tasks. 6. **Payload & Rate Guardrails:** - All interactive action endpoints must be bounded by rate-limiting and a strict 16KB request body ceiling.