# Proposed contract, version 1: endpoints, errors, paging, idempotency, security and the capability of every
# operation. Resource schemas were initialized from the data model (docs/06-data) and are kept aligned with it; input
# schemas (*Input, *Request) and views are specific to this contract. Status: proposal for review, not confirmed design.
# Conventions: docs/05-interfaces/choosing-an-interface.md. Vendor extensions: x-moonitoring-audience (who calls),
# x-moonitoring-capability (the capability checked), x-moonitoring-entitlement (the entitlement feature checked),
# x-moonitoring-requirements (the requirements of 1.requisiti-raffinati.txt the operation serves).
openapi: 3.1.0
info:
  title: AI Model Platform Models API
  version: 1.0.0
  description: 'The model registry: models, their versions trained by a run, which version is deployed and the batch
    scorings that write predictions back to `farm`. A retired version refuses calls. Follows Model, ModelVersion
    and ScoringBatch of the data model (req 74 to 76, added with D7).'
servers:
- url: https://ai-model-platform.moonitoring.com/models/v1
  description: Prod
- url: https://stage-ai-model-platform.moonitoring.com/models/v1
  description: Stage, through IAP
security:
- bearer: []
tags:
- name: Models
  description: Registered models
- name: Versions
  description: Trained versions
- name: Scoring
  description: Batch scoring of farms
paths:
  /models:
    get:
      summary: List models
      operationId: listRegisteredModels
      tags:
      - Models
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/Model'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-model-platform.models.read
      x-moonitoring-requirements:
      - '74'
      - '1006.25'
      - '68.3'
    post:
      summary: Register a model
      operationId: registerModel
      tags:
      - Models
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ModelInput'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Model'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-model-platform.models.manage
      x-moonitoring-requirements:
      - '74'
      - '1006.25'
      - '68.3'
  /models/{model_id}:
    get:
      summary: Read a model
      operationId: getRegisteredModel
      tags:
      - Models
      parameters:
      - name: model_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Model'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-model-platform.models.read
      x-moonitoring-requirements:
      - '74'
      - '1006.25'
  /models/{model_id}/retire:
    post:
      summary: Retire a model
      operationId: retireModel
      description: A retired model refuses calls.
      tags:
      - Models
      parameters:
      - name: model_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Model'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-model-platform.models.manage
      x-moonitoring-requirements:
      - '74.9'
      - '1006.25'
  /models/{model_id}/versions:
    get:
      summary: List a model's versions
      operationId: listModelVersions
      tags:
      - Versions
      parameters:
      - name: model_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/ModelVersion'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-model-platform.models.read
      x-moonitoring-requirements:
      - '75'
      - '1006.25'
      - '62'
    post:
      summary: Register a version
      operationId: registerModelVersion
      tags:
      - Versions
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      - name: model_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ModelVersionInput'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ModelVersion'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-model-platform.models.manage
      x-moonitoring-requirements:
      - '75'
      - '75.4'
      - '1006.25'
      - '62'
  /model-versions/{version_id}/deploy:
    post:
      summary: Deploy a version
      operationId: deployModelVersion
      description: Publishes `model_version.deployed.v1`; the previous deployed version is retired.
      tags:
      - Versions
      parameters:
      - name: version_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ModelVersion'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-model-platform.models.manage
      x-moonitoring-requirements:
      - '75.7'
      - '74.8'
      - '1006.25'
  /model-versions/{version_id}/retire:
    post:
      summary: Retire a version
      operationId: retireModelVersion
      tags:
      - Versions
      parameters:
      - name: version_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ModelVersion'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-model-platform.models.manage
      x-moonitoring-requirements:
      - '75.7'
      - '1006.25'
  /scoring-batches:
    get:
      summary: List scoring batches
      operationId: listScoringBatches
      tags:
      - Scoring
      parameters:
      - name: model_version
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this version.
      - name: status
        in: query
        required: false
        schema:
          type: string
          enum:
          - queued
          - running
          - done
          - failed
        description: Only this status.
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Cursor
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/Limit
      responses:
        '200':
          description: One page of results.
          content:
            application/json:
              schema:
                type: object
                description: One page of items.
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/ScoringBatch'
                  next_cursor:
                    type: string
                    description: Where the next page starts; absent on the last page.
                required:
                - items
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-model-platform.models.read
      x-moonitoring-requirements:
      - '76'
      - '62'
      - '1006.25'
    post:
      summary: Start a scoring batch
      operationId: createScoringBatch
      description: Reads with `farm.canonical_data.read_all`, records a ModelRun and appends the predictions to
        `farm` through its gRPC `ComputedRecords` service.
      tags:
      - Scoring
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ScoringBatchInput'
      responses:
        '202':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ScoringBatch'
        '400':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/BadRequest
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '409':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Conflict
        '422':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/UnprocessableEntity
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-model-platform.models.manage
      x-moonitoring-requirements:
      - '76'
      - '62'
      - '62.2'
      - '62.3'
      - '1006.23'
      - '1006.25'
  /scoring-batches/{batch_id}:
    get:
      summary: Read a scoring batch
      operationId: getScoringBatch
      tags:
      - Scoring
      parameters:
      - name: batch_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ScoringBatch'
        '401':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Unauthorized
        '403':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/Forbidden
        '404':
          $ref: ../../../../common/v1/schemas.yaml#/components/responses/NotFound
      x-moonitoring-audience: staff
      x-moonitoring-capability: ai-model-platform.models.read
      x-moonitoring-requirements:
      - '76'
components:
  schemas:
    Model:
      type: object
      description: A model other systems can call, with the feature that gates it (req 74).
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          description: Unique, e.g. mastitis-risk.
        description:
          type: string
        feature:
          type: string
          description: The entitlement feature an Organization needs, e.g. farm.models.mastitis.
        output_kind:
          type: string
          enum:
          - observation
          - event
          description: 'What a prediction is written as in `farm`: a computed observation or a computed event.'
        output_observation_type:
          type: string
          format: uuid
          description: Only for output_kind observation.
        output_event_type:
          type: string
          description: The CanonicalEvent subtype, e.g. HeatEvent; only for output_kind event.
        deployed_version:
          type: string
          format: uuid
        status:
          type: string
          enum:
          - active
          - retired
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - name
      - feature
      - output_kind
      - status
      - created_at
      - updated_at
    ModelVersion:
      type: object
      description: One trained version of a model (req 75).
      properties:
        id:
          type: string
          format: uuid
        model:
          type: string
          format: uuid
        version:
          type: string
          description: Semver label.
        training_run:
          type: string
          format: uuid
          description: ID of the ModelRun that trained it.
        artifact_path:
          type: string
          description: gs:// path of the artifact in the model registry.
        endpoint:
          type: string
          description: The Vertex AI endpoint or the batch pipeline that serves it.
        status:
          type: string
          enum:
          - registered
          - deployed
          - retired
        deployed_at:
          type: string
          format: date-time
        retired_at:
          type: string
          format: date-time
        created_by:
          type: string
          format: uuid
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - model
      - version
      - training_run
      - status
      - created_at
      - updated_at
    ScoringBatch:
      type: object
      description: 'One batch scoring: reads farm data at a write number and appends predictions to `farm` as computed
        records (req 76).'
      properties:
        id:
          type: string
          format: uuid
        model_version:
          type: string
          format: uuid
        scope:
          type: string
          description: Farms, animals and period covered.
        data_seq:
          type: integer
        status:
          type: string
          enum:
          - queued
          - running
          - done
          - failed
        model_run:
          type: string
          format: uuid
          description: The ModelRun recorded for the batch.
        predictions_written:
          type: integer
        started_at:
          type: string
          format: date-time
        finished_at:
          type: string
          format: date-time
        last_error:
          type: string
        created_by:
          type: string
          format: uuid
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - model_version
      - scope
      - status
      - created_at
      - updated_at
    ModelInput:
      type: object
      description: Registers a model.
      properties:
        name:
          type: string
        description:
          type: string
        feature:
          type: string
        output_kind:
          type: string
          enum:
          - observation
          - event
          description: 'What a prediction is written as in `farm`: a computed observation or a computed event.'
        output_observation_type:
          type: string
          format: uuid
        output_event_type:
          type: string
      required:
      - name
      - feature
      - output_kind
    ModelVersionInput:
      type: object
      description: Registers a trained version from its training run.
      properties:
        version:
          type: string
        training_run:
          type: string
          format: uuid
        artifact_path:
          type: string
      required:
      - version
      - training_run
      - artifact_path
    ScoringBatchInput:
      type: object
      description: Starts a batch scoring.
      properties:
        model_version:
          type: string
          format: uuid
        scope:
          type: string
        data_seq:
          type: integer
          description: 'Default: the watermark.'
      required:
      - model_version
      - scope
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'The short-lived token signed by `access`: an Organization user token, a staff token or a client
        token, as the operation''s audience says.'
