auth-yes/tasks/ui-audit-3.md

26 KiB
Raw Blame History

UI & UX Live Audit Log — Round 3 (ui-audit-3.md)

Date: 2026-08-26 (Session: 21:30)
Target Environments: https://auth.atyg.org | https://ed-droid.atyg.org
Scope: Verification of Phase 5 Deliverables (True Slide-Over Guest Drawer, Multi-Event Compact Toggle, Standardized Countdown Pills, Mobile Density Optimization, Backend Revocation).


1. Core Verification Focus Areas

# Feature / Flow Target Behavior Status
1 Slide-Over Guest Drawer Clicking [ 👥 Manage Guests (N) ] opens a fixed right-side panel on Desktop (420px; 100vh) and bottom sheet on Mobile (100vw; 80vh) with backdrop fade, Escape key close, and backdrop click dismissal. ⏳ Pending Test
2 Guest Drawer Information IA Pinned contextual header showing [Event Name] Guests + N / Max Claimed Seats · ⏳ Xh Ym left · (Expires Time). Individual rows only display unique data (Seat #[N], Username, Joined relative time, 🟢 Active / ⏸️ Paused). ⏳ Pending Test
3 Backend Revocation Fix Event creator clicking [ 🗑️ Revoke ] inside the Guest Drawer immediately deletes the attendee session from Valkey cache and DB without 404 access-denied errors. ⏳ Pending Test
4 Multi-Event Compact Toggle [ 🗂️ Grid ] vs [ 📋 Compact ] toggle collapses 5–10 active event cards into sleek 1-row strips (Title · 🟢 Active · ⏳ 2h 45m left · 12/50 Seats · PIN · [ 👥 Guests ]). View mode persists in localStorage. ⏳ Pending Test
5 Dynamic Countdown Pills Countdown pills across all Event Pass cards, Guest Drawer, and Sessions list display ⏳ Xh Ym left · (Expires Time) with dynamic colors (green \rightarrow amber $<1$h \rightarrow red expired) and tick down live every 30s. ⏳ Pending Test
6 Mobile Session Density Remote personal device cards in SessionDeck.tsx have no dedicated full-width bottom row; compact [ 🗑️ Revoke ] sits inline in the header row next to the status badge. ⏳ Pending Test

2. Live Observation & Findings Log

Record observations, visual feedback, quirks, and confirmations here as we execute.

Timestamp Scenario Component / Flow Observation / Finding Resolution / Action Item
21:30 Setup System Opened ui-audit-3.md tracking log for Phase 5 live deployment testing. Ready for live observation inputs.
21:31 State Consistency EventCockpitDeck.tsx & Queries Contradictory Status (⏳ Expired + Active Badge): An expired workshop pass shows the countdown pill as ⏳ Expired (red) but right next to it the status badge remains hardcoded as green Active (<span class="badge badge-success status-badge">Active</span>). Furthermore, expired passes remain in the active deck rather than being filtered or marked as expired. Action Item:
1. Derive badge dynamically: if is_paused \rightarrow badge-warning Paused; if isExpired \rightarrow badge-secondary Expired; else badge-success Active.
2. Filter out or separate expired passes in the database query (WHERE expires_at > NOW()) so the active cockpit deck only shows currently actionable passes.
21:38 Information Architecture ExpiryBadge Component Finalized Natural Expiry & Lifespan Format (Option A+): Standardize all session and pass expiration indicators to a clean, highly readable pattern:
[Date] · [Time] · [ Colored Urgency Badge ]

• Natural Date String: Today (if $<24$h), Tomorrow (if $<48$h), Sep 23 (same year), Jan 15, 2027 (future year).
• Exact Time: 10:39 PM (local time).
• Floating Dot Separator: Styled subtle · with muted opacity to preserve visual rhythm.
• Multi-Tier Urgency Badge:
  - $<1$h: Amber [ 45m left ]
  - $<24$h: Amber/Green [ 2h 45m left ]
  - 1–60d: Green [ 28d left ]
  - 2–12 mos: Green [ 4.5 mos left ] (no clunky 142d)
  - 1+ yrs: Green [ 1.2 yrs left ] (no clunky 420d)
  - Expired: Red [ Expired ]
• Optional Prefix: showPrefix?: boolean (defaults to false since headers/cards establish context).
• Full Precision Tooltip: title="Wednesday, August 26, 2026, 10:39:01 PM EDT" on element for hover/long-press.
21:59 Lifecycle & Business Logic server/routes/events.ts & Deck Extending Expired Events (Re-activation vs Kill Switch):
1. Not an Anti-Pattern: Allowing an event host to add time to a naturally expired event (where is_active = TRUE) is high-value for real workshops running overtime, saving the host from creating a new event and forcing 30 participants to re-join.
2. Backend Math Bug: Currently SET expires_at = expires_at + interval '1 hour' fails if the event expired hours ago. It must be SET expires_at = GREATEST(expires_at, NOW()) + interval '${extendHours} hours'.
3. Distinction from Hard Kill Switch: [ End Event ] sets is_active = FALSE (hard revocation, permanent archive). A naturally expired event remains is_active = TRUE and can be re-opened with [ 🔄 Reopen (+1h) ].
Action Item:
• Update SQL in events.ts:extend to use GREATEST(expires_at, NOW()).
• In EventCockpitDeck.tsx, render expired passes in a collapsed <details> / [ 📁 Expired Passes (N) ] section or with a distinct [ 🔄 Reopen (+1h) ] button rather than deleting them immediately.
22:13 IA & Telemetry Design EventGuestsDrawer.tsx & Script Clunky "Joined 474m ago" & Redundant Slug Overwhelm:
1. Displaying raw minutes (Joined 474m ago) is unreadable math clutter.
2. Printing full redundant slugs (guest_universal-sandbox-read-only_1) on every seat creates massive visual noise.
3. Missing actionable guest telemetry (last action, ingress route, activity level).
Action Item (Inverted Start-Time & Telemetry Pattern):
• Header: Bold Seat #[N] + 🟢 Active / ⏸️ Paused badge.
• Line 1 (Inverted Start-Time): Joined Today · 2:15 PM · [ Active 7h 54m ] (or Joined Aug 25 · [ Active 2d ]) using the symmetrical time-since formatter.
• Line 2 (Action Telemetry): Last Action: ForwardAuth Ingress (ed-droid) · 2m ago · 💻 Web (pulling last_activity_action and last_activity_at from sessions).
• Drop the redundant full slug from the visual text (keep in hover tooltip only).
22:18 Visual Layout & Redundancy SessionsPage.tsx vs EventCockpitDeck.tsx Duplicate "Event Passes" Heading: SessionsPage.tsx:60 rendered <h2>Event Passes</h2>, while EventCockpitDeck.tsx:7 ALSO rendered <h2>Event Passes</h2> alongside the view toggle, creating two stacked identical titles. Action Item: Remove the redundant <h2>Event Passes</h2> from SessionsPage.tsx so EventCockpitDeck.tsx exclusively owns its section header and attached view mode toggle.
22:25 Layout Density & Visual Bug EventCockpitDeck.tsx (Compact View) Critical Compact Mode Breakdown (Verified via Screenshot):
1. Severe Text Collision: The event title (testing workshop event:...) collides and overlaps directly on top of Seats Claimed 3/40, ⏳ Expired, and the PIN input.
2. Border Bleed: Input boxes and Copy buttons blow past the right card border boundary.
3. Buttons Pushed Outside Card: [ 👥 Guests (3) ] and [ ▸ Details ] are pushed completely outside the blue card border onto the empty page background.
4. Mock Code Regression: The [ ▸ Details ] button executes an inline browser alert (alert('Expand functionality for compact view to be implemented if needed')).
5. Double Heading & Arrow: Double Event Passes headings and double ▶ ▸ disclosure arrows.
Action Item (2-Row Compact Card Architecture): Scrap the broken single-line CSS hack. Build a dedicated, strictly bounded 2-Row Compact Card (~70px height):
• Row 1: [▸ Event Title (ellipsis, max-w 260px)] · [Date · Time · Urgency Badge] · [3/40 Seats] · [🟢 Status Badge].
• Row 2: [ PIN: 241-881 (Copy) ] [ Link (Copy) ] [ CLI (Copy) ] on the left, and [ 👥 Guests (3) ] + [ 🔄 +1h ] docked on the right.
• Remove mock [ ▸ Details ] alert completely since all handoffs are 1 click away on Row 2.
• Remove duplicate <h2>Event Passes</h2> from SessionsPage.tsx.
22:30 Visual Affordance & Contrast EventCockpitDeck.tsx (View Toggle) Ambiguous Active State on Grid/Compact Toggle: The [ 🗂️ Grid ] vs [ 📋 Compact ] toggle lacks clear visual distinction between active and inactive states (both look almost flat with faint border outlines), making it hard to discern at a glance which mode is currently selected. Action Item (High-Contrast Segmented Pill Control):
• Active Option: High-contrast solid brand pill (background: var(--primary); color: #ffffff; font-weight: 700; box-shadow: 0 1px 3px rgba(0,0,0,0.3);).
• Inactive Option: Muted translucent background (color: var(--text-muted); opacity: 0.75;).
• Include aria-pressed="true/false" for complete screen reader accessibility.
22:54 UX Polish & Action Clarity WorkshopDrawer.tsx (Handoff State) Mismatched Blue Copy Button & Ambiguous "Dismiss":
1. In the created event handoff screen, Copy PIN is styled as btn-primary (solid blue) while Copy URL and Copy 1-Liner are btn-outline, creating inconsistent button hierarchy.
2. The bottom button says "Dismiss", which sounds negative and confusing.
Action Item:
• Standardize all 3 copy buttons to uniform btn-outline (Copy PIN, Copy URL, Copy 1-Liner).
• Replace "Dismiss" with a clean, minimal button [ OK ] that closes the drawer and ensures the newly created event appears in the deck.
22:58 State Machine Reset SessionsScript.tsx (openDelegateDrawer) Stale Drawer State on Re-open: When clicking [ Delegate Session ] after previously creating an event or session, the drawer opens directly to the stale handoff success screen rather than resetting back to the clean creation form. Action Item: In openDelegateDrawer(), always reset the state machine:
• Reset #eventCreateState to display: block and #eventHandoffState to display: none.
• Clear form input values.
• Default back to Single Session tab.
23:01 Security & Ingress Invalidation server/routes/events.ts (rotate-pin) Incomplete Ingress Rotation (PIN rotated but Link & CLI stayed open): Currently, clicking rotate only generates a new 6-digit PIN, leaving the static slug active. If the direct link or CLI command was leaked to bad actors, rotating the PIN fails to lock them out! Action Item (Universal Ingress Rotation):
• Update POST /api/events/:id/rotate-pin to rotate BOTH the numeric PIN (pin_code) and the event slug suffix (slug).
• Return { success: true, pinCode, slug, link, cli } and update all 3 fields in the UI simultaneously.
• Existing active attendees remain completely unaffected, while any new join attempt using the old PIN, old Link, or old CLI command is immediately blocked.

3. Retained Security & Architecture Roadmap

  • 🛡️ Peer-to-Peer Vouching (High-Security Web of Trust): Attendee PIN join \rightarrow quarantined: true \rightarrow Local peer/host 1-time QR code/emoji approval \rightarrow Activated (with hierarchical branch revocation).
  • ⚡ Transparent Client Proof-of-Work (PoW): Background ~50ms crypto.subtle SHA-256 hash collision on PIN submission to defeat distributed botnets.
  • 📌 Sticky / Persistent Delegation Action Bar: Floating/sticky trigger for [ Delegate Session ] on deep scrolling pages.