- docs/REFACTOR_WAVE3_REPORT.md and the Wave 3 policy: canonical map, production changes, verification and remaining external steps. - Gap backlog: GAP-BILL-01 resolved; new GAP-BILL-02 (Payple renewal never ran, Payple client key never set), GAP-WEB-01 (tunnel host for /app), GAP-OPS-01 (NAS compose/.env drift), GAP-CI-01, GAP-I18N-02, GAP-TEAM-02. - design.md: hero loop decision (numbers taken from the app capsule), pricing mismatch closed; feature catalog SHELL-11 updated. - docs/map, release guide and mobile release docs no longer describe the deleted wwwroot, binaries, Dockerfile.admin, NAS site copy or .github CI. - docker-compose.nas.yml gains the d3ro-whisper service that only existed in the NAS copy, so the repository file is the complete definition. - refactor-wave skill: Wave 3 index and lessons P10-P12.
6.5 KiB
6.5 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 → rate limiter → authentication → authorization. The API no longer serves static files:
wwwroot(stale site build, download/invite pages,.well-knowncopy, legacy embedded admin SPA, 1.0.0 binaries) was deleted 2026-09-26 (Wave 3,cd9d199), andUseStaticFiles/the mobile-asset-block fallbacks were removed fromProgram.csalong with it. The Next.js admin (apps/admin) is the only admin UI. - Health:
GET /health,GET /api/health→{status, service, version, uptimeSeconds, database, timestamp}.
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.
- No static file serving —
wwwrootand its mobile/legacy release asset block were deleted 2026-09-26 (Wave 3,cd9d199); downloads/releases are served only fromsite/. LlmProxyServiceMock fallback.
- This backend holds a separate identity from Supabase; see
11-gap-backlog.mdID-01.