mirror of
https://github.com/azaion/admin.git
synced 2026-06-21 13:31:08 +00:00
f369153149
Batch 5 (cycle 2 hotfix sprint, batch 1 of 2). 6 story points under epic AZ-530. Addresses 2 Critical + 2 High deploy-blocking findings from security_report_cycle2.md (F-INFRA-1..F-INFRA-4). AZ-552 — drop_jwt_secret_deploy_preflight (1 pt, F-INFRA-1 Critical) scripts/start-services.sh swaps obsolete JwtConfig__Secret preflight for the cycle-2 trio (KeysFolder + ActiveKid + DataProtection.KeysFolder). .env.example, env/api/env.ps1, _docs/04_deploy/* updated to match. Repo scan in scripts/ and .env.example returns 0 offenders. AZ-553 — bind_mount_es256_keys (2 pts, F-INFRA-2 Critical) start-services.sh bind-mounts DEPLOY_HOST_JWT_KEYS_DIR read-only at /etc/azaion/jwt-keys; preflight fails fast on a missing or empty host directory with operator-actionable error messages. AZ-554 — persist_dataprotection_keys (2 pts, F-INFRA-3 High) Program.cs DataProtection wiring now fails fast in Production when KeysFolder is unset OR not probe-writable. start-services.sh bind-mounts DEPLOY_HOST_DP_KEYS_DIR read-write at /var/lib/azaion/dp-keys. Development behaviour unchanged (ephemeral default). AZ-555 — secrets_readme_es256_rewrite (1 pt, F-INFRA-4 High) secrets/README.md schema fully rewritten; new "Host-side directories" subsection with bind-mount table + ownership/permission guidance. Cycle-1 JwtConfig__Secret removed from live schema (one prose deprecation paragraph retained). Adjacent hygiene module-layout.md "Owns" extended to include scripts/, secrets/, env/, .env.example (gap from Step 9 new-task layout-delta). Tests e2e/Azaion.E2E/Tests/Cycle2HotfixDeployTests.cs — 19 facts (8 exec, 11 Skip with rationale per AZ-537/AZ-538 precedent). Skipped tests cover preflight/restart/Production-only paths verified at deploy gate. Build: 0W 0E across Azaion.AdminApi + Azaion.E2E. Test run deferred to autodev Step 11 (Run Tests). Tracker transition deferred to next batch (MCP availability unverified in this session — Leftovers pattern). Co-authored-by: Cursor <cursoragent@cursor.com>
85 lines
7.5 KiB
Markdown
85 lines
7.5 KiB
Markdown
# Module Layout
|
|
|
|
**Language**: csharp
|
|
**Layout Convention**: solution-flat (legacy — pre-`src/` convention)
|
|
**Root**: `./` (csproj folders sit at workspace root)
|
|
**Last Updated**: 2026-05-14 *(cycle 2 Auth Modernization AZ-531..AZ-538; cycle-2 hotfix AZ-552..AZ-557 added `scripts/`, `secrets/`, `env/`, `.env.example` to Admin API Owns)*
|
|
|
|
## Layout Rules
|
|
|
|
1. This admin/ workspace is one **deployable** (the `Azaion.AdminApi` HTTP service) split across three production csproj projects + one e2e test csproj: `Azaion.AdminApi`, `Azaion.Services`, `Azaion.Common`, `e2e/Azaion.E2E`. (The `Azaion.Test` unit-test project was removed in cycle 2 once its only test class — `SecurityTest.cs` — was deleted along with the encrypted-download stack; no in-process unit tests remain.)
|
|
2. Existing task specs (`_docs/02_tasks/*/AZ-*.md`) all use `Component: Admin API` as a single coarse identifier covering this entire workspace. The Per-Component Mapping below honors that convention rather than rewriting every task spec.
|
|
3. The conceptual sub-components documented in `_docs/02_document/components/01_data_layer..05_admin_api/` are **read-time** documentation aids, not write-time ownership boundaries. They are listed under "Conceptual Sub-Components" below for reference only.
|
|
4. Public API surface = the namespaces / interfaces exposed across csproj boundaries (`I*Service` interfaces in `Azaion.Services`, request DTOs in `Azaion.Common/Requests/`, entities in `Azaion.Common/Entities/`).
|
|
5. Tests live in `e2e/Azaion.E2E/` (HTTP black-box). Production code never imports from there.
|
|
|
|
## Per-Component Mapping
|
|
|
|
### Component: Admin API
|
|
|
|
- **Epic**: AZ-181 (and any other admin-API epic, e.g. AZ-509 for the Detection Classes feature)
|
|
- **Directory**: workspace root (multi-csproj, see below)
|
|
- **Owns (exclusive write during implementation)**:
|
|
- `Azaion.AdminApi/**`
|
|
- `Azaion.Services/**`
|
|
- `Azaion.Common/**`
|
|
- `e2e/Azaion.E2E/**` (xUnit/HttpClient-based black-box tests)
|
|
- `e2e/db-init/**` (test-DB seed/init scripts consumed by the e2e harness)
|
|
- `docker-compose.test.yml`
|
|
- `scripts/**` (deploy / lifecycle bash helpers — workspace-root infra)
|
|
- `secrets/**` (sops + age handover, public env overlays, jwt-keys host dir)
|
|
- `env/**` (DB schema/install scripts, dev convenience env setters)
|
|
- `.env.example` (operator-facing runtime env template)
|
|
- **Public API** (visible to other csprojs within the workspace):
|
|
- `Azaion.Services/I*Service.cs` interfaces (UserService, AuthService, ResourcesService, …)
|
|
- `Azaion.Services/Security.cs`, `Azaion.Services/Cache.cs` (used by `Azaion.AdminApi/Program.cs`)
|
|
- `Azaion.Common/Requests/*` request DTOs
|
|
- `Azaion.Common/Entities/*` linq2db entities
|
|
- `Azaion.Common/Database/*` `IDbFactory` + connection helpers
|
|
- `Azaion.Common/Configs/*` strongly-typed config records
|
|
- `Azaion.Common/Extensions/*` extension methods
|
|
- `Azaion.Common/BusinessException.cs`
|
|
- `Azaion.AdminApi/Program.cs` (composition root + minimal-API endpoints)
|
|
- `Azaion.AdminApi/BusinessExceptionHandler.cs`
|
|
- **Internal (do NOT import across csproj boundaries)**:
|
|
- private/internal members within each csproj (default C# visibility rules apply)
|
|
- `Azaion.AdminApi/appsettings*.json` (loaded by the host, not imported)
|
|
- `e2e/Azaion.E2E/Helpers/*` (test-only helpers, never imported by production)
|
|
- **Imports from**: (none — this is the only deployable in the workspace; the Loader is architecturally retired per `suite/_docs/_repo-config.yaml` `unresolved:loader-retirement-arch-doc`)
|
|
- **Consumed by**: HTTP clients (UI workspace, edge services on secured Jetson, SaaS browser sessions) — out of process
|
|
|
|
## Conceptual Sub-Components (documentation only — NOT ownership boundaries)
|
|
|
|
These come from `_docs/02_document/components/` and exist for reading the codebase, not for assigning task ownership. A single task may legitimately touch multiple sub-components within the `Admin API` umbrella.
|
|
|
|
| # | Sub-component | Primary file locations |
|
|
|---|----------------------|------------------------|
|
|
| 1 | Data Layer | `Azaion.Common/Database/`, `Azaion.Common/Configs/` (incl. cycle-2 `AuthConfig.cs` + `JwtConfig.cs` rebuilt for ES256 + new `SessionConfig`), `Azaion.Common/Entities/` (incl. cycle-1 `DetectionClass.cs`; cycle-2 `Session.cs` + `AuditEvent.cs`; `User.cs` extended with lockout + MFA columns; `RoleEnum.cs` + `Service = 60`) |
|
|
| 2 | User Management | `Azaion.Services/UserService.cs` (cycle-2 — Argon2id verify/hash + lazy migration + lockout + per-account rate-limit checks; new dependencies on `IAuditLog`, `IOptions<AuthConfig>`), `Azaion.Common/Requests/Register{User,DeviceResponse}.cs`, `LoginRequest.cs`, `LoginResponse.cs` *(new — AZ-531)*, `MfaRequests.cs` *(new — AZ-534)*, `MissionSessionRequest.cs` *(new — AZ-533)*, `SetUserQueueOffsetsRequest.cs` |
|
|
| 3 | Auth & Security | `Azaion.Services/AuthService.cs` (cycle-2 — ES256 + `AccessToken` record + sid/jti/amr claims), `Azaion.Services/Security.cs` (cycle-2 — Argon2id `HashPassword`/`VerifyPassword`; `ToHash` deleted), `Azaion.Services/RefreshTokenService.cs` *(new — AZ-531)*, `Azaion.Services/SessionService.cs` *(new — AZ-535)*, `Azaion.Services/MfaService.cs` *(new — AZ-534)*, `Azaion.Services/MissionTokenService.cs` *(new — AZ-533)*, `Azaion.Services/JwtSigningKeyProvider.cs` *(new — AZ-532)*, `Azaion.Services/AuditLog.cs` *(new — AZ-537)*, `Azaion.Services/Cache.cs` |
|
|
| 4 | Resource Management | `Azaion.Services/ResourcesService.cs` (`GetResourceRequest.cs` removed in cycle 2 with `POST /resources/get`; `SetHWRequest.cs` removed by AZ-197; `ResourceUpdateService.cs` + `GetUpdateRequest.cs` + `PublishResourceRequest.cs` removed when AZ-183 was reverted) |
|
|
| 4b | Detection Classes | `Azaion.Services/DetectionClassService.cs` + `Azaion.Common/Requests/{Create,Update}DetectionClassRequest.cs` (added cycle 1 / AZ-513) |
|
|
| 5 | Admin API (HTTP) | `Azaion.AdminApi/Program.cs` (cycle-2 — significantly expanded: HSTS / HTTPS redirect, RateLimiter, DataProtection, eight new endpoints, `IssueDualTokens` + `ParseSidClaim`/`ParseUserIdClaim` helpers), `Azaion.AdminApi/BusinessExceptionHandler.cs` (cycle-2 — per-enum status mapping + `Retry-After` header), `Azaion.AdminApi/appsettings*.json` |
|
|
|
|
## Allowed Dependencies (csproj layering)
|
|
|
|
| Layer | csproj | May reference |
|
|
|-------|--------|---------------|
|
|
| 4. Entry / Host | `Azaion.AdminApi` | `Azaion.Services`, `Azaion.Common` |
|
|
| 3. Application | `Azaion.Services` | `Azaion.Common` |
|
|
| 2. Foundation | `Azaion.Common` | (none) |
|
|
| —. Tests (out-of-process e2e) | `e2e/Azaion.E2E` | (none from production csprojs — HTTP only) |
|
|
|
|
A reference from a lower production layer to a higher production layer is an **Architecture** finding (High severity) in `/code-review` Phase 7. Test projects may reference any production csproj; production csprojs may NOT reference test projects.
|
|
|
|
## Layout Conventions (reference)
|
|
|
|
| Language | Root | Per-component path | Public API file | Test path |
|
|
|----------|------|-------------------|-----------------|-----------|
|
|
| C# (.NET) | `./` (this workspace, legacy flat layout) | `./<Csproj>/` | namespace-root types in each csproj | `e2e/Azaion.E2E/` |
|
|
|
|
## Notes
|
|
|
|
- This file was authored 2026-05-13 by `/autodev` Step 10 to satisfy `/implement` Step 4. The `_docs/` artifact set predates the Step 1.5 module-layout addition, so this is a **backfill** rather than a fresh decompose Step 1.5 run.
|
|
- If the project later splits into multiple deployables (e.g. carving out `Azaion.AnnotationsApi`), re-run `/decompose` Step 1.5 to produce a finer-grained mapping.
|