Add event-admin password reset flow
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-06 11:02:09 +01:00
parent 51e8beb46c
commit 54b3fa0d87
17 changed files with 1080 additions and 81 deletions

View File

@@ -10,6 +10,7 @@
{"id":"fotospiel-app-25q","title":"Security review: payments/webhooks code audit (signatures, idempotency, linkage)","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-01T16:05:25.747336642+01:00","created_by":"soeren","updated_at":"2026-01-01T16:05:25.747336642+01:00"}
{"id":"fotospiel-app-29o","title":"Paddle catalog sync: PackageResource sync status badges + timestamp","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:01:10.009385187+01:00","created_by":"soeren","updated_at":"2026-01-01T16:01:15.639525807+01:00","closed_at":"2026-01-01T16:01:15.639525807+01:00","close_reason":"Completed in codebase (verified)"}
{"id":"fotospiel-app-2hq","title":"Security review: marketing/API controller+validation review","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-01T16:05:08.862737923+01:00","created_by":"soeren","updated_at":"2026-01-01T16:05:08.862737923+01:00"}
{"id":"fotospiel-app-2yn","title":"Event-Admin: Reset link routing + notifications + tests","description":"Point password reset emails to event-admin reset page; add rate limiting and tests for the new flow.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-06T10:45:09.279245468+01:00","created_by":"soeren","updated_at":"2026-01-06T11:01:49.083154811+01:00","closed_at":"2026-01-06T11:01:49.083154811+01:00","close_reason":"Closed"}
{"id":"fotospiel-app-33m","title":"Security review checklist: Guest PWA dynamic tests","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-01T16:04:40.730459361+01:00","created_by":"soeren","updated_at":"2026-01-01T16:04:40.730459361+01:00"}
{"id":"fotospiel-app-38f","title":"Paddle catalog sync: surface last sync error/log context in admin","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:59:14.865414785+01:00","created_by":"soeren","updated_at":"2026-01-02T21:16:09.109922491+01:00","closed_at":"2026-01-02T21:16:09.109922491+01:00","close_reason":"Completed"}
{"id":"fotospiel-app-3ut","title":"SEC-API-03 Synthetic monitoring + alert config","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-01T15:52:46.793875724+01:00","created_by":"soeren","updated_at":"2026-01-01T15:52:46.793875724+01:00"}
@@ -71,6 +72,7 @@
{"id":"fotospiel-app-fp3","title":"Security review: guest PWA code audit (join tokens, uploads, SW cache)","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-01T16:05:14.493336661+01:00","created_by":"soeren","updated_at":"2026-01-01T16:05:14.493336661+01:00"}
{"id":"fotospiel-app-g5o","title":"SEC-MS-04 Storage health widget in Super Admin","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:53:15.088501536+01:00","created_by":"soeren","updated_at":"2026-01-01T15:53:20.739996548+01:00","closed_at":"2026-01-01T15:53:20.739996548+01:00","close_reason":"Completed in codebase (verified)"}
{"id":"fotospiel-app-g74","title":"Paddle migration: automated tests for checkout/webhooks/sync","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:58:34.795423009+01:00","created_by":"soeren","updated_at":"2026-01-01T15:58:40.467997776+01:00","closed_at":"2026-01-01T15:58:40.467997776+01:00","close_reason":"Completed in codebase (verified)"}
{"id":"fotospiel-app-gfl","title":"Event-Admin: Forgot/Reset Password UI (Tamagui pages + routing)","description":"Add /event-admin/forgot-password + /event-admin/reset-password/{token} routes and Tamagui pages; include form, status/errors, and link from login.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-06T10:44:55.52396697+01:00","created_by":"soeren","updated_at":"2026-01-06T11:01:43.370661887+01:00","closed_at":"2026-01-06T11:01:43.370661887+01:00","close_reason":"Closed"}
{"id":"fotospiel-app-gsv","title":"Localized SEO: validate hreflang via Search Console/Lighthouse","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-01T16:02:36.4821072+01:00","created_by":"soeren","updated_at":"2026-01-01T16:02:36.4821072+01:00"}
{"id":"fotospiel-app-h5d","title":"Live Show: decide display access model (token link vs kiosk session)","description":"# Decision: Display access model (public player view)\n\n## Context\nWe need a *hands-off* playback surface for projectors/TVs (“Live Show player view”). It must be easy to open on any device, safe to share with staff, and revocable if leaked.\n\nWe already use tokenized public routes for the guest PWA (`/g/{token}`, `/e/{token}/{path?}` in `routes/web.php`). We also use Laravel signed URLs for some one-off documents (gift voucher print), but that pattern is not ideal for long-running displays.\n\n## Options\n### A) Token-only show link (recommended)\n- Admin generates a **random, unguessable token** per event: e.g. `/show/{token}`.\n- Player view is publicly accessible *only* with the token.\n- Admin can **rotate** token to invalidate all current displays.\n- Optional: add **expires_at** for temporary links (off by default for convenience).\n\n**Pros**\n- Fastest operator workflow; no login needed on projector device.\n- Matches existing public-token patterns in this repo.\n- Simple to rotate/kill in case of leakage.\n\n**Cons**\n- Anyone with the link can view the show (mitigated by rotation and not showing PII).\n\n### B) Admin-authenticated “kiosk session”\n- Projector device logs in as an admin (or receives a kiosk session after admin auth) and then shows the player view.\n\n**Pros**\n- Strong access control.\n\n**Cons**\n- Operationally painful at venues (login, MFA, account management).\n- Higher support burden and more failure points.\n\n### C) Temporary signed URL (Laravel signed routes)\n- Generate a time-limited signed URL and use that for the player.\n\n**Pros**\n- No DB token storage required.\n\n**Cons**\n- Long-running displays need long expiry; link rotation/revocation is awkward.\n- Not great UX when a signature expires mid-event.\n\n## Recommended decision\nChoose **Option A: Token-only show link**.\n\n### Security posture\n- Token is treated as a secret: do not log full token; never display it in error messages.\n- Public player view must not display PII (no guest names, no device IDs).\n- Add rate limiting middleware for the show endpoints (lightweight protection against brute force).\n\n## Operational workflow\n1. Admin enables Live Show for an event.\n2. Admin copies the show link and opens it on the playback device.\n3. If link leaks: admin clicks **Rotate link** → all old links stop working.\n\n## Implementation notes (to guide downstream work)\n- Add `events.live_show_token` (random 32+ bytes, base64url/hex) and `events.live_show_token_rotated_at`.\n- New public route e.g. `GET /show/{token}` → serves the player SPA shell.\n- New public API endpoint resolved by token (read-only): `GET /api/v1/live-show/{token}/state` (settings + initial photo batch).\n- Realtime channel uses token to subscribe (or resolves event id server-side after token validation).\n\n## Decision needed from product\n- Confirm whether we want optional **expires_at** (default: no expiry, rely on rotation).\n- Confirm if multiple simultaneous display devices are supported (default: yes; token works naturally).\n","acceptance_criteria":"- Issue records options A/B/C with pros/cons\\n- Clear recommendation (token-only) with security considerations\\n- Concrete implementation notes (DB fields, route shape, revocation workflow)\\n- Explicit product decisions listed (expiry + multi-screen)","notes":"Decision: token-only show link per event; no expiry by default; rely on rotation/invalidation. Multi-screen supported naturally via token.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-05T11:43:11.636746837+01:00","created_by":"soeren","updated_at":"2026-01-05T12:06:45.909441986+01:00","closed_at":"2026-01-05T12:06:45.909441986+01:00","close_reason":"Closed","dependencies":[{"issue_id":"fotospiel-app-h5d","depends_on_id":"fotospiel-app-vro","type":"blocks","created_at":"2026-01-05T11:43:43.272652233+01:00","created_by":"soeren"}]}
{"id":"fotospiel-app-hbt","title":"Moderation queue for guest content","description":"Queue for flagged guest content (photos, feedback). Bulk actions to hide/delete/resolve with audit.","notes":"Land the plane: tests run (FilamentPanelNavigationTest, PhotoModerationQueueTest, TenantFeedbackModerationQueueTest, TenantLifecycle*), migrations added for photo + feedback moderation, no follow-up blockers.","status":"closed","priority":1,"issue_type":"feature","created_at":"2026-01-01T14:18:37.777772819+01:00","updated_at":"2026-01-02T17:33:22.599440896+01:00","closed_at":"2026-01-02T17:33:22.599440896+01:00","close_reason":"Closed"}
@@ -91,6 +93,7 @@
{"id":"fotospiel-app-lnb","title":"SEC-GT-01 Hash join tokens + data migration","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T15:52:01.658868778+01:00","created_by":"soeren","updated_at":"2026-01-01T15:52:07.314317124+01:00","closed_at":"2026-01-01T15:52:07.314317124+01:00","close_reason":"Completed in codebase (verified)"}
{"id":"fotospiel-app-lnf","title":"Remove legacy registration page assets","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-06T08:37:39.419274918+01:00","created_by":"soeren","updated_at":"2026-01-06T08:37:39.419274918+01:00"}
{"id":"fotospiel-app-lqp","title":"Integrations health (Paddle/RevenueCat/webhooks)","description":"Health/status dashboard for payment and webhook integrations.","status":"closed","priority":3,"issue_type":"feature","created_at":"2026-01-01T14:20:25.197673148+01:00","updated_at":"2026-01-02T18:45:16.225355969+01:00","closed_at":"2026-01-02T18:45:16.225355969+01:00","close_reason":"Closed"}
{"id":"fotospiel-app-m76","title":"Event-Admin: Forgot-Password API endpoint (tenant-auth)","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-06T10:44:36.950627645+01:00","created_by":"soeren","updated_at":"2026-01-06T11:01:25.486182309+01:00","closed_at":"2026-01-06T11:01:25.486182309+01:00","close_reason":"Closed"}
{"id":"fotospiel-app-mfz","title":"Playwright: paddle sandbox checkout test fails after login (coupon field missing)","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-06T09:54:27.979177519+01:00","created_by":"soeren","updated_at":"2026-01-06T09:54:27.979177519+01:00"}
{"id":"fotospiel-app-ml7","title":"SEC-GT-03 Tighten gallery/photo rate limits + alerting","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-01T15:52:18.593415508+01:00","created_by":"soeren","updated_at":"2026-01-01T15:52:18.593415508+01:00"}
{"id":"fotospiel-app-mol","title":"Coupon ops: wire analytics into Matomo dashboard","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-01T16:09:27.722458747+01:00","created_by":"soeren","updated_at":"2026-01-02T23:28:18.178704873+01:00","closed_at":"2026-01-02T23:28:18.178704873+01:00","close_reason":"Closed"}