fix(web): guard admin jobs with legal state transitions - #5746
Conversation
Add nextJobStatus (mirroring nextLeadStatus) so illegal action/status pairs reject with 400 invalid_transition instead of applying unconditionally. Decision (a) on JSONbored#5270. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-31 20:55:22 UTC
Review summary Nits — 5 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. Decision record
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5746 +/- ##
==========================================
- Coverage 96.44% 96.42% -0.02%
==========================================
Files 532 532
Lines 16401 16414 +13
Branches 3751 3756 +5
==========================================
+ Hits 15818 15828 +10
- Misses 195 198 +3
Partials 388 388
🚀 New features to boost your workflow:
|
Summary
nextJobStatus) matching listing-leads'nextLeadStatus.JobInvalidTransitionError; the admin jobs PATCH route returns400 invalid_transition.activate/reactivateis unchanged.invalid_transition400 path (coverage gap on the prior attempt).Closes #5270
Supersedes #5524 (closed by screenshot-gate false positive on a non-visual admin API change; this reland embeds the required viewport×theme matrix like merged #5536 / #5398).
Submission Source
Quality Evidence
PATCH /api/admin/jobs(apps/web/src/routes/api/admin/jobs.ts)apps/web/src/lib/job-admin-lib.ts,apps/web/src/lib/job-admin.tstests/job-admin-lib.test.ts,tests/d1-dynamic-state.test.ts,tests/admin-jobs-invalid-transition.test.ts400witherror.code = "invalid_transition"and{ action, currentStatus }details.activatefirst-publishes fromdraft/pending_reviewonly (not fromclosed/archived)reactivatereopensstale_pending_review/closedonlystaleonly fromactivearchivedis terminalrevalidatenever changes status and remains allowed from any known statusactivate/reactivateunchangedNewly blocked (was previously allowed)
archivedactivate,reactivate,stale,close,expire,review,archiveclosedactivate,stale,review,expire,closereactivate/archivedraftstale,reactivate,close,expirereview/activate/archivepending_reviewstale,reactivate,expire,reviewactivate/close/archiveactiveactivate,reactivate,reviewstale/close/expire/archive/revalidatestale_pending_reviewactivate,stale,reviewreactivate/close/expire/archiveStill allowed (unchanged intent)
draft→review/activate/archivepending_review→activate/close/archiveactive→stale/close/expire/archive/revalidatestale_pending_review→reactivate/close/expire/archiveclosed→reactivate/archiverevalidatefrom any known status (no status change)UI Evidence
Before/after identical (admin JSON API + lib lifecycle guard only; no rendered HTML/page/theme delta).
Validation
pnpm exec vitest run tests/job-admin-lib.test.ts tests/d1-dynamic-state.test.ts tests/admin-jobs-invalid-transition.test.ts tests/web-job-admin.test.ts(286 passed)pnpm exec vitest run tests/api-contracts.test.ts tests/api-contracts-lib.test.ts(420 passed)pnpm type-check(clean)pnpm exec prettier --checkon changed files (clean)git diff --check(clean)