# RD21 final source review Reviewed baseline `8e7e3f6387544e24082ebe2c107c0b868897959e` through `05a7386`, using the supplied exact diff, REQUEST.md, PLAN.md, progress ledger, earlier backend reviews, and connected production source. Verdict: **needs fixes** for the two findings below before final qualification. The main repair is sound in the reviewed paths: source revisions accompany drafts, canonical/Identity/import writes share transactions, EF compares original revisions at the eventual update, and the UI retains rejected drafts. The package draft guard deliberately preserves its original revision when parent props change; keep that property during fixes. ## Findings ### 1. High: expose the committed revision header to browser clients - Changed consumer: `job-tracker-ui/src/applicationWorkspace.ts:313-316`. - Connected configuration: `JobTrackerApi/Program.cs:144-152`; default cross-origin client: `job-tracker-ui/src/api.ts:40-47`. - The new application-drafts client requires `response.headers["x-job-version"]` after the 204 response. The CORS policy allows request headers but never exposes this response header. In the supported localhost UI/API setup, browsers therefore hide it from Axios. The database commits successfully, then the client throws `Missing committed job revision.` and leaves the draft dirty with the previous revision. Retrying that same draft then gets 409. - This is a false failed-save acknowledgement in an ordinary development configuration, independent of an actual conflicting writer. Same-origin requests and Playwright APIRequestContext calls do not exercise the restriction. - Suggested fix: expose `X-Job-Version` through the existing credentialed CORS policy. Retain the client's fail-closed validation. Add an actual cross-origin browser Answers save followed by another save, verifying acknowledgement, the advanced revision, and persisted text. ### 2. Medium: open Answers from a fresh coherent snapshot after other workspace writes - Changed binding: `job-tracker-ui/src/views/ApplicationWorkspacePage.tsx:264-270`. - Connected lifecycle: `ApplicationWorkspacePage.tsx:127-152,159-176,263`; `job-tracker-ui/src/components/ApplicationAssets.tsx:511-547,849-862,881`. - The workspace fetches its overview on mount/job/locale changes and selected callbacks. A successful cover-letter save changes the shared job revision but only updates the cover-letter component; it does not refresh the overview. Changing the application subsection does not load the overview either. Opening Answers then initializes its source revision from that older overview. Example: overview revision 7, save letter to revision 8, open Answers, type an answer, save with expectedVersion 7: 409 despite no competing editor. Reopening Answers repeats the same stale initialization until a full workspace reload or another action happens to refresh its overview. CV attachment and other job mutations without an overview refresh can produce the same stale source. - Suggested fix: fetch a coherent answer/recruiter-text/revision snapshot when entering Answers, or invalidate/refresh the shared overview after all relevant job mutations. Prevent editing before that initial fresh read is accepted; do not merely update a revision independently of its source text, and never replace the revision of an already dirty draft. A cover-letter-only callback fix would leave other shared-job writers unhandled. - Add a connected workspace regression: load workspace, save a cover letter, switch to Answers, save an answer successfully; retain the existing test that parent refresh cannot authorize an older dirty draft. ## Review bounds and deferred judgments - Inspected the Career, generic job, cover-letter, application-drafts and legacy tailored-CV replacement paths, revision mapping/migration, exception handling, related frontend consumers, session response interceptor, workspace mount/unmount behavior, and selected deterministic regression source. Earlier task-1/task-2 backend reviews remain complementary evidence, not new execution results. - Test/build/browser results supplied by the coordinator were not rerun or independently certified here. The supplied full browser run was still pending; partial runs cannot establish full regression acceptance. MariaDB runtime qualification is unavailable and remains outstanding. No production or release-readiness claim is made. - Existing extraction-run discard-versus-accept lifecycle concurrency was considered but not reproduced or expanded into this changed-contract review. The existing discard command has no canonical replacement payload; any separate lifecycle repair needs its own evidence and coordinator scope ruling. - No product files, tests, database, Git state, build or browser lanes were changed. Only this requested review artifact was written. No external network calls were made. ## Assessment **Ready for final acceptance: no, with the two bounded fixes above pending.** Neither finding demonstrates a bypass of the backend stale-write guard; both are user-visible save regressions caused by incomplete integration of the new shared revision contract. Requalify the repaired source, including browser-level acknowledgement and the connected workspace sequence, before reassessing RD21 and Phase 9.