diff --git a/tasks/new/2026-0826.01.jul.story.arch.event-delegation-and-session-ux-overhaul-1440.md b/tasks/new/2026-0826.01.jul.story.arch.event-delegation-and-session-ux-overhaul-1440.md new file mode 100644 index 0000000..80a3078 --- /dev/null +++ b/tasks/new/2026-0826.01.jul.story.arch.event-delegation-and-session-ux-overhaul-1440.md @@ -0,0 +1,90 @@ +# TASK METADATA + +- **Target Files:** + - `server/routes/auth_forward.ts` + - `server/routes/events.ts` + - `ui/db_queries.ts` + - `ui/components/LoginPage.tsx` + - `ui/components/EventJoinPage.tsx` + - `ui/components/SessionsPage.tsx` + - `ui/components/sessions/WorkshopDrawer.tsx` + - `ui/components/sessions/EventCockpitDeck.tsx` + - `ui/components/sessions/EventAttendeesDrawer.tsx` + - `ui/components/sessions/SessionsScript.tsx` + - `server/tests/forward_auth.test.ts` + - `server/tests/events.test.ts` +- **Core Objective:** Execute a comprehensive 4-phase architectural and UX + overhaul of Event Passes, attendee join flows, ForwardAuth guest ingress, + session management hierarchies, and live attendee roster controls. +- **Dependencies:** None. +- **Additional Important Notes:** + - Strictly 100% pure Hono SSR JSX (React-free). + - Must preserve zero-trust boundary: guest accounts must remain strictly + quarantined from `/admin` and primary user mutations. + - Must pass all quality gates (`deno fmt`, `deno task lint`, + `deno task check`, and `deno test --allow-all`). + +--- + +## Architectural Considerations & Risks + +### Risks +1. **Ingress Privilege Escalation:** Broadening ForwardAuth to support `guest` + accounts could accidentally grant unauthorized access to non-scoped apps. + - *Mitigation:* Explicitly enforce that `account_status: 'guest'` ONLY grants + ingress if `auth.customScopes` contains the specific `app:` grant. +2. **State Machine Confusion in Drawer:** Concurrently showing creation inputs + and success handoffs leads to phantom cancellations. + - *Mitigation:* Ensure strict 2-state mutually exclusive rendering in + `WorkshopDrawer.tsx`. +3. **NAT Seat Depletion:** Limiting joins strictly by IP locks out legitimate + users on shared conference/office WiFi. + - *Mitigation:* Implement cookie/session token-based idempotent seat re-use + rather than aggressive raw IP bans. + +### Alternatives Considered +- **Dedicated Event Dashboard Route (`/dashboard/events/:id`):** Evaluated and + rejected in favor of the **Slide-Out Attendee Drawer** pattern to eliminate + jarring page reloads and context loss during live event management. + +--- + +## Proposed Implementation (4-Phase Architecture) + +### Phase 1: Backend Core & Guest Ingress (`.ph1.md`) +- **ForwardAuth Guest Ingress (`server/routes/auth_forward.ts`):** Allow + `account_status === 'guest'` and validate `app:` custom scope. +- **Launchpad Scopes (`ui/db_queries.ts`):** Update `getDashboardApps` to + evaluate session `customScopes` and return authorized app cards for guests. +- **Audit Logging on Join (`server/routes/events.ts`):** Wire `auditLog` in + `POST /api/join` for `event_seat_claimed`. +- **Test Harness (`server/tests/forward_auth.test.ts`, `server/tests/events.test.ts`):** + Add unit tests for guest ForwardAuth and audit event logging. + +### Phase 2: Login Discovery, PIN Normalization & Anti-DoS (`.ph2.md`) +- **Discovery Link (`ui/components/LoginPage.tsx`):** Add `Join with PIN` link + in `/login` footer. +- **Input Normalization (`server/routes/events.ts`, `ui/components/EventJoinPage.tsx`):** + Strip hyphens/spaces and lowercase slugs (`LOWER(slug)`). +- **Anti-DoS & Rate Limiting (`server/routes/events.ts`):** Mount tiered Valkey + rate limiting and NAT-safe cookie seat re-use. +- **Test Harness:** Add unit tests for PIN formatting tolerance and rate limits. + +### Phase 3: Sessions Layout & Drawer State Machine (`.ph3.md`) +- **Page Hierarchy (`ui/components/SessionsPage.tsx`):** Standardize top + heading to `Active Sessions & Passes` with `[ 🔑 Delegate Session ]` button. +- **Subsections:** `Event Passes` cards above, `Active Sessions` table below. +- **2-State Drawer (`ui/components/sessions/WorkshopDrawer.tsx`):** Hide creation + form on success; render 3 distinct visible cards (PIN, URL, CLI) + `Dismiss`. +- **Emoji & Header Fixes:** Fix double emoji (`🎟️ 🎟️`) and mobile title + wrapping. + +### Phase 4: Attendee Drawer & Live Event Controls (`.ph4.md`) +- **Card Enhancements (`ui/components/sessions/EventCockpitDeck.tsx`):** Add + `⏳ Xh Ym left` countdown badge, accessible `
` CLI expander, and + `[ End Event ]` with `aria-label`. +- **Attendee Roster Drawer (`ui/components/sessions/EventAttendeesDrawer.tsx`):** + Add slide-out drawer on `[ 👥 Manage Attendees (N) ]` to inspect guest seats. +- **Session Pausing:** Introduce non-destructive `is_paused` session state + with instant Pause/Resume toggles. +- **Live Controls:** Add `[ 🔄 Rotate PIN ]` and `[ +5 Seats ]` on event cards. diff --git a/tasks/new/2026-0826.01.jul.story.arch.event-delegation-and-session-ux-overhaul-1440.ph1.md b/tasks/new/2026-0826.01.jul.story.arch.event-delegation-and-session-ux-overhaul-1440.ph1.md new file mode 100644 index 0000000..66f161a --- /dev/null +++ b/tasks/new/2026-0826.01.jul.story.arch.event-delegation-and-session-ux-overhaul-1440.ph1.md @@ -0,0 +1,66 @@ +# TASK METADATA + +- **Target Files:** + - `server/routes/auth_forward.ts` + - `ui/db_queries.ts` + - `ui/mod.ts` + - `server/routes/events.ts` + - `server/tests/forward_auth.test.ts` + - `server/tests/events.test.ts` +- **Core Objective:** Implement Phase 1 of the Event Delegation & Ingress Overhaul: + enable Traefik ForwardAuth guest ingress for scoped event attendees, bridge + session custom scopes to the Launchpad UI, and wire audit logging on seat claims. +- **Dependencies:** None. +- **Additional Important Notes:** + - Strictly 100% pure Hono SSR JSX. + - Zero-Trust Ingress Rule: `account_status: 'guest'` must ONLY be permitted if + the session holds the specific `app:` custom scope for the target host. + - Must pass all quality gates (`deno fmt`, `deno task lint`, `deno task check`, + and `deno test --allow-all`). + +--- + +## Architectural Considerations & Risks + +### Risks +1. **Scope Leakage:** If ForwardAuth allows any guest account through without + validating the specific `app:` scope, a guest for Event A could + access Event B's workload. + - *Mitigation:* In `server/routes/auth_forward.ts`, explicitly require that + either `grantRole` exists in PostgreSQL or `auth.customScopes` includes + `app:${appRecord.name}`. +2. **Launchpad Scope Resolution:** Guests do not have rows in the `grants` table. + - *Mitigation:* Update `getDashboardApps` in `ui/db_queries.ts` to accept + optional `customScopes?: string[]` from `auth` and query matching apps + with role `'Guest (Viewer)'`. + +--- + +## Proposed Implementation + +### 1. ForwardAuth Guest Ingress (`server/routes/auth_forward.ts`) +- Update the user account status validation (around line 120): + - Permit `user.account_status === "active" || user.account_status === "guest"`. +- Update the grant resolution check (around line 128): + - Check if `auth.customScopes` contains `app:${appRecord.name}`. + - If matched, set `grantRole = "viewer"` (or the role defined in scopes) and + allow ingress with injected `X-Forwarded-*` headers. + +### 2. Launchpad Guest Scopes (`ui/db_queries.ts` & `ui/mod.ts`) +- Update `getDashboardApps(userId: string, isAdmin: boolean, customScopes?: string[])`: + - If `customScopes` contains items formatted as `app:`, query the `apps` + table for those app names. + - Return the app records with `role: "Guest (Viewer)"`. +- In `ui/mod.ts` under `/dashboard`: Pass `auth.customScopes` to `getDashboardApps`. + +### 3. Join Audit Logging (`server/routes/events.ts`) +- In `POST /api/join` (around line 265): + - Call `auditWrapper.auditLog(guestUuid, "event_seat_claimed", event.id, { eventName: event.name, slug: event.slug, seatNumber: event.seats_claimed }, getClientIp(c))` + - Ensures all guest claims are captured in the Merkle audit ledger. + +### 4. Unit & Integration Tests +- In `server/tests/forward_auth.test.ts`: + - Add test: `Tier 1 & 2: GET /api/forward-auth - Guest session with app scope allowed`. + - Add test: `Tier 1 & 2: GET /api/forward-auth - Guest session without app scope rejected (403)`. +- In `server/tests/events.test.ts`: + - Verify that `POST /api/join` triggers `event_seat_claimed` audit event.