Hartmut
1d6d75ecf6
fix(api): wrap critical mutations in transactions and fix TOCTOU race conditions
...
- applyProjectScenario: wrap assignment loop in db.$transaction to prevent partial updates
- vacation approve/reject: fix TOCTOU race via updateMany with status-guard in WHERE + CONFLICT on count=0
- vacation cancel: wrap vacation.update + entitlement.updateMany in $transaction
- batchApprove: collect mutations, wrap in $transaction, dispatch SSE/notifications after commit
- Fix dead-code bug in createHappyPathDb where $transaction was assigned after return
- Add atomicity and concurrency tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-09 08:34:59 +02:00
Hartmut
e3c585a403
test(scenario): add unit regression coverage for all four scenario modules
...
Previously untested business logic — no direct tests existed for the
scenario domain beyond auth guards and delegation stubs.
scenario-shared.test.ts (13 tests)
- roundToTenths: rounding edge cases
- getScenarioAvailability: null/undefined fall through to DEFAULT_AVAILABILITY
- collectScenarioSkillSet: null, empty, lowercase, dedup, whitespace filter
- calculateScenarioEntryHours: null resourceId → calculateAllocation,
non-null → calculateEffectiveBookedHours with context map lookup
scenario-apply.test.ts (6 tests)
- NOT_FOUND guard
- remove:true → CANCELLED status, not counted in appliedCount
- assignmentId without remove → update branch, appliedCount 1
- no assignmentId / no resourceId → skipped, appliedCount 0
- resourceId only → create with computed dailyCostCents (lcrCents × hours)
- mixed changes → correct aggregate appliedCount
scenario-baseline.test.ts (6 tests)
- NOT_FOUND guard
- empty project → zeroed totals
- costCents computed from lcrCents × effective hours
- CANCELLED assignments excluded via findMany WHERE filter
- demands mapped with headcount and roleName from roleEntity
- totalCostCents is sum of all assignment costCents
scenario-simulation.test.ts (6 tests)
- NOT_FOUND guard
- unchanged carry-through → delta.headcount 0
- remove change → delta.headcount -1
- new resource → delta.headcount +1
- budget exceeded → warnings includes /exceeds budget/i
- skill coverage → delta.skillCoveragePct > 0 when scenario adds skills
Co-Authored-By: claude-flow <ruv@ruv.net >
2026-04-02 21:30:46 +02:00