# meowtrace — Admin Portal Plan (ADMIN-PLAN.md)

> ↩ **Back to canonical entry:** [SPEC.md](./SPEC.md)
> Full living spec for the **Admin Portal** surface — current state + planned work.
> The User surface has its own doc: [PORTAL-PLAN.md](./PORTAL-PLAN.md).

**Status:** Built (Phase 5 ✅), on staging — living spec for ongoing feature work
**Surface:** `https://admin.staging.meowtrace.com` (hostname-selected; role-gated to `role=admin`)
**Last updated:** 2026-07-27

---

## 1. What this is

The **Admin Portal** is the internal, role-gated back office. It is one half of a single
role-gated React/Vite SPA ([`src/portal/`](../src/portal/)) — the **same build** as the
User Portal ([PORTAL-PLAN.md](./PORTAL-PLAN.md)); hostname `admin.*` selects the Admin
surface and it is gated to `role=admin`. A non-admin account reaching `admin.*` sees an
"access denied" panel.

Auth is a **bearer token** (`mt_token`, `localStorage`); admin API calls hit role-gated
`/v1/admin/*` endpoints (403 for non-admins, 200 for admins). Admin login screen is
distinct from the user login. Admins are **provisioned** (never self-register); grant via
`UPDATE accounts SET role='admin' WHERE email='...'` (see [DEVOPS.md](./DEVOPS.md)).
Admin credentials are **not stored in docs** (this file is served publicly).

## 2. Surfaces & routes (current)

| Route | Page | Purpose |
|---|---|---|
| `/` | Admin Accounts | Accounts list + usage/credit rollup; row → detail |
| `/accounts/:id` | Account detail | Identity, orgs, subscriptions, recent usage + **overrides** (tier, credits, suspend) |
| `/logs` | Request logs | Cross-account API traffic (filter by account/status) |

Backing API (role-gated): `/v1/admin/accounts`, `/v1/admin/accounts/:id`,
`PATCH /v1/admin/accounts/:id` (tier), `POST /v1/admin/accounts/:id/credits`,
`POST /v1/admin/accounts/:id/suspend`, `/v1/admin/logs`, `/v1/admin/stats`.
User-side org-details management: `GET`/`PATCH /v1/orgs`.

## 3. Feature detail

### 3.0 Navigation
- **Side navigation (sidenav)**, not a topbar — consistent with the User surface
  ([PORTAL-PLAN.md](./PORTAL-PLAN.md)). Both surfaces share the sidenav shell.

### 3.1 Back-office surface (from SPEC §5.1 scope)
The Admin Portal's intended remit — user/account management, credit & tier overrides,
usage/billing oversight, fair-usage/abuse monitoring (§3.4), and system health (§3.5).
**Built (Phase 5 completion):** accounts list, per-account detail, credit/tier overrides,
flag/suspend, and cross-account request logs. **Remaining (Phase 6):** §3.4 abuse
monitoring + §3.5 system health (both need the observability tier).

### 3.2 Billing oversight (Admin Portal)
- View/adjust any account's plan, credits, and balance (overrides).
- Inspect usage + billing history per account.
- Reconcile Stripe state (subscriptions, invoices, failed payments).
- Flag/suspend accounts (fair-usage / abuse — [SPEC.md §8](./SPEC.md)).

### 3.3 HTTP request/response log view (Admin)
- Ops sees **logs across accounts** for support, abuse investigation
  ([SPEC.md §8](./SPEC.md) fair-usage), and incident review.
- Admin access is **role-gated and audited**; never log API-key secrets or card data.
- Backed by the request-log data model in [SPEC.md §9.1](./SPEC.md) (shared with the
  User own-request view in [PORTAL-PLAN.md](./PORTAL-PLAN.md)).

### 3.4 Fair-usage / abuse monitoring
Guards the house against abuse while staying invisible to honest heavy users
([SPEC.md §8](./SPEC.md) Enterprise Fair-Usage Policy). The Admin surface for it:
- **Signals surfaced:** accounts/keys approaching or sustaining traffic near the
  fair-usage ceiling (~10M lookups/day), concurrency near the per-key cap (~100 in-flight),
  and error/429 spikes that suggest hammering.
- **Free-tier signup-spam / farming detection:** flag patterns that exploit the Free
  daily allowance (10 credits/day) by mass-creating accounts — e.g. many signups from one
  source IP or IP block, disposable/`+`-alias or throwaway-domain email clusters, bursts of
  new accounts in a short window, and personal orgs whose only activity is draining the
  free refill. Surfaces suspected sybil/farming clusters for review (link/suspend).
- **Anti-abuse heuristics (flag for review, not auto-ban):** sustained near-ceiling
  traffic; single-IP credential sharing (one key from many source IPs, or many keys from
  one IP); scraping-pattern access (sequential IP sweeps, flat high-rate calls);
  free-tier account farming (above).
- **Per-key scoping:** flags attach to the offending API key (keys are org-scoped and
  revocable); an admin can review, then revoke/suspend via §3.2.
- **Review queue:** flagged accounts/keys land in a list with the triggering signal,
  recent traffic summary, and a link to the cross-account log view (§3.3) for drill-down.
- **Data source:** derived from `usage_records`/request logs ([SPEC.md §9.1](./SPEC.md))
  + credit-burn aggregates. _(TBD: thresholds, look-back window, and whether detection is
  batch/rollup or near-real-time — tune before launch, [SPEC.md §8](./SPEC.md).)_
- **Dependency:** meaningful signal needs the observability/metrics tier — largely
  **Phase 6** ([SPEC.md §5.2](./SPEC.md)).

### 3.5 System health
Operational visibility for the ops/admin ([SPEC.md §5.2](./SPEC.md) observability).
- **Traffic & latency:** requests/sec, p50/p95/p99 lookup latency, error-rate split
  (4xx/5xx), 404 not-found vs. found ratio.
- **Credit economy:** credit-burn rate, 429 hard-cap hit-rate (how often accounts run
  dry), refill/reset activity.
- **Service state:** API fleet up/health, DB reachable, cache hit-rate (when the cache
  tier lands), Stripe webhook backlog/failures.
- **Presentation:** dashboard cards + time-series; alert thresholds _(TBD)_.
- **Data source:** app metrics/logs + `usage_records` aggregates. _(TBD: metrics backend —
  Prometheus/CloudWatch/etc. — and retention.)_
- **Dependency:** requires the metrics/observability infrastructure — **Phase 6**
  ([SPEC.md §5.2](./SPEC.md)); building the UI ahead of the metrics tier is premature.

## 4. Planned / backlog

**Built (Phase 5 completion, 2026-07-20 — deployed + verified live):**
- [x] **Sidenav navigation** — side nav, shared shell with the User surface (§3.0).
- [x] **Credit & tier overrides** — set tier + adjust balance via `admin-adjust` ledger delta (§3.2).
- [x] **Usage/billing oversight (account detail)** — per-account identity, orgs, subscriptions, recent usage (§3.2).
- [x] **Cross-account request-log view** — filterable logs across accounts (§3.3).
- [x] **Flag / suspend accounts** — `accounts.suspended`; suspended key lookups refused 401 (§3.2).

**Backlog (Phase-6-gated on the observability/metrics tier):**
- [ ] **Fair-usage / abuse monitoring** — flag/review queue for near-ceiling traffic,
  credential sharing, scraping, **and free-tier signup-spam / account farming** (§3.4).
- [ ] **System health** — traffic/latency/credit-burn/service dashboards (§3.5).

## 5. Data & API dependencies

- **Usage tracking data model** — the shared contract lives in [SPEC.md §9.1](./SPEC.md).
  This doc describes the **Admin-facing oversight views** of that data, not the model.
- **API** — role-gated `/v1/admin/*` (403/200 by role); see [API.md](./API.md).
- **Fair-usage / abuse policy** — [SPEC.md §8](./SPEC.md) (ceilings, concurrency, anti-abuse).

## Changelog
- **2026-07-26** — **Request-log row drill-down added (§3.3).** Clicking a log row now
  opens a right-side **forensic record** drawer showing every field the trail actually
  holds: outcome (status + HTTP meaning, endpoint/method, queried summary, latency,
  credits), origin (caller IP, account, org, **API key prefix**), and timing (UTC +
  local). **Honesty marker (SPEC §9.4):** the backend `usage_records` table stores **no
  raw request/response headers or bodies** — only a bounded summary. The drawer's
  "Headers & body" section is therefore a **capability marker** ("not captured on this
  tier — full, short-retention, redacted capture is a Phase-6 observability item"), not
  fabricated data. Backend: `/v1/admin/logs` now also returns `org_id`, `api_key_id`,
  and `key_prefix` (LEFT JOIN `api_keys`) — real fields previously unsurfaced;
  `meowtrace-api` restarted. Files: `components/LogDetail.tsx` (new), `pages/AdminLogs.tsx`,
  `lib/adminApi.ts`, backend `admin_routes.ts`. Deployed + HTTPS-verified.
  > **Open item for Ben:** if you want *real* request/response header+body capture in the
  > drill-down, that is a backend change (capture + short-retention + redaction, SPEC §9.4
  > "full-body capture is TBD") — flag it and I will spec it as Phase-6 work.
- **2026-07-26** — **Admin console visual redesign (no scope/feature change).** The
  console read as undressed default MUI (light canvas, bare white tables, confetti
  chips) behind a bespoke login. Restyled the surface into a dark "watchtower"
  instrument panel matching the Báizhēn sentinel identity: dedicated dark admin theme
  (`src/portal/src/theme.ts`), Fraunces display + Inter body + **JetBrains Mono** for
  all data (IPs/IDs/latency/credits, tabular figures = ledger), hairline cartographic
  tables, gold reserved as the single "true-north" signal (active nav, key totals,
  alerts), status shown as precise dots not loud chips, and an at-a-glance stat strip
  on Accounts. Restyled sidenav (gold active tick + tiger seal). User portal untouched
  (light theme preserved). Desktop + 390px mobile verified in Chrome; production build
  clean, dev render-harness shims stripped by `import.meta.env.DEV`. Files: `theme.ts`,
  `components/{Layout,ui,StatCards}.tsx`, `pages/Admin{Accounts,AccountDetail,Logs}.tsx`,
  `index.html` (fonts). Design plan: [.review/ADMIN-REDESIGN.md](../.review/ADMIN-REDESIGN.md).
- **2026-07-20** — **Phase 5 completion (Admin Portal build-out) DONE:** sidenav (both
  surfaces), credit/tier overrides, per-account detail/oversight, cross-account request
  logs, flag/suspend (+ lookup enforcement via `accounts.suspended`). Built, deployed to
  `app`/`admin.staging`, verified live (all five endpoints + non-admin 403 guard). §3.4/§3.5
  remain Phase-6 backlog. Routes table + §3.1 + §4 updated.
- **2026-07-20** — **Abuse monitoring extended:** §3.4 now covers **free-tier signup-spam /
  account farming** (mass signups to exploit the 10/day free allowance — IP clustering,
  disposable-email patterns, burst detection). **Security:** removed the admin login
  email/credentials from this doc (publicly served).
- **2026-07-20** — **Backlog rulings:** kept #1–#5; **removed dataset-refresh controls**
  (dropped from §3.1 remit + backlog); **expanded** fair-usage/abuse monitoring into §3.4
  and system health into §3.5 (both flagged Phase-6-dependent on the observability tier).
- **2026-07-20** — **Navigation decision:** Admin surface uses a **sidenav** (shared shell
  with the User surface), not a topbar. Added §3.0 + backlog item.
- **2026-07-20** — Created. Migrated Admin-Portal feature detail out of SPEC (§5.1 surface,
  §9.3 billing oversight, §9.4 admin log view) into this full living spec. Usage-tracking
  **data model** stays in [SPEC.md §9.1](./SPEC.md) (shared contract).
