Files
admin/_docs/00_problem/acceptance_criteria.md
2026-04-16 06:25:36 +03:00

57 lines
4.3 KiB
Markdown

# Acceptance Criteria
Derived from validation rules, test assertions, configuration limits, and health check patterns found in the codebase.
## Authentication
| # | Criterion | Threshold | Source |
|---|-----------|-----------|--------|
| AC-1 | Login with valid credentials returns a JWT token | Token is non-empty string | `Program.cs` `/login` endpoint |
| AC-2 | Login with unknown email returns error code 10 | HTTP 409, `ErrorCode: 10` | `UserService.ValidateUser` throws `NoEmailFound` |
| AC-3 | Login with wrong password returns error code 30 | HTTP 409, `ErrorCode: 30` | `UserService.ValidateUser` throws `WrongPassword` |
| AC-4 | JWT token expires after configured hours | Token `exp` claim = now + `TokenLifetimeHours` | `AuthService.CreateToken`, default 4 hours |
| AC-5 | JWT token contains user ID, email, and role claims | Claims: `NameIdentifier`, `Name`, `Role` | `AuthService.CreateToken` |
## User Management
| # | Criterion | Threshold | Source |
|---|-----------|-----------|--------|
| AC-6 | Registration rejects email < 8 characters | Validation error, code `EmailLengthIncorrect` | `RegisterUserValidator` |
| AC-7 | Registration rejects invalid email format | Validation error, code `WrongEmail` | `RegisterUserValidator` |
| AC-8 | Registration rejects password < 8 characters | Validation error, code `PasswordLengthIncorrect` | `RegisterUserValidator` |
| AC-9 | Registration rejects duplicate email | HTTP 409, `ErrorCode: 20` (EmailExists) | `UserService.RegisterUser` |
| AC-10 | Password is stored as SHA-384 hash, never plaintext | `PasswordHash` column contains Base64 of SHA-384 | `Security.ToHash()` |
| AC-11 | User listing supports optional email and role filters | Filters applied via `WhereIf` | `UserService.GetUsers` |
| AC-12 | Only ApiAdmin role can create, list, modify, or delete users | Endpoints require `apiAdminPolicy` | `Program.cs` authorization |
## Hardware Binding
| # | Criterion | Threshold | Source |
|---|-----------|-----------|--------|
| AC-13 | First hardware check stores the hardware fingerprint | `hardware` column updated from null to provided string | `UserService.CheckHardwareHash` |
| AC-14 | Subsequent hardware checks compare hash of provided hardware against stored | Hash comparison via `Security.GetHWHash` | `UserService.CheckHardwareHash` |
| AC-15 | Hardware mismatch returns error code 40 | HTTP 409, `ErrorCode: 40` (HardwareIdMismatch) | `UserService.CheckHardwareHash` |
| AC-16 | Admin can reset hardware by setting it to null | `PUT /users/hardware/set` with null hardware | `UserService.UpdateHardware` |
## Resource Management
| # | Criterion | Threshold | Source |
|---|-----------|-----------|--------|
| AC-17 | File upload supports up to 200 MB | Kestrel `MaxRequestBodySize = 209715200` | `Program.cs` |
| AC-18 | Uploaded file is saved to configured resource folder | File written to `ResourcesConfig.ResourcesFolder` | `ResourcesService.SaveResource` |
| AC-19 | Resource download returns AES-256-CBC encrypted stream | Encryption via `Security.EncryptTo` | `ResourcesService.GetEncryptedResource` |
| AC-20 | Encrypted resource can be decrypted with same key | Round-trip encrypt/decrypt preserves data | `SecurityTest.EncryptDecryptTest` ✓ |
| AC-21 | Large files (hundreds of MB) can be encrypted/decrypted | Round-trip works for ~400 MB files | `SecurityTest.EncryptDecryptLargeFileTest` ✓ |
| AC-22 | Missing file upload returns error code 60 | HTTP 409, `ErrorCode: 60` (NoFileProvided) | `ResourcesService.SaveResource` |
| AC-23 | Installer download returns latest `AzaionSuite.Iterative*` file | Scans installer folder, returns first match | `ResourcesService.GetInstaller` |
| AC-24 | Only ApiAdmin can clear resource folders | `POST /resources/clear` requires `apiAdminPolicy` | `Program.cs` |
## API Behavior
| # | Criterion | Threshold | Source |
|---|-----------|-----------|--------|
| AC-25 | Business errors return HTTP 409 with JSON `{ErrorCode, Message}` | Handled by `BusinessExceptionHandler` | `BusinessExceptionHandler.TryHandleAsync` |
| AC-26 | Swagger UI available in Development environment | `app.UseSwagger()` conditional on `IsDevelopment` | `Program.cs` |
| AC-27 | Root URL redirects to /swagger | URL rewrite rule | `Program.cs` |
| AC-28 | CORS allows requests from admin.azaion.com | Origins: `https://admin.azaion.com`, `http://admin.azaion.com` | `Program.cs` |