credential-health — is the credential ALIVE, is the record TRUE, and did it leak
Mirrored from the fleet knowledge base: wi/components/credential-health.md
Updated
Mirrored verbatim from
utopia-models/knowledgewi/components/credential-health.mdby the allowlisted publish pipeline. Edit it there, not here.
component: credential-health
serves: all
runs-on: novaserver
adrs: [6154]
owns:
- _infra/scripts/verify-credential-record.sh
- _infra/scripts/verify-no-token-in-argv.sh
- wi/registry/master-token-shape.yaml
- _infra/scripts/probe-logins.sh
- token-health.service
- token-health.timercredential-health — is the credential ALIVE, is the record TRUE, and did it leak
WHAT IT IS
The layer that answers four different questions about a credential, none of which infisical answers:
| question | who answers it |
|---|---|
| is this token still live, and can it be healed without a human? | token-health.service on svc-ops |
| is every agent's Claude login live and on its rule seat? | probe-logins.sh --file, run by the same service (knowledge#10216) |
| does the record of what we hold match what we actually hold? | verify-credential-record.sh · verify-master-token-shape.sh |
| did a credential leak into a world-readable place? | verify-no-token-in-argv.sh |
Its reason for existing is doctrine/credentials.md's forbidden default: an agent writing "I don't
have access" without reading the registry first. That sentence is a claim about the world, and this
component is the set of commands that turn it into a measurement.
🔴 A scope list is a measurement, and this component refuses to store one (#4549). Six hand-maintained
per-brain copies of "what scopes does this token hold" had no writer and aged into fiction at different
rates — one token was recorded with 20 scopes while holding 21, and its cannot: denied two abilities it
had. The registries keep DECISIONS (what a token may hold); the instruments below read the token.
HOW IT WORKS TODAY
flowchart TD
subgraph runtime["runtime — nova only"]
T["token-health.timer (hourly)"] --> S["token-health.service<br/>~/.claude/scripts/token-health.sh --auto"]
S --> A["TTL check -> auto-heal from the durable<br/>Infisical token -> batched blocked:tyler<br/>ONLY on genuine dead auth"]
S --> P["probe-logins.sh --file<br/>every agent: HTTP + seat (org id) + 7d<br/>-> one board issue per dead/off-rule agent,<br/>closed when it grades ok"]
end
subgraph session["every master, every session"]
H["SessionStart hook<br/>plugin -> sessionstart-capabilities-inject.sh"] --> C["capabilities.sh --inject<br/>live-probed access, not a note"]
end
subgraph ondemand["on demand — the in-repo instruments"]
R["verify-credential-record.sh"] --> V["registry vs the live vault"]
M["verify-master-token-shape.sh"] --> X["each token's OWN x-oauth-scopes"]
N["verify-no-token-in-argv.sh"] --> L["ps from a SECOND unix user"]
end
V --> Y["wi/registry/master-token-shape.yaml<br/>fleet_github_tokens: — the ONE inventory"]
X --> YThe runtime half is one box, not the fleet. Measured this session with
bash _infra/scripts/mechanism-liveness.sh token-health.sh: token-health.sh is on disk on nova only
and is driven by token-health.service; win, dust, cloud, sf and agent have neither the script nor the
unit. It heals nova's own credential and escalates only on genuine dead auth.
The login detector covers every agent (knowledge#10216). The same hourly token-health.service (on svc-ops
since #9201) then runs probe-logins.sh --file: for each novaserver agent in wi/registry/organization.yaml it
sends one 5-token haiku call with the agent's own token (read and handed to curl on stdin inside that user's
shell, via ssh nova@… + sudo -n -u; an agent probing itself runs in its own shell with no hop, knowledge#10445), and grades HTTP code and anthropic-organization-id against Tyler's
rule — axes.is_master agents on nova@ (05fc1756…), every other agent on tyler@ (62f6acd0…), service_users
with no login. A 401 on an expired access token whose refresh token exists is not graded DEAD yet: the probe starts
one fresh claude as that agent (which refreshes on start) and re-probes, and grades DEAD only if that fails
(knowledge#10686). An HTTP 429 is a live login, not a dead one: the token authenticated and named its seat before the quota refused, so it is graded on its seat like a 200 (detail rate-limited, login live) — DEAD is any other non-200 (knowledge#10872). Each dead or off-rule agent gets ONE open issue titled [login-detector] <agent>: … (found by
that title on the live board, so nothing is stored), lane = agent (the Architect runs the login runbook;
masters never stage a login — Tyler, 2026-10-25, knowledge#10215), parented under
the lowest standing-hygiene Feature with room (GitHub caps a parent at 100 sub-issues). An agent that grades
ok has its issue commented and closed. Read it by hand: bash _infra/scripts/probe-logins.sh (one line per
agent: seat, want, HTTP, 7d, verdict — no token text); --tsv prints the same grading machine-readable (agent, verdict, http, 7d, seat, status), which dispatch.sh reads to call an HTTP 401 login-expired (no reset time) instead of showing the account's weekly reset (#10774). probe-logins.sh --whoami is the network-free half: the
account, tier, plan and credentials state each user holds right now, read from its own files (knowledge#10399).
The session half is the one that actually reaches every master. capabilities.sh --inject runs at
SessionStart on win, nova, dust, cloud and agent. sf has neither.
🔴 Corrected 2026-09-08 (#7696): its output is a CACHE THAT PRINTS ITS OWN AGE, not a live probe, and
that is the fix rather than a regression. The injecting hook is registered with a 15s timeout; the old
--inject ran stale && probe inline over six network calls, and a hook that times out injects
NOTHING — silence indistinguishable from a healthy session. It also made any downstream age warning
dead code, because probe() rewrote the cache before anything could stat it. --inject now prints
the manifest with probed <ts>, NhMMm ago, says so out loud when that exceeds 6h, and spawns a
detached re-probe. Doctrine asks for exactly this: "make it an uncached live read, or make it print
its own age."
And the rows themselves changed meaning. Each is now EXERCISED against the API that owns the
capability, and each records that owning system. The previous set answered questions about local state
and reported them as access: nats_bus said YES for a bus deleted 2026-07-23 (it tested whether a seed
FILE resolved), vercel said YES off a string-length check that never called Vercel, and higgsfield
said NO off hf auth token while the API returned 200 for the vaulted key pair in the same minute.
There is a third status now — ? UNTESTED, meaning the probe could not RUN here — because reporting
"no access" for a missing local binary is the false-blocked conclusion this whole layer exists to
prevent.
The record half is in this repo, and it is deliberately assertion-shaped.
master-token-shape.yaml's fleet_github_tokens: block carries a population_rule, a population_source,
a dated measured: line that says of itself "this line is a MEASUREMENT and it rots", and two verify:
fields naming the commands that answer the question today.
The leak half is verify-no-token-in-argv.sh, whose whole point (ADR-6154) is that --box-scan must
tell a credential apart from a search for one — the scanner's own grep sits in the same process table
it reads.
BOUND VALUES
- ✅
_infra/scripts/verify-credential-record.sh - ✅
_infra/scripts/verify-master-token-shape.sh - ✅
_infra/scripts/verify-no-token-in-argv.sh - ✅
wi/registry/master-token-shape.yaml - ✅
_infra/scripts/verify-credential-record.sh— still called bywi/registry/master-token-shape.yaml - ✅
_infra/scripts/verify-master-token-shape.sh— still called bywi/registry/master-token-shape.yaml - 🔴
credential-health— no such row inwi/registry/components.yaml
DETERMINE CURRENT STATE
Five measurements and one liveness read; none of them consults a stored scope list:
# the record vs the live vault
bash _infra/scripts/verify-credential-record.sh
# every master token's own scopes, from GitHub
bash _infra/scripts/verify-master-token-shape.sh
# no credential on any argv, read as a different unix user
bash _infra/scripts/verify-no-token-in-argv.sh --box-scan
# Google Workspace access, end to end
bash ~/.claude/scripts/google-cred-healthcheck.sh
# where each piece actually runs
bash _infra/scripts/mechanism-liveness.sh token-health.sh capabilities.sh google-cred-healthcheck.sh
# every agent's Claude login: seat, HTTP, 7d use (no token printed)
bash _infra/scripts/probe-logins.shKNOWN BROKEN
- 🔴
google-cred-healthcheck.shis present on three boxes and wired on none.bash _infra/scripts/mechanism-liveness.sh google-cred-healthcheck.shthis session: on disk underscriptson win, nova and cloud; absent on dust, sf and agent;WIRED-INis-on all six. Its own header says "Run in preflight + the proactive audit" — nothing runs it. It passes when invoked by hand, which is exactly the present-and-dead shapemechanism-liveness.shwas written to expose: wire it or delete it, but do not leave it claiming a preflight it is not part of. - ⚠ Healing is still one box; DETECTION is every agent.
token-health.sh's auto-heal and batched escalation cover the three Linux masters' TTL only. A dead or off-seat login on any agent is now filed within the hour byprobe-logins.sh --file(knowledge#10216) — first run 2026-10-25 filed win and nova (on tyler@, rule nova@) and dust (empty accessToken). - ⚠
sfis outside the session half too.capabilities.shis neither present nor wired onsf, so the one always-on agent starts with no probed access picture. - ⚠
credential-registry.yaml— the file doctrine tells every agent to read FIRST — is gitignored and per-brain. It lives at~/.claude/config/credential-registry.yamlin each brain repo, so there are as many copies as there are agents and nothing reconciles them. The in-git half (master-token-shape.yaml) is the only copyverify-credential-record.shcan grade. 🔴 Measured 2026-09-08: it is worse than divergent — on this box it is the ONLY readable copy.wc -l /home/{win,nova,cloud,dust}/.claude/config/credential-registry.yamlreturns 314 lines forwinand unreadable/absent for the other three, and win's copy still recordsCF_API_TOKEN_UTOPIAas🔴 DEAD/REVOKED — verified 2026-07-12for a token that returned HTTP 200 on 2026-09-08. Doctrine also cites it aswi/registry/credential-registry.yaml; there is no such file in this repo. What a credential OPENS moved into Infisical's ownsecretMetadataunder #7694 for exactly this reason —infisical-get.sh --usage/--capabilities, written from the one committed sourcewi/registry/capability-map.yaml. Readingstatus:out of the per-box registry answers "what did some box record whenever someone last edited it", never "is this credential live"; the capability's ownprobe:answers that, now. - ⚠ There is no
credential-healthrow incomponents.yaml, so this component appears on no registry surface and its one unit is in no sweep. - ⚠
verify-master-token-shape.shis partitioned toagent-master, not here. It landed in that doc'sowns:first and a thing belongs to exactly one component, so it is named in this doc's probes and not in itsowns:. If the boundary is re-drawn, move it — do not list it twice.