openapi: "3.0.3"

info:
  title: SentryAgent.ai — OIDC Trust Policies
  version: 1.0.0
  description: |
    OIDC trust policy management endpoints for the SentryAgent.ai AgentIdP platform.

    Trust policies allow tenants to configure Workload Identity Federation:
    workflows running in a trusted OIDC provider (e.g. GitHub Actions) can exchange
    their OIDC JWT for a SentryAgent.ai access token without long-lived credentials.

    **Supported OIDC providers:** `github`

    **Workflow:**
    1. Create a trust policy linking a GitHub repo (+ optional branch) to an agent UUID
    2. In your GitHub Actions workflow, call `POST /api/v1/oidc/token` with the GitHub OIDC JWT
    3. Receive a SentryAgent.ai Bearer token scoped to the linked agent

    **All endpoints require a valid Bearer JWT.**

servers:
  - url: http://localhost:3000/api/v1
    description: Local development server
  - url: https://api.sentryagent.ai/v1
    description: Production server

tags:
  - name: OIDC Trust Policies
    description: Workload Identity Federation trust policy management

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        JWT access token obtained via `POST /token`.
        Include as `Authorization: Bearer <token>`.

  schemas:
    OIDCProvider:
      type: string
      enum:
        - github
      description: |
        Supported OIDC provider identifier.
        Currently only "github" is supported; the list is extensible.
      example: github

    OIDCTrustPolicy:
      type: object
      description: A persisted OIDC trust policy record.
      required:
        - id
        - provider
        - repository
        - agentId
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          format: uuid
          description: Immutable system-assigned UUID for this trust policy.
          readOnly: true
          example: "tp-abcd-1234-5678-ef01"
        provider:
          $ref: '#/components/schemas/OIDCProvider'
        repository:
          type: string
          description: |
            GitHub repository in "org/repo" format.
            Only workflows running in this repository may exchange tokens.
          pattern: '^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$'
          example: "acme-corp/agent-deployer"
        branch:
          type: string
          nullable: true
          description: |
            Optional branch constraint. When set, only the specified branch may
            exchange tokens. When null, any branch in the repository is allowed.
          example: "main"
        agentId:
          type: string
          format: uuid
          description: UUID of the agent this trust policy grants access to.
          example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
        createdAt:
          type: string
          format: date-time
          readOnly: true
          example: "2026-03-01T08:00:00.000Z"
        updatedAt:
          type: string
          format: date-time
          readOnly: true
          example: "2026-03-28T11:30:00.000Z"

    CreateTrustPolicyRequest:
      type: object
      description: Request body for registering a new OIDC trust policy.
      required:
        - provider
        - repository
        - agentId
      properties:
        provider:
          $ref: '#/components/schemas/OIDCProvider'
        repository:
          type: string
          description: |
            GitHub repository in "org/repo" format. Case-sensitive.
            Only workflows in this repository may use this trust policy.
          pattern: '^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$'
          example: "acme-corp/agent-deployer"
        branch:
          type: string
          description: |
            Optional branch constraint. When omitted, any branch in the repository is permitted.
            Recommended to set this to `main` for production trust policies.
          example: "main"
        agentId:
          type: string
          format: uuid
          description: |
            UUID of the agent to grant access to.
            The agent must be registered and active in the same organization.
          example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"

    ErrorResponse:
      type: object
      description: Standard error response envelope.
      required:
        - code
        - message
      properties:
        code:
          type: string
          example: "TRUST_POLICY_NOT_FOUND"
        message:
          type: string
          example: "Trust policy with the specified ID was not found."
        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."

    Forbidden:
      description: Valid token but insufficient permissions.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: "FORBIDDEN"
            message: "You do not have permission to perform this action."

    NotFound:
      description: Trust policy not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: "TRUST_POLICY_NOT_FOUND"
            message: "Trust policy 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."

security:
  - BearerAuth: []

paths:
  /oidc/trust-policies:
    post:
      operationId: createOIDCTrustPolicy
      tags:
        - OIDC Trust Policies
      summary: Create an OIDC trust policy
      description: |
        Registers a new OIDC trust policy.

        Once created, workflows running in the specified GitHub repository
        (and optionally matching the specified branch) can exchange their
        GitHub OIDC JWT for a SentryAgent.ai access token via `POST /oidc/token`.

        A trust policy is organization-scoped — the agent referenced by `agentId`
        must belong to the same organization as the authenticated caller.

        Requires a valid Bearer JWT (minimum `agents:write` scope recommended).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTrustPolicyRequest'
            example:
              provider: "github"
              repository: "acme-corp/agent-deployer"
              branch: "main"
              agentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      responses:
        '201':
          description: Trust policy created successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OIDCTrustPolicy'
              example:
                id: "tp-abcd-1234-5678-ef01"
                provider: "github"
                repository: "acme-corp/agent-deployer"
                branch: "main"
                agentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                createdAt: "2026-04-07T09:00:00.000Z"
                updatedAt: "2026-04-07T09:00:00.000Z"
        '400':
          description: Validation error in request body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalidProvider:
                  summary: Unsupported OIDC provider
                  value:
                    code: "VALIDATION_ERROR"
                    message: "Request validation failed."
                    details:
                      field: "provider"
                      reason: "Only 'github' is supported."
                invalidRepository:
                  summary: Invalid repository format
                  value:
                    code: "VALIDATION_ERROR"
                    message: "Request validation failed."
                    details:
                      field: "repository"
                      reason: "Must be in 'org/repo' format."
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: Referenced agent not found in this organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: "AGENT_NOT_FOUND"
                message: "Agent with the specified ID was not found."
        '409':
          description: A trust policy for this provider/repository/branch combination already exists.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: "TRUST_POLICY_CONFLICT"
                message: "A trust policy for this repository and branch already exists."
                details:
                  provider: "github"
                  repository: "acme-corp/agent-deployer"
                  branch: "main"
        '500':
          $ref: '#/components/responses/InternalServerError'

    get:
      operationId: listOIDCTrustPolicies
      tags:
        - OIDC Trust Policies
      summary: List OIDC trust policies
      description: |
        Returns all trust policies for the authenticated organization,
        optionally filtered by the `agentId` query parameter.

        Requires a valid Bearer JWT.
      parameters:
        - name: agentId
          in: query
          required: false
          description: Filter trust policies linked to a specific agent UUID.
          schema:
            type: string
            format: uuid
          example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      responses:
        '200':
          description: List of trust policies returned successfully.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/OIDCTrustPolicy'
              example:
                - id: "tp-abcd-1234-5678-ef01"
                  provider: "github"
                  repository: "acme-corp/agent-deployer"
                  branch: "main"
                  agentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                  createdAt: "2026-03-01T08:00:00.000Z"
                  updatedAt: "2026-03-01T08:00:00.000Z"
                - id: "tp-efgh-5678-1234-ab01"
                  provider: "github"
                  repository: "acme-corp/inference-runner"
                  branch: null
                  agentId: "b2c3d4e5-f6a7-8901-bcde-f12345678901"
                  createdAt: "2026-03-15T10:00:00.000Z"
                  updatedAt: "2026-03-15T10:00:00.000Z"
        '400':
          description: Invalid query parameters.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: "VALIDATION_ERROR"
                message: "Invalid query parameter value."
                details:
                  field: "agentId"
                  reason: "Must be a valid UUID."
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /oidc/trust-policies/{id}:
    parameters:
      - name: id
        in: path
        required: true
        description: UUID of the trust policy to delete.
        schema:
          type: string
          format: uuid
        example: "tp-abcd-1234-5678-ef01"

    delete:
      operationId: deleteOIDCTrustPolicy
      tags:
        - OIDC Trust Policies
      summary: Delete an OIDC trust policy
      description: |
        Permanently deletes an OIDC trust policy.

        After deletion, workflows that previously used this policy to exchange
        GitHub OIDC tokens will receive `403 Forbidden` from `POST /oidc/token`.

        Requires a valid Bearer JWT.
      responses:
        '204':
          description: Trust policy deleted successfully. No response body.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
