Skip to content

fix(config): layer project .cu.yml correctly and stop Save leaking it into global config - #43

Open
timimsms wants to merge 1 commit into
mainfrom
fix/config-precedence-and-save
Open

fix(config): layer project .cu.yml correctly and stop Save leaking it into global config#43
timimsms wants to merge 1 commit into
mainfrom
fix/config-precedence-and-save

Conversation

@timimsms

Copy link
Copy Markdown
Owner

Summary

Fixes the two halves of #37: project .cu.yml was loaded at the wrong precedence, and Save wrote far more than it should.

Precedence. Project config merged with viper.Set() — viper's override slot, which outranks everything. The documented chain is flags > env > project > global; the actual behaviour was project > flags > env > global. It now merges via MergeConfigMap into the config layer, so project values override the global file while still losing to env and flags.

Save. Save() serialized the entire merged viper state into the global file, so cu config set inside any project baked that project's values into ~/.config/cu/config.yaml. It now starts from the file on disk and applies only values written through Set.

Why this is more than a precedence bug. Because those two combine, a project .cu.yml containing api_token was written into the global config, replacing the real token. Reproduced against v0.1.0:

$ cat .cu.yml
default_list: from-project
api_token: EVIL-token
$ cu config set default_workspace ws-1
$ cat ~/.config/cu/config.yaml
api_token: EVIL-token      # was: real-token
default_list: from-project
output: yaml

Any cloned repository could substitute the credential used for API calls. Credential keys from a project file are now dropped with a warning, implementing the credential blocklist from the accepted context-layer design (§2.4).

Same fixture on this branch:

$ cu config set default_workspace ws-1
cu: ignoring "api_token" in /…/.cu.yml — credentials come from the keyring, environment, or your global config
$ cat ~/.config/cu/config.yaml
api_token: real-token
default_space: global-space
default_workspace: ws-1

Also: config loading moves entirely into config.Init. It previously ran in both cobra.OnInitialize and PersistentPreRunE, in that order, so a re-read could clobber the merged layer.

Tests

New TestProjectConfigPrecedence (project > global, env > project, flag > project, credentials ignored) and TestSaveDoesNotLeakProjectConfig. All four precedence cases also verified end-to-end with a built binary against a sandboxed HOME.

Checklist

  • ./scripts/ci.sh passes locally — except errcheck, which reports the same 27 pre-existing findings on main, none in files this PR touches
  • Commit messages use conventional prefixes
  • CLI docs regenerated if command help text changed — no help text changed
  • Docs updated if user-facing behavior changed

Project config was merged with viper.Set, which writes viper's override slot —
outranking flags and environment variables and inverting the documented
precedence. It now merges via MergeConfigMap into the config layer, so the
chain is flags > env > project .cu.yml > global config > defaults.

Save serialized the whole merged viper state into the global file, so
`cu config set` inside any project baked that project's values into
~/.config/cu/config.yaml. Save now starts from the file on disk and applies
only values written through Set.

Together these were worse than a precedence bug: with the released binary, a
project .cu.yml containing api_token overwrote the real token in the global
config. Credential keys from a project file are now dropped with a warning,
per the context-layer design's credential blocklist.

Config loading also moves entirely into config.Init. It previously ran in both
cobra.OnInitialize and PersistentPreRunE, in that order, so any re-read could
clobber the merged layer.

Fixes #37

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014aqbmccWm1tqttmBUCR5rv
ClickUp: 86dxbeqyt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant