Two structural decisions for dynamic resource ownership (OQ-42), recorded
in the OQ so ADR drafting starts from a clear position:
1. Storage side reuses the repo/adapter pattern (ADR-033) — a fourth
instance alongside IdentityProvider/IdentityStore/CredentialStore.
Trait in alknet-core with an in-memory default adapter; persistence
adapter separable. Sync read with ArcSwap + honker-NOTIFY cache
invalidation, same shape as ConfigIdentityProvider (ADR-035). No new
shape invented; no Phase 0 needed for the storage side.
2. Integration point is Option 2 — AccessControl::check consults the
ownership provider directly. Rejected Option 1 (augment identity with
a per-request snapshot) because its purity was theatrical — the
question 'can X exec into container C' was never purely a function of
identity, it just looked that way because the resource set was static.
Option 2 makes check's signature honest about what ACL checking is in
the presence of dynamic resources. Cost is a check signature change
(one-way door, every call site updates) — implementation cost, not
semantic cost, per the project's decision principle.
Refinement that makes Option 2 clean: OperationSpec gains resource_id_path
(JSON pointer into the input, e.g. '$.containerId'). Fits naturally with
the existing JSON-Schema-backed input_schema — the pointer is within an
existing schema on the same spec. OperationSpec becomes fully
self-describing for authorization: resource type, action, and which input
field drives the resource lookup, all declared on the spec.
Four specifics remain open for the ADR: the no-specific-resource (list)
case, teardown coupling, fleet representation (spoke resources on the
hub), and composition interaction with dynamic ownership. These were
surfaced by choosing Option 2 rather than by leaving the integration point
undecided.