Configuration Hardening 2
What changed:
- Added visible runtime override reporting with masking for sensitive values.
- Expanded effective config for build cleanup, script compiler discovery/env, extract layout/cleanup/
HAK discovery, wiki deploy defaults, autogen cache policy, and release-source env names.
- Wired configured values into build, script compiler resolution, extract, autogen cache refresh/max
age, parts manifest release source, wiki generation/deploy, and TLK output naming.
- Added config sources override output and validation-rule hints in config explain.
- Added CONFIGURATION_HARDENING_AUDIT.md.
- Updated README.md with config commands, schema defaults, and JSON artifact boundaries.
- Added regression tests for override visibility/masking, compiler/extract/wiki/autogen config,
configured HAK discovery, and config sources output.
This commit is contained in:
+35
-2
@@ -149,7 +149,7 @@ var commands = []command{
|
||||
},
|
||||
{
|
||||
name: "extract",
|
||||
description: "Extract a module archive back into the src/ tree.",
|
||||
description: "Extract built archives back into the configured source and asset trees.",
|
||||
run: runExtract,
|
||||
},
|
||||
{
|
||||
@@ -169,7 +169,7 @@ var commands = []command{
|
||||
},
|
||||
{
|
||||
name: "apply-hak-manifest",
|
||||
description: "Apply a generated HAK manifest to src/module/module.ifo.json.",
|
||||
description: "Apply a generated HAK manifest to the configured module source.",
|
||||
run: runApplyHAKManifest,
|
||||
},
|
||||
{
|
||||
@@ -749,6 +749,9 @@ func runConfig(ctx context) error {
|
||||
if provenance.Deprecated {
|
||||
fmt.Fprintf(ctx.stdout, "deprecated: true\n")
|
||||
}
|
||||
if rules := configValidationRules(key); len(rules) > 0 {
|
||||
fmt.Fprintf(ctx.stdout, "validation: %s\n", strings.Join(rules, "; "))
|
||||
}
|
||||
return nil
|
||||
case "sources":
|
||||
if len(ctx.args) > 2 {
|
||||
@@ -759,12 +762,42 @@ func runConfig(ctx context) error {
|
||||
fmt.Fprintf(ctx.stdout, "format: %s\n", p.ConfigSource.Format)
|
||||
fmt.Fprintf(ctx.stdout, "legacy: %t\n", p.ConfigSource.Legacy)
|
||||
fmt.Fprintf(ctx.stdout, "candidates: %s\n", strings.Join(project.ConfigFileCandidates, ", "))
|
||||
overrides := p.ActiveOverrides()
|
||||
if len(overrides) == 0 {
|
||||
fmt.Fprintln(ctx.stdout, "active overrides: none")
|
||||
return nil
|
||||
}
|
||||
fmt.Fprintln(ctx.stdout, "active overrides:")
|
||||
for _, override := range overrides {
|
||||
fmt.Fprintf(ctx.stdout, " %s=%s (%s)\n", override.Key, override.Value, override.Source)
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unknown config subcommand %q", ctx.args[1])
|
||||
}
|
||||
}
|
||||
|
||||
func configValidationRules(key string) []string {
|
||||
switch {
|
||||
case strings.HasPrefix(key, "paths."), strings.Contains(key, ".root"), strings.Contains(key, ".dir"), strings.Contains(key, ".cache"):
|
||||
return []string{"relative paths must not escape the repository root unless explicitly documented"}
|
||||
case strings.HasPrefix(key, "outputs."):
|
||||
return []string{"generated output names must use the configured extension and must not escape the repository root"}
|
||||
case key == "extract.layout":
|
||||
return []string{"supported value: nwn_canonical_json"}
|
||||
case key == "extract.hak_discovery":
|
||||
return []string{"supported values: build_glob, configured_haks"}
|
||||
case key == "autogen.cache.max_age":
|
||||
return []string{"Go duration string, for example 1h or 30m"}
|
||||
case strings.HasPrefix(key, "topdata.package_hak"):
|
||||
return []string{"must be a .hak file name"}
|
||||
case strings.HasPrefix(key, "topdata.package_tlk"), strings.HasPrefix(key, "topdata.compiled_tlk"):
|
||||
return []string{"must be a .tlk file name"}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func parseConfigFormatArgs(commandName string, args []string) (string, error) {
|
||||
format := "yaml"
|
||||
for _, arg := range args {
|
||||
|
||||
@@ -286,6 +286,37 @@ paths:
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigSourcesListsActiveOverrides(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
writeFile(t, filepath.Join(root, "nwn-tool.yaml"), `
|
||||
module:
|
||||
name: Test Module
|
||||
resref: testmod
|
||||
paths:
|
||||
source: src
|
||||
`)
|
||||
t.Setenv("SOW_BUILD_HAKS_KEEP_EXISTING", "1")
|
||||
|
||||
var stdout bytes.Buffer
|
||||
ctx := context{
|
||||
stdout: &stdout,
|
||||
stderr: &bytes.Buffer{},
|
||||
cwd: root,
|
||||
args: []string{"config", "sources"},
|
||||
}
|
||||
|
||||
if err := runConfig(ctx); err != nil {
|
||||
t.Fatalf("runConfig failed: %v", err)
|
||||
}
|
||||
output := stdout.String()
|
||||
if !strings.Contains(output, "active overrides:") {
|
||||
t.Fatalf("expected active overrides section, got %q", output)
|
||||
}
|
||||
if !strings.Contains(output, "build.keep_existing_haks=1") {
|
||||
t.Fatalf("expected keep existing override, got %q", output)
|
||||
}
|
||||
}
|
||||
|
||||
func mkdirAll(t *testing.T, path string) {
|
||||
t.Helper()
|
||||
if err := os.MkdirAll(path, 0o755); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user