Skip to main content
Parmana Policy API. Validate Runtime policies, and run policy governance: propose a change, list changes, approve or reject one with a signed step up authorization.

PolicyApi Objects

Policy API.

Responsibilities

  • Read the policy in effect for a capability, and what a request must carry
  • Confirm a policy (name + version) is loadable by the Runtime
  • Propose a policy change, list changes for review, approve or reject one
This API does NOT:
  • validate an arbitrary policy document’s contents. POST /policies/validate (packages/api/src/routes/policies.ts) only checks that policyRepository.load(policyId, policyVersion) succeeds — it does not accept or check a policy document body.
  • execute Business Transactions
  • verify trust records
  • replay executions
  • generate receipts

in_effect

The policy a request for capability must declare right now, and what the request must carry. Maps to GET /policies/in-effect. Returns every fact the policy’s rules read, their types, the signals bound to the Intent, and the signals that need a signed approval. Call it before every request: an approved new version replaces the old one at once. Raises AuthorizationError (403, code CAPABILITY_NOT_ALLOWED) when the key may not invoke the capability, NotFoundError (404, CAPABILITY_NOT_BOUND) when no policy governs it, and ConflictError (409, NO_APPROVED_POLICY_VERSION) or InternalServerError (503, POLICY_VERSION_UNAVAILABLE) when every request for it is refused right now. Do not send a request in any of those cases.

validate

Confirm that a policy (name + version) is loadable.

Parameters

policy_id: Policy identifier (policyId). policy_version: Policy version (policyVersion).

Returns

\{"valid": bool, "errors": list[str]\}. POST /policies/validate does not use the shared {error, code?} envelope for 400 or 404: both are {valid, errors}, the caller’s answer, not an SDK-level failure — so those two statuses are exempted from the default raise-on-error behavior. 401 is not exempted: it is generated by caller-auth middleware before this route’s own handler ever runs, and does use the shared envelope, identically to every other route.

propose_change

Propose a policy change. Maps to POST /policies/{name}/{version}/pending-changes. The API key must belong to a verified human (credential holder type USER). proposed_content is the whole policy.json, sent exactly as given; its policyId must equal name. Only one open proposal per name and version is allowed; a second one raises ConflictError.

list_changes

List policy changes for review, with the content in effect now next to the proposed content. Maps to GET /policies/pending-changes. The API key must belong to a verified human.

Parameters

status: “PENDING_APPROVAL”, “APPROVED” or “REJECTED”. Omit for all.

approve_change

Approve a policy change, which then takes effect. Maps to POST /policies/pending-changes/{id}/approve. The API key must belong to a verified human with a registered step up key, who is not the proposer. Make step_up_authorization with parmana.crypto.sign_policy_change_step_up(action="approve", ...); it is valid once, for 120 seconds by default.

reject_change

Reject a policy change. Maps to POST /policies/pending-changes/{id}/reject. Same caller rules as approve_change(); sign with action “reject”. A reason is required.