feat(phase-3): workstream 2 — W3C DIDs
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>
This commit is contained in:
95
src/types/did.ts
Normal file
95
src/types/did.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* W3C DID Core 1.0 and AGNTCY extension types for SentryAgent.ai AgentIdP.
|
||||
* All interfaces are strictly typed — no `any` usage.
|
||||
*/
|
||||
|
||||
/** A W3C DID Core 1.0 verification method. */
|
||||
export interface IVerificationMethod {
|
||||
id: string;
|
||||
type: string;
|
||||
controller: string;
|
||||
publicKeyJwk: IPublicKeyJwk;
|
||||
}
|
||||
|
||||
/** JWK representation of a public key. */
|
||||
export interface IPublicKeyJwk {
|
||||
kty: string;
|
||||
crv?: string;
|
||||
x?: string;
|
||||
y?: string;
|
||||
/** RSA modulus (base64url). */
|
||||
n?: string;
|
||||
/** RSA public exponent (base64url). */
|
||||
e?: string;
|
||||
use?: string;
|
||||
kid?: string;
|
||||
}
|
||||
|
||||
/** A W3C DID Document service endpoint. */
|
||||
export interface IDIDService {
|
||||
id: string;
|
||||
type: string;
|
||||
serviceEndpoint: string;
|
||||
}
|
||||
|
||||
/** W3C DID Core 1.0 DID Document. */
|
||||
export interface IDIDDocument {
|
||||
'@context': string[];
|
||||
id: string;
|
||||
controller: string;
|
||||
verificationMethod: IVerificationMethod[];
|
||||
authentication: string[];
|
||||
assertionMethod?: string[];
|
||||
service?: IDIDService[];
|
||||
agntcy?: IAgntcyExtension;
|
||||
}
|
||||
|
||||
/** AGNTCY extension fields on a per-agent DID Document. */
|
||||
export interface IAgntcyExtension {
|
||||
agentId: string;
|
||||
agentType: string;
|
||||
capabilities: string[];
|
||||
deploymentEnv: string;
|
||||
owner: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
/** W3C DID Resolution result format. */
|
||||
export interface IDIDResolutionResult {
|
||||
didDocument: IDIDDocument;
|
||||
didDocumentMetadata: {
|
||||
created: string;
|
||||
updated: string;
|
||||
deactivated: boolean;
|
||||
};
|
||||
didResolutionMetadata: {
|
||||
contentType: string;
|
||||
retrieved: string;
|
||||
};
|
||||
}
|
||||
|
||||
/** AGNTCY-format agent card. */
|
||||
export interface IAgentCard {
|
||||
did: string;
|
||||
name: string;
|
||||
agentType: string;
|
||||
capabilities: string[];
|
||||
owner: string;
|
||||
version: string;
|
||||
deploymentEnv: string;
|
||||
identityProvider: string;
|
||||
issuedAt: string;
|
||||
}
|
||||
|
||||
/** Raw database row for agent_did_keys. */
|
||||
export interface IAgentDIDKeyRow {
|
||||
keyId: string;
|
||||
agentId: string;
|
||||
organizationId: string;
|
||||
publicKeyJwk: IPublicKeyJwk;
|
||||
vaultKeyPath: string;
|
||||
keyType: string;
|
||||
curve: string;
|
||||
createdAt: Date;
|
||||
rotatedAt: Date | null;
|
||||
}
|
||||
@@ -69,6 +69,10 @@ export interface IAgent {
|
||||
status: AgentStatus;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
/** W3C DID identifier for this agent. Populated after DID generation. */
|
||||
did?: string;
|
||||
/** Timestamp when the DID was first generated for this agent. */
|
||||
didCreatedAt?: Date;
|
||||
}
|
||||
|
||||
/** Request body for registering a new AI agent. */
|
||||
|
||||
Reference in New Issue
Block a user