# 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 | | `_api_client_lock`| `threading.Lock` | Protects lazy initialization of `_api_client` (double-checked) | | `_unlock` | `_UnlockStateHolder` | Holds unlock workflow state and last error under an inner lock | #### `_UnlockStateHolder` | Member | Description | |-----------|-----------------------------------------------------------------------------| | `get()` | Returns `(state: UnlockState, error: Optional[str])` under lock | | `set(state, error=None)` | Sets state and optional error message under lock | | `state` (property) | Current `UnlockState` (read under lock) | ## Internal Logic ### `get_api_client()` Double-checked locking: if `_api_client` is `None`, acquires `_api_client_lock`, re-checks, then imports `ApiClient` and constructs `ApiClient(RESOURCE_API_URL)` once. ### Unlock Workflow (`_run_unlock`) Background task (via FastAPI BackgroundTasks) that runs these steps: 1. Check if Docker images already loaded → if yes, set `ready` (preserving any prior error from `get()`) 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. Remove tar file; on `OSError`, log a warning and continue 7. Set state to `ready` with no error (or `error` on failure) State and error are updated only through `_unlock.set()` and read via `_unlock.get()` / `_unlock.state`. ### `/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**: `UnlockState` from `unlock_state`, `get_api_client()` (lazy `api_client` import), `binary_split` (lazy import in unlock paths) - **External**: `os`, `threading` (stdlib), `fastapi`, `pydantic`, `loguru` (logger for tar cleanup warnings) ## 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 and error are guarded by `_UnlockStateHolder`’s lock; API client initialization is guarded by `_api_client_lock` - Lazy imports of Cython modules (`api_client`, `binary_split`) to avoid import-time side effects ## Tests No tests found.