1.8 KiB
1.8 KiB
Task 04: Разблокировка SNAPSHOT_LOCKED → READY
Assigned to: Antigravity (Implementation Orchestrator)
Priority: MEDIUM (functional regression)
Date: 2026-08-21
Base SHA: fb6ae616285aebe4ef6ac1436cd0861664f3ba0d
Scope
- Implement
POST /api/giveaways/[id]/unlockendpoint:- Security:
requireGiveawayOwner, CSRF-guard, user-scoped rate limiting (expensiveApiRateLimiter),Idempotency-Keysupport. - Atomic state transition
SNAPSHOT_LOCKED->READY. - Rejects
DRAWNandPUBLISHEDstates with409 Conflict.
- Security:
- Atomic repository transition
unlockSnapshot(id: string)in bothMemoryGiveawayRepositoryandPrismaGiveawayRepository:- Enforce condition
status: 'SNAPSHOT_LOCKED'. - Reset
seed: nullin DB in the same atomic transaction. - Versioning strategy: keep historical snapshots with incrementing version (
version = max(version) + 1upon next lock) or manage previous snapshot records cleanly.
- Enforce condition
- Expose
GiveawayStore.unlockSnapshot(id). - Update UI: on Step 4 of the wizard (
src/app/giveaways/new/page.tsx), add a button to unlock snapshot and return to Step 3 with filter adjustment. - Create regression and concurrency test suite
tests/snapshot-unlock.test.ts:- Full cycle: lock -> unlock -> change rules -> lock -> draw.
- Seed and commitment before and after unlock/re-lock are different (CSPRNG re-generated).
- Unlock from
DRAWN->409 Conflict. - Unlock of another user's giveaway ->
403 Forbidden. - Concurrent unlock requests: exactly 1 succeeds, remaining return
409 Conflict.
- Verification Gate:
npm ci,npx prisma generate,npm test,npm run lint,npm run build,npx tsc --noEmit.
- Output report in
agents/antigravity/done/TASK-2026-08-21-04-snapshot-unlock.md.