Files
alknet/tasks/call/registry/operation-spec-resource-id-path.md
glm-5.2 de536b82e1 tasks: add ADR-050 implementation tasks — ownership store, resource_id_path, check signature, dispatch wiring
Four tasks forming a DAG for the dynamic resource ownership model (ADR-050):

1. core/ownership-store-trait (no deps) — OwnershipProvider (sync read) +
   OwnershipStore (async write) traits + InMemoryOwnershipStore + OwnershipError
   in alknet-core; fourth instance of the repo/adapter pattern (ADR-033)
2. call/registry/operation-spec-resource-id-path (no deps) — add
   resource_id_path: Option<String> to OperationSpec (JSON pointer into
   input for resource ID extraction)
3. call/registry/access-control-ownership-check (depends on 1) — update
   AccessControl::check signature to accept resource_id + OwnershipProvider;
   backward compatible (ownership=None falls back to static Identity.resources)
4. call/registry/dispatch-resource-id-extraction (depends on 2, 3) — wire
   dispatch path to extract resource_id from input via spec.resource_id_path
   and thread OwnershipProvider to check(); OperationContext gains ownership
   field

Tasks 1 and 2 can run in parallel (different crates, no deps). Task 3
depends on 1. Task 4 depends on 2 and 3. Validated: no cycles, 90 tasks total.
2026-07-05 11:12:44 +00:00

3.8 KiB

id, name, status, depends_on, scope, risk, impact, level
id name status depends_on scope risk impact level
call/registry/operation-spec-resource-id-path Add resource_id_path field to OperationSpec (ADR-050 §2a) pending
single low component implementation

Description

Add a resource_id_path: Option<String> field to OperationSpec. This is a JSON pointer into the operation input that tells the dispatcher where to find the resource ID for runtime-spawned resource authorization. Per ADR-050 §2a.

The field

pub struct OperationSpec {
    pub name: String,
    pub namespace: String,
    pub op_type: OperationType,
    pub visibility: Visibility,
    pub input_schema: Value,
    pub output_schema: Value,
    pub error_schemas: Vec<ErrorDefinition>,
    pub access_control: AccessControl,
    /// JSON pointer into the input for the resource ID, when
    /// `access_control.resource_type` is set and the operation targets a
    /// specific runtime-spawned resource (ADR-050). e.g., `"$.containerId"`
    /// for `docker/container/exec`. Absent for no-specific-resource
    /// operations (the `list` case). `None` for operations with no
    /// `resource_type` or with static resource sets.
    pub resource_id_path: Option<String>,
}

Construction

OperationSpec::new(...) currently takes 7 arguments (name, op_type, visibility, input_schema, output_schema, error_schemas, access_control). This task adds resource_id_path as an 8th argument. Since all construction sites need to update, consider whether a builder pattern is worth introducing — but for now, add it as the last positional argument (defaulting to None at call sites that don't need it).

What this task does NOT do

  • Does NOT change AccessControl::check — that's call/registry/access-control-ownership-check, which depends on core/ownership-store-trait.
  • Does NOT extract the resource ID from input or pass it to check — that's call/registry/dispatch-resource-id-extraction, which depends on this task.
  • This task only adds the field to the struct, updates new(), and updates all existing construction sites + tests.

Existing construction sites

Search for OperationSpec::new( across the codebase — every call site needs the new argument added. Most will pass None (no runtime-spawned resources). The existing tests in spec.rs construct OperationSpec without resource_id_path — they all need the None argument added.

Acceptance Criteria

  • OperationSpec struct has resource_id_path: Option<String> field
  • OperationSpec::new(...) takes resource_id_path as the 8th argument
  • All existing OperationSpec::new(...) call sites updated (most pass None)
  • All existing tests that construct OperationSpec updated
  • Existing tests still pass (no semantic change — None means "no resource ID extraction")
  • Unit test: resource_id_path is None by default when not specified
  • cargo test -p alknet-call succeeds
  • cargo clippy -p alknet-call succeeds with no warnings

References

  • docs/architecture/crates/call/operation-registry.md — OperationSpec (updated with resource_id_path)
  • docs/architecture/decisions/050-dynamic-resource-ownership-for-runtime-spawned-resources.md — ADR-050 §2a
  • crates/alknet-call/src/registry/spec.rs — current OperationSpec struct

Notes

The fit with JSON Schema is load-bearing: input_schema is already a JSON Schema, so resource_id_path is a pointer within an existing schema on the same spec. The OperationSpec becomes fully self-describing for authorization — what resource type, what action, and which input field drives the resource lookup. This is a single field addition with no semantic change — existing call sites pass None and behave exactly as before. The field is consumed by the dispatch path in call/registry/dispatch-resource-id-extraction.