The server turns Cacheboard from a manual/browser-only page into the Docker-backed local multi-account metrics Dashboard. It serves the card UI, protects provider access behind one bearer token, reads account-scoped Claude data, and projects the verified signed Codex snapshot published by the Windows Orchestrator. The Dashboard does not run Codex or receive a Codex credential path.
The universal Claude/Codex controller is the separate Windows-local orchestrator/ Hub on 127.0.0.1:8790. The ordinary one-click launcher starts and verifies both layers together, establishes the signed Dashboard browser session, and follows the same bounded one-time bridge into Orchestrator as the primary experience. The original Dashboard remains available through Orchestrator's reciprocal Dashboard link, while -NoOrchestrator intentionally opens the metrics-only Dashboard. Neither bridge direction exposes DASHBOARD_TOKEN or provider credentials to the controller. See the high-level feature overview and implemented control-plane map.
The eight intended local provider profiles—four Claude and four Codex—were enrolled and returned identity-verified plan/activity data by 2026-08-10. The shared stable IDs are earl, bbpyderz, ehayestrainer, and claude; claude is verified as claude@bigbwain.com on both providers. server/.env and provider credentials remain machine-local and must never be committed. Re-run the health and route checks below before relying on that receipt after provider, credential, image, or configuration changes.
On Windows, from the repository root:
Copy-Item server/.env.example server/.env
$earlEmail = Read-Host 'Exact email for earl'
$bbpyderzEmail = Read-Host 'Exact email for bbpyderz'
$trainerEmail = Read-Host 'Exact email for ehayestrainer'
$claudeEmail = Read-Host 'Exact email for claude'
.\server\setup-claude-profiles.ps1 -Accounts "earl=$earlEmail","bbpyderz=$bbpyderzEmail","ehayestrainer=$trainerEmail","claude=$claudeEmail" -SkipRestart
.\server\setup-codex-profiles.ps1 -Accounts "earl=$earlEmail","bbpyderz=$bbpyderzEmail","ehayestrainer=$trainerEmail","claude=$claudeEmail"Codex setup accepts only a subset of those four fixed IDs. It acquires the
shared setup mutex and requires port 8790 to be proven closed before it
resolves Codex, creates or changes a profile, or invokes the provider. Run it
only in a deliberate stopped-Orchestrator window, normally before starting
Cacheboard after Windows sign-in. An open or unknown listener is left untouched;
never terminate it by PID merely to make setup continue.
Set DASHBOARD_TOKEN in server/.env. For normal Windows use, the one-click
launcher starts the container, waits for health, and opens an authenticated
browser session:
.\server\start-cacheboard.ps1Install or repair the ordinary Desktop shortcut from the current checkout with:
.\server\install-desktop-launcher.ps1The generated Start Cacheboard.cmd forwards only options supplied by the
person launching it. It never makes -SkipClaudeRecovery the default, so an
ordinary double-click first tries the saved Claude refresh credential and can
guide exact-email browser reauthentication only when that credential is not
locally usable. The same integrated start prepares the Codex metrics bridge,
starts or safely reuses the sole Windows writer, and reports typed exact-account
Codex repair guidance without opening provider login automatically.
When an already-running Orchestrator has a different artifact identity, normal
startup requests a graceful refresh only if that broker is the authenticated
exact owner, is idle, and advertises
/healthz.lifecycle.contract: cacheboard-orchestrator-lifecycle-v1 with
restart: graceful. Pass -NoRuntimeRefresh to disable that request; a stale
broker is then left untouched with concise next-step guidance. Busy, unowned,
and legacy brokers fail closed the same way. The launcher does not print raw
structured receipt data and never falls back to Stop-Process, taskkill, or a
forced replacement; after an accepted refresh it waits for the old PID, port
8790 listener, and owner lock to close before starting the current artifact.
See the runtime identity boundary
for the exceptional owner-verified legacy recovery path.
Before opening Cacheboard, the launcher checks authenticated /health. If an
exact-email-configured Claude plan credential is expired or not ready, it runs
isolated setup one account at a time. A signed native Claude Code 2.1.233+
executable first exchanges a locally usable saved refresh credential in an
owner-only staging profile; the result is promoted only after first-party
status returns the configured exact email. A locally unusable refresh state
(for example a missing, expired, invalid, or incomplete credential)
selects the guided browser flow. Any ambiguous provider nonzero,
timeout, or transport failure preserves live bytes and stops with retry plus
explicit -ForceLogin guidance instead of silently opening a browser. A wrong
identity or failed post-restart readiness check stops startup instead of
guessing or opening a misleading dashboard. Recovery uses the exact host root
from CLAUDE_PROFILES_HOST_DIR; it never writes to a guessed profile location.
The launcher passes -RefreshOnly -SkipRestart; this credential-only mode
rejects missing or mismatched .env paths, email mappings, or profile metadata
before invoking Claude. Ordinary setup does not use -RefreshOnly and still
creates or repairs those mappings when an existing credential is already ready.
Use -SkipClaudeRecovery only for
an intentional offline/stale-data launch; Codex profiles are not changed by
this Claude recovery pass. Codex saved-credential refresh and exact-email reads
belong to the separately started Windows Orchestrator and its pinned app-server.
If Docker's Linux engine is not reachable, the launcher first uses Docker
Desktop's supported docker desktop start command when available, then falls
back to the installed Desktop executable. It waits up to three minutes and
reports the active Docker context, Desktop/backend process presence, and
Desktop status without changing Docker settings. Keep Docker Desktop visible
so a first-run license, WSL update, or recovery prompt can be completed. Normal
one-click startup still fails rather than silently returning a partial product.
For deliberate continuity while repairing Docker, rerun
Start-Cacheboard.cmd -OrchestratorOnlyIfDockerUnavailable: it starts the local
broker, uses its loopback-only bearer exchange to create the same short-lived
one-time browser ticket, and clearly reports the Dashboard, provider usage
cards, Dashboard bridge, and container-backed provider readings as unavailable.
This is an explicit degraded Orchestrator-only mode, not a successful start of
the full Cacheboard product. Controller features that depend on current
Dashboard capacity readings remain stale or unavailable until Docker is healthy
again.
The launcher sends DASHBOARD_TOKEN only in the authorization header of a
loopback request. Cacheboard exchanges it for a random 60-second, single-use
bootstrap path bound to one exact destination, then sets a 30-day
HttpOnly; SameSite=Strict session cookie. Normal startup redirects through
/auth/orchestrator; -NoOrchestrator redirects to the Dashboard. The
dashboard token is never placed in a URL or printed.
The visible Orchestrator link targets the authenticated same-origin
/auth/orchestrator bridge. The server uses its configured token to request a
separate one-time Orchestrator ticket over the fixed loopback boundary, then
redirects the browser only to that bounded ticket path. After consumption,
Orchestrator delivers its own signed exact-origin session once in a URL fragment;
its client immediately moves the value to origin-scoped sessionStorage, clears
the fragment, and uses separate purpose-bound SSE tickets. Neither bearer token
enters HTML, browser JavaScript, logs, or a URL.
Orchestrator has its own persistence contract. Its local queued-action vault
encrypts pending local provider prompts/action payloads at rest, but its remote
Host Fabric stores bounded remote managed launch/follow-up prompts and
non-secret question answers as plaintext JSON command payloads in broker SQLite
history. The launch UI does not derive a title from the prompt; its separate
optional operator-entered chat title is
limited to 200 characters and persists as plaintext session metadata. Do not
put credentials, secrets, or unrestricted transcript bodies into remote prompts
or answers, or sensitive text into titles. That Fabric retention is documented
in the Host Agent guide;
it is not Dashboard credential storage.
-NoBrowser starts and verifies Cacheboard without minting a ticket or opening
a browser. Browser bootstrap is disabled whenever the effective published bind
is not loopback; use bearer authentication behind an authenticated HTTPS
reverse proxy for intentional LAN access.
For a degraded Dashboard-only diagnostic without opening a browser:
docker compose -f server/docker-compose.yml up -d --build
docker compose -f server/docker-compose.yml logs --tail 100 dashboardRaw Compose does not prepare or validate the protected host metrics bridge and
does not start the Windows Orchestrator. Unless a previously prepared bridge is
deliberately supplied, all four Codex rows are orchestrator_unavailable. Use
the repository launcher for the supported complete-product startup.
The default URL is http://127.0.0.1:8787. Compose binds to loopback even though Node listens on 0.0.0.0 inside the container. Change CACHEBOARD_BIND only if LAN access is intentional; use a reverse proxy with HTTPS for untrusted networks.
The image uses the digest-pinned Node 22 runtime on Debian with CA certificates for its remaining HTTPS integrations. It contains only the Dashboard server, the snapshot reader, the shared normalization/verification contract, and runtime-identity inputs; it has no Codex package, executable, bootstrap, credential mount, or provider writer. It does not force public DNS, so LAN name resolution follows Docker/host configuration. CACHEBOARD_HOST_PORT changes the host-side port; the container's internal PORT remains 8787. When the host port changes, update ALLOWED_ORIGINS to the same exact browser origin/port or authenticated browser calls will be rejected by CORS.
Stable account IDs use lowercase letters, numbers, and underscores. IDs select data; labels never do.
On Windows, setup and startup apply a fail-closed owner-only ACL to server/.env and the managed Claude/Codex credential roots and files without reading their contents. Inheritance is removed; only the current user, SYSTEM, and BUILTIN\Administrators receive FullControl, with child inheritance only on directories. Existing links, junctions/reparse points, access-denied ancestors, and path escapes are rejected rather than followed. Claude's configured profile root may also contain an unrelated ordinary sibling directory left by an older/manual Claude setup. Cacheboard does not treat that directory as an identity or traverse it during configured-identity validation, so it cannot strand startup. A configured identity that is not a real directory, any link/reparse point at the root, or any link/escape inside a configured identity still fails closed before credential setup.
In either setup script, earl=person@example.test supplies an expected identity and hard-fails if the provider authenticates a different address. earl=Friendly Label supplies only cosmetic text. The same verified provider email cannot populate two IDs, including persisted mappings, and a shared Claude/Codex ID cannot resolve to different emails.
Preferred variables for account earl:
CLAUDE_ACCOUNTS=earl
CLAUDE_PROFILE_EARL=/profiles/claude/earl
CLAUDE_CREDENTIALS_FILE_EARL=/profiles/claude/earl/.credentials.json
CLAUDE_PROJECTS_DIR_EARL=/profiles/claude/earl/projects
CLAUDE_PROFILE_METADATA_EARL=/profiles/claude/earl/.cacheboard-profile.json
CLAUDE_EMAIL_EARL=exact-verified-email
CLAUDE_LABEL_EARL=EarlCLAUDE_PROFILE_<ID> is a convenience root that derives the credential, project, and metadata paths. Explicit paths take precedence. Metadata must be <profile>/.cacheboard-profile.json with:
{
"accountId": "earl",
"provider": "claude",
"email": "exact-address-returned-by-claude",
"verifiedAt": "2026-08-09T00:00:00.0000000Z"
}The setup script produces this only after claude auth status --json confirms the exact email. It stores no token. CLAUDE_CREDENTIALS_FILE plus CLAUDE_PROJECTS_DIR remains an explicit unnamed single-account fallback. Named cards always require ?account= and do not silently fall back.
Cacheboard performs supported Claude Code refresh-token exchange first through
a signed native Claude Code 2.1.233+ executable, then verifies logged-in,
first-party status and the configured exact email before atomic promotion. It
does not infer provider error classes from CLI text or silently fall back to a
browser after an ambiguous failure. When browser repair is required or an
owner explicitly wants replacement, use only the transactional setup
script with an exact mapping, for example
setup-claude-profiles.ps1 -Accounts "earl=person@example.test" -ForceLogin.
Do not point Claude's login command directly at a live Cacheboard profile: the
setup script signs into a staging profile, verifies the returned email, and
only then promotes the credential. It restores the prior credential, metadata,
and .env byte-for-byte if login, validation, persistence, or restart fails. A
newly written bearer is revision-keyed, so it does not inherit a rejected
previous bearer's 180-second failure cooldown.
Windows Orchestrator is the sole active Codex credential writer. The fixed
profiles derive only from CODEX_PROFILES_HOST_DIR plus the stable ID. Setup
writes the protected host root and exact per-ID email/label mappings; legacy
global or per-ID home overrides fail closed instead of selecting another
credential authority.
Preferred variables:
CODEX_PROFILES_HOST_DIR=C:/Users/you/codex-profiles
CODEX_EMAIL_EARL=exact-verified-email
CODEX_LABEL_EARL=EarlEach profile remains an ordinary owner-protected directory such as
%USERPROFILE%\codex-profiles\earl. The Orchestrator uses the pinned official
app-server to read the current ChatGPT identity, perform supported
saved-credential refresh when required, verify the configured exact email, and
collect rate-limit and usage data. An exact signed-in email mismatch fails
closed; metadata, directory names, labels, and plan type never choose an
identity.
The broker atomically publishes one bounded HMAC-authenticated
codex-metrics.v1.json snapshot into the protected
%LOCALAPPDATA%\Cacheboard\Orchestrator\dashboard-bridge directory by default.
The launcher exports that ordinary directory as
CACHEBOARD_CODEX_METRICS_BRIDGE_DIR; Compose mounts it read-only at
/bridge/codex. The snapshot contains exactly earl, bbpyderz,
ehayestrainer, and claude in that order. It contains normalized readings and
identity evidence, never credentials or the HMAC key.
The Dashboard reader opens the exact ordinary single-link file, bounds the read,
verifies stable file custody, HMAC, schema, fixed order, and signed lifetime,
and rejects an observed unsafe, invalid, or older replacement immediately. A
previously verified in-memory generation may be reused only for a missing or
transiently unavailable file while that signed generation remains unexpired.
Missing, invalid, or expired bridge custody is exposed as
orchestrator_unavailable; configured-email mapping drift is
temporarily_unavailable, never an identity mismatch. Only a signed record that
proves a different provider email is identity_mismatch.
Normal startup accepts ready records plus the typed unavailable reasons
credential_expired, credential_unavailable, refresh_rejected,
identity_mismatch, and temporarily_unavailable. Only the first three are
browser-required states, and the launcher prints a setup command bound to the
exact fixed ID and configured email. It never invokes that command. Identity
mismatch, Orchestrator absence, missing configured email, and ambiguous or
temporary failures do not recommend or open provider login.
For an explicitly typed browser-required account, first establish a verified
stopped-broker window, then run the exact printed
setup-codex-profiles.ps1 -Accounts "<id>=<email>" -ForceLogin command. Setup
verifies the exact provider identity before retaining the protected Windows
profile and metadata. It has no restart, Docker, or runtime-replacement path.
The historical Docker Codex volume remains sensitive dormant rollback custody.
It is declared but unmounted and is never an implicit fallback or automatic
reactivation path. A future owner-reviewed rollback must deliberately stop the
Windows writer and transfer credential authority before mounting it. Do not run docker compose -f server/docker-compose.yml down -v; it would delete both active Dashboard state and this retained dormant custody.
Strict identity is mandatory for Codex; there is no unverified mode. Claude's separate temporary migration gate never overrides an actual email mismatch.
Claude identityVerified means the current configuration agrees with setup-time metadata created from claude auth status --json; it is not continuous provider-side proof. Rerun setup-claude-profiles.ps1 after any Claude sign-out, login change, or manual reauthentication. Codex identity and readings are refreshed by the Windows broker before it publishes the corresponding signed snapshot generation; the Dashboard performs no provider request.
All API routes except /healthz require either Authorization: Bearer <DASHBOARD_TOKEN> or the signed browser session cookie created by the one-click
launcher. Bearer authentication remains compatible with scripts and configured
CORS origins. Session cookies are HMAC-signed with DASHBOARD_TOKEN, checked
for tampering and expiry, survive server restarts, and are invalidated when the
dashboard token changes. Ticket minting and browser-session cookie acceptance
are loopback-only; ticket minting always requires bearer authentication.
| Route | Purpose |
|---|---|
GET /healthz |
Public process liveness only: { "ok": true } |
POST /auth/bootstrap |
Loopback-only, bearer-authenticated minting of one short-lived browser bootstrap path |
GET /auth/bootstrap/<ticket> |
Consumes the ticket once, sets the signed HttpOnly session cookie, and redirects to its exact minted destination (/ or /auth/orchestrator) |
GET /auth/orchestrator |
Requires the signed Dashboard browser session, mints a bounded one-time Orchestrator ticket server-side, and redirects only to http://127.0.0.1:8790/auth/ticket/<ticket> |
GET /health |
Authenticated provider inventory and per-account readiness/identity details |
GET /usage/claude-plan?account=<id> |
Claude subscription windows and reset times |
GET /usage/claude-code?account=<id>&tzOffsetMin=<n> |
Claude Code transcript activity for today/week/month/all |
GET /usage/codex-plan?account=<id> |
Codex rate-limit windows, credits, and plan type |
| `GET /usage/codex-usage?account=&period=today | week |
* /proxy/<provider>/<path> |
Strict allowlisted provider proxy |
POST /token/<provider>/refresh |
OAuth refresh for configured providers |
POST /token/fitbit/seed |
Loopback-only handoff of Fitbit's rotating refresh token, bound to the verified Fitbit user ID |
GET /security/<check> |
Named self-assessment against targets fixed in .env |
The plan endpoints normalize provider windows into series entries with used, totalLimit: 100, unit: "%", and reset metadata. Codex activity returns both tokens and used for the selected period, plus totals and dailyUsageBuckets. It intentionally returns no subscription token ceiling; the UI keeps the user's configured target.
The public Codex DTOs remain compatible with the former Dashboard collector.
The HTTP wrapper still adds source followed by tookMs; successful snapshot
projections retain cached followed by cacheAgeMs in addition to the existing
plan or usage fields. /health retains the four ordered
codexAccountDetails, and /usage/codex-plan plus /usage/codex-usage retain
their existing success shapes. Typed unavailable routes fail without exposing a
bridge path, signature, provider payload, or credential detail.
/health also adds the versioned, server-owned aiLaneDirectory projection:
{
"contract": "cacheboard-ai-lane-directory-v1",
"lanes": [{
"laneKey": "earl:claude",
"identityId": "earl",
"provider": "claude",
"expectedEmail": "earl@example.test",
"verifiedEmail": "earl@example.test",
"identityState": "verified",
"reasonCode": null,
"capacity": { "authority": "allowed", "reasonCode": null },
"activity": { "authority": "allowed", "reasonCode": null }
}],
"providerIssues": []
}The projection always contains exactly eight rows: Claude rows for earl,
bbpyderz, ehayestrainer, and claude, followed by Codex rows in the same
frozen identity order. A missing fixed row remains present and blocked; labels,
plan names, directories, and browser input never create or select a lane.
identityState is limited to verified, unverified, mismatch, or
unavailable. A lane or reading reason is either null or one of
configuration_unavailable, contract_unavailable, identity_unverified,
identity_mismatch, credential_expired, credential_unavailable,
refresh_rejected, orchestrator_unavailable, temporarily_unavailable,
capacity_unavailable, and activity_unavailable.
providerIssues is bounded attention metadata within this same fixed shape:
each item can contain only provider claude or codex plus reason
contract_unavailable. It never contains an upstream message. The directory
does not expose credentials, native errors, profile paths, prompts, provider
payloads, raw output, or the signed-snapshot HMAC. The legacy account arrays and
detail DTOs remain available unchanged for existing consumers.
This health projection states current identity and reading authority only. A successful health response never refreshes a meter, changes its measurement timestamp, clears its route error, or makes a retained Capacity or Activity reading current.
The browser treats connection truth and measurement truth as orthogonal. Its
persistent compact Dashboard connection state is loading, ready,
auth_required, or unavailable. ready means only that the authenticated
health response and versioned eight-row directory validated; it does not mean
that every lane or meter is readable. A missing/expired browser session remains
visibly auth_required. Backend or contract failure reports the typed compact
connection failure without inventing a readable-lane count.
Every lane's Capacity and Activity presentation independently records:
- intent:
enabledorhidden; - authority:
allowedorblocked; - availability:
available,unavailable, ornot_requested; - freshness:
current,stale, ornever_measured; - one bounded reason code; and
- nullable measurement/stale timestamps plus existing window/reset provenance.
The authenticated fixed eight-lane directory and this per-reading model remain the internal source of identity, authority, availability, and freshness truth. They are not rendered as a second Account readiness matrix. The two canonical Claude and Codex provider overview cards are the visible capacity/activity surface: together they retain every configured lane reading, window, reset, value, freshness, and bounded status without creating one duplicate card per lane.
Metric-card status chrome is actionable-only. It stays absent when the visible cards are healthy and appears as one compact native disclosure only when cards need attention. Attention is the total actionable set; error and stale controls are labeled as overlapping subsets and keep their established filter keys. Count and pressed-state updates patch stable nodes in place so background refresh does not replace the disclosure, its open state, or a still-visible focused control. If a focused subset reaches zero, focus moves to the connected status summary and an empty subset filter reconciles to Attention while other actionable cards remain. If the last actionable count reaches zero, focus moves to the visible All filter and the view reconciles to All before the status section hides. No hidden control remains focused or selected as invisible filter truth.
Health success changes only connection and lane authority. A prior meter value, timestamp, route error, series, and history remain untouched until that exact meter succeeds. If connection health later fails, retained provider-overview measurements remain measurement evidence and are labeled stale through their existing typed source state; rendering does not clear or rewrite the underlying measurement object.
Lane and meter reasons pass through a fixed copy allowlist; an unknown reason renders only Reading unavailable. Raw identity errors, provider output, credential text, backend bodies, paths, tokens, and payloads are never used as visible status copy. Ordinary loading/ready transitions use a polite status announcement, while each new authentication/backend failure transition uses a once-only alert; repeated renders of the same state do not reannounce it.
This presentation changes neither provider calculations nor the existing % used · % left, Activity, history, or reset semantics. Provider-free fixtures
do not prove parity with the visible ChatGPT application; that comparison still
requires the same exact account, window, timestamp, and bucket.
$headers = @{ Authorization = 'Bearer YOUR_DASHBOARD_TOKEN' }
$health = Invoke-RestMethod http://127.0.0.1:8787/health -Headers $headers
$health.claudeAccountDetails | Format-Table name,expectedEmail,identityVerified,mismatch,ready
$health.codexAccountDetails | Format-Table name,expectedEmail,identityVerified,mismatch,ready
Invoke-RestMethod 'http://127.0.0.1:8787/usage/claude-plan?account=earl' -Headers $headers
Invoke-RestMethod 'http://127.0.0.1:8787/usage/codex-plan?account=earl' -Headers $headers
Invoke-RestMethod 'http://127.0.0.1:8787/usage/codex-usage?account=earl&period=week' -Headers $headersDo not treat a card as correctly mapped until health reports the expected email, identityVerified: true, mismatch: false, and ready: true.
| Symptom | Action |
|---|---|
Codex credential_expired, credential_unavailable, or refresh_rejected |
Use only the exact ID/email setup command printed by the launcher, after proving port 8790 is closed. The launcher never opens login automatically. |
Codex identity_mismatch |
Stop. Inspect the signed actual/expected identity and correct that exact Windows profile during an owner-approved stopped-broker setup window; do not relabel it or infer login from a directory. |
Codex orchestrator_unavailable |
Repair/start the exact Orchestrator and protected signed bridge. Do not reauthenticate a provider to repair absent, invalid, or expired snapshot custody. |
Codex temporarily_unavailable |
Retry the ordinary launcher and inspect broker/provider diagnostics. Ambiguous transport or configured-email mapping drift never opens or recommends login. |
| Claude 401/403 | Reauthenticate the isolated Claude profile; setup-token is not a valid replacement |
| Claude 429 | Preserve the script-generated claude-code/<version> user agent and wait for the per-account 180-second cache window |
| Startup reports an Orchestrator runtime identity mismatch | Rerun the normal launcher to permit its bounded graceful refresh. Use -NoRuntimeRefresh only when you intentionally want to leave the stale broker untouched and receive concise guidance. Never terminate a process by PID alone. |
| Orchestrator refresh is refused or does not finish | Active work, uncertain ownership, or a broker without cacheboard-orchestrator-lifecycle-v1 is intentionally not replaced. Preserve it and follow the owner-verified recovery boundary; do not use a force-kill fallback. |
| Empty Claude activity | Confirm CLAUDE_PROJECTS_DIR_<ID> points to that profile's projects directory |
| Activity percentage seems wrong | The provider gives usage, not a token ceiling; edit the card's planning target |
Claude plan failures are throttled by credential identity for at least 180 seconds and honor longer upstream Retry-After values. If a prior successful reading exists, the route returns it explicitly marked stale with refreshError and retryAt; the dashboard displays that fallback without treating it as a fresh reading.
Launcher recovery helpers are covered separately so they can be validated without opening provider login windows:
powershell -NoProfile -ExecutionPolicy Bypass -File .\server\startup-auth.test.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\server\startup-docker.test.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\server\setup-claude-transaction.test.ps1
node --test .\server\claude-plan-throttle.test.mjsOpenAI API billing requires an organization Admin API key in OPENAI_API_KEY; normal project keys cannot read organization costs. Provider OAuth refresh, a strict generic proxy, and passive checks (port-drift, tls-expiry, http-headers) remain supported. Fitbit's browser flow can seed its refresh token only while Cacheboard is loopback-bound. That durable refresh state is bound to one verified Fitbit user ID; a different profile is rejected instead of silently replacing or reading the first profile. Targets and secrets come only from .env; callers cannot choose arbitrary scan targets or proxy hosts.
The official Codex app-server protocol used only by the Windows Orchestrator is documented in the OpenAI Codex repository. Claude plan collection is deliberately isolated and documented in PLAN-USAGE-SEAM.md because its endpoint is not a public contract.