Skip to main content

Delegation Management

ID Wispera tracks credential provenance through delegation chains as credentials flow from human owners to AI agents and sub-agents.

Overview

A delegation chain records every handoff of a credential. Each hop captures who delegated to whom, what scope was granted, and when the delegation expires. This enables:
  • Least privilege — scope narrows at each hop
  • Auditability — full chain is always visible
  • Expiry enforcement — hops expire independently
  • Revocation — any hop can be cut

Adding a Delegation

import { addDelegation } from '@id-wispera/core';

const updated = await addDelegation(vault, passport.id, {
  from: '[email protected]',
  to: 'coding-agent-01',
  scope: ['read', 'write'],
  expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
  notes: 'Daily coding task',
}, '[email protected]');
Every delegation hop should include an expiresAt value. Open-ended delegations are a security risk and may be blocked by the default policy engine rules.

Traversing the Chain

import {
  getDelegationDepth,
  getCurrentHolder,
  getOriginalIssuer,
  getDelegationPath,
} from '@id-wispera/core';

getDelegationDepth(passport);     // 2
getCurrentHolder(passport);       // "sub-agent-02"
getOriginalIssuer(passport);      // "[email protected]"
getDelegationPath(passport);      // "[email protected] -> coding-agent-01 -> sub-agent-02"

Scope Narrowing

The effective scope is the intersection of all scopes in the chain.
Scope can only narrow — never widen — at each delegation hop. A delegate cannot grant permissions they do not themselves hold.
Example chain:
HopEntityGranted Scope
0Human owner["read", "write", "admin"]
1coding-agent-01["read", "write"]
2sub-agent-02["read"]
import { getEffectiveScope, isScopePermitted } from '@id-wispera/core';

getEffectiveScope(passport);              // ["read"]
isScopePermitted(passport, 'read');       // true
isScopePermitted(passport, 'write');      // false

Revoking Delegations

import { revokeDelegation, clearDelegations } from '@id-wispera/core';

// Revoke the most recent delegation hop
const updated = await revokeDelegation(vault, passport.id, '[email protected]');

// Clear the entire delegation chain
const cleared = await clearDelegations(vault, passport.id, '[email protected]');
When an agent is decommissioned, revoke its delegations immediately rather than waiting for them to expire. This closes the access window right away.

Validation

import {
  validateDelegationChain,
  hasExpiredDelegation,
  getExpiringDelegations,
} from '@id-wispera/core';

const result = validateDelegationChain(passport);
if (!result.valid) {
  for (const issue of result.issues) {
    console.log('Issue:', issue);
  }
}

if (hasExpiredDelegation(passport)) {
  console.log('Chain contains expired delegations');
}

// Find delegations expiring within the next 7 days
const expiring = getExpiringDelegations(passport, 7);

Best Practices

  1. Keep chains shallow. The default policy limits depth to 3. Deeper chains are harder to audit.
  2. Narrow scope at each hop. Use the scope field to restrict permissions at every delegation.
  3. Set expiry on every hop. Open-ended delegations are a security risk.
  4. Validate regularly. Run validateDelegationChain to detect broken chains and expired hops.
  5. Monitor with audit trail. All delegation operations are automatically logged.
  6. Revoke promptly. When an agent is decommissioned, revoke rather than waiting for expiry.

Next Steps