Skip to main content

delegate

Function delegate 

Source
pub fn delegate(
    parent: &CapabilityToken,
    child_scope: &ChioScope,
    delegator_keypair: &Keypair,
    delegatee: &PublicKey,
    attenuation: ScopeAttenuation,
    signed_at: u64,
    nonce: [u8; 16],
) -> Result<DelegationReceipt, Error>
Expand description

Recursive-delegation mint helper.

delegate wraps DelegationLink::sign with fail-closed attenuation enforcement and emits a [DelegationReceipt] alongside the signed link. Returns Err (denying the mint) when any of:

  • The parent token’s scope does not explicitly authorize Operation::Delegate.
  • The proposed child_scope is not a subset of the parent token’s scope (rejected by validate_attenuation).
  • Any attenuation.steps entry is not a true narrowing of the parent (raises a cap, targets a tool outside the parent scope, or extends expiry). Steps are validated reduce-only rather than copied verbatim, and each is checked against every covering parent grant so an overlapping *:* grant cannot mask a concrete grant that holds the targeted operation or cost cap.
  • Any declared step is not actually reflected in child_scope / child_expires_at (for example an AddConstraint step whose constraint the child grant omits). This mirrors chio-kernel’s declared-attenuation validation so the helper never emits a receipt whose signed link and child scope disagree.
  • attenuation.budget_share_bps exceeds the parent’s share. The share is parent-relative: a child can never claim a larger fraction of the budget than the parent holds (an absent parent share is treated as 100%). When the parent holds a share strictly below the 100% ceiling, the child MUST state an explicit budget_share_bps: omission is rejected fail-closed because downstream admission treats a missing share as the full budget (a widening). A parent at the full ceiling (None or Some(10_000)) accepts an omitted child share as a no-op.
  • The requested child_expires_at is greater than the parent’s expires_at (rejected as an Error::AttenuationViolation).
  • delegator_keypair.public_key() != parent.subject (the mint helper is fail-closed: only the parent capability’s bound subject may delegate further).

The helper is intentionally pure with respect to the local clock: callers pass signed_at and nonce explicitly so unit tests, replay proofs, and proptest-driven invariants stay deterministic.

This function is gated behind the delegation feature flag. Callers must opt in explicitly.