openapi: 3.1.0
jsonSchemaDialect: "https://json-schema.org/draft/2020-12/schema"
info:
  title: FermiHDI Message Bus Ingester API
  description: |
    Control and telemetry endpoints for the Message Bus Ingester.
    
    The ingester exposes two sets of endpoints:
    1. **Observability Endpoints** (Unencrypted, Port 8081 by default): Used for health checks and metrics.
    2. **Control Plane Endpoints** (mTLS, Port 6986 by default): Used by the DMS to push configuration updates.
  version: 1.1.0
servers:
  - url: "http://localhost:8081"
    description: Observability Server
  - url: "https://localhost:6986"
    description: Control Plane mTLS Server (Requires client certificate)

paths:
  /healthz:
    get:
      summary: Liveness/Readiness Check
      description: Returns the health status and current epoch timestamp.
      responses:
        '200':
          description: Service is healthy.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status: { type: string, example: "ok" }
                  timestamp: { type: number, example: 1706767436.123 }
  /livez:
    get:
      summary: Liveness Check
      description: Standard orchestrator liveness check.
      responses:
        '200':
          description: Service is alive.
  /readyz:
    get:
      summary: Readiness Check
      description: Standard orchestrator readiness check.
      responses:
        '200':
          description: Service is ready.
  /metrics:
    get:
      summary: Prometheus Metrics
      description: Exposes system metrics in Prometheus format.
      responses:
        '200':
          description: Prometheus metrics text.
          content:
            text/plain:
              schema: { type: string }

  /v1/ingest/config:
    post:
      summary: Configuration Update (DMS Push)
      description: |
        Pushed by the DMS when Storage Cluster topography changes. 
        Updates take effect at the next batch rotation to maintain consistency.
        
        During Phase 1 boot, receiving the first populated `scc_targets` push will trigger Phase 2 completion
        and report StatusFullyReady to the DMS.
      security:
        - mtls: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AppConfig'
      responses:
        '202':
          description: Configuration update queued for next batch.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status: { type: string, example: "accepted" }

webhooks:
  dmsRegistration:
    post:
      summary: DMS Registration Webhook
      description: The Ingester automatically calls out to the DMS on startup to register its presence.
      operationId: registerWithDms
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                service_name: { type: string }
                node_name: { type: string }
                environment: { type: string }
      responses:
        '200':
          description: Registration successful, usually returns initial configuration parameters.

components:
  securitySchemes:
    mtls:
      type: mutualTLS
  schemas:
    AppConfig:
      type: object
      description: Complete configuration for the Message Bus Ingester.
      properties:
        ingression_type:
          type: string
          enum: [kafka, rabbitmq, mqtt, file, s3]
          default: kafka
        input_format:
          type: string
          enum: [json, rowbinary, csv]
          default: json
        schema_file:
          type: string
          default: dataset_schema.json
        batch_interval_seconds:
          type: integer
          nullable: true
          description: Optional override for batch rotation window in seconds.
        batch_id_field:
          type: string
          description: Field in the payload to use as Batch ID.
        tcp_max_session_duration_sec:
          type: integer
          default: 600
        kafka:
          type: object
          properties:
            brokers: { type: string }
            topic: { type: string }
            group_id: { type: string }
        rabbitmq:
          type: object
          properties:
            url: { type: string }
            queue: { type: string }
        mqtt:
          type: object
          properties:
            address: { type: string }
            client_id: { type: string }
            topic: { type: string }
        file:
          type: object
          properties:
            directory: { type: string }
            sort_by: { type: string, enum: [alphanumeric, modified_time] }
        s3:
          type: object
          properties:
            bucket: { type: string }
            prefix: { type: string }
            region: { type: string }
            endpoint: { type: string }
            sort_by: { type: string, enum: [alphanumeric, modified_time] }
        scc_targets:
          type: array
          items:
            $ref: '#/components/schemas/SCCTarget'
        target_storage_clusters:
          type: array
          items: { type: string }
        env:
          type: string
          enum: [production, development]
          default: production
        node_name: { type: string }
        log_level:
          type: string
          enum: [DEBUG, INFO, WARN, ERROR]
          default: INFO
        otel_collector_url: { type: string }
        dms_url: { type: string }
        healthcheck_port: { type: integer, default: 8081 }
        opt_in: { type: boolean, default: false }
        sentry_dsn: { type: string }
        bootstrap_token: { type: string }
        k8s_token: { type: string }
        client_cert_file: { type: string }
        client_key_file: { type: string }
    SCCTarget:
      type: object
      required: [address, port]
      properties:
        address: { type: string }
        port: { type: integer }
        description: { type: string }
        round_batch_id_field:
          type: boolean
          description: If true, rounds the extracted batch ID to the time index interval for time_series datasets.
