# AI-004 durable CV processing Updated: 2026-08-09 Status: `IMPLEMENTED — NOT VERIFIED`. The repository queue migration and automated tests pass. Parser dependency/isolation work, browser checks, selected-model execution, MariaDB, restart canary and production rollout remain blocked or unverified. ## Revalidated execution path and root cause CV upload previously saved an artifact and held the HTTP request while extraction, reconstruction, classification, normalization, structured parsing and model-capable work completed. Reprocess, rebuild and improve returned 202, but woke an unbounded process-local channel. A hosted service separately scanned queued/running extraction rows at startup. The persistent `CvExtractionRun` protected the review result, but the execution path had no shared admission, lease, deadline, retry, cancellation, provider provenance or persistent notification contract. A proxy/backend restart could therefore lose the wakeup or present a 504 even when later work completed. Live 504 reproduction remains blocked; this is confirmed source-path evidence, not a claimed browser reproduction. ## Implemented contract - Upload now saves the owner-scoped artifact and queued extraction run, enqueues typed `cv.process` work, and returns 202 with the existing safe operation DTO/status URL. It does not parse inside the request. - Reprocess, rebuild and improve use the same producer. The old channel and `CvProcessingHostedService` are removed; AI-001 is the only scheduler/worker. - Operations store only subject type `cv_extraction_run` and the numeric run ID. Raw CV text, filenames, prompts and parser output are not copied into `UserOperations`. - The worker re-enters the operation owner scope, rechecks live Pro/AI policy, and only loads an extraction run owned by that scope. The handler reports provider/model/route metadata when available. - Sequential duplicate uploads with the same content and active rebuild/improve/reprocess requests reuse one active run/operation. The duplicate temporary upload copy is deleted before it is added to the database. - Retryable provider failures leave the extraction run queued while the operation owns retry timing. Final/non-retryable failures become failed. Running cancellation and timeout state are synchronized; generic operation state is embedded in extraction-history responses so refresh resumes queued/retry/cancel/failure UI. - Upload/reprocess reopen the stored owner artifact in the worker. Rebuild/improve pass the worker cancellation token to the metadata-capable generation call. - Successful processing stops at `pending_review`. It does not update profile text/structure/current-version pointers until the existing accept endpoint is called. Discard remains available. - The UI shows queued, local processing, retry wait, approved-fallback wait, failed, cancelled and cancellation-requested states with cancel/retry actions. The upload spinner now ends after admission and reports the queued run rather than false extraction success. No dependency, schema, migration, proxy timeout or production switch changed. `Workers:AiOperationsEnabled` remains false by default. ## Automated evidence - Focused CV/queue/SQLite tests: 40/40 after the final failure-path addition; synthetic files and fake providers only. - Full backend: 594/594. - Focused Career Profile UI: 10/10. - Full frontend: 47/47 suites and 161/161 tests. - Backend build, frontend production build and `git diff --check`: pass; line-ending notices only. - Integration coverage uses real SQLite operation/run/artifact/notification rows and proves 202, active duplicate reuse, no raw CV payload in operation state, owner-scoped execution, provider-failure retry state, one terminal notification and the unchanged human review gate. ## Remaining gates and known limits - SEC-006/007 still own fixed parser versions, page/pixel/decompression/memory/process isolation and complete parser-child cancellation/cleanup. Legacy structured parsing calls are not all cancellation-aware. No malicious file was executed. - Cancellation of an operation before a worker claims it is authoritative in `UserOperation` and shown correctly after refresh; the underlying extraction row is reconciled when retried/processed, but immediate terminal synchronization of that dormant row remains follow-up cleanup work. - Browser localhost is denied by administrator policy. No real browser/mobile/theme/keyboard/refresh/back-forward workflow or screenshot is claimed. - The authorized private CV was not used. Synthetic input must pass the SEC-006/007 gates before that local-only check. - The generic lease tests cover restart recovery, but no CV parser/model process was interrupted and resumed in a runtime canary. - MariaDB, selected Ollama model, worker telemetry, production activation and rollback canary remain unverified. The worker stays default-off. ## Rollback Keep `Workers:AiOperationsEnabled=false`, revert `c3c5af8`, and retain the additive operation/extraction tables. Cancel or drain queued `cv.process` operations before removing the handler. No database downgrade or artifact rewrite is required; existing extraction runs remain readable.