Hardening audit

Key hardening changes:

  - Config validation now rejects paths.source: . and paths.assets: ., so source/asset roots cannot
    resolve to the repository root.
  - apply-hak-manifest now refuses to run when paths.source is unset or unsafe, instead of potentially
    writing under a root-level module/.
  - Inline flags across utility parsers now reject empty values consistently, e.g. --dataset=, --hak=,
    --endpoint=, --output=.
  - build-changelog now supports --flag=value inline syntax like the other utilities.
This commit is contained in:
2026-05-08 00:31:17 +02:00
parent 9f16aa8872
commit fa4c9116ae
8 changed files with 314 additions and 28 deletions
+75 -2
View File
@@ -12,6 +12,15 @@ Build the development binary into `tools/sow-toolkit`:
./build-tool.sh
```
On Windows:
```powershell
.\build-tool.ps1
```
Both wrappers use `.cache/go-build` for the Go build cache and skip rebuilding
when the sources are older than the existing development binary.
Or run directly with Go:
```bash
@@ -27,10 +36,39 @@ internal/erf/ ERF/MOD/HAK reading and writing
internal/gff/ canonical GFF JSON and binary conversion
internal/pipeline/ build, extract, compare, and manifest workflows
internal/project/ config loading and repo scanning
internal/topdata/ native topdata, wiki, and autogen workflows
internal/validator/validation and diagnostics
tools/ built development binary output
```
## Commands
The shared CLI exposes these project utilities:
```bash
sow-toolkit build
sow-toolkit build-module
sow-toolkit build-haks [--hak <name>] [--archive <name>] [--source-manifest <path>] [--plan-only] [--skip-music] [--music-dataset <id>]
sow-toolkit extract [<module-or-hak-file> ...]
sow-toolkit validate
sow-toolkit compare
sow-toolkit apply-hak-manifest [<manifest-path>]
sow-toolkit config <validate|effective|inspect|explain|sources>
sow-toolkit music <list-datasets|scan|build|credits|validate|manifest|normalize>
sow-toolkit validate-topdata
sow-toolkit build-topdata [--force] [--wiki]
sow-toolkit build-top-package [--force]
sow-toolkit compare-topdata
sow-toolkit convert-topdata <2da-to-json|2da-to-module|json-to-2da> ...
sow-toolkit build-wiki [--force]
sow-toolkit deploy-wiki [--source-dir <path>] [--endpoint <url>] [--token <token>] [--version <ver>] [--namespace <ns>] [--category <namespace=cid>] [--manifest <path>] [--dry-run] [--create] [--force]
sow-toolkit build-changelog [--config <path>] [--output <path>] [--current-tag <tag>] [--previous-tag <tag>] [--api-base-url <url>] [--token <token>]
```
Global logging flags `--quiet`, `--verbose`, and `--debug` may be passed after
the command name. Long options that take values accept either `--flag value` or
`--flag=value`; empty inline values such as `--dataset=` are rejected.
## Repository Configuration
Human-authored consumer repository configuration is YAML. The toolkit discovers
@@ -177,6 +215,19 @@ autogen:
repo_env: SOW_ASSETS_REPO
```
`paths.source` and `paths.assets` must name real repository subtrees when they
are configured. They may be omitted for repositories that do not own that class
of source, but they must not resolve to the repository root (`.`). Output and
cache paths must stay relative to the repository root unless a specific setting
documents otherwise.
Extraction is deliberately guarded because it writes source files from binary
archives. Module resources require a configured `paths.source`; HAK assets
require a configured `paths.assets`; both roots must resolve to safe subtrees.
If a root is unset or resolves to the repository root, extraction fails before
writing instead of creating extension directories like `mdl/` or `png/` at the
repo top level. Stale cleanup uses the same safe-root rule.
Music defaults (used when not explicitly configured):
```yaml
@@ -208,6 +259,8 @@ sow-toolkit music build --dataset westgate --dry-run
sow-toolkit music build --dataset westgate
sow-toolkit music credits --dataset westgate --check
sow-toolkit music validate --dataset westgate --json
sow-toolkit music manifest --dataset westgate
sow-toolkit music normalize --dataset westgate
```
`build-haks` uses the same music pipeline. Use `--plan-only` or music
@@ -220,17 +273,37 @@ topdata datasets, caches, credits inventories, build reports, and canonical GFF
documents. Nested metadata such as `topdata/templates/config.json` is not root
repository configuration and is intentionally unchanged.
## Wiki And Changelog Utilities
`build-topdata --wiki` or `build-wiki` renders wiki pages from the current
native topdata state. `deploy-wiki` publishes those pages to NodeBB. It reads
`NODEBB_API_ENDPOINT`, `NODEBB_API_TOKEN`, `GITHUB_REF_NAME`, and
`NODEBB_WIKI_CATEGORIES` when equivalent flags are omitted. Category mappings
use `namespace=cid`, for example:
```bash
sow-toolkit deploy-wiki --dry-run --namespace spells --category spells=42
```
`build-changelog` renders a release changelog from tagged pull requests. It
defaults to `scripts/changelog.json`, reads Gitea tokens from `GITEA_API_TOKEN`,
`GITEA_TOKEN`, or `SOW_TOOLS_TOKEN`, and writes to stdout unless `--output` is
provided.
## Intended Consumers
- `sow-module` uses `sow-toolkit` for `build-module`, `extract`, `validate`, `compare`, and `apply-hak-manifest`
- `sow-assets` uses `sow-toolkit` for `build-haks` and validation
- `sow-module` uses `sow-toolkit` for `build`, `build-module`, `extract`, `validate`, `compare`, and `apply-hak-manifest`
- `sow-assets` uses `sow-toolkit` for `build-haks`, music processing, changelog generation, and validation
- validation now fails early if duplicate asset resources would collide inside the same generated HAK
- duplicate resources split across different HAK groups remain warnings because later HAK order can still override earlier content at runtime
- `sow-module` now also uses `sow-toolkit` for topdata:
- `validate-topdata`
- `build-topdata`
- `build-top-package`
- `compare-topdata`
- `convert-topdata`
- `build-wiki`
- `deploy-wiki`
During development, sibling repositories can point at `../sow-tools/tools/sow-toolkit`
or `../sow-tools/tools/sow-toolkit.exe`. For pinned releases, each consumer repo can