Files
wehub-resource-sync bf9395e022
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / results (push) Has been cancelled
CI / deadcode (push) Has been cancelled
CI / e2e-live (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:54 +08:00
..

Example: read-only policy

A policy plugin that installs a Rule allowing only docs/* and im/* read commands. Any write command produces a structured command_denied envelope.

Build & run

cd extension/platform/examples/readonly-policy
go build -o readonly-cli .

./readonly-cli config policy show
# {
#   "source": "plugin",
#   "source_name": "readonly",
#   "denied_paths": N,
#   "rule": {
#     "name": "agent-readonly",
#     "allow": ["docs/**", "im/**"],
#     "deny": [],
#     "max_risk": "read",
#     "identities": [],
#     "allow_unannotated": false
#   }
# }

./readonly-cli docs +update --doc-token X --content Y
# {"ok":false,"error":{
#   "type":"command_denied",
#   "detail":{
#     "layer":"policy",
#     "policy_source":"plugin:readonly",
#     "rule_name":"agent-readonly",
#     "reason_code":"write_not_allowed"
#   }
# }}

./readonly-cli docs +fetch --doc-token X
# Normal read response (assuming credentials)

Key points

  • Restrict(&Rule{...}) is the only call needed — the Builder flips Capabilities to Restricts=true, FailurePolicy=FailClosed automatically. A policy plugin that silently fails to install would erase the security boundary, so FailClosed is enforced.
  • MaxRisk: platform.RiskRead rejects any command annotated write / high-risk-write.
  • AllowUnannotated is left default (false): unannotated commands are denied with risk_not_annotated. Set it to true if you need a gradual-adoption window for the lark-cli main tree.

Caveats

  • A binary may have only one plugin calling Restrict(). Two policy plugins is a deliberate plugin_conflict configuration error.
  • This Rule shadows any ~/.lark-cli/policy.yml — plugin Rule wins per the resolver precedence.