26 KiB
26 KiB
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
\rightarrowquarantined: true\rightarrowLocal peer/host 1-time QR code/emoji approval\rightarrowActivated (with hierarchical branch revocation). - ⚡ Transparent Client Proof-of-Work (PoW): Background ~50ms
crypto.subtleSHA-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.