feat: pi-agent wrapper
This commit is contained in:
125
PLAN.md
125
PLAN.md
@@ -1,57 +1,98 @@
|
||||
# PLAN
|
||||
|
||||
## Context
|
||||
- Implement **Option A**: run `pi` through a **rootless Podman** container while keeping a native terminal UX.
|
||||
- Preserve `flake.nix` + `nix develop` workflows by using the **host Nix daemon** from inside the container.
|
||||
- Keep logic centralized in `nixpkgs` and host-specific values in `nixos-config`.
|
||||
- Target implementation is confirmed as `m3ta.pi-agent` (no container mode).
|
||||
- You want a **fresh-from-scratch rewrite** of `modules/nixos/pi-agent.nix` and to ignore prior behavior as design baseline.
|
||||
- Required behavior:
|
||||
- dedicated isolated Unix user/group for Pi (`pi-agent` defaults)
|
||||
- host UX stays `pi`
|
||||
- bypass prevention (wrapper should be the canonical executable path)
|
||||
- per-host-user project root policy (different roots per user)
|
||||
- no writable/access scope beyond isolated Pi home/state + explicitly allowed project roots
|
||||
- isolated environment must include user Pi config from HM (`modules/home-manager/coding/agents/pi.nix`) and support Nix-managed settings/env merging.
|
||||
- Repo findings:
|
||||
- `modules/nixos/default.nix` + `flake.nix` already import/export `pi-agent` module.
|
||||
- `modules/home-manager/coding/agents/pi.nix` already renders Pi config files under a configurable relative path (`coding.agents.pi.path`, default `.pi/agent`).
|
||||
|
||||
## Approach
|
||||
- Extend the existing Home Manager module at `modules/home-manager/coding/agents/pi.nix` with a `coding.agents.pi.container.*` option set.
|
||||
- Implement **Option A defaults** from your decisions:
|
||||
- wrapper command name is `pi` (native command replacement),
|
||||
- project roots are mounted read-write,
|
||||
- `autoStart = true` by default,
|
||||
- `autoNixDevelop = false` by default,
|
||||
- `image` default set to `docker.io/nixos/nix:latest` as a conservative base and overridden in host config for a Pi-ready image.
|
||||
- Generate a deterministic wrapper script (installed via Home Manager) that:
|
||||
- verifies cwd is within allowed project roots,
|
||||
- ensures rootless container exists/runs,
|
||||
- maps cwd and runs `podman exec -it <container> pi "$@"`,
|
||||
- optionally runs via `nix develop -c pi ...` when `autoNixDevelop=true` and `flake.nix` is present.
|
||||
- Configure safe Podman mounts:
|
||||
- allowed project roots only,
|
||||
- host Nix daemon socket (Option A),
|
||||
- minimal Nix config/certs needed for CLI operation.
|
||||
- Wire host-specific config in `nixos-config/home/features/coding/pi.nix` and remove direct host `pi` binary installation from the coding package list to avoid command-path ambiguity.
|
||||
- Fully replace `modules/nixos/pi-agent.nix` with a new design centered on:
|
||||
1. **Dedicated runtime identity** (`user/group/createUser/stateDir`).
|
||||
2. **Policy-driven wrapper flow** (`pi` -> privileged runner -> isolated execution).
|
||||
3. **Per-user project allowlists** (cwd must be under roots assigned to invoking host user).
|
||||
4. **Config + env convergence**:
|
||||
- sync user HM Pi config directory (e.g. `~/.pi/agent`) into isolated state,
|
||||
- merge Nix-managed Pi settings into isolated `settings.json`,
|
||||
- merge Nix-managed env vars + env files into isolated runtime env source,
|
||||
- make merged results visible to the isolated runtime every invocation (without container recreation semantics).
|
||||
5. **Hard isolation defaults** with `systemd-run` sandboxing and explicit bind/read-write paths only for state + allowed projects.
|
||||
- Keep wrapper command as `pi`, and avoid exposing direct package binary on PATH when wrapper mode is enabled.
|
||||
|
||||
## Files to modify
|
||||
- `modules/home-manager/coding/agents/pi.nix` (new container options + wrapper + container lifecycle logic)
|
||||
- `/home/m3tam3re/p/NIX/nixos-config/home/features/coding/pi.nix` (host-specific container settings)
|
||||
- `modules/nixos/pi-agent.nix` (full rewrite)
|
||||
- `modules/nixos/default.nix` (only if import list changes)
|
||||
- `flake.nix` (only if output export attrs change)
|
||||
- `docs/guides/pi-agent-isolation.md` (update option model + merge behavior)
|
||||
- `docs/guides/using-modules.md` (update examples/options)
|
||||
|
||||
## Reuse
|
||||
- Existing Pi HM module and option namespace:
|
||||
- `modules/home-manager/coding/agents/pi.nix`
|
||||
- Existing coding feature wiring in nixos-config:
|
||||
- `/home/m3tam3re/p/NIX/nixos-config/home/features/coding/default.nix`
|
||||
- `/home/m3tam3re/p/NIX/nixos-config/home/features/coding/pi.nix`
|
||||
- Module/user/service patterns:
|
||||
- `modules/nixos/mem0.nix`
|
||||
- `templates/nixos-module/default.nix`
|
||||
- Pi config rendering contract to consume/sync:
|
||||
- `modules/home-manager/coding/agents/pi.nix` (`coding.agents.pi.path`, `settings.json`, `mcp.json`, agent docs)
|
||||
|
||||
## Steps
|
||||
- [ ] Add `coding.agents.pi.container` options (enable/name/image/projectRoots/autoStart/autoNixDevelop/extraRunArgs/extraEnv) with defaults matching your preferences (`autoStart=true`, `autoNixDevelop=false`, default image as above).
|
||||
- [ ] Implement wrapper script generation in HM module with cwd allowlist checks and container create/start/exec behavior.
|
||||
- [ ] Make wrapper binary name `pi` (native UX) when container mode is enabled.
|
||||
- [ ] Add deterministic container run/create args with safe mounts and host Nix daemon socket.
|
||||
- [ ] Add optional in-container `nix develop -c pi` path when flake project is detected.
|
||||
- [ ] Wire host-specific values in nixos-config `home/features/coding/pi.nix`.
|
||||
- [ ] Remove direct host `pi` package install in nixos-config coding packages so wrapper is the effective `pi` command.
|
||||
- [ ] Validate eval/build and document command outputs for flake and non-flake wrapper behavior.
|
||||
- [ ] Define the new `m3ta.pi-agent` option schema for fresh module behavior, including:
|
||||
- base runtime options (`package`, `binaryName`, `user`, `group`, `createUser`, `stateDir`),
|
||||
- wrapper controls (`enable`, `commandName`, runner name, hide-direct-binary behavior),
|
||||
- per-user policy map (allowed users and each user’s allowed project roots),
|
||||
- host-config sync knobs (source path relative/absolute),
|
||||
- Nix-managed settings/env options for merge.
|
||||
- [ ] Implement new wrapper script:
|
||||
- identify invoking user,
|
||||
- validate user exists in policy map,
|
||||
- expand/resolve that user’s roots,
|
||||
- deny out-of-policy cwd,
|
||||
- escalate only to the dedicated runner.
|
||||
- [ ] Implement new privileged runner script:
|
||||
- enforce root-only execution,
|
||||
- resync host Pi config into isolated config dir,
|
||||
- merge managed settings into isolated settings file,
|
||||
- merge managed env + env files into isolated env file/export source,
|
||||
- prepare deterministic project mount aliases under isolated home,
|
||||
- launch Pi through hardened transient `systemd-run` unit as isolated user.
|
||||
- [ ] Apply hardening policy in execution profile:
|
||||
- `ProtectSystem=strict`, `ProtectHome=yes`, `NoNewPrivileges=yes`,
|
||||
- explicit `ReadWritePaths` limited to state + mounted allowed projects,
|
||||
- bounded runtime PATH and writable tool/cache locations under `stateDir`.
|
||||
- [ ] Add assertions for misconfiguration (e.g., empty per-user roots, wrapper enabled without authorized users).
|
||||
- [ ] Add tightly scoped sudoers rule for runner command only.
|
||||
- [ ] Ensure bypass prevention in packaging/PATH behavior when wrapper mode is enabled.
|
||||
- [ ] Update docs with new option examples (per-user roots + settings/env merge + HM sync expectations).
|
||||
|
||||
## Verification
|
||||
- Static checks for both repos (module eval/build where appropriate).
|
||||
- Home Manager evaluation/switch check in nixos-config.
|
||||
- Manual wrapper checks:
|
||||
- Inside a flake project: `pi` resolves via `nix develop -c pi ...` when enabled.
|
||||
- Outside flake project: `pi` runs directly via container exec.
|
||||
- Capture exact commands + outputs for report.
|
||||
- Static/eval:
|
||||
- `nix flake check`
|
||||
- host config eval/build with new module options.
|
||||
- Policy checks:
|
||||
- authorized user in authorized root: succeeds
|
||||
- authorized user outside authorized root: denied
|
||||
- unauthorized user: denied
|
||||
- Isolation checks:
|
||||
- runtime identity is isolated service user (`pi-agent`)
|
||||
- no unintended write access outside `stateDir` + allowed project binds
|
||||
- direct binary bypass unavailable when wrapper mode is enabled
|
||||
- Merge checks:
|
||||
- HM-rendered Pi files are present in isolated config dir
|
||||
- Nix-managed settings are merged into effective isolated `settings.json`
|
||||
- env values from declarative attrs + env files are present in isolated runtime environment.
|
||||
|
||||
## Open questions
|
||||
- None currently blocking; proceed with conservative default image and host override guidance.
|
||||
- None.
|
||||
|
||||
## Resolved decisions
|
||||
- Merge precedence is confirmed as:
|
||||
1) synced host Pi config/env,
|
||||
2) Nix-managed settings/env override synced values,
|
||||
3) wrapper/runtime shell env does not implicitly override managed values.
|
||||
- Per-user host config source defaults to `.pi/agent` for all users, with optional per-user override support in the policy map.
|
||||
|
||||
Reference in New Issue
Block a user