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'
