P0 security fix. Any authenticated agent could previously read, modify, or
decommission agents belonging to other organizations.
Changes:
- IAgentListFilters: add organizationId field (forced from JWT, never from query)
- AgentRepository.findAll(): filter by organizationId when set
- AgentService: getAgentById, updateAgent, decommissionAgent — accept organizationId
and throw AuthorizationError(403) on cross-tenant access
- AgentController: extract req.user.organization_id on all 5 handlers; throw 403
if claim is absent; registerAgent forces body.organizationId from JWT claim
- OpenAPI spec: document tenant isolation rules per endpoint
- Tests: update MOCK_USER with organization_id; add 5 new missing-org-id 403 tests;
assert organizationId is passed through to service on all mutating calls
Fixes field trial failure: Test C.7 (Org Isolation).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements W3C DID Core 1.0 per-agent identity for every registered agent:
Schema:
- agent_did_keys table: stores EC P-256 public key JWK + Vault path for private key
- agents.did + agents.did_created_at columns
Key management:
- EC P-256 key pair generated on every agent registration via Node.js crypto
- Private key stored in Vault KV v2 (dev:no-vault marker when Vault not configured)
- Public key JWK stored in PostgreSQL agent_did_keys table
API (4 new endpoints):
- GET /.well-known/did.json — instance DID Document (public, cached)
- GET /api/v1/agents/:id/did — per-agent DID Document (public, 410 for decommissioned)
- GET /api/v1/agents/:id/did/resolve — W3C DID Resolution result (agents:read scope)
- GET /api/v1/agents/:id/did/card — AGNTCY agent card (public)
Implementation:
- DIDService: DID construction, key generation, Redis caching (TTL configurable)
- DIDController: 410 Gone for decommissioned agents, correct Content-Type on resolve
- AgentService: calls DIDService.generateDIDForAgent on every new registration
Tests: 429 passing, DIDService 98.93% coverage, private key absence verified in all responses
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>