Instruction file imported from compozy/releasepr (
.cursor/rules/global-config.mdc). Copyright stays with the author.
globs: *.go alwaysApply: false
Global Configuration Standards
Source of Truth & Precedence
Add a New Property (Existing Category)
-
Add struct field to typed config (required)
- File:
pkg/config/config.go - Add field under the respective
*Configstruct with tags:koanf:"<name>" json:"<name>" yaml:"<name>" mapstructure:"<name>"env:"<ENV_VAR>"when environment overrides are supportedvalidate:"..."when constraints apply- Use
SensitiveStringtype orsensitive:"true"tag for secrets
- File:
-
Map from registry to typed struct (required)
- File:
pkg/config/config.go - Update corresponding
build<Section>Config(registry *definition.Registry)to set the new field usinggetString/getInt/getBool/getDuration/getInt64/getStringSlice
- File:
-
Defaults map (usually automatic)
- File:
pkg/config/provider.go - Defaults come from
Default()which is built from the registry; add to the section’screate<Section>Defaultsonly if special formatting is needed (e.g.,.String()for durations)
- File:
-
Validation (if needed)
- Prefer struct tag validation (
validate:"...") - For cross-field rules, extend
pkg/config/loader.go→validateCustom
- Prefer struct tag validation (
-
Env var mapping (automatic, verify tags)
pkg/config/env_mappings.goauto-generates mappings from structenv:"..."tags- Ensure the new field has a correct
envtag; verify withconfig diagnostics --verbose
-
CLI flag exposure (from registry)
- Global flags are created from the registry:
cli/helpers/global.go→AddGlobalFlags - If the property should be user-settable via CLI, add a
CLIFlagand optionalShorthandin the registry entry
- Global flags are created from the registry:
-
Help categorization (for better UX)
- File:
cli/helpers/flag_categories.go - Add the new flag name to an existing category’s
Flagslist; if not categorized it appears under “Other Flags”
- File:
-
Diagnostics and
config showvisibility- File:
cli/cmd/config/config.go - Add the field to the appropriate
flatten<Section>Configso it appears in table/JSON/YAML outputs with proper redaction
- File:
-
Sensitive output handling
- Use
redactSensitive()for plain secrets andredactURL()for connection strings in flatteners - Prefer
SensitiveStringfor secrets to ensure automatic JSON redaction across outputs
- Tests & validation
- Run
make lintandmake test - Add/extend tests under
pkg/config/*_test.gowhen adding validation or complex defaults
Create a New Category (Top-level Section)
-
Add to root
Config- File:
pkg/config/config.go - Add
Section <Section>Configwithkoanf:"<section>" json:"<section>" yaml:"<section>" mapstructure:"<section>"
- File:
-
Register all fields in the registry
- File:
pkg/config/definition/schema.go - Create
register<Section>Fields(registry *Registry) - Add to
CreateRegistry()
- File:
-
Map defaults from registry to typed struct
- File:
pkg/config/config.go - Add
build<Section>Config(registry *definition.Registry)
- File:
-
Default provider map
- File:
pkg/config/provider.go - Add
create<Section>Defaultsand include inadd<Service|Infra|Core>Defaults
- File:
-
CLI output visibility
- File:
cli/cmd/config/config.go - Add
flatten<Section>Config
- File:
-
CLI help categorization
- File:
cli/helpers/flag_categories.go - Add a category block or include flags in an existing category as appropriate
- File:
-
Validation
- Use struct tags and extend
validateCustomif cross-field constraints apply
- Use struct tags and extend
-
Run
make lintandmake test
Naming & Conventions
Quick Example: Add a Property
- Registry (schema.go)
registry.Register(&FieldDef{
Path: "runtime.max_concurrent_jobs",
Default: 8,
CLIFlag: "max-concurrent-jobs",
EnvVar: "RUNTIME_MAX_CONCURRENT_JOBS",
Type: reflect.TypeOf(0),
Help: "Maximum concurrent runtime jobs",
})
- Typed config (config.go)
type RuntimeConfig struct {
MaxConcurrentJobs int `koanf:"max_concurrent_jobs" json:"max_concurrent_jobs" yaml:"max_concurrent_jobs" mapstructure:"max_concurrent_jobs" env:"RUNTIME_MAX_CONCURRENT_JOBS" validate:"min=1"`
}
- Builder (config.go)
func buildRuntimeConfig(reg *definition.Registry) RuntimeConfig {
return RuntimeConfig{
// ...existing fields
MaxConcurrentJobs: getInt(reg, "runtime.max_concurrent_jobs"),
}
}
- CLI flatten (cli/cmd/config/config.go)
func flattenRuntimeConfig(cfg *config.Config, out map[string]string) {
// ...existing fields
out["runtime.max_concurrent_jobs"] = fmt.Sprintf("%d", cfg.Runtime.MaxConcurrentJobs)
}
-
Categorize flag (cli/helpers/flag_categories.go) Add
"max-concurrent-jobs"under "Runtime & Performance". -
Validate Run:
make lint && make test