operator runbooks
Intended Documentation
Author a Policy
Author an Intended authority policy as a governed draft — structure a policy set, scope its rules and effects, create the draft through the Policies API or console, and submit it for review. No fictional CLI command group.
Author a Policy#
A policy is what the authority runtime consults to reach a decision. This runbook walks you through authoring one as a governed draft: you structure a policy set, scope its rules, create the draft, and submit it for review. Promotion to a live version is covered in Deploy and Rollback.
There is no `intended policy …` command
Policy authoring is driven through the Policies API (/authority/policies and the /policy/* lifecycle) and the console policy editor. The Intended CLI is flat and hyphenated; the only policy-related CLI verbs are deploy-policy (= policy-pack-install) and policy-pack-inspect. There is no intended policy init / validate / test / review — those commands do not exist. A first-class authoring CLI is Roadmap.
Prerequisites#
- An API key (
intended_live_…; legacymrt_…also accepted) or a portal session with theauthority:policy:writepermission. Authoring and every lifecycle transition require it. - The tenant id you are authoring for. Every policy call is tenant-scoped: the credential's tenant, the
x-tenant-idheader, and the bodytenantIdmust all agree, or the request is rejected with403 TENANT_MISMATCH.
How a policy decides#
Before you write rules, understand how they combine. The engine loads the tenant's policy sets, matches rules by their bindings and conditions, and resolves the outcome most-severe-wins (DENY > REQUIRE_APPROVAL > ESCALATE > ALLOW). When no rule matches, it defaults to DENY. Interpretation-layer (LIM) signals can only upgrade severity — never soften it. The risk score is baseRiskScore + (privileged?20) + (production?20) + (sensitive?15), capped at 100.
Warning
Always keep defaultDecision: "DENY" for production policy sets. A default-allow set creates an unaudited authorization gap — any binding you forgot to cover would silently pass.
Policy set structure#
A policy set is the unit the engine evaluates. It is JSON, not YAML, and is carried inside the draft you create.
Fields#
| Field | Required | Description |
|---|---|---|
name | Yes | Human-readable policy-set name. |
version | Yes | Integer version. Increment when the rule set changes. |
enabled | Yes | Whether the engine loads this set. |
defaultDecision | Yes | The decision when no rule matches. Use DENY in production. |
rules[] | Yes | One or more rules; see below. |
description | No | Why this set exists. |
Rule bindings and effect#
A rule matches an evaluation when every binding it declares is satisfied. Bindings left unset are wildcards.
| Binding | Matches against |
|---|---|
intentTypes | The compiled intent type. |
actions | proposedAction on the intent. |
targetSystems | The targetSystem being acted on. |
tools | The adapter/tool in context (github-actions, jira, …). |
actorRoles | The actor's role. |
environments | The runtime environment (production, staging, …). |
A rule may also carry confidenceThresholds, budgetCeilings, and conditions. Its effect is { decision, approvalRequirement?, escalation? }, where decision is ALLOW / DENY / REQUIRE_APPROVAL / ESCALATE.
Step 1 — Create the draft#
Author through the governed lifecycle: create a draft rather than upserting the live set directly. Every lifecycle step appends to the audit ledger and requires authority:policy:write.
Open a draft
POST /policy/drafts with the policy set inline.
The response is 201 with the new draft, including its id.
Fill in the rules
Edit the draft with PUT /policy/drafts/:id, supplying the complete policySet. Map each binding to the intents you want to govern, and choose an effect (REQUIRE_APPROVAL to gate, DENY to block, ESCALATE to route to a human, ALLOW to permit).
Tip
Prefer the console policy editor for interactive authoring — it edits the same drafts and shows the impact summary inline. Use the API when you want authoring under version control or in CI.
Step 2 — Submit for review#
When the rules are complete, submit the draft for review. The reviewer who approves must hold authority:policy:write; separation of duties is a review-process control, not enforced by the endpoint.
Submit to review
Attach a simulationRunId so the reviewer sees the projected impact alongside the change. Run that simulation first — see Simulate Impact.
Reviewer approves or rejects
A reviewer calls POST /policy/drafts/:id/approve or POST /policy/drafts/:id/reject with { tenantId, reviewerId, comments? }. Approval moves the draft to a deployable state; it does not deploy. Deploying is a separate, explicit step.
Failure modes#
| Status | Code | Cause |
|---|---|---|
400 | validation | Draft body or policySet failed schema. |
400 | TENANT_MISMATCH | Body tenantId ≠ intent/header tenant. |
401 | UNAUTHORIZED | No valid credential. |
403 | FORBIDDEN | Missing authority:policy:write. |
403 | TENANT_MISMATCH | Body tenant ≠ credential tenant. |
404 | not found | Draft id does not exist for this tenant. |
Common mistakes#
| Mistake | Consequence | Fix |
|---|---|---|
defaultDecision: "ALLOW" in prod | Uncovered bindings pass silently | Always default to DENY. |
| Upserting the live set directly | No review, weak audit trail | Author through /policy/drafts. |
| Over-broad bindings (all wildcards) | Rule fires on unintended intents | Scope targetSystems / environments / actorRoles explicitly. |
| Submitting without a simulation | Reviewer can't see impact | Attach simulationRunId to the review. |
Next steps#
- Simulate Impact — preview the effect of the draft before you promote it.
- Deploy and Rollback — approve, deploy, and roll back.
- Policies API — the full route reference for
/authority/policiesand/policy/*.