openapi: 3.0.3
info:
  title: Repzo API - AI Object Detection Mission Set
  version: 1.0.0
  description: |
    **Mission sets** group missions (`/ai-object-detection-mission`) into
    the unit assignment rules (`/ai-object-detection-assignment-rule`)
    target: "assign set X to clients with tag Y", each rule line carrying a
    requirement mode for the set's missions. Resolution happens at read /
    evaluation time (the mission `scores_for` read, the assigned-missions
    read and the metric evaluator) — nothing is ever persisted on the
    client, so editing a set's `missions` is reflected on the next read.

    **Validation.** Create AND update require `missions` with at least one
    valid mission id (every violation listed in one 400). `enabled: false`
    makes the set invisible to assignment resolution without deleting it.

    **Multi-tenancy & lifecycle.** Scoped by `company_namespace` (injected
    from the caller's token; SDK callers may pass an explicit value on
    create), soft-deleted via `disabled`. `PATCH` is not supported (400 —
    use `PUT`). Admin-facing.
servers:
  - url: https://sv.api.repzo.me
security:
  - ApiKeyAuth: []
  - JwtAuth: []
paths:
  /ai-object-detection-mission-set:
    get:
      summary: List mission sets
      operationId: findMissionSet
      parameters:
        - in: query
          name: _id
          schema:
            oneOf:
              - type: string
              - type: array
                items: { type: string }
        - in: query
          name: name
          description: Exact name match.
          schema:
            oneOf:
              - type: string
              - type: array
                items: { type: string }
        - in: query
          name: search
          description: Case-insensitive substring search on `name`.
          schema: { type: string }
        - in: query
          name: enabled
          schema: { type: boolean }
        - in: query
          name: disabled
          description: "Include soft-deleted sets (`true`) or only live ones (`false`). Omitted = no filter."
          schema: { type: boolean }
        - in: query
          name: from_updatedAt
          schema: { type: number }
        - in: query
          name: to_updatedAt
          schema: { type: number }
        - in: query
          name: from_createdAt
          schema: { type: number }
        - in: query
          name: to_createdAt
          schema: { type: number }
        - in: query
          name: per_page
          schema: { type: integer, minimum: 1 }
        - in: query
          name: page
          schema: { type: integer, minimum: 1 }
      responses:
        "200":
          description: "Paginated documents (newest `_id` first)."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MissionSetFindResult"
    post:
      summary: Create a mission set
      operationId: createMissionSet
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MissionSetCreateBody"
      responses:
        "201":
          description: The created document.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MissionSet"
        "400":
          description: Validation failed — the message lists every violation.
  /ai-object-detection-mission-set/{id}:
    get:
      summary: Get a mission set
      operationId: getMissionSet
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      responses:
        "200":
          description: The document.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MissionSet"
        "400":
          description: Not found.
    put:
      summary: Update a mission set (re-validated)
      description: "Same validation as create — `missions` (≥ 1 id) is required again. Set `disabled: true` to soft-delete."
      operationId: updateMissionSet
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MissionSetUpdateBody"
      responses:
        "200":
          description: The updated document.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MissionSet"
        "400":
          description: Validation failed.
        "404":
          description: Not found.
    delete:
      summary: Soft-delete a mission set
      operationId: removeMissionSet
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      responses:
        "200":
          description: The disabled document.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MissionSet"
        "404":
          description: Not found.
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: api-key
    JwtAuth:
      type: apiKey
      in: header
      name: Authorization
  schemas:
    UserStamp:
      type: object
      description: "Who created / last edited the document (server-stamped from the token)."
      properties:
        _id: { type: string }
        name: { type: string }
        type:
          type: string
          enum: [admin, rep, client, tenant]
        admin: { type: string }
        rep: { type: string }
        client: { type: string }
        tenant: { type: string }
    MissionSetFields:
      type: object
      properties:
        name: { type: string }
        description: { type: string }
        missions:
          type: array
          minItems: 1
          items: { type: string }
          description: "Mission ids in this set (required, ≥ 1 valid id)."
        enabled: { type: boolean, default: true }
    MissionSetCreateBody:
      allOf:
        - $ref: "#/components/schemas/MissionSetFields"
        - type: object
          required: [name, missions]
          properties:
            company_namespace:
              type: array
              items: { type: string }
              description: Optional tenant namespace override for SDK callers.
    MissionSetUpdateBody:
      allOf:
        - $ref: "#/components/schemas/MissionSetFields"
        - type: object
          required: [missions]
          properties:
            disabled:
              type: boolean
              description: Soft-delete flag.
    MissionSet:
      allOf:
        - $ref: "#/components/schemas/MissionSetFields"
        - type: object
          properties:
            _id: { type: string }
            disabled: { type: boolean }
            creator:
              $ref: "#/components/schemas/UserStamp"
            editor:
              $ref: "#/components/schemas/UserStamp"
            company_namespace:
              type: array
              items: { type: string }
            createdAt: { type: string, format: date-time }
            updatedAt: { type: string, format: date-time }
    MissionSetFindResult:
      type: object
      description: Standard paginated result envelope.
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/MissionSet"
        total_result: { type: number }
        current_count: { type: number }
        total_pages: { type: number }
        current_page: { type: number }
        per_page: { type: number }
        first_page_url: { type: string }
        last_page_url: { type: string }
        next_page_url: { type: string, nullable: true }
        prev_page_url: { type: string, nullable: true }
        path: { type: string }
