# Resource Management > **Cycle 1 (2026-05-13) note** — AZ-197 removed the `Hardware` field from `GetResourceRequest` and removed `CheckResourceRequest` and `POST /resources/check` entirely. AZ-183 introduced an OTA update path (`POST /get-update`, `POST /resources/publish`, `IResourceUpdateService`, `Resource` entity, `resources` table, `ResourcesConfig.EncryptionMasterKey`) but it was reverted later the same day after the security audit (finding F-1) — the OTA delivery model itself was deemed obsolete. The component is now back to filesystem-backed storage only. ## 1. High-Level Overview **Purpose**: filesystem-backed storage — upload, list, download (per-user AES-encrypted), folder clearing, installer distribution. Owned by `IResourcesService`. **Architectural Pattern**: a single service over the local filesystem. No DB access, no cache. **Upstream dependencies**: Data Layer (`ResourcesConfig`), Authentication & Security (encryption via `Security.EncryptTo`). **Downstream consumers**: Admin API (resource endpoints). ## 2. Internal Interfaces ### Interface: IResourcesService | Method | Input | Output | Async | Error Types | |--------|-------|--------|-------|-------------| | `GetInstaller` | `bool isStage` | `(string?, Stream?)` | No | None (returns nulls if not found) | | `GetEncryptedResource` | `string? dataFolder, string fileName, string key, CancellationToken` | `Stream` | Yes | `FileNotFoundException` | | `SaveResource` | `string? dataFolder, IFormFile data, CancellationToken` | void | Yes | `BusinessException(NoFileProvided)` | | `ListResources` | `string? dataFolder, string? search, CancellationToken` | `IEnumerable` | Yes | `DirectoryNotFoundException` | | `ClearFolder` | `string? dataFolder` | void | No | None | **Input DTO**: ``` GetResourceRequest (post-AZ-197): Password: string (required, min 8 chars) FileName: string (required, not empty) // Hardware field removed by AZ-197. // CheckResourceRequest — REMOVED by AZ-197. // GetUpdateRequest, PublishResourceRequest — added by AZ-183, removed in the post-cycle-1 revert. ``` ## 3. External API Specification N/A — exposed through Admin API. ## 4. Data Access Patterns `ResourcesService` is filesystem-only — no DB access, no cache. | Source | Service | Pattern | |--------|---------|---------| | Filesystem (`ResourcesConfig.ResourcesFolder`) | `ResourcesService` | Direct read/write/delete | ### Storage Estimates - **Filesystem**: AI models, DLLs, installers — potentially hundreds of MB per file. ## 5. Implementation Details **State Management**: stateless — reads/writes directly to filesystem. **Key Dependencies**: none beyond BCL (System.IO). **Error Handling Strategy**: - `SaveResource` throws `BusinessException(NoFileProvided)` for null uploads. - Missing files/directories throw standard .NET I/O exceptions. - `ClearFolder` silently returns if directory doesn't exist. - `GetInstaller` returns `(null, null)` tuple if installer file is not found. ## 6. Extensions and Helpers | Helper | Purpose | Used By | |--------|---------|---------| | `Security.EncryptTo` | AES stream encryption | `GetEncryptedResource` | | `Security.GetApiEncryptionKey(email, password)` | Per-user key derivation (post-AZ-197 — no hardware component) | Admin API (before calling `GetEncryptedResource`) | ## 7. Caveats & Edge Cases **Known limitations** (security-audit findings): - **F-2 (High)** — no path traversal protection: `dataFolder` parameter is concatenated directly with `ResourcesFolder`. A malicious `dataFolder` like `../../etc` could access arbitrary filesystem paths. Filed as separate ticket. - `SaveResource` deletes existing file before writing — no versioning or backup. - `GetEncryptedResource` loads the entire encrypted file into a `MemoryStream` — memory-intensive for large files. - `ListResources` wraps a synchronous `DirectoryInfo.GetFiles` in `Task.FromResult` — not truly async. **Performance bottlenecks**: - Full file encryption to memory before streaming response: memory usage scales with file size. - `ClearFolder` iterates and deletes files synchronously. ## 8. Dependency Graph **Must be implemented after**: Data Layer (ResourcesConfig), Authentication & Security (encryption). **Can be implemented in parallel with**: User Management. **Blocks**: Admin API. ## 9. Logging Strategy | Log Level | When | Example | |-----------|------|---------| | INFO | Successful file save | `Resource {data.FileName} Saved Successfully` | **Log format**: string interpolation via Serilog (security audit F-12 hygiene item: convert to structured form). **Log storage**: console + rolling file (via Serilog configured in Program.cs). ## Modules Covered - `Services/ResourcesService` - `Common/Requests/GetResourceRequest` (post-AZ-197 — no `CheckResourceRequest`, no `Hardware` field) - `Common/Configs/ResourcesConfig` (the `EncryptionMasterKey` field added by AZ-183 was removed in the post-cycle-1 revert)