feat(observability): structured logger + authmux diag (X3)#32
Merged
Conversation
Theme X3 (Observability v1) from docs/future/17-ROADMAP.md.
- src/infra/log/logger.ts: zero-dep structured logger with
debug/info/warn/error levels. Default human single-line on stderr;
AUTHMUX_LOG=json switches to JSON-lines. AUTHMUX_LOG_LEVEL filters.
child({correlationId}) injects an ID into every event;
newCorrelationId() returns a 16-hex string. An in-memory ring buffer
keeps the last 200 JSON events for diag.
- Daemon evaluation cycles emit paired daemon.cycle.start /
daemon.cycle.end events with a shared correlation id, action, and
duration (no auth bytes).
- src/commands/diag.ts: new "authmux diag" command writing
authmux-diag-<ts>.tgz to cwd. Bundle contains version, node, platform,
paths, accounts dir listing (filenames + sizes + mtimes ONLY — never
contents), allowlisted env, and the last 200 log lines. Env table is
allowlist-only (CODEX_AUTH_*, AUTHMUX_*, plus PATH/HOME/SHELL/TERM/
NODE_ENV/...); credential-shaped suffixes (_TOKEN/_KEY/_PASSWORD/
_SECRET/_COOKIE) are filtered even if the prefix matches. HOME's
literal value never appears — only its length stand-in.
- src/tests/logger.test.ts and src/tests/diag-redaction.test.ts:
ring buffer, correlation IDs, JSON line shape, and the leak-guard
proving OPENAI_API_KEY / MY_TOKEN / DB_PASSWORD / *_SECRET / *_KEY
never reach the output while CODEX_AUTH_DEBUG / AUTHMUX_LOG do.
Redaction list (never in bundle): auth.json, snapshot file contents,
any env name matching the FORBIDDEN_SUFFIXES list, raw HOME value.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Theme X3 — Observability v1: structured logs +
authmux diag.Reference:
docs/future/17-ROADMAP.md(Next horizon, Theme X3).Summary
src/infra/log/logger.ts— zero-dep structured logger.info/warn/error/debug. Default = human single-line on stderr;AUTHMUX_LOG=jsonswitches to JSON-lines.AUTHMUX_LOG_LEVELfilters.logger.child({correlationId})returns a child logger that injects the id into every event.newCorrelationId()returns a hexcrypto.randomBytes(8)string. In-memory ring buffer keeps the last 200 JSON events forauthmux diag.auto-switch/policy.tsnow emit paireddaemon.cycle.start/daemon.cycle.endevents sharing one correlation id. End event includesaction(noop/switched/error),ms, and eitherreasonorfrom/to.src/commands/diag.ts— newauthmux diagcommand. Writesauthmux-diag-<ts>.tgzto cwd containingsummary.txt,bundle.json, andlog-tail.jsonl. Bundle includes authmux version, node, platform, lazily-resolved paths, accounts dir listing (filenames + sizes + mtimes ONLY — never contents), allowlisted env, and the last 200 ring-buffer log lines.Exit criteria
src/infra/log/logger.tsexports aloggerwithinfo/warn/error/debugmethods, no transitive deps.authmux diagwritesauthmux-diag-<ts>.tgzto cwd containing version, env table (filtered),~/.codex/accounts/listing (no contents), the last 200 log lines.auth.jsonor snapshot bytes.Redaction allowlist
Snapshot bytes,
auth.jsoncontents, and registry/sessions contents arenever read by
diag. The accounts dir listing comes fromfsp.readdir+fsp.statonly.Verification
Tarball layout:
Test plan
npm run buildcleannpm test— 135/135authmux diagwrites a.tgzto cwdauthmux diag --print-envdoes not leakOPENAI_API_KEYorMY_TOKENdiag-redaction.test.tsasserts the leak guardlogger.test.tsasserts ring buffer cap of 200 and correlation IDs