Skip to main content
Version: v5.7.0

opschain approval-policies convert-settings-approvers

packs:change-governance

opschain approval-policies convert-settings-approvers [--dry-run]

Converts the retired settings requires_approval_from entries into approval policies (ChangeGovernanceService.ConvertSettingsApprovers). The old node-settings entries were never enforced by this server — an operator who configured them believed changes were gated when they were not — so the converge, the node compare and the settings editor no longer serve the key, and approval policies are the enforced successor. This verb is the operator path from one to the other: it scans every stored settings document (the global document and every node's current settings version) and creates one policy per entry, through the same store the policy write verbs use.

Each converted entry becomes a policy at the owning node's path:

  • the policy's path pattern is the owning node's path covering its whole subtree (<node path>/**; a global entry becomes /**), matching how the old entries inherited down the settings converge;
  • the entry's change_filter.actions become the policy's action patterns ("all" becomes *; literal names and *-globs carry over);
  • the entry's user_names and ldap_groups become the policy's named approvers, with quorum 1 and self-approval allowed — the old gate was satisfied by any one named approver, a change creator among them included;
  • the policy's scope is the owning node's path, so the usual delegable governance determination governs who may edit it afterwards.

The report names every stored entry: converted (with the new policy's name and id), already converted (a re-run creates nothing twice — an entry whose converted shape already exists as a policy is skipped, whatever the policy has since been renamed to) or unconvertible. Unconvertible entries are left in place and must be recreated by hand; the reasons are property-placeholder approver names ({{ … }}) that nothing resolves any more, created_by change filters (approval policies do not match on the change's creator), extended action globs (?, […], {a,b} — policies support * only), entries naming no approvers, and entries stored on templates or template versions (no node path to anchor the policy to). Email addresses in user_names are copied verbatim — the old resolver's email-to-username lookup is not applied, so check such approvers against real usernames.

The verb requires a PostgreSQL-backed server holding the packs:change-governance entitlement, the change-governance determination (updatable on /governance/change, the root scope — the conversion writes policies across the whole estate) and a stepped-up session. A writing run is audited as api:settings_approvers:converted; --dry-run produces the same report without writing anything and is not audited.

The stored entries themselves are not deleted: the server ignores them everywhere, and this verb keeps reading them so a re-run can report them. Remove the global document's entries afterwards with opschain admin settings prune (the key is in the pruneable set); node-level entries can be removed by editing each node's settings document.

Flags​

FlagMeaning
--dry-runReport what would convert without writing any policy.

-o json / -o yaml emit the typed report in its protojson wire shape.

Exit codes​

CodeMeaning
0Report produced (a writing run may have created policies; no stored requires_approval_from entries found when the estate holds none).
1The conversion failed — the error names the server's Connect code and message, including the packs:change-governance funnel refusal, the missing governance determination and the step-up refusal.
2Usage error, including a missing server target.

Examples​

$ opschain approval-policies convert-settings-approvers --dry-run
[would convert] /projects/demo filter={"actions":["deploy"]} approvers=alice, dba -> policy "Converted settings approvers /projects/demo 1a2b3c4d" (path /projects/demo/**, actions deploy)
[unconvertible] System Configuration filter={"actions":"all"} approvers={{ approvers }} — the approver "{{ approvers }}" is a property placeholder the retired settings resolver would have resolved — resolve it by hand
1 convertible, 0 already converted, 1 unconvertible (left in place)

$ opschain approval-policies convert-settings-approvers
[converted] /projects/demo filter={"actions":["deploy"]} approvers=alice, dba -> policy "Converted settings approvers /projects/demo 1a2b3c4d" (01993…, path /projects/demo/**, actions deploy)
...