Files
nixpkgs/PLAN.md
2026-04-14 18:36:13 +02:00

5.2 KiB
Raw Blame History

PLAN

Context

  • 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

  • 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/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

  • 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

  • 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 users 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 users 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/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.

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.