fix(vv): resolve all 6 V&V issues — field trial unblocked
All findings from the inaugural LeadValidator audit resolved and confirmed. Release gate: PASS. VV_ISSUE_002 (BLOCKER): 15 OpenAPI specs verified present covering all 20 route groups (46 endpoints documented in docs/openapi/) VV_ISSUE_003 (MAJOR): Remove any types from src/db/pool.ts — replaced pool.query shim with unknown[] + Object.defineProperty, zero any types, eslint-disable suppressions removed VV_ISSUE_004 (MAJOR): Remove raw Pool from ScaffoldController and HealthDetailedController — injected AgentRepository/CredentialRepository and DbProbe interface respectively; added CredentialRepository.findActiveClientId() VV_ISSUE_005 (MAJOR): Add unit tests for 5 untested services — ComplianceStatusStore, EventPublisher, MarketplaceService, OIDCTrustPolicyService, UsageService VV_ISSUE_006 (MAJOR): Add integration tests for 7 missing route groups — analytics, billing, tiers, webhooks, marketplace, oidc-trust-policies, oidc-token-exchange VV_ISSUE_001 (MINOR): Create missing design.md and tasks.md in 4 OpenSpec archives — all archives now complete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
410
docs/openapi/oidc-wellknown.yaml
Normal file
410
docs/openapi/oidc-wellknown.yaml
Normal file
@@ -0,0 +1,410 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
title: SentryAgent.ai — OIDC Well-Known & Agent Info
|
||||
version: 1.0.0
|
||||
description: |
|
||||
OpenID Connect discovery, JWKS, and agent identity endpoints for the
|
||||
SentryAgent.ai AgentIdP platform.
|
||||
|
||||
**Unauthenticated endpoints** (public metadata):
|
||||
- `GET /.well-known/openid-configuration` — OIDC Discovery Document
|
||||
- `GET /.well-known/jwks.json` — JSON Web Key Set (public signing keys)
|
||||
|
||||
**Authenticated endpoint** (requires Bearer JWT):
|
||||
- `GET /agent-info` — Agent identity claims (equivalent to OIDC UserInfo)
|
||||
|
||||
All endpoints are mounted at the application root (`/`) so that
|
||||
`/.well-known/*` paths resolve correctly without an `/api/v1` prefix.
|
||||
|
||||
servers:
|
||||
- url: http://localhost:3000
|
||||
description: Local development server
|
||||
- url: https://api.sentryagent.ai
|
||||
description: Production server
|
||||
|
||||
tags:
|
||||
- name: OIDC Discovery
|
||||
description: Public OIDC metadata endpoints (unauthenticated)
|
||||
- name: Agent Info
|
||||
description: Authenticated agent identity endpoint
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
BearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
description: |
|
||||
JWT access token obtained via `POST /api/v1/token`.
|
||||
Include as `Authorization: Bearer <token>`.
|
||||
|
||||
schemas:
|
||||
OIDCDiscoveryDocument:
|
||||
type: object
|
||||
description: |
|
||||
OpenID Connect Discovery 1.0 document as defined in the OIDC specification.
|
||||
Returned by `GET /.well-known/openid-configuration`.
|
||||
required:
|
||||
- issuer
|
||||
- authorization_endpoint
|
||||
- token_endpoint
|
||||
- jwks_uri
|
||||
- response_types_supported
|
||||
- subject_types_supported
|
||||
- id_token_signing_alg_values_supported
|
||||
- scopes_supported
|
||||
- claims_supported
|
||||
- grant_types_supported
|
||||
properties:
|
||||
issuer:
|
||||
type: string
|
||||
format: uri
|
||||
description: OIDC Issuer URL. Must match the `iss` claim in ID tokens.
|
||||
example: "https://idp.sentryagent.ai"
|
||||
authorization_endpoint:
|
||||
type: string
|
||||
format: uri
|
||||
description: Authorization endpoint (stub — not implemented; client_credentials only).
|
||||
example: "https://idp.sentryagent.ai/oauth2/authorize"
|
||||
token_endpoint:
|
||||
type: string
|
||||
format: uri
|
||||
description: Token endpoint for the client_credentials grant.
|
||||
example: "https://idp.sentryagent.ai/oauth2/token"
|
||||
jwks_uri:
|
||||
type: string
|
||||
format: uri
|
||||
description: JWKS endpoint for ID token verification public keys.
|
||||
example: "https://idp.sentryagent.ai/.well-known/jwks.json"
|
||||
response_types_supported:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Supported response types.
|
||||
example: ["token", "id_token"]
|
||||
subject_types_supported:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Supported subject types.
|
||||
example: ["public"]
|
||||
id_token_signing_alg_values_supported:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Supported ID token signing algorithms.
|
||||
example: ["RS256", "ES256"]
|
||||
scopes_supported:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Supported OAuth 2.0 scopes.
|
||||
example: ["openid", "agents:read", "agents:write", "tokens:read", "audit:read", "admin:orgs"]
|
||||
claims_supported:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Claims that may appear in ID tokens or the agent-info response.
|
||||
example: ["sub", "iss", "aud", "iat", "exp", "agent_type", "deployment_env", "organization_id", "did"]
|
||||
grant_types_supported:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Supported grant types.
|
||||
example: ["client_credentials"]
|
||||
|
||||
JWKSKey:
|
||||
type: object
|
||||
description: A single JSON Web Key. Supports RSA (RS256) and EC P-256 (ES256) keys.
|
||||
required:
|
||||
- kid
|
||||
- kty
|
||||
- use
|
||||
- alg
|
||||
properties:
|
||||
kid:
|
||||
type: string
|
||||
description: Key ID — matches the `kid` header in signed JWTs.
|
||||
example: "key-20260328-001"
|
||||
kty:
|
||||
type: string
|
||||
description: Key type.
|
||||
enum:
|
||||
- RSA
|
||||
- EC
|
||||
example: "RSA"
|
||||
use:
|
||||
type: string
|
||||
description: Intended use. Always `sig` for signing keys.
|
||||
example: "sig"
|
||||
alg:
|
||||
type: string
|
||||
description: Algorithm.
|
||||
enum:
|
||||
- RS256
|
||||
- ES256
|
||||
example: "RS256"
|
||||
n:
|
||||
type: string
|
||||
description: RSA — Base64url-encoded modulus.
|
||||
example: "sI3P8XVb..."
|
||||
e:
|
||||
type: string
|
||||
description: RSA — Base64url-encoded public exponent.
|
||||
example: "AQAB"
|
||||
crv:
|
||||
type: string
|
||||
description: EC — Curve name.
|
||||
example: "P-256"
|
||||
x:
|
||||
type: string
|
||||
description: EC — Base64url-encoded x coordinate.
|
||||
example: "f83OJ3D..."
|
||||
y:
|
||||
type: string
|
||||
description: EC — Base64url-encoded y coordinate.
|
||||
example: "x_FEzRu..."
|
||||
|
||||
JWKSResponse:
|
||||
type: object
|
||||
description: JSON Web Key Set returned by `GET /.well-known/jwks.json`.
|
||||
required:
|
||||
- keys
|
||||
properties:
|
||||
keys:
|
||||
type: array
|
||||
description: |
|
||||
Array of JSON Web Keys. Includes all non-expired keys to support
|
||||
key rotation grace periods.
|
||||
items:
|
||||
$ref: '#/components/schemas/JWKSKey'
|
||||
|
||||
AgentInfoResponse:
|
||||
type: object
|
||||
description: |
|
||||
Agent identity claims for the authenticated caller.
|
||||
Analogous to the OIDC UserInfo endpoint.
|
||||
required:
|
||||
- sub
|
||||
- agent_type
|
||||
- deployment_env
|
||||
- organization_id
|
||||
- scope
|
||||
properties:
|
||||
sub:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Agent UUID (subject).
|
||||
example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
||||
agent_type:
|
||||
type: string
|
||||
description: Functional classification of the agent.
|
||||
example: "screener"
|
||||
deployment_env:
|
||||
type: string
|
||||
description: Target deployment environment of the agent.
|
||||
example: "production"
|
||||
organization_id:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Organization UUID the agent belongs to.
|
||||
example: "org-1234-5678-abcd-ef01"
|
||||
did:
|
||||
type: string
|
||||
description: W3C DID identifier for the agent, if one has been generated.
|
||||
example: "did:web:api.sentryagent.ai:agents:a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
||||
scope:
|
||||
type: string
|
||||
description: OAuth 2.0 scope associated with the Bearer token used to call this endpoint.
|
||||
example: "agents:read agents:write"
|
||||
|
||||
ErrorResponse:
|
||||
type: object
|
||||
description: Standard error response envelope.
|
||||
required:
|
||||
- code
|
||||
- message
|
||||
properties:
|
||||
code:
|
||||
type: string
|
||||
example: "UNAUTHORIZED"
|
||||
message:
|
||||
type: string
|
||||
example: "A valid Bearer token is required to access this resource."
|
||||
details:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
responses:
|
||||
Unauthorized:
|
||||
description: Missing or invalid Bearer token.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
example:
|
||||
code: "UNAUTHORIZED"
|
||||
message: "A valid Bearer token is required to access this resource."
|
||||
|
||||
NotFound:
|
||||
description: The requested resource was not found.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
example:
|
||||
code: "AGENT_NOT_FOUND"
|
||||
message: "Agent with the specified ID was not found."
|
||||
|
||||
InternalServerError:
|
||||
description: Unexpected server error.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
example:
|
||||
code: "INTERNAL_SERVER_ERROR"
|
||||
message: "An unexpected error occurred. Please try again later."
|
||||
|
||||
paths:
|
||||
/.well-known/openid-configuration:
|
||||
get:
|
||||
operationId: getOIDCDiscoveryDocument
|
||||
tags:
|
||||
- OIDC Discovery
|
||||
summary: OIDC Discovery Document
|
||||
description: |
|
||||
Returns the OpenID Connect Discovery 1.0 document for the SentryAgent.ai AgentIdP.
|
||||
|
||||
Consumers can fetch this document to auto-discover the token endpoint,
|
||||
JWKS URI, supported scopes, and supported claims — without hard-coding URLs.
|
||||
|
||||
This endpoint is **unauthenticated** and publicly cacheable.
|
||||
security: []
|
||||
responses:
|
||||
'200':
|
||||
description: OIDC Discovery Document returned successfully.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/OIDCDiscoveryDocument'
|
||||
example:
|
||||
issuer: "https://idp.sentryagent.ai"
|
||||
authorization_endpoint: "https://idp.sentryagent.ai/oauth2/authorize"
|
||||
token_endpoint: "https://idp.sentryagent.ai/oauth2/token"
|
||||
jwks_uri: "https://idp.sentryagent.ai/.well-known/jwks.json"
|
||||
response_types_supported:
|
||||
- token
|
||||
- id_token
|
||||
subject_types_supported:
|
||||
- public
|
||||
id_token_signing_alg_values_supported:
|
||||
- RS256
|
||||
- ES256
|
||||
scopes_supported:
|
||||
- openid
|
||||
- agents:read
|
||||
- agents:write
|
||||
- tokens:read
|
||||
- audit:read
|
||||
- admin:orgs
|
||||
claims_supported:
|
||||
- sub
|
||||
- iss
|
||||
- aud
|
||||
- iat
|
||||
- exp
|
||||
- agent_type
|
||||
- deployment_env
|
||||
- organization_id
|
||||
- did
|
||||
grant_types_supported:
|
||||
- client_credentials
|
||||
'500':
|
||||
$ref: '#/components/responses/InternalServerError'
|
||||
|
||||
/.well-known/jwks.json:
|
||||
get:
|
||||
operationId: getJWKS
|
||||
tags:
|
||||
- OIDC Discovery
|
||||
summary: JSON Web Key Set (public signing keys)
|
||||
description: |
|
||||
Returns the JSON Web Key Set (JWKS) containing all active public keys
|
||||
used to sign ID tokens. Consumers use this to verify ID token signatures.
|
||||
|
||||
All non-expired keys are returned to support key rotation grace periods —
|
||||
a token signed with a recently-rotated key will still verify correctly
|
||||
if the old key appears in the JWKS response.
|
||||
|
||||
**Cache-Control:** `public, max-age=3600` — responses may be cached for up to 1 hour.
|
||||
|
||||
This endpoint is **unauthenticated**.
|
||||
security: []
|
||||
responses:
|
||||
'200':
|
||||
description: JWKS returned successfully.
|
||||
headers:
|
||||
Cache-Control:
|
||||
schema:
|
||||
type: string
|
||||
description: Caching directive. Always `public, max-age=3600`.
|
||||
example: "public, max-age=3600"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/JWKSResponse'
|
||||
example:
|
||||
keys:
|
||||
- kid: "key-20260328-001"
|
||||
kty: "RSA"
|
||||
use: "sig"
|
||||
alg: "RS256"
|
||||
n: "sI3P8XVb..."
|
||||
e: "AQAB"
|
||||
'500':
|
||||
$ref: '#/components/responses/InternalServerError'
|
||||
|
||||
/agent-info:
|
||||
get:
|
||||
operationId: getAgentInfo
|
||||
tags:
|
||||
- Agent Info
|
||||
summary: Get authenticated agent identity claims
|
||||
description: |
|
||||
Returns identity claims for the agent authenticated by the provided Bearer token.
|
||||
Equivalent to the OIDC UserInfo endpoint — returns the agent's type,
|
||||
deployment environment, organization, DID (if generated), and active scopes.
|
||||
|
||||
The agent UUID is read from the `sub` claim of the Bearer token.
|
||||
Requires a valid Bearer JWT.
|
||||
security:
|
||||
- BearerAuth: []
|
||||
responses:
|
||||
'200':
|
||||
description: Agent identity claims returned successfully.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AgentInfoResponse'
|
||||
example:
|
||||
sub: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
||||
agent_type: "screener"
|
||||
deployment_env: "production"
|
||||
organization_id: "org-1234-5678-abcd-ef01"
|
||||
did: "did:web:api.sentryagent.ai:agents:a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
||||
scope: "agents:read agents:write"
|
||||
'401':
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
'404':
|
||||
description: The agent referenced in the token no longer exists.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
example:
|
||||
code: "AGENT_NOT_FOUND"
|
||||
message: "Agent with the specified ID was not found."
|
||||
'500':
|
||||
$ref: '#/components/responses/InternalServerError'
|
||||
Reference in New Issue
Block a user