Commit Graph

6 Commits

Author SHA1 Message Date
Oleksandr Bezdieniezhnykh 5d84d2839e [AZ-505] Test-spec sync + task-mode doc updates for cycle 6
ci/woodpecker/push/01-test Pipeline was successful
ci/woodpecker/push/02-build-push Pipeline was successful
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>
2026-05-12 22:29:22 +03:00
Oleksandr Bezdieniezhnykh 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>
2026-05-12 21:16:37 +03:00
Oleksandr Bezdieniezhnykh 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>
2026-05-12 18:01:27 +03:00
Oleksandr Bezdieniezhnykh 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>
2026-05-11 23:50:49 +03:00
Oleksandr Bezdieniezhnykh 687d6bdd5b [AZ-484] Multi-source tile storage: source + captured_at
Add per-source tile rows to support multi-provider imagery (Google
Maps + future UAV). Migration 013 (transactional) introduces
source/captured_at columns, backfills existing rows to
(source='google_maps', captured_at=created_at), and replaces the
4-column unique index with a 5-column index that includes source.

TileRepository:
- ColumnList includes source + captured_at
- GetByTileCoordinatesAsync returns most-recent row across sources
  (ORDER BY captured_at DESC, updated_at DESC, id DESC)
- GetTilesByRegionAsync uses DISTINCT ON to pick the most-recent
  tile per cell, restoring caller-facing row order
- Insert/Update upsert on the new 5-column conflict key

TileSource enum lives in Common.Enums. Snake_case wire format
(google_maps, uav) is enforced by a focused TileSourceTypeHandler
because the generic ToLowerInvariant pattern would emit
"googlemaps", violating contract v1.0.0.

TileService stamps Source=GoogleMaps + CapturedAt=UtcNow on every
new tile. Tile-storage contract is now frozen at v1.0.0.

AC coverage 7/7. New unit + integration tests cover all ACs;
existing 200 unit + 5 smoke tests preserved.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 06:21:59 +03:00
Oleksandr Bezdieniezhnykh 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>
2026-05-10 04:44:08 +03:00