feat(config): add global config fallback with documented precedence#60
Open
dark-sorceror wants to merge 7 commits into
Open
feat(config): add global config fallback with documented precedence#60dark-sorceror wants to merge 7 commits into
dark-sorceror wants to merge 7 commits into
Conversation
There was a problem hiding this comment.
All reported issues were addressed across 18 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
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.
Summary
Fixes #53
Credentials were project-local only:
traceroot loginwrites./.traceroot/config.jsonrelative to the current working directory, and discovery read exactly that path — no fallback. Running any command from a different directory (even a subdirectory of the same repo) silently "logged you out," reportingNo API key foundwith no hint that the user was, in fact, logged in one directory over.This adds a global (per-user) config fallback at
~/.config/traceroot/config.json(or$XDG_CONFIG_HOME/traceroot/config.json), consulted only when no project-local config resolves a value.loginstill only ever writes the project-local file — the global file is a manual, read-only fallback for credentials you want available everywhere.How it works
statusanddoctornow report both which source won and the concrete file path it resolved from, soConfig source/config_sourcein JSON output distinguishes"config"(project) from"global-config".What's included
Config resolution
src/config/manager.ts— newglobalConfigPath()/readGlobalConfig(), sharing the same parse/validate logic as the project-localconfigPath()/readConfig()src/config/resolve.ts— new"global-config"AuthSource;resolveAuthtakes an optionalreadGlobalConfig, consulted after project config and before the auto-discovered.envsrc/context.ts— wires the realreadGlobalConfigintobuildContextby default, injectable for testsStatus / doctor / login
src/commands/status.ts—describeSourceand JSONconfig_pathresolve to the global config path when that's the winning sourcesrc/commands/doctor.ts/src/doctor/checks.ts—api_key_resolvedmessage names the global config path when it won; new informationalglobal_config_file_presentcheck (only emitted when the file exists — its absence is not a warning)src/commands/login.ts— the "already logged in" warning now also triggers when credentials came from the global config (previously only checkedapiKeySource === "config");loginitself still only ever writes the project-local filesrc/commands/shared.ts— the missing-api-key/missing-hostCliErrornow names both checked paths, e.g.(checked ./.traceroot/config.json and ~/.config/traceroot/config.json — config is per-directory, with a global fallback)— paths only, never key materialDocs
README.md— documents the full precedence order, the global fallback location, thatloginnever writes it (with a manualcpexample), and thatstatus/doctorreport the winning sourcesrc/config/schema.ts— corrected the stale docstring that claimed the config lives at~/.traceroot/config.json(a path the CLI never read or wrote)Test isolation
tests/helpers/runCli.ts(74a19e4) — the shared spawn helper now scrubsTRACEROOT_CONFIG_PATH,XDG_CONFIG_HOME,TRACEROOT_API_KEY, andTRACEROOT_HOST_URLfor every spawned CLI test, mirroring the existing isolation intests/output.contract.test.ts. Without this, a developer's real~/.config/traceroot/config.jsonor exportedTRACEROOT_*vars would resolve credentials and turn hermetic spawn tests into live network calls.Test plan
XDG_CONFIG_HOME, confirming spawned tests can't accidentally read it$XDG_CONFIG_HOME/traceroot/config.jsonand an empty, unrelated cwd —traceroot statusresolves credentials from the live workspace, reportsConfig source: <global config path>, andconfig_source: "global-config"in--jsonoutputtraceroot doctorshows "Global config file present" when the global config existsTRACEROOT_API_KEY) overrides a present global configSummary by cubic
Adds a per-user global config fallback and shows exactly where credentials come from in
status/doctor, fixing the “logged out from subdirectories” issue. Also warns on weak global-config permissions and reads the fallback lazily so higher-precedence sources always win.New Features
.env;loginstill writes only./.traceroot/config.json(copy to~/.config/traceroot/config.jsonif desired).status/doctorshow the winning source and path; JSON reportsconfig_sourceandconfig_path(global path when it wins); missing-credential errors name both checked paths.Bug Fixes
doctorwarns when the global config file is group/world-readable and recommendschmod 600.Written for commit e6fee6a. Summary will update on new commits.