Approve a pending policy change (checker)
Approves a Pending Policy Change (checker). Requires, in order, all fail-closed: a human-authenticated caller distinct from the proposer (maker != checker, 403 SAME_ACTOR_CANNOT_APPROVE_OWN_CHANGE otherwise), and a valid step-up authorization envelope proving fresh, explicit intent (403 STEP_UP_AUTHORIZATION_INVALID on a missing, malformed, expired, replayed, wrong-id, wrong-action, or wrong-key-signed envelope). Once both pass, this writes the live policies///policy.json file and records a signed PolicyChangeApprovalRecord BEFORE marking the change APPROVED, so a failure partway through never leaves a pending change falsely resolved with no corresponding live effect. Per-check step-up diagnostic detail is logged server-side only, never in this response.
Authorizations
Caller API key issued by scripts/generate-api-key.ts. Sent as Authorization: Bearer . Verified against a stored SHA-256 hash in constant time by packages/api/src/auth/StaticKeyAuthenticator.ts. Required on every route not listed as exempt in this document's top-level description. See /api-reference/authentication.
Path Parameters
Body
Request body for POST /policies/pending-changes/{id}/approve.
Signed envelope proving a checker's explicit, fresh intent to approve or reject one specific Pending Policy Change (Policy Governance, Layer 4). Produced by PolicyChangeStepUpAuthorizationSigner (@parmana/crypto) using the checker's own step-up private key, never the bearer API key. Verified server-side against: the checker's registered stepUpPublicKey, payload.pendingPolicyChangeId matching the URL's {id}, payload.action matching the endpoint (approve vs reject), payload.expiresAt not yet passed, and payload.nonce not previously seen (single-use, replay-rejected on a second attempt with the same envelope).
Response
Approved. The live policy.json file has been written.
A proposed change to a policy's content, held in a durable pending state until a second, distinct human explicitly approves or rejects it (Policy Governance, maker-checker). Only ever moves from PENDING_APPROVAL to APPROVED or REJECTED, exactly once.
Unique Pending Policy Change identifier.
The policy this proposal targets, same identifier as Policy.policyId.
The existing version this proposal is a change against ("the version being replaced"). Not necessarily equal to proposedContent's own declared version: an in-place patch and a version bump are both legitimate.
The full proposed policy.json content, in its entirety, not a diff or patch.
Identity of the proposer (maker). Always a human-authenticated (credentialHolderType USER) caller.
PENDING_APPROVAL, APPROVED, REJECTED Free-text justification from the proposer, required at creation.
Identity of the resolver (checker). Absent while PENDING_APPROVAL. Never equal to proposedBy.
Absent while PENDING_APPROVAL.
Present only when status is REJECTED.
Present only when non-empty: uncovered-fact warnings from PolicyValidator.findUncoveredFacts against proposedContent.
Present only when non-empty: advisory rule-conflict warnings from PolicyValidator.findRuleConflicts against proposedContent, never blocking.