46 lines
6.9 KiB
Markdown
46 lines
6.9 KiB
Markdown
# Career Profile import contracts
|
|
|
|
26 October 2026. `CareerProfileService` remains the only canonical profile/history/revision writer. No CV variant, letter, submitted package, application association or frozen document is rewritten by import.
|
|
|
|
## API and lifecycle
|
|
|
|
- `POST /api/profile-cv/import`: authenticated Pro PDF/DOCX upload, 5 MiB limit, file signature/archive validation, safe owned artifact name and SHA-256, existing durable `cv.process` admission. New runs use `document_import` / `docling-v1`. Legacy `/upload` remains available until replacement qualification.
|
|
- `GET /runs/{id}/review`: owned source text, original filename, warnings, current canonical revision and explicit fields grouped by supported Career Profile category. Each field has current/imported values and source method/snippet/page. Metadata does not substitute for authorization.
|
|
- `GET /runs/{id}/source`: authenticated owner-scoped original-file response with private/no-store and nosniff headers. Frontend fetches an authenticated blob; token credentials are never placed in an iframe URL.
|
|
- `POST /runs/{id}/apply-reviewed`: `expectedVersion` plus allowlisted decisions `{id,action,value?}`. Keep skips a field; use/add accepts its extracted value; correct records an explicit user correction. Missing decisions are omitted, never implicitly accepted. An empty selected set is refused and the user can discard instead. Legacy `/accept` refuses `docling-v1` runs.
|
|
|
|
The existing queue supplies admission limits, ownership scope, durable operation status, attempts/deadlines, cancellation, recovery and retry. Real extraction/interpretation/readiness stages are persisted, with no simulated percent. Heartbeats preserve the latest reported stage and cancel execution if renewal fails. Final publication checks the active operation lease/cancellation state in the database predicate. Recovery qualification is distinct from actual model quality.
|
|
|
|
The additive `20261026090000_AddCvImportReviewEvidence` migration adds nullable `DocumentJson` and `ReviewJson` to existing extraction runs. No second master profile, queue, storage root or revision counter is introduced. Account export serializes extraction records including these columns; account deletion already deletes owned runs/artifacts and files.
|
|
|
|
## Supported fields and evidence
|
|
|
|
Canonical `StructuredCvProfile` is authoritative: contact (including GitHub and labelled links), summary, jobs, education, certifications, projects, skills, languages, interests, awards, publications, organisations, references and custom sections. Courses and other unsupported typed domains remain custom section items. Existing schema has no separate experience-duration or arbitrary qualification records.
|
|
|
|
`CvDocumentInterpreter` interprets structural blocks/headings and labelled fields conservatively. Clear delimited employment/education records retain source date strings and current markers. Unknown employment stays as reviewable source rather than inventing a role or employer. Missing language proficiency remains null. Unclassified source remains visible. The current deterministic grammar is bounded; unconventionally arranged documents may require corrections. Native PDF table structure is explicitly limited.
|
|
|
|
`CvDocumentReview.Ground` removes unsupported candidate strings, refuses inferred date precision and attaches source block/page/snippet to significant fields. Fixed heuristic confidence percentages are not used in this path. Current employment is a labelled normalization of a supported source marker. The original extraction is stored on the run; approved/corrected profile metadata and the actual reviewed decisions preserve their origin. No AI-generated facts enter the active deterministic path.
|
|
|
|
## Merge and revision safety
|
|
|
|
Review IDs are generated from the typed extracted profile; callers cannot submit arbitrary JSON patches. Invalid/duplicate/excessive paths/actions and invalid corrections are refused. Existing profile validation and a serialized-size bound apply before persistence.
|
|
|
|
Jobs match only on complete normalized employer/title/start/end; education on institution/qualification/start/end; certificates on name/issuer/date; projects on name/role/start/end. Incomplete or conflicting identifiers are conservatively new records. Similar titles alone never trigger an update. Language names and custom-section titles are category-specific matches. Duplicate existing matches remain new/reviewable rather than choosing an arbitrary record. List entries append uniquely, and unrelated contact links are preserved by labelled matching. Existing values absent from the upload remain untouched.
|
|
|
|
Apply loads the canonical revision and writes profile, relational children, append-only history, Identity projection and run acknowledgement inside the existing atomic transaction. Identity/projection failure rolls everything back and clears tracked mutations. A stale expected revision returns 409. A repeated identical applied request returns its original recorded acknowledgement without creating another profile version; different decisions on an applied run return conflict. Stable IDs remain assigned by the existing owner. CV overrides, inheritance and frozen documents remain outside this transaction's write scope.
|
|
|
|
## Source retention
|
|
|
|
The new hosted retention sweep runs on startup and hourly. New import source files last at most seven days, or one day after failed/cancelled/discarded work, subject to sweep timing. Abandoned review/processing expires; the user must reupload. Late operations are revoked before source deletion. Files must resolve within the configured CV artifact root; failed deletions retain their database reference for retry. Canonical approved facts/history are retained according to existing account policies, and are removed through existing account-deletion controls. Pending review is no longer silently pruned by the generic 20-completed-run history cap.
|
|
|
|
## Evidence and retained failures
|
|
|
|
- Entry provider: 64/64 actual MariaDB PASS.
|
|
- `provider-review-01`: FAIL, new redundant startup repair called a SQLite-only helper on MariaDB. Removed the repair; the additive migration owns these columns.
|
|
- `provider-review-02`: 67/69; current migration expectation and rollback-detached test entity fixture were corrected without relaxing behavior.
|
|
- `provider-review-03`: 69/69 actual MariaDB PASS, no skips; includes new reviewed application/rollback/idempotency/stale/ownership/down-up cases, plus retained RD21/letter/frozen-package coverage. Generated service cleanup exited zero.
|
|
- `parser-red-01`: three real structural-parser failures before the block interpreter; successor `parser-green-01` passed 46 focused cases.
|
|
- `retention-green-01`: 50 focused cases PASS. `link-merge-red` reproduced unrelated-link replacement; `review-safe-green-01` passed 51 focused cases after correction.
|
|
|
|
Focused runs overlap full regression and each other. They must never be added together. Final source-frozen regression/provider acceptance is still a separate checkpoint.
|