feat: Phase 1 MVP — complete AgentIdP implementation
Implements all P0 features per OpenSpec change phase-1-mvp-implementation: - Agent Registry Service (CRUD) — full lifecycle management - OAuth 2.0 Token Service (Client Credentials flow) - Credential Management (generate, rotate, revoke) - Immutable Audit Log Service Tech: Node.js 18+, TypeScript 5.3+ strict, Express 4.18+, PostgreSQL 14+, Redis 7+ Standards: OpenAPI 3.0 specs, DRY/SOLID, zero `any` types Quality: 18 unit test suites, 244 tests passing, 97%+ coverage OpenAPI: 4 complete specs (14 endpoints total) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
283
src/types/index.ts
Normal file
283
src/types/index.ts
Normal file
@@ -0,0 +1,283 @@
|
||||
/**
|
||||
* Shared TypeScript interfaces and types for SentryAgent.ai AgentIdP.
|
||||
* All interfaces and types live here — no inline type definitions in service/controller files.
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// Enumerations / Union Types
|
||||
// ============================================================================
|
||||
|
||||
/** Functional classification of an AI agent. */
|
||||
export type AgentType =
|
||||
| 'screener'
|
||||
| 'classifier'
|
||||
| 'orchestrator'
|
||||
| 'extractor'
|
||||
| 'summarizer'
|
||||
| 'router'
|
||||
| 'monitor'
|
||||
| 'custom';
|
||||
|
||||
/** Lifecycle status of an AI agent. */
|
||||
export type AgentStatus = 'active' | 'suspended' | 'decommissioned';
|
||||
|
||||
/** Target deployment environment for an agent. */
|
||||
export type DeploymentEnv = 'development' | 'staging' | 'production';
|
||||
|
||||
/** Lifecycle status of an agent credential. */
|
||||
export type CredentialStatus = 'active' | 'revoked';
|
||||
|
||||
/** OAuth 2.0 scope values supported by this IdP. */
|
||||
export type OAuthScope = 'agents:read' | 'agents:write' | 'tokens:read' | 'audit:read';
|
||||
|
||||
/** Audit action identifiers for all significant platform events. */
|
||||
export type AuditAction =
|
||||
| 'agent.created'
|
||||
| 'agent.updated'
|
||||
| 'agent.decommissioned'
|
||||
| 'agent.suspended'
|
||||
| 'agent.reactivated'
|
||||
| 'token.issued'
|
||||
| 'token.revoked'
|
||||
| 'token.introspected'
|
||||
| 'credential.generated'
|
||||
| 'credential.rotated'
|
||||
| 'credential.revoked'
|
||||
| 'auth.failed';
|
||||
|
||||
/** Outcome of an audited action. */
|
||||
export type AuditOutcome = 'success' | 'failure';
|
||||
|
||||
// ============================================================================
|
||||
// Agent Registry
|
||||
// ============================================================================
|
||||
|
||||
/** Full representation of a registered AI agent identity. */
|
||||
export interface IAgent {
|
||||
agentId: string;
|
||||
email: string;
|
||||
agentType: AgentType;
|
||||
version: string;
|
||||
capabilities: string[];
|
||||
owner: string;
|
||||
deploymentEnv: DeploymentEnv;
|
||||
status: AgentStatus;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
/** Request body for registering a new AI agent. */
|
||||
export interface ICreateAgentRequest {
|
||||
email: string;
|
||||
agentType: AgentType;
|
||||
version: string;
|
||||
capabilities: string[];
|
||||
owner: string;
|
||||
deploymentEnv: DeploymentEnv;
|
||||
}
|
||||
|
||||
/** Request body for partially updating an agent. */
|
||||
export interface IUpdateAgentRequest {
|
||||
agentType?: AgentType;
|
||||
version?: string;
|
||||
capabilities?: string[];
|
||||
owner?: string;
|
||||
deploymentEnv?: DeploymentEnv;
|
||||
status?: AgentStatus;
|
||||
}
|
||||
|
||||
/** Paginated list of agents. */
|
||||
export interface IPaginatedAgentsResponse {
|
||||
data: IAgent[];
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
}
|
||||
|
||||
/** Query filters for listing agents. */
|
||||
export interface IAgentListFilters {
|
||||
owner?: string;
|
||||
agentType?: AgentType;
|
||||
status?: AgentStatus;
|
||||
page: number;
|
||||
limit: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Credentials
|
||||
// ============================================================================
|
||||
|
||||
/** A credential record for an AI agent (clientSecret never included). */
|
||||
export interface ICredential {
|
||||
credentialId: string;
|
||||
clientId: string;
|
||||
status: CredentialStatus;
|
||||
createdAt: Date;
|
||||
expiresAt: Date | null;
|
||||
revokedAt: Date | null;
|
||||
}
|
||||
|
||||
/** Credential with the plain-text secret — returned once only on create/rotate. */
|
||||
export interface ICredentialWithSecret extends ICredential {
|
||||
clientSecret: string;
|
||||
}
|
||||
|
||||
/** Database row for a credential, including the bcrypt hash. */
|
||||
export interface ICredentialRow extends ICredential {
|
||||
secretHash: string;
|
||||
}
|
||||
|
||||
/** Request body for generating or rotating a credential. */
|
||||
export interface IGenerateCredentialRequest {
|
||||
expiresAt?: string | Date;
|
||||
}
|
||||
|
||||
/** Paginated list of credentials. */
|
||||
export interface IPaginatedCredentialsResponse {
|
||||
data: ICredential[];
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
}
|
||||
|
||||
/** Query filters for listing credentials. */
|
||||
export interface ICredentialListFilters {
|
||||
status?: CredentialStatus;
|
||||
page: number;
|
||||
limit: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// OAuth2 Token
|
||||
// ============================================================================
|
||||
|
||||
/** JWT access token payload (claims). */
|
||||
export interface ITokenPayload {
|
||||
/** Subject — agentId. */
|
||||
sub: string;
|
||||
/** client_id — agentId. */
|
||||
client_id: string;
|
||||
/** Space-separated OAuth 2.0 scopes. */
|
||||
scope: string;
|
||||
/** JWT ID — UUID v4. */
|
||||
jti: string;
|
||||
/** Issued at (Unix seconds). */
|
||||
iat: number;
|
||||
/** Expiry (Unix seconds). */
|
||||
exp: number;
|
||||
}
|
||||
|
||||
/** OAuth 2.0 token request (form-encoded). */
|
||||
export interface ITokenRequest {
|
||||
grant_type: string;
|
||||
client_id?: string;
|
||||
client_secret?: string;
|
||||
scope?: string;
|
||||
}
|
||||
|
||||
/** Successful OAuth 2.0 token response. */
|
||||
export interface ITokenResponse {
|
||||
access_token: string;
|
||||
token_type: 'Bearer';
|
||||
expires_in: number;
|
||||
scope: string;
|
||||
}
|
||||
|
||||
/** OAuth 2.0 error response (RFC 6749 §5.2). */
|
||||
export interface IOAuth2ErrorResponse {
|
||||
error: string;
|
||||
error_description: string;
|
||||
}
|
||||
|
||||
/** Token introspection request (RFC 7662). */
|
||||
export interface IIntrospectRequest {
|
||||
token: string;
|
||||
token_type_hint?: string;
|
||||
}
|
||||
|
||||
/** Token introspection response (RFC 7662). */
|
||||
export interface IIntrospectResponse {
|
||||
active: boolean;
|
||||
sub?: string;
|
||||
client_id?: string;
|
||||
scope?: string;
|
||||
token_type?: string;
|
||||
iat?: number;
|
||||
exp?: number;
|
||||
}
|
||||
|
||||
/** Token revocation request (RFC 7009). */
|
||||
export interface IRevokeRequest {
|
||||
token: string;
|
||||
token_type_hint?: string;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Audit Log
|
||||
// ============================================================================
|
||||
|
||||
/** An immutable audit event record. */
|
||||
export interface IAuditEvent {
|
||||
eventId: string;
|
||||
agentId: string;
|
||||
action: AuditAction;
|
||||
outcome: AuditOutcome;
|
||||
ipAddress: string;
|
||||
userAgent: string;
|
||||
metadata: Record<string, unknown>;
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
/** Input for creating a new audit event. */
|
||||
export interface ICreateAuditEventInput {
|
||||
agentId: string;
|
||||
action: AuditAction;
|
||||
outcome: AuditOutcome;
|
||||
ipAddress: string;
|
||||
userAgent: string;
|
||||
metadata: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/** Paginated list of audit events. */
|
||||
export interface IPaginatedAuditEventsResponse {
|
||||
data: IAuditEvent[];
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
}
|
||||
|
||||
/** Query filters for the audit log. */
|
||||
export interface IAuditListFilters {
|
||||
agentId?: string;
|
||||
action?: AuditAction;
|
||||
outcome?: AuditOutcome;
|
||||
fromDate?: string;
|
||||
toDate?: string;
|
||||
page: number;
|
||||
limit: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// API Error Response
|
||||
// ============================================================================
|
||||
|
||||
/** Standard error response envelope used across all SentryAgent.ai APIs. */
|
||||
export interface IErrorResponse {
|
||||
code: string;
|
||||
message: string;
|
||||
details?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Express type augmentation
|
||||
// ============================================================================
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
namespace Express {
|
||||
interface Request {
|
||||
/** Decoded JWT payload attached by the auth middleware. */
|
||||
user?: ITokenPayload;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user