Implement B01-B06 with regression coverage and retained validation evidence. Preserve the production ingress preflight; F04 runtime verification remains open.
15 KiB
Verification record
Assessment date: 2026-09-07. Source baseline: main, 7d641edc7bca866ccf06012897ba1d107c07e59f. The starting working tree was clean. The audit adds only this report directory, an observational harness and a TODO entry. No application/controller/schema/deployment correction is represented as completed.
Environment and boundaries
Windows with installed .NET SDK 9.0.317 at C:\Users\Connor\.dotnet\dotnet.exe, Node 24.19.0, the existing UI dependencies/Chromium, and tools/summarizer/.venv/Scripts/python.exe. The dotnet initially on PATH had no SDK; the explicit SDK path above was used. No dependency installation/download was needed.
Backend checks used test fixtures and synthetic local data. The normal browser suite starts its own temporary SQLite API on port 5302 and UI on 3300. The additional harness starts an independent temporary SQLite API on 5402 and a production static export on 3400. Fixtures use reserved example.test addresses, a clearly synthetic password, a short fictional profile and harmless formula text. Existing development/production databases were not migrated or reset. Fresh temporary test databases do run application migrations.
No live payment, mail delivery, OAuth login, external AI/NAV integration test, host inspection, production deployment or destructive failure exercise occurred. The adversarial browser aborts non-loopback remote requests, including Google Fonts. Its AI URL is a closed loopback port and relevant integrations/workers are disabled or unconfigured. The normal browser suite ran as written; it is not an all-process egress isolation proof. No current external advisory, price, legal or runtime-support lookup was performed, respecting the repository's restriction on external services.
This is one local baseline run per normal suite, plus development iterations of the observational harness. Only the final successful harness run is retained as the reported 27 observations. Earlier fixture/selector/locale corrections are not product findings. One successful run does not establish a flake rate or production-provider equivalence.
Normal verification
| Check | Result | Evidence / limit |
|---|---|---|
| Backend Release tests | 753 passed, 0 failed, 0 skipped | TRX; reported test execution about 9s after build. Test collection concurrency disabled for this run. |
| UI Jest | 65 suites / 279 tests passed, none failed/pending | JSON; about 93.5s. Tests passing does not imply standalone TypeScript success. |
| Parser pytest | 37 passed | Model loading skipped and HF/Transformers offline; about 15.8s. No live model quality proof. |
| Existing Playwright suite | 13 passed, 0 failed, 0 skipped, 0 flaky | JSON; 159.9s. Covers existing core/a11y/long-content/PDF flows; builder route was outside that axe coverage. |
| Supply-chain helper tests | 3 passed | Local script tests. |
| Tracked-secret scan | Passed | No high-confidence tracked-file patterns reported; not a scan of Git history, deployed environment or every possible secret. |
| Ollama evaluation-helper tests | 5 passed | Evaluation tooling behavior, not live model factuality or Bokmål quality. |
| Browser-extension capture URL tests | 3 passed | Local Node test suite. |
| ESLint, zero-warning threshold | Passed, exit 0 | Stale Browserslist data notice remains in tooling output. |
| Standalone TypeScript | Failed, exit 2 | src/interview-prep.test.tsx(120,10): TS2571: Object is of type 'unknown'. F17. |
| Next production static build | Passed, exit 0 | Next 16.2.12; compiler about 3.6s and build type phase about 10.6s. Output was built for the local audit API. |
Do not deploy this audit's generated out/ as a production artifact: it intentionally embeds the loopback test API URL. A real release must rebuild with the intended configuration through its normal process. Build output remains ignored and was not added to Git.
Commands below use PowerShell. Run the root commands from the repository root and the UI commands from job-tracker-ui. These are recorded checks, not permission to run production operations.
# Repository root
$env:DOTNET_CLI_TELEMETRY_OPTOUT = '1'
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = '1'
& 'C:\Users\Connor\.dotnet\dotnet.exe' test JobTrackerApi.Tests\JobTrackerApi.Tests.csproj --configuration Release --no-restore --logger 'trx;LogFileName=expanded-audit.trx' --results-directory .artifacts\expanded-audit -- xUnit.parallelizeTestCollections=false xUnit.maxParallelThreads=1
python scripts/test-supply-chain.py
python scripts/supply-chain.py scan-secrets
python scripts/test-ollama-evaluation.py
node --test browser-extension/tests/capture-url.test.mjs
# tools/summarizer directory
$env:AI_SERVICE_SKIP_MODEL_LOAD = '1'
$env:HF_HUB_OFFLINE = '1'
$env:TRANSFORMERS_OFFLINE = '1'
& .venv/Scripts/python.exe -m pytest -q --disable-warnings
# job-tracker-ui directory
node node_modules/jest/bin/jest.js --watchAll=false --runInBand --json --outputFile=../.artifacts/expanded-audit/jest.json
node node_modules/typescript/bin/tsc --noEmit --pretty false
node node_modules/eslint/bin/eslint.js . --max-warnings=0
$env:DOTNET_HOST_PATH = 'C:\Users\Connor\.dotnet\dotnet.exe'
$env:Ai__BaseUrl = 'http://127.0.0.1:1'
$env:NEXT_TELEMETRY_DISABLED = '1'
node node_modules/@playwright/test/cli.js test --reporter=json
Console/JSON redirection during the audit retained .artifacts/expanded-audit/expanded-audit.trx, jest.json, playwright.json, jest.log, lint.log, typecheck.log, build.log and playwright-server.log. These large local logs remain ignored; the selected synthetic evidence below is included with the report. Parser/helper counts were recorded from command output rather than a newly retained test report.
Break Jobjakt observations
The harness is an observational tool. Exit 0 means the harness finished; it does not mean the desired product behavior passed. An unexpected harness failure exits 2. Product expectations are stored individually as meetsExpectation; consume those explicitly if converting a scenario to a regression test. Several expectations are proposed safety contracts, such as same-intent creation deduplication, rather than promises already made by the current API.
Prerequisites: installed UI packages and Chromium; free loopback ports 5402/3400; a Release API build; a static UI export built with the matching loopback API. The script does not install dependencies. It creates a unique temporary data directory, starts its own child processes and stops those process trees on exit. Synthetic temporary data is retained for diagnosis; it does not delete existing database directories. On this Windows machine its default SDK path works; DOTNET_HOST_PATH can override it.
# job-tracker-ui directory; test-only build configuration
$env:NEXT_TELEMETRY_DISABLED = '1'
$env:NEXT_PUBLIC_API_BASE_URL = 'http://localhost:5402/api'
node --max-old-space-size=4096 node_modules/next/dist/bin/next build
# Repository root, after the Release API and static UI builds
$env:DOTNET_HOST_PATH = 'C:\Users\Connor\.dotnet\dotnet.exe'
node docs/audits/2026-09-07/break-jobjakt.mjs
Final run: 27 observations, 22 unmet desired expectations, 5 met. Multiple states test the same cause: eight builder combinations and four date/offset examples are not twelve unrelated vulnerabilities. These observations feed the 21 prioritized source/observed findings, not a 22-vulnerability severity total.
| Scenario | Observed result | Interpretation |
|---|---|---|
| Stale CV save | First and stale PUT both 200; stale value becomes current; version reaches 3 | Missing revision precondition, F01. |
| Simultaneous CV save | Both PUTs return 200 | No cross-editor conflict contract; single-editor save queue does not protect another client. |
| Another owner's CV GET/PUT/DELETE | All 404 | Three exercised owner boundaries pass. |
| Repeated job creation | Both 201, different IDs | No same-intent deduplication. Distinct POST requests are not inherently an HTTP specification violation; define operation identity before fixing. |
| Four follow-up offset/DST round trips | All ICS requests 200, all expected UTC instants wrong | F21; exact values below. |
| CSV formula | Harmless =1+1 remains a formula cell |
F05; quoting separators alone is insufficient. |
| Auth identity, private CV and CSV response caching | No explicit Cache-Control on all three samples | F15 hardening gap; does not prove a cross-user cache leak. |
| Standard-user admin audit access | 403 | Exercised role boundary passes. |
| Export account isolation | After A's two exports, B's first from same IP gets 429 | Account limiter executes before authenticated identity is populated, F06. |
| Builder EN/NB x light/dark x 375/1440 | All eight have serious axe contrast findings; desktop also has scrolling-region keyboard finding; outer overflow0 | F14. Measured viewport is not a zoom or screen-reader test. |
| Save while offline | Visible failed-save state | Useful existing recovery feedback passes. |
| Confirm reload after failed offline save | Draft not recovered after acknowledging unload warning | F09; the warning exists and was not bypassed accidentally. |
| Logout in another tab | Idle private editor remains mounted; subsequent backend identity requests 401 | F08 visual/session UX residue, not successful unauthorized API access. |
| Input follow-up | Expected ICS UTC | Actual ICS UTC |
|---|---|---|
| 2026-03-28T09:00:00+01:00 | 20260328T080000Z | 20260328T090000Z |
| 2026-03-29T09:00:00+02:00 | 20260329T070000Z | 20260329T090000Z |
| 2026-10-25T02:30:00+02:00 | 20261025T003000Z | 20261025T023000Z |
| 2026-10-25T02:30:00+01:00 | 20261025T013000Z | 20261025T023000Z |
The timestamps demonstrate an offset/instant preservation bug, not a defect limited only to DST dates. MariaDB and other server timezones need a permanent round-trip regression after the boundary is corrected. Do not blindly reinterpret existing user dates during migration.
Raw synthetic observations: evidence/break-results.json, generated 2026-09-07T10:27:52.479Z, SHA-256 bccc69965d0505800624151fa046d973f845b109ea7ca770f9da8e44e7f3a468. This contains axe targets/ratios, actual language/theme markers, console/network observations and timings; no real customer data. The included harness differs from the executed final script only by its explanatory header comments.
Synthetic screenshots (all eight states retained):
| Locale / theme | 375px | 1440px |
|---|---|---|
| English / light | Mobile | Desktop |
| English / dark | Mobile | Desktop |
| Bokmål / light | Mobile | Desktop |
| Bokmål / dark | Mobile | Desktop |
Console, network and backend logs
The normal Playwright suite reported no failure/flakiness, but it does not establish that every normal route is console-clean. The additional browser capture recorded repeated warnings that combining iframe allow-scripts and allow-same-origin can allow sandbox escape. This is weakened isolation, not proof of exploitable generated HTML. It also recorded intentionally induced offline request failures, post-logout 401s, and Google Fonts blocked by the harness. Those expected failures are not unexplained production outages.
The NB UI was genuinely set to nb-NO rather than just labelled Norwegian in screenshot filenames. It still contains English template descriptions. Light-theme chips included green text at 3.29:1 contrast against white, below the axe threshold for that small text. A short profile displayed a preview horizontal-overflow warning despite zero measured outer-page overflow; those are different measurements. Investigate the document measurement/layout with both fallback and approved fonts.
Local navigation-to-main measurements were jobs 497ms, career 395ms and builder 382ms. These are single localhost shell measurements, not full data completion, LCP, INP, production p95, waterfall analysis or load capacity. Response-size budgets, duplicate/polling requests, post-unmount requests and production source-map errors require a fuller network/performance sweep.
The additional API log was inspected for warning/error categories. Fresh SQLite migration produced EF warnings 30200 and 20410 for AddJobEntityAndProspectStages: a table rebuild/SQL ordering warning and nontransactional PRAGMA foreign_keys = 0, with partial-migration recovery implications. Fresh startup completed; interruption/replay was not tested. Data Protection warning 35 said no XML encryptor was configured for the synthetic local key. These are actionable migration/key-custody evidence, not proof that production has identical conditions. No recurring normal-request fail:/exception category was observed in that log. Verbose development SQL includes schema/content field names; it is not shipped as a public diagnostic artifact.
Tooling reported stale Browserslist metadata. No online update/advisory fetch was done. The standalone TypeScript error is retained above; it was not hidden by the successful build/lint/test result.
Outstanding acceptance evidence
The coverage index lists narrower gaps individually. Highest-value remaining checks are:
- After fixes, real SQLite and MariaDB revision/idempotency/quota/date tests; concurrent authorization/deletion and shared-account operations.
- An isolated DB-outage/recovery and worker-failure drill; renderer/export stress only after strict resource admission is in place. No 1,000-Chromium or host disk-exhaustion experiment was attempted on the user's computer.
- Actual consistent backup restoration of DB, files, keys and tombstones; interrupted/large migration, old-image compatibility and measured RPO/RTO.
- Stripe sandbox duplicate/order/concurrency/deletion and uncertain email-send reconciliation using safe test identities and sinks.
- Actual proxy/firewall/TLS/host/container/runner/deployment permissions, provider transport and secret-rotation evidence; current advisory/license/support review when external access is authorized.
- Core routes including builder with Narrator/NVDA, complete keyboard flow, actual zoom, text spacing, forced colors, reduced motion, mobile keyboard and generated-document reading order.
- Large synthetic tenants/query plans, browser leak/unmount/cancellation/old-client tests, complete endpoint DTO/serialization/regex/XSS corpus, and live model EN/Bokmål evaluation.
These gaps are explicit limits of the completed local assessment. The report supplies prioritization and test/rollout criteria; it does not certify the application for public paid operation or mark the proposed overhaul implemented.