Files
ui/_docs/02_document/tests/traceability-matrix.md
T
Oleksandr Bezdieniezhnykh 873749197a
ci/woodpecker/push/build-arm Pipeline failed
[AZ-512] Cycle 4 Steps 12-15: test-spec sync + docs + sec + perf
Steps 12-15 closure for cycle 4 (AZ-512 admin class inline edit):

- Step 12 (Test-Spec Sync): traceability O9 -> Covered; new FT-P-62
  + FT-N-18 in blackbox-tests.md.
- Step 13 (Update Docs): AdminPage module doc gains the inline-edit
  state slots, four new handlers, PATCH integrations row, expanded
  i18n key list, tests section. architecture.md row 272 now lists
  PATCH /api/admin/classes/{id} with AZ-513 deploy-gate caveat.
- Step 14 (Security Audit): cycle-4 delta report records one new
  LOW finding (F-SAST-CY4-1 lost-update / mid-air-collision on
  PATCH, by design per spec); verdict carries PASS_WITH_WARNINGS;
  bun audit re-run clean.
- Step 15 (Performance Test): NFT-PERF-01 bundle = 291 332 B
  (+757 B / +0.26% vs cycle 3; ~13.89% of 2 MB budget); PASS.

Tests 243 passed / 13 skipped / 0 failed (+12 AZ-512 cases).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 04:51:17 +03:00

21 KiB

Traceability Matrix

Maps every acceptance criterion and every restriction in _docs/00_problem/ to the test scenarios that verify it (this directory) and the expected-result row in _docs/00_problem/input_data/expected_results/results_report.md that provides the quantifiable observable. Quarantined tests are marked [Q] — they assert against a Phase B target feature or a Step 4 fix that has not landed; they activate the day the implementation ships.

Acceptance Criteria Coverage

AC ID Acceptance Criterion (short) Tests results_report rows Coverage
AC-01 credentials:'include' on every authenticated fetch FT-P-01 (un-quarantined cycle 3 / 2026-05-13 by AZ-510 — bootstrap is now POST + credentials:'include' with chained /users/me per Vision P3; FT-P-01 runs as a regression guard on the wire shape), FT-P-02, NFT-PERF-02, NFT-SEC-04, NFT-RES-01, NFT-RES-08 01, 02, 03 Covered
AC-02 Bearer never written to client storage NFT-SEC-01 04 Covered
AC-03 Refresh cookie Secure HttpOnly SameSite=Strict NFT-SEC-02, NFT-SEC-03 05, 06, 07 Covered
AC-04 Numeric enums match suite spec FT-P-04, FT-P-05, FT-P-06 14, 15, 16, 17, 18, 19 Covered (enum_spec_snapshot.json committed — Phase 3 gate resolved)
AC-05 Annotation save endpoint + required body fields FT-P-07, FT-P-08 22, 23 Covered
AC-06 Selected-flight persistence path FT-P-16, FT-P-17 32, 33 Covered
AC-07 Bulk-validate works FT-P-20, FT-P-21, NFT-PERF-07 36, 37 Covered
AC-08 Live-GPS SSE per flight FT-P-18, FT-P-19, NFT-PERF-04, NFT-PERF-05, NFT-RES-10, NFT-RES-LIM-06, NFT-RES-LIM-07 34, 35, 97 Covered
AC-09 Annotation-status SSE during page lifetime FT-P-09, FT-P-10, NFT-PERF-06, NFT-RES-LIM-05 24, 25, 97 Covered
AC-10 Upload size cap 500 MB + UI error path FT-N-06, NFT-RES-07, NFT-RES-LIM-02 38, 39 Covered
AC-11 Initial JS bundle ≤ 2 MB NFT-PERF-01, NFT-RES-LIM-01 40 Covered (documentary — no CI gate today)
AC-12 i18n key parity en ↔ ua FT-P-22, FT-P-23 45, 46 Covered
AC-13 i18n detector + persistence FT-P-24 [Q], FT-P-25 [Q] 47, 48 Covered (quarantined — Step 4 fix)
AC-14 Destructive actions require ConfirmDialog + alert() forbidden FT-P-26, FT-P-27, FT-N-07, NFT-SEC-07, NFT-SEC-08 49, 50, 51 Covered
AC-15 ConfirmDialog a11y FT-P-28, FT-P-29, FT-N-08 52, 53, 54 Covered
AC-16 Header flight dropdown a11y FT-P-30, FT-P-31, FT-N-09 55, 56, 57 Covered
AC-17 ProtectedRoute spinner a11y + timeout FT-P-32, FT-P-33 [Q], NFT-RES-04 [Q] 58, 59 Covered (quarantined for timeout)
AC-18 Browser support — Chromium + Firefox latest 2 FT-P-34, NFT-PERF-10 60, 98 Covered (manual smoke, no automated gate today)
AC-19 Mobile / desktop breakpoint variants FT-P-35, FT-P-36 61, 62 Covered
AC-20 OpenWeatherMap key not in source NFT-SEC-09 (all 3 steps active — source check un-quarantined on cycle 2 / 2026-05-12 by AZ-499) 63 Covered
AC-21 UserSettings panel-width persistence FT-P-37 [Q], FT-P-38 [Q], NFT-PERF-08 [Q] 64, 65 Covered (quarantined)
AC-22 RBAC client-side route gates FT-N-03 [Q], FT-N-04, FT-N-05 [Q], NFT-SEC-05 [Q], NFT-SEC-06 [Q], NFT-RES-08 08, 09, 10 Covered (quarantined for /admin + /settings gates)
AC-23 Auth refresh transparency FT-P-02, FT-P-03, NFT-PERF-02, NFT-RES-01; "AC-4 (AZ-510)" colocated test in src/auth/AuthContext.test.tsx covers the bootstrap edge where POST refresh succeeds but chained /users/me returns 401 → bearer cleared, console.error logged (added cycle 3 / 2026-05-13 by AZ-510) 11, 12 Covered
AC-24 SSE bearer-rotation reconnect NFT-PERF-03 [Q], NFT-RES-02 [Q], NFT-RES-10 13, 97 Covered (quarantined — Step 8 hardening)
AC-25 Detect endpoint correctness (sync + async) FT-P-11, FT-P-12 [Q], FT-P-13 [Q] 26, 27, 28 Covered (async path quarantined — F7 target)
AC-26 Numeric input hygiene FT-N-11 [Q], FT-N-12 [Q] 66, 67 Covered (quarantined — Step 4 fix)
AC-27 Save error surfacing in settings FT-N-13 [Q], FT-N-14 [Q], NFT-PERF-09 [Q], NFT-RES-05 [Q], NFT-RES-06 [Q] 68, 69 Covered (quarantined — Step 4 fix)
AC-28 Annotation overlay time window [-50, +150] ms FT-P-14, FT-P-15, FT-N-01, FT-N-02 29, 30, 31 Covered
AC-29 mediaType is typed (no magic literals) FT-N-15 20, 21 Covered
AC-30 Class delete confirmation FT-P-26, FT-N-07, NFT-SEC-08 49 Covered (overlaps AC-14 row 49)
AC-31 mission-planner/ not in production bundle NFT-RES-LIM-04 41 Covered
AC-32 CI image tag + OCI labels NFT-RES-LIM-11, NFT-RES-LIM-12, NFT-RES-LIM-13 70, 71, 72 Covered
AC-33 Production runtime nginx:alpine only NFT-RES-LIM-03 42 Covered
AC-34 nginx routes 9 services with prefix stripping NFT-RES-LIM-09, NFT-RES-LIM-10 43, 44 Covered
AC-35 Manual bbox draw on CanvasEditor FT-P-39 73 Covered
AC-36 8-handle resize + Ctrl-multi-select + Ctrl-wheel zoom + Ctrl-drag pan FT-P-40, FT-P-41, FT-P-42, FT-P-43 74, 75, 76, 77 Covered
AC-37 Class picker — load + hotkey + click + fallback FT-P-44, FT-P-45, FT-P-46, FT-P-47 78, 79, 80, 81 Covered (pending backend ordering check — Phase 3 gate)
AC-38 PhotoMode switcher FT-P-48, FT-P-49, FT-P-50 82, 83, 84 Covered
AC-39 Tile-splitting endpoint + parser FT-P-51 [Q], FT-P-52, FT-P-53, FT-N-10 85, 86, 87, 88 Covered (split surface quarantined)
AC-40 Tile-zoom auto-zoom + indicator FT-P-54 [Q], FT-P-55 [Q] 89, 90 Covered (quarantined — UX missing today)
AC-N1 No collaborative-edit semantics NFT-SEC-14 91 Covered
AC-N2 No in-browser ML NFT-SEC-10 92 Covered
AC-N3 No offline mode NFT-RES-03, NFT-SEC-12 93 Covered
AC-N4 No response-signature library NFT-SEC-11 94 Covered
AC-N5 Dropped legacy features (Sound Detections, Drone Maintenance) NFT-SEC-13 95 Covered
AC-41 Map tiles served by self-hosted satellite-provider via cookie auth; classic/satellite toggle removed (added cycle 2 / 2026-05-12, epic AZ-497, ticket AZ-498) FT-P-56, FT-P-57, FT-P-58, FT-P-59, NFT-RES-11; STC-T1 (env-decl typecheck), STC-FP22 (i18n parity post-key removal), STC-ARCH-01 + STC-ARCH-02 (architecture gates stay green) n/a — env-var plumbing + DOM observable + e2e contract; no results_report.md row required Covered
AC-42 mission-planner OpenWeatherMap key + base URL externalized via Vite env vars; fail-soft on missing key; STC-SEC1C source-tree literal scan defends against re-introduction (added cycle 2 / 2026-05-12, epic AZ-497, ticket AZ-499) FT-P-60, FT-N-16; NFT-SEC-09 step 3 (STC-SEC1C); STC-T1 (env-decl typecheck) 63 (literal-key scan shares row 63 with AC-20) Covered (manual deliverable AZ-499 AC-7 — old key revocation at OWM dashboard — tracked separately, not a test)
AC-43 mission-planner Google Geocode API key extracted to a new services/GeocodeService.ts module + externalized via Vite env var; fail-soft + console.warn on missing key; STC-SEC1D source-tree literal scan defends against re-introduction (added cycle 2 / 2026-05-12 from security audit _docs/05_security/, ticket AZ-501) FT-P-61, FT-N-17; NFT-SEC-09b (STC-SEC1D); STC-T1 (env-decl typecheck) n/a — env-var plumbing + console-warn assertion; no results_report.md row required Covered (manual deliverable AZ-501 AC-6 — old key revocation at Google Cloud Console — tracked separately, not a test)
AC-44 Vite + PostCSS upgraded past CVE-2026-39363 / GHSA-p9ff-h696-f583 / GHSA-4w7w-66w2-5vf9 / GHSA-qx2v-qp2m-jg93 in both roots via package.json overrides flooring transitive resolutions to safe versions (added cycle 2 / 2026-05-12 from security audit, ticket AZ-502) bun audit (zero advisories in both roots after bun install) n/a — supply-chain hygiene; verified by audit tool exit code Covered (CI gate bun audit --severity high in .woodpecker/build-arm.yml is a Phase B follow-up — see _docs/05_security/infrastructure_review.md F-INF-1)

Restrictions Coverage

RID Restriction (short) Tests / Mechanism Coverage
H1 ARM64-only production image NFT-RES-LIM-03 (image base check); the build pipeline produces ARM64 only — meta-config Covered
H2 Edge-device deployment target NFT-PERF-10, NFT-RES-LIM-08 Covered (documentary)
H3 No GPU expectation in UI image environment.md (no GPU in test rig); NFT-SEC-10 (no ML libs) — together they verify the constraint Covered (by composition)
H4 HTML5 video + canvas + EventSource on Chromium / Firefox latest 2 FT-P-34 Covered
S1 TypeScript strict mode STC-S1: static read of tsconfig.json for "strict": true (planned static check — added by Phase 3 if accepted) NOT COVERED — Phase 3 to add
S2 React 19 STC-S2: package.json dep version pin NOT COVERED — Phase 3 to add
S3 Vite 6 STC-S3: package.json dep version pin NOT COVERED — Phase 3 to add
S4 Bun 1.3.11 STC-S4: package.json packageManager field + Dockerfile base image pin NOT COVERED — Phase 3 to add
S5 Static-bundle output only (no Node in prod image) NFT-RES-LIM-03 Covered
S6 REST + SSE only (no WebSocket / GraphQL / gRPC-Web) STC-S6: dep scan for ws, socket.io, graphql, apollo, grpc-web (planned) NOT COVERED — Phase 3 to add
S7 Two React Contexts only (no Redux / Zustand / TanStack Query) STC-S7: dep scan for redux, zustand, @reduxjs/.*, @tanstack/.* NOT COVERED — Phase 3 to add
S8 Tailwind 4 + az-* design tokens STC-S8: dep version pin + presence of token CSS vars NOT COVERED — Phase 3 to add
S9 leaflet@1.9.4 + react-leaflet@5 + leaflet-draw + leaflet-polylinedecorator STC-S9: package.json version pin set NOT COVERED — Phase 3 to add
S10 chart.js@4 + react-chartjs-2@4 STC-S10 NOT COVERED — Phase 3 to add
S11 @hello-pangea/dnd@18 STC-S11 NOT COVERED — Phase 3 to add
S12 i18next + react-i18next with EN + UA bundles only FT-P-22, FT-P-23 + STC-S12 (no other locale bundle files) Partially Covered
S13 No client-side persistence library NFT-SEC-01 + STC-S13 (dep scan for localforage, idb, dexie) Partially Covered
S14 No test framework configured today META — these tests' very existence supersedes this restriction; resolved at Step 5 (Decompose Tests) per acceptance_criteria.md AC-14 / S14 note N/A — meta
E1 Air-gap-friendly bundle NFT-RES-03 (offline boot) + external-dep stubs in environment.md Partially Covered
E2 nginx strips /api/<service>/ per service NFT-RES-LIM-09, NFT-RES-LIM-10 Covered
E3 Secure HttpOnly SameSite=Strict refresh cookie NFT-SEC-03 Covered
E4 Vite dev proxy at /api → http://localhost:8080 dev-only; not testable in production runtime NOT COVERED — meta-config (Phase 3 to confirm)
E5 AZAION_REVISION stamped at build NFT-RES-LIM-13 Covered
E6 OCI image labels NFT-RES-LIM-12 Covered
E7 Image registry + tag scheme NFT-RES-LIM-11 Covered
E8 Branch triggers (dev / stage / main) STC-E8: parse .woodpecker/build-arm.yml triggers (planned) NOT COVERED — Phase 3 to add
E9 client_max_body_size 500M NFT-RES-LIM-02 Covered
E10 OpenWeatherMap direct-from-browser today NFT-SEC-09 (key check) + environment.md owm-stub (E2E isolation) Covered
O1 Bilingual UI mandatory FT-P-22, FT-P-23 Covered
O2 Bearer never in localStorage / sessionStorage NFT-SEC-01 Covered
O3 credentials:'include' on every authenticated fetch NFT-SEC-04 Covered
O4 RBAC is server-enforced (UI must NOT trust AuthUser.role) meta-design + FT-N-04 (unauth → /login regardless of any client claim); STC-O4 (no if (user.role === 'admin') gating sensitive data, only UI hide/show) Partially Covered — Phase 3 may add the static gate-pattern lint
O5 Refresh cookie attributes NFT-SEC-03 Covered
O6 No hardcoded credentials NFT-SEC-09 Covered
O7 Spec is source of truth for numeric enums FT-P-04, FT-P-05, FT-P-06 Covered
O8 Persist what you type (panel widths) FT-P-37 [Q], FT-P-38 [Q] Covered (quarantined)
O9 Admin can edit existing detection classes (P12) FT-P-62, FT-N-18 — landed cycle 4 / 2026-05-13 by AZ-512 (UI-side; user-authorized Option B path — implementation shipped against MSW stubs). Live deploy gate remains until AZ-513 ships on admin/ and is deployed: `POST PATCH
O10 Destructive actions require ConfirmDialog NFT-SEC-08, FT-P-26, FT-P-27, FT-N-07 Covered
O11 No SSR / RSC NFT-RES-LIM-03 (no Node in image) + STC-O11 (no react-dom/server import) Partially Covered
O12 mission-planner/ not compiled by production Vite build NFT-RES-LIM-04 Covered
O13 Bundle size budget ≤ ~2 MB gzipped initial JS NFT-PERF-01, NFT-RES-LIM-01 Covered (target — no CI gate today)
O14 No CI test step today META — resolved at Step 5 (Decompose Tests) N/A — meta
O15 No vuln scan / SBOM / image signing NOT COVERED — Step 6 / security_approach surface; Phase B addition NOT COVERED

Coverage Summary

Category Total Items Covered Partially Covered Not Covered N/A (meta) Coverage % (Covered+Partial)
Acceptance Criteria 44 44 0 0 0 100% (cycle-2 deltas: AC-41, AC-42, AC-43, AC-44 added; AC-20 source check no longer quarantined. Cycle 3 deltas: FT-P-01 bootstrap part un-quarantined by AZ-510 — closes Vision P3 / Finding B3; AC-23 row gained the AZ-510 chained-/users/me failure-path test reference.)
Anti-Criteria 5 5 0 0 0 100%
Restrictions 41 17 8 13 3 61%
Total 90 66 8 13 3 82%

Acceptance criterion coverage exceeds the 75 % template threshold. Restriction coverage is short of 75 % because most of the un-covered restrictions are dependency-version pins (S1-S11) for which a single static check pass (planned STC-S* family) would lift them to Covered without changing the SPA's observable behavior.

Uncovered Items Analysis

Item Reason Not Covered Risk Mitigation
S1-S11 (TS strict, React/Vite/Bun version pins, Tailwind, Leaflet, Chart.js, DnD) Dependency-version restrictions need a static package.json / tsconfig.json parser pass; not authored in this phase Drift between pinned and installed versions (e.g., transitive resolution); accidental upgrade in a refactor breaking ADRs (ADR-001 …) Phase 3 to confirm adding the STC-S* family; otherwise Step 4 / Step 8 may add them as part of the testability fix
S12, S13 partials STC-S12 (no other locale bundles) and STC-S13 (no IndexedDB / localForage / Dexie deps) need explicit dep scans Low — currently aligned per package.json; risk only on dep additions Phase 3 promotion to a single static dep-scan job (run alongside the dep-license lint)
E4, E8 Dev-only proxy and pipeline branch triggers are not consumer-observable from a production build None today; future risk if the proxy diverges from the prod nginx Document-only; Phase 3 confirms
O4 partial (RBAC trust pattern) No lint rule today; the design intent is captured but not asserted in code UI accidentally gates sensitive data on a client claim Phase 3 to add an STC-O4 lint that bans if (user.role === 'admin') { /* reveal data */ } patterns; FT-N-04 already locks the unauth path
O9 (admin can edit classes — P12) The feature does not exist today (only add + delete); cannot test absence of a regression Functionality missing relative to spec Phase B feature cycle will add PATCH /api/admin/classes/{id} plus FT-P-XX in the cycle that ships it; AC-37 / AC-30 already enforce the surrounding contract
O11 partial NFT-RES-LIM-03 confirms no Node binary in the image; an explicit "no react-dom/server import" lint is missing Could regress to SSR by accident on a refactor; the image base check would still pass Phase 3 confirms STC-O11
O15 (vuln scan / SBOM / signing) Pipeline does not emit any of these today Supply-chain risk Addressed at Step 6 / security_approach.md; outside the test-spec scope
AC-11, AC-18, AC-24, AC-40, AC-25 async path Phase B / target features with quarantined tests Tests do not gate today — risk = the feature ships without the assertion being un-quarantined Phase 3 chooses: keep quarantined (gates the day the feature ships) OR downgrade to documentary; recommendation: keep quarantined
AC-04 enum spec numeric values for MediaStatus / Affiliation / CombatReadiness The exact spec values are not pinned in enum_spec_snapshot.json yet Tests use symbolic comparison and may silently match a wrong UI state Phase 3 to require population of the snapshot before AC-04 tests gate CI; recommendation: BLOCK Step 4 until the snapshot is committed
AC-37 backend ordering The class-hotkey contract requires [0..N-1, 20..20+N-1, 40..40+N-1] ordering from the suite; not yet verified Hotkey test fails at integration; ambiguous responsibility Phase 3 to surface; fix can land server-side or via a client-side resort, depending on the verification result

Quarantine List (running)

The following 16 tests assert against a Phase B target or a Step 4 fix and are quarantined until the implementation lands. Phase 3 will decide their disposition. (Cycle 2 / 2026-05-12 update: NFT-SEC-09 source check REMOVED — closed by AZ-499 + STC-SEC1C; new AC-41 / AC-42 tests added in this cycle are NOT quarantined. Cycle 3 / 2026-05-13 update: FT-P-01 bootstrap part REMOVED — closed by AZ-510, runs as a regression guard now.)

Test Reason Activates when
FT-P-12, FT-P-13 Async video detect (F7) not wired Phase B feature cycle
FT-P-24, FT-P-25 i18n detector + persistence missing Step 4 fix
FT-P-33 (timeout) ProtectedRoute timeout missing Step 4 fix
FT-P-37, FT-P-38 Panel-width writer missing (useResizablePanel) Step 4 fix
FT-P-51 Split surface not on dataset page today Phase B
FT-P-54, FT-P-55 Tile-zoom UX missing (finding #24) Phase B
FT-N-03, FT-N-05 /admin and /settings role-gates missing Step 4 / Step 8
FT-N-11, FT-N-12, FT-N-13, FT-N-14 Settings form hygiene fixes missing Step 4
NFT-PERF-03 / NFT-RES-02 SSE refresh-rotation reconnect missing Step 8 hardening
NFT-PERF-08 / NFT-PERF-09 Tied to FT-P-37 / FT-N-13 quarantines per above
NFT-SEC-05, NFT-SEC-06 Tied to FT-N-03, FT-N-05 per above
NFT-RES-04 Tied to FT-P-33 per above

Phase 3 (Data Validation Gate) — Open Items to Resolve

Resolved in Phase 3

  1. enum_spec_snapshot.json — populate from the suite spec before AC-04 tests gate CI.Resolved: snapshot committed at _docs/00_problem/input_data/enum_spec_snapshot.json. verification_pending: true markers remain for CombatReadiness and MediaType (numeric ordering inferred from schema member-listing); Step 4 .NET-service inspection lifts those.
  2. NFT-RES-09 — no results_report.md row binding.Resolved: row 96 added (tainted-canvas fallback observable).
  3. NFT-RES-10 — no results_report.md row binding.Resolved: row 97 added (SSE server-disconnect observable; ≤ 10 s indicator-or-reconnect; reconnect attempts ≤ 1 in window).
  4. NFT-PERF-10 — FCP baseline has no results_report.md row.Resolved: row 98 added (FCP ≤ 3 000 ms on warm-cache navigation to /flights, headless Chromium, 2 vCPU / 4 GB edge profile).

Still open (carry forward to Step 4 / runner)

  1. AC-37 backend ordering — verify the annotations/ service response shape and either confirm matches or schedule a fix on the appropriate side.
  2. STC family — confirm adding the STC-S* / STC-O4 / STC-O11 static-check IDs to lift the restriction coverage above 75 %.
  3. Quarantine disposition — accept the quarantine list above; decide whether quarantined tests gate CI today (recommended: no, but they are picked up automatically the day the feature lands).
  4. AC-04 UI enum drift in src/types/index.ts — tests will FAIL until the Step 4 fix lands per acceptance_criteria.md; quarantine until Step 4 OR run them and use the failure as the gate to schedule Step 4. The drift list is pinned in enum_spec_snapshot.jsonui_drift_summary (5 enums).
  5. Parent-suite doc fixes (leftover)../_docs/01_annotations.md line 208 and ../_docs/09_dataset_explorer.md line 165 show stale affiliation: 2 // Hostile examples; should be 20 per 00_database_schema.md. Record as a leftover in _docs/_process_leftovers/ when raised against the parent suite.