mirror of
https://github.com/azaion/admin.git
synced 2026-06-21 21:11:08 +00:00
3a925b9b0f
- Deleted the `POST /resources/get/{dataFolder?}` and `GET /resources/get-installer` endpoints as part of the architectural shift towards simplified resource management.
- Removed associated methods and configurations, including `ResourcesService.GetEncryptedResource`, `ResourcesService.GetInstaller`, and related properties in `ResourcesConfig`.
- Cleaned up environment variables and configuration files to reflect the removal of installer-related settings.
- Eliminated the `GetResourceRequest` DTO and its validator, along with the `WrongResourceName` error code.
- Updated documentation to clarify the changes in resource handling and the retirement of per-user file encryption.
Co-authored-by: Cursor <cursoragent@cursor.com>
140 lines
12 KiB
Markdown
140 lines
12 KiB
Markdown
# Traceability Matrix
|
|
|
|
## Acceptance Criteria Coverage
|
|
|
|
| AC ID | Acceptance Criterion | Test IDs | Coverage |
|
|
|-------|---------------------|----------|----------|
|
|
| AC-1 | Valid login returns JWT | FT-P-01, NFT-PERF-01, NFT-RES-01, NFT-RES-LIM-04 | Covered |
|
|
| AC-2 | Unknown email returns code 10 | FT-N-01 | Covered |
|
|
| AC-3 | Wrong password returns code 30 | FT-N-02 | Covered |
|
|
| AC-4 | JWT lifetime 4 hours | FT-P-03, NFT-SEC-04 | Covered |
|
|
| AC-5 | Email min 8 chars | FT-P-02, FT-N-03 | Covered |
|
|
| AC-6 | Email format validation | FT-P-02, FT-N-04 | Covered |
|
|
| AC-7 | Password min 8 chars | FT-P-02, FT-N-08 | Covered |
|
|
| AC-8 | Duplicate email returns code 20 | FT-N-07 | Covered |
|
|
| AC-9 | Only ApiAdmin can manage users | FT-P-06, FT-P-07, FT-P-11, FT-P-12, FT-P-13, NFT-SEC-02, NFT-SEC-06 | Covered |
|
|
| AC-10 | First hardware check stores | FT-P-04, NFT-RES-03 | Covered |
|
|
| AC-11 | Subsequent hardware check validates | FT-P-05, NFT-RES-03 | Covered |
|
|
| AC-12 | Hardware mismatch returns code 40 | FT-N-06 | Covered |
|
|
| AC-13 | Max upload 200 MB | FT-P-08, NFT-RES-LIM-01, NFT-RES-LIM-02, NFT-PERF-03 | Covered |
|
|
| AC-14 | AES-256-CBC encryption | FT-P-09, FT-P-10, NFT-PERF-02, NFT-PERF-03, NFT-RES-LIM-03 | Covered |
|
|
| AC-15 | Encrypt-decrypt round-trip | FT-P-10 | Covered |
|
|
| AC-16 | Empty file upload returns code 70 | FT-N-05 | Covered |
|
|
| AC-17 | SHA-384 password hashing | NFT-SEC-03 | Covered |
|
|
| AC-18 | All non-login endpoints require auth | FT-P-09, NFT-SEC-01, NFT-RES-02, NFT-RES-LIM-04 | Covered |
|
|
| AC-19 | Encryption key derived from email+password+hw | FT-P-10, NFT-SEC-05 | Covered |
|
|
|
|
## Restrictions Coverage
|
|
|
|
| Restriction ID | Restriction | Test IDs | Coverage |
|
|
|---------------|-------------|----------|----------|
|
|
| RESTRICT-SW-01 | .NET 10.0 runtime | All tests (implicit — Docker build uses .NET 10.0) | Covered |
|
|
| RESTRICT-SW-02 | PostgreSQL database | All DB tests (implicit — docker-compose uses PostgreSQL) | Covered |
|
|
| RESTRICT-SW-03 | Max request body 200 MB | NFT-RES-LIM-01, NFT-RES-LIM-02 | Covered |
|
|
| RESTRICT-SW-04 | JWT HMAC-SHA256 signing | FT-P-03, NFT-SEC-04 | Covered |
|
|
| RESTRICT-HW-01 | ARM64 target architecture | — | NOT COVERED — CI builds ARM64; tests run on dev x64 host |
|
|
| RESTRICT-ENV-01 | Secrets via env vars | All tests (implicit — docker-compose passes env vars) | Covered |
|
|
| RESTRICT-ENV-02 | CORS admin.azaion.com | — | NOT COVERED — CORS is browser-enforced, not testable at API level |
|
|
| RESTRICT-OP-01 | Serilog logging | — | NOT COVERED — log output verification not in scope |
|
|
|
|
## Coverage Summary
|
|
|
|
| Category | Total Items | Covered | Not Covered | Coverage % |
|
|
|----------|-----------|---------|-------------|-----------|
|
|
| Acceptance Criteria (baseline) | 19 | 19 | 0 | 100% |
|
|
| Acceptance Criteria (cycle 1) | 24 | 24 | 0 | 100% |
|
|
| Acceptance Criteria (cycle 2) | 6 | 6 | 0 | 100% |
|
|
| Restrictions | 8 | 5 | 3 | 63% |
|
|
| **Total** | **57** | **54** | **3** | **95%** |
|
|
|
|
## Uncovered Items Analysis
|
|
|
|
| Item | Reason Not Covered | Risk | Mitigation |
|
|
|------|-------------------|------|-----------|
|
|
| RESTRICT-HW-01 (ARM64) | Tests run on x64 dev/CI host; cross-architecture testing requires ARM hardware | Low — .NET runtime handles arch differences; no arch-specific code in application | CI builds ARM64 image; manual smoke test on target device |
|
|
| RESTRICT-ENV-02 (CORS) | CORS is enforced by browsers, not by server-to-server HTTP calls | Low — CORS policy is declarative in Program.cs | Visual inspection of CORS configuration in code |
|
|
| RESTRICT-OP-01 (Logging) | Log output format/content verification adds complexity without proportional value | Low — Serilog configuration is declarative | Code review of Serilog setup |
|
|
|
|
## Cycle 1 Additions (2026-05-13) — AZ-513, AZ-196, AZ-183, AZ-197
|
|
|
|
Appended during the existing-code cycle 1 Test-Spec Sync (autodev Step 12). Cycle 1 ACs are namespaced by their tracker ID to avoid colliding with the baseline AC-1..AC-19 numbering above.
|
|
|
|
### AZ-513 — Detection Classes CRUD
|
|
|
|
| AC ID | Acceptance Criterion | Test IDs | Coverage |
|
|
|-------|---------------------|----------|----------|
|
|
| AZ-513 AC-1 | POST /classes creates a class | FT-P-14 | Covered |
|
|
| AZ-513 AC-2 | POST /classes requires ApiAdmin authorization | FT-N-09 | Covered |
|
|
| AZ-513 AC-3 | PATCH /classes/{id} updates an existing class (full body) | FT-P-15 | Covered |
|
|
| AZ-513 AC-4 | PATCH /classes/{id} accepts partial body (partial-merge) | FT-P-16 | Covered |
|
|
| AZ-513 AC-5 | PATCH /classes/{id} returns 404 for unknown id | FT-N-10 | Covered |
|
|
| AZ-513 AC-6 | PATCH /classes/{id} requires ApiAdmin authorization | FT-N-11 | Covered |
|
|
| AZ-513 AC-7 | DELETE /classes/{id} removes a class | FT-P-17 | Covered |
|
|
| AZ-513 AC-8 | DELETE /classes/{id} returns 404 for unknown id | FT-N-12 | Covered |
|
|
| AZ-513 AC-9 | DELETE /classes/{id} requires ApiAdmin authorization | FT-N-13 | Covered |
|
|
| AZ-513 AC-10 | UI add/delete/edit affordances work end-to-end | — | Cross-workspace (ui/ e2e harness) — out of scope for this workspace |
|
|
|
|
### AZ-196 — Device Auto-Registration
|
|
|
|
| AC ID | Acceptance Criterion | Test IDs | Coverage |
|
|
|-------|---------------------|----------|----------|
|
|
| AZ-196 AC-1 | First device gets serial azj-0000 (shape: serial / email / 32-hex password) | FT-P-18 | Covered |
|
|
| AZ-196 AC-2 | Sequential numbering on subsequent calls | FT-P-19 | Covered |
|
|
| AZ-196 AC-3 | Persisted user has Role=CompanionPC, IsEnabled=true | FT-P-20 | Covered (verified via successful login → role-gated behaviour) |
|
|
| AZ-196 AC-4 | Returned plaintext password is hashed (SHA-384) in DB, not stored plaintext | FT-P-20 | Covered (verified via successful login round-trip) |
|
|
| AZ-196 AC-5 | Requires ApiAdmin authorization | FT-N-14 | Covered |
|
|
|
|
### AZ-183 — Resources OTA Update Check (REVERTED post-cycle-1)
|
|
|
|
The OTA Update Check & Publish feature shipped in cycle 1 was reverted later the same day after the security audit (finding F-1: `/get-update` disclosed plaintext per-resource encryption keys to any authenticated caller; the OTA delivery model itself was deemed obsolete in the target architecture). The endpoints, service, entity, table, request DTOs, response DTO, cache key, master-key config field, and the e2e test class `ResourceUpdateTests` were all removed.
|
|
|
|
| AC ID | Acceptance Criterion | Test IDs | Status |
|
|
|-------|---------------------|----------|--------|
|
|
| AZ-183 AC-1 | Resources table created with required columns | — | **Reverted** — table dropped from migration set (`env/db/05_resources.sql` deleted) |
|
|
| AZ-183 AC-2 | POST /get-update returns newer resources | ~~FT-P-21~~ | **Reverted** — endpoint and test deleted |
|
|
| AZ-183 AC-3 | POST /get-update returns empty when device already current | ~~FT-P-22~~ | **Reverted** — endpoint and test deleted |
|
|
| AZ-183 AC-4 | Memory cache avoids DB pressure under 2000-device polling | — | **Reverted** — cache key removed |
|
|
| AZ-183 AC-5 | Cache invalidated on CI/CD publish | ~~FT-P-23~~ | **Reverted** — endpoint and test deleted |
|
|
|
|
### AZ-197 — Hardware-Binding Removal
|
|
|
|
| AC ID | Acceptance Criterion | Test IDs | Coverage |
|
|
|-------|---------------------|----------|----------|
|
|
| AZ-197 AC-1 | Resource download works without `Hardware` field | FT-P-09 / FT-P-10 (legacy bodies retained; wire shape now omits the field) | Covered (e2e `ResourceTests` updated by AZ-197 batch 6) |
|
|
| AZ-197 AC-2 | `PUT /users/hardware/set` and `POST /resources/check` return 404 | FT-N-15 | Covered |
|
|
| AZ-197 AC-3 | `Security.GetApiEncryptionKey` signature simplified to (email, password) | — | Internal signature — covered by `Azaion.Test/SecurityTest` unit tests, not blackbox |
|
|
| AZ-197 AC-4 | `HardwareBindingTests` removed; no remaining test asserts code 40 / hardware-hash binding | — | Build/CI invariant — verified by test-suite enumeration |
|
|
| AZ-197 AC-5 | Resource calls in remaining tests do not send `Hardware` | — | Build/CI invariant — verified by source review during AZ-197 batch 6 |
|
|
| AZ-197 AC-6 | `ExceptionEnum` no longer carries `HardwareIdMismatch` / `BadHardware` | — | Build/CI invariant — verified by enum read |
|
|
| AZ-197 AC-7 | `dotnet build` is clean (no new warnings) | — | Build invariant |
|
|
| AZ-197 AC-8 | Test suite passes (excluding deleted `HardwareBindingTests`) | All e2e tests + `Azaion.Test` | Covered by Step 11 Run Tests (48/48 e2e + 2/2 unit, 2026-05-13) |
|
|
|
|
### Obsoleted Baseline Entries (superseded by AZ-197)
|
|
|
|
The matrix rows below are kept for ID stability but no longer reflect production behaviour. They are superseded by the AZ-197 entries above and by FT-N-15 in `blackbox-tests.md`. Do NOT regenerate or delete these in cycle-update mode — wait for a full `/test-spec` rerun.
|
|
|
|
| Legacy Matrix Row | Status |
|
|
|-------------------|--------|
|
|
| AC-10 (First hardware check stores) | Obsoleted by AZ-197 — endpoint removed |
|
|
| AC-11 (Subsequent hardware check validates) | Obsoleted by AZ-197 — endpoint removed |
|
|
| AC-12 (Hardware mismatch returns code 40) | Obsoleted by AZ-197 — `ExceptionEnum` value removed |
|
|
| AC-19 (Encryption key derived from email+password+hw) | Partially obsoleted — derivation is now `email + password` only |
|
|
|
|
## Cycle 2 Cleanup (2026-05-14) — Obsolete Resource Endpoints Removed
|
|
|
|
The encrypted-download and installer-download endpoints were removed as obsolete. Affected matrix rows below are kept for ID stability but the underlying behaviour is gone; they are superseded by FT-N-16 in `blackbox-tests.md`.
|
|
|
|
| Removed surface | Endpoint(s) | Affected legacy entries | Status |
|
|
|-----------------|-------------|-------------------------|--------|
|
|
| Per-user encrypted resource download | `POST /resources/get/{dataFolder?}` | AC-14 (AES-256-CBC encryption), AC-15 (round-trip), AC-19 (key derivation), FT-P-09, FT-P-10 | **Reverted** — endpoint deleted; `Security.GetApiEncryptionKey` / `EncryptTo` / `DecryptTo` and `ResourcesService.GetEncryptedResource` deleted; `GetResourceRequest` DTO deleted; e2e tests `Encrypted_download_returns_octet_stream_and_non_empty_body` and `Encryption_round_trip_decrypt_matches_original_bytes` deleted from `ResourceTests.cs`; e2e test `Per_user_encryption_produces_distinct_ciphertext_for_same_file` deleted from `SecurityTests.cs`; `Azaion.Test/SecurityTest.cs` deleted (and the now-empty `Azaion.Test` project removed from the solution). |
|
|
| Installer download (production + staging) | `GET /resources/get-installer`, `GET /resources/get-installer/stage` | AC-23 (latest installer), `ResourcesConfig.SuiteInstallerFolder` / `SuiteStageInstallerFolder` references | **Reverted** — endpoints deleted; `ResourcesService.GetInstaller` deleted; both config properties removed from `appsettings.json`, `.env.example`, `secrets/staging.public.env`, `secrets/production.public.env`, and `docker-compose.test.yml`. No e2e tests had been written for these endpoints, so no tests required removal. |
|
|
|
|
| AC ID | Acceptance Criterion | Test IDs | Coverage |
|
|
|-------|---------------------|----------|----------|
|
|
| Cycle-2 AC-1 | `POST /resources/get/{dataFolder?}` returns 404 | FT-N-16 | Covered |
|
|
| Cycle-2 AC-2 | `GET /resources/get-installer` returns 404 | FT-N-16 | Covered |
|
|
| Cycle-2 AC-3 | `GET /resources/get-installer/stage` returns 404 | FT-N-16 | Covered |
|
|
| Cycle-2 AC-4 | `ExceptionEnum` no longer carries `WrongResourceName` (50); the gap is preserved | — | Build/CI invariant — verified by enum read |
|
|
| Cycle-2 AC-5 | `Azaion.Test` project no longer in solution; build is clean | — | Build invariant — `dotnet build Azaion.AdminApi.sln` clean post-cleanup |
|
|
| Cycle-2 AC-6 | E2E suite passes after the test deletions above | All e2e tests | Covered by Step 11 Run Tests post-cleanup (2026-05-14) |
|