diff --git a/PHASE-8-PROGRESS.md b/PHASE-8-PROGRESS.md index c76920f..042276d 100644 --- a/PHASE-8-PROGRESS.md +++ b/PHASE-8-PROGRESS.md @@ -16,12 +16,12 @@ ## Plan 8a — Public intake links and route - [x] Task 1: Schema — `c99be4d`. Bridge: plan assumed `getOrCreateCollection` extended existing select values; it doesn't, so added `ensureCardsCreatedByRoleValues` and extended `ensureActivityActionValues`. Tests: 446 pass. -- [ ] Task 2: Token generator -- [ ] Task 3: Best-effort client IP -- [ ] Task 4: Rate limiter -- [ ] Task 5: Token resolver and daily counter -- [ ] Task 6: Middleware carve-out -- [ ] Task 7: The public Server Action +- [x] Task 2: Token generator — `36572d9`. 24 bytes CSPRNG → base64url → 32 chars. `isIntakeToken` matches. +- [x] Task 3: Best-effort client IP — `f608931`. x-forwarded-for → x-real-ip → "unknown". +- [x] Task 4: Rate limiter — `70ce019`. 60 req / 5 min per opaque key, in-memory, lossy on restart. 4 unit tests. +- [x] Task 5: Token resolver and daily counter — `3ece6cb`. `resolveIntakeLink`, `isLinkUsable` with lazy date-reset, `validateIntakeLinkForStep` returns 3-valued LinkState. +- [x] Task 6: Middleware carve-out — `65b0cf4`. `/intake/:path*` short-circuits before cookie check. +- [x] Task 7: Public Server Action — `9081659`. token-shape → rate-limit → daily-cap → `nextStep`. Same `InterviewStep` shape as signed-in. - [ ] Task 8: The public submission route - [ ] Task 9: Minimal intake layout - [ ] Task 10: The public intake page