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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Implements the backend of the #329 design (spike doc on that issue; epic #323).
AnonymousSessionMongo doc (opaque GUID id, createdAt, lastSeenAt) with 90-day idle TTL index;POST /api/Lessons/anonymous/session(anonymous, tight per-IP Redis rate limit)anonymousLessonProgresscollection keyed(anonId, lessonNumber)+ TTL; shape mirrorsUserLessonProgressminus identityGET /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)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 intoUserLessonProgress, delete anon records, triggerCheckAutoAwardsso claimed lessons retroactively earn skills; response reports lessons claimed + skills awarded for the celebration UXGuardrails from the design: grading rigor identical to authenticated flow; skills stay account-only; sandbox untouched.
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 — merged to
master. Backend anonymous sessions, graded anon progress, horizon computation, and sign-in claim landed in PR #56 (0fbe895). Closing.