mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-21 13:01:14 +00:00
62d6b8310a22986dd21766538edbe68182dd17d0
19 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
32bc5c1e48 |
[AZ-808] [AZ-809] [AZ-810] [AZ-811] [AZ-812] Cycle 8 perf run
8/8 scenarios PASS within threshold. Cycle-8 strict-validation overhead is below percentile resolution on every measured endpoint. PT-06 (route creation) required one in-cycle perf-script fix: add requestMaps=false + createTilesZip=false to the body to satisfy AZ-809's no-defaulting rule. The script had already been updated for AZ-812's wire rename during cycle 8 but missed AZ-809's newly required fields. Production code is correct; only the perf probe was stale. Report: _docs/06_metrics/perf_2026-05-23_cycle8.md. Trend vs cycle 7 is flat within noise band on every scenario. Known harness quirks (pre-existing, not cycle-8 regressions) surfaced and documented for cleanup: - PT-07 cross-run cache pollution (hard-coded base coords) - PT-01 "cold" misnomer (tile cached on disk since cycle 5) - PT-03 cached-by-PT-02 side effect (cycle-7 note carried forward) Auto-chains to Step 16 (Deploy). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
490902c80a |
[AZ-810] Strict validation for POST /api/satellite/upload metadata
Adds the per-endpoint child of AZ-795 ("Strict Input Validation Epic")
for the UAV upload multipart endpoint. Three new validators land under
SatelliteProvider.Api/Validators/:
- UavTileBatchMetadataPayloadValidator: items NotNull + NotEmpty +
count <= MaxBatchSize + RuleForEach dispatching to the per-item
validator.
- UavTileMetadataValidator: lat / lon / tileZoom range, tileSizeMeters
> 0, capturedAt within [now - MaxAgeDays, now + future-skew]; uses an
injectable TimeProvider so unit tests can drive a fixed clock.
- UavUploadValidationFilter: IEndpointFilter that reads the multipart
`metadata` form field, deserializes it with the strict global
JsonSerializerOptions (so UnmappedMemberHandling.Disallow +
[JsonRequired] from AZ-795 are honored), runs the FluentValidation
chain, and enforces the cross-field `items.Count == files.Count`
envelope rule. FluentValidation errors are prefixed with `metadata.`
so wire keys look like `errors["metadata.items[0].latitude"]`.
[JsonRequired] is added to every non-optional axis on
UavTileMetadata and UavTileBatchMetadataPayload; FlightId stays
nullable per AZ-503 anonymous-flight semantics.
Coverage: 13 unit tests + 16 integration tests + 1 curl probe script
exercise the happy path and every failure mode. All 9 ACs covered;
no regression in AZ-488 UavUploadTests payloads (traced against the
new rules).
Documentation: uav-tile-upload.md bumped v1.1.0 -> v1.2.0 with the
new validation rules section + 400-shape examples + changelog entry.
api_program.md updated to describe the three new validators + filter
+ the AddTransient<UavUploadValidationFilter>() DI registration.
Reports: batch_04_cycle8_report.md + reviews/batch_04_cycle8_review.md
record the PASS_WITH_WARNINGS verdict (2 Low DRY-in-tests findings:
FixedTimeProvider duplication crossed the cycle-2 "promote to shared"
threshold; PostBatch helper duplicated between two integration
suites). Both deferred to follow-up PBIs.
Task spec archived: _docs/02_tasks/todo/AZ-810... -> done/.
Jira: AZ-810 transitioned In Progress -> In Testing.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
5e056b2334 |
[AZ-809] Strict validation for POST /api/satellite/route
Third concrete child of AZ-795 (cycle 8 batch 3). FluentValidation +
[JsonRequired] + UnmappedMemberHandling.Disallow combine to reject every
malformed payload at the API boundary with RFC 7807 ValidationProblemDetails.
Validators (SatelliteProvider.Api/Validators/, all new)
- CreateRouteRequestValidator: id non-empty, name/description length,
regionSizeMeters/zoomLevel ranges, points count [2, 500], cross-field
createTilesZip => requestMaps. Chains RoutePointValidator (per-point)
and GeofencePolygonValidator (per-polygon, guarded by When(Geofences != null)).
OverridePropertyName("geofences.polygons") on the geofences chain so
FluentValidation's default leaf-only key policy doesn't drop the parent
path on deep expressions like req.Geofences!.Polygons.
- RoutePointValidator: lat/lon ranges; OverridePropertyName("lat"/"lon")
chained AFTER InclusiveBetween (the extension is defined on
IRuleBuilderOptions<T, TProperty>, so the generic type is only
inferable after the first concrete rule) so error keys match the
wire format (`points[i].lat`) rather than the C# property name
(`points[i].latitude`).
- GeofencePolygonValidator: per-corner range checks via private nested
GeoCornerValidator; cross-field NW.Lat > SE.Lat and NW.Lon < SE.Lon
invariants emit at errors["geofences.polygons[i].northWest"].
DTOs (SatelliteProvider.Common/DTO/, [JsonRequired] additions only)
- CreateRouteRequest: id, name, regionSizeMeters, zoomLevel, points,
requestMaps, createTilesZip
- RoutePoint: Latitude, Longitude
- GeofencePolygon: NorthWest, SouthEast; Geofences: Polygons
- GeoPoint: Lat, Lon
Tests
- Unit: 26 methods total — 16 in CreateRouteRequestValidatorTests, 6 in
GeofencePolygonValidatorTests, 4 in RoutePointValidatorTests. Each
RuleFor/RuleForEach chain has at least one positive + one negative case.
- Integration: CreateRouteValidationTests.cs — 16 methods (happy + 15
failure modes) wired into smoke + full suites. Covers empty body,
missing/zero id, empty name, out-of-range regionSizeMeters/zoomLevel,
points count < 2, per-point lat/lon out-of-range, geofence invariants,
missing requestMaps, cross-field createTilesZip, unknown root field,
nested type mismatch.
- Manual probe: scripts/probe_route_validation.sh curl-exercises every
failure mode end-to-end + happy path.
Docs
- New contract _docs/02_document/contracts/api/route-creation.md v1.0.0
with nested DTO chain, invariants, per-field test cases table, and
advisories on the legacy service-layer RouteValidator + the
input/output RoutePoint vs RoutePointDto naming asymmetry.
- system-flows.md F4 sequence diagram extended with the validation-filter
branch; preconditions + error scenarios reference the new contract.
- modules/api_program.md: CreateRoute handler section added; Api/Validators
bumped to AZ-808/AZ-809/AZ-811.
- modules/common_dtos.md: DTO descriptions updated with [JsonRequired]
annotations and constraint summaries.
- tests/blackbox-tests.md BT-06/BT-N03/BT-N04/BT-N05 align with the new
wire format and named error keys.
- tests/security-tests.md SEC-04 references GlobalExceptionHandler's
JsonException branch + AZ-353 correlationId.
- _docs/03_implementation/batch_03_cycle8_report.md + reviews/batch_03_cycle8_review.md
(PASS_WITH_NOTES — F1 Low: OverridePropertyName documented inline,
F2 + F3 Info: pre-existing advisories for follow-up).
Smoke green (mode=smoke, exit 0). AZ-809 transitioned to In Testing on Jira.
Task file moved to _docs/02_tasks/done/.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
34ee1e0b83 |
[AZ-808] [AZ-811] Strict validation on region POST + lat/lon GET
AZ-808: FluentValidation for POST /api/satellite/request - RegionRequestValidator: id non-empty, lat/lon/sizeMeters/zoomLevel ranges - RequestRegionRequest: [JsonRequired] on every property, no implicit defaults - Wired via .WithValidation<RequestRegionRequest>() in MapPost chain - Unit + integration tests + curl probe script - New contract: contracts/api/region-request.md v1.0.0 AZ-811: FluentValidation + envelope filter for GET /api/satellite/tiles/latlon - GetTileByLatLonQuery: nullable record (double?/int?) so the minimal-API binder never short-circuits with BadHttpRequestException before filters - GetTileByLatLonQueryValidator: Cascade(Stop) + NotNull + InclusiveBetween per param; missing surfaces as `\`<name>\` is required.` - RejectUnknownQueryParamsEndpointFilter: reusable IEndpointFilter that rejects any query key outside the allowed set with errors[<key>] map; catches legacy `?Latitude=` typos and hostile probes (`?debug=1&admin=1`) - Handler: [AsParameters] GetTileByLatLonQuery + .Value deref post-validator - Unit (validator + filter) + integration tests + curl probe script - New contract: contracts/api/tile-latlon.md v1.0.0 Shared hygiene - Promote AssertErrorsContainsMention from per-test-file private helpers to ProblemDetailsAssertions (closes batch-1 Low-severity DRY warning) - Sync Swagger param descriptions, README, blackbox/security/perf scripts, uuidv5 doc with the new lat/lon/zoom query-param names Docs - system-flows.md F1/F2 reference the new contracts + validation layers - modules/api_program.md adds Api/Validators + Api/DTOs sections - _autodev_state.md: batch 2 of 4 complete; next batch = AZ-809 All smoke tests green (mode=smoke, exit 0). AZ-808 + AZ-811 transitioned to In Testing on Jira. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
fcd494f67e |
[AZ-812] Region API: rename Latitude/Longitude → Lat/Lon (OSM convention)
Mirror of AZ-794 (inventory z/x/y rename). RequestRegionRequest.cs renames C#
props Latitude→Lat / Longitude→Lon and adds [JsonPropertyName("lat"/"lon")] so
the wire format is unambiguous under the AZ-795 strict-parsing stack
(UnmappedMemberHandling.Disallow → legacy {"latitude":..,"longitude":..} now
returns HTTP 400 instead of silently coercing).
Updates all in-repo consumers: API handler (Program.cs), integration tests
(Models.cs, RegionTests.cs, IdempotentPostTests.cs, SecurityTests.cs), the
performance harness (run-performance-tests.sh PT-03/04/05/07), and module
docs (common_dtos.md, api_program.md; system-flows.md F2 already used
lat/lon). New RegionFieldRenameTests.cs covers AC-4 both directions (new
format → 200, legacy format → 400). Smoke green; no regressions.
region-request.md contract doc not bumped here — AZ-808 publishes v1.0.0
directly with the post-rename names per AZ-812 coordination clause.
Batch 01 of cycle 8. PASS_WITH_WARNINGS (one Low DRY finding for follow-up
test-helper consolidation; details in
_docs/03_implementation/reviews/batch_01_cycle8_review.md).
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
9a53bff92e |
[AZ-375] [AZ-377] HashSet tile lookup + consolidate Earth constants
Batch 24 of 03-code-quality-refactoring run; closes the run. AZ-375 (C22): GoogleMapsDownloaderV2.DownloadTilesGridAsync now builds a HashSet<(int X, int Y, int Z)> once from existingTiles and tests Contains((x, y, zoomLevel)) per cell. Removes the per-cell FirstOrDefault tolerance scan and the unused _processingConfig .LatLonTolerance reference at this site. AZ-377 (C24): promote Earth + tile-pixel constants to a single home. GeoUtils now exposes EarthRadiusMeters, EarthEquatorial CircumferenceMeters, MetersPerDegreeLatitude as public const. MapConfig adds DefaultTileSizePixels (const) wired as the TileSizePixels property default. TileRepository and Google MapsDownloaderV2 read those constants instead of duplicating the literals 6378137, 40075016.686, 111000.0, and 256. Tests: +6 new (DownloaderRefactorTests, extended GeoUtils RefactorTests). 200/200 unit tests pass. Cumulative K=3 review (batches 22-24): PASS_WITH_WARNINGS, 4 Low findings only — see _docs/03_implementation/reviews/cumulative_review_22-24.md. Tooling fix: scripts/run-tests.sh --unit-only path now restores before testing (was failing on SixLabors resolution in clean container). Stripped stray BOM from MapConfig.cs to satisfy the .editorconfig charset gate. Updates _dependencies_table.md to reflect all 27 03-code-quality- refactoring tasks done; updates _autodev_state.md to refactor phase 5 (test-sync). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
68359350fc |
[AZ-372] Add .editorconfig, Directory.Build.props, format/coverage wiring
Wires the C19 tooling baseline so dotnet format and Coverlet gate the test script and a small NetAnalyzers ruleset (CA1001, CA1051, CA1816, CA2227) at warning severity is visible from the next build. - .editorconfig (new, root=true): whitespace rules, per-extension indent sizes, C# style preferences as suggestions, initial CA rules. - Directory.Build.props (new): EnableNETAnalyzers=true, AnalysisLevel=latest, AnalysisMode=None so only rules explicitly enabled in .editorconfig fire; EnforceCodeStyleInBuild=false to keep build clean from style. - scripts/run-tests.sh: Step 0 runs dotnet format whitespace --verify-no-changes via Docker SDK; unit/integration test calls now collect XPlat Code Coverage into TestResults/. New --skip-format escape hatch. - .gitignore: TestResults/, coverage.cobertura.xml, *.coverage. - SatelliteProvider.Tests/ToolingConfigurationTests.cs (new, 6 tests): runtime assertions that the config files, script wiring, and coverlet.collector reference are all in place; mirrors the AcceptanceCriteriaRT2Tests pattern. Whitespace cleanup that the new format gate uncovers is staged for the next commit (per AZ-372 spec: "commit cleanup as a separate batch"). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
cc0a876168 |
[AZ-AUTODEV] Step 7 (Run Tests): smoke profile + green run
Add a fast integration profile so Step 7 (and future autodev re-entries) can verify the full stack in ~2 min instead of ~15 min, without losing access to the long-running coverage when needed. - TestRunMode.cs: smoke flag + tightened poll/timeout values. - Program.cs: env var INTEGRATION_TESTS_MODE / --smoke|--full CLI switch; smoke runs Tile + 200m region + simple route + ZIP route + Security; full keeps the existing sequence. - RegionTests / ExtendedRouteTests: read timeouts from TestRunMode instead of hardcoding 120/180/360. - docker-compose.tests.yml: forwards INTEGRATION_TESTS_MODE to the integration-tests container (default 'full'). - scripts/run-tests.sh: adds --unit-only / --smoke / --full flags, loads .env automatically, fails fast if GOOGLE_MAPS_API_KEY is missing. Step 7 result: all tests passed in 111.86 s wall-clock (35/35 unit + 5/5 smoke integration scenarios incl. SEC-01..04). Report saved to _docs/03_implementation/test_run_step7.md. State advanced to Step 8 (Refactor). Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
7822841587 |
[AZ-289] [AZ-290] Batch 3 tests: integration ZIP cap, perf, security, queue
AZ-289 — RL-01 50MB ZIP cap added to RunRouteWithTilesZipTest;
existing integration tests already cover BT-08/BT-09 + AC-1/AC-2.
AZ-290:
- scripts/run-performance-tests.sh extended with PT-01/03/04/05
- SatelliteProvider.IntegrationTests/SecurityTests.cs (SEC-01..SEC-04),
wired into Program.cs
- SatelliteProvider.Tests/RegionRequestQueueTests.cs covering RS-04 /
RL-02 queue capacity behavior
Notes:
- RS-04 spec wording ("rejects overflow") drifts from the channel's
BoundedChannelFullMode.Wait back-pressure semantics. Tests assert
the actual behavior; spec to be reconciled in Step 12 (Test-Spec
Sync). Tracked as Low/Spec-Gap in batch_03_review.md.
- Unit tests: 35/35 passed (Docker .NET 8 SDK).
- Integration test project builds clean (0 warnings, 0 errors).
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
b0fffa6d42 |
[AZ-284] Autodev baseline + testability refactor
Phase A baseline outputs from /autodev (Steps 1-5): - Problem & solution docs (_docs/00_problem, _docs/01_solution) - Codebase documentation (_docs/02_document) incl. architecture, module-layout, glossary, system-flows, baseline compliance scan - Test specs (blackbox, performance, resilience, security, resource, traceability matrix) - Test task decomposition (_docs/02_tasks/todo): AZ-285..AZ-290 - Testability refactor (_docs/04_refactoring/01-testability-refactoring): - TC-01 Move DownloadedTileInfoV2 + new ExistingTileInfo to Common.DTO - TC-02 Replace dead ISatelliteDownloader API with real signatures - TC-03 GoogleMapsDownloaderV2 implements ISatelliteDownloader - TC-04 TileService depends on ISatelliteDownloader (mockable) - TC-05 DI + endpoints use ISatelliteDownloader - Test runner scripts (scripts/run-tests.sh, run-performance-tests.sh) - Autodev state pointer (_docs/_autodev_state.md) Prepares the codebase for AZ-285..AZ-290 unit/integration test work. Co-authored-by: Cursor <cursoragent@cursor.com> |