Files
jobtrackingapp/docs/redesign/phase-9/rd21-remediation/ACCEPTANCE_ADDENDUM_2026-10-23.md
T

144 lines
12 KiB
Markdown

# RD21 acceptance addendum — 23 October 2026
**The reproduced SQLite stale-write and partial-commit defects are repaired and locally verified.
Formal RD21 remains UNRESOLVED because the unchanged issue requires supported MariaDB runtime
evidence. Phase 9, Phase 10 readiness and production remain NO-GO.**
This supplements the original [Phase 9 acceptance](../p9-07/FINAL_ACCEPTANCE.md); it does not
rewrite its historical findings or approval boundaries. The remediation uses the requested
`fix/rd21-acknowledged-edit-loss` branch from final Phase 9
`8e7e3f6387544e24082ebe2c107c0b868897959e`. Qualified product checkpoint: `1b89a77`.
## Separate acceptance decisions
| Decision | Disposition and evidence boundary |
| --- | --- |
| A. RD21 | **UNRESOLVED (qualification).** SQLite implementation repair passes. The [original required closure evidence](../p9-04/RD21_CONCURRENCY_ISSUE.md) explicitly includes MariaDB runtime constraints, held readers/writers and partial failure. That qualification remains absent. |
| B. Phase 9 functional QA | **NO-GO.** Local remediation assessment and complete automated regression are finished, but formal RD21 and original output/provider/manual conditions remain open. |
| C. Human accessibility/device acceptance | **Outstanding.** Fresh automated route/accessibility diagnostics do not replace NVDA/VoiceOver, physical touch/drag/software keyboard, forced colours, human zoom/reflow or professional Bokmål review. Original manual rows remain. |
| D. Provider/database qualification | **SQLite verified locally; MariaDB NOT TESTED.** No inference from SQLite or SQL generation to MariaDB runtime. External providers, enabled-worker recovery and model semantics remain separate. |
| E. Phase 10 readiness | **NO-GO.** Preserve all routes, compatibility paths, canonical/CV/frozen boundaries and remaining criteria. This handoff authorizes no cleanup/deletion or Phase 10 implementation. |
| F. Production | **NO-GO.** Storage faults, backup/restore/rollback, live advisories, deployment identity, ingress and provider/manual gates remain. No production database, migration, service restart, filesystem repair, deployment or model action occurred. |
## Reproduction and exact root cause
The unchanged original characterization ran at the exact baseline using two independent
authenticated clients and synthetic SQLite data. Both clients read one record. A successfully
saves a changed summary/title; B submits its older complete snapshot with a different field
changed. Career accepts B with 200; jobs accepts B with 204. Fresh reads restore A's field to its
old value: both `lostFirstEdit=true`. Its one passing characterization is evidence of unsafe
behavior, not a safety pass. [Captured observations](original-reproduction.json).
Both domains lacked the editor's source precondition on replacement writes. Career incremented
an internal version without comparing the source revision or enforcing it as an EF concurrency
token. Jobs had no equivalent revision token. A new request could therefore load the current row
and replace it with arbitrarily old client fields. The optional awaited job summary also left a
read/write interval that a controller-only comparison could not protect.
Career had a second proven failure: the canonical aggregate transaction committed before the
controller's Identity projection update. Injecting an Identity failure left canonical content
changed despite a failure response. Parse and reviewed import acceptance shared that split
boundary. Native SQLite RED tests capture persisted loss and partial commits; see
[before-regressions.json](before-regressions.json) and [root-cause analysis](ROOT_CAUSE.md).
## Implemented correction
Career source snapshots expose a coherent revision. Manual save, history restore, parse and
reviewed import acceptance require that revision. EF compares the original version at the
eventual database write, and competing first saves use the existing unique owner constraint.
Canonical children/history, raw text, Identity projection and applied-import metadata commit in
one transaction. Failure rolls back and clears failed tracked changes. GET no longer backfills
unversioned canonical data. The obsolete identity-only CV projection bypass fails closed.
Jobs have an application-managed EF concurrency token, advanced by every tracked job mutation.
Generic replacement and directly related cover-letter, application-answer and legacy tailored-CV
snapshot writers require their source revision. Related persisted text loss was reproduced
before extending the correction. Opportunity/timeline changes remain in the same SaveChanges
transaction; rejected requests append no success history or side effects. Generic Notes editing
preserves the separately embedded application answer and validates company ownership.
Clients keep source revision and draft together. They acknowledge saves after successful server
responses, retain rejected/network-failed drafts, exclude overlapping edits and late modal/read
responses, and require deliberate review/reload after conflict. They never fetch a newer revision
to authorize an older body. Whole-branch review found two integration defects: the committed job
header was hidden by CORS, and Answers could mount from a stale overview after a sibling write.
Both received deterministic RED evidence, one fix wave and a clean scoped re-review. Actual
cross-origin JavaScript and native successive saves prove the repaired integration.
[SAVE_CONTRACT.md](SAVE_CONTRACT.md) specifies endpoint/status/revision compatibility. Older
unversioned replacement clients intentionally fail closed: missing Career preconditions return
400, stale Career returns 409, and missing/invalid/stale job revisions return 409. Existing 204
job writes return the committed `X-Job-Version`, exposed by the allowlisted credentialed CORS
policy. No automatic stale retry, silent merge, arbitrary delay or new dependency was added.
## Completed verification
| Lane | Actual final result |
| --- | --- |
| Backend Release | **1,109 passed**, zero failed/skipped, exit 0; actual SQLite persisted-state, overlap, rollback, tenant, first-save, stale restore/import and populated migration upgrade/rollback/reapply coverage. |
| Frontend Jest | **934 passed / 105 suites**, zero failed/pending/todo, exit 0 on final source. |
| Ordinary browser | **362 passed**: serial shards 98 + 87 + 88 + 89; exact unique discovery membership, four exit 0 outcomes, no run errors/retries/skips/flakiness. |
| Separate browser contracts | **23 passed**: AI withholding 2, auth recovery 2, rate limits 9, ingress 6, PDF admission 1, preferences 3; no retries/skips/flakiness. |
| Sidecar | **56 passed**, zero failed/skipped, exit 0; `SKIP_MODEL_LOAD=1`, no model semantics claim. |
| New remediation browser | **6 passed**, no retries/skips: original A/B ordering, independent immediate SQLite reads, navigation/refresh/new authenticated session, missing revisions, native draft retention/recovery, actual cross-origin header, successive Answers saves and fresh source entry after letter save; includes conforming bounded sustained workload. |
| Conforming volume companion | **3 passed**: 100 CV revisions/additive restore, 100 exact timeline messages and 100 cancellation notifications/ownership/counts. Only Career seed revision supplied; original assertions retained. |
| Unchanged historical diagnostics | **16 passed / 2 failed**, exit 1: old Career seeds in `data.spec.ts` and `sustained.spec.ts` expect 200 without a revision and receive 400. Actual failures retained; zero skipped/retried. |
| Unchanged historical volume | **2 passed / 1 failed**, exit 1: old CV-volume Career seed also expects unversioned 200 and receives 400. Actual failure retained. |
| Types/lint/build | Final full TypeScript and ESLint exit 0; API Release and UI static export builds pass. New companion diagnostics receive separate TypeScript checking. No deployment. |
| Offline security | Supply-chain 3, evaluator 5, browser-runtime 6, ingress 3, Node dependency/SMTP 15 and extension 3 pass; tracked-secret scan passes and SBOM generated. No live advisory refresh. |
| Native PDF oracle | **16/16 standard fixtures, 36 pages; 8/8 Settings fixtures, 24 pages**. Unchanged oracle/tolerances, exact membership/page counts, inputs hashed before/after verification against final shard-produced bytes. Automated fidelity evidence; no new human/print/device acceptance. |
[validation.json](validation.json) retains exact cases, process timestamps/exits and report hashes.
The final source manifest binds **878 inputs**, SHA256
`7487f343786928e90a3c8a740571c29e5c934c80fa822abb80c7a39483e1353b`, including source,
active fixtures, historical diagnostics, static export and API/test assemblies. Source checks
before ordinary shards and after final diagnostics found no drift. The later conforming volume
copy has separate original/copy hashes in its [fixture provenance](volume/fixture-provenance.json).
The unchanged original reproduction was rerun and intentionally retained its actual post-fix
failure at the now-invalid unversioned seed. The conforming companion preserves the same A/B
read/write ordering with each source revision and stronger assertions: A's commit is read directly
from SQLite immediately after acknowledgement; B receives 409; A's values/history/projection
remain after rejection, navigation, reload and a new authenticated session. This is an explicit
contract adaptation, not a changed historical test or an assertion that the old fixture passed.
Counts are separate lanes, never summed into a blanket all-green total. Focused tests overlap full
suites; initial remediation 4 and focused integration 2 overlap final 6. Pre-review Jest 930 is
superseded by final 934. One earlier ordinary run was interrupted after 22 passes for confirmed
review findings and is not a completed suite. Baseline unsafe characterization and native RED
records remain. The initial job RED runner overwrote its first raw TRX; that provenance limitation
is disclosed in before-regressions.json rather than replaced with fabricated raw evidence.
The finite sustained run shared its host with frontend/static qualification work; it is a bounded
correctness workload and cannot establish an uncontended performance baseline or SLA.
## Provider, preservation and remaining risks
Docker `default`, `desktop-linux` and `desktop-windows` read-only probes failed because engine
named pipes were absent. No native MariaDB/MySQL executable or common Program Files installation
was found. No service installation, restart, download or production access was attempted.
MariaDB concurrency/first-save constraints/held-reader-writer/partial rollback must be exercised on
an isolated disposable supported instance before formal closure. Do not infer deployment safety
from a generated SQL script or the local SQLite migration test.
All **57 groups and 33 routes** remain; **56 PARTIAL / C11 DEFERRED**, zero upgrades to PASS.
Original remaining criteria and historical observations are retained in the
[reconciliation](PRESERVATION.md). Canonical versus CV-specific null-as-inherit overrides,
append-only revisions and submitted/frozen archives retain their passing native contracts.
The [related review](RELATED_REVIEW.md) distinguishes already-guarded Dashboard/CV/email drafts,
narrow job lifecycle commands and independent settings/company/contact records. This is not
complete multi-session acceptance of every independent editor.
Historical overwritten edits are not proven recoverable. Existing history may help a specific
record, but no live records were inspected and no recovery is claimed. Creation-intent idempotency
remains separate and unimplemented. Extraction discard-versus-accept lifecycle concurrency was
considered but not reproduced; it is not certified by these replacement-write tests. Unknown
network outcomes still require deliberate current-data review before retry. Mixed old/new clients
and servers, real MariaDB and production rollback remain unqualified; schema downgrade does not
preserve revision identity. Original duplicate reminder GET and raw `Created` terminology findings
remain separate low-priority observations.
Next qualification: run the same persisted-state, transaction/tenant and migration contracts on
disposable MariaDB; complete the original manual/provider/output/release gates; then reassess
RD21 and Phase 9. Phase 10 receives this blocked handoff only. No main merge, production action,
model activation, new integration or Phase 10 implementation is authorized by this addendum.