Skip to main content
Version: v5.7.0

10.2 Asset owners and impacted-owner approval

packs:change-governance

After this you can: declare subtree owners, require their approval through the all-of line, and hand ownership over.

Before you start — tick each one:

  • Lesson 10.1 — Approval policies and the change funnel (opschain learn 10.1)

In the GUI: Governance → Policies & owners — the approval policies beside the subtree owner declarations the funnel resolves approvers from; a held change's owner lines show in Reviews & approvals like any other line.

"Approval of each impacted asset owner" is the approval rule most change boards actually want — and the one that cannot be spelled as a static approver list, because who approves depends on what the change touches. OpsChain makes ownership an authz-shaped fact declared on the policy fabric, then resolves it per change at the create funnel. The model reference is opschain docs change-governance; this lesson assumes the funnel basics from lesson 10.1.

Licence entitlement. Asset-owner declarations and the impacted_asset_owners approver kind ride ChangeGovernanceService, so everything here requires the packs:change-governance entitlement (see opschain docs entitlements).

The walkthrough uses the Lime Group demo estate: robert owns core_banking, sarah owns payments_gateway, and internet_banking is deliberately unowned.

1. Declare ownership​

An asset owner declaration names a subtree root and its owner identities (users and groups). Declaring is delegable exactly like the metadata-writer role: writes are decided updatable on the reserved /governance/owners<node path> rule-path family, sit on the step-up floor, and are audited; reads ride readable on the same family, 404-on-deny. As a holder of that grant (elevated):

opschain governance owners declare /projects/limebank/environments/prod/assets/core_banking \
--owner-user robert
owners declared on /projects/limebank/environments/prod/assets/core_banking (01a2f5a0-3c1d-7e2f-8b4a-9d0e1f2a3b4c): robert
opschain governance owners list
NODE PATH OWNERS CREATED BY CREATED AT
/projects/limebank/environments/prod/assets/core_banking robert ryan 2026-10-27T09:30:12Z
/projects/limebank/environments/prod/assets/payments_gateway sarah ryan 2026-10-27T09:30:40Z
  • A declaration covers its node and whole subtree on segment boundaries; the deepest covering declaration wins (inheritance).
  • The subtree is immutable once declared: move ownership by remove + declare, so the audit trail shows the handover (opschain audit --type-prefix api:asset_owners:).

2. The owner policy​

A policy carrying the impacted_asset_owners approver kind resolves declarations per change instead of naming anyone. The canonical row — production × destroy — as the change governance administrator (elevated):

opschain approval-policies create --name 'Production destroy control' \
--path-pattern '/projects/limebank/environments/prod/**' \
--action-pattern 'destroy*' \
--approver-kind impacted_asset_owners --require-step-up
approval policy "Production destroy control" created (01a2f5a1-6b2e-7f30-9c5b-0e1f2a3b4c5d) — path /projects/limebank/environments/prod/**, quorum 1

Named approvers and kinds compose: a policy may carry users, groups and/or kinds, but must carry at least one source.

3. The all-of owner line​

As jessica (elevated — the policy also demands step-up), run destroy_stack against an owned asset:

opschain runs create change /projects/limebank/environments/prod/assets/core_banking --action destroy_stack
created change 01a2f5a2-8d3f-7a41-ad6c-1f2a3b4c5d6e (destroy_stack on /projects/limebank/environments/prod/assets/core_banking) — pending_approval
opschain approvals show <run-id>
change 01a2f5a2-8d3f-7a41-ad6c-1f2a3b4c5d6e — destroy_stack on /projects/limebank/environments/prod/assets/core_banking
status: pending · requested by jessica at 2026-10-27T09:35:02Z
quorum deadline: 2026-11-03T09:35:02Z

lines:
Production destroy control — 0/1
waiting on robert

The change enters pending_approval with one all-of line per resolved owner: quorum 1 per line, every owner line must satisfy — all-of, not n-of-m — with the resolved subtree root frozen onto the line (owner_path). Sarah cannot approve robert's line; robert approves and the change releases:

opschain approvals approve <run-id>
approval recorded — the checklist completed and 01a2f5a2-8d3f-7a41-ad6c-1f2a3b4c5d6e was released to run

Self-approval exclusion and distinct-identity counting apply per owner line: an owner who requested the change cannot wave their own asset through.

4. The uncovered refusal​

Run the same action against the unowned asset:

opschain runs create change /projects/limebank/environments/prod/assets/internet_banking --action destroy_stack
Error: The approval policy "Production destroy control" requires approval of each impacted asset owner, but no subtree owner is declared covering: /projects/limebank/environments/prod/assets/internet_banking — declare owners for every impacted target before this change can be created (a covered change is never approver-less; see: opschain docs change-governance)

An impacted target no declaration covers refuses the create loudly — a covered change is never created approver-less, and nothing is created at all. Fix it by declaring an owner (or an ancestor-level declaration that covers the gap), then re-run.

5. Handover, audited​

Ownership changes are themselves governed facts:

opschain governance owners update <declaration-id> --owner-user sarah
owners updated on /projects/limebank/environments/prod/assets/core_banking (01a2f5a0-3c1d-7e2f-8b4a-9d0e1f2a3b4c): sarah
opschain audit --type-prefix api:asset_owners:
WHEN TYPE USER SOURCE NODE CORRELATION
2026-10-27T09:41:18Z api:asset_owners:update ryan - /projects/limebank/environments/prod/assets/core_banking 01a2f5a4-…
2026-10-27T09:30:12Z api:asset_owners:create ryan - /projects/limebank/environments/prod/assets/core_banking 01a2f5a0-…

The update event carries before/after owners. Removing a declaration (opschain governance owners remove <declaration-id>) ends coverage — any covered destroy against that subtree then refuses at create until ownership is re-declared.

Check yourself​

  • Which refusal does the funnel print when an impacted subtree has no owner declared — and is a change created at all? Then: after robert approves his line, what does opschain approvals show report as the checklist status?

What you learned​

  • Ownership is declared per subtree on the reserved /governance/owners<path> rule-path family — delegable, audited, step-up floored, deepest declaration wins, immutable subtree.
  • The impacted_asset_owners kind resolves owners per change over the frozen target set: one all-of checklist line per owner, self-approval excluded per line.
  • An uncovered impacted target refuses the create by name — fail closed, never approver-less.

Next: lesson 10.3 — The approval context (opschain learn 10.3), or back to your track (opschain learn).