Tri-product root-cause audit — 2026-06-03
43-agent parallel audit across CareerVector / JobCache / sporewright + admin UIs + integration, adversarially verified. 6 of 35 findings confirmed real.
Fixed (committed)
- CV mirror write-protection — the bug CLASS. Five mirror-aware WRITE handlers
resolved a read-only mirror to its source workspace and wrote to it without the
readOnlyguard:POST /workspaces/:id/agent-presence(presence rows) andPOST /llm/{evaluate,extract,salary}(stage-attempt ledger + LLM token spend on the source's BYOK keys). Addedif (resolved.readOnly) return 403 read_only_mirrorto all five./llm/tailoris NOT affected — it never mirror-resolves (a mirror_id 404s instead of mapping to a source). - JC critical — stale observation clobbers task state.
submitObservation's task UPDATE ran unconditionally after the lease release; a stale observation whose lease was expired+reclaimed in the TOCTOU window (no transaction) could overwrite a legitimate result. Gated the task transition onleaseRelease.rowsAffected > 0, else rejectlease-not-active. - JC config fail-fast.
jobcache/shared/src/config.tsnow throws when the command-drain is configured (CAREERVECTOR_WEB_URL/ drain interval) butJOBCACHE_CONTROL_TOKENis empty — an empty token was invisible to Render's/healthzprobe and silently 401'd every drain. Mirrors the DATABASE_URL precedent.
No regressions: @cv/api 17/17, jobcache-shared 31/31, jobcache-interface 71/71;
all typechecks clean.
NEEDS YOUR DECISION (not touched — deliberate + deployment-sensitive)
- JobCache Ops API + MCP auth is STRIPPED. Commit
a1948023("auth-buried: delete jobcache/ops/api gate, every route public") deletedregisterAdminGate+lib/auth.ts; the ops MCP is "Auth-less (stripped 2026-05-18); all tools open".api.ops.jobcache.corbet.ch+mcp.ops.jobcache.corbet.chare internet-facing (Pulumi-wired,jobcache/infra/cloudflare.ts) with NO auth and NO compensating CF-Access policy. Live exposure is MEDIUM, not critical: the truly-destructive actions (source pause/resume, scrape-trigger) forward to the bearer-gated downstream control API and are blocked tokenless; what IS open = unauth audit-log writes, transient badge/state overrides, and read-side info disclosure (cockroach/corpus/ devices/audit). This looks DELIBERATE (commit message + datedAUTH STRIPPEDcomments), so I did NOT restore it autonomously — a naive restore 401s the cockpit and MCP unlessADMIN_TOKENis set + the UI cookie + MCP bearer forwarding re-armed. Decide: re-arm the gate (and wire the token), or confirm it's intentionally open.
Skipped (verified non-issue / fix-as-written would be harmful)
HYDRATABLE_FIELDS(CVlib/server/src/jobcache-lookup.ts) vsWORKSPACE_SAFE_ATTRIBUTES(JCjobcache/shared/src/fact-tree.ts) duplication: the two 9-entry allowlists sit on OPPOSITE sides of an HTTP trust boundary (CV = ingress allowlist on the received payload; JC = egress allowlist before serializing). Intentionally independent. The finder's fix (import the shared constant into the CF Worker bundle) would pull postgres/aws-sdk/pino into the 1 MB-limited Worker AND dissolve the security boundary. Real defect is minor and fail-safe; left as-is.
Follow-ups (safe, deferred)
- Enforcement hardening for the mirror class (stops recurrence): make
assertWritable(resolved)real —lib/server/src/mirror.ts's own doc comment tells callers to use it but it does not exist — and makeResolvedWorkspaceaSourceWorkspace | ReadOnlyWorkspacediscriminated union so the compiler forces a readOnly check beforesourceIdis usable on a write path. - Regression tests: 403-on-mirror_id for the 5 guarded handlers; a
submitObservationstale-lease reject test (noUPDATE taskswhen the lease is no longer active). submitObservationtransactional wrap: the rowsAffected gate is the load-bearing fix; the residual two-statement race wants the lease load + lease+task UPDATEs wrapped in a transaction the wayleaseTaskalready does.
kind: journal nodes:
- tri-product-root-cause-audit-2026-06-03
summary: "Working record of the CareerVector, JobCache, and shared-infrastructure root-cause audit on 2026-06-03."
links:
event:
- tri-product-audit-event-2026-06-03 anomaly:
- tri-product-root-cause