Re-applies 4 defects merged with Phase 3 (still present on main), ported from the stale reference branch and adapted to current main. FIX 1 (BLOCKER): all 5 budget routes (GET/burndown/PUT/pause/resume) read productId from the URL with no caller check, so a caller for product A could read or modify product B budget. Add requireOwnProduct() -> 403 on mismatch. FIX 2: stop tracking services/platform-service/.data/platform-events.json (the EVENT_BUS_FILE runtime log); gitignore .data/. FIX 3: accrueSpend was definition-only (budgets never accrued) and not idempotent. Add accruedRunIds to FleetBudgetDoc; accrueSpend(productId, costUsd, runId) no-ops on a seen runId; wire it into patchJobFenced on stage shipped, flag-gated + best-effort + idempotent via jobId:leaseEpoch. Accrue the run ACTUAL insights.costUsd so spentUsd and costBurndown agree. FIX 4: submitChildren cycle detection is now batch-aware — rejects duplicate child keys and walks each child declared deps across BOTH the unpersisted batch and existing jobs, rejecting child-self, child-parent and sibling cycles. Tests: +2 budget-authz (403 on all 5 verbs), +3 accrual (idempotent runId, ship accrues insights.costUsd once, flag-off no accrual), +5 cycle detection. Gates green: tsc/build, fleet+items (204), full suite (only the unrelated single-fork migration-isolation file flakes, passes isolated). Flags stay default-OFF. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
6 lines
91 B
Plaintext
6 lines
91 B
Plaintext
node_modules/
|
|
dist/
|
|
|
|
# Local datastore (memory provider event log) — never commit
|
|
.data/
|