# Module: main ## Purpose FastAPI application entry point providing HTTP endpoints for health checks, authentication, encrypted resource loading/uploading, and a multi-step Docker image unlock workflow. ## Public Interface ### FastAPI Application `app = FastAPI(title="Azaion.Loader")` ### Endpoints | Method | Path | Request Body | Response | Description | |--------|------------------|---------------------|----------------------------|----------------------------------------------------| | GET | `/health` | — | `{"status": "healthy"}` | Liveness probe | | GET | `/status` | — | `StatusResponse` | Auth status + model cache dir | | POST | `/login` | `LoginRequest` | `{"status": "ok"}` | Set credentials on API client | | POST | `/load/{filename}`| `LoadRequest` | binary (octet-stream) | Download + decrypt resource | | POST | `/upload/{filename}`| multipart (file + folder) | `{"status": "ok"}` | Encrypt + upload resource (big/small split) | | POST | `/unlock` | `LoginRequest` | `{"state": "..."}` | Start background unlock workflow | | GET | `/unlock/status` | — | `{"state": "...", "error": ...}` | Poll unlock progress | ### Pydantic Models | Model | Fields | |-----------------|----------------------------------------------| | LoginRequest | email: str, password: str | | LoadRequest | filename: str, folder: str | | HealthResponse | status: str | | StatusResponse | status: str, authenticated: bool, modelCacheDir: str | ### Module-level State | Name | Type | Description | |----------------|--------------------|------------------------------------------------| | api_client | ApiClient or None | Lazy-initialized singleton | | unlock_state | UnlockState | Current unlock workflow state | | unlock_error | Optional[str] | Last unlock error message | | unlock_lock | threading.Lock | Thread safety for unlock state mutations | ## Internal Logic ### `get_api_client()` Lazy singleton pattern: creates `ApiClient(RESOURCE_API_URL)` on first call. ### Unlock Workflow (`_run_unlock`) Background task (via FastAPI BackgroundTasks) that runs these steps: 1. Check if Docker images already loaded → if yes, set `ready` 2. Authenticate with API (login) 3. Download key fragment from `/binary-split/key-fragment` 4. Decrypt archive at `IMAGES_PATH` → `.tar` 5. `docker load` the tar file 6. Clean up tar file 7. Set state to `ready` (or `error` on failure) State transitions are guarded by `unlock_lock` (threading.Lock). ### `/unlock` Endpoint - If already `ready` → return immediately - If already in progress → return current state - If no encrypted archive found → check if images already loaded; if not, 404 - Otherwise, starts `_run_unlock` as a background task ## Dependencies - **Internal**: `unlock_state` (UnlockState enum), `api_client` (lazy import), `binary_split` (lazy import) - **External**: `os`, `threading` (stdlib), `fastapi`, `pydantic` ## Consumers None — this is the entry point module. ## Data Models `LoginRequest`, `LoadRequest`, `HealthResponse`, `StatusResponse` (Pydantic models defined inline). ## Configuration | Env Variable | Default | Description | |------------------|--------------------------------|--------------------------------| | RESOURCE_API_URL | `https://api.azaion.com` | Azaion resource API base URL | | IMAGES_PATH | `/opt/azaion/images.enc` | Path to encrypted Docker images | | API_VERSION | `latest` | Expected Docker image version tag | ## External Integrations - **Azaion Resource API**: via `ApiClient` (authenticated resource download/upload) - **Docker CLI**: via `binary_split` (docker load, image inspect) - **File system**: encrypted archive at `IMAGES_PATH` ## Security - Login endpoint returns 401 on auth failure - All resource endpoints use authenticated API client - Unlock state is thread-safe via `threading.Lock` - Lazy imports of Cython modules (`api_client`, `binary_split`) to avoid import-time side effects ## Tests No tests found.