Skip to content

Policy: add agent-scoped policy overlays#85817

Merged
giodl73-repo merged 9 commits into
openclaw:mainfrom
giodl73-repo:policy-agent-scoped-design
May 25, 2026
Merged

Policy: add agent-scoped policy overlays#85817
giodl73-repo merged 9 commits into
openclaw:mainfrom
giodl73-repo:policy-agent-scoped-design

Conversation

@giodl73-repo

@giodl73-repo giodl73-repo commented May 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements Policy overlays under scopes.<scopeName> for policy sections whose evidence is attributable to runtime agent ids: tools and agents.workspace.

Scopes are purpose-named policy blocks. The scope name is descriptive only; matching uses selector values inside the block. In this PR every scoped block must declare agentIds, and those ids are normalized OpenClaw runtime agent ids. A scope without a selector is invalid, and a selector can only carry sections that Policy can evaluate for that selector.

Selector rule in this PR:

Selector Supported scoped sections Meaning
agentIds tools, agents.workspace Apply those policy claims only to evidence for the listed runtime agent ids; ids absent from agents.list[] are evaluated against inherited global/default posture.

Scope blocks reuse the normal policy section grammar instead of a per-agent mini-language. The overlay model is additive and config-conformance only: top-level tools and agents.workspace claims still run, while scoped blocks can add stricter claims and emit their own findings. Unsupported scoped sections are rejected rather than ignored. This PR does not add runtime enforcement.

Strictness metadata validates scoped overlays: allowlist-subset, denylist-superset, requires-true, requires-false, and exact-list. tools.denyTools uses existing group and glob coverage semantics.

Example shape:

{
  "scopes": {
    "release-workspace": {
      "agentIds": ["release-agent", "support-agent"],
      "agents": {
        "workspace": {
          "allowedAccess": ["none", "ro"],
          "denyTools": ["write", "edit", "apply_patch"]
        }
      }
    },
    "release-tools-lockdown": {
      "agentIds": ["release-agent"],
      "tools": {
        "exec": {
          "allowHosts": ["sandbox"],
          "requireAsk": ["always"]
        },
        "alsoAllow": {
          "expected": []
        },
        "denyTools": ["group:runtime", "group:fs"]
      }
    }
  }
}

The same agent can appear in multiple scopes when the scopes cover different policy fields. If two scopes set the same field for the same agent, the later value must be equally or more restrictive according to the field metadata.

The adjacent agent CI fixes previously carried in this branch were split out:

Verification

  • OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/tmp/openclaw-85817-policy-only node scripts/run-vitest.mjs extensions/policy/src/doctor/register.test.ts extensions/policy/src/cli.test.ts -- --reporter=dot -> 2 files, 184 tests passed
  • pnpm exec oxfmt --check docs/cli/policy.md docs/plan/policy-agent-scoped-overlays.md docs/plugins/reference/policy.md extensions/policy/src/doctor/register.ts extensions/policy/src/doctor/register.test.ts
  • pnpm exec oxlint extensions/policy/src/doctor/register.ts extensions/policy/src/doctor/register.test.ts
  • pnpm docs:check-mdx docs/cli/policy.md docs/plugins/reference/policy.md docs/plan/policy-agent-scoped-overlays.md
  • git diff --check

Real behavior proof

Behavior addressed: Policy conformance can express stricter workspace and tool posture claims for named policy scopes that target explicit runtime agent ids without weakening deployment-wide policy claims.

Real environment tested: WSL Ubuntu 24.04 checkout under /root/src/openclaw-policy-agent-scoped-design, with disposable OPENCLAW_HOME, disposable OPENCLAW_CONFIG_PATH, and a disposable workspace containing policy.jsonc.

Exact steps or command run after this patch: created a disposable config/workspace, then invoked the policy check command implementation from this source-tree head with json: true and the disposable workspace cwd. The normal pnpm openclaw policy check --json wrapper attempted an unrelated source rebuild first in this checkout, so this proof calls the same Policy command path directly through extensions/policy/src/cli.ts.

Evidence after fix: the redacted output below shows global/default workspace and tool findings, scoped release-workspace findings for both listed agents, and scoped release-tools-lockdown findings only for release-agent.

Observed result after fix: the policy check returned ok: false with an attestation and expected findings for top-level and scoped requirements. Focused tests also passed: 2 files and 184 tests; formatter, linter, docs MDX, and git diff --check passed.

Redacted policy check --json output excerpt:

{
  "ok": false,
  "attestation": {
    "checkedAt": "2026-05-25T15:00:41.933Z",
    "policy": {
      "path": "policy.jsonc",
      "hash": "sha256:06c55213e533b5e00b8f99d4c1c62e552a91d78d344213be05c5b333bcf5884f"
    },
    "workspace": {
      "scope": "policy",
      "hash": "sha256:dbe4edab363158aa5579067522b4bbffc4f1c11c135628ebce131f1f542810ab"
    },
    "findingsHash": "sha256:56be99850c4d0df97a7e98a1ffa3ff1fd44e07d4ce18ca1196bb30d36bdbee7f",
    "attestationHash": "sha256:636272a96eccb7c9dadabc635c5c317532c15962929ca2e7b0ac833c30b1d4bc"
  },
  "evidence": {
    "agentWorkspace": [
      {
        "id": "agents-defaults-workspace-access",
        "kind": "workspaceAccess",
        "source": "oc://openclaw.config/agents/defaults/sandbox/workspaceAccess",
        "scope": "defaults",
        "value": "rw",
        "sandboxMode": "all",
        "sandboxModeSource": "oc://openclaw.config/agents/defaults/sandbox/mode",
        "sandboxEnabled": true,
        "explicit": true
      },
      {
        "id": "release-agent-workspace-access",
        "kind": "workspaceAccess",
        "source": "oc://openclaw.config/agents/list/#0/sandbox/workspaceAccess",
        "scope": "agent",
        "agentId": "release-agent",
        "value": "rw",
        "sandboxMode": "all",
        "sandboxModeSource": "oc://openclaw.config/agents/list/#0/sandbox/mode",
        "sandboxEnabled": true,
        "explicit": true
      },
      {
        "id": "support-agent-workspace-access",
        "kind": "workspaceAccess",
        "source": "oc://openclaw.config/agents/list/#1/sandbox/workspaceAccess",
        "scope": "agent",
        "agentId": "support-agent",
        "value": "ro",
        "sandboxMode": "all",
        "sandboxModeSource": "oc://openclaw.config/agents/list/#1/sandbox/mode",
        "sandboxEnabled": true,
        "explicit": true
      }
    ],
    "toolPosture": [
      {
        "id": "release-agent-alsoAllow",
        "kind": "alsoAllow",
        "source": "oc://openclaw.config/agents/list/#0/tools/alsoAllow",
        "scope": "agent",
        "agentId": "release-agent",
        "entries": [
          "read",
          "gateway"
        ],
        "explicit": true
      },
      {
        "id": "release-agent-deny",
        "kind": "deny",
        "source": "oc://openclaw.config/agents/list/#0/tools/deny",
        "scope": "agent",
        "agentId": "release-agent",
        "entries": [],
        "explicit": false
      },
      {
        "id": "release-agent-exec-host",
        "kind": "execHost",
        "source": "oc://openclaw.config/agents/list/#0/tools/exec/host",
        "scope": "agent",
        "agentId": "release-agent",
        "value": "node",
        "explicit": true
      },
      {
        "id": "support-agent-alsoAllow",
        "kind": "alsoAllow",
        "source": "oc://openclaw.config/agents/list/#1/tools/alsoAllow",
        "scope": "agent",
        "agentId": "support-agent",
        "entries": [],
        "explicit": false
      },
      {
        "id": "support-agent-deny",
        "kind": "deny",
        "source": "oc://openclaw.config/agents/list/#1/tools/deny",
        "scope": "agent",
        "agentId": "support-agent",
        "entries": [],
        "explicit": false
      },
      {
        "id": "support-agent-exec-host",
        "kind": "execHost",
        "source": "oc://openclaw.config/agents/list/#1/tools/exec/host",
        "scope": "agent",
        "agentId": "support-agent",
        "value": "sandbox",
        "explicit": true
      },
      {
        "id": "tools-alsoAllow",
        "kind": "alsoAllow",
        "source": "oc://openclaw.config/tools/alsoAllow",
        "scope": "global",
        "entries": [],
        "explicit": false
      },
      {
        "id": "tools-deny",
        "kind": "deny",
        "source": "oc://openclaw.config/tools/deny",
        "scope": "global",
        "entries": [],
        "explicit": false
      },
      {
        "id": "tools-exec-host",
        "kind": "execHost",
        "source": "oc://openclaw.config/tools/exec/host",
        "scope": "global",
        "value": "node",
        "explicit": true
      }
    ]
  },
  "findings": [
    {
      "checkId": "policy/agents-workspace-access-denied",
      "message": "agents.defaults sandbox workspaceAccess 'rw' is not allowed by policy.",
      "ocPath": "oc://openclaw.config/agents/defaults/sandbox/workspaceAccess",
      "requirement": "oc://policy.jsonc/agents/workspace/allowedAccess"
    },
    {
      "checkId": "policy/agents-workspace-access-denied",
      "message": "agent 'release-agent' sandbox workspaceAccess 'rw' is not allowed by policy.",
      "ocPath": "oc://openclaw.config/agents/list/#0/sandbox/workspaceAccess",
      "requirement": "oc://policy.jsonc/agents/workspace/allowedAccess"
    },
    {
      "checkId": "policy/agents-workspace-access-denied",
      "message": "agent 'release-agent' sandbox workspaceAccess 'rw' is not allowed by policy.",
      "ocPath": "oc://openclaw.config/agents/list/#0/sandbox/workspaceAccess",
      "requirement": "oc://policy.jsonc/scopes/release-workspace/agents/workspace/allowedAccess"
    },
    {
      "checkId": "policy/agents-workspace-access-denied",
      "message": "agent 'support-agent' sandbox workspaceAccess 'ro' is not allowed by policy.",
      "ocPath": "oc://openclaw.config/agents/list/#1/sandbox/workspaceAccess",
      "requirement": "oc://policy.jsonc/scopes/release-workspace/agents/workspace/allowedAccess"
    },
    {
      "checkId": "policy/tools-exec-host-unapproved",
      "message": "agent 'release-agent' uses unapproved exec host 'node'.",
      "ocPath": "oc://openclaw.config/agents/list/#0/tools/exec/host",
      "requirement": "oc://policy.jsonc/tools/exec/allowHosts"
    },
    {
      "checkId": "policy/tools-exec-host-unapproved",
      "message": "global tools config uses unapproved exec host 'node'.",
      "ocPath": "oc://openclaw.config/tools/exec/host",
      "requirement": "oc://policy.jsonc/tools/exec/allowHosts"
    },
    {
      "checkId": "policy/tools-exec-host-unapproved",
      "message": "agent 'release-agent' uses unapproved exec host 'node'.",
      "ocPath": "oc://openclaw.config/agents/list/#0/tools/exec/host",
      "requirement": "oc://policy.jsonc/scopes/release-tools-lockdown/tools/exec/allowHosts"
    },
    {
      "checkId": "policy/tools-also-allow-unexpected",
      "message": "agent 'release-agent' has unexpected tools.alsoAllow entry 'gateway'.",
      "ocPath": "oc://openclaw.config/agents/list/#0/tools/alsoAllow",
      "requirement": "oc://policy.jsonc/scopes/release-tools-lockdown/tools/alsoAllow/expected"
    },
    {
      "checkId": "policy/tools-also-allow-unexpected",
      "message": "agent 'release-agent' has unexpected tools.alsoAllow entry 'read'.",
      "ocPath": "oc://openclaw.config/agents/list/#0/tools/alsoAllow",
      "requirement": "oc://policy.jsonc/scopes/release-tools-lockdown/tools/alsoAllow/expected"
    },
    {
      "checkId": "policy/tools-required-deny-missing",
      "message": "agent 'release-agent' does not deny required tool 'exec'.",
      "ocPath": "oc://openclaw.config/agents/list/#0/tools/deny",
      "requirement": "oc://policy.jsonc/scopes/release-tools-lockdown/tools/denyTools"
    },
    {
      "checkId": "policy/tools-required-deny-missing",
      "message": "agent 'release-agent' does not deny required tool 'process'.",
      "ocPath": "oc://openclaw.config/agents/list/#0/tools/deny",
      "requirement": "oc://policy.jsonc/scopes/release-tools-lockdown/tools/denyTools"
    },
    {
      "checkId": "policy/tools-required-deny-missing",
      "message": "agent 'release-agent' does not deny required tool 'code_execution'.",
      "ocPath": "oc://openclaw.config/agents/list/#0/tools/deny",
      "requirement": "oc://policy.jsonc/scopes/release-tools-lockdown/tools/denyTools"
    }
  ]
}

What was not tested: live channel, sandbox, ingress, or runtime tool enforcement. This PR intentionally adds Policy conformance and audit grammar, not runtime enforcement.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation extensions: policy size: XL maintainer Maintainer-authored PR labels May 23, 2026
@clawsweeper

clawsweeper Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed May 25, 2026, 11:24 AM ET / 15:24 UTC.

Summary
Adds agent-scoped Policy plugin overlays for tools and agents.workspace, with docs and doctor regression coverage.

PR surface: Source +881, Tests +939, Docs +257. Total +2077 across 5 files.

Reproducibility: not applicable. this is a new Policy plugin capability, not a reported current-main bug. The PR body does include a concrete after-patch policy-check proof showing the intended scoped/global finding behavior.

Review metrics: 2 noteworthy metrics.

  • Policy grammar surface: 1 added. scopes.<scopeName> with required agentIds is a new user-authored policy surface that maintainers should approve before release.
  • Scoped policy inventory: 10 scoped fields, 2 new check ids. The new fields and check ids can affect policy-check output, attestation hashes, and downstream automation.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

  • This adds a new policy.jsonc grammar surface and two new policy check ids, so existing policy automation or attestation consumers may need an intentional update when the check set changes.
  • Policy conformance is used as an audit/security signal; maintainers should explicitly approve the additive scoped-overlay semantics and inherited-default matching before relying on the new findings as a boundary.
  • The PR intentionally rejects unsupported scoped sections and weak scoped overrides, which is safer but may surprise operators expecting per-agent exception semantics.

Maintainer options:

  1. Approve the scoped policy contract (recommended)
    Maintainers can land once they explicitly accept the additive-only scopes.<scopeName>.agentIds grammar, inherited-default matching, and changed check inventory.
  2. Require upgrade proof first
    Maintainers can ask for additional before/after proof around accepted attestation hashes or automation that consumes exact check ids/counts before merge.
  3. Pause for exception semantics
    If maintainers want scoped rules to loosen a global policy for named agents, this PR should pause because the current implementation deliberately supports stricter additive overlays only.

Next step before merge
The remaining action is maintainer/security approval of the new Policy grammar and upgrade semantics, not an automated repair.

Security
Cleared: No concrete supply-chain or secret-handling regression was found in the policy-only diff; the security-sensitive semantics remain a maintainer approval risk rather than a line-level security defect.

Review details

Best possible solution:

Land this as the canonical Policy overlay implementation only after maintainer/security approval of the new grammar and upgrade semantics, with maintainer-owned changelog/release notes handled during landing.

Do we have a high-confidence way to reproduce the issue?

Not applicable: this is a new Policy plugin capability, not a reported current-main bug. The PR body does include a concrete after-patch policy-check proof showing the intended scoped/global finding behavior.

Is this the best way to solve the issue?

Unclear pending maintainer approval: the implementation is coherent and covered, but it chooses additive stricter-only policy overlays for a security-sensitive config surface. If maintainers want exception-style weakening of global rules, the product direction should change before merge.

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 89aea9b84333.

Label changes

Label changes:

  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦞 diamond lobster, so this older rating label is no longer current.

Label justifications:

  • P2: This is a normal-priority Policy plugin feature with security/audit relevance but no confirmed active regression or outage.
  • merge-risk: 🚨 compatibility: The PR adds a new policy grammar and check ids that can affect policy file validation, check counts, and accepted attestation hashes.
  • merge-risk: 🚨 security-boundary: Policy findings are an audit/security signal, so the scoped semantics need explicit approval before they become trusted conformance output.
  • merge-risk: 🚨 automation: Automation consuming policy check --json, check ids, check counts, or attestation hashes may need updates after the new checks land.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • feature: ✨ showcase: ClawSweeper spotlight: unusually compelling feature idea for maintainer attention. Per-agent policy overlays are a high-value operator capability because they can replace custom audit scripts with first-class Policy plugin conformance and attestation.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes redacted after-fix live output from a disposable environment showing scoped and top-level Policy findings for the new overlay behavior.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes redacted after-fix live output from a disposable environment showing scoped and top-level Policy findings for the new overlay behavior.
Evidence reviewed

PR surface:

Source +881, Tests +939, Docs +257. Total +2077 across 5 files.

View PR surface stats
Area Files Added Removed Net
Source 1 962 81 +881
Tests 1 1002 63 +939
Docs 3 257 0 +257
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 5 2221 144 +2077

What I checked:

  • Repository policy read: Root, docs, and extensions AGENTS.md were read; the guidance treats config/default additions and policy/security boundaries as compatibility-sensitive and it affected the merge-risk review. (AGENTS.md:1, c4bce00727ec)
  • No matching maintainer notes: The only maintainer note in the checkout is Telegram-specific, so no Policy plugin note changed the review outcome.
  • Scoped policy metadata: The PR defines strictness metadata for 10 agent-scoped fields, including workspace access/tool deny posture and tool profile/fs/exec/elevated/alsoAllow/denyTools posture. (extensions/policy/src/doctor/register.ts:127, 5495febffce2)
  • Scoped shape validation: The PR requires agentIds, rejects unsupported scoped sections, and checks duplicate/overlapping scoped fields against strictness metadata before scoped findings run. (extensions/policy/src/doctor/register.ts:1287, 5495febffce2)
  • Scoped runtime evaluation: The implementation applies scoped workspace and tool posture findings only to matching normalized agent ids, falling back to defaults/global evidence when an agent id is absent from agents.list[]. (extensions/policy/src/doctor/register.ts:2445, 5495febffce2)
  • Regression coverage: The tests cover normalized agent ids, inherited default posture for absent scoped agents, independent global/scoped tool claims, scoped alsoAllow drift, and invalid scoped policy shapes. (extensions/policy/src/doctor/register.test.ts:3081, 5495febffce2)

Likely related people:

  • giodl73-repo: Authored the merged tool-posture conformance substrate and the current scoped-overlay implementation, so this is the clearest routing candidate for Policy overlay behavior. (role: feature owner / recent area contributor; confidence: high; commits: 1e2e6147480c, 5b98706fb763, f1d30bb738f0; files: extensions/policy/src/doctor/register.ts, extensions/policy/src/policy-state.ts, extensions/policy/src/doctor/register.test.ts)
  • galiniliev: Provided the earlier maintainer-facing review that identified the stacked tools.alsoAllow evidence false-negative and is assigned in the PR timeline. (role: reviewer / assigned follow-up owner; confidence: medium; files: extensions/policy/src/doctor/register.ts, extensions/policy/src/policy-state.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 23, 2026
@clawsweeper

clawsweeper Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

✨ Hatched: 🥚 common Clockwork Crabkin

Hatch command

Comment @clawsweeper hatch when this PR is hatchable.

Hatchability rules:

  • Merged PRs are hatchable.
  • Open PRs are hatchable when they are status: 👀 ready for maintainer look, status: 🚀 automerge armed, or labeled clawsweeper:automerge.
  • Closed unmerged PRs are hatchable only when one of those hatchable labels is still present in the durable record.

Rarity: 🥚 common.
Trait: keeps receipts.
Image traits: location release reef; accessory review stamp; palette seafoam, black, and opal; mood determined; pose standing beside its cracked shell; shell starlit enamel shell; lighting soft studio lighting; background gentle dashboard dots.
Share on X: post this hatch
Copy: My PR egg hatched a 🥚 common Clockwork Crabkin in ClawSweeper.

What is this egg doing here?
  • Eggs appear after the PR passes real-behavior proof. It is here for vibes, not verdicts: it does not change labels, ratings, merge decisions, or automation.
  • The shell reacts to review momentum: open follow-up work warms it up, re-review makes it wobble, and a clean final review lets it hatch.
  • Hatchability usually comes from sufficient real-behavior proof, no blocking P0/P1/P2 findings, no security attention needed, and clean correctness. A merged PR is already final, so merge makes the egg hatchable independently.
  • The hatch is seeded from this repository and PR number, so the same PR keeps the same creature; the reviewed head SHA can only change safe visual details.
  • Rarity is just collectible sparkle: 🥚 common, 🌱 uncommon, 💎 rare, ✨ glimmer, and 🌈 legendary.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 23, 2026
@galiniliev galiniliev self-assigned this May 23, 2026
@galiniliev

Copy link
Copy Markdown
Contributor

PR #85817 adds docs for agent-scoped policy overlays on top of a stacked Policy plugin runtime/docs change. The important surface is extensions/policy/src/policy-state.ts, extensions/policy/src/doctor/register.ts, and docs/cli/policy.md; this matters because policy conformance is used as an audit/security boundary.

By: Gio Della-Libera (@giodl73-repo, acct 2025-09-30) | OpenClaw: 125 PRs, 14 issues, 88 commits/12mo | GitHub: 5305 commits, 150 PRs, 29 issues, 18 reviews
Assignment: assigned to galiniliev on 2026-05-23 23:29 UTC, fresh.

Findings

[P1] tools.alsoAllow is omitted from policy evidence, so widened profiles can pass policy. Runtime treats alsoAllow as a real profile-widening control: resolveEffectiveToolPolicy reads agent/global alsoAllow and applies it at the profile stage in src/agents/pi-tools.policy.ts:475 and src/agents/pi-tools.policy.ts:511. The config schema also exposes it for global and per-agent tools in src/config/zod-schema.agent-runtime.ts:302, src/config/zod-schema.agent-runtime.ts:805, and src/config/zod-schema.agent-runtime.ts:1157. But the new policy evidence collector only pushes allow and deny lists in extensions/policy/src/policy-state.ts:884, with pushToolPostureList restricted to "allow" | "deny" at extensions/policy/src/policy-state.ts:1028. Result: a config like tools.profile="messaging" plus tools.alsoAllow=["exec"] can still satisfy tools.profiles.allow=["messaging"], and the accepted attestation hash will not drift for that privilege expansion. Add alsoAllow to tool posture evidence, include global/per-agent inherited handling, and add regression coverage for findings/attestation drift.

Provenance: introduced by this PR's stacked tool-posture implementation, commit 87bb37325b4a.

Best-fix verdict: don't merge as-is. The overlay design doc is reasonable, but the carried runtime policy stack has a real false-negative in the tool posture evidence contract.

Verification I performed: pnpm docs:list; live PR metadata/labels/assignment; git diff against the fetched PR ref; surrounding runtime/schema reads for tool policy merge semantics; live CI log inspection. Current CI is also UNSTABLE, but the visible failures I checked look unrelated to this diff: one xAI model alias expectation and one missing OPENAI_API_KEY startup failure in gateway reload tests.

@giodl73-repo giodl73-repo changed the title Docs: design agent-scoped policy overlays Policy: add agent-scoped policy overlays May 24, 2026
@giodl73-repo giodl73-repo force-pushed the policy-agent-scoped-design branch from 777f1cf to 54b063d Compare May 24, 2026 00:12
@giodl73-repo

giodl73-repo commented May 24, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @galiniliev. I rebased this on current main after #85482/#85795 landed, so the stacked tools.alsoAllow false-negative is no longer in this PR diff. Current main records global and per-agent alsoAllow as toolPosture evidence and has attestation coverage for those entries.

This PR is now the initial implementation for generic agent-scoped policy overlays under scopes.agents.<agentId>, limited to tools and agents.workspace where the evidence already carries agent identity. Global claims still run, scoped claims are additive, and unsupported scoped sections/keys are rejected rather than silently ignored.

I also added exact-list conformance for tools.alsoAllow.expected, including missing entries, unexpected entries, invalid shape handling, and the empty-list case where policy expects no additive grants.

Focused proof on the rebased head:

  • pnpm docs:list
  • pnpm exec oxfmt --check --threads=1 docs/cli/policy.md docs/plugins/reference/policy.md docs/plan/policy-agent-scoped-overlays.md extensions/policy/src/doctor/register.ts extensions/policy/src/doctor/register.test.ts
  • pnpm docs:check-mdx docs/cli/policy.md docs/plugins/reference/policy.md docs/plan/policy-agent-scoped-overlays.md
  • node scripts/run-vitest.mjs extensions/policy/src/doctor/register.test.ts extensions/policy/src/cli.test.ts -- --reporter=dot - 169 tests passed
  • pnpm exec oxlint extensions/policy/src/doctor/register.ts extensions/policy/src/doctor/register.test.ts
  • git diff --check
  • codex review --base origin/main - no accepted/actionable findings

Latest commit is signed and rebased on current origin/main: 4d46764cb7f53084433d7977fab59c3de1e53066.

@giodl73-repo giodl73-repo force-pushed the policy-agent-scoped-design branch 2 times, most recently from 13dc474 to dfde965 Compare May 24, 2026 14:37
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels May 25, 2026
@giodl73-repo giodl73-repo force-pushed the policy-agent-scoped-design branch from b3bfc75 to 28d0690 Compare May 25, 2026 14:38
@openclaw-barnacle openclaw-barnacle Bot removed the agents Agent runtime and tooling label May 25, 2026
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Cleaned this PR back to policy-only scope.

What changed:

Current #85817 diff is only:

  • docs/cli/policy.md
  • docs/plan/policy-agent-scoped-overlays.md
  • docs/plugins/reference/policy.md
  • extensions/policy/src/doctor/register.ts
  • extensions/policy/src/doctor/register.test.ts

Validation on the cleaned policy-only head:

  • OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/tmp/openclaw-85817-policy-only node scripts/run-vitest.mjs extensions/policy/src/doctor/register.test.ts extensions/policy/src/cli.test.ts -- --reporter=dot -> 2 files, 184 tests passed
  • pnpm exec oxfmt --check docs/cli/policy.md docs/plan/policy-agent-scoped-overlays.md docs/plugins/reference/policy.md extensions/policy/src/doctor/register.ts extensions/policy/src/doctor/register.test.ts
  • pnpm exec oxlint extensions/policy/src/doctor/register.ts extensions/policy/src/doctor/register.test.ts
  • pnpm docs:check-mdx docs/cli/policy.md docs/plugins/reference/policy.md docs/plan/policy-agent-scoped-overlays.md
  • git diff --check

No merge performed.

@clawsweeper

clawsweeper Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels May 25, 2026
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Added the requested redacted real policy-check proof to the PR body.

What changed:

  • Added disposable config/workspace proof for the cleaned policy-only head.
  • Included redacted JSON output showing top-level workspace/tool findings plus scoped release-workspace and release-tools-lockdown findings.
  • Kept the PR diff policy-only; no source changes were pushed for this proof update.

Note: in this WSL source checkout, pnpm openclaw policy check --json attempts an unrelated source rebuild first and currently fails before command execution on a missing protobufjs/google/protobuf/descriptor.json package asset. The proof therefore invokes the same Policy command implementation directly from extensions/policy/src/cli.ts with json: true, disposable OPENCLAW_HOME, disposable OPENCLAW_CONFIG_PATH, and disposable workspace cwd.

No merge performed.

@clawsweeper

clawsweeper Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Command router queued. I will update this comment with the next step.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 25, 2026
@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels May 25, 2026
@clawsweeper

clawsweeper Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation extensions: policy feature: ✨ showcase ClawSweeper spotlight: unusually compelling feature idea for maintainer attention. maintainer Maintainer-authored PR merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: XL status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants