Files
loader/_docs/00_problem/acceptance_criteria.md
T
Oleksandr Bezdieniezhnykh 8f7deb3fca Add E2E tests, fix bugs
Made-with: Cursor
2026-04-13 05:17:48 +03:00

39 lines
2.8 KiB
Markdown

# Acceptance Criteria
## Functional Criteria
| # | Criterion | Measurable Target | Source |
|---|-----------|-------------------|--------|
| AC-1 | Health endpoint responds | GET `/health` returns `{"status": "healthy"}` with HTTP 200 | `main.py:54-55` |
| AC-2 | Login sets credentials | POST `/login` with valid email/password returns `{"status": "ok"}` | `main.py:69-75` |
| AC-3 | Login rejects invalid credentials | POST `/login` with bad credentials returns HTTP 401 | `main.py:74-75` |
| AC-4 | Resource download returns decrypted bytes | POST `/load/{filename}` returns binary content (application/octet-stream) | `main.py:79-85` |
| AC-5 | Resource upload succeeds | POST `/upload/{filename}` with file returns `{"status": "ok"}` | `main.py:89-100` |
| AC-6 | Unlock starts background workflow | POST `/unlock` with credentials returns `{"state": "authenticating"}` | `main.py:158-181` |
| AC-7 | Unlock detects already-loaded images | POST `/unlock` when images are loaded returns `{"state": "ready"}` | `main.py:163-164` |
| AC-8 | Unlock status reports progress | GET `/unlock/status` returns current state and error | `main.py:184-187` |
| AC-9 | Unlock completes full cycle | Background task transitions: authenticating → downloading_key → decrypting → loading_images → ready | `main.py:103-155` |
| AC-10 | Unlock handles missing archive | POST `/unlock` when archive missing and images not loaded returns HTTP 404 | `main.py:168-174` |
## Security Criteria
| # | Criterion | Measurable Target | Source |
|---|-----------|-------------------|--------|
| AC-11 | Resources encrypted at rest | AES-256-CBC encryption with per-user or shared key | `security.pyx` |
| AC-12 | Hardware-bound key derivation | API download key incorporates hardware fingerprint | `security.pyx:54-55` |
| AC-13 | Binary split prevents single-source compromise | Small part on API + big part on CDN required for decryption | `api_client.pyx:166-186` |
| AC-14 | JWT token obtained from trusted API | Login via POST to Azaion Resource API with credentials | `api_client.pyx:43-55` |
| AC-15 | Auto-retry on expired token | 401/403 triggers re-login and retry | `api_client.pyx:140-146` |
## Operational Criteria
| # | Criterion | Measurable Target | Source |
|---|-----------|-------------------|--------|
| AC-16 | Docker images verified | All 7 API_SERVICES images checked via `docker image inspect` | `binary_split.py:60-69` |
| AC-17 | Logs rotate daily | File sink rotates every 1 day, retains 30 days | `constants.pyx:19-26` |
| AC-18 | Container builds on ARM64 | Woodpecker CI produces `loader:arm` image | `.woodpecker/build-arm.yml` |
## Non-Functional Criteria
No explicit performance targets (latency, throughput, concurrency) are defined in the codebase. Resource download/upload latency depends on file size and network conditions.