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>
9.0 KiB
9.0 KiB
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 inresults_report.mdcorrespond 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 coveredrows 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.