on main help sign in
docs: update resolver godoc to match lenient default
45f7484Christian Rocha
internal/config/resolve.go+11−5
@@ -58,8 +58,11 @@ type shellVariableResolver struct {
58// NewShellVariableResolver returns a VariableResolver that delegates to
58// NewShellVariableResolver returns a VariableResolver that delegates to
59// the embedded shell (the same interpreter used by the bash tool and
59// the embedded shell (the same interpreter used by the bash tool and
60// hooks). Supported constructs match shell.ExpandValue: $VAR, ${VAR},
60// hooks). Supported constructs match shell.ExpandValue: $VAR, ${VAR},
61−// ${VAR:-default}, $(command), quoting, and escapes. Unset variables are
61+// ${VAR:-default}, $(command), quoting, and escapes. Unset variables
62−// an error; use ${VAR:-} to opt in to an empty fallback.
62+// expand to the empty string by default, matching bash; use
63+// ${VAR:?message} to require a value and fail loudly when it is missing.
64+// The stricter "unset is always an error" mode is gated globally by
65+// shell.NoUnset.
63func NewShellVariableResolver(e env.Env, opts ...ShellResolverOption) VariableResolver {
66func NewShellVariableResolver(e env.Env, opts ...ShellResolverOption) VariableResolver {
64 r := &shellVariableResolver{
67 r := &shellVariableResolver{
65 env: e,
68 env: e,
@@ -77,9 +80,12 @@ func NewShellVariableResolver(e env.Env, opts ...ShellResolverOption) VariableRe
77// - $VAR and ${VAR} for environment variables.
80// - $VAR and ${VAR} for environment variables.
78// - ${VAR:-default} / ${VAR:+alt} / ${VAR:?msg} for defaulting.
81// - ${VAR:-default} / ${VAR:+alt} / ${VAR:?msg} for defaulting.
79//
82//
80−// Unset variables are a hard error (nounset), mirroring the historical
83+// Unset variables expand to the empty string by default, matching bash.
81−// behaviour of this resolver: silently expanding an unset variable to the
84+// Command-substitution failures are always a hard error. Required
82−// empty string is exactly how broken credentials reach MCP servers.
85+// credentials should use ${VAR:?message} so a missing variable fails
86+// loudly at load time instead of quietly resolving to empty. Global
87+// strict mode is available via shell.NoUnset for callers that want the
88+// old nounset-on behaviour back.
83func (r *shellVariableResolver) ResolveValue(value string) (string, error) {
89func (r *shellVariableResolver) ResolveValue(value string) (string, error) {
84 // Preserve the historical backward-compat contract: a lone "$" is a
90 // Preserve the historical backward-compat contract: a lone "$" is a
85 // malformed config value, not a legal literal. The underlying shell
91 // malformed config value, not a legal literal. The underlying shell