mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-27 08:31:13 +00:00
chore: WIP pre-implement cycle 14 baseline
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -428,3 +428,22 @@ Cycle 8 extends the AZ-795 shared validation infrastructure (FluentValidation +
|
||||
**AC trace**: AZ-1113 AC-1..AC-3 (blackbox); AC-4 (`UavTileUploadHandler` envelope) verified by `UavTileUploadHandlerTests` unit only; AC-5 (contract doc) verified at Step 13.
|
||||
**Notes**: This is a cross-cutting tightening of Inv-5 for 4xx paths — BT-27..BT-31 strict-validation scenarios remain the binding functional specs; BT-33 adds the message-content contract on top. SEC-14..SEC-16 mirror these three sub-cases in the security category.
|
||||
|
||||
## Cycle 13 — AZ-1126 `capturedAt` DateTimeOffset (F-AZ810-2 closure)
|
||||
|
||||
Cycle 13 tightens UAV upload metadata time handling: `UavTileMetadata.CapturedAt` is `DateTimeOffset` with a strict JSON converter requiring an explicit UTC offset. Offset-less ISO-8601 strings fail at deserialization before FluentValidation. Contract `uav-tile-upload.md` patched 1.2.0 → 1.2.1.
|
||||
|
||||
## BT-34: UAV Upload `capturedAt` Requires Explicit UTC Offset
|
||||
|
||||
**Trigger**: `POST /api/satellite/upload` multipart calls exercising AZ-1126 AC-2 and AC-3 on the existing AZ-810 validation surface.
|
||||
**Precondition**: API up; valid JWT with `permissions:["GPS"]`. `uav-tile-upload.md` v1.2.1 frozen.
|
||||
**Expected**: Offset-less timestamps rejected at deserializer; offset-aware UTC clients unchanged.
|
||||
|
||||
| # | AC | Trigger excerpt | Expected | Test method |
|
||||
|---|-----|-----------------|----------|-------------|
|
||||
| 1 | AC-2 | Valid JPEG + metadata with `capturedAt: "2026-06-26T12:00:00"` (no `Z` / offset) | HTTP 400; `errors` mentions `capturedAt` | `UavUploadValidationTests.ItemCapturedAtOffsetLess_Returns400` |
|
||||
| 2 | AC-3 | Valid JPEG + metadata with `capturedAt` as ISO-8601 UTC (`...Z` or `...+00:00`) | HTTP 200 (happy path unchanged vs AZ-810 BT-30 `pos`) | `UavUploadValidationTests.HappyPath_Returns200` + existing AZ-488 suite |
|
||||
|
||||
**Pass criterion**: Sub-case 1 returns HTTP 400 with `capturedAt` in the error surface. Sub-case 2 remains green in the full integration suite (cycle 13 Step 11: 457 unit + all integration groups passed).
|
||||
**AC trace**: AZ-1126 AC-1 (type migration — unit: `UtcOffsetRequiredDateTimeOffsetConverterTests`, `UavTileMetadataValidatorTests`, `UavTileQualityGateTests`); AC-2, AC-3 (blackbox); AC-4 (contract doc — verified at Step 13).
|
||||
**Notes**: Closes security finding F-AZ810-2. Does not change inventory response `capturedAt` (`DateTime?` read path) or gRPC surfaces. BT-30 sub-cases 9a/9b (future/too-old freshness) remain valid for offset-aware timestamps only.
|
||||
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# Test Environment
|
||||
|
||||
## Platform
|
||||
|
||||
Three execution contexts — all use **native** Docker for the host CPU (no Rosetta / QEMU emulation).
|
||||
|
||||
| Context | Host CPU | Docker platform | How tests/builds run |
|
||||
|---------|----------|-----------------|----------------------|
|
||||
| **Local dev** | Apple Silicon Mac (`darwin/arm64`, e.g. M1) | `linux/arm64` | `scripts/run-tests.sh` sets `DOCKER_DEFAULT_PLATFORM=linux/arm64`; compose builds follow the host |
|
||||
| **CI unit tests** | Woodpecker `platform: arm64` agent (colocated Jetson) | `linux/arm64` | `.woodpecker/01-test.yml` — `dotnet test` in sdk image (arm64-only by suite convention) |
|
||||
| **CI image build** | Woodpecker `platform: arm64` **or** `amd64` agent | matches agent | `.woodpecker/02-build-push.yml` matrix — same Dockerfile, tags `{branch}-arm` / `{branch}-amd64` |
|
||||
|
||||
**Mac M1 rule**: do **not** pin `platform: linux/amd64` in compose files or Dockerfiles. That forces Rosetta/QEMU emulation and logs warnings such as `The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8)`.
|
||||
|
||||
**amd64 agent rule**: the remote Woodpecker amd64 agent builds production images natively. Deploy (`suite/_infra/deploy/satellite-provider/`) pulls `${BRANCH}-amd64` — built only on the amd64 agent, not cross-compiled from arm64.
|
||||
|
||||
| Surface | Behavior |
|
||||
|---------|----------|
|
||||
| `scripts/run-tests.sh` | On `darwin/arm64`, exports `DOCKER_DEFAULT_PLATFORM=linux/arm64` before every `docker run` / `docker compose` |
|
||||
| `docker-compose.tests.yml` | No `platform:` override — images match the host (arm64 on Mac, amd64 on an amd64 Linux dev box) |
|
||||
| `docker-compose.yml` (dev / perf) | Same — no arch pin |
|
||||
| API + integration Dockerfiles | Multi-arch `sdk:10.0` / `aspnet:10.0`; build stage installs Debian `protobuf-compiler` + `PROTOBUF_PROTOC=/usr/bin/protoc` on **arm64** (bundled `Grpc.Tools` `linux_arm64/protoc` segfaults; harmless on amd64) |
|
||||
|
||||
Suite CI/agent reference: [`suite/_infra/ci/README.md`](../../../../_infra/ci/README.md) § Agent pools and § Build-push step.
|
||||
|
||||
## Infrastructure
|
||||
|
||||
| Component | Technology | Configuration |
|
||||
|
||||
@@ -164,6 +164,10 @@
|
||||
| AZ-812 AC-4 | `curl` probe with `{"id":"<guid>","lat":49.94,"lon":36.31,"sizeMeters":200,"zoomLevel":18,"stitchTiles":false}` returns HTTP 200 + valid `regionId`; old `{"latitude":..,"longitude":..}` returns HTTP 400 with `UnmappedMemberHandling.Disallow` rejecting the unknown fields | BT-28 sub-case `pos` (new names accepted) + sub-case `9` (`OldLatLongNames_Returns400` — old `latitude`/`longitude` rejected as unknown). The strict-deserializer behavior is what AZ-795's `UnmappedMemberHandling.Disallow` makes possible; pre-cycle-8 the rename would have silently coerced old names to `Lat=0, Lon=0` | ✓ |
|
||||
| AZ-812 AC-5 | Docs updated: `common_dtos.md`, `api_program.md`, `system-flows.md` (F2) | Doc-state AC — all three files updated in cycle-8 batch; verified at Step 13 review | ◐ doc-verified at Step 13 |
|
||||
| AZ-812 AC-6 | Contract doc coordination: `region-request.md` v1.0.0 published directly with `lat`/`lon` (because AZ-808 + AZ-812 shipped in same cycle) — no `v1.0.0 → v2.0.0` bump needed | Doc-state AC — `region-request.md` v1.0.0 Change Log section names both AZ-808 (validation rules) and AZ-812 (`lat`/`lon` field names); verified at Step 13 review | ✓ |
|
||||
| AZ-1126 AC-1 | `UavTileMetadata.CapturedAt` is `DateTimeOffset`; freshness comparisons use UTC without manual `DateTimeKind` normalization | `UtcOffsetRequiredDateTimeOffsetConverterTests` (unit); `UavTileMetadataValidatorTests` + `UavTileQualityGateTests` + `UavTileUploadHandlerTests` (unit); existing AZ-810 BT-30 sub-cases 9a/9b remain green with offset-aware timestamps (cycle 13 Step 11 full run) | ✓ |
|
||||
| AZ-1126 AC-2 | Offset-less `capturedAt` (no explicit UTC offset) rejected with HTTP 400 referencing `capturedAt` | BT-34 sub-case 1 (blackbox); `UavUploadValidationTests.ItemCapturedAtOffsetLess_Returns400` (integration) | ✓ |
|
||||
| AZ-1126 AC-3 | Compliant clients sending `Z` or `+00:00` timestamps unchanged | BT-34 sub-case 2 (blackbox); `UavUploadValidationTests.HappyPath_Returns200` + full AZ-488 integration suite green (cycle 13 Step 11) | ✓ |
|
||||
| AZ-1126 AC-4 | `uav-tile-upload.md` v1.2.1 documents offset requirement and F-AZ810-2 closure | Doc-state AC — contract patch in cycle 13 batch; verified at Step 13 review | ✓ |
|
||||
|
||||
## Restrictions → Test Mapping
|
||||
|
||||
@@ -220,7 +224,8 @@
|
||||
| Cycle 10 — AZ-1113 REST 400 error message sanitization (integration + unit + blackbox + contract patch) | 3 integration assertion paths (inventory deserializer, latlon bind, UAV metadata) + 3 unit methods (`GlobalExceptionHandlerTests` ×2, `UavTileUploadHandlerTests` ×1) + 1 blackbox (BT-33 with 3 sub-cases) + 3 security (SEC-14..SEC-16) + `error-shape.md` v1.0.1 patch | 5/5 in-scope (AZ-1113 AC-1..AC-5) | — |
|
||||
| Cycle 11 — AZ-1123 perf compose documentation (deployment + test env docs) | doc-only (`containerization.md` compose overlays, `environment.md` perf cross-link) | 3/3 in-scope (AZ-1123 AC-1..AC-3); doc-verified at Step 13 | — |
|
||||
| Cycle 12 — AZ-1124 PT-10 gRPC stream perf (perf harness + unit) | 1 perf (PT-10) + 3 unit (`PerfBootstrapPt10Tests`) + integration bootstrap (`SatelliteProvider.IntegrationTests --run-pt10`) | 6/6 in-scope (AZ-1124 AC-1..AC-6); 1 AC gated at Step 15 (AC-3); 1 doc-verified at Step 13 (AC-5) | — |
|
||||
| **Total** | **173** | **130/130 in-scope (100%); 3 ACs gated at Step 15 (2 AZ-504 + 1 AZ-1124 AC-3); 11 prior-cycle ACs doc-verified at Step 13 (2 cycle-7 + 8 cycle-8 + 1 AZ-1124 AC-5 pending); 2 advisory non-tested (cycle-8 AZ-809 AC-9/AC-10)** | **8/8 (100%)** |
|
||||
| Cycle 13 — AZ-1126 capturedAt DateTimeOffset (integration + unit + blackbox + contract patch) | 1 integration method (`UavUploadValidationTests.ItemCapturedAtOffsetLess_Returns400`) + 4 unit files (`UtcOffsetRequiredDateTimeOffsetConverterTests`, updated UAV validator/gate/handler tests) + 1 blackbox (BT-34 with 2 sub-cases) + `uav-tile-upload.md` v1.2.1 patch | 4/4 in-scope (AZ-1126 AC-1..AC-4); 1 doc-verified at Step 13 (AC-4); closes F-AZ810-2 | — |
|
||||
| **Total** | **174** | **134/134 in-scope (100%); 3 ACs gated at Step 15 (2 AZ-504 + 1 AZ-1124 AC-3); 11 prior-cycle ACs doc-verified at Step 13 (2 cycle-7 + 8 cycle-8 + 1 AZ-1124 AC-5); 2 advisory non-tested (cycle-8 AZ-809 AC-9/AC-10)** | **8/8 (100%)** |
|
||||
|
||||
**Coverage shape notes (Cycle 5 — AZ-503 foundation):**
|
||||
- AZ-503 was split mid-cycle (Option C, autodev Step 10 batch 2): 7 of 12 original ACs land here; 5 (AC-5, AC-6, AC-9, AC-10, AC-12) are deferred to AZ-505 with a `Blocks` link in Jira and an entry in `_docs/02_tasks/_dependencies_table.md`. The deferred rows above are marked `◐ deferred → AZ-505` so the matrix surfaces the scope boundary explicitly.
|
||||
|
||||
Reference in New Issue
Block a user