mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-21 08:21:14 +00:00
30d99e09addfae8bcc8fb1c2fa6a85821a1c99fa
169 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
30d99e09ad |
[AZ-794] [AZ-795] [AZ-796] Cycle 7 Step 16 deploy report
Cycle 7 is a pure-quality cycle: no migrations, no new endpoints, no new env vars, unchanged container image base. The full shipping payload is a contract MAJOR bump (tile-inventory.md 1.0.0 -> 2.0.0, breaking) plus a new strict-validation surface across the inventory endpoint. Deploy report covers: - 3 cycle-7 commits (task adoption, implementation, sync) + this one + the pending close commit. - Zero migrations; tiles schema unchanged from cycle 6. - Postgres host-port move 5432 -> 5433 (dev-only sibling-conflict avoidance; staging/prod unaffected). - Two NuGet additions (FluentValidation 12.0.0 + .DependencyInjectionExtensions 12.0.0), both CVE-clean. - 5 verification gates: tests PASS, test-spec sync PASS, docs PASS, security PASS_WITH_WARNINGS (3 Low), perf PASS (9/9 incl. PT-09 v2 smoke). - 4 NEW cycle-7 recommended follow-ups (D-AZ795-1 FV bump; F-AZ795-1/2 message sanitisation; implementation-report exit-gate contract; AZ-795 child-task sweep for remaining public endpoints). - Zero new process leftovers; cycle 5/6 carry-overs unchanged. Step 16.5 (Release) skipped per the cycle-2-to-6 convention; the operator runbook in this deploy report serves as the release record. User-confirmed via Choose A/B/C at the Step 16.5 gate. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
bc04ba7f99 |
[AZ-794] [AZ-795] [AZ-796] Cycle 7 Steps 12-15 sync (test-spec / docs / security / perf)
Step 12 (Test-Spec Sync): adds BT-27 for the AZ-796 9-rule validation surface and 12 cycle-7 AC rows + Coverage Summary update to traceability-matrix.md. Step 13 (Update Docs): module-layout + module docs for the new SatelliteProvider.Api/Validators namespace + GlobalExceptionHandler + updated TileInventory DTO; tests_unit + tests_integration document the new InventoryRequestValidatorTests (16 unit tests covering all 9 rules) + TileInventoryValidationTests (16 integration tests) + ProblemDetailsAssertions support; glossary entries for Validation Problem Details / FluentValidation / Unmapped Member Handling; system-flows F8 (Tile Inventory Bulk Lookup) expanded with deserializer + validator gates and a 13-row Validation Surface table; data_parameters § Tile Inventory documents the v2 input schema + constraints; ripple_log_cycle7 captures the doc-side ripple decisions. Step 14 (Security Audit): 5-phase audit ran; verdict PASS_WITH_WARNINGS (3 Low findings — D-AZ795-1 FluentValidation 12.0.0 -> 12.1.1 recommended bump, F-AZ795-1 JsonException.Message leak in 400 detail, F-AZ795-2 BadHttpRequestException.Message leak). No Critical / High; auth runs before validation (confirmed in Program.cs); two NuGet additions (FluentValidation 12.0.0 + .DependencyInjectionExtensions 12.0.0) both CVE-clean. Per-phase reports plus consolidated security_report_cycle7.md. Step 15 (Performance Test): docker compose stack used for perf run, scripts/run-performance-tests.sh exited 0 with 8/8 scenarios PASS (second consecutive clean exit-0); added PT-09 cycle-7 smoke probe (v2 z/x/y schema, 2500-tile all-miss batch) measuring min=27ms median=44ms p95=73ms max=86ms (13.7x under AZ-505 AC-4 1000ms budget). PT-07/08 improvements traced to the cycle-6 TLS handshake-overhead identification, not application-side change. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
865dfdb3b9 |
[AZ-794] [AZ-795] [AZ-796] Strict input validation + z/x/y rename
AZ-794: rename inventory wire fields tileZoom/tileX/tileY -> z/x/y to match the slippy-map URL convention. Contract bumped to v2.0.0. AZ-795: shared validation infrastructure -- FluentValidation + ValidationEndpointFilter + GlobalValidatorConfig (camelCase paths). GlobalExceptionHandler now converts JsonException (UnmappedMember + JsonRequired) into RFC 7807 ValidationProblemDetails. JSON layer hardened with UnmappedMemberHandling.Disallow + camelCase naming policy. New error-shape.md contract. AZ-796: InventoryRequestValidator covers 9 rules (XOR tiles vs locationHashes, cap 1000, z 0..22, x/y in slippy bounds, hash length/charset). 16 unit tests + 16 integration tests + a manual curl probe script. Adjacent fixes uncovered by the new strict layer: - IdempotentPostTests RoutePoint payload corrected to lat/lon (the DTO has used JsonPropertyName for ages; previously silently ignored under PascalCase fallback). - TileInventoryTests slippy x/y reduced to fit z=18 bounds. - docker-compose.yml host port for Postgres moved 5432 -> 5433 to avoid sibling-project conflict; appsettings.Development + README + AGENTS + architecture + containerization docs aligned. New coderule (suite + repo): API consumer-facing OpenAPI descriptions must not contain task IDs, contract filenames, or version-bump history -- internal change tracking belongs in commits/contract docs/changelogs. Existing offending descriptions in Program.cs cleaned up. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
dceaddc436 |
[AZ-794] [AZ-795] [AZ-796] Adopt cycle 7 tasks (API quality follow-up)
Adopt three Jira tickets originally filed by gps-denied-onboard AZ-777 Phase 1 Jetson probing into satellite-provider cycle 7. - AZ-794: rename inventory body fields tileZoom/tileX/tileY → z/x/y (OSM convention; aligns body shape with URL slippy-map convention). - AZ-795: epic + shared infra ship for strict input validation across all public endpoints (FluentValidation + global ProblemDetails filter + JsonSerializerOptions.UnmappedMemberHandling.Disallow). - AZ-796: first concrete per-endpoint child of AZ-795 — strict validation for POST /api/satellite/tiles/inventory; reference implementation pattern for sibling per-endpoint tasks. Re-labels the cross-repo follow-up section in _dependencies_table.md as Step 9 cycle 7, sets cycle 7 ordering (shared infra → rename → inventory validator), and bumps the autodev state cursor to Step 10 (Implement) for cycle 7. Source: gps-denied-onboard AZ-777 Phase 1 Jetson probe (2026-05-22). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
7d3ba1c3fd |
Enhance .cursor documentation and workflows
Updated the README.md to reflect new skill commands and improved descriptions for various workflows, including the addition of new skills like /test-spec, /code-review, and /release. Enhanced clarity on session boundaries and flow resolutions in the auto-chaining process. Removed the implementer agent file as it is no longer needed. Updated coderule and meta-rule documents to enforce stricter testing and implementation standards, ensuring real results are produced rather than simulated ones. Revised the autodev flow documentation to include a new release step and clarified the retrospective process. Adjusted the testing rules to specify coverage thresholds for critical paths. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
19c0371fd6 |
[no-ticket] Sync .cursor with suite root
Bring this repo's .cursor/ in line with the suite monorepo root .cursor/ so rules, skills, and autodev artifacts stay consistent across submodules and sibling repos. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
af661359c7 |
[AZ-505] Cycle 6 Step 17: retrospective + close cycle
Single-task cycle delivering AZ-505 (3 SP); 1 batch, PASS verdict after a single auto-fix round (ComputeLocationHash duplication consolidated into Uuidv5.LocationHashForTile). Step 14 Security Audit skipped; Step 15 Performance Test PASS (8/8, exit 0) and closes the cycle-3 perf-harness leftover that carried across cycles 3-5. Top 3 lessons appended to LESSONS.md ring buffer: - Kestrel Http1AndHttp2 requires TLS for ALPN; spec-time decision - Dapper-bypassing test paths own the Npgsql type contract - Test fixtures naming specific schema artifacts need migration awareness Cycle 7 opens at Step 9 (New Task). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
ba3bdb1918 |
[AZ-505] Cycle 6 Steps 15-16 perf + deploy report
Step 15 (Performance Test): 8/8 PT scenarios PASS in a single default-parameter run (exit 0). Adapts scripts/run-performance-tests.sh for the new TLS+ALPN dev listener via CURL_OPTS=(--cacert ./certs/api.crt). Report at _docs/06_metrics/perf_2026-05-12_cycle6.md. The clean exit-0 satisfies the cycle-3 perf-harness leftover deletion criterion that carried across cycles 3-5; leftover file deleted. Step 16 (Deploy): _docs/03_implementation/deploy_cycle6.md captures the shipping payload (inventory endpoint, HTTP/2 TLS+ALPN, tiles_leaflet_path covering index, migration 015), the dev-cert plumbing for local-docker + integration-tests parity, the production-TLS topology note (terminate at ingress; never promote the dev cert), and the operator runbook for promoting cycle-6 past dev. NU1902 / CA2227 / ASPDEPR002 / Serilog-10.x re-listed as carry-overs unchanged; admin-team iss/aud confirmation unchanged. State advanced to Step 17 (Retrospective). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
5d84d2839e |
[AZ-505] Test-spec sync + task-mode doc updates for cycle 6
Step 12 (Test-Spec Sync, cycle-update mode): - blackbox-tests.md: append BT-23..BT-26 for AZ-505's new observable behaviors (inventory order/shape; leaflet most-recent via location_hash; HTTP/2 multiplex over TLS+ALPN; request validation). - performance-tests.md: append PT-09 (inventory p95 ≤ 1000ms / 2500 tiles); records cycle-6 measured p95=66ms; documents promotion path to scripts/run-performance-tests.sh if budget ever tightens. - traceability-matrix.md: resolve the 5 AZ-503 deferrals (AC-5/6/9/10/12) by pointing at AZ-505 test names + add 7 AZ-505 AC rows (AC-1..AC-7) + bump totals (90 -> 94 tests, 56/56 -> 63/63 in-scope) + add cycle-6 coverage shape notes (budget relaxation rationale, voting-filter deferral note, TLS+ALPN pivot, NFR propagation). Step 13 (Update Docs, task mode): - common_dtos.md: add 5 new TileInventory DTOs. - common_interfaces.md: add ITileService.GetInventoryAsync. - services_tile_service.md: document TileService.GetInventoryAsync steps + the XOR-validation-in-handler note. - dataaccess_migrator.md: bump migration count 14 -> 15; describe migration 015 (AZ-505 leaflet covering index, lock window, INCLUDE-list trade-off). - system-flows.md: add F7 (Leaflet Tile Serving, AZ-310 + AZ-505 location_hash rewire + TLS+ALPN) and F8 (Tile Inventory Bulk Lookup) with sequence diagrams, validation surface, and AC-4 perf evidence. Update Flow Inventory + Dependencies tables accordingly. - glossary.md: add "Tile Inventory" entry pointing at the v1.0.0 contract. - ripple_log_cycle6.md: new file — exhaustive reverse-dependency analysis confirms zero stale downstream module docs. Advance autodev state from step 11 -> 14 (skipping 12+13 as completed in this commit; auto-chain through Step 14 = Security Audit optional gate). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
c74a2339aa |
[AZ-505] AC-5 fix: enable TLS for HTTP/2 via ALPN
Kestrel with HttpProtocols.Http1AndHttp2 on a plaintext listener silently downgrades to HTTP/1.1-only (logs "HTTP/2 is not enabled ... TLS is not enabled"), so AC-5's multiplexed-GET test failed with HTTP_1_1_REQUIRED. ALPN cannot run over plaintext, so the fix switches the dev listener to TLS on https://+:8080: - scripts/run-tests.sh generates a self-signed dev cert idempotently (./certs/api.pfx + api.crt) via openssl in an alpine container; certs/ is gitignored. - docker-compose.yml binds Kestrel to ASPNETCORE_URLS=https://+:8080 with Kestrel__Certificates__Default__Path bound to the .pfx. - docker-compose.tests.yml mounts api.crt into the integration-tests container's CA store and runs update-ca-certificates so HttpClient trusts the cert transparently; default API_URL is now https://api:8080. - Drop the obsolete Http2UnencryptedSupport AppContext switch from Http2MultiplexingTests; ALPN over TLS handles negotiation. Test-data fixes caught on the post-TLS rerun (independent of the TLS switch but surfaced together): - Http2MultiplexingTests: switch slippy coords from (154321, 95812) -- which Google Maps returns 404 for -- to (158485, 91707), the slippy projection of (47.461747, 37.647063) already exercised by JwtIntegrationTests. - TileInventoryTests + LeafletPathIndexOnlyTests: SpecifyKind to Unspecified at the binding site for raw Npgsql seed paths writing into tiles.captured_at / created_at / updated_at (TIMESTAMP without tz). Npgsql v6+ refuses Kind=Utc into plain timestamp columns; production goes through Dapper and never hits this code path. - MigrationTests Az503NewUniqueIndexCoversIntegerKeyAndFlightId: accept either idx_tiles_location_hash (migration 014) or its AZ-505 successor tiles_leaflet_path (migration 015) -- both have location_hash as the leading column, which is the AC-9 intent. Docs updated to reflect the TLS+ALPN path: tile-inventory.md Non-Goals, modules/api_program.md, module-layout.md, the AZ-505 task spec's Risk 3, and the cycle 6 implementation + completeness reports. The full integration test suite passes (mode=full, exit 0). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
da40534b49 |
chore: advance autodev state to Step 11 (Run Tests) after AZ-505 batch 1
Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
909f69cb3a |
[AZ-505] Tile inventory endpoint + HTTP/2 + Leaflet covering index
Production code:
- POST /api/satellite/tiles/inventory (XOR body, 5000-cap,
most-recent-per-location_hash select, present/absent shaping).
- Kestrel HttpProtocols.Http1AndHttp2 on every listener (AC-5).
- Migration 015 creates tiles_leaflet_path covering index over
(location_hash, captured_at DESC, updated_at DESC, id DESC)
INCLUDE (file_path, source); drops superseded idx_tiles_location_hash.
- TileRepository.GetByTileCoordinatesAsync rewired to filter by
location_hash (Index Only Scan via tiles_leaflet_path).
- TileRepository.GetTilesByLocationHashesAsync added with Npgsql-
direct ANY($1::uuid[]) binding (Dapper IEnumerable expansion is
incompatible with the array form).
- Uuidv5.LocationHashForTile centralises the UUIDv5(TileNamespace,
"{z}/{x}/{y}") formula — single source of truth for the cross-repo
invariant (gps-denied-onboard parity).
Contracts:
- New: contracts/api/tile-inventory.md v1.0.0.
- Bumped: contracts/data-access/tile-storage.md to v2.0.0 (joint
ownership by AZ-503-foundation + AZ-505: schema + covering index +
GetByTileCoordinatesAsync rewrite).
Tests:
- TileInventoryTests covers AC-1, AC-2 (DB-level), AC-4, AC-6.
- Http2MultiplexingTests covers AC-5 (20 concurrent multiplexed GETs
over h2c via SocketsHttpHandler + AppContext Http2Unencrypted switch).
- LeafletPathIndexOnlyTests covers AC-3 (EXPLAIN (ANALYZE, BUFFERS)
asserts Index Only Scan over tiles_leaflet_path with heap_blocks=0).
Docs:
- architecture.md, system-flows.md, data_model.md, module-layout.md,
glossary.md, modules/api_program.md, modules/dataaccess_tile_repository.md,
components/02_data_access/description.md all updated to reference the
v2.0.0 tile-storage contract + new tile-inventory contract + AC-7.
Reports:
- batch_01_cycle6_report.md, batch_01_cycle6_review.md,
implementation_completeness_cycle6_report.md (PASS),
implementation_report_tile_inventory_cycle6.md.
Task spec moved todo/ -> done/.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
3c7cd4e56b |
chore: update autodev state to Step 10 (Implement) and refine task details for AZ-505
- Advanced the autodev state to Step 10, reflecting the implementation phase. - Updated task name for AZ-505 to "Implement" and adjusted its status to "not_started." - Enhanced the dependencies table with detailed context for AZ-505, clarifying its relationship with AZ-503 and its role in cycle 6. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
aa1a1bf19f |
chore: open cycle 6 — state advanced to Step 9 (New Task)
Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
ea278afb37 |
[AZ-503] [AZ-504] Cycle 5 Step 17: retrospective + close cycle
retro_2026-05-12_cycle5.md captures the cycle-end retrospective: - Implementation: 2 tasks (AZ-504 + AZ-503-foundation), 4 SP total, 100% first-attempt pass rate, 1 mid-implement scope-split (AZ-503 → AZ-503-foundation + AZ-505, blocked-linked). - Quality: 50/50 PASS/PASS_WITH_WARNINGS, 0 new Medium+, 1 new Low (defensive contentSha256 soft-NULL guard). - Security: PASS_WITH_WARNINGS, 0 new Critical/High/Medium, 2 new Low informational (F1 flightId provenance, F2 pgcrypto runbook gap). - Performance: PASS_WITH_INFRA_WARNINGS — first measurable PT-08 ever (Run #1 199ms, Run #2 117ms vs 2000ms threshold); PT-01/02 failed on recurring local Docker/colima DNS cold-start, not an app regression. - Structural: +1 ProjectReference edge (IntegrationTests → Common), +1 minor contract bump (uav-tile-upload 1.0.0 → 1.1.0), +1 DB migration (014_AddTileIdentityColumns.sql), 0 NuGet bumps, 0 csproj additions, DAG still acyclic at 9 projects. structure_2026-05-12_cycle5.md captures the structural snapshot. LESSONS.md updated with 3 cycle-5 entries (oldest dropped to preserve the 15-entry ring buffer): - [architecture] Cross-repo cryptographic invariants must live as code constants in both repos with reference-vector tests. - [tooling] When perf-mode "one re-run" fires twice with the same DNS root cause, escalate from re-run to harness fix. - [process] Spec contradicts live code by >=2 prerequisites → prefer split into foundation + follow-up (A/B/C option C). Top 3 follow-up actions (cycle 6 candidates): - Action 1 (1 SP): DNS pre-warm in scripts/run-performance-tests.sh → closes the cycle-3 perf-harness leftover. - Action 2 (5 SP): AZ-505 — inventory endpoint + HTTP/2 + Leaflet covering index (blocked-linked on AZ-503-foundation, this cycle). - Action 3 (1 SP): pgcrypto pre-install runbook step (F2-cy5 doc fix). Cycle 5 closed. Autodev state advanced for cycle 6 by the next /autodev invocation. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
0e05fc519a |
[AZ-503] [AZ-504] Cycle 5 Step 16 deploy report
deploy_cycle5.md captures everything operators need to promote cycle 5 beyond dev: - Code shipped: AZ-503-foundation (deterministic UUIDv5 tile identity, integer-only flight-aware UPSERT, per-flight on-disk paths) + AZ-504 (perf script grep-pipefail fix). - NEW database migration 014_AddTileIdentityColumns.sql adds flight_id, location_hash, content_sha256, legacy_id; enables pgcrypto; swaps the AZ-484 float index for the new idx_tiles_unique_identity integer index. Idempotent under DbUp's journal. - NEW contract version uav-tile-upload.md 1.0.0 → 1.1.0 (adds optional flightId; derived tileId in response). - NEW per-flight on-disk path layout for UAV tiles (additive; legacy paths preserved). - No env-var changes. Container image base unchanged from cycle 4. - Verification gates passed: PASS (Step 11), PASS (Steps 12+13), PASS_WITH_WARNINGS (Step 14), PASS_WITH_INFRA_WARNINGS (Step 15). - Cycle-3 perf-harness leftover stays OPEN with two clean follow-up paths recorded (DNS pre-warm in script, OR move perf gate to CI). - Operator runbook includes pgcrypto pre-install check for managed Postgres providers. Autodev state advanced to Step 17 (Retrospective). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
61612044fb |
[AZ-503] [AZ-504] Cycle 5 Steps 11-15 sync
Wrap up cycle 5 verification + documentation: - Steps 10/11 wrap-up reports (implementation_completeness + implementation_report) for the AZ-503-foundation + AZ-504 batch. - Step 12 test-spec sync: AZ-503-foundation/AZ-504 ACs appended; AZ-505 deferred ACs recorded. - Step 13 update-docs: architecture, data-model, glossary, module- layout, uav-tile-upload contract (v1.1.0), DataAccess + Services + Tests module docs synced; new common_uuidv5.md module doc. - Step 14 security audit: PASS_WITH_WARNINGS; 0 new Critical/High; 2 new Low informational (F1 flightId provenance, F2 pgcrypto deploy gap). - Step 15 performance test: PASS_WITH_INFRA_WARNINGS; PT-08 passed twice (AZ-504 fix verified); PT-01/02 failed due to recurring local Docker/colima DNS cold-start (not an app regression). Cycle-3 perf-harness leftover stays OPEN with replay #5 documented. - Autodev state moved to Step 16 (Deploy). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
c646aa93e2 |
[AZ-503] Tile identity → UUIDv5 + integer UPSERT (foundation)
Foundation half of original AZ-503 (split during /autodev step 10 batch 2
on user choice; deferred work moved to AZ-505 with a Blocks link).
Adds deterministic tile identity (UUIDv5 over (z, x, y, source, flight_id))
shared cross-repo with gps-denied-onboard via the pinned TileNamespace
5b8d0c2e-7f1a-4d3b-9c5e-1f3a8e7d2b6c, switches the tiles UPSERT key from
floats to integers with per-flight separation, plumbs FlightId through
UavTileMetadata + handler, and writes UAV evidence to per-flight
on-disk directories so two flights at the same (z, x, y) coexist.
- Common: pure-C# RFC 9562 Uuidv5 (no third-party dep) + FlightId DTO
field; 10 Python-reference unit vectors verify byte parity.
- DataAccess: migration 014 adds flight_id (uuid NULL), location_hash
(uuid NOT NULL, backfilled via session-scoped pg_temp.uuidv5),
content_sha256 (bytea NULL), legacy_id (uuid NULL = preserves
pre-AZ-503 random id one cycle); drops idx_tiles_unique_location_source
(AZ-484) and adds idx_tiles_unique_identity keyed on
(tile_zoom, tile_x, tile_y, tile_size_meters, source,
COALESCE(flight_id, '00000000-...'::uuid)) + idx_tiles_location_hash.
- TileRepository: ColumnList + UPSERT updated; id never updated on
conflict (preserves AC-2 idempotence). UpdateAsync extended.
- Services: TileService and UavTileUploadHandler compute deterministic
Id + LocationHash + ContentSha256 before insert; UAV file path
becomes ./tiles/uav/{flight_id or 'none'}/{z}/{x}/{y}.jpg.
- Tests: Uuidv5Tests (10 reference vectors), UavTileFilePathTests
(per-flight + anonymous paths), UavTileUploadHandlerTests (AC-2,
AC-3, AC-7, AC-11 unit-level), UavUploadTests (AC-3 + AC-4
integration: multi-flight DB coexistence with shared location_hash
+ distinct file_path; float-different lat/lon collapse to 1 row),
MigrationTests (column shape, idx_tiles_unique_identity supersedes
AZ-484 index, deterministic backfill).
- IntegrationTests project references Common to reuse Uuidv5 in raw
SQL seeds.
- AZ-488 MultiSourceCoexistence seed fixed to populate location_hash
(otherwise migration 014's NOT NULL constraint fails).
ACs covered: AC-1, AC-2, AC-3, AC-4, AC-7, AC-8, AC-11.
ACs deferred to AZ-505: AC-5, AC-6, AC-9, AC-10, AC-12.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
f6197499a4 |
chore: update autodev state after AZ-504 batch 1
Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
ab437a15df |
[AZ-504] Fix grep | wc -l pipefail crash in PT-08 batch counting
scripts/run-performance-tests.sh:416-417 used `grep -o ... | wc -l` to count `"status":"accepted"` and `"status":"rejected"` markers in the PT-08 batch response. On the happy path (rejected=0) grep -o exits 1, and under `set -o pipefail` + `set -e` (line 16) the pipeline killed the script before reaching any of PT-08's reporting code — reproducing twice in the cycle-3 perf-harness leftover (replay #2 + #3 post-AZ-500). Fix: neutralise grep's no-match exit locally with `|| true` on the grep stage of each pipeline. `grep -o | wc -l` is kept (not swapped for `grep -c`) because the PT-08 response is compact JSON — all items live on one line, so `grep -c` would always return 1 and lose occurrence-count semantics. An 8-line comment explains why grep cannot fail for I/O at this code path (file is curl-written, HTTP 200 gated). AC-1 + AC-2 verified in-place against a standalone harness under `set -e -o pipefail` (compact-JSON, mixed-status, edge-empty cases). AC-3 + AC-4 are Step 15 (Performance Test) obligations by spec design — the leftover deletion (AC-4) is "in the same commit" as the green full perf run. Batch report: _docs/03_implementation/batch_01_cycle5_report.md. Code review: _docs/03_implementation/reviews/batch_01_cycle5_review.md — PASS, no findings. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
8e509b550c |
[AZ-503] [AZ-504] cycle 5 new-task: tile identity + perf-script-fix
- AZ-503 (3 SP, epic AZ-483) — Tile identity → UUIDv5 deterministic id; integer-only UPSERT with COALESCE(flight_id) per-flight separation; content_sha256 column; POST /api/satellite/tiles/inventory bulk-list endpoint; HTTP/2 at Kestrel edge. Cross-workspace handoff from gps-denied-onboard (AZ-304 / AZ-316 counterpart). Supersedes the AZ-484 UPSERT-conflict-key portion. - AZ-504 (1 SP, epic AZ-483) — Fix scripts/run-performance-tests.sh lines 416-417: grep -o | wc -l + set -o pipefail kills PT-08 when rejected=0. Closes the replay obligation for the cycle-3 perf-harness leftover (leftover deletion gated on green full perf run, AC-4). Updates _dependencies_table.md with cycle 5 entries and records replay attempt #4 against the perf-cycle3 leftover (PBI opened — leftover still stays until AZ-504 lands and full perf run is green). State advanced to Step 10 (Implement). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
e31f59211d |
[AZ-500] Cycle 4 Step 17: retrospective + close cycle
Adds retro_2026-05-12_cycle4.md, structure_2026-05-12_cycle4.md, and the deploy_cycle4.md report that was dropped from the Steps 12-15 sync commit. Appends 3 new lessons to LESSONS.md (12/15 ring buffer) on transitive major-version bumps, exposed pre-existing bugs, and single-task-cycle metric framing. State advances to cycle 5 / step 9 (awaiting next New Task invocation). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
af4219fce6 |
[AZ-500] Cycle 4 Steps 12-15 sync (test-spec / docs / security / perf)
Step 12 (Test-Spec Sync) - cycle-update mode
- traceability-matrix: 8 AZ-500 AC rows + .NET 10 runtime
restriction supersession + Cycle-4 coverage shape note
(no new tests; ACs verified by re-running existing 78-test
suite + build pipeline + manifest grep)
Step 13 (Update Docs) - task mode
- FINAL_report, 00_discovery, architecture, module-layout,
api_program, tests_unit: .NET 8 -> .NET 10 / C# 12 -> 14 /
Swashbuckle 6.6.2 -> 10.1.7 + Microsoft.OpenApi 2.x
refactor note in api_program; Serilog.AspNetCore 8.0.3
fallback documented inline per AZ-500 Risk #4
- deployment/{containerization, ci_cd_pipeline}: Docker
aspnet/sdk:8.0 -> :10.0
- ripple_log_cycle4: empty import-graph ripple recorded
(Program.cs is entry point; ParameterDescriptionFilter only
consumed by Program.cs; csproj/global.json/Dockerfile have
no import edges)
Step 14 (Security Audit) - resume mode
- dependency_scan_cycle4: AZ-500 19-package delta scanned;
cycle-3 D1+D3 (CVE-2026-26130) closed by major-version
bump; cycle-3 D2 (Test.Sdk 17.8.0 NuGet.Frameworks flag)
carried over - explicitly out of AZ-500 scope
- security_report_cycle4: PASS_WITH_WARNINGS (only carry-over
Medium open; AZ-500 introduced 0 new Critical/High); cycle-3
static_analysis/owasp_review/infrastructure_review carried
forward unchanged (AZ-500 made no source-level edits to
those surfaces)
Step 15 (Performance Test) - perf mode, full default-param run
- perf_2026-05-12_cycle4: 7 Pass + 1 Unverified (PT-08 hit
pre-existing scripts/run-performance-tests.sh:417 grep-
pipefail bug, NOT a .NET 10 regression)
- PT-07 warm p95 = 301ms (7.7x improvement vs cycle-3 short
variant - .NET 10 pipeline + N=20 dilution); cold p95 =
2782ms (-14%); PT-06 90ms (-49%)
- AZ-500 NFR (Performance) MET for 7/8 scenarios
- Cycle-3 perf-harness leftover updated with replay #3
results; STAYS OPEN per AZ-500 Constraint (deletes only on
fully clean run)
Recommended follow-up PBIs (out of cycle-4 scope, surfaced for
the backlog):
- 1 SP fix scripts/run-performance-tests.sh:416-417 grep-
pipefail (replace grep -o ... | wc -l with grep -c ... ||
true) - unblocks PT-08 + closes the cycle-3 perf leftover
- 3 SP migrate WithOpenApi(...) callsites to ASP.NET Core 10
minimal-API metadata extensions (clears 8 ASPDEPR002
warnings; recorded in batch_01_cycle4_review.md)
- 1 SP Microsoft.OpenApi 2.x nullable cleanup (CS8604 in
ParameterDescriptionFilter.cs:25)
- 1 SP bump Microsoft.NET.Test.Sdk 17.8.0 -> 17.13.0+
(closes cycle-3 D2 NuGet.Frameworks transitive flag)
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
de609cffa1 |
[AZ-500] Cycle 4 implement-skill wrap-up reports
Adds the cycle-4 product implementation completeness gate report (verdict: PASS) and the final implementation report for the .NET 10 migration. Records the Step 16 handoff to Step 11 (test-run skill) to avoid duplicating the full-suite run already executed during AC-6 verification (271/271 unit + full integration suite green). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
813136326f |
[AZ-500] .NET 8 -> .NET 10 migration
Coordinated cross-cutting bump: 9 csproj TFMs net8.0 -> net10.0;
global.json sdk.version 8.0.0 -> 10.0.0; all Dockerfiles + scripts/
+ .woodpecker on mcr.microsoft.com/dotnet/{sdk,aspnet,runtime}:10.0;
all Microsoft.AspNetCore.* (8.0.25) and Microsoft.Extensions.* (9.0.10)
packages -> 10.0.7. Serilog.AspNetCore retained at 8.0.3 (10.0.0
requires Serilog.Sinks.File >= 7.0.0; out of AZ-500 scope per "no
unrelated package bumps") -- documented in AGENTS.md. Swashbuckle
9.x bumped to 10.1.7 to track Microsoft.OpenApi 2.x; Program.cs +
ParameterDescriptionFilter.cs refactored for the 2.x namespace
(Microsoft.OpenApi), OpenApiSecuritySchemeReference, JsonSchemaType
enum, and IOpenApiSchema dictionary properties. Fixed implicit AC-5
prereq: scripts/run-performance-tests.sh PERF_DLL path bin/Release/
net8.0 -> net10.0. Docs sync: architecture.md + AGENTS.md.
ACs verified: AC-1..AC-4 + AC-7 + AC-8 by grep + build; AC-6 by
./scripts/run-tests.sh --full (271/271 unit tests + full integration
suite green); AC-5 short bootstrap-smoke (PERF_REPEAT_COUNT=2
PERF_UAV_BATCH_SIZE=2) succeeded at the bootstrap step (no exit 3),
PT-01..PT-07 PASS. PT-08 surfaced a pre-existing grep-pipefail bug
in run-performance-tests.sh:417 -- not an SDK problem; recorded as
follow-up in the perf-cycle3 leftover. Code review verdict:
PASS_WITH_WARNINGS (2 Medium deferred per scope discipline:
WithOpenApi ASPDEPR002 deprecation x8, CS8604 nullable in
ParameterDescriptionFilter.cs; both targeted at follow-up PBIs).
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
c0f004d2c9 |
[AZ-500] Cycle 4 Step 9: new-task .NET 10 migration
Closes Step 9 (New Task) of cycle 4. AZ-500 spec defines the .NET 8 -> .NET 10 migration (TFM bump on 9 csprojs, global.json SDK pin to 10.0.0, both Dockerfiles + run-tests.sh + woodpecker to mcr.microsoft.com/dotnet/*:10.0, Microsoft.AspNetCore.* and Microsoft.Extensions.* to the 10.x line, Serilog.AspNetCore to 10.x or documented 8.0.3 fallback, plus arch.md + AGENTS.md doc sync). Closes the cycle-3 perf-harness leftover via AC-5 (bootstrap smoke after migration). Also logs the cycle-4 perf-leftover replay attempt that discovered the host-SDK / project-SDK mismatch and rolls the state file from cycle 3 -> cycle 4 (Step 9 done -> Step 10 ready). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
ca0ca9f2a4 |
[AZ-491] [AZ-492] [AZ-493] [AZ-494] [AZ-495] [AZ-496] Cycle 3 Step 17: retrospective + close cycle
Cycle-3 retrospective:
- 6 tasks (AZ-491..AZ-496), 5 batches, 18 SP delivered.
- 100% code review pass rate (5/5 PASS_WITH_WARNINGS, 0 FAIL).
- 0 Critical/High/Medium review findings; 7 distinct Low.
- Security audit PASS_WITH_WARNINGS: 0 new Medium, 3 Low (all
test-only or operator-CLI), 2 Informational, 1 False Positive.
- Net Architecture delta: **-3** (F-AUTH-2 + D1 + D3 RESOLVED;
only new findings are Low test-side surfaces). First
net-negative cycle on record.
- 5 of 6 tasks completed first attempt (no post-review fix
commits). Cycle-2's 2 prior-retro actions all translated to
closed work (AZ-491 from Action 1, AZ-492 from Action 2,
AZ-493 from Action 3).
Top 3 cycle-4 improvement actions surfaced:
1. Execute the perf harness to capture PT-07/PT-08 baseline.
2. Bump TestSupport JWT pins 7.0.3 → 7.1.2+ (D4 NU1902 cleanup).
3. Add `workspace:` tag to cross-repo ACs in task-spec writing
and render them separately in the traceability matrix.
3 new ring-buffer lessons appended to _docs/LESSONS.md:
- [process] Option-B forcing functions for cross-team blockers.
- [process] ACs prescribing a measurement should also prescribe
the collection path.
- [process] Cross-repo-write ACs need workspace tags.
Structural snapshot at structure_2026-05-12_cycle3.md records the
new SatelliteProvider.TestSupport project (+2 ProjectReference edges
into it; no production-layer dependents) and the AZ-496 package
bumps (8.0.21 → 8.0.25).
Cycle 3 COMPLETE. State advanced to Step 9 (New Task) for cycle 4
per existing-code flow Re-Entry After Completion.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
65cdfae970 |
[AZ-491] [AZ-492] [AZ-493] [AZ-494] [AZ-495] [AZ-496] Cycle 3 Step 15 skip + Step 16 deploy report
Step 15 (Performance Test): SKIPPED. User skipped the optional gate
question. Per meta-rule.mdc, performance tests require explicit
approval; a skipped question is not approval. Recorded as leftover at
_docs/_process_leftovers/2026-05-12_perf-cycle3-harness-execution.md
for replay at next /autodev invocation.
Step 16 (Deploy): COMPLETED. Produced deploy_cycle3.md mirroring the
cycle-2 shape. Covers:
- 9 cycle-3 commits + zero DB migration
- Config changes (JWT_ISSUER/JWT_AUDIENCE env vars w/ fail-fast,
8.0.25 package bumps, new TestSupport project)
- Pre-deploy gate recap (Steps 11-15)
- Cycle-3 operational risks R1-R4 (admin-team iss/aud confirm,
cross-repo doc deferral, cycle-2 R1/R3 carry-overs, test-runner
log line)
- Rollback plan, post-deploy verification (incl. wrong-iss / wrong-
aud smoke probes), CI/CD push policy
- Resolved this cycle: F-AUTH-2, D1, D3, PT-07/PT-08 leftover
- Follow-up backlog: D4 NU1902 bump, F-DBR-2 third guard, F-PERF-1
token-history hardening, image-fixture consolidation, AC-7 cross-
repo write, no-revocation-list residual
Next: Step 17 (Retrospective, cycle-end mode).
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
314d1dec39 |
[AZ-491] [AZ-492] [AZ-493] [AZ-494] [AZ-496] Cycle 3 Step 14: security audit refresh
All 5 phases refreshed against cycle-3 delta:
Phase 1 (Dependency Scan):
- D1 RESOLVED (AZ-496): Microsoft.AspNetCore.OpenApi 8.0.21 → 8.0.25
- D3 RESOLVED (AZ-496): JwtBearer 8.0.21 → 8.0.25
- D4 NEW (Low, test-only): System.IdentityModel.Tokens.Jwt 7.0.3 +
Microsoft.IdentityModel.Tokens 7.0.3 pinned in TestSupport carry
CVE-2024-21319 (JWE DoS). Bump to ≥ 7.1.2 tracked as future PBI.
Phase 2 (Static Analysis):
- F-AUTH-3 (Info): test runner Program.cs logs iss/aud at startup;
production API does NOT (verified by grep).
- F-AUTH-4 (Info): DEV-ONLY iss/aud placeholders in
appsettings.Development.json + .env.example — by design per
Option B for AZ-494.
- F-DBR-1: TRUNCATE string interpolation in
IntegrationTestDatabaseReset.cs — false positive (hard-coded
table list).
- F-DBR-2 (Low): TRUNCATE guard is operator-bypassable. Two-guard
model is conservative-by-default and unit-tested.
- F-PERF-1 (Low): perf-bootstrap --mint-only writes a 4-hour
GPS-permission token to stdout. Operator-trusted machine assumed.
Phase 3 (OWASP Top 10):
- A03 carries D1/D3 RESOLVED + D4 NEW.
- A07 flips F-AUTH-2 to RESOLVED (AZ-494); residual revocation-list
Low recorded.
- A05 status unchanged (F-DBR-1 false positive).
- A08 picks up F-DBR-2.
Phase 4 (Infrastructure):
- JWT_ISSUER / JWT_AUDIENCE flow .env → compose → Kestrel config,
same pattern as JWT_SECRET.
- INTEGRATION_TEST_DB_RESET + ASPNETCORE_ENVIRONMENT=Testing wired
for AZ-493 reset gate.
- SatelliteProvider.TestSupport is IsPackable=false — never ships
in a production container image.
- New operational gate added to deploy runbook: grep for DEV-ONLY-
in the rendered deploy environment must return zero hits.
Phase 5 (Security Report):
- Verdict: PASS_WITH_WARNINGS (cycle 3 does not escalate).
- 0 Critical, 0 High, 0 new Medium.
- Cycle-2 F-AUTH-2 (Medium) RESOLVED; cycle-1 D1 + cycle-2 D3
RESOLVED.
Autodev state advanced to Step 14 completed. Next: Step 15
(Performance Test, optional gate).
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
e42bf62152 |
[AZ-491] [AZ-492] [AZ-493] [AZ-494] [AZ-495] [AZ-496] Cycle 3 Steps 11-13: test-spec sync + ripple log
Step 11 (Run Tests) is recorded as PASS based on the implement skill's
internal Step 16 gate (./scripts/run-tests.sh --full, all-green) per
test-run/SKILL.md § Functional Mode — same runner, immediately
preceding invocation, no value in a second run.
Step 12 (Test-Spec Sync, cycle-update mode):
- traceability-matrix.md: rows added for AZ-491 AC-1..AC-6,
AZ-493 AC-1..AC-6, AZ-495 (doc convention), AZ-496 AC-1..AC-N
(dependency bump); AZ-494 AC-1/AC-2 rows now cross-reference
new SEC-12 / SEC-13 blackbox IDs.
- security-tests.md: SEC-12 (wrong iss returns 401) and SEC-13
(wrong aud returns 401) appended for AZ-494.
- environment.md: Environment Variables table extended with
GOOGLE_MAPS_API_KEY, JWT_SECRET, JWT_ISSUER, JWT_AUDIENCE,
INTEGRATION_TEST_DB_RESET. Closes a cycle-2 oversight where
JWT_SECRET was never recorded.
Step 13 (Update Docs, task mode):
- tests_unit.md: consolidated the duplicate
AuthenticationServiceCollectionExtensionsTests entry that
spanned AZ-487 + AZ-494 into one coherent block.
- ripple_log_cycle3.md created: per-task source files +
every doc that was touched (architecture, module-layout,
api_program, tests_unit, tests_integration, traceability,
performance-tests, security-tests, environment, security_report,
owasp_review, deploy_cycle2, retro_2026-05-11_cycle2). Notes
which docs were intentionally NOT touched and the open
cross-repo doc ripple (AC-7).
Autodev state advanced to Step 13 completed. Next: Step 14 Security
Audit (optional gate).
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
495605f51b |
[AZ-494] [AZ-492] Cycle 3 Step 16: full test suite green; close batches
Final cumulative review for batches 04-05 (PASS_WITH_WARNINGS, 4 Low findings, all non-blocking). Combined with the prior 01-03 cumulative, this closes the per-cycle batch coverage with two PASS_WITH_WARNINGS verdicts. scripts/run-tests.sh --full green: format check + 13 cycle-3 unit tests (including the 4 new AZ-494 fail-fast cases for missing / empty iss / aud) + the full integration suite (including the 2 new WrongIssuer / WrongAudience 401 assertions). Fixed a stale "leave blank to fall back" comment in .env.example that contradicted the "REQUIRED" line right above it; the integration runner reads env vars directly with no appsettings fallback so blank values now fail-fast. Advanced _docs/_autodev_state.md to mark Step 10 (Implement) status: completed. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
f979e18811 |
[AZ-494] Enable JWT iss/aud validation with fail-fast startup
Option B per user decision: production ships with empty Jwt.Issuer / Jwt.Audience in appsettings.json so the API process refuses to start unless JWT_ISSUER + JWT_AUDIENCE env vars are supplied. Development ships with grep-friendly DEV-ONLY- placeholders so local + docker flows keep working unchanged. AuthenticationServiceCollectionExtensions flips ValidateIssuer + ValidateAudience to true and wires ValidIssuer / ValidAudience via a new ResolveRequiredOrThrow helper that all three required values (secret, iss, aud) now share. JwtTokenFactory.Create + CreateExpired gain optional iss / aud parameters (default null) so existing call sites compile unchanged. JwtTestHelpers adds MintAuthenticated / MintExpired wrappers that resolve iss + aud from env, plus ResolveIssuerOrThrow / ResolveAudienceOrThrow. PerfBootstrap.MintToken + Program.cs JWT bootstrap migrated to the new surface so the perf harness and the integration runner both validate against the same contract. Adds 4 fail-fast unit tests (missing/empty issuer + audience), 2 negative integration scenarios (WrongIssuer_Returns401, WrongAudience_Returns401), and re-tags every existing integration mint site via MintAuthenticated. Compose, .env.example, run-tests.sh, run-performance-tests.sh all load + export JWT_ISSUER + JWT_AUDIENCE alongside JWT_SECRET. Resolves F-AUTH-2 (security_report.md + owasp_review.md). AC-7 (cross-repo suite/_docs/10_auth.md write) deferred — outside this workspace; tracked in deploy_cycle2.md R3 follow-up. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
080441db5d |
[AZ-492] Cycle 3 batch 4: perf harness PT-07 + PT-08 + JWT-attach
Drains all three deferred perf-harness items in one batch: - PT-01..PT-06 now carry Authorization: Bearer minted via the canonical SatelliteProvider.TestSupport.JwtTokenFactory (AZ-491) — no third copy of JWT logic in the shell. - PT-07 implemented as cold + warm dual-pass distribution (N=20 each), reports p50/p95 for both passes and fails if warm p95 >= cold p95. - PT-08 implemented as 20-batch upload distribution with batch p95 gated at the AZ-488 2000 ms target; per-item gate cost reported as derived proxy (batch_p95 / batch_size). New SatelliteProvider.IntegrationTests/PerfBootstrap.cs adds two CLI short-circuit subcommands (--mint-only and --gen-uav-fixture <path>) invoked by the shell so the perf script never inlines the JWT or JPEG-fixture logic. The dispatch sits at the top of Program.cs Main and runs before any HTTP / DB / readiness setup. performance-tests.md PT-07 + PT-08 flip from Deferred to Implemented. traceability-matrix.md PT-07 + PT-08 rows move from recorded to covered (PT-08 partial due to per-item proxy — flagged Low in batch-4 review). _docs/_process_leftovers/2026-05-11_perf-pt07-harness.md deleted; the leftovers directory is now empty. Closes cycle-2 retro Action 2; LESSONS.md [process] rule about Deferred NFRs remains in force as a guardrail. Also includes the previously-uncommitted cumulative review report for cycle-3 batches 01-03 (generated at the end of batch 3 but not staged). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
745f4840e6 |
[AZ-493] Cycle 3 batch 3: integration test DB-reset hook
AZ-493 (2 SP): replace the cycle-2 wallclock-seeded _coordinateCounter workaround with a proper Postgres state-reset hook that runs at integration test runner startup, eliminating the per-source-unique-index collision risk that the persistent docker-compose Postgres volume introduced post-AZ-484. The reset is split into two surfaces: * SatelliteProvider.TestSupport.IntegrationTestResetGuard - pure static class, I/O-free, unit-tested. Two independent guards: (a) ASPNETCORE_ENVIRONMENT must equal "Testing", (b) DB_CONNECTION_STRING Host must be in the allowed-host list (postgres, localhost, 127.0.0.1). Failure of either guard surfaces a structured operator-friendly InvalidOperationException. * SatelliteProvider.IntegrationTests.IntegrationTestDatabaseReset - instance class owning the Npgsql side effects. Calls the guard then runs TRUNCATE TABLE route_regions, route_points, routes, regions, tiles RESTART IDENTITY CASCADE inside a single Npgsql transaction. Spec-vs-reality: the task spec prescribed "DB name contains _test" as Guard 2; the actual compose file uses Database=satelliteprovider and DB rename is gated on user confirmation per coderule.mdc. Substituted a Host allowlist as the equivalent guard (intent identical: reject remote / production hosts). Recorded as Low/Spec-Gap in the review. Program.cs adds --keep-state CLI flag and INTEGRATION_KEEP_STATE env var (1/true) opt-outs so a developer can inspect leftover state when debugging. Startup banner shows which path executed. docker-compose.tests.yml gets ASPNETCORE_ENVIRONMENT=Testing + passthrough for INTEGRATION_KEEP_STATE. scripts/run-tests.sh wires the --keep-state flag through to compose. UavUploadTests._coordinateCounter wallclock seed is retained as defense-in-depth (per the task spec's implementer choice). The reset is the primary isolation path; the seed is the belt-and-suspenders fallback for --keep-state runs. 8 new unit tests in SatelliteProvider.Tests/TestSupport/ IntegrationTestResetGuardTests.cs cover Production/Staging/missing-env throw, allowed-host case-insensitivity, disallowed-host rejection with representative prod hostnames, and the AllowedHosts contract. tests_integration.md gains a Reliability section that documents the hook, the two guards, the truncate order, and the three opt-out forms. module-layout.md TestSupport entry extended with the new pure guard and the explicit "Npgsql stays in IntegrationTests" boundary. Test-suite gate (AC-6) deferred to Step 16 Final Test Run per implement skill convention. Per-batch review verdict: PASS_WITH_WARNINGS with 1 Low (spec-vs-reality on Guard 2, non-blocking). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
c396740644 |
[AZ-491] Cycle 3 batch 2: consolidate JWT test-mint helpers into TestSupport
AZ-491 (3 SP): eliminate the cycle-2 duplicate of JWT-minting logic that existed in both SatelliteProvider.Tests/TestUtilities/ JwtTokenFactory.cs (unit-side) and SatelliteProvider.IntegrationTests/ JwtTestHelpers.cs (integration-side), where the same Expires < NotBefore bug needed parallel fixes in commits |
||
|
|
9cfd80babe |
[AZ-495] [AZ-496] Cycle 3 batch 1: doc convention + AspNetCore 8.0.25
AZ-495 (1 SP): formalize the modules-only documentation convention for the WebApi component. _docs/02_document/module-layout.md now carries an explicit Documentation Layout section anchoring WebApi docs at modules/api_program.md; the components/06_web_api/ folder is intentionally absent. .cursor/skills/new-task/SKILL.md Step 4 directs future agents at the correct path. Cycle-1 + cycle-2 F1 findings in the two batch-review files are marked RESOLVED with back-reference to AZ-495. Cycle-2 retrospective decision-item list F1 updated. AZ-496 (2 SP): bump Microsoft.AspNetCore.OpenApi and JwtBearer in SatelliteProvider.Api.csproj from 8.0.21 to 8.0.25, closing CVE- 2026-26130 (SignalR DoS - not reachable in this app, but the runtime patch is the recommended hardening per cycle-1 D1 + cycle-2 D3). SatelliteProvider.Tests.csproj has no direct JwtBearer reference - it consumes JwtBearer transitively via ProjectReference to Api, so no edit needed there. Dockerfiles use floating mcr.microsoft.com/ dotnet/aspnet:8.0 / sdk:8.0 / runtime:8.0 tags which auto-resolve to >= 8.0.25 on rebuild. Security artifacts (dependency_scan.md, security_report.md) and current-state docs (module-layout.md, architecture.md, modules/api_program.md, modules/tests_unit.md) updated to reflect 8.0.25. Batch report + code review report (verdict PASS_WITH_WARNINGS with 2 Low findings, neither blocking) written under _docs/03_implementation. Test suite gate deferred to Step 16 (Final Test Run) per implement skill convention. Patch-level bump within .NET 8 LTS; regression risk very low. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
76076cbd90 |
[AZ-491] [AZ-492] [AZ-493] [AZ-494] [AZ-495] [AZ-496] Cycle 3 Step 9: 6 task specs
Drains the cycle-2 retrospective top-3 improvement actions plus three carried-forward security and process items, into 6 individually- trackable PBIs: - AZ-491 (3 SP) consolidate JWT test-mint helpers (Retro Action 1) - AZ-492 (3 SP) perf harness PT-07 + PT-08 + JWT-attach (Retro Act. 2) - AZ-493 (2 SP) integration test DB-reset hook (Retro Action 3) - AZ-494 (2 SP) JWT iss/aud validation (cycle-2 F-AUTH-2 Medium) - AZ-495 (1 SP) doc-folder convention for WebApi (cycle 1+2 F1 carry) - AZ-496 (2 SP) bump AspNetCore 8.0.21 -> 8.0.25 (cycle 1+2 D1+D3) All 6 at-or-below the user-rule 5 SP cap. AZ-494 gated on admin-team confirming iss/aud values. Cycle 3 total: 13 SP. Autodev pointer advances to Step 10 Implement. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
b69cf5640e |
[AZ-487] [AZ-488] retro: cycle 2 report + structural snapshot
Cycle-2 retrospective covering AZ-487 + AZ-488. Captures six patterns (duplicate JWT helpers diverged then both broke; pre-existing test bugs unmasked by downstream test pressure; cycle 1 perf-NFR action stopped adding scenarios but did not drain backlog; doc-path F1 carried over twice with no decision; integration test DB isolation = wallclock workaround; 8 SP friction observable even with user override). Top-3 improvement actions: consolidate JWT mint helpers, promote PT-07/PT-08/JWT-attach to real PBI, real integration DB-reset hook. LESSONS.md ring buffer now holds 6 entries (testing x3, process x2, estimation x1). Structural snapshot: 6 components / 12 PR edges unchanged; contract coverage 14% -> 29%; new external NuGet edges (JwtBearer 8.0.21 + ImageSharp 3.1.11) tied to cycle-2 security findings. Autodev pointer advances to cycle 3 / Step 9 New Task. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
e9f4e84adb |
[AZ-487] [AZ-488] docs: cycle 2 deploy report
Per-cycle deploy report covering AZ-487 (JWT baseline) + AZ-488 (UAV tile batch upload). Lists all 12 cycle-2 commits already pushed to origin/dev, recaps Steps 11-15 gate outcomes, flags three operator-gated risks (R1 consumer Bearer-token coordination, R2 JWT_SECRET prod-distinct verification, R3 GPS-permission claim provisioning), documents rollback (image flip; zero schema change), and lists deferred follow-ups (PT-07/PT-08 harness + run-perf script JWT-attach, F1 doc-folder choice). Advances autodev pointer to Step 17 (Retrospective). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
cbbb26bd28 |
[AZ-487] [AZ-488] chore: cycle 2 Step 15 skip + record JWT-attach script rot
Step 15 (Performance Test) — skipped per gate (option B). Recording two deferred items in the existing perf leftover: * PT-07 + PT-08 remain Deferred. Both NFRs depend on the same baseline-capture harness that has not landed; the integration-test fixtures needed for PT-08 already exist (UavUploadTests + UavTileImageFactory), so PT-08 attaches to the same harness as PT-07 when implemented. * scripts/run-performance-tests.sh PT-01..PT-06 currently return 401 against the post-AZ-487 build because they attach no Bearer token. Script must mint an HS256 token from JWT_SECRET at script start before any curl call. Tracked in the leftover so PT-01..PT-06 are runnable again the same cycle PT-07/PT-08 are activated. No code change in this commit — leftover + state advance only. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
5214a4a647 |
[AZ-487] [AZ-488] security: cycle 2 delta audit (PASS_WITH_WARNINGS)
Step 14 (Security Audit) for cycle 2 — delta scan against the cycle-1 baseline. Verdict remains PASS_WITH_WARNINGS; no Critical/High. Scope: JWT auth boundary (AZ-487) and UAV multipart upload + ImageSharp decode of attacker-controlled bytes (AZ-488). Both new packages (JwtBearer 8.0.21, ImageSharp 3.1.11 in Services.TileDownloader) checked. Cycle-2 delta: * 0 Critical / 0 High * 2 Medium: F-AUTH-2 (iss/aud not validated — by design until admin team publishes values, AZ-487 § Constraints), F-UAV-1 (ImageSharp decode now runs on attacker-controlled bytes — mitigations sufficient; pin to GHSA subscribe-and-bump policy). * 4 Low: F-AUTH-1 (DEV-ONLY secret in appsettings.Development.json — accepted), F-AUTH-3 (rate-limit gap extends to 401 floods — folds into cycle-1 I3), F-UAV-2 (JsonDocument.Parse on signature-validated claims — bounded by Kestrel header cap), D3 (JwtBearer shares D1 patch line). * 1 Informational: F-UAV-3 (reject reasons disclose gate structure — accepted UX trade-off; documented in contract). OWASP refresh: A01 / A07 move from N/A (with caveat) to PASS_WITH_WARNINGS (per-tenant authz absent; iss/aud + revocation gaps tracked). Pre-deploy operational gate added: deploy pipeline must verify JWT_SECRET != DEV-ONLY placeholder before promoting api. Artifacts: dependency_scan.md, static_analysis.md, owasp_review.md, infrastructure_review.md, security_report.md — all appended with a "Cycle 2 Delta" section preserving cycle-1 finding IDs. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
e3cd388577 |
[AZ-487] [AZ-488] docs: cycle 2 doc sync (task mode)
Step 13 (Update Docs) for cycle 2. Most cross-cutting docs were already updated during Step 10 (architecture.md, glossary.md, components/03_tile_downloader, modules/api_program.md, data_model.md, contracts/api/uav-tile-upload.md). This commit completes the remaining module-level + module-layout updates and writes the cycle-2 ripple log. * modules/common_configs.md: + UavQualityConfig section and appsettings-section row (UavQuality). * modules/common_dtos.md: + UavTileMetadata, UavTileBatchMetadataPayload, UavTileBatchUploadResponse, UavTileUploadResultItem, UavTileUploadStatus, UavTileRejectReasons (closed enumeration v1.0.0). * module-layout.md: refresh Common (+ UavQualityConfig + UAV DTOs), TileDownloader (+ UavTileQualityGate, UavTileUploadHandler, + SixLabors.ImageSharp 3.1.11 PackageReference), and WebApi (+ Authentication/*, DTOs/UavTileBatchUploadRequest, + JwtBearer 8.0.21 PackageReference). Updates the "Last Updated" stamp to cycle 2. * modules/tests_unit.md: replace the obsolete "only a dummy test" description; add cycle-2 AZ-487 / AZ-488 test classes (AuthenticationServiceCollectionExtensionsTests, JwtTokenFactoryTests, UavTileQualityGateTests, UavTileUploadHandlerTests, UavTileFilePathTests, PermissionsRequirementTests) + new ProjectReference / package references. * modules/tests_integration.md: + JwtIntegrationTests, UavUploadTests (incl. wall-clock-seeded coordinate counter rationale from the Step 11 fix), and the StubAndErrorContractTests update for the removed 501 stub. * ripple_log_cycle2.md (new): cycle-2 reverse-dependency scan results showing every importer of the new symbols resolves inside the three already-updated components (WebApi, TileDownloader, Common). No unexpected ripple, no heuristic fallback needed. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
98cdcd17c1 |
[AZ-487] [AZ-488] docs: cycle 2 test-spec sync
Append cycle 2 entries to test-spec artifacts (cycle-update mode): * security-tests.md: SEC-05..SEC-09 (AZ-487 JWT 401/403/parity) + SEC-10..SEC-11 (AZ-488 permission + reject-detail leak hygiene). * blackbox-tests.md: BT-13..BT-17 (UAV happy / mixed / multi-source coexistence / same-source UPSERT / rule-ordering) + BT-18 (existing endpoints parity with Bearer token). * resource-limit-tests.md: RL-05..RL-07 (MaxBatchSize, per-item MaxBytes, Kestrel/Form envelope cap). * performance-tests.md: untouched (PT-08 already landed with AZ-488 as Deferred — see _docs/_process_leftovers/2026-05-11_perf-pt07-harness). * traceability-matrix.md: append AC rows for AZ-487 AC-1..AC-8 and AZ-488 AC-1..AC-10 + AC-7a..AC-7e; annotate "No authentication" restriction as superseded by AZ-487+AZ-488; add NFR rows (perf, security, reliability, compatibility) for both tasks; refresh totals (78 tests; 47/47 ACs; 8/8 restrictions). Coverage shape: AZ-487 AC-7 (Swagger Authorize) and the perf NFRs are recorded but not actively measured this commit (manual UI smoke + deferred PT-08 harness, respectively). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
dc3dabe7bd |
[AZ-488] fix: seed UavUploadTests coordinate counter from wall-clock
Postgres data volume persists across docker-compose runs. The previous `int _coordinateCounter = 0` reset on every test-runner process start so the SECOND `--full` run collided with rows seeded by the first `--smoke` run (the AC-3 MultiSourceCoexistence test does a raw INSERT for the pre-seed step, not an UPSERT, and the unique constraint fires). Seed the counter from a wall-clock value (~Unix epoch seconds mod 1M) so each runner process picks a distinct coordinate band. Eliminates inter-run collisions without coupling the test to docker volume reset. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
1802d32107 |
[AZ-488] UAV tile batch upload + 5-rule quality gate
Replaces the 501 stub at POST /api/satellite/upload with a multipart
batch endpoint that ingests UAV-captured tiles, runs each item through
a 5-rule quality gate, and persists accepted tiles via the AZ-484
multi-source storage path with source='uav'.
Quality gate (in fixed order, first failure wins): JPEG format
(content-type + magic), size band 5 KiB-5 MiB, exact 256x256
dimensions, captured-at age (no future >30 s skew, no older than
7 days), luminance variance on 32x32 downsample. Closed reject-reason
enumeration in v1.0.0 contract.
Authorization: custom PermissionsRequirement / PermissionsAuthorization
Handler that reads the JWT `permissions` claim (tolerates both
repeated-string and JSON-array shapes). Endpoint protected by
RequiresGpsPermission policy; 401 without token, 403 without GPS perm.
Persistence: file-first to ./tiles/uav/{z}/{x}/{y}.jpg, then
ITileRepository.InsertAsync UPSERT (per-source UPSERT contract from
AZ-484). Per-item failures reported in response without aborting the
batch. Kestrel MaxRequestBodySize and FormOptions limits set to
MaxBatchSize x MaxBytes (default 100 x 5 MiB = 500 MiB).
New frozen contract: _docs/02_document/contracts/api/uav-tile-upload.md
v1.0.0. PT-08 NFR added to performance-tests.md as Deferred (harness
work tracked in PT-07 leftover, per AZ-488 § Risk 4).
Tests: 11 quality-gate unit tests, 5 handler unit tests, 3 file-path
unit tests, 12 permission-handler unit tests, 7 integration tests
(AC-1..AC-6, AC-8). All 253 unit tests + smoke integration suite
green.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
11b7074485 |
[AZ-487] fix: integration-test JWT factory handles negative lifetime
Same fix as
|
||
|
|
f64d0d760a |
[AZ-487] fix: JWT factory + tests now pass on net8.0
- JwtTokenFactory.Create: negative `lifetime` produced Expires < NotBefore
which `JwtSecurityToken` rejects at construction time. Shift NotBefore
behind Expires whenever the requested lifetime is non-positive so the
expired-token fixture round-trips and lifetime validation can fire.
- JwtTokenFactoryTests: validate against a handler with
`MapInboundClaims = false` so assertions read the factory's own claim
names ("sub", "email", "permissions") rather than the .NET-default
remapped ClaimTypes.* aliases.
These were latent — masked by the CS0104 build break fixed in
|
||
|
|
753be43d11 |
[AZ-487] fix: resolve CS0104 ambiguity in AuthN tests
`AuthenticationServiceCollectionExtensions` is also a built-in .NET type under `Microsoft.Extensions.DependencyInjection`. With both namespaces imported the unqualified references in this test file failed with CS0104, breaking the entire test project build. Resolved via a `using` alias so the call sites stay short while the build stays unambiguous. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
96cd3c4495 |
[AZ-487] JWT validation baseline (HS256, all endpoints)
Adds Microsoft.AspNetCore.Authentication.JwtBearer 8.0.21 and the SatelliteProvider.Api.Authentication.AddSatelliteJwt extension that validates HS256 tokens against a shared JWT_SECRET (>=32 bytes, fail fast at startup). Every minimal-API endpoint now carries .RequireAuthorization(); the middleware chain is UseExceptionHandler -> UseHttpsRedirection -> UseCors -> UseAuthentication -> UseAuthorization -> endpoints. Swagger UI gets a Bearer security definition so the Authorize button works. Test infrastructure: JwtTokenFactory (unit) and JwtTestHelpers (integration) mint deterministic tokens against the same secret; the integration test runner attaches a default Bearer token to its shared HttpClient so existing tests continue to exercise protected endpoints. JwtIntegrationTests adds AC-1..AC-4 and AC-7 (Swagger advertises Bearer) end-to-end; AuthenticationServiceCollectionExtensionsTests covers AC-5 (missing/empty/short secret fail-fast) plus env-var precedence; JwtTokenFactoryTests covers AC-6 (claims pass through the JwtSecurityTokenHandler.ValidateToken path JwtBearer uses). docker-compose and scripts/run-tests.sh now propagate JWT_SECRET to the api and integration-tests containers, with a >=32-byte guard. .env.example documents the required keys; .env stays gitignored. Code review verdict: PASS_WITH_WARNINGS (2 Low findings surfaced in _docs/03_implementation/reviews/batch_01_cycle2_review.md). Cross-component coordination: gps-denied-onboard and the mission planner UI must attach Bearer tokens before this lands in dev. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
8e15e53782 |
chore: cycle 2 step 9 task plan artifacts + step 10 state
Carries forward new-task research + solution drafts under
_docs/02_task_plans/uav-batch-upload/ that were not included in
the Step 9 task-spec commit (
|