- 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>
5.6 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.
| 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 | /resources/get/{dataFolder?} |
Any authenticated | Downloads an encrypted resource (key derived from email + password only) |
AZ-197 wire change (no Hardware field) |
| GET | /resources/get-installer |
Any authenticated | Downloads latest production installer | — |
| GET | /resources/get-installer/stage |
Any authenticated | Downloads latest staging installer | — |
| 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 in cycle 1
The following endpoints were removed during cycle 1 and now return 404:
| Method | Path | Reason removed |
|---|---|---|
| PUT | /users/hardware/set |
AZ-197 — hardware-binding feature deleted (no fielded clients in target architecture) |
| POST | /resources/check |
AZ-197 — was the hardware-binding side-effect probe; no remaining purpose |
| POST | /get-update |
OTA delivery model retired post-cycle-1 (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 |
Same revert as /get-update — the publish counterpart of the OTA flow |
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 paths
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.