docs: add task plan for phase 1 of events guest ingress
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>
This commit is contained in:
parent
e9060eee5a
commit
4ec15fe35f
@ -0,0 +1,85 @@
|
|||||||
|
# TASK METADATA
|
||||||
|
|
||||||
|
- **Target Files:** `server/routes/auth_forward.ts`, `ui/db_queries.ts`,
|
||||||
|
`ui/mod.ts`, `server/routes/events.ts`, `server/tests/forward_auth.test.ts`,
|
||||||
|
`server/tests/events.test.ts`
|
||||||
|
- **Core Objective:** Implement Phase 1 of the Event & Session Overhaul: Enable
|
||||||
|
Traefik ForwardAuth guest ingress for scoped event attendees, bridge session
|
||||||
|
custom scopes to the Launchpad UI, and wire audit logging on event seat
|
||||||
|
claims.
|
||||||
|
- **Dependencies:** None.
|
||||||
|
- **Additional Important Notes:** Follow zero-trust default-deny principles for
|
||||||
|
ForwardAuth. Guest sessions minting needs to correctly log to the Merkle audit
|
||||||
|
ledger for SIEM visibility.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Architectural Considerations & Risks
|
||||||
|
|
||||||
|
- **Risks:**
|
||||||
|
- **ForwardAuth Security:** Modifying ForwardAuth to accept `guest` accounts
|
||||||
|
risks inadvertently allowing guests to access applications they are not
|
||||||
|
explicitly scoped for. Strict validation of `auth.customScopes` against the
|
||||||
|
requested `appRecord.name` is critical.
|
||||||
|
- **Launchpad Leakage:** The `getDashboardApps` query modification must be
|
||||||
|
robust. If the UNION query is not correctly structured, it could leak
|
||||||
|
visibility of unregistered or unauthorized apps to guests.
|
||||||
|
- **Audit Logging Integrity:** Failure to capture the audit events properly
|
||||||
|
during the `join` phase would break SIEM visibility. Using the non-blocking
|
||||||
|
`auditWrapper.auditLog` is required to avoid impacting user request latency
|
||||||
|
while ensuring compliance.
|
||||||
|
|
||||||
|
- **Alternatives:**
|
||||||
|
- We considered a bypass in `ui/db_queries.ts` where guests completely skip
|
||||||
|
the `grants` JOIN. However, using a `UNION` is structurally superior as it
|
||||||
|
seamlessly supports both pure guests and regular active users who might hold
|
||||||
|
delegated scoped passes. It provides a unified data retrieval flow.
|
||||||
|
|
||||||
|
### 3. Proposed Implementation
|
||||||
|
|
||||||
|
#### Phase 1: ForwardAuth Guest Ingress (`server/routes/auth_forward.ts`)
|
||||||
|
|
||||||
|
1. **Permit Guest Accounts:** Update the account status validation to allow
|
||||||
|
`user.account_status === 'guest'` in addition to `'active'`.
|
||||||
|
2. **Custom Scopes Validation:** If the user is a guest (or relying on custom
|
||||||
|
scopes), verify that `auth.customScopes` contains the explicit application
|
||||||
|
grant (e.g., `app:${appRecord.name}`). If not, return a 403 Forbidden.
|
||||||
|
3. **Header Injection:** For guest sessions, compute the scopes to inject into
|
||||||
|
`X-Forwarded-Scopes` by taking the comma-joined list of `auth.customScopes`
|
||||||
|
(`auth.customScopes.join(",")`). This propagates the app scope (e.g.,
|
||||||
|
`app:ed-droid`) and role (e.g., `viewer`) to downstream reverse proxies.
|
||||||
|
|
||||||
|
#### Phase 2: Launchpad App Query (`ui/db_queries.ts` & `ui/mod.ts`)
|
||||||
|
|
||||||
|
1. **Function Signature Update:** Update
|
||||||
|
`getDashboardApps(userId: string, isAdmin: boolean, customScopes?: string[])`
|
||||||
|
to accept the session's custom scopes.
|
||||||
|
2. **UNION Query:** Update the non-admin SQL query to use a `UNION`.
|
||||||
|
- The first part queries explicitly granted apps via the `grants` table.
|
||||||
|
- The second part parses the provided `customScopes` array to extract allowed
|
||||||
|
app names (e.g., stripping the `app:` prefix), querying the `apps` table
|
||||||
|
for those matching names, and assigning them a pseudo-role such as
|
||||||
|
`"Guest (Viewer)"` (or extracting the role from the scopes if possible).
|
||||||
|
3. **UI Integration:** In `ui/mod.ts`, pass `auth.customScopes` from the
|
||||||
|
resolved session into `getDashboardApps`.
|
||||||
|
|
||||||
|
#### Phase 3: Join Audit Logging (`server/routes/events.ts`)
|
||||||
|
|
||||||
|
1. **Audit `POST /api/join` (Web):** Immediately after minting the guest
|
||||||
|
session, invoke
|
||||||
|
`auditWrapper.auditLog(guestUuid, "event_seat_claimed", event.id, { slug: event.slug, name: event.name, seatNumber: event.seats_claimed, method: "web" }, getClientIp(c))`.
|
||||||
|
2. **Audit `GET /join/:slug` (CLI):** Similarly, wire
|
||||||
|
`auditWrapper.auditLog(guestUuid, "event_seat_claimed", event.id, { slug: event.slug, name: event.name, seatNumber: event.seats_claimed, method: "cli" }, getClientIp(c))`
|
||||||
|
into this endpoint before returning the token.
|
||||||
|
|
||||||
|
#### Phase 4: Unit Testing
|
||||||
|
|
||||||
|
1. **ForwardAuth Tests (`server/tests/forward_auth.test.ts`):**
|
||||||
|
- Add tests simulating a guest session with an `app:{name}` scope to ensure a
|
||||||
|
`200 OK` response with correctly formatted `X-Forwarded-Scopes`.
|
||||||
|
- Add tests simulating a guest session without the necessary `app:{name}`
|
||||||
|
scope to ensure a `403 Forbidden` response.
|
||||||
|
2. **Events Tests (`server/tests/events.test.ts`):**
|
||||||
|
- Ensure the `POST /api/join` and `GET /join/:slug` assertions capture the
|
||||||
|
`auditLog` spy calls and verify the exact payload (`event_seat_claimed`
|
||||||
|
action, `event.id` as resource, correct metadata structure).
|
||||||
Loading…
x
Reference in New Issue
Block a user