- 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>
6.3 KiB
Module: Azaion.AdminApi.Program
Purpose
Application entry point: configures DI, middleware, authentication, authorization, CORS, Swagger, logging, and defines all HTTP endpoints using ASP.NET Core Minimal API.
Public Interface (HTTP Endpoints)
Cycle 1 (2026-05-13) note — endpoint surface changed by AZ-513 (detection-class CRUD), AZ-196 (device auto-registration), AZ-197 (hardware-binding removal). AZ-183 (OTA update check + publish) was reverted later the same day after the security audit (finding F-1) — the OTA delivery model itself was deemed obsolete; see
_docs/05_security/security_report.mdfor context. The table reflects the post-cycle-1 state including that revert.Cycle 2 (2026-05-14) note — three more endpoints were removed as obsolete:
POST /resources/get/{dataFolder?},GET /resources/get-installer,GET /resources/get-installer/stage. The encrypted-download support stack (Security.GetApiEncryptionKey/EncryptTo/DecryptTo,ResourcesService.GetEncryptedResource/GetInstaller,GetResourceRequestDTO,WrongResourceName = 50enum value,ResourcesConfig.SuiteInstallerFolder/SuiteStageInstallerFolder) went with them. ADR-003 inarchitecture.mdwas retired in the same change.
| Method | Path | Auth | Summary | Cycle 1 origin |
|---|---|---|---|---|
| POST | /login |
Anonymous | Validates credentials, returns JWT token | — |
| POST | /users |
ApiAdmin | Creates a new user | — |
| POST | /devices |
ApiAdmin | Creates a CompanionPC device user (auto serial / email / 32-hex password) | AZ-196 |
| GET | /users/current |
Any authenticated | Returns current user from JWT claims | — |
| GET | /users |
ApiAdmin | Lists users with optional email/role filters | — |
| PUT | /users/queue-offsets/set |
Any authenticated | Updates user's queue offsets | — |
| PUT | /users/{email}/set-role/{role} |
ApiAdmin | Changes a user's role | — |
| PUT | /users/{email}/enable |
ApiAdmin | Enables a user account | — |
| PUT | /users/{email}/disable |
ApiAdmin | Disables a user account | — |
| DELETE | /users/{email} |
ApiAdmin | Removes a user | — |
| POST | /resources/{dataFolder?} |
Any authenticated | Uploads a resource file | — |
| GET | /resources/list/{dataFolder?} |
Any authenticated | Lists files in a resource folder | — |
| POST | /resources/clear/{dataFolder?} |
ApiAdmin | Clears a resource folder | — |
| POST | /classes |
ApiAdmin | Creates a detection class | AZ-513 |
| PATCH | /classes/{id:int} |
ApiAdmin | Updates a detection class (partial-merge) | AZ-513 |
| DELETE | /classes/{id:int} |
ApiAdmin | Deletes a detection class | AZ-513 |
Removed endpoints
The following endpoints have been removed and now return 404:
| Method | Path | Removed in | Reason |
|---|---|---|---|
| PUT | /users/hardware/set |
cycle 1 (AZ-197) | hardware-binding feature deleted (no fielded clients in target architecture) |
| POST | /resources/check |
cycle 1 (AZ-197) | was the hardware-binding side-effect probe; no remaining purpose |
| POST | /get-update |
post-cycle-1 (AZ-183 reverted) | security audit F-1: endpoint disclosed plaintext per-resource encryption keys to any authenticated caller; the underlying installer-distribution flow is itself obsolete |
| POST | /resources/publish |
post-cycle-1 (AZ-183 reverted) | same revert as /get-update — the publish counterpart of the OTA flow |
| POST | /resources/get/{dataFolder?} |
cycle 2 (2026-05-14) | obsolete — per-user encrypted-download flow no longer used by any client; ADR-003 retired |
| GET | /resources/get-installer |
cycle 2 (2026-05-14) | obsolete — installer-shipping era is over (browser SaaS + fTPM Jetsons) |
| GET | /resources/get-installer/stage |
cycle 2 (2026-05-14) | same as /resources/get-installer |
Internal Logic
DI Registration
IUserService→UserService(Scoped)IAuthService→AuthService(Scoped)IResourcesService→ResourcesService(Scoped)IDetectionClassService→DetectionClassService(Scoped) — added by AZ-513IDbFactory→DbFactory(Singleton)ICache→MemoryCache(Scoped)LazyCacheviaAddLazyCache()- FluentValidation validators auto-discovered from
RegisterUserValidatorassembly (also picks upCreateDetectionClassRequest,UpdateDetectionClassRequestvalidators introduced in cycle 1) BusinessExceptionHandlerregistered as exception handler
Middleware Pipeline
- Swagger (dev only)
- CORS (
AdminCorsPolicy) - Authentication (JWT Bearer)
- Authorization
- URL rewrite: root
/→/swagger - Exception handler
Authorization Policies
apiAdminPolicy: requiresRoleEnum.ApiAdminrole
The
apiUploaderPolicy(RoleEnum.ResourceUploaderORApiAdmin) was added by AZ-183 and removed in the same cycle when the OTA endpoints it guarded were retired (see "Removed in cycle 1" above).RoleEnum.ResourceUploaderitself remains as a data value (the seeduploader@azaion.comstill uses it) but is no longer wired to any endpoint policy.
Configuration Sections
JwtConfig— JWT signing/validationConnectionStrings— DB connectionsResourcesConfig— file storage path (ResourcesFolder); the installer subfolders were dropped in cycle 2 along with the installer endpoints
Kestrel
- Max request body size: 200 MB (for file uploads)
Logging
- Serilog: console + rolling file (
logs/log.txt)
CORS
- Allowed origins:
https://admin.azaion.com,http://admin.azaion.com - All methods and headers allowed
- Credentials allowed
Dependencies
All services, configs, entities, and request types from Azaion.Common and Azaion.Services.
Consumers
None — this is the application entry point.
Data Models
None defined here.
Configuration
Reads JwtConfig, ConnectionStrings, ResourcesConfig from IConfiguration.
External Integrations
- PostgreSQL (via DI-registered
DbFactory) - Local filesystem (via
ResourcesService)
Security
- JWT Bearer authentication with full validation (issuer, audience, lifetime, signing key)
- Role-based authorization policies
- CORS restricted to
admin.azaion.com - Request body limit of 200 MB
- Antiforgery disabled for resource upload endpoint
- Password sent via POST body (not URL)
Tests
None directly; tested indirectly through integration tests.