Commit Graph

8 Commits

Author SHA1 Message Date
Oleksandr Bezdieniezhnykh 9cfd80babe [AZ-495] [AZ-496] Cycle 3 batch 1: doc convention + AspNetCore 8.0.25
ci/woodpecker/push/01-test Pipeline was successful
ci/woodpecker/push/02-build-push Pipeline was successful
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>
2026-05-12 01:24:48 +03:00
Oleksandr Bezdieniezhnykh e3cd388577 [AZ-487] [AZ-488] docs: cycle 2 doc sync (task mode)
ci/woodpecker/push/01-test Pipeline was successful
ci/woodpecker/push/02-build-push Pipeline was successful
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>
2026-05-12 00:04:05 +03:00
Oleksandr Bezdieniezhnykh 51b572108a [AZ-484] Cycle 1 Steps 12-16: docs, security, perf, deploy report
ci/woodpecker/push/01-test Pipeline was successful
ci/woodpecker/push/02-build-push Pipeline was successful
Captures the post-implementation autodev gates for AZ-484 multi-source
tile storage:

- Step 12 (Test-Spec Sync): added 7 AC rows (AZ-484 AC-1..AC-7) and a
  PT-07 NFR row to traceability-matrix.md; added PT-07 scenario to
  performance-tests.md.
- Step 13 (Update Docs): refreshed data_model.md (tiles columns +
  indexes + selection rule + UPSERT contract + migrations 012/013),
  module-layout.md (Common/Enums section with L-001 guidance,
  DataAccess imports-from now lists 6 sites), 6 module / component
  docs to reflect the new repo signatures, source/captured_at fields,
  and Dapper enum bypass workaround. ripple_log_cycle1.md records
  zero out-of-scope ripple.
- Step 14 (Security Audit): PASS_WITH_WARNINGS - 0 Critical, 0 High,
  5 Medium, 5 Low. AZ-484 itself added zero new findings. Hardening
  items (Postgres default creds, .env in build context, GMaps key
  rotation, ASP.NET Core 8.0.21 -> 8.0.25, rate limiter) recorded
  for separate tickets.
- Step 15 (Performance Test): all PT-01..PT-07 scenarios Unverified
  (non-blocking); PT-07 baseline-comparison harness deferred to a
  leftover for next cycle.
- Step 16 (Deploy): cycle deploy report covering migration safety,
  rollback path, post-deploy verification, security caveats.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 10:03:05 +03:00
Oleksandr Bezdieniezhnykh e9d6db077c [AZ-484] Fix multi-source tile reads: drop Dapper enum handler
Two integration-test failures uncovered after the initial commit:

1) GetTilesByRegionAsync outer ORDER BY referenced 'updated_at' but
   the inner DISTINCT ON subquery aliased it to 'UpdatedAt' (Postgres
   folds to 'updatedat'). DISTINCT ON already guarantees one row per
   (latitude, longitude, ...) so the third tiebreak was unreachable;
   removed it.

2) Dapper 2.1.35 silently bypasses SqlMapper.TypeHandler<T> for enum
   types during read deserialization (Dapper issue #259). The
   TileSourceTypeHandler worked for writes but reads fell through to
   Enum.TryParse, which cannot map 'google_maps' to GoogleMaps.

   Pivoted: TileEntity.Source is now a string (the wire value).
   TileSource enum stays as the public producer surface in
   Common.Enums; TileSourceConverter (Common.Enums) provides
   ToWireValue / FromWireValue / IsValidWireValue at the boundary.
   TileSourceTypeHandler deleted; registration removed from
   DapperEnumTypeHandlers.RegisterAll.

   tile-storage.md Inv-5 amended to document the storage choice.
   _docs/LESSONS.md L-001 records the Dapper bypass for future cycles.

Full suite passes (213 unit + integration suite incl. AZ-484
AC-1..AC-5, security SEC-01..SEC-04, AZ-356/362/357).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 06:44:34 +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 08451df027 [AZ-350] Close 03-code-quality-refactoring: Phase 6+7 + FINAL_report
ci/woodpecker/push/01-test Pipeline was successful
ci/woodpecker/push/02-build-push Pipeline was successful
Phase 6 (Verification): smoke run green (format gate + 200/200
unit + integration smoke). verification_report.md captures
metric deltas vs Phase 0 baseline; all 5 ACs met, all 4
constraints honored, 0 regressions.

Phase 7 (Documentation):
- module-layout.md: corrected DataAccess->Common dependency
  (was mistakenly documented as "Imports from: (none)" by
  prior AZ-315 baseline; csproj reference + 7 import sites
  have actually been there since AZ-309).
- architecture_compliance_baseline.md: F5 entry revised to
  reflect the actual layering invariant (one-way: Common
  MUST NOT import from DataAccess, but DataAccess MAY
  import from Common).
- 00_discovery.md: added "Updates Since Baseline" section
  enumerating the AZ-309 split + AZ-350 27-change run +
  AZ-372 tooling additions; original tree kept as a
  2026-05-10 snapshot.

FINAL_report: complete run summary (10 batches, 27 tasks,
3 K=3 cumulative reviews, baseline->final metric table,
remaining items, lessons learned).

Autodev state: advance Step 8 -> Step 9 (New Task);
sub_step reset to phase 0 awaiting-invocation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 05:23:35 +03:00
Oleksandr Bezdieniezhnykh 6b373082c8 [AZ-315] Sync architecture docs after coupling refactor
Phase C of architecture coupling refactor (epic AZ-309). Closes the
last baseline finding (F5 — DataAccess incorrectly documented as
importing Common) and synchronizes the rest of _docs/02_document/
with the post-split project layout from AZ-312/313/314:

- module-layout.md: per-component sections for the three new csprojs
  with explicit ProjectReferences and the no-cross-sibling-reference
  invariant the split enforces.
- architecture.md: components and internal-communication tables
  updated to show calls flow through Common interfaces.
- architecture_compliance_baseline.md: F1..F5 marked Resolved with
  task IDs and commit refs; baseline summary now 0 findings.
- diagrams/components.md, components/03_tile_downloader/description.md,
  modules/{common_interfaces,services_tile_service,
  services_google_maps_downloader,tests_unit}.md updated for the
  split, RateLimitException relocation, and new ITileService methods.

Documentation-only batch — no code, no tests, no build changes.
Epic AZ-309 complete (6 tasks across 3 batches).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 07:25:21 +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