runecore: construction-authority doors at mutation tools + typed wire-boundary argument validation (audit T12) #2619

Open
conductor wants to merge 2 commits from fix/tool-boundary-audits into master
pull from: fix/tool-boundary-audits
Owner

Summary

Repairs the two HIGH tool-boundary defects from the owner code audit T12 (reproduced on frozen master a52624b3, re-verified on current master 79ff61b3 before any repair):

  1. Mutation family ran with no construction authority. runecore.ExecuteGatedTool now crosses two doors before write_file/edit_file/run_command effects (internal/runecore/authority.go): wire-boundary argument validation, then the construction-authority consult — Go I/O reads the nearest construction store walking up from the mutation site (run_command's door is its workdir); scope matching mirrors the parity-frozen CheckScope mechanics (D33 research verdict: no Rust crate provides the runtime path-scope decision — construction_decision resolves need→surface at adoption only — so the existing Go-side mechanics are reused verbatim, no new Go↔Rust crossing); draft is not authority, closed/failed/abandoned are expired; missing/broken/uncovered authority fails closed with the typed envelope the model reads: no open construction contract covers this path — open one via the construction interface.
  2. Destructive default truncated files. argStr("content","") turned missing/null/numeric/bool content into a 0-byte overwrite reported as success. Required-field presence + string-type is now enforced exactly where the schema advertises it (write_file content/path, edit_file search/replace, run_command command); an explicitly-supplied empty string stays legal.

Constraints honored

  • D49: no tool is removed from any mode; the consent card stays work-promotion — the gate adds the scaffolding authority at mutation doors, it does not gate capability (D49's own "real safety layer" text).
  • D57: refusal wording is action-directive; refusal.go untouched (interplay flagged in the plan's FOL).
  • Scaffolding law: contract-first — ADMIT-tool-boundary-audits-20261025 minted via the real construction interface (scripts/admit_wave_tool_boundary.py) naming every surface; the pre-commit landing gate verified coverage.

Verification

  • Red-first: new tests failed against unpatched master with the defect signatures verbatim ("wrote … (0 bytes)", shell executed, file clobbered) — then green after the repair; go test ./..., go test -race ./internal/runecore, go vet, gofmt all clean.
  • Mutation spot-check on the new gate (draft marked authoritative → draft test RED → restored).
  • Engine-level fake-model tests cover absent/draft/expired/out-of-scope/corrupt authority incl. shell-mediated mutation; argument tests pin byte-for-byte file preservation.
  • Plan + discharge table: plans/2026-10-25-tool-boundary-audits.md.

Follow-ups (out of scope here, recorded in the plan)

  • refusal.go tier-2 can classify a truthful authority paraphrase as a false capability claim (spurious correction turn).
  • run_command authority is workdir-anchored — the law is the door, not a sandbox.
## Summary Repairs the two HIGH tool-boundary defects from the owner code audit **T12** (reproduced on frozen master a52624b3, re-verified on current master 79ff61b3 before any repair): 1. **Mutation family ran with no construction authority.** `runecore.ExecuteGatedTool` now crosses two doors before write_file/edit_file/run_command effects (`internal/runecore/authority.go`): wire-boundary argument validation, then the construction-authority consult — Go I/O reads the nearest construction store walking up from the mutation site (run_command's door is its **workdir**); scope matching mirrors the parity-frozen `CheckScope` mechanics (D33 research verdict: no Rust crate provides the runtime path-scope decision — construction_decision resolves need→surface at adoption only — so the existing Go-side mechanics are reused verbatim, no new Go↔Rust crossing); `draft` is not authority, `closed/failed/abandoned` are expired; **missing/broken/uncovered authority fails closed** with the typed envelope the model reads: `no open construction contract covers this path — open one via the construction interface`. 2. **Destructive default truncated files.** `argStr("content","")` turned missing/null/numeric/bool content into a 0-byte overwrite reported as success. Required-field presence + string-type is now enforced exactly where the schema advertises it (write_file `content`/`path`, edit_file `search`/`replace`, run_command `command`); an explicitly-supplied empty string stays legal. ## Constraints honored - **D49**: no tool is removed from any mode; the consent card stays work-promotion — the gate adds the scaffolding authority at mutation doors, it does not gate capability (D49's own "real safety layer" text). - **D57**: refusal wording is action-directive; refusal.go untouched (interplay flagged in the plan's FOL). - **Scaffolding law**: contract-first — `ADMIT-tool-boundary-audits-20261025` minted via the real construction interface (`scripts/admit_wave_tool_boundary.py`) naming every surface; the pre-commit landing gate verified coverage. ## Verification - Red-first: new tests failed against unpatched master with the defect signatures verbatim (`"wrote … (0 bytes)"`, shell executed, file clobbered) — then green after the repair; `go test ./...`, `go test -race ./internal/runecore`, `go vet`, `gofmt` all clean. - Mutation spot-check on the new gate (draft marked authoritative → draft test RED → restored). - Engine-level fake-model tests cover absent/draft/expired/out-of-scope/corrupt authority incl. shell-mediated mutation; argument tests pin byte-for-byte file preservation. - Plan + discharge table: `plans/2026-10-25-tool-boundary-audits.md`. ## Follow-ups (out of scope here, recorded in the plan) - refusal.go tier-2 can classify a truthful authority paraphrase as a false capability claim (spurious correction turn). - run_command authority is workdir-anchored — the law is the door, not a sandbox.
conductor added 1 commit 2026-10-26 00:31:28 +00:00
feat(runecore): construction-authority doors at the mutation family + wire-boundary argument validation (audit T12)
deploy / deploy (push) Skipped
CI Pipeline / lint (push) Canceled after 0s
CI Pipeline / unit-tests (push) Canceled after 0s
CI Pipeline / go-surface (push) Canceled after 0s
CI Pipeline / rust-surface (push) Canceled after 0s
CI Pipeline / canary (push) Canceled after 0s
CI Pipeline / best-practices (push) Canceled after 0s
CI Pipeline / documentation (push) Canceled after 0s
CI Pipeline / type-check (push) Canceled after 0s
CI Pipeline / gitea-offline (push) Canceled after 0s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
Auto-label / auto-label (pull_request) Successful in 4s
Local-Model First-Pass Review (#131) / first-pass-review (pull_request) Successful in 22s
CI Pipeline / lint (pull_request) Failing after 50s
CI Pipeline / go-surface (pull_request) Failing after 28s
CI Pipeline / rust-surface (pull_request) Failing after 8s
CI Pipeline / unit-tests (pull_request) Failing after 1m30s
CI Pipeline / best-practices (pull_request) Successful in 4s
CI Pipeline / documentation (pull_request) Successful in 4s
CI Pipeline / type-check (pull_request) Failing after 43s
CI Pipeline / canary (pull_request) Failing after 1m7s
Spec gate (headless) / spec-gate (pull_request) Successful in 17s
CI Pipeline / gitea-offline (pull_request) Successful in 21s
CI Pipeline / required-checks (pull_request) Failing after 1s
CI Pipeline / CI Pipeline / notify-event-bridge (pull_request) Failing after 6s
be625b7f90
Two HIGH tool-boundary findings from the owner code audit (base
a52624b3, re-verified on current master 79ff61b3 before repair:

1) ExecuteGatedTool dispatched write_file/edit_file/run_command with
   NO construction-authority consult. Mutation calls now cross two
   doors before effects (authority.go): required-argument validation
   at the wire boundary — the argStr("content","") destructive
   default turned missing/null/numeric content into a 0-byte overwrite
   reporting success (explicit empty string stays legal) — then the
   construction-authority consult: Go I/O reads the nearest
   store/.rune store walking up from the mutation site (run_command's
   door is its workdir), scope matching mirrors the parity-frozen
   CheckScope mechanics (D33 verdict: no Rust crate provides the
   runtime path-scope decision; no new crossing invented), draft/
   closed/failed/abandoned authority refuses, missing/broken authority
   FAILS CLOSED with the typed envelope the model reads: 'no open
   construction contract covers this path — open one via the
   construction interface'. D49 holds: no tool is removed from any
   mode and the consent card stays work-promotion.

2) args validation: presence + string type enforced exactly where the
   schema advertises it (write_file content/path, edit_file
   search/replace/path, run_command command).

Red-first evidence: engine-level fake-model tests (absent/draft/
expired/out-of-scope/corrupt authority incl. shell-mediated
run_command) plus argument-type cases with byte-for-byte file
preservation; mutation spot-check (draft marked authoritative ->
draft test RED -> restored). Admission
ADMIT-tool-boundary-audits-20261025; plan:
plans/2026-10-25-tool-boundary-audits.md
gitea-actions Bot added the P1 — highbuggovernancememoryperception labels 2026-10-26 00:31:33 +00:00

🤖 Headless spec gate (non-blocking, #204 first slice)

Spec-gate agent produced no text output — check runner logs.

Deterministic floors still govern the merge

This comment is advisory. Required checks (lint, tests, canaries, type-check, coverage, dependency lock, impact gate) remain the merge authority per docs/adversarial-review.md proportionality.

🤖 **Headless spec gate (non-blocking, #204 first slice)** Spec-gate agent produced no text output — check runner logs. <details><summary>Deterministic floors still govern the merge</summary> This comment is advisory. Required checks (lint, tests, canaries, type-check, coverage, dependency lock, impact gate) remain the merge authority per docs/adversarial-review.md proportionality.</details>
conductor added 1 commit 2026-10-26 00:41:10 +00:00
docs(plans): CI observation + refusal TUI-visibility for PR #2619 (audit T12)
CI Pipeline / lint (push) Canceled after 0s
CI Pipeline / unit-tests (push) Canceled after 0s
CI Pipeline / go-surface (push) Canceled after 0s
CI Pipeline / rust-surface (push) Canceled after 0s
CI Pipeline / canary (push) Canceled after 0s
CI Pipeline / best-practices (push) Canceled after 0s
CI Pipeline / documentation (push) Canceled after 0s
CI Pipeline / type-check (push) Canceled after 0s
CI Pipeline / gitea-offline (push) Canceled after 0s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
deploy / deploy (push) Skipped
Local-Model First-Pass Review (#131) / first-pass-review (pull_request) Successful in 24s
Spec gate (headless) / spec-gate (pull_request) Successful in 27s
CI Pipeline / lint (pull_request) Failing after 53s
CI Pipeline / go-surface (pull_request) Failing after 24s
CI Pipeline / rust-surface (pull_request) Failing after 10s
CI Pipeline / unit-tests (pull_request) Failing after 1m25s
CI Pipeline / best-practices (pull_request) Successful in 3s
CI Pipeline / documentation (pull_request) Successful in 3s
CI Pipeline / canary (pull_request) Failing after 1m5s
CI Pipeline / type-check (pull_request) Failing after 48s
CI Pipeline / gitea-offline (pull_request) Successful in 14s
CI Pipeline / required-checks (pull_request) Failing after 1s
CI Pipeline / CI Pipeline / notify-event-bridge (pull_request) Failing after 11s
70e6c72fb4

🤖 Headless spec gate (non-blocking, #204 first slice)

Spec-gate agent produced no text output — check runner logs.

Deterministic floors still govern the merge

This comment is advisory. Required checks (lint, tests, canaries, type-check, coverage, dependency lock, impact gate) remain the merge authority per docs/adversarial-review.md proportionality.

🤖 **Headless spec gate (non-blocking, #204 first slice)** Spec-gate agent produced no text output — check runner logs. <details><summary>Deterministic floors still govern the merge</summary> This comment is advisory. Required checks (lint, tests, canaries, type-check, coverage, dependency lock, impact gate) remain the merge authority per docs/adversarial-review.md proportionality.</details>
Some required checks failed
CI Pipeline / lint (push) Canceled after 0s
CI Pipeline / unit-tests (push) Canceled after 0s
CI Pipeline / go-surface (push) Canceled after 0s
CI Pipeline / rust-surface (push) Canceled after 0s
CI Pipeline / canary (push) Canceled after 0s
CI Pipeline / best-practices (push) Canceled after 0s
CI Pipeline / documentation (push) Canceled after 0s
CI Pipeline / type-check (push) Canceled after 0s
CI Pipeline / gitea-offline (push) Canceled after 0s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
deploy / deploy (push) Skipped
Local-Model First-Pass Review (#131) / first-pass-review (pull_request) Successful in 24s
Spec gate (headless) / spec-gate (pull_request) Successful in 27s
CI Pipeline / lint (pull_request) Failing after 53s
CI Pipeline / go-surface (pull_request) Failing after 24s
CI Pipeline / rust-surface (pull_request) Failing after 10s
CI Pipeline / unit-tests (pull_request) Failing after 1m25s
CI Pipeline / best-practices (pull_request) Successful in 3s
CI Pipeline / documentation (pull_request) Successful in 3s
CI Pipeline / canary (pull_request) Failing after 1m5s
CI Pipeline / type-check (pull_request) Failing after 48s
CI Pipeline / gitea-offline (pull_request) Successful in 14s
CI Pipeline / required-checks (pull_request) Failing after 1s
Required
Details
CI Pipeline / CI Pipeline / notify-event-bridge (pull_request) Failing after 11s
Some required checks were not successful.
This pull request is blocked because it's outdated.
You are not authorized to merge this pull request.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/tool-boundary-audits:fix/tool-boundary-audits
git checkout fix/tool-boundary-audits
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: conductor/rune#2619