MAISON-004: Private overlay configuration split
Historical record: this delivery was superseded by the single consumer-root model. The old source-selection state and command paths described below are not supported; current migration guidance is in Migration Contract.
Delivery Summary
- Beads feature root:
maison-mol-e9t - Status: delivered, later superseded by
maison-hi8 - Pull request: pending delivery action
- Merge commit: pending delivery action
- Design record: design.md
Delivered Capability
Maison now separates public reusable vehicle code from private site configuration. The public repository keeps neutral starter inventory, host examples, package files, dotfiles, validators, Nix modules, and task machinery. A tracked private overlay repository can own real hosts, usernames, emails, deploy targets, package declarations, dotfile overrides, and trusted key material.
Bootstrap accepts --overlay <git-url-or-path>, records the selected source in local XDG state, and clones or updates
the overlay into a standard XDG data path. When the overlay contains inventory.toml, Maison uses that typed inventory
and its sibling hosts/ tree for shell task lookups, Python validation, Nix evaluation, host mutation, and deployment
targeting.
User-Facing Behavior
Operators keep using the existing Maison command surface. Fresh setup can provide an overlay explicitly:
./bootstrap.sh --host "$(hostname -s)" --overlay GIT-URL-OR-PATH
Overlay source precedence is:
--overlay <git-url-or-path>for the current bootstrap run.MAISON_OVERLAY_SOURCE, including a value supplied by mise secrets.${XDG_STATE_HOME:-$HOME/.local/state}/maison/overlay.toml.
The standard clone/update path is ${XDG_DATA_HOME:-$HOME/.local/share}/maison/overlay. Interactive setup may prompt
when overlay input is required; non-interactive setup fails clearly instead of silently continuing with public starter
data for a real machine.
Design Integration
The implementation preserves Maison’s two-layer architecture. Nix/Lix remains the privileged system owner and mise remains the user-state owner. The overlay is a data source for the same typed inventory and layout contracts; it is not a second command surface or arbitrary schema framework.
Public Maison remains a valid starter repository. Private overlays mirror supported owned data paths such as
inventory.toml, hosts/, config/mise/*.toml, dotfiles/, and trusted key files.
Operational Impact
Operators can recover overlay selection by restoring or recreating the XDG state file, or by rerunning bootstrap with
--overlay. If the overlay clone is corrupt, it can be moved aside and recloned from the recorded source.
maison host add mutates the active inventory repository. With an overlay inventory, new inventory entries and optional
host override stubs are written to the overlay clone rather than to public Maison.
Reference and Contracts
- Architecture
- Operations
- Remote deployment
- Recovery
- Package policy
- Task reference
- Adding a Host
- Adding a Tool
- Adding an App
Validation Evidence
python3 -m py_compile scripts/maison_overlay.py tests/test_topology.py .mise/lib/inventory.py— passed.python3 -m unittest -v tests.test_topology.OverlayContractTest— passed.uv run scripts/check-docs.py— passed.mise -E dev run check— passed.
Design Reconciliation
Delivered as Designed
- Bootstrap supports
--overlayand hands the selected source to the bootstrap task. - Overlay state uses
${XDG_STATE_HOME:-$HOME/.local/state}/maison/overlay.toml. - Overlay clones use
${XDG_DATA_HOME:-$HOME/.local/share}/maison/overlay. --overlaytakes precedence over environment and saved state sources.- The same typed TOML inventory validator handles public examples and private overlay fixtures.
- Python task lookups, Nix evaluation, host overrides, and deployment targeting use the active overlay inventory when present.
- Public starter inventory, dotfiles, and reader examples no longer contain personal infrastructure identity.
Intentional Changes
- The first implementation introduced a small tested Python helper at
scripts/maison_overlay.pyplus a thin shell adapter at.mise/lib/overlay.sh, matching the design preference for Python stdlib state handling while preserving shell task compatibility. - Public starter data remains usable for validation and examples, but real machine convergence is documented around an overlay rather than public defaults.
Deferred Work
- Overlay layering for every possible
config/mise/*.tomlanddotfiles/application path remains limited to the documented mirrored layout and active inventory behavior delivered here. Future features can expand mutation surfaces if needed.
Rejected or Removed Scope
- Public Maison no longer carries personal usernames, hostnames, email addresses, deploy endpoints, or trusted signing keys.
- Untracked-only local inventory is not the durable source of truth; the private overlay repository is tracked.
Documentation Updated
README.mddocs/add-a-host.mddocs/add-a-tool.mddocs/add-an-app.mddocs/architecture.mddocs/deployment.mddocs/operations.mddocs/package-policy.mddocs/recovery.mddocs/task-reference.mddocs/src/features/maison-004-private-overlay-configuration/design.mddocs/src/features/maison-004-private-overlay-configuration/index.mddocs/src/features/index.mddocs/src/planned-features.mddocs/src/SUMMARY.md
Audit Trail
- Specification reconciliation task:
maison-mol-luq, commit4d88caa. - Implementation coordinator:
maison-mol-z6x. - Overlay contract task:
maison-mol-z6x.1, commit96136b0. - Overlay loader task:
maison-mol-z6x.2, commit8ae4710. - Overlay docs/examples task:
maison-mol-z6x.3, commit8d5c240. - Documentation reconciliation task:
maison-mol-5is. - Validation task:
maison-mol-uie.