The hub responds with `Access-Control-Allow-Origin: *`, and the CORS
spec forbids the wildcard + credentials combination. Firefox rejects
the preflight before any response reaches JS, surfacing as
"NetworkError when attempting to fetch resource" when a user clicks
"Supprimer cette tâche" on an already-completed step (or any step).
Every other HUB_URL call in the ops SPA already omits credentials —
aligning TaskNode with the rest of the codebase is the simplest fix.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- contracts.js: _inferPlanName now reads the Quotation's first positive-rate
item ("Internet Megafibre 80 Mbps") instead of generic fallback.
- contracts.js: subPayload writes service_contract back-ref so an active/
pending sub blocks its parent contract's deletion (LinkExistsError).
- contracts.js: GET /contract/audit-orphans[?fix=1] scans for orphaned subs
(dangling contract link or no link at all) and contracts without a sub;
filters out 2026-03-29 legacy-migration batch via LEGACY_CUTOFF.
- dispatch.js: deleteJobSafely() rewires children's depends_on to the
victim's parent, re-parents descendants if victim was chain root, then
deletes. POST /dispatch/job-delete exposes it. Fixes LinkExistsError
when users delete a middle step in the UI.
- TaskNode.vue: confirmDelete calls /dispatch/job-delete and surfaces a
warning when dependents will be rewired.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>