diff --git a/docs/guide/policies.md b/docs/guide/policies.md index 3d138cc..7d8bc3e 100644 --- a/docs/guide/policies.md +++ b/docs/guide/policies.md @@ -1,6 +1,14 @@ -# Policies and the five gates +# Policies and rules -OpenAgentLock policy is **deterministic YAML**. No LLM lives inside the evaluator. A rule is a path-shape match plus a verdict. Verdicts are `allow`, `deny`, or `skip` — there is **no** `ask` verdict in the default path, and the schema rejects it at load time. +OpenAgentLock policy is **deterministic YAML**. No LLM lives inside the evaluator. A rule (called a *gate* in the YAML schema) is a path-shape match plus a verdict. Verdicts are `allow`, `deny`, or `skip` — there is **no** `ask` verdict in the default path, and the schema rejects it at load time. + +Most operators do not author policies from scratch. The shape of a real-world policy is: + +1. The **five built-in defaults** the daemon boots with — useful baseline, intentionally narrow. +2. A handful of **community rules** pulled from [openagentlock/rules](https://openagentlock.github.io/rules/) on top. +3. Optionally, a **private rules registry** with internal-to-your-org rules. + +This page covers all three plus the YAML schema underneath them. ## Two switches: `mode` and rule actions @@ -11,9 +19,56 @@ Two things determine whether a tool call is blocked: `PATCH /v1/mode` toggles the daemon-level switch, which is the **outer** override. In `firewall` mode it escalates any policy-monitor match back to `deny`; in `monitor` mode it suppresses any policy `deny` to `allow`. Use it as the global kill switch — per-rule `mode: monitor` remains the right tool for staging individual rules during rollout. -## The five baseline gates +## The community rules registry — start here + +The [openagentlock/rules](https://github.com/openagentlock/rules) registry hosts ready-to-install gates the community has tested in the wild. Browse the catalog at , copy the install one-liner, and paste: + +```bash +# Upstream is auto-registered on first sync. +agentlock rules sync + +# Search the catalog by name, tag, or description. +agentlock rules search exfil +agentlock rules search bash + +# Install — the rule's gate block is POSTed to the daemon's +# /v1/policy/gates/yaml endpoint and lands in the live policy with a +# fresh hash. Existing sessions stay pinned to the old hash until they +# reload, so installs never invalidate in-flight work. +agentlock rules install exfil.curl-with-env +agentlock rules install rogue.secret-read + +# Remove later — by gate id, the same /v1/policy/gates/{id} DELETE +# handler the dashboard uses. +agentlock rules uninstall exfil.curl-with-env +``` + +`agentlock rules` is wired through to the same daemon endpoint the [local web dashboard](dashboard.md) uses, so installs are immediately visible at `http://127.0.0.1:7879/rules`. + +### Pin a private registry too + +Most teams want a few internal-only rules alongside the upstream catalog. Any Git repo with the same `rules//rule.yaml` layout works: + +```bash +# Tap your private registry. Multiple registries are merged at sync time. +agentlock rules add https://github.com/your-org/your-rules.git + +# Confirm what's wired up. +agentlock rules sources + +# Remove a registry (local-only — does not touch installed gates). +agentlock rules remove your-org-your-rules +``` + +If a rule id collides between two registries the CLI errors out and asks you to disambiguate with `:`. The same rule.yaml schema applies to both registries; the registry's own CI [validates against `schema/rule.schema.json`](https://github.com/openagentlock/rules/blob/main/schema/rule.schema.json) on every PR. -Every install ships `policies/default.yaml` with five gates in monitor mode: +### Authoring new rules with an agent + +When the catalog doesn't have what you need, the [openagentlock/skills](https://github.com/openagentlock/skills) toolkit ships agent skills (Claude Code, Cursor, Codex) that turn natural-language intent into a `rule.yaml` and run `agentlock rules install` to land it. See the `block-pattern` skill for the canonical "block this command shape" flow. + +## The five built-in defaults + +When the daemon boots, it loads `policies/default.yaml`, which ships these five gates in monitor mode. They are intentionally narrow — most operators leave them on and add registry rules on top.
@@ -54,7 +109,9 @@ Reads of `.env`, `~/.ssh`, `~/.aws/credentials`, anywhere a secret-shaped path a
-## Authoring rules +The community registry has tighter / opinionated variants of several of these — e.g. `rogue.git-force-push` (only deny force-push to main / develop / release), `exfil.curl-with-env` (catch the `$ENV_VAR` exfil shape specifically), `rogue.eval-untrusted` (deny dynamic-eval shells). Install whichever match your threat model. + +## Authoring rules from scratch Two rules of thumb: @@ -62,32 +119,6 @@ Two rules of thumb: > **Use the dashboard.** The local web dashboard (`127.0.0.1:7879`) lets you right-click a logged tool call and "block this next time" — it generates a starter rule from the call's shape. Iterate from there. -## Installing community rules - -The [openagentlock/rules](https://github.com/openagentlock/rules) registry ships ready-to-pin gates. Browse them at , then install via CLI: - -```bash -# upstream is auto-registered on first sync -agentlock rules sync -agentlock rules search exfil - -# install one rule into the live policy -agentlock rules install exfil.curl-with-env - -# remove later -agentlock rules uninstall exfil.curl-with-env -``` - -The rule's `gate:` block is POSTed to `/v1/policy/gates/yaml` and lands in the live policy with a fresh hash; existing sessions stay pinned to the old hash until they reload, so installs never invalidate in-flight work. - -You can register additional registries (private internal rules, etc.): - -```bash -agentlock rules add https://github.com/your-org/your-rules.git -agentlock rules sources -agentlock rules remove your-org-your-rules # local-only — does not touch installed gates -``` - ## Authoring via the dashboard Open . The dashboard is shaped like a firewall admin UI: @@ -100,23 +131,26 @@ Changes are validated against the policy schema before being written, and a snap ## Policy schema -The full schema lives in [`api/openapi.yaml`](https://github.com/openagentlock/OpenAgentLock/blob/main/control-plane/api/openapi.yaml) under `components.schemas.Policy`. Minimal example: +The full schema lives in [`api/openapi.yaml`](https://github.com/openagentlock/OpenAgentLock/blob/main/control-plane/api/openapi.yaml) under `components.schemas.Policy`. Community-rule authors should match the registry shape documented in [`schema/rule.schema.json`](https://github.com/openagentlock/rules/blob/main/schema/rule.schema.json). Minimal example: ```yaml +version: 1 mode: monitor - -evaluator: - on_miss: allow - on_hit: deny - +defaults: + bash: allow gates: - id: rogue.secret-read - when: - command_regex: '(\.env(\b|[._-])|/\.ssh(/|\b)|/\.aws(/|\b)|credentials)' - on_hit: deny - severity: high + match: + tool: Bash + any_command_regex: + - '(\.env(\b|[._-])|/\.ssh(/|\b)|/\.aws(/|\b)|credentials)' + evaluate: + - kind: always + action: deny ``` +The daemon's regex engine is Go RE2 — **no negative lookahead, no backreferences**. If you find yourself reaching for `(?!…)`, invert the match: write a positive regex for the dangerous shape rather than a negative regex around the safe one. + ## Enforcement vs monitor - **Monitor** — every gate matches but the verdict is downgraded to `allow` for the harness. Use this on day one. diff --git a/mkdocs.yml b/mkdocs.yml index f4bc5c3..23b1c51 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -106,7 +106,7 @@ nav: - Guide: - Getting started: guide/getting-started.md - Installation: guide/installation.md - - Policies and the five gates: guide/policies.md + - Policies and rules: guide/policies.md - Signers: guide/signers.md - The ledger: guide/ledger.md - Local web dashboard: guide/dashboard.md