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:
| Hop | Entity | Granted Scope |
|---|
| 0 | Human owner | ["read", "write", "admin"] |
| 1 | coding-agent-01 | ["read", "write"] |
| 2 | sub-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
- Keep chains shallow. The default policy limits depth to 3. Deeper chains are harder to audit.
- Narrow scope at each hop. Use the
scope field to restrict permissions at every delegation.
- Set expiry on every hop. Open-ended delegations are a security risk.
- Validate regularly. Run
validateDelegationChain to detect broken chains and expired hops.
- Monitor with audit trail. All delegation operations are automatically logged.
- Revoke promptly. When an agent is decommissioned, revoke rather than waiting for expiry.
Next Steps