Files

93 lines
3.8 KiB
Markdown
Raw Permalink Normal View History

# Analytics & usage audit (Descrybe v2)
Date: 2026-08-04
Scope: company billing usage, admin analytics, meters vs live Postgres.
## Surfaces
| Surface | Path / API | Role |
|---------|------------|------|
| Company billing / usage | `/billing``GET /api/billing/credits`, `GET /api/billing/usage?range=` | Tenant |
| Dashboard meters | `/dashboard``/api/auth/me` credits + product count | Tenant |
| Admin overview | `/admin` → summary from `/api/admin/analytics` | Platform admin |
| Admin analytics | `/admin/analytics``GET /api/admin/analytics?days=` | Platform admin |
| Admin billing | `/admin/billing` | Plans / credits / cycles |
## Bugs found
1. **Stale cycle override on company usage**
`UsageSummary` preferred the latest `billing_cycles` row (`credits_used=22`, `products_processed=12`, JuneJuly window) over live wallet and catalog. Demo wallet was `used_credits=0` with **~4323+** processed products and an **AugSep** `company_plans` cycle.
2. **Misleading empty / range UI on `/billing`**
“Usage history” gated on `credits_used > 0`, so a rich catalog with zero wallet spend looked empty. The 7d/30d selector did not change any numbers.
3. **Admin provider cards at zero on running binary**
Disk already had `ai_provider_mode` rollups; the old `api.exe` still returned stub zeros. After rebuild, internal mode matches DB (`internal` on all products/jobs).
4. **Feeds missing from admin volume**
Input/export feed counts were not exposed on the analytics summary.
## Fixes
### `GET /api/billing/usage?range=7d|30d|cycle|all` (default `30d`)
- **Credits** always from live `credit_balances` (not historical cycle rows).
- **Products / tokens** filtered by range; `products_total` is all-time catalog.
- **Cycle dates** from active `company_plans` (`billing_cycle_start` / `next_billing_date`).
- **Feeds** (`feeds_input`, `feeds_export`) and `jobs_total` from live tables.
- **Series** (products + tokens by UTC day) for 7d / 30d / cycle.
- Notes clarify that credit debits are not daily-ledgered yet.
### Admin analytics
- Summary includes `feeds_input` / `feeds_export`.
- Provider breakdown + detail + per-day class series from `ai_provider_mode`.
- Notes updated; billing-cycle table labeled as historical rollups that may lag the active plan window.
### UI
- `/billing`: catalog card, range metric cards, honest empty states, range-driven chart via `AdminSeriesChart`.
- `/admin/analytics`: feed counts on Volume card; clearer cycle table copy.
## Demo verification (Local Demo Co)
Against `postgres://…@localhost:5433/descrybe` after rebuild, logged in as `demo@descrybe.local`:
| Meter | API | DB |
|-------|-----|-----|
| Wallet used / total | 0 / 1_000_000 | 0 / 1_000_000 |
| Products (all) | 4326 | 4326 |
| Input / export feeds | 12 / 5 | 12 / 5 |
| Plan cycle | 2026-08-04 → 2026-09-04 | `company_plans` |
| Platform products | 7225 | 7225 |
| Platform credits used | 26 | 26 |
| Platform feeds in/out | 35 / 12 | 35 / 12 |
| Provider internal tokens/products | 11_383_374 / 7225 | `ai_provider_mode=internal` |
Previously the usage API returned **22 credits / 12 products** from a stale `billing_cycles` row — fixed.
## Remaining limitations
- No per-day **credit** ledger; range filters apply to products/tokens only.
- `billing_cycles` historical rows can lag or disagree with the active plan window; they remain an admin history table, not the tenant source of truth.
- Token series for migrated catalogs often clumps on import day(s).
## Verification commands
```powershell
cd apps/api
go test ./internal/billing/ -run ParseUsageRange -count=1
go build -o bin/api.exe ./cmd/api
cd ../web
npm run check
```
Demo smoke (after API restart):
```powershell
# login as demo@descrybe.local then:
# GET /api/billing/usage?range=30d
# GET /api/admin/analytics?days=30
```