feat(nono): add restrictive core policy contract

This commit is contained in:
jb
2026-08-30 12:49:17 -04:00
parent 54c20e2012
commit 90f8090f61
19 changed files with 1862 additions and 9 deletions
@@ -0,0 +1,13 @@
# Materialize trusted Nono policy composition before launch
Nono 0.74 accepts multiple `extends` parents, merges additive grants and environment allowlists across them, and preserves restrictive network decisions such as `block: true`. The trusted Slice 3 generator will therefore treat the Slice 1 core and provider profiles as reviewed policy inputs, select exactly one core and one provider, materialize one canonical launch profile, and validate that result rather than launching a multiple-inheritance profile directly. This keeps the reusable core fail-closed when validated alone while allowing the trusted generator to make the selected provider route explicit.
## Consequences
The managed LM Studio extension uses exact URL `http://127.0.0.1:1234/v1`, while Nono's Linux policy grants outbound TCP port `1234`. Nono 0.74 Landlock mediation is port-only and cannot constrain that grant to loopback, so compromised sandbox code could connect to another address on port 1234. The adjacent-port behavioral proof and exact extension endpoint make this narrower than broad networking without overstating host enforcement.
Cloud provider fragments enable Nono networking with an explicit empty direct-domain allowlist and exactly one phantom credential route. The route's reviewed upstream is the only proxy destination; raw provider keys remain denied to the sandbox. Live secret-backed verification stays behind a separate explicit approval gate.
The active unmanaged LM Studio source remains in place during Slice 1 by explicit approval because quarantining it before an immutable managed installation would disable the current provider. Its reviewed legacy digest and both blockers are recorded in `config/pi-package-lock.json`; Slice 3 must perform hash-guarded quarantine atomically with immutable promotion before activation.
Provider fragments are not standalone launch profiles despite passing strict schema validation. They exclude the inherited Linux and macOS system runtime-read groups, so direct execution cannot read its executable; the trusted generator extracts only the reviewed provider route into a core that owns runtime reads. Untrusted repositories cannot compose or override fragments, and every generated profile must prove that it contains one state namespace, one worktree grant, one temporary directory, and exactly one provider route before `nono run`. Slice 1 isolated settings expose only Pi's `read`, `edit`, and `write` built-ins; model-visible `bash`, package tools, notification commands, background-job extensions, and project resources are absent. Core profiles intentionally define no `command_policies`; later broker slices must bind each controlled command to an exact executable and declare every permitted caller under `commands.<name>.from`, because inherited denials and caller edges are not safely loosened by child profiles. Slice 3 must invoke the exact Pi entrypoint and must not expose arbitrary caller-selected Nono commands as a launch interface.
+4
View File
@@ -4,6 +4,10 @@
A Slice 0 `node scripts/pi-links.mjs prune --dry-run` from `.worktrees/nono-dynamic-permissions-slice-zero-direct` exited 2 and classified every active link into the primary checkout as an outside-repository conflict. The tool anchors ownership to the current worktree root, while active links correctly target the primary repository checkout. Teach check and dry-run planning to recognize canonical checkouts sharing the same Git common directory without broadening stale-link deletion to unrelated repositories. Add linked-worktree fixtures before changing prune behavior. Until fixed, run host reconciliation only from the integrated primary checkout.
## Harden Nono 0.74 command-policy and resolved-policy diagnostics
Slice 1 found two Nono 0.74 limitations while building behavioral policy proofs. First, command-policy startup fails with `path must be shorter than SUN_LEN` when Nono creates its supervisor socket beneath a moderately long isolated `TMPDIR` such as `/tmp/nono-slice-one-*/sessions/personal/tmp`. Before broker profiles activate command policies, reproduce the maximum safe path, then have the launcher select a private short socket root or confirm an upstream fix. Second, `nono profile show --json` omits resolved `environment`, `command_policies`, `network.connect_port`, and `network.custom_credentials` fields even though strict validation and live enforcement accept them. Do not treat resolved JSON as complete evidence for these capabilities; retain behavioral `nono run` and `nono why --command` proofs until the output is complete and regression-tested.
## Replace `pi-workflow` with a skill-based orchestrator
The strict `pi-workflow` extension repeatedly failed before implementation because planner output and persisted state-machine constraints were too brittle for adaptive subagent orchestration. In a separate session, design a repository-managed skill where the main Pi agent owns the plan, task tree, isolated worktree, explicit user approval gates, verification, and independent review while launching standard `scout` and `worker` subagents directly. Preserve file-ownership boundaries, no inferred approvals, review independence, and resumable repository evidence, but prefer native Pi primitives over a custom orchestration engine. Evaluate a small committed state manifest for crash recovery before retiring or archiving the extension. Use the abandoned `.worktrees/pi-workflow-plan-seed` implementation only as reference; do not integrate it by default.