feat(phase-5): WS2 — A2A Authorization

Implements agent-to-agent delegation chains:
- Migration 024: delegation_chains table with HMAC signature, TTL, revocation
- DelegationCrypto: HMAC-SHA256 sign/verify, UUID token generation
- DelegationService: create (scope subset validation, self-delegation guard,
  same-tenant delegatee check), verify (returns valid: false on expired/revoked,
  never throws), revoke (delegator-only, conflict guard)
- DelegationController + router at /oauth2/token/delegate (POST/DELETE) and
  /oauth2/token/verify-delegation (POST)
- Feature-flagged behind A2A_ENABLED env var (default on)
- Prometheus metrics: delegations_created/verified/revoked_total
- 33 tests (unit + integration): all pass, DelegationService 87.5%+ branch coverage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
SentryAgent.ai Developer
2026-04-03 02:49:36 +00:00
parent 0506bc1b8e
commit 16497706d3
9 changed files with 1339 additions and 0 deletions

53
src/types/delegation.ts Normal file
View File

@@ -0,0 +1,53 @@
/**
* TypeScript interfaces for the A2A (Agent-to-Agent) delegation subsystem.
* All delegation types are defined here — no inline type definitions in services or controllers.
*/
/** A delegation chain record as stored in the database. */
export interface DelegationChain {
id: string;
tenantId: string;
delegatorAgentId: string;
delegateeAgentId: string;
scopes: string[];
delegationToken: string;
signature: string;
ttlSeconds: number;
issuedAt: Date;
expiresAt: Date;
revokedAt: Date | null;
createdAt: Date;
}
/** Request body for creating a new delegation. */
export interface CreateDelegationRequest {
/** UUID of the agent receiving delegated authority. Must be in the same tenant. */
delegateeAgentId: string;
/** Scopes to delegate. Must be a strict subset of the delegator's own scopes. */
scopes: string[];
/** Delegation lifetime in seconds. Min: 60, Max: 86400. */
ttlSeconds: number;
}
/** Result of verifying a delegation token. Never throws on expired/revoked — returns valid: false. */
export interface DelegationVerificationResult {
valid: boolean;
chainId: string;
delegatorAgentId: string;
delegateeAgentId: string;
scopes: string[];
issuedAt: Date;
expiresAt: Date;
revokedAt: Date | null;
}
/** Payload signed by HMAC-SHA256 to produce the delegation signature. */
export interface DelegationTokenPayload {
chainId: string;
tenantId: string;
delegatorAgentId: string;
delegateeAgentId: string;
scopes: string[];
issuedAt: string; // ISO 8601
expiresAt: string; // ISO 8601
}