randomayzer/agents/antigravity/inbox/TASK-2026-08-21-04-snapshot-unlock.md

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

  1. Implement POST /api/giveaways/[id]/unlock endpoint:
    • Security: requireGiveawayOwner, CSRF-guard, user-scoped rate limiting (expensiveApiRateLimiter), Idempotency-Key support.
    • Atomic state transition SNAPSHOT_LOCKED -> READY.
    • Rejects DRAWN and PUBLISHED states with 409 Conflict.
  2. Atomic repository transition unlockSnapshot(id: string) in both MemoryGiveawayRepository and PrismaGiveawayRepository:
    • Enforce condition status: 'SNAPSHOT_LOCKED'.
    • Reset seed: null in DB in the same atomic transaction.
    • Versioning strategy: keep historical snapshots with incrementing version (version = max(version) + 1 upon next lock) or manage previous snapshot records cleanly.
  3. Expose GiveawayStore.unlockSnapshot(id).
  4. 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.
  5. 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.
  6. Verification Gate:
    • npm ci, npx prisma generate, npm test, npm run lint, npm run build, npx tsc --noEmit.
  7. Output report in agents/antigravity/done/TASK-2026-08-21-04-snapshot-unlock.md.