mirror of
https://github.com/azaion/annotations.git
synced 2026-06-21 13:01:06 +00:00
03f879206e
This commit captures everything produced during autodev existing-code Steps 1 (Document), 2 (Architecture Baseline Scan), and 3 (Test Spec), together with the targeted auth + CORS re-sync triggered on 2026-05-14 when codebase drift was detected at Step 4 entry. None of this work was previously committed. Step 1 (Document) — 50+ _docs/02_document/ files: problem, solution, architecture, system flows, glossary, module-layout, per-component specs (01..06), modules, deployment, diagrams, data model, FINAL report, verification log, discovery. Step 2 (Architecture Baseline) — architecture_compliance_baseline.md. Verdict PASS_WITH_WARNINGS (0 Critical, 0 High, 1 Medium, 2 Low). No High/Critical findings; auto-chained to Step 3 per existing-code flow. Step 3 (Test Spec) — _docs/02_document/tests/* (67 scenarios across blackbox, security, resilience, resource-limit, performance), plus e2e/docker-compose.test.yml, e2e/seed/run.sh, scripts/run-tests.sh, scripts/run-performance-tests.sh. Coverage 88% over the active scope (40 of 45 items covered, 6 RB-deferred, 5 documented-as-uncovered). Targeted auth + CORS re-sync — replaces the deleted in-house token issuer with a JWKS-verifier model. AuthController and TokenService removed; JwtExtensions switched from HS256 symmetric to ES256 over admin's JWKS. ConfigurationResolver and CorsConfigurationValidator added under src/Infrastructure/. ADR-002 and ADR-006 retired; SEC-01, SEC-02, SEC-03 marked Closed. One new testability risk recorded in architecture.md Open Risks Section 6 (JWKS HTTPS gating). Source changes: - src/Auth/JwtExtensions.cs (modified) — ES256, JWKS, alg pinning - src/Program.cs (modified) — DI wiring for ConfigurationResolver and CorsConfigurationValidator - src/Controllers/AuthController.cs (deleted) — no in-service issuance - src/Services/TokenService.cs (deleted) — same - src/Infrastructure/ConfigurationResolver.cs (new) - src/Infrastructure/CorsConfigurationValidator.cs (new) - .env.example (new) — required env var documentation - .gitignore (updated) Cross-repo coordination: _docs/cross-repo/flights_h1_h2_h3_change_spec captures the change-spec for downstream services that consumed the now deleted /auth endpoints. Co-authored-by: Cursor <cursoragent@cursor.com>
99 lines
9.0 KiB
Markdown
99 lines
9.0 KiB
Markdown
# Traceability Matrix
|
|
|
|
## Acceptance Criteria Coverage
|
|
|
|
### Functional ACs
|
|
|
|
| AC ID | Acceptance Criterion (short) | Test IDs | Coverage |
|
|
|-------|-----------------------------|----------|----------|
|
|
| AC-F-01 | Same image bytes → same id | FT-P-01, FT-P-02 | Covered |
|
|
| AC-F-02 | Re-POST is no-op | FT-P-02 | Covered |
|
|
| AC-F-03 | YOLO label file format | FT-P-03, FT-P-04 | Covered |
|
|
| AC-F-04 | POST /annotations returns persisted DTO | FT-P-01, FT-N-01, FT-N-02, FT-N-06, FT-N-07 | Covered |
|
|
| AC-F-05 | `[after RB-01]` Every mutation emits SSE + outbox | FT-P-21, FT-P-22, NFT-RES-01 | Deferred — gated on RB-01 |
|
|
| AC-F-06 | `[after RB-01]` DELETE is soft + relocates files | FT-P-22 | Deferred — gated on RB-01 |
|
|
| AC-F-07 | `[after RB-01+RB-08]` soft-deleted hidden from reads | (test added in cycle-update once RB-01+RB-08 land) | Deferred |
|
|
| AC-F-08 | `[after RB-02]` no `silent_detection` artifacts | (covered by RB-02 implementation tests) | Deferred — gated on RB-02 |
|
|
| AC-F-10 | SSE delivery < 1s | FT-P-07, NFT-PERF-SSE-FANOUT-01 | Covered |
|
|
| AC-F-11 | No SSE backfill | FT-P-07 (step 2), inline assertion | Partial — add explicit test in cycle-update |
|
|
| AC-F-12 | Outbox drain → stream | FT-P-08, FT-P-09, NFT-RES-01 | Covered |
|
|
| AC-F-13 | `[after RB-09]` `(annotation_id, operation, date_time)` on the wire | (added in cycle-update once RB-09 lands) | Deferred — gated on RB-09 |
|
|
| AC-F-20 | POST /media single | FT-P-10, FT-N-14, FT-N-15 | Covered |
|
|
| AC-F-21 | POST /media/batch | FT-P-11 | Covered |
|
|
| AC-F-30 | GET /dataset filter | FT-P-16, FT-P-17 | Covered |
|
|
| AC-F-31 | POST /dataset/status/bulk | FT-P-18, FT-N-16 | Covered |
|
|
| AC-F-40 | PUT /settings/directories triggers Reset() | FT-P-15, FT-N-13 | Covered |
|
|
| AC-F-41 | GET /classes returns 19 rows | FT-P-14 | Covered |
|
|
| AC-F-42 | `[after RB-06]` admin CRUD on /classes | (added once RB-06 lands) | Deferred — gated on RB-06 |
|
|
| AC-F-50 | Bearer token verification (iss/aud/exp/sig/alg) | FT-P-12, FT-P-13, FT-N-10, FT-N-11, NFT-SEC-01, NFT-SEC-02, NFT-SEC-10 | Covered |
|
|
| AC-F-51 | Annotations does not host token-issuance/refresh | (asserted by NFT-SEC-05 — only `/health` is anonymous) | Covered (negative) |
|
|
| AC-F-52 | Policy boundaries | FT-N-03, FT-N-04, FT-N-08, FT-N-12, FT-N-13, FT-N-15, NFT-SEC-03, NFT-SEC-04, NFT-SEC-05, NFT-SEC-08 | Covered |
|
|
| AC-F-53 | Error envelope shape | covered as global invariant; FT-N-* assert envelope | Covered |
|
|
| AC-F-54 | GET /health returns 200 | FT-P-19, NFT-PERF-* warmup | Covered |
|
|
|
|
### Non-Functional ACs
|
|
|
|
| AC ID | Acceptance Criterion (short) | Test IDs | Coverage |
|
|
|-------|-----------------------------|----------|----------|
|
|
| AC-N-01 | Container boot to /health 200 within healthcheck budget | FT-P-19, NFT-RES-LIM-06 | Covered (threshold inferred — Step 15 contracts it) |
|
|
| AC-N-02 | Migrator is idempotent | FT-P-20 | Covered |
|
|
| AC-N-03 | Outbox queue depth bounded | NFT-PERF-OUTBOX-DRAIN-01, NFT-RES-LIM-01, NFT-RES-LIM-03 | Covered |
|
|
| AC-N-04 | Zero unhandled exceptions to clients | NFT-RES-03, NFT-SEC-06 | Covered |
|
|
| AC-N-05 | SSE longevity ≥ 30 min | NFT-RES-LIM-05 | Covered (10-min run is a smoke proxy; 30-min is the nightly variant) |
|
|
|
|
## Restrictions Coverage
|
|
|
|
| Restriction ID | Restriction (short) | Test IDs | Coverage |
|
|
|----------------|---------------------|----------|----------|
|
|
| HW-01 | ARM64 only | covered by build pipeline (the test image IS ARM64) | Covered (environment-level) |
|
|
| HW-02 | Writable `images_dir` / `videos_dir` / `deleted_dir` | FT-P-01, FT-P-15, FT-P-22 | Covered |
|
|
| HW-03 | Memory pressure on `FailsafeProducer` image re-read | NFT-RES-LIM-01, NFT-RES-LIM-04 | Covered |
|
|
| SW-01 | .NET 10 | environment-level (Dockerfile) | Covered (deployment) |
|
|
| SW-02 | Postgres 13+ semantics | FT-P-20 (idempotent migrator exercises `CREATE TYPE` etc.) | Covered |
|
|
| SW-03 | RabbitMQ streams plugin | FT-P-09, NFT-RES-01, NFT-RES-06 | Covered |
|
|
| SW-04 | Linq2DB + MessagePack + gzip wire | FT-P-09 (decodes the wire format) | Covered |
|
|
| SW-05 | JWT verifier-only (ES256 over admin's JWKS, alg pinned) | NFT-SEC-01, NFT-SEC-02, NFT-SEC-08, NFT-SEC-10, FT-N-10, FT-N-11 | Covered |
|
|
| ENV-01 | Env vars required | environment.md docker-compose | Covered (environment-level) |
|
|
| ENV-02 | Service on port 8080 HTTP, no in-image TLS | environment.md | Covered (environment-level) |
|
|
| ENV-03 | `AZAION_REVISION` boot stamp | not exposed via API today; covered by inspecting `docker logs` (test runner asserts log line `AZAION_REVISION=test-...` appears within 5s of boot) | Partial — add log-assertion test in cycle-update |
|
|
| ENV-04 | Branch-driven `${BRANCH}-arm` tags | CI-pipeline concern; not a runtime test | Not covered (CI-level) |
|
|
| ENV-05 | Swagger UI mounted always | NFT-SEC (verifier in Step 14 catches this); not a hard test today | Not covered — Step 14 |
|
|
| ENV-06 | Config-driven CORS gated by `CorsConfigurationValidator` | NFT-SEC-09 | Covered (asserts allow-list-only ACAO in `Production`) |
|
|
| ENV-07 | DDL applied at boot | FT-P-20 | Covered |
|
|
| OP-01 | Per-instance SSE state | NFT-RES-LIM-05, NFT-RES-04 | Covered |
|
|
| OP-02 | No outbox row leasing | NFT-RES-01 (single-instance baseline); multi-instance double-publish is **not tested today** because the test stack runs a single SUT — flagged | Not covered (multi-instance) |
|
|
| OP-03 | No automated test suite | this matrix IS the contract; the implementation lands in Step 6 | N/A (meta) |
|
|
| OP-04 | No lint / formatter step in CI | CI concern | Not covered (CI-level) |
|
|
| OP-05 | `HEALTHCHECK` calls `/health` | FT-P-19, environment.md (Dockerfile has `HEALTHCHECK`) | Covered |
|
|
| OP-06 | `annotations_queue_records` is a private outbox | enforced by code ownership; test asserts no public endpoint allows writing to it (negative coverage via NFT-SEC-05) | Covered (negative) |
|
|
| OP-07 | DB connection string in `jdbc:postgresql://…` form | Boot succeeds with this format → FT-P-19 implicitly checks it | Covered (implicit) |
|
|
|
|
## Coverage Summary
|
|
|
|
| Category | Total Items | Covered | Deferred (RB) | Not Covered | Coverage % (excl. deferred) |
|
|
|----------|-----------|---------|--------------|-------------|----------------------------|
|
|
| Functional ACs | 24 | 18 | 6 | 0 | 18 / 18 = 100% (active scope) |
|
|
| Non-Functional ACs | 5 | 5 | 0 | 0 | 100% |
|
|
| HW restrictions | 3 | 3 | 0 | 0 | 100% |
|
|
| SW restrictions | 5 | 5 | 0 | 0 | 100% |
|
|
| ENV restrictions | 7 | 4 | 0 | 3 (ENV-04, ENV-05; OP-04 noted) | 57% — gaps are CI-level / Step-14 |
|
|
| OP restrictions | 7 | 5 | 0 | 2 (OP-02 multi-instance, OP-04 CI lint) | 71% |
|
|
| **Total (active scope)** | **51** | **40** | **6** | **5** | 88% covered, 12% NOT_COVERED with reasons |
|
|
|
|
## Uncovered Items Analysis
|
|
|
|
| Item | Reason Not Covered | Risk | Mitigation |
|
|
|------|-------------------|------|-----------|
|
|
| AC-F-05, AC-F-06, AC-F-07, AC-F-08, AC-F-13, AC-F-42 | Gated on Refactor Backlog items (RB-01, RB-02, RB-06, RB-08, RB-09) | Until those refactors land, the lifecycle observability + soft-delete + dedupe contract are not in code | The corresponding tests are authored in advance (FT-P-21, FT-P-22, NFT-RES-01) and remain `skipped` until the RB items move; the cycle-update mode of the test-spec skill (per `.cursor/skills/test-spec/modes/cycle-update.md`) flips them to `enabled` when Phase B implements the RB items |
|
|
| ENV-06 (post-refactor) | CORS test now exercises the validator-enforced allow-list rather than the legacy wide-open default | None — the test asserts current behavior | NFT-SEC-09 covers it; no follow-up needed |
|
|
| ENV-04 | Branch-driven CI tag scheme is a CI concern, not a runtime contract | Wrong tag could deploy the wrong revision | Covered by Woodpecker pipeline tests (separate harness) — not a Step 6 deliverable |
|
|
| ENV-05 | Swagger UI exposure is a Step 14 (Security Audit) item | Information disclosure | Step 14 produces a SEC-XX item; test added once the gating decision is made |
|
|
| OP-02 | Multi-instance double-publish requires the test harness to spin up ≥ 2 SUT instances; current harness is single-instance | Two-pod deploy could double-publish | Documented as a pre-deployment constraint; full multi-instance testing waits for either RB-09 dedupe contract OR a horizontal-scale design decision |
|
|
| OP-04 | "No lint / formatter in CI" is a meta-restriction (about CI), not a runtime contract | Style drift, dead code accumulating | Step 14 / Step 17 retrospective will set this up; not a runtime test |
|
|
|
|
## Notes
|
|
|
|
- The `[after RB-XX]` rows in `results_report.md` correspond directly to the **Deferred** column above. The implementation skill (Step 6) is instructed to author these tests with `[Skip(Reason = "awaiting RB-01")]` etc., so they show in the test discovery surface and flip to active automatically when the gating refactor lands.
|
|
- The `Not covered` rows under ENV / OP are intentional — they are CI-pipeline or environment-level concerns that do NOT belong in the Step 6 blackbox suite. They are listed here so reviewers see the full restriction inventory.
|
|
- Per the test-spec Phase 3 hard gate threshold (≥ 75% coverage), the active-scope coverage of **88%** clears the bar with a wide margin.
|