allow or deny). Policies are authored in the dashboard or pushed via the API, versioned on each save, and published as a signed bundle that the SDK pulls every 30 seconds.
Anatomy
Fields
Rule conditions
A rule matches when every condition in its list matches (logical AND). Condition shape:Common fields
Versioning
Every save creates a new version. Versions can be:- draft — saved but not published. Visible in the editor, not in the bundle.
- active — currently published. There is at most one active version per policy.
- archived — was active, has been replaced. Kept for audit.
Dry-run
Before publishing, click Dry-run in the editor. Rubric replays the last 1000 audit events through the candidate policy and shows you:- How many events would have been allowed vs denied.
- Which agents are most affected.
- A diff against the currently-published version.
Scope: which agents does this policy enforce against?
Scope is prescriptive and operator-controlled. Every policy carries an explicit list of agents it enforces against, stored separately from the YAML. The list is editable on the policy detail page and required at publish time.
This is explicit opt-in by design. A newly-enrolled agent is unpoliced until an operator scopes a policy onto it — the cost of accidentally leaving a policy off one agent was judged lower than the cost of an over-broad policy quietly enforcing somewhere unintended.
How it ships
- Scope is not part of the policy YAML — it’s a separate per-policy agent list. Forking a template never carries scope across orgs; the fork prompts the operator for fresh agent selection.
- Each agent gets its own bundle slice. Editing scope on a published policy fans out fresh bundles to the affected agents only — no version bump, no SDK restart.
- Every scope add/remove is recorded in the audit ledger right alongside tool-call decisions, on the same tamper-evident chain. Config tampering is as detectable as decision tampering.
Required at publish
The dashboard disables the publish button until you pick at least one agent. Drafts are allowed to have empty scope — they’re not in the bundle anyway.Filtering rule logic by agent metadata
Conditions likeagent_environment eq prod still work for narrowing which calls inside a scoped agent match a rule. They’re orthogonal to scope: scope picks which agents see the policy; conditions pick which calls within those agents trigger which effect.
Default-allow vs default-deny
The defaultspec.defaultEffect: allow is the right starting point — it lets you ship an integration with zero policies and add denies incrementally.
For high-trust environments, flip to defaultEffect: deny and add explicit allow rules. The SDK supports both; nothing in the framework prefers one model.