diff --git a/docs/prs/2026-09-03-PR#19-werkdock-config-section.md b/docs/prs/2026-09-03-PR#19-werkdock-config-section.md new file mode 100644 index 0000000..694e6ad --- /dev/null +++ b/docs/prs/2026-09-03-PR#19-werkdock-config-section.md @@ -0,0 +1,98 @@ +> **WARNING:** This document describes only the change applied in this PR. +> It may already be outdated once the next PR is merged. +> Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation. + +## The Problem + +The build sandbox for hosts without Docker was configured as `bwrap`, named after the mechanism rather than after the thing Werkator runs. +Since step 21 session C (v1.0.0) Werkator does not invoke `bwrap` at all: it shells out to the [werkdock](https://git.javagil.de/mi/werkdock) CLI, which assembles the bubblewrap invocation and owns the image store. +The name outlived its truth, and the clearest symptom was the key `bwrap.werkdock` — a section naming its own executor. + +It also leaked outward. +`tools/remote` gained a `WERKATOR_SANDBOX` key in PR#18 whose value had to be `bwrap` while the very thing it switches on is *uploading the werkdock binary*, and the question that prompted this PR — "is there also `WERKATOR_SANDBOX=werkdock`?" — is one nobody would ask about a name that matched. + +## Non-Goals + +- Refusing the old name. That belongs to the release which sets `ConfigVersions.FORMAT_BROKE_IN` (plan step 18): only there can a file that declares no version be caught by name at all, and only there is one migration asked of the operator instead of two. +- Renaming `tools/build-bwrap-rootfs.sh` or `docs/plan/17-bwrap-build-runtime.md`. The script really does build a bubblewrap rootfs, and plan documents are historic records. +- Touching ADR 0008, which decided the *runtime* and is a snapshot of that decision. + +## The Scenarios + +### Feature: the sandbox is named after the tool that runs it + +#### Background + +- `builds..werkdock` replaces `builds..bwrap`, and `werkdock.binary` replaces `bwrap.werkdock`. +- The pinned set is unchanged in meaning: `enabled`, `rootfs` and the binary stay host-pinned, under their new names. + +#### Scenario#19.01: A configuration written for the old name keeps working + +So that no installation has to be edited before it can be updated — the section lives in machine configurations that no repository tracks. + +- **Given** a configuration writing `builds.default.bwrap` with `enabled`, `rootfs`, `werkdock` and `env` +- **When** the configuration is loaded +- **Then** the settings appear as `werkdock.enabled`, `werkdock.rootfs`, `werkdock.binary` and `werkdock.env`, and the file is named once in a warning + +##### Verified by + +- [ConfigLoaderTest — "the legacy bwrap section is read as werkdock, its werkdock key as binary"](../../src/test/kotlin/de/hoennig/werkator/config/ConfigLoaderTest.kt) + +#### Scenario#19.02: The old name is not a way around the pinning + +So that a branch cannot escape its sandbox by writing the section a branch is not allowed to write under its previous name. + +- **Given** a host configuration with `werkdock.enabled: true` and a rootfs +- **When** a branch's committed config sets `bwrap.enabled: false` with a foreign rootfs +- **Then** the sandbox stays enabled and the host's rootfs is used + +##### Verified by + +- [ConfigLoaderTest — "a legacy bwrap section on a branch is pinned exactly like the new name"](../../src/test/kotlin/de/hoennig/werkator/config/ConfigLoaderTest.kt) + +#### Scenario#19.03: The new name behaves exactly as the old one did + +So that the rename is a rename, not a change of behavior. + +- **Given** configurations using `werkdock` throughout +- **When** builds are dispatched, pinned keys stripped, and both sandboxes enabled at once +- **Then** the werkdock runner is selected, the branch cannot override the pinned keys, and enabling docker and werkdock together is rejected naming both + +##### Verified by + +- [DispatchingBuildRunnerTest — "runs in the werkdock sandbox when the branch enables it (and not Docker)"](../../src/test/kotlin/de/hoennig/werkator/build/DispatchingBuildRunnerTest.kt) +- [ConfigLoaderTest — "a branch cannot disable its werkdock sandbox …"](../../src/test/kotlin/de/hoennig/werkator/config/ConfigLoaderTest.kt) and "enabling both docker and werkdock on a build is rejected, not picked silently" +- [WerkdockBuildRunnerTest](../../src/test/kotlin/de/hoennig/werkator/build/WerkdockBuildRunnerTest.kt), unchanged in substance and renamed with the runner + +## The Solution + +`BwrapConfig` → `WerkdockConfig` (field `werkdock` → `binary`), `BwrapOverrides` → `WerkdockOverrides`, `BranchConfig.bwrap` → `.werkdock`, `BwrapBuildRunner` → `WerkdockBuildRunner`, and `PINNED_BWRAP_KEYS` → `PINNED_WERKDOCK_KEYS` with `binary` in place of `werkdock`. + +The compatibility lives in exactly one function, `ConfigLoader.renameLegacySandbox`, applied in `loadFile` and `parseYaml` — the two places a raw layer enters — so it runs before merging, before pinning and before binding, and every consumer downstream knows one name. +That placement is what makes Scenario#19.02 hold without a second thought: the branch layer is normalised *before* `stripPinned` reads it, so the old name cannot smuggle a pinned key past a check that looks for the new one. +Where a file writes both sections, the explicit `werkdock` one wins, because it is the name that is meant. +The warning is emitted once per file (`warnedSections`), like the other section-level warnings, since the config is re-read on every poll cycle. + +The version is bumped to 1.2.0 with a release note: the minor, because this changes the configuration schema, and a deployment must be identifiable as the one that introduced it. + +## Open Questions + +- **Should `WERKATOR_SANDBOX` keep accepting `bwrap`?** It does today, normalised on read and documented as the former name. The env files are local and gitignored, so this alias costs one line and can go whenever the config alias does. + +## Additional Changes + +- None beyond the rename and its documentation. + +## Deployment note + +The order matters, and only in one direction: deploy v1.2.0 to a host *before* rewriting its init fragment (`.env..yml`) to the new key names. +A fragment carrying `werkdock:` applied by an older Werkator fails the fragment's strict schema validation — which is the safe outcome, but a failed `repo-init` nonetheless. +The reverse never breaks: v1.2.0 reads every existing `bwrap:` fragment and machine config as before. + +## Prerequisite PRs + +- [PR#18](2026-09-03-PR%2318-remote-host-layout.md) introduced `WERKATOR_SANDBOX`, whose value this PR renames. + +## Follow-up PRs + +- Plan step 18 (removing the legacy `branches` section) sets `ConfigVersions.FORMAT_BROKE_IN`; the `bwrap` alias should be dropped in the same release, refusing the key by name.