Promote a policy to Enforce on the strength of an anomaly
POST/api/public/v1/policies/{public_id}/promote
Sets mode: enforce and writes a policy_history row promoted_from_anomaly whose evidence_ref is the anomaly cited — the audit answer to why was this enforced. Evidence is resolved through I-6's tenant-scoped stored-anomaly reader; accepting an id unchecked would write an evidence_ref pointing at nothing and read, forever after, as a decision somebody backed with data. The checks that ARE live run first and in this order: submitting from a descendant layer is 409 INHERITED_HERE (you change a policy where it was authored), a policy that is not ratified is 409 NOT_RATIFIED carrying its actual status (a draft composes into nothing, so Enforce on one would enforce nothing), and a policy with no enforceable intent is 409 NOT_ACTIVATABLE with no_enforceable_atoms in details[]. Unknown, cross-tenant and archived evidence, and evidence raised by a different policy, are each 422. An agent (OAuth) caller must send the version of the policy it read: missing answers 428 POLICY_VERSION_REQUIRED, one that is no longer current 409 POLICY_VERSION_STALE.
curl --fail-with-body -X POST 'https://app.openlatch.ai/api/public/v1/policies/<policy_public_id>/promote' \ -H "Authorization: Bearer $OPENLATCH_API_KEY" \ -H 'Content-Type: application/json' \ -d '{"evidence_anomaly_id":"<evidence_anomaly_id>","zone_id":"<zone_id>"}'import jsonimport osimport urllib.request
body = '{"evidence_anomaly_id":"<evidence_anomaly_id>","zone_id":"<zone_id>"}'request = urllib.request.Request( 'https://app.openlatch.ai/api/public/v1/policies/<policy_public_id>/promote', method='POST', data=body.encode(), headers={ 'Authorization': 'Bearer ' + os.environ['OPENLATCH_API_KEY'], 'Content-Type': 'application/json', },)with urllib.request.urlopen(request) as response: text = response.read().decode() print(json.dumps(json.loads(text), indent=2) if text else response.status)#!/usr/bin/env bashset -euo pipefail
curl -sS --fail-with-body -X POST 'https://app.openlatch.ai/api/public/v1/policies/<policy_public_id>/promote' \ -H "Authorization: Bearer $OPENLATCH_API_KEY" \ -H 'Content-Type: application/json' \ -d '{"evidence_anomaly_id":"<evidence_anomaly_id>","zone_id":"<zone_id>"}' | jq .$headers = @{ Authorization = "Bearer $env:OPENLATCH_API_KEY"}$body = '{"evidence_anomaly_id":"<evidence_anomaly_id>","zone_id":"<zone_id>"}'Invoke-RestMethod -Method POST -Uri 'https://app.openlatch.ai/api/public/v1/policies/<policy_public_id>/promote' -Headers $headers -ContentType 'application/json; charset=utf-8' -Body $body | ConvertTo-Json -Depth 20Authorization
Section titled “Authorization”| Role in the organization | This endpoint |
|---|---|
owner | Allowed |
admin | Allowed |
editor | Allowed |
viewer | Not allowed |
A key carries the role its owner holds in the organization. See Authentication.
API key scope: policies:write
Path parameters
Section titled “Path parameters”| Parameter | Type | Description |
|---|---|---|
public_id | string | Required. |
Header parameters
Section titled “Header parameters”| Parameter | Type | Description |
|---|---|---|
Idempotency-Key | string or null | Optional. Makes the request safe to retry: the same key and the same request, within 24 hours, returns the stored response with Idempotent-Replayed: true and runs once. |
Request body
Section titled “Request body”| Field | Type | Description |
|---|---|---|
evidence_anomaly_id | string | Required. |
version | integer or null | The version of the policy the caller read. Required of an agent (OAuth) caller: missing answers 428 POLICY_VERSION_REQUIRED, a version that is no longer current 409 POLICY_VERSION_STALE. |
zone_id | string (uuid) or null |
Response
Section titled “Response”- 200 OK — the call succeeded.
- 400 Bad Request —
BAD_REQUEST - 401 Unauthorized —
UNAUTHORIZED - 402 Payment Required —
license_expired - 403 Forbidden —
FEATURE_DISABLED,FORBIDDEN,INSUFFICIENT_SCOPE - 404 Not Found —
NOT_FOUND - 409 Conflict —
CONFLICT,IDEMPOTENCY_IN_PROGRESS,INHERITED_HERE,LOOSENS_LAYER,NOT_ACTIVATABLE,NOT_ATTACHED,NOT_RATIFIED,POLICY_VERSION_STALE,SAME_LAYER_CONFLICT,ZONE_REQUIRED - 422 Unprocessable Content —
IDEMPOTENCY_KEY_REUSED,INVALID_ID,VALIDATION_ERROR - 428 Precondition Required —
POLICY_VERSION_REQUIRED - 429 Too Many Requests —
TOO_MANY_REQUESTS - 500 Internal Server Error —
INTERNAL_SERVER_ERROR,tenant_isolation_violation - 503 Service Unavailable —
ENGINE_UNAVAILABLE,EVIDENCE_UNAVAILABLE,FEATURE_STATE_UNAVAILABLE,PROOF_UNAVAILABLE,SERVICE_UNAVAILABLE
Response fields
Section titled “Response fields”| Field | Type | Description |
|---|---|---|
data | object | Required. One policy as a zone's list serves it. |
data.anomalies_7d | integer | |
data.attached_here | boolean | Whether the viewed zone holds its own attachment. |
data.attachment_mode | string — one of disabled, monitor, enforce or null | The viewed zone's own attachment mode; null when it only inherits the AIP. |
data.coverage | object | Required. D-66 — installs counted from stamped negotiation, never from mode + recent poll. |
data.coverage.compatibility_unavailable_installs | integer | Required. |
data.coverage.enforced_installs | integer | Required. |
data.dimensions | array of string | Required. |
data.display_title | string | The AIP's name: its title, else its generated_title, else its statement. |
data.effective_layer | object or null | The zone whose attachment sets effective_mode when it is not layer; null otherwise. |
data.effective_layer.inherited | boolean | Required. |
data.effective_layer.label | string | Required. |
data.effective_layer.unit_id | string | Required. |
data.effective_layer.zone_id | string | Required. |
data.effective_mode | string — one of disabled, monitor, enforce or null | The mode the AIP runs in at the viewed zone: the strictest attachment on its path. |
data.id | string | Required. |
data.intents | object | Required. How many of the policy's atoms are actually enforceable. |
data.intents.enforceable | integer | Required. |
data.intents.monitor_only | integer | Required. |
data.intents.total | integer | Required. |
data.layer | object | Required. The layer a policy row is labelled with: the zone being viewed when it holds the AIP, else the zone whose
attachment sets its mode there. `inherited` is true when the viewed zone holds no attachment of it. |
data.layer.inherited | boolean | Required. |
data.layer.label | string | Required. |
data.layer.unit_id | string | Required. |
data.layer.zone_id | string | Required. |
data.mode | string | Required. Deprecated: attachment_mode when the viewed zone holds it, else effective_mode. |
data.preset | object or null | |
data.preset.application_id | string | Required. |
data.preset.preset_id | string | Required. |
data.preset.preset_name | string | Required. |
data.preset.preset_policy_key | string | Required. |
data.preset.preset_version | integer | Required. |
data.public_id | string | Required. |
data.statement | string | Required. |
data.status | string | Required. |
data.version | integer | Required. |
Example response
Section titled “Example response”{ "data": { "anomalies_7d": 0, "attached_here": false, "attachment_mode": "disabled", "coverage": { "compatibility_unavailable_installs": 3, "enforced_installs": 3 }, "dimensions": [ "string" ], "display_title": "", "effective_layer": { "inherited": false, "label": "string", "unit_id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10", "zone_id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10" }, "effective_mode": "disabled", "id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10", "intents": { "enforceable": 3, "monitor_only": 3, "total": 3 }, "layer": { "inherited": false, "label": "string", "unit_id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10", "zone_id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10" }, "mode": "string", "preset": { "application_id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10", "preset_id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10", "preset_name": "release-bot", "preset_policy_key": "string", "preset_version": 3 }, "public_id": "3f6c1a2e-8b4d-4c1f-9a7e-0d5b2c8e4f10", "statement": "string", "status": "string", "version": 3 }}