Some checks failed
deploy-site / deploy (push) Failing after 40s
Release notes for 1.1.0 were split between an Unreleased section and the version section, so the published notes would have omitted the update-feed and desktop changes. Everything shipping in this version now sits under one `## [1.1.0]` heading. `docs/map/` becomes the entry point for what infrastructure exists per platform and how far each feature is developed, with a documented update protocol so feature work and this map do not drift apart again. The release guide now states that installer binaries live in the update feed rather than the repository.
6.4 KiB
6.4 KiB
07 — API Server (.NET) Map
Surface:
apps/api-server(D3ROVoice.Api), tests inapps/api-server.TestsStack: ASP.NET Core 10 + EF Core + SQLite Role: AI proxy (LLM/STT) + admin back-office backend for the .NET identity side
1. Composition root (Program.cs)
- DI:
AddControllers,AddHttpClient(proxies), Swagger (v1), rate limiter policyauth(fixed window 10/min per IP, 429),AddDbContext<AppDbContext>(SQLite;DATA_DIR/DB_PATH), scopedIAuthService,ILlmProxyService,ISttProxyService,IAdminOperationService. - Auth: JWT Bearer HS256; startup hard-fails unless
JWT_SECRET(≥32 bytes),JWT_ISSUER,JWT_AUDIENCEare set. Zero clock skew. - Policies:
ManagerOrAbove(manager/admin/superadmin),AdminOrAbove(admin/superadmin),SuperAdminOnly(superadmin). Role normalization strips_/-, lowercases. - CORS/Hosts: strict origin validation (
CORS_ALLOWED_ORIGINS),ALLOWED_HOSTSrequired outside Development. - Startup DB init:
EnsureCreated(), rawCREATE TABLE IF NOT EXISTSfor admin operation/audit tables, legacy SHA-256 password lockdown (IsActive=false,Role="LegacyDisabled"), idempotent env admin provisioning (ADMIN_EMAIL/ADMIN_PASSWORD, only when no active user), default LLM/STT endpoints seeded. - Middleware order: Swagger (dev) → CORS → invite-page hardening (CSP/no-store) → default files → mobile/legacy asset block (404 for
.apk/.aab/signed zips + legacy bundles) → static files → rate limiter → authentication → authorization. - Health:
GET /health,GET /api/health→{status, service, version, uptimeSeconds, database, timestamp}. - Fallbacks:
/accept-invite→accept-invite.html;/admin/{*path}→ legacy embedded admin SPA inwwwroot/admin.
2. Controllers & routes
AuthController (/api/auth)
| Route | Auth | Behavior |
|---|---|---|
POST /register |
anonymous + X-D3RO-Bootstrap-Token |
Rate-limited, ≤16KB; requires ADMIN_BOOTSTRAP_TOKEN; fixed-time compare; 409 if registered |
POST /login |
anonymous | Rate-limited; returns JWT; 401 invalid |
GET /me |
[Authorize] |
UserInfoDto or 404 |
LlmController (/api/llm, class [Authorize])
| Route | Behavior |
|---|---|
POST /generate |
Requires prompt; GenerateAsync |
POST /chat |
ChatAsync (last message = prompt) |
SttController (/api/stt, class [Authorize])
| Route | Auth | Behavior |
|---|---|---|
POST /transcribe |
any auth | Always 410 Gone stt_edge_gateway_required — user transcription is Edge-only |
POST /internal/transcribe |
anonymous + X-D3RO-STT-Gateway-Token |
multipart, ≤26MB; requires D3RO_API_TOKEN; fixed-time compare; provider orchestration; error map 503/400/502 |
GET /providers |
ManagerOrAbove | List STT endpoints |
POST /test?endpointId= |
ManagerOrAbove | Test endpoint |
AdminController (/api/admin, class ManagerOrAbove)
All mutations flow through ExecuteAdminMutationAsync (idempotent + audited).
| Route | Effective policy |
|---|---|
GET /stats |
Manager+ |
GET /users |
Manager+ |
GET/POST/PUT/DELETE /endpoints[/{id}] |
Manager+ read; Admin+ write |
GET /stt-endpoints, /stt-endpoints/{id} |
Manager+ |
POST/PUT/DELETE /stt-endpoints[/{id}], POST .../set-default |
Admin+ |
POST /stt-endpoints/{id}/test |
Manager+ |
POST /stt-endpoints/test-direct |
Admin+ |
GET /stt-usage, GET /usage |
Manager+ |
POST /license-audit |
SuperAdminOnly |
3. Services
| Service | Purpose |
|---|---|
AuthService |
Register (one-time SuperAdmin bootstrap only, PasswordHasher<User>, serialized), login (timing-safe dummy verify, inactive rejection, rehash), JWT gen (8h, claims id/email/role) |
LlmProxyService |
Resolve endpoint by model → fallback → Mock echo; OpenAI-style POST; parse content+usage; token cost → ApiUsageLog; errors → ServerErrorLog + fallback text |
SttProxyService (~1182 lines) |
Provider adapters (groq/openai/custom, deepgram, google, assemblyai, azure, local-sidecar), candidate resolution + fallback, content-type/duration detection, SttUsageLog cost, synthetic-tone endpoint test, CRUD with exclusive default, usage report |
AdminOperationService |
Validates actor/idempotency key/memo, SHA-256 request hash, Serializable transaction, idempotent replay, before/after audit entry |
4. Data (Data/AppDbContext.cs)
| DbSet / table | Key fields |
|---|---|
Users |
Id, unique Email, PasswordHash, Role (default "User"), IsActive, CreatedAt, LastLoginAt |
ModelEndpoints |
Id, unique ModelId, ModelName, Provider, EndpointUrl, ApiKey, per-1k costs, IsActive |
UsageLogs |
UserId/Email, model, tokens, cost, duration, status |
ErrorLogs |
ErrorType, Message, StackTrace, Endpoint |
SttProviderEndpoints |
Name, ProviderType, URL, ApiKey, ModelId, Method, Language, Prompt, Temperature, per-minute/second cost, IsDefault, FallbackPriority, ExtraHeadersJson |
SttUsageLogs |
User, endpoint, provider, duration, cost, latency, status, transcript preview |
AdminOperationRequests |
ActorEmail + IdempotencyKey (unique), Operation, RequestHash, ResponseJson |
AdminAuditEntries |
ActorEmail, Action, TargetType/Id, BeforeJson, AfterJson, Memo, IdempotencyKey |
DTOs (Dtos/Dtos.cs): auth, license audit, LLM, admin/model endpoints, STT (transcribe, endpoints, test, usage reports).
5. Tests (apps/api-server.Tests/, xUnit)
AdminAuthorizationE2ETests, AdminOperationServiceTests, AuthBootstrapControllerTests, AuthSecurityTests, SttControllerSecurityTests, SttFailClosedTests, SttGatewayAuthorizationE2ETests (26/26 per SSOT).
6. API server status summary
- Auth, login, JWT, role policies, rate limiting, CORS, host restrictions: implemented.
- LLM proxy: implemented (with local Mock echo fallback for standalone testing).
- STT proxy: implemented for internal gateway; public
/transcribeintentionally410(Edge-only by design). - Admin API: users, endpoints (LLM + STT), usage, license audit: implemented with idempotency + audit.
- Known intentional states (not bugs):
- Legacy SHA-256 users force-disabled.
- No hardcoded/seeded admin credentials.
- Mobile/legacy release assets blocked with 404.
LlmProxyServiceMock fallback.
- This backend holds a separate identity from Supabase; see
11-gap-backlog.mdID-01.