Files
admin/_docs/02_document/components/04_resource_management/description.md
T
Oleksandr Bezdieniezhnykh c7b297de83
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
refactor: remove deploy.cmd and update Dockerfile for health checks
- 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>
2026-05-13 08:47:21 +03:00

4.9 KiB

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<string> 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)