fix(codex): keep WHAM usage response upstream-compatible - #8
Draft
darvell wants to merge 12 commits into
Draft
Conversation
…onest analytics Replace the single shared friend_code with three principal kinds (guest, member, operator), per-request authorization using signed credential issue-time cutoffs, and an immutable DuckDB event ledger behind a durable Bolt outbox. Key changes: - PassportStore: Bolt-backed principals, clients, sessions, join links, audit - Authorization: in-memory map read (702ns/op), issue-time cutoff per principal - Guest passes: required private note, optional expiry, multi-use magic link - Member sign-in: Argon2id passwords, optional WebAuthn passkeys - Per-client credentials: up to 20 labelled tokens per principal - DuckDB analytics: immutable fact ledger, durable outbox, crash replay - Operator console: ranking, detail, suspension, audit log - Migration: preserves all 50 existing user IDs and history byte-for-byte - Security: CSRF double-submit, HttpOnly/Secure/SameSite=Strict cookies - Packaging: multi-stage Docker linux/amd64 build with native DuckDB Removes: friend_code request auth, friend_landing.html, cute_code_landing.html Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
DuckDB defaults to grabbing most of host memory. On the 1.9GB staging droplet this caused an OOM during importLegacyBolt. Now honors the DUCKDB_MEMORY_LIMIT env var before schema creation and import.
On the 1GB production droplet, DuckDB's default memory allocation (732MB) plus the legacy Bolt import from the 627MB proxy.db exceeds the cgroup limit. When DUCKDB_LOW_MEMORY is set, skip the import and write a marker so it doesn't retry. The SQLite analytics.db already holds the historical data; the DuckDB ledger accumulates new facts going forward.
…auto-promote - Add GET /api/auth/config endpoint exposing legacy_signup and operator_exists - Add operator bootstrap form to AccessGate when no operator exists - Allow /api/setup/operator without admin token when no operator exists yet - Promote first legacy signup to operator when none exists - Hide legacy signup button when legacyFriendCode is not configured - Add loadAuthConfig and operatorBootstrap API functions
- Restore friend_landing.html and cute_code_landing.html templates - Restore /api/friend/claim endpoint for Cute Code CLI setup - / serves friend landing (friend_code entry), /app serves Passport SPA - /join and /recover serve the Passport SPA (fragment-based auth) - /cute-code serves the cute code setup page - Simplify Mine page: inline setup with platform tabs, collapsed profile - Rename 'Mine' to 'MY STATS' in nav, remove separate Setup page - Collapse pass form behind 'NEW PASS' button - First legacy signup auto-promotes to operator when none exists - Update tests for new routing and promotion behavior
MY STATS: - Merged client list and setup into one flow: each client has inline SETUP button that reveals platform tabs, no separate dropdown/reveal - Removed redundant CLIENTS table and USAGE table (chart already shows this) - Removed redundant TOKEN BURN panel title - Mint form hidden behind '+ ADD CLIENT' button - Profile section uses inline form layout - Passkey registration uses inline form layout Console: - Member admin form collapsed behind '+ MEMBER' button - Removed 'K.10 //' section codes from headers - Shortened labels (PRINCIPALS, TOKENS, 24H/7D/30D/1Y) - Audit log capped at50 entries - Removed 'Bring-your-own-key passthrough is excluded' copy - Removed 'ANALYTICS //' prefix from health badge
AccessGate: - Removed 'A.00 / PRIVATE FREQUENCY' calibration text - Removed 'Friends of PP' header - Changed 'Full-Spectrum Signal Room' to 'Sign in' - Removed 'For the few who know. The charts are nosy.' tagline - Shortened button labels (PASSKEY, CREATE OPERATOR) - Removed signup guidance copy Navigation: - Guests: only STATS - Members: only MY STATS + PASSES - Operators: all7 items (PULSE, INSIGHTS, MY STATS, PASSES, CONSOLE, ACCOUNTS, MODELS)
- Removed calibration codes (J.00, J.10, R.00, A.00, A.01, K.20) - Removed 'SIGNAL INTERRUPTED //' error prefix - Removed 'Full-Spectrum Signal Room' from page title - Removed nav-index 'A.01' from sidebar - Simplified JoinUnavailable: 'Pass unavailable' instead of 'This pass is unavailable.' - Simplified JoinSwitch: shorter copy, 'SWITCH' button - Simplified MemberRecovery: 'Set your password', shorter expiry copy - Console detail: 'SEEN' not 'LAST SEEN', 'VALUE' not 'API-EQUIV', removed NONE expiry placeholder - Console chart: 'USAGE' not '30-DAY HOURLY SHAPE'
MY STATS: - When no clients exist, show 'CREATE FIRST CLIENT' button with guidance instead of requiring user to discover '+ ADD CLIENT' - After creating a client, setup is shown inline automatically PASSES: - When no passes exist, form is shown automatically (no need to click NEW PASS) - Removed 'PASS READY' label and 'Multi-use link. Revokable anytime.' copy from the fresh pass result — the link and copy button speak for themselves
- / now serves the Passport SPA (role-based login), not the friend landing - /friend serves the old friend landing (for Cute Code users who want it) - /cute-code serves the cute code setup page - Added SETUP page back to nav for all authenticated users - SETUP page: client list with inline SETUP buttons, platform tabs, and + ADD CLIENT mint form at the bottom - First-time users see 'CREATE CLIENT' button with guidance
Replaces the hidden SETUP-button-per-card flow with the obvious flow: client pills across the top (default client auto-selected and revealed), tool tabs (CODEX, CLAUDE CODE, GEMINI, GROK, CUTE CODE, PI), and SDK tabs (ANTHROPIC API, OPENAI SDK) with full instructions: - Each CLI tab: install command, automatic one-liner (bash + PowerShell), manual config download - Each SDK tab: base URL + auth cards, Python/TypeScript/curl examples with the client token interpolated, model pill list - + NEW pill mints a client inline and immediately shows its instructions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Codex 0.150.1 could not read account rate limits through the pool proxy. The proxy added pool-specific fields to the upstream
/wham/usageresponse, and app-server failed decoding the response before Jam could receive the weekly window.Change
The Codex-facing usage endpoint now returns only the upstream-compatible
plan_type,rate_limit_reset_credits, andrate_limitfields. Pool diagnostics remain available through the pool-owned surfaces.Validation
go test ./...passed in an isolated worktree.rateLimits.primary.windowDurationMins = 10080.Review focus
Does any supported client depend on the removed pool-specific fields from
/backend-api/wham/usage?