Files
annotations/_docs/02_document/module-layout.md
T
Oleksandr Bezdieniezhnykh 03f879206e docs+src: complete Steps 1-3 outcomes + auth re-sync baseline
This commit captures everything produced during autodev existing-code
Steps 1 (Document), 2 (Architecture Baseline Scan), and 3 (Test Spec),
together with the targeted auth + CORS re-sync triggered on 2026-05-14
when codebase drift was detected at Step 4 entry. None of this work was
previously committed.

Step 1 (Document) — 50+ _docs/02_document/ files: problem, solution,
architecture, system flows, glossary, module-layout, per-component
specs (01..06), modules, deployment, diagrams, data model, FINAL
report, verification log, discovery.

Step 2 (Architecture Baseline) — architecture_compliance_baseline.md.
Verdict PASS_WITH_WARNINGS (0 Critical, 0 High, 1 Medium, 2 Low). No
High/Critical findings; auto-chained to Step 3 per existing-code flow.

Step 3 (Test Spec) — _docs/02_document/tests/* (67 scenarios across
blackbox, security, resilience, resource-limit, performance), plus
e2e/docker-compose.test.yml, e2e/seed/run.sh, scripts/run-tests.sh,
scripts/run-performance-tests.sh. Coverage 88% over the active scope
(40 of 45 items covered, 6 RB-deferred, 5 documented-as-uncovered).

Targeted auth + CORS re-sync — replaces the deleted in-house token
issuer with a JWKS-verifier model. AuthController and TokenService
removed; JwtExtensions switched from HS256 symmetric to ES256 over
admin's JWKS. ConfigurationResolver and CorsConfigurationValidator
added under src/Infrastructure/. ADR-002 and ADR-006 retired; SEC-01,
SEC-02, SEC-03 marked Closed. One new testability risk recorded in
architecture.md Open Risks Section 6 (JWKS HTTPS gating).

Source changes:
- src/Auth/JwtExtensions.cs (modified) — ES256, JWKS, alg pinning
- src/Program.cs (modified) — DI wiring for ConfigurationResolver
  and CorsConfigurationValidator
- src/Controllers/AuthController.cs (deleted) — no in-service issuance
- src/Services/TokenService.cs (deleted) — same
- src/Infrastructure/ConfigurationResolver.cs (new)
- src/Infrastructure/CorsConfigurationValidator.cs (new)
- .env.example (new) — required env var documentation
- .gitignore (updated)

Cross-repo coordination: _docs/cross-repo/flights_h1_h2_h3_change_spec
captures the change-spec for downstream services that consumed the now
deleted /auth endpoints.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 20:19:05 +03:00

179 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Module Layout
**Status**: derived-from-code
**Language**: csharp
**Layout Convention**: single-assembly (`Azaion.Annotations`), vertical slices expressed as **logical components** under flat `src/` folders (`Controllers/`, `Services/`, `DTOs/`).
**Root**: `src/`
**Last Updated**: 2026-05-14
## Verification Needed
1. **No per-component physical root** — all components share `src/Controllers/`, `src/Services/`, `src/DTOs/`. File ownership below is **exclusive for implementation planning**; merges touching the same file need explicit batch ordering.
2. **`AnnotationsController.cs` split (user-approved six-component model)** — **REST + static files** belong to **01 Annotations REST**; **SSE** (`Events`) belongs to **02 Annotations realtime & sync**. For `/implement`, treat **`src/Controllers/AnnotationsController.cs` as owned by 01**; tasks that **only** change SSE must still edit this file — flag as **cross-component** (01 + 02) or split into partial classes in a future refactor.
3. **`src/DTOs/`** — no subfolders; each file has a **primary owner** in [Shared: DTO files](#shared-dto-files-primary-ownership) to resolve FORBIDDEN vs OWNED during tasks.
4. **`FailsafeProducer.cs`** contains `RabbitMqConfig` and `FailsafeProducer` — fully owned by **02** (even though `Program.cs` registers the config as singleton).
---
## Layout Rules (adapted for this repo)
1. Components map to **logical** slices from `_docs/02_document/components/*/description.md`, not to separate top-level directories.
2. **Foundation** (`06_platform`) owns schema, enums, auth registration helpers, middleware, path resolution, and **composition** (`Program.cs`, csproj, Dockerfile).
3. **Feature** components own listed **service + controller** files; they **read** foundation public APIs and **shared DTO** types per the DTO table.
4. Tests are **not present** in-repo; future test project should follow `tests/Azaion.Annotations.Tests/` (conventional) — not owned by feature slices until created.
---
## Per-Component Mapping
### Component: `01_annotations-rest`
- **Epic**: (assign per change; layout is structural)
- **Directory (primary)**: `src/Services/` (partial), `src/Controllers/` (partial)
- **Public API** (types other components may reference through DI / same assembly):
- `Azaion.Annotations.Services.AnnotationService`
- `Azaion.Annotations.Controllers.AnnotationsController` (REST + image/thumbnail actions only — see Verification)
- **Internal**: private methods inside owned types; do not reach into other components services from new code without updating this layout.
- **Owns (exclusive write scope)**:
- `src/Services/AnnotationService.cs`
- `src/Controllers/AnnotationsController.cs`**primary file owner** (REST, `GetThumbnail`, `GetImage`; coordinate with 02 for `Events`)
- **Imports from**: `06_platform` (Database, Enums, DTOs used here, PathResolver, Middleware indirectly), `02_annotations-realtime-sync` (`AnnotationEventService` for publish)
- **Consumed by**: `04_dataset` (read paths share DB entities; no direct `AnnotationService` reference required), external callers
### Component: `02_annotations-realtime-sync`
- **Epic**: (assign per change)
- **Directory (primary)**: `src/Services/` (partial)
- **Public API**:
- `Azaion.Annotations.Services.AnnotationEventService`
- `Azaion.Annotations.Services.RabbitMqConfig`
- `Azaion.Annotations.Services.FailsafeProducer`
- `FailsafeProducer.EnqueueAsync` (static helper on same type as producer)
- **Owns**:
- `src/Services/FailsafeProducer.cs` (includes `RabbitMqConfig` + `FailsafeProducer`)
- `src/Services/AnnotationEventService.cs`
- **SSE contract**: `AnnotationsController.Events` (same `.cs` as 01 — see Verification)
- **Imports from**: `06_platform` (Database, Entities, PathResolver, Enums, `DTOs/QueueMessages.cs`), `DTOs/AnnotationEventDto.cs` (see Shared)
- **Consumed by**: `01_annotations-rest` (publishes events), external RabbitMQ consumers
### Component: `03_media`
- **Epic**: (assign per change)
- **Public API**: `MediaService`, `MediaController`
- **Owns**:
- `src/Services/MediaService.cs`
- `src/Controllers/MediaController.cs`
- **Imports from**: `06_platform`
- **Consumed by**: `01_annotations-rest` (domain: media rows referenced by annotations), UI
### Component: `04_dataset`
- **Epic**: (assign per change)
- **Public API**: `DatasetService`, `DatasetController`
- **Owns**:
- `src/Services/DatasetService.cs`
- `src/Controllers/DatasetController.cs`
- **Imports from**: `06_platform`
- **Consumed by**: Dataset Explorer UI
### Component: `05_settings-metadata`
- **Epic**: (assign per change)
- **Public API**: `SettingsService`, `SettingsController`, `ClassesController`
- **Owns**:
- `src/Services/SettingsService.cs`
- `src/Controllers/SettingsController.cs`
- `src/Controllers/ClassesController.cs`
- **Imports from**: `06_platform`
- **Consumed by**: UI; `PathResolver` / directory settings (via DB) interact with **06** cache reset when dirs change
### Component: `06_platform`
- **Epic**: (assign per change)
- **Public API** (representative; all `public` types in these areas are the integration surface):
- `Azaion.Annotations.Database.AppDataConnection`, `DatabaseMigrator`, `Azaion.Annotations.Database.Entities.*`
- `Azaion.Annotations.Enums.*`
- `Azaion.Annotations.Middleware.ErrorHandlingMiddleware`
- `Azaion.Annotations.Auth.JwtExtensions`
- `Azaion.Annotations.Infrastructure.ConfigurationResolver`, `CorsConfigurationValidator`
- `Azaion.Annotations.Services.PathResolver`
- `Program` (implicit entry), `src/Program.cs`
- **Owns**:
- `src/Enums/**`
- `src/Database/**`
- `src/Middleware/**`
- `src/Auth/**`
- `src/Infrastructure/**`
- `src/Services/PathResolver.cs`
- `src/GlobalUsings.cs`
- `src/Program.cs`
- `src/Azaion.Annotations.csproj`
- `src/Dockerfile`
- **Imports from**: (none — foundation)
- **Consumed by**: all other components
---
## Shared: DTO files (primary ownership)
| File under `src/DTOs/` | Primary component | Notes |
|------------------------|-------------------|--------|
| `PaginatedResponse.cs` | `06_platform` | Generic list wrapper — cross-cutting |
| `ErrorResponse.cs` | `06_platform` | Shared error shape |
| `CreateAnnotationRequest.cs` | `01_annotations-rest` | |
| `UpdateAnnotationRequest.cs` | `01_annotations-rest` | |
| `UpdateStatusRequest.cs` | `01_annotations-rest` / `04_dataset` | **Shared type****01** owns file edits; `04_dataset` uses for PATCH |
| `GetAnnotationsQuery.cs` | `01_annotations-rest` | |
| `AnnotationListItem.cs` | `01_annotations-rest` | |
| `DetectionDto.cs` | `01_annotations-rest` | |
| `AnnotationEventDto.cs` | `02_annotations-realtime-sync` | SSE payload |
| `QueueMessages.cs` | `02_annotations-realtime-sync` | MessagePack stream payloads |
| `CreateMediaRequest.cs` | `03_media` | |
| `GetMediaQuery.cs` | `03_media` | |
| `MediaListItem.cs` | `03_media` | |
| `GetDatasetQuery.cs` | `04_dataset` | |
| `DatasetItem.cs` | `04_dataset` | |
| `ClassDistributionItem.cs` | `04_dataset` | |
| `BulkStatusRequest.cs` | `04_dataset` | |
| `UpdateSystemSettingsRequest.cs` | `05_settings-metadata` | |
| `UpdateDirectoriesRequest.cs` | `05_settings-metadata` | |
| `UpdateCameraSettingsRequest.cs` | `05_settings-metadata` | |
| `UpdateUserSettingsRequest.cs` | `05_settings-metadata` | |
---
## Shared / Cross-Cutting (non-DTO)
### `common-helpers/01_http-error-envelope.md`
- **Purpose**: Documents middleware as cross-cutting (see `_docs/02_document/common-helpers/`).
- **Owned by**: tasks touching **06_platform** (`ErrorHandlingMiddleware`).
- **Consumed by**: all HTTP components.
---
## Allowed Dependencies (layering)
Higher layers may depend on lower; **not** the reverse. Same-layer components should not introduce compile-time cycles (current codebase: none detected).
| Layer | Components | May import from (namespaces / types from) |
|-------|------------|---------------------------------------------|
| 1 — Foundation | `06_platform` | *(none)* |
| 2 — Realtime infra | `02_annotations-realtime-sync` | `06_platform` |
| 3 — Application features | `01_annotations-rest`, `03_media`, `04_dataset`, `05_settings-metadata` | `06_platform`, and **`01` additionally `02`** (`AnnotationEventService`) |
**Rules**
- `03`, `04`, `05`**must not** reference `AnnotationService` / `MediaService` across features without an explicit API (today: only via shared `AppDataConnection` in same assembly — acceptable but treat as **tight coupling**; prefer domain services for new code).
- `02`**must not** reference `01` service types (no reverse dependency today).
Violations are **Architecture** findings for code-review Phase 7.
---
## Layout Conventions (reference)
| Language | Root | This repo |
|----------|------|-----------|
| C# (.NET) | `src/` | Single web project; vertical slices = **logical** component rows above + DTO table |