- anthropic-teams.js: detect HTTP 400 extra-usage policy blocks, return
status='policy_rejected' with quota headers still readable
- report.js: display policy_rejected as CRITICAL with 'POLICY BLOCKED' label
- getSeverity: treat policy_rejected as critical
Currently the direct API (used by monitor) returns 200; pi's OAuth path
returns 400. This fix future-proofs against the block extending to direct
API calls, and correctly classifies the status if it does.
Refs: trentuna/commons#17, trentuna/token-monitor#4
allowed_warning providers can serve requests — only the budget is
approaching its limit. Previously they were excluded from both Phase 1
and Phase 2 selection, causing unnecessary escalation to shelley-proxy
emergency fallback when team-vigilio was at 79% 7d (allowed_warning)
and team-ludo was showing invalid_key in the health-pulse cache.
Now:
- Phase 1: first provider under threshold with status allowed or allowed_warning
- Phase 2: lowest-utilization provider with either status; reason notes warning
Effect: next wake picks team-vigilio (79% 7d, warning) instead of
shelley-proxy. Shelley-proxy is now a true last resort again.
invalid_key (HTTP 401) can be transient during key rotation or
temporary API issues — unlike rejected/exhausted which are stable
budget states. When cache shows all chain providers as invalid_key,
bypass cache and probe fresh so recovery is immediate instead of
waiting for the 20-minute TTL to expire.
Selects optimal Teams provider from chain based on real 7d utilization.
Uses cached monitor data (no extra API calls if fresh cache exists).
- Phase 1: first provider in chain with 7d util < SWITCH_THRESHOLD (default 75%)
- Phase 2: all over threshold → pick lowest 7d allowed provider
- Phase 3: all rejected → emergency=true, signals shelley-proxy needed
- Always fails safe: returns team-vigilio on any error
- PUT /auth/api-keys/{id} with fieldMask qps,qpm
- Defines limits per role: ba=2/30, vigilio=3/30, analysts=2/20
- --dry-run and --show flags included
- Blocked on UpdateApiKey ACL for management key (needs console.x.ai)
- See token-monitor#2 for Ludo action required
- providers/xai-billing.js: fetchXaiUsage, fetchXaiInvoicePreview,
aggregateByKey, renderXaiSection
- analyze.js: --xai flag for standalone view; xAI section appended
to full report when XAI_MANAGEMENT_KEY is set
- Verified against live API: per-key spend by unit type, prepaid
balance, current billing period total
- Usage endpoint: POST /v1/billing/teams/{id}/usage (analyticsRequest)
- Invoice endpoint: GET /v1/billing/teams/{id}/postpaid/invoice/preview
Two bugs caused all xai providers to show 'error' in the monitor:
1. Double /v1 in URL: models.json baseUrl is https://api.x.ai/v1 (OpenAI-
compatible convention), and the probe was appending /v1/chat/completions,
producing https://api.x.ai/v1/v1/chat/completions → HTTP 4xx.
Fix: strip trailing /vN from baseUrl before constructing the probe URL.
2. Wrong model: probe used grok-3-mini, which requires specific x.ai
console permissions not granted to our keys. Keys have access to
grok-4-1-fast-reasoning only.
Fix: use GET /v1/models instead — lightweight, no model guessing,
returns 200 (valid key) or 401 (invalid). Includes available models
in result for visibility.
158/158 tests pass (unit tests for parseXaiHeaders unchanged).
- analyze.js: burn rate, weekly reconstruction, cycle stagger, rotation
rank, underspend alerts, log prune with weekly archive
- logger.js: getCachedRun(maxAgeMinutes) — skip probing if recent data exists
- monitor.js: cache guard at wake — 20-min dedup, zero extra API calls
- test.js: fix type assertion for gemini-api/xai-api providers (+5 passing);
add 14 new tests for cache guard and analyze.js (162 total, all green)
- docs/analyze.md: usage reference
Co-authored-by: Hannibal Smith <hannibal@trentuna.com>
Implements modular provider probing with two distinct header schemas:
- Teams direct (unified schema): 5h/7d utilization floats, status, reset countdown
- Shelley proxy (classic schema): token/request counts + Exedev-Gateway-Cost (USD/call)
- api-ateam: reports no billing data (confirmed non-existent by recon)
Key: uses claude-haiku-4-5-20251001 for minimal probe calls (1 token).
Rate-limit headers present on ALL responses (200 and 429).
113/113 tests passing.
Built from Face recon (trentuna/a-team#91) — live header capture confirmed
unified schema with utilization floats replaces old per-count schema.