openapi: 3.0.3
info:
  title: Saur.run API & Agent Gateway
  description: |
    Ultra-lightweight CI/CD Runner for GitLab & Autonomous AI Agent Studio.
    Provides Scale-to-Zero execution telemetry, dynamic OTP session rotation, and an OpenAI-compatible /v1/chat/completions endpoint with scoped knowledge RAG.
  version: 1.1.0
  contact:
    name: Saur.run Team
    url: https://saur.run
    email: support@saur.run
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: https://saur.run
    description: Production Cloudflare & Gateway Edge
  - url: http://localhost:8080
    description: Local Saur Studio & Agent Gateway

paths:
  /healthz:
    get:
      summary: Health check endpoint
      description: Returns OK if the runner/server process is alive.
      operationId: getHealth
      tags:
        - System
      responses:
        '200':
          description: Service is healthy
          content:
            text/plain:
              schema:
                type: string
                example: OK

  /api/v1/status:
    get:
      summary: Get Runner & Agent Telemetry
      description: Returns real-time Scale-to-Zero stats, active jobs, tags, and memory metrics.
      operationId: getRunnerStatus
      tags:
        - Runner
      responses:
        '200':
          description: Current runner runtime telemetry
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunnerStatusResponse'

  /api/v1/sessions/grant:
    post:
      summary: Grant Ephemeral OTP Session Token
      description: |
        Generates a short-lived, IP-bound session token for client-side chat widgets and third-party bots without exposing master API keys.
      operationId: grantSessionToken
      tags:
        - Authentication & Sessions
      security:
        - MasterKeyAuth: []
        - BearerAuth: []
        - []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GrantSessionRequest'
      responses:
        '200':
          description: Ephemeral session token successfully generated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GrantSessionResponse'
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized master key

  /api/v1/sessions/revoke:
    post:
      summary: Revoke Active Session Token
      description: Immediately invalidates an ephemeral OTP session token.
      operationId: revokeSessionToken
      tags:
        - Authentication & Sessions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - session_token
              properties:
                session_token:
                  type: string
                  example: saur_sess_9a8b7c6d5e4f3a2b
      responses:
        '200':
          description: Session successfully revoked
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Session token revoked

  /v1/chat/completions:
    post:
      summary: OpenAI-Compatible Chat Completions
      description: |
        Standard chat completions endpoint compatible with OpenAI SDKs, LangChain, and Botpress.
        Leverages Google Antigravity & Claude Code agents with scoped knowledge base retrieval (RAG).
      operationId: createChatCompletion
      tags:
        - AI Chat Completions
      security:
        - BearerAuth: []
        - SessionTokenAuth: []
        - []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatCompletionRequest'
      responses:
        '200':
          description: Successful completion response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatCompletionResponse'
            text/event-stream:
              schema:
                type: string
                description: Real-time SSE streaming tokens (when stream=true)
        '401':
          description: Missing or expired session token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

components:
  securitySchemes:
    MasterKeyAuth:
      type: apiKey
      in: header
      name: X-Master-Key
      description: Private server-side master API key for granting session tokens.
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT/Opaque
      description: Ephemeral session token or API key passed as Bearer token.
    SessionTokenAuth:
      type: apiKey
      in: header
      name: X-Session-Token
      description: Ephemeral session token granted via /api/v1/sessions/grant.

  schemas:
    GrantSessionRequest:
      type: object
      properties:
        tenant_id:
          type: string
          description: Project or tenant identifier
          example: my-shop
          default: consultant
        user_id:
          type: string
          description: Optional client/user identifier
          example: usr_8921
        ttl_seconds:
          type: integer
          description: Token lifetime in seconds
          example: 3600
          default: 3600
        allowed_topics:
          type: array
          items:
            type: string
          description: Scoped categories/topics the consultant may discuss
          example: ["shipping", "payment", "returns"]
        max_messages:
          type: integer
          description: Maximum messages allowed within this session
          example: 50
          default: 50

    GrantSessionResponse:
      type: object
      required:
        - success
        - session_token
        - expires_at
      properties:
        success:
          type: boolean
          example: true
        session_token:
          type: string
          example: saur_sess_7f8a9b0c1d2e3f4a
        expires_at:
          type: string
          format: date-time
          example: "2026-08-21T02:22:00Z"
        tenant_id:
          type: string
          example: my-shop
        agent_id:
          type: string
          example: google-antigravity

    ChatCompletionRequest:
      type: object
      required:
        - messages
      properties:
        model:
          type: string
          description: Model identifier
          example: google-antigravity
          default: google-antigravity
        messages:
          type: array
          description: Conversation history in OpenAI role/content format
          items:
            $ref: '#/components/schemas/ChatMessage'
        stream:
          type: boolean
          description: Enable Server-Sent Events (SSE) streaming
          default: false
        temperature:
          type: number
          format: float
          description: Sampling temperature (0.0 to 1.0)
          example: 0.7
          default: 0.7
        max_tokens:
          type: integer
          description: Maximum token count in completion
          example: 1024

    ChatMessage:
      type: object
      required:
        - role
        - content
      properties:
        role:
          type: string
          enum: [system, user, assistant]
          example: user
        content:
          type: string
          example: Какие варианты доставки доступны?

    ChatCompletionResponse:
      type: object
      required:
        - id
        - object
        - created
        - model
        - choices
      properties:
        id:
          type: string
          example: chatcmpl-1787219672669591000
        object:
          type: string
          example: chat.completion
        created:
          type: integer
          example: 1787219672
        model:
          type: string
          example: google-antigravity
        choices:
          type: array
          items:
            type: object
            properties:
              index:
                type: integer
                example: 0
              message:
                $ref: '#/components/schemas/ChatMessage'
              finish_reason:
                type: string
                example: stop
        usage:
          type: object
          properties:
            prompt_tokens:
              type: integer
              example: 45
            completion_tokens:
              type: integer
              example: 88
            total_tokens:
              type: integer
              example: 133

    RunnerStatusResponse:
      type: object
      required:
        - status
        - mode
      properties:
        status:
          type: string
          example: active
        mode:
          type: string
          example: gitlab_worker
        tags:
          type: string
          example: "saurrun,ai-runner,spot-runner"
        scale_to_zero:
          type: boolean
          example: true
        idle_ram_mb:
          type: integer
          example: 0
        stats:
          type: object
          properties:
            executed_jobs:
              type: integer
              example: 142
            active_jobs:
              type: integer
              example: 1
            uptime_seconds:
              type: integer
              example: 3600

    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          example: Invalid or expired session token
        code:
          type: integer
          example: 401
