Depends on #13.
Motivation
The current default subordinate UID/GID width, 65536, matches the documented rootless-Docker prerequisite ("/etc/subuid and /etc/subgid should contain at least 65,536 subordinate UIDs/GIDs for the user") but is too narrow for nested rootless BuildKit: the moby/buildkit:rootless image maps IDs 100000–165535 inside the build container, so the host user's range must span 165536 IDs for such builds to work. That makes the wider range the practical default for a build runner. And a declared width is currently never converged: an existing entry is left untouched whatever the data says, so a declaration wider than the host's range is silently unmet and only fails at job time.
Goal
The declared width is a real, enforced minimum: hosts converge to it, a range the module does not own fails loud when too narrow, and any other divergence between data and host is visible on every apply.
Acceptance criteria
- The default width accommodates the rootless BuildKit layout.
- An owned range (entry at the declared start) narrower than declared is widened in place in a single locked operation, followed by an automatic rootless-daemon restart in the same apply; the module never shrinks a range and never rewrites one at a foreign start.
- The preflight compares the summed on-host width against the declaration and fails loud when a foreign-owned range is too narrow.
- Every other host/data mismatch warns on each apply; only the exact-match state is silent.
Documentation
README (host requirements, BuildKit prerequisite), REFERENCE.md, CHANGELOG.
Delivery
The change layers into pieces that build on each other:
- A structured fact reads
/etc/subuid and /etc/subgid into a per-owner map, so each apply can compare the declared range against real host state — something a catalog compile and --noop cannot otherwise see.
- Grow-only enforcement widens an owned range that is too narrow, in a single locked operation, and restarts the rootless daemon in the same apply so the wider user namespace takes effect; a range the module does not own is left untouched.
- A width-aware preflight sums the on-host ranges and fails loud, with remedies, when an unowned range is too narrow to work.
- Compile-time advisories cover every remaining divergence — an owned range wider than declared, an unowned range that is wide enough, or a declared range that overlaps another user's allocation — so a mismatch stays visible on every apply; only the exact match is silent.
- Tests exercise each row of the divergence case matrix at non-default values, alongside the documentation above.
Depends on #13.
Motivation
The current default subordinate UID/GID width, 65536, matches the documented rootless-Docker prerequisite ("
/etc/subuidand/etc/subgidshould contain at least 65,536 subordinate UIDs/GIDs for the user") but is too narrow for nested rootless BuildKit: themoby/buildkit:rootlessimage maps IDs 100000–165535 inside the build container, so the host user's range must span 165536 IDs for such builds to work. That makes the wider range the practical default for a build runner. And a declared width is currently never converged: an existing entry is left untouched whatever the data says, so a declaration wider than the host's range is silently unmet and only fails at job time.Goal
The declared width is a real, enforced minimum: hosts converge to it, a range the module does not own fails loud when too narrow, and any other divergence between data and host is visible on every apply.
Acceptance criteria
Documentation
README (host requirements, BuildKit prerequisite), REFERENCE.md, CHANGELOG.
Delivery
The change layers into pieces that build on each other:
/etc/subuidand/etc/subgidinto a per-owner map, so each apply can compare the declared range against real host state — something a catalog compile and--noopcannot otherwise see.