mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-22 10:41:15 +00:00
[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>
This commit is contained in:
@@ -207,3 +207,40 @@ All Cycle-5 UAV scenarios reuse the AZ-488 envelope. The new observable surface
|
||||
**Pass criterion**: All column / index assertions pass AND the deterministic backfill matches the reference function on 100% of sampled rows.
|
||||
**AC trace**: AZ-503 AC-8.
|
||||
|
||||
## BT-23: Inventory Endpoint — Order Preserved Across Present/Absent Mix
|
||||
|
||||
**Trigger**: `POST /api/satellite/tiles/inventory` with a body of 25 interleaved `(z, x, y)` coords at zoom 18, where 12 of the 25 are seeded into `tiles` (mix of `google_maps` and per-flight `uav` rows) and 13 are absent. Valid JWT attached.
|
||||
**Precondition**: Migration 015 applied (`tiles_leaflet_path` index exists); rows seeded via `TileRepository.AddAsync` so `location_hash` is populated.
|
||||
**Expected**: HTTP 200; response body is a `TileInventoryResponse` with `results.length == 25`; entries appear in the **same order** as the request body; 12 entries have `present=true` with `id` / `locationHash` / `capturedAt` / `source` populated; 13 entries have `present=false` with only `locationHash` populated (UUIDv5 of `"{z}/{x}/{y}"`), `id` is `null`, and `capturedAt` / `source` / `flightId` / `resolutionMPerPx` are all `null`.
|
||||
**Pass criterion**: All ordering, presence, and field-shape invariants from `tile-inventory.md` v1.0.0 Inv-1..Inv-6 hold for every entry.
|
||||
**AC trace**: AZ-505 AC-1 (resolves AZ-503 AC-5 deferral).
|
||||
|
||||
## BT-24: Leaflet Read Path — Most-Recent Selection Keyed on location_hash
|
||||
|
||||
**Trigger**: `GET /tiles/{z}/{x}/{y}` against a cell that has two seeded rows for the same `(z, x, y)`: a `google_maps` row with `captured_at = T - 2h` and a `uav` row with `captured_at = T - 30min` (strictly newer) and a distinct `flight_id`.
|
||||
**Precondition**: Migration 015 applied; both rows persisted with their `location_hash` populated via `Uuidv5.LocationHashForTile`.
|
||||
**Expected**: The DB-level SELECT that `TileRepository.GetByTileCoordinatesAsync` runs (`SELECT … FROM tiles WHERE location_hash = $1 ORDER BY captured_at DESC, updated_at DESC, id DESC LIMIT 1`) returns exactly **one** row — the UAV row.
|
||||
**Pass criterion**: `picked.id == uavId` (the newer row wins); selection semantics are byte-identical to AZ-484 / AZ-503-foundation, only the access key changed from the `(tile_zoom, tile_x, tile_y, tile_size_meters)` 4-tuple to `location_hash`.
|
||||
**AC trace**: AZ-505 AC-2 (resolves AZ-503 AC-6 deferral).
|
||||
|
||||
## BT-25: HTTP/2 Multiplexed Tile Reads on a Single TLS Connection
|
||||
|
||||
**Trigger**: A single `HttpClient` configured with `SocketsHttpHandler { EnableMultipleHttp2Connections = false }` + `HttpVersion.Version20` + `HttpVersionPolicy.RequestVersionExact` issues 20 concurrent `GET /tiles/{z}/{x}/{y}` requests for the same well-known tile.
|
||||
**Precondition**: Kestrel configured with `HttpProtocols.Http1AndHttp2`; dev listener bound to `https://+:8080` with a self-signed cert (`./certs/api.pfx`, generated by `scripts/run-tests.sh`); the integration-test container trusts the cert via `/usr/local/share/ca-certificates/` + `update-ca-certificates`. ALPN advertises `h2` and `http/1.1`.
|
||||
**Expected**: All 20 responses succeed with HTTP 200; each `HttpResponseMessage.Version` equals `2.0`; per-tile `ETag` and `Cache-Control` headers are preserved unchanged from the HTTP/1.1 baseline; all 20 streams share a single TLS connection (enforced by `EnableMultipleHttp2Connections = false`).
|
||||
**Pass criterion**: 20/20 responses are `Status=200`, `Version=2.0`, with non-null `ETag` and non-null `Cache-Control`.
|
||||
**Note (post-merge correction)**: Original AZ-505 wording was "dev plaintext endpoint" / h2c; switched to TLS+ALPN during the cycle-6 Run-Tests step because Kestrel silently downgrades `Http1AndHttp2` to HTTP/1.1 over plaintext (ALPN cannot run unencrypted). See `_docs/03_implementation/implementation_report_tile_inventory_cycle6.md` → "Post-merge correction".
|
||||
**AC trace**: AZ-505 AC-5 (resolves AZ-503 AC-12 deferral).
|
||||
|
||||
## BT-26: Inventory Endpoint — Request Validation
|
||||
|
||||
**Trigger**: Four `POST /api/satellite/tiles/inventory` calls, each exercising one validation rule.
|
||||
**Precondition**: API up; valid JWT attached except for the anonymous case.
|
||||
**Expected**:
|
||||
- Both `tiles` and `locationHashes` populated → HTTP 400 with a descriptive `detail` per `tile-inventory.md` Inv-1.
|
||||
- Neither `tiles` nor `locationHashes` populated → HTTP 400.
|
||||
- `tiles.length > 5000` or `locationHashes.length > 5000` → HTTP 400 (the 5000 cap matches `TileInventoryLimits.MaxEntriesPerRequest`, Inv-7).
|
||||
- No `Authorization: Bearer …` header → HTTP 401 before the handler runs (matches the `.RequireAuthorization()` baseline; same shape as SEC-05).
|
||||
**Pass criterion**: All four expected status codes returned; no response leaks server internals.
|
||||
**AC trace**: AZ-505 AC-6.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user