refactor: remove deploy.cmd and update Dockerfile for health checks
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status

- Deleted the deploy.cmd script as it was no longer needed.
- Updated Dockerfile to include curl for health checks and added a non-root user for improved security.
- Modified health check command to use curl for better reliability.
- Adjusted docker-compose.test.yml to reflect changes in health check configuration.
- Cleaned up appsettings.json and removed unused configuration properties.
- Removed Resource entity and related requests from the codebase as part of the architectural shift.
- Updated documentation to reflect the removal of hardware binding and related endpoints.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-13 08:47:21 +03:00
parent 43fe38e67d
commit c7b297de83
76 changed files with 4034 additions and 832 deletions
@@ -1,12 +1,14 @@
# 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**: Server-side file storage management — upload, list, download (with per-user AES encryption), folder clearing, and installer distribution.
**Purpose**: filesystem-backed storage — upload, list, download (per-user AES-encrypted), folder clearing, installer distribution. Owned by `IResourcesService`.
**Architectural Pattern**: Service layer — filesystem operations with encryption applied at the service boundary.
**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).
**Upstream dependencies**: Data Layer (`ResourcesConfig`), Authentication & Security (encryption via `Security.EncryptTo`).
**Downstream consumers**: Admin API (resource endpoints).
@@ -22,15 +24,15 @@
| `ListResources` | `string? dataFolder, string? search, CancellationToken` | `IEnumerable<string>` | Yes | `DirectoryNotFoundException` |
| `ClearFolder` | `string? dataFolder` | void | No | None |
**Input DTOs**:
**Input DTO**:
```
GetResourceRequest:
GetResourceRequest (post-AZ-197):
Password: string (required, min 8 chars)
Hardware: string (required, not empty)
FileName: string (required, not empty)
// Hardware field removed by AZ-197.
CheckResourceRequest:
Hardware: string (required)
// CheckResourceRequest — REMOVED by AZ-197.
// GetUpdateRequest, PublishResourceRequest — added by AZ-183, removed in the post-cycle-1 revert.
```
## 3. External API Specification
@@ -39,17 +41,21 @@ N/A — exposed through Admin API.
## 4. Data Access Patterns
No database access. All operations are filesystem-based.
`ResourcesService` is filesystem-only — no DB access, no cache.
| Source | Service | Pattern |
|--------|---------|---------|
| Filesystem (`ResourcesConfig.ResourcesFolder`) | `ResourcesService` | Direct read/write/delete |
### Storage Estimates
Resources are stored as flat files in configured directories. Size depends on uploaded content (AI models, DLLs, installers — potentially hundreds of MB per file).
- **Filesystem**: AI models, DLLs, installers — potentially hundreds of MB per file.
## 5. Implementation Details
**State Management**: Stateless — reads/writes directly to filesystem.
**State Management**: stateless — reads/writes directly to filesystem.
**Key Dependencies**: None beyond BCL (System.IO).
**Key Dependencies**: none beyond BCL (System.IO).
**Error Handling Strategy**:
- `SaveResource` throws `BusinessException(NoFileProvided)` for null uploads.
@@ -61,13 +67,13 @@ Resources are stored as flat files in configured directories. Size depends on up
| Helper | Purpose | Used By |
|--------|---------|---------|
| `Security.EncryptTo` | AES stream encryption | GetEncryptedResource |
| `Security.GetApiEncryptionKey` | Key derivation | Admin API (before calling GetEncryptedResource) |
| `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**:
- No path traversal protection: `dataFolder` parameter is concatenated directly with `ResourcesFolder`. A malicious `dataFolder` like `../../etc` could access arbitrary filesystem paths.
**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.
@@ -90,11 +96,11 @@ Resources are stored as flat files in configured directories. Size depends on up
|-----------|------|---------|
| INFO | Successful file save | `Resource {data.FileName} Saved Successfully` |
**Log format**: String interpolation via Serilog.
**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).
**Log storage**: console + rolling file (via Serilog configured in Program.cs).
## Modules Covered
- `Services/ResourcesService`
- `Common/Requests/GetResourceRequest` (includes CheckResourceRequest)
- `Common/Configs/ResourcesConfig`
- `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)