[Ratio unlocks 1/2] Backend: anonymous sessions, graded anon progress, horizon, sign-in claim #331

Closed
opened 2026-07-02 02:45:40 +00:00 by spikerj · 2 comments
Owner

Implements the backend of the #329 design (spike doc on that issue; epic #323).

  • AnonymousSession Mongo doc (opaque GUID id, createdAt, lastSeenAt) with 90-day idle TTL index; POST /api/Lessons/anonymous/session (anonymous, tight per-IP Redis rate limit)
  • anonymousLessonProgress collection keyed (anonId, lessonNumber) + TTL; shape mirrors UserLessonProgress minus identity
  • Anonymous grading variants reusing the strategy/attempt-token path unchanged: GET /api/Lessons/{n}/attempt/anonymous, POST /api/Lessons/{n}/submit/anonymous — server-side horizon check before serving an attempt (never trust the client's horizon), per-anonId + per-IP rate limits, daily completion cap (config, default 20)
  • Horizon computation: visibleCount = freeAllotment(language) + floor(completions × 1.5) over display-number order; free allotment = Tiers 0–1 per language; GET /api/Lessons/anonymous/horizon?language=
  • POST /api/Lessons/progress/claim ([Authorize]): idempotent migration of the anon ledger into UserLessonProgress, delete anon records, trigger CheckAutoAwards so claimed lessons retroactively earn skills; response reports lessons claimed + skills awarded for the celebration UX
  • Unit tests: horizon math, claim idempotency, horizon enforcement on attempt-serve, TTL configuration

Guardrails from the design: grading rigor identical to authenticated flow; skills stay account-only; sandbox untouched.

Implements the backend of the #329 design (spike doc on that issue; epic #323). - [ ] `AnonymousSession` Mongo doc (opaque GUID id, createdAt, lastSeenAt) with 90-day idle TTL index; `POST /api/Lessons/anonymous/session` (anonymous, tight per-IP Redis rate limit) - [ ] `anonymousLessonProgress` collection keyed `(anonId, lessonNumber)` + TTL; shape mirrors `UserLessonProgress` minus identity - [ ] Anonymous grading variants reusing the strategy/attempt-token path unchanged: `GET /api/Lessons/{n}/attempt/anonymous`, `POST /api/Lessons/{n}/submit/anonymous` — server-side horizon check before serving an attempt (never trust the client's horizon), per-anonId + per-IP rate limits, daily completion cap (config, default 20) - [ ] Horizon computation: `visibleCount = freeAllotment(language) + floor(completions × 1.5)` over display-number order; free allotment = Tiers 0–1 per language; `GET /api/Lessons/anonymous/horizon?language=` - [ ] `POST /api/Lessons/progress/claim` (`[Authorize]`): idempotent migration of the anon ledger into `UserLessonProgress`, delete anon records, trigger `CheckAutoAwards` so claimed lessons retroactively earn skills; response reports lessons claimed + skills awarded for the celebration UX - [ ] Unit tests: horizon math, claim idempotency, horizon enforcement on attempt-serve, TTL configuration Guardrails from the design: grading rigor identical to authenticated flow; skills stay account-only; sandbox untouched.
spikerj added the enhancement label 2026-07-02 02:45:40 +00:00
Author
Owner

Done in spikersoft-backend#56 (merged to master). Ships anonymous sessions + PII-free progress ledger (TTL/unique indexes), the server-authoritative horizon (freeAllotment + floor(completions×1.5), Tiers 0–1 free), anonymous attempt/submit (423 beyond horizon, 20/day cap, reuses the worker regrade path), and the idempotent sign-in claim (retroactive skill awards, ledger dropped). 28 tests green; WASM link-includes verified clean. Closing — frontend #332 is next.

Done in spikersoft-backend#56 (merged to master). Ships anonymous sessions + PII-free progress ledger (TTL/unique indexes), the server-authoritative horizon (`freeAllotment + floor(completions×1.5)`, Tiers 0–1 free), anonymous attempt/submit (423 beyond horizon, 20/day cap, reuses the worker regrade path), and the idempotent sign-in claim (retroactive skill awards, ledger dropped). 28 tests green; WASM link-includes verified clean. Closing — frontend #332 is next.
Author
Owner

Done — merged to master. Backend anonymous sessions, graded anon progress, horizon computation, and sign-in claim landed in PR #56 (0fbe895). Closing.

Done — merged to `master`. Backend anonymous sessions, graded anon progress, horizon computation, and sign-in claim landed in PR #56 (`0fbe895`). Closing.
Sign in to join this conversation.