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.
5.6 KiB
5.6 KiB
08 — Admin Console (Next.js) Map
Surface:
apps/adminStack: Next.js 16 App Router + MUI (@d3ro/uitheme) + Supabase service role + .NET proxy Role: back office CRM/ops — users, subscriptions, models, usage, audit, releases, ads
1. Route tree (src/app/)
Public
| Route | Purpose |
|---|---|
/login |
Email/password → /api/auth/login; Google OAuth via Supabase → /auth/callback; maps error keys |
/unauthorized |
403 screen |
/auth/callback |
OAuth code → session exchange |
Protected (admin) (guarded by (admin)/layout.tsx → requireManager())
| Route | Purpose |
|---|---|
/ |
Dashboard: backend stats, node health, MRR/ARR/active subscriptions (Supabase), recent errors |
/pipelines |
AI/voice pipeline telemetry; explicit "unavailable" card when no measured data |
/models |
LLM model + STT provider manager (presets, CRUD, test) |
/releases |
Forgejo live release hub (assets, platforms, sizes, downloads, SHA-256) |
/users |
User directory: search + tier/role filters |
/users/[id] |
User 360: profile, subscription, 30-day usage, role change (admin+), payment history |
/subscriptions |
Subscription ops list + filters; license issuer (super_admin) |
/subscriptions/new |
Grant VIP subscription (admin+) |
/subscriptions/[id] |
Subscription detail: edit (manager+) / delete (admin+) |
/ads |
Ad mediation console (10 networks, all fail_closed) + reward stats |
/support |
Stub — explicit "not configured" panel |
/usage |
Combined LLM + STT usage/cost analytics |
/audit-log |
Supabase audit log list + target filter + pagination |
/audit-log/[id] |
Audit detail with before/after diff |
2. API route handlers (src/app/api/)
| Route | Methods | Behavior |
|---|---|---|
/api/auth/login |
POST | Validate body, reject honeypot trap, in-memory rate limit/lockout, proxy to .NET /api/auth/login (7s timeout, HTTPS in prod), validate token/role/email/expiry, sign HMAC session cookie d3ro_admin_session |
/api/auth/logout |
POST/GET | Clear cookie; GET redirects /login |
/api/admin/backend/[...segments] |
GET/POST/PUT/DELETE | Allow-list proxy to .NET /api/admin/*; required role by path; same-origin for non-GET; ≤64KB; UUID idempotency-key for mutations |
/api/admin/license |
POST | Same-origin + requireVerifiedBackendSession('super_admin'); sign Ed25519 key with ADMIN_LICENSE_PRIVATE_KEY (@d3ro/core/utils/crypto-license); best-effort audit |
/api/admin/supabase/[operation] |
GET/POST/PATCH/DELETE | admin-users, admin-subscriptions, admin-payments via RPCs; strict allow-lists; Payple live history returns 501 |
/auth/callback |
GET | Supabase OAuth exchange |
3. Libraries (src/lib/)
| File | Purpose |
|---|---|
admin-session.ts |
Session types, secret validation (≥32 bytes), strict cookie parse, adminCookieSecure() escape hatch |
security.ts |
server-only HMAC-SHA256 sign/verify, in-memory rate limit/lockout, runtime security validation |
admin-guard.ts |
RSC guards requireManager/requireAdmin/requireSuperAdmin, role helpers |
edge-session.ts |
Edge-runtime HMAC verify via WebCrypto (used by proxy.ts) |
backend-session.ts |
requireApiServerOrigin, requireVerifiedBackendSession(minRole) (verifies cookie + .NET /api/auth/me), fetchAdminBackend |
api-server.ts |
server-only data access to .NET backend (stats, users, endpoints, usage reports) |
backend-admin-client.ts |
client CRUD for model/STT endpoints with auto idempotency keys |
admin-api.ts |
client callAdminApi for Supabase admin operations |
supabase-admin.ts |
service-role client, actor resolution RPC, product user fetch |
supabase-browser.ts / supabase-server.ts |
client/server Supabase wrappers |
ad-monetization.ts |
MEDIATION_ROSTER (fail_closed) + ad reward stats |
subscription-metrics.ts |
MRR/ARR/active/tier breakdown |
audit-sanitize.ts |
recursive redaction of sensitive keys in audit snapshots |
forgejo-releases.ts |
Forgejo release feed parser (RELEASE_REPO_URL) |
console-theme.ts |
design tokens + MUI style presets |
Root files: instrumentation.ts (startup security validation), proxy.ts (edge middleware: public paths, auth redirect, security headers), robots.ts (disallow all).
4. Components (src/components/)
admin-sidebar (nav island: Core Platform / Customer & Revenue / Intelligence & Security), unavailable-admin-panel (reusable "NOT CONNECTED", no sample data), audit-diff-viewer, payment-history, subscription-form, role-change-dialog + role-change-button, memo-dialog, license-issuer-button + license-issuer-dialog, checksum-copy, charts (dau-chart, feature-usage-chart, top-users-chart).
5. Admin status summary
- Dashboard, models, releases, users, subscriptions, usage, audit log, ads: implemented against real backend/Supabase data.
- Security: HMAC signed sessions, RSC + edge guards, rate limit/lockout, honeypot, strict origin/allow-list, no-store, robots disallow, audit redaction. Red-team scenarios were exercised (see
memory/project_status.md). - Explicit fail-closed / not-configured states (by design, not bugs):
/supportstub — no ticket/SLA/diagnostics contract./ads— all 10 networksfail_closed; no live bids.admin-paymentsPayple live history →501.UnavailableAdminPanelwhenever Supabase env absent; writes disabled, no sample metrics./pipelinesand dashboard node/error sections render only measured data.
- Deploy:
Dockerfile.admin/apps/admin/Dockerfile→ GHCR + NAS compose; GitLab admin NAS deploy job disabled.