Sessions UI Overhaul Phase 5
Implemented Phase 5 Task Plan for Sessions UI Overhaul: fixed the backend attendee session revocation permission checks to allow event creators to delete sessions; upgraded the EventGuestsDrawer into a fixed slide-over panel on Desktop and bottom sheet on Mobile; added standardized dynamic countdown pills using SSR and client-side real-time ticking; added a multi-event compact density toggle with localStorage memory; optimized the mobile session deck view; fixed unit tests to mock SQL correctly due to SQL query changes.
- Update `DELETE /api/sessions/:id` in `server/routes/sessions.ts` to allow event creators to delete guests' sessions.
- Update page hierarchy and top headings in `ui/components/SessionsPage.tsx`.
- Refactor `EventAttendeesDrawer.tsx` to `EventGuestsDrawer.tsx` as a fixed slide-over overlay.
- Add multi-event compact view toggle with `localStorage` persistence in `EventCockpitDeck.tsx`.
- Standardize dynamic countdown pills across `EventCockpitDeck.tsx`, `EventGuestsDrawer.tsx`, `SessionDeck.tsx`, and `SessionTable.tsx`.
- Optimize mobile session deck in `SessionDeck.tsx`.
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
feat: implement live attendee management drawer and session pause
Implemented Phase 4 of the Event & Session Overhaul:
- **Database:** Added `is_paused` flag to `sessions` and `event_passes` tables safely via soft-fail migrations.
- **API (Sessions):** Added `POST /api/sessions/:id/pause` endpoint; updated `session_resolver` to serialize `is_paused` into Valkey caches and the edge middleware (`auth_forward.ts`) to return 403 when paused.
- **API (Events):** Added endpoints to fetch `attendees` (resolving via `guest_<slug>_<seat>` deterministic lookup), `rotate-pin`, and `expand` seats. Secured all event modification endpoints to enforce `created_by` or global admin scope.
- **UI & Scripts:** Built `EventAttendeesDrawer` to visualize live connections, injected the `<EventAttendeesDrawer />` container in `SessionsPage`, added quick controls to the `EventCockpitDeck`, and backed the DOM manipulation seamlessly with vanilla JS in `SessionsScript.tsx`.
This commit finalizes Phase 4 of the Event & Session Overhaul:
1. Implements session pause logic across PostgreSQL schema, Valkey cache, and `auth_forward.ts` edge check (`is_paused`).
2. Implements non-destructive operational endpoints (`/api/events/:id/rotate-pin`, `/api/events/:id/expand`, `/api/events/:id/attendees`) with Zero-Trust Ownership verification.
3. Upgrades existing `end` and `extend` endpoints in `events.ts` to utilize robust Zero-Trust Ownership queries (created_by OR isGlobalAdmin).
4. Creates `EventAttendeesDrawer.tsx` to handle live participant inspection and individual session controls (Pause, Revoke).
5. Updates `EventCockpitDeck.tsx` and `SessionsScript.tsx` to mount and drive the new controls via vanilla JavaScript, respecting zero-framework guidelines.
6. Ensures `deno fmt`, `deno task lint`, `deno task check` and `deno test` execute successfully against the new schema and API guards.
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
Created a detailed Markdown task specification in `tasks/new/` for Phase 4 of the event system overhaul, outlining the database updates for session pausing, API endpoints for live controls, and UI enhancements for the attendee slide-out drawer based on provided architectural guidance.
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
feat(ui): implement 2-state workshop drawer machine and refine session page hierarchy
Reorganized the Sessions page hierarchy to place the Event Cockpit below the main header. Refactored the Workshop Drawer to utilize a strict 2-state container machine for clean transitions between the creation form and the success handoff modal. Implemented UI accessibility enhancements and fixed mobile text wrapping constraints.
- Moved `EventCockpitDeck` below main header in `SessionsPage.tsx`
- Refactored `WorkshopDrawer.tsx` to strictly use a 2-state display toggle (`#eventCreateState` and `#eventHandoffState`)
- Added `aria-label`s to copy buttons for accessibility
- Configured `#status-banner` with `role="status"` and `aria-live="polite"`
- Fixed mobile title text wrapping on `#createdEventTitle`
- Fixed script emoji injection logic to prevent double emojis
- Added JS reset logic in `closeDelegateDrawer` to restore drawer states and clear form data
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
feat(events): implement bifurcated join inputs and NAT-safe idempotency
Discovery Links: Added Join with PIN links next to registration options on the login and register pages.
Bifurcated Input Normalization: Updated the Join endpoints to normalize event slugs to LOWER(slug) and PINs by stripping whitespace/hyphens via regex before checking the SQL layer. This allows event slugs to correctly keep hyphens while letting users type in 6-digit PINs without client-side format anxiety.
NAT-Safe Idempotent Cookies: Reworked POST /api/join to use a SELECT operation first to test input matching. If a match is found, the endpoint will check if the user is already authenticated as a valid guest for this specific event (username.startsWith("guest_" + slug)). If so, it successfully redirects with a renewed session TTL instead of claiming an additional seat or duplicating a user account.
Rate Limiting: Added a non-mutating isRateLimited function back to server/ratelimit.ts. The join API checks this limit upfront (5 attempts / 60 seconds). Only failed lookup branches trigger checkRateLimit which increments the counter. Successful attempts bypass the rate limiter, mitigating DoS via brute-forcing while remaining performant.
Testing: Updated events.test.ts to assert normalization paths, rate limit threshold locking, and NAT-safe reusable behaviors, achieving 100% test passing and preserving coverage.
- Adds UI links for joining with PIN in Login and Register pages.
- Normalizes event slugs to lowercase (preserving hyphens) and event PINs to strip all hyphens/spaces to handle raw inputs.
- Implements a pre-check rate limit pattern (`isRateLimited`) to safely enforce a max of 5 failed attempts per IP window (60s) without rate-limiting successful authentications.
- Achieves NAT-safe idempotency in `POST /api/join` by extracting and reusing active event guest sessions instead of blindly incrementing claimed seats on every request.
- Integrates complete test suite coverage for these new constraints.
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
feat: Phase 1 Event & Session Overhaul (Guest Ingress & Audits)
Allowed guest accounts to be evaluated in forward-auth
Validated guest account's customScopes and rejected ungranted access
Added Array parameterization and UNION query in getDashboardApps
Mapped customScopes to getDashboardApps in the UI route /dashboard
Wired web and CLI joins in events.ts to auditWrapper.auditLog using correct schema (event.id, {slug, method})
Added auditWrapper.auditLog unit test validations in events.test.ts
Added guest session scope unit tests in forward_auth.test.ts
Moved Markdown tasks logic from tasks/new/ to tasks/complete/
- Allowed guest accounts to be evaluated in `forward-auth`
- Validated `guest` account's `customScopes` and rejected ungranted access
- Added Array parameterization and `UNION` query in `getDashboardApps`
- Mapped `customScopes` to `getDashboardApps` in the UI route `/dashboard`
- Wired web and CLI joins in `events.ts` to `auditWrapper.auditLog` using correct schema (`event.id`, `{slug, method}`)
- Added `auditWrapper.auditLog` unit test validations in `events.test.ts`
- Added guest session scope unit tests in `forward_auth.test.ts`
- Moved Markdown tasks logic from `tasks/new/` to `tasks/complete/`
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
Generates a planning task file in `tasks/new/` detailing the architecture, requirements, and steps for Phase 3 of the Event & Session Overhaul, specifically addressing the page hierarchy, the 2-state drawer machine, and layout bugs.
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
Adds a new task specification in `tasks/new/` documenting the plan for Phase 2 Event Overhaul,
including PIN discovery, input normalization, rate limiting, and NAT-safe idempotent re-entry
for event joins.
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
Adds the task definition markdown file `2026-0826.01.jul.story.events.phase-1-guest-ingress-1400.md` detailing the architectural scope and plan for enabling Traefik ForwardAuth guest ingress, bridging custom scopes to the Launchpad UI via UNION query, and wiring event claim audit logs using event.id.
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
feat(ui): decompose Admin UI with separate Drawers and Scripts
Completes the phase 2 of the UI decomposition roadmap for the Admin pages by extracting the drawer components and client-side SSR JSX scripts into modular files.
- Extracted forms (`AppDrawer`, `InviteDrawer`, `RoleEditorDrawer`, `GrantDrawer`) to `ui/components/admin/drawers/`.
- Extracted scripts (`AdminAppsScript`, `AdminInvitesScript`, `AdminRolesScript`, `AdminUserDetailsScript`) to `ui/components/admin/`.
- Updated `AdminAppsPage.tsx`, `AdminInvitesPage.tsx`, `AdminRolesPage.tsx`, and `AdminUserDetailsPage.tsx` to use the components.
- Add Section 3.5 to AGENTS.md for agent orchestration and tool autonomy
- Add Section E to tasks/GUIDELINES.md with pre-review summary gate
- Update tasks/do.md dispatch template with DRY positive acceptance criteria
- Align task lifecycle state machine to keep in-flight work in tasks/new/
Refactor WebAuthn UI Components & Deduplicate Bip39 Assets
Phase 3 of the UI decomposition task. I successfully decomposed the WebAuthn client scripts out of the main page components (`PasskeysPage.tsx` and `RegisterPage.tsx`), and I also deduplicated the wordlist asset by removing the duplicate copy under `ui/public/ui/utils/` and pointing all imports to the correct location.
- Extracted `PasskeyTable` and `WebAuthnScript` into `ui/components/auth/`.
- Refactored `PasskeysPage.tsx` and `RegisterPage.tsx` to use the new components instead of inline scripts and HTML.
- Deleted the duplicate `ui/public/ui/utils/bip39_wordlist.ts` and `ui/public/ui/utils/bip39.ts`.
- Updated all import references to use `ui/utils/bip39_wordlist.ts` and `/public/utils/bip39.ts`.
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
Extract Navbar, MobileNav, and UserMenu from AuthenticatedLayout.tsx.
Extract SessionTable, SessionDeck, and SessionsScript from SessionsPage.tsx.
Preserves existing pure Hono SSR JSX and logic.
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
Creates `tasks/new/2026-0825.01.jul.story.arch.ui-decomposition-roadmap-2300.md` containing the architectural analysis and phased execution plan for modularizing `ui/` monoliths into pure SSR JSX components while maintaining testability.
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
Refactor: Decompose `server/auth-session.ts` and `ui/mod.ts` (Phase 6)
server/auth-session.ts: Kept as the clean barrel/middleware export for zero-trust scope guards and permission middlewares (requireAdmin, requireScope, hasScope, isSessionAdmin). Re-exported definitions from server/forward_auth.ts and server/session_resolver.ts.
server/forward_auth.ts (new): Extracted Traefik ForwardAuth header parsing, dynamic bypass evaluation (is_public, bypass_paths), and upstream identity injection.
server/session_resolver.ts (new): Extracted multi-cookie iteration, Valkey L1/L2 cache resolution, and PostgreSQL fallback queries.
ui/auth_checks.ts (new): Extracted admin authorization and session verification middleware.
ui/db_queries.ts (new): Extracted raw SQL queries for loading apps, roles, grants, invites, and audit logs.
ui/mod.ts: Refactored to import from ui/db_queries.ts and ui/auth_checks.ts, leaving it purely as the SSR page router mounting the UI view components.
All pre-commit checks (deno fmt, deno task lint, deno task check, deno test --allow-all) ran and passed successfully. No new failures were introduced.
Extracted the 1,577-line monolithic `server/main.test.ts` into five isolated, domain-specific files under `server/tests/`:
- `forward_auth.test.ts`: ForwardAuth bypass, cookie scoping, and sandbox.
- `rpc.test.ts`: ConnectRPC SPIFFE and RBAC tests.
- `auth.test.ts`: Audit ledger, WebAuthn PRF, passkey magic links.
- `events.test.ts`: Multi-claim join endpoints and killswitch.
- `scopes.test.ts`: Zero-trust guards and self-revocations.
Successfully maintained all tests cleanly isolated via standard mocking and deleted `main.test.ts` after migrating and executing `deno test --allow-all` with zero failures.
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>