2.9 KiB
2.9 KiB
Phase 7: Attendee Relational Decoupling & Immutable Identity
1. Context & Rationale
Currently, guest attendee sessions are bound to their originating event via
brittle string matching on users.username (e.g.,
WHERE username LIKE 'guest_' || ep.slug || '_%'). This creates two major
architectural flaws:
- Rotation Breakage: If an event host rotates the event's ingress PIN/slug
(e.g.,
deno-lab-1a2btodeno-lab-9x8z), the backend loses track of previously joined guests because their usernames retain the old slug suffix. - Unwieldy Data: Guest usernames inherit the full event slug, leading to
massive, unreadable usernames in logs and the database (e.g.,
guest_annual-cyber-security-training-workshop-4f8x_12).
2. Objective
Implement a robust "A+B Architecture" to permanently decouple guest session lifecycle from transient URL slugs:
- Option A (Relational Integrity): Link guests directly to the Event UUID
via a strict Foreign Key (
event_pass_id). - Option B (Immutable Identity): Mint short, deterministic, and immutable usernames using the Event UUID prefix.
3. Scope & Acceptance Criteria
3.1 Database Migration (server/db.ts)
- Add column:
ALTER TABLE users ADD COLUMN IF NOT EXISTS event_pass_id UUID REFERENCES event_passes(id) ON DELETE CASCADE; - Ensure backward compatibility with existing standalone users (column
should be nullable, as admins/owners won't have an
event_pass_id).
3.2 Immutable Username Minting (server/routes/events.ts)
- In
POST /api/join: Change guest username generation fromguest_${event.slug}_${seat}toguest_${event.id.split('-')[0]}_${seat}. - In
POST /api/join: Insertevent.idinto the newevent_pass_idcolumn for the newly minted user.
3.3 Query Refactoring (Zero String Parsing)
GET /api/events/:id/attendees: Refactor the query to useWHERE u.event_pass_id = ${eventId}.POST /api/events/:id/extend: Refactor the query to target sessions belonging tou.event_pass_id = ${eventId}.POST /api/events/:id/end: Refactor the revocation query to targetu.event_pass_id = ${eventId}.DELETE /api/sessions/:id: Refactor the ownership check to verifyu.event_pass_id = ${eventId}instead of string parsing.
3.4 Quality Gates
- Run
deno fmt,deno task lint,deno task check. - All 67+ backend tests must pass. (Update
server/tests/events.test.tsto mock/handle the newevent_pass_idcolumn and short username generation).
4. Anti-Patterns to Avoid
- No
LIKE 'guest_%'queries anywhere in the backend logic. - No updating usernames on slug rotation. The
POST /api/events/:id/rotate-pinendpoint should ONLY touchevent_passes.slugandevent_passes.pin_code, leaving attendees completely unaffected.