- 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.
5.7 KiB
5.7 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:
apps/admin/Dockerfile→ GHCR + NAS compose; the duplicate rootDockerfile.adminwas deleted 2026-09-26 (Wave 3,cd9d199) sinceapps/admin/Dockerfileis the one actually used. GitLab admin NAS deploy job disabled.