56 lines
26 KiB
Markdown
56 lines
26 KiB
Markdown
# 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:**<br>1. Derive badge dynamically: if `is_paused` $\rightarrow$ `badge-warning Paused`; if `isExpired` $\rightarrow$ `badge-secondary Expired`; else `badge-success Active`.<br>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:<br>`[Date] · [Time] · [ Colored Urgency Badge ]`<br><br>• **Natural Date String:** `Today` (if $<24$h), `Tomorrow` (if $<48$h), `Sep 23` (same year), `Jan 15, 2027` (future year).<br>• **Exact Time:** `10:39 PM` (local time).<br>• **Floating Dot Separator:** Styled subtle `·` with muted opacity to preserve visual rhythm.<br>• **Multi-Tier Urgency Badge:**<br> - $<1$h: Amber `[ 45m left ]`<br> - $<24$h: Amber/Green `[ 2h 45m left ]`<br> - 1–60d: Green `[ 28d left ]`<br> - 2–12 mos: Green `[ 4.5 mos left ]` (no clunky `142d`)<br> - 1+ yrs: Green `[ 1.2 yrs left ]` (no clunky `420d`)<br> - Expired: Red `[ Expired ]`<br>• **Optional Prefix:** `showPrefix?: boolean` (defaults to `false` since headers/cards establish context).<br>• **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):**<br>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.<br>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'`.<br>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:**<br>• Update SQL in `events.ts:extend` to use `GREATEST(expires_at, NOW())`.<br>• 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:**<br>1. Displaying raw minutes (`Joined 474m ago`) is unreadable math clutter.<br>2. Printing full redundant slugs (`guest_universal-sandbox-read-only_1`) on every seat creates massive visual noise.<br>3. Missing actionable guest telemetry (last action, ingress route, activity level). | **Action Item (Inverted Start-Time & Telemetry Pattern):**<br>• **Header:** Bold `Seat #[N]` + `🟢 Active / ⏸️ Paused` badge.<br>• **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.<br>• **Line 2 (Action Telemetry):** `Last Action: ForwardAuth Ingress (ed-droid) · 2m ago · 💻 Web` (pulling `last_activity_action` and `last_activity_at` from `sessions`).<br>• 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):**<br>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.<br>2. **Border Bleed:** Input boxes and Copy buttons blow past the right card border boundary.<br>3. **Buttons Pushed Outside Card:** `[ 👥 Guests (3) ]` and `[ ▸ Details ]` are pushed completely outside the blue card border onto the empty page background.<br>4. **Mock Code Regression:** The `[ ▸ Details ]` button executes an inline browser alert (`alert('Expand functionality for compact view to be implemented if needed')`).<br>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):<br>• **Row 1:** `[▸ Event Title (ellipsis, max-w 260px)]` · `[Date · Time · Urgency Badge]` · `[3/40 Seats]` · `[🟢 Status Badge]`.<br>• **Row 2:** `[ PIN: 241-881 (Copy) ]` `[ Link (Copy) ]` `[ CLI (Copy) ]` on the left, and `[ 👥 Guests (3) ]` + `[ 🔄 +1h ]` docked on the right.<br>• Remove mock `[ ▸ Details ]` alert completely since all handoffs are 1 click away on Row 2.<br>• 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):**<br>• **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);`).<br>• **Inactive Option:** Muted translucent background (`color: var(--text-muted); opacity: 0.75;`).<br>• 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":**<br>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.<br>2. The bottom button says `"Dismiss"`, which sounds negative and confusing. | **Action Item:**<br>• Standardize all 3 copy buttons to uniform `btn-outline` (`Copy PIN`, `Copy URL`, `Copy 1-Liner`).<br>• 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:<br>• Reset `#eventCreateState` to `display: block` and `#eventHandoffState` to `display: none`.<br>• Clear form input values.<br>• 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):**<br>• Update `POST /api/events/:id/rotate-pin` to rotate **BOTH** the numeric PIN (`pin_code`) and the event slug suffix (`slug`).<br>• Return `{ success: true, pinCode, slug, link, cli }` and update all 3 fields in the UI simultaneously.<br>• 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.
|