# 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: Farm Reconciliation API
  version: 1.0.0
  description: 'One fact per real event, built from the evidence of every feed by versioned rules: resolved events
    and the evidence behind them, animal links, data issues that tell the farm what to fix at the source, and the
    rule sets and source reliability rankings. The system decides; there is no human review step, and this API changes
    nothing but the rules.'
servers:
- url: https://farm.moonitoring.com/reconciliation/v1
  description: Prod
- url: https://stage-farm.moonitoring.com/reconciliation/v1
  description: Stage, through IAP
security:
- bearer: []
tags:
- name: Resolved events
  description: What consumers read
- name: Animal links
  description: Two records, one animal
- name: Data issues
  description: Doubts and conflicts
- name: Rules
  description: Versioned rule sets and reliability
paths:
  /organizations/{organization_id}/resolved-events:
    get:
      summary: List resolved events
      operationId: listResolvedEvents
      description: 'The facts: one per real event, with the status that says how sure the resolution is. Disputed
        facts keep their status; consumers never treat them silently as truth.'
      tags:
      - Resolved events
      parameters:
      - name: organization_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: 'The farm: the token''s active Organization, or a farm that delegated to it.'
      - name: animal
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this animal.
      - name: animal_group
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this group.
      - name: event_type
        in: query
        required: false
        schema:
          type: string
          enum:
          - HerdEntryEvent
          - HerdExitEvent
          - ServiceEvent
          - PregnancyCheckEvent
          - ParturitionEvent
          - AbortionEvent
          - DryOffEvent
          - HeatEvent
          - DiagnosisEvent
          - TreatmentEvent
          - HealthCheckEvent
          - BreedingStatusEvent
          - GroupTreatmentEvent
        description: Only this kind.
      - name: status
        in: query
        required: false
        schema:
          type: string
          enum:
          - corroborated
          - single_source
          - linked_with_doubt
          - conflict_resolved
          - unresolved
          - cancelled
          - retired
        description: Only this status.
      - name: from
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Records whose time is at or after.
      - name: to
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: Records whose time is before.
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      - $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/ResolvedEvent'
                  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: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '45'
      - '1002.11'
      - '1006.23'
  /resolved-events/{resolved_event_id}:
    get:
      summary: Read a resolved event with its evidence
      operationId: getResolvedEvent
      tags:
      - Resolved events
      parameters:
      - name: resolved_event_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResolvedEventView'
        '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: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '45'
      - '46'
  /resolved-events/{resolved_event_id}/revisions:
    get:
      summary: List a resolved event's revisions
      operationId: listResolvedEventRevisions
      tags:
      - Resolved events
      parameters:
      - name: resolved_event_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/ResolvedEvent'
                  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: any
      x-moonitoring-capability:
      - farm.animal_records.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '45.9'
      - '45.11'
      - '45.12'
  /organizations/{organization_id}/animal-links:
    get:
      summary: List animal links
      operationId: listAnimalLinks
      tags:
      - Animal links
      parameters:
      - name: organization_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: 'The farm: the token''s active Organization, or a farm that delegated to it.'
      - name: animal
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Links where this animal is survivor or other.
      - name: status
        in: query
        required: false
        schema:
          type: string
          enum:
          - active
          - reverted
        description: Only this status.
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/AsOfSeq
      - $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/AnimalLink'
                  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: any
      x-moonitoring-capability:
      - farm.animals.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '47'
      - '1002.2'
  /animal-links/{link_id}:
    get:
      summary: Read an animal link
      operationId: getAnimalLink
      tags:
      - Animal links
      parameters:
      - name: link_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AnimalLink'
        '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: any
      x-moonitoring-capability:
      - farm.animals.read
      - farm.canonical_data.read_all
      x-moonitoring-requirements:
      - '47'
  /organizations/{organization_id}/data-issues:
    get:
      summary: List data issues
      operationId: listDataIssues
      tags:
      - Data issues
      parameters:
      - name: organization_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: 'The farm: the token''s active Organization, or a farm that delegated to it.'
      - name: kind
        in: query
        required: false
        schema:
          type: string
          enum:
          - possible_same_event
          - value_conflict
          - impossible_sequence
          - date_disagreement
          - identity_conflict
          - invalid_identifier
          - events_after_exit
          - feed_disagreement_rate
          - submission_outdated
          - profile_conflict
          - ambiguous_local_time
        description: Only this kind.
      - name: severity
        in: query
        required: false
        schema:
          type: string
          enum:
          - high
          - normal
          - low
        description: Only this severity.
      - name: status
        in: query
        required: false
        schema:
          type: string
          enum:
          - open
          - resolved_at_source
          - obsolete
        description: Only this status; default open.
      - name: animal
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only issues about this animal.
      - name: feed
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only issues to fix at this feed.
      - name: sync_run
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only issues detected in this run.
      - $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/DataIssue'
                  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: any
      x-moonitoring-capability:
      - farm.data_issues.read
      - farm.data_issues.read_all
      x-moonitoring-requirements:
      - '48'
      - '1002.21'
      - '1006.22'
  /data-issues:
    get:
      summary: List every data issue
      operationId: listAllDataIssues
      tags:
      - Data issues
      parameters:
      - name: farm
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Only this farm.
      - name: severity
        in: query
        required: false
        schema:
          type: string
          enum:
          - high
          - normal
          - low
        description: Only this severity.
      - name: status
        in: query
        required: false
        schema:
          type: string
          enum:
          - open
          - resolved_at_source
          - obsolete
        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/DataIssue'
                  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: farm.data_issues.read_all
      x-moonitoring-requirements:
      - '48'
      - '1006.22'
  /data-issues/{issue_id}:
    get:
      summary: Read a data issue
      operationId: getDataIssue
      tags:
      - Data issues
      parameters:
      - name: issue_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DataIssue'
        '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: any
      x-moonitoring-capability:
      - farm.data_issues.read
      - farm.data_issues.read_all
      x-moonitoring-requirements:
      - '48'
  /rule-sets:
    get:
      summary: List rule sets
      operationId: listRuleSets
      tags:
      - Rules
      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/ReconciliationRuleSet'
                  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: any
      x-moonitoring-capability: null
      x-moonitoring-requirements:
      - '49'
    post:
      summary: Create a rule set version
      operationId: createRuleSet
      tags:
      - Rules
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReconciliationRuleSetInput'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReconciliationRuleSet'
        '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: farm.reconciliation_rules.manage
      x-moonitoring-requirements:
      - '49'
      - '49.6'
  /rule-sets/{rule_set_id}:
    get:
      summary: Read a rule set
      operationId: getRuleSet
      tags:
      - Rules
      parameters:
      - name: rule_set_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReconciliationRuleSet'
        '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: any
      x-moonitoring-capability: null
      x-moonitoring-requirements:
      - '49'
  /rule-sets/{rule_set_id}/reliability:
    get:
      summary: List a rule set's reliability rankings
      operationId: listSourceReliability
      tags:
      - Rules
      parameters:
      - name: rule_set_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/SourceReliability'
                  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: any
      x-moonitoring-capability: null
      x-moonitoring-requirements:
      - '50'
    post:
      summary: Add a reliability ranking
      operationId: createSourceReliability
      tags:
      - Rules
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      - name: rule_set_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SourceReliabilityInput'
      responses:
        '201':
          description: The result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SourceReliability'
        '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: farm.reconciliation_rules.manage
      x-moonitoring-requirements:
      - '50'
      - '50.5'
  /resolution-runs:
    post:
      summary: Re-run resolution
      operationId: createResolutionRun
      description: Accepted and run in the background under WriteCommits of kind resolution; every call is a PlatformAuditEvent.
      tags:
      - Rules
      parameters:
      - $ref: ../../../../common/v1/schemas.yaml#/components/parameters/IdempotencyKey
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ResolutionRunRequest'
      responses:
        '202':
          description: The result.
          content:
            application/json:
              schema:
                type: object
                description: The request was accepted; the work continues in the background and can be followed
                  by its id.
                properties:
                  id:
                    type: string
                    format: uuid
                    description: The resource or run that was created to follow the work.
                  status:
                    type: string
                required:
                - id
        '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: farm.reconciliation_rules.manage
      x-moonitoring-requirements:
      - '49'
      - '45.9'
      - '47.5'
components:
  schemas:
    ResolvedEvent:
      description: One real fact, supported by one or more canonical events from different feeds. It is what consumers,
        periods and exports read, and its status says whether the sources agree, conflict or leave a doubt.
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        animal:
          type: string
          format: uuid
          description: ID of the Animal.
        animal_group:
          type: string
          format: uuid
          description: ID of the AnimalGroup. Exactly one subject, matching evidence; use the AnimalLink revision
            available at the query cutoff.
        event_type:
          type: string
          description: The CanonicalEvent subtype, e.g. ParturitionEvent.
        occurred:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/EventTime
          description: Taken from the evidence that wins the timing attribute group (`EventEvidence.wins`).
        status:
          type: string
          enum:
          - corroborated
          - single_source
          - linked_with_doubt
          - conflict_resolved
          - unresolved
          - cancelled
          - retired
          description: '`corroborated`: independent origins agree, not merely two delivery feeds. `single_source`:
            only one independent evidence source. `linked_with_doubt`: linked in the grey zone of the rule (e.g.
            calvings 8-30 days apart). `conflict_resolved`: incompatible values (e.g. death vs slaughter), the most
            reliable source won. Both carry a DataIssue. `cancelled`: all its evidence was cancelled at the source.
            `retired`: the resolution was replaced after merge/split/rule correction; its underlying source evidence
            need not be cancelled.'
        date_disagreement_days:
          type: integer
          default: 0
          description: Largest gap between the dates of its evidence.
        rule_set:
          type: string
          format: uuid
          description: ID of the ReconciliationRuleSet.
        issues:
          type: array
          items:
            type: string
            format: uuid
          description: ID of the DataIssue.
        replaced_by:
          type: array
          items:
            type: string
            format: uuid
          description: ID of the ResolvedEvent. Exact replacement revisions for a retired resolution; splitting
            may have several successors. No cycles.
        retirement_reason:
          type: string
          enum:
          - merged
          - split
          - rule_revision
          - invalid_resolution
          description: Required only when retired; a rule re-run may reopen via a new revision. Never reactivate
            the historical row.
        revision:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/RecordRevision
          description: Changed resolutions append revisions; attribute winners identify exact evidence revisions.
            Each required attribute group has one winner or explicit unknown/unresolved value. Corroboration needs
            independent evidence, not the same upstream record delivered through two channels.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - event_type
      - occurred
      - status
      - date_disagreement_days
      - rule_set
      - revision
      - created_at
      - updated_at
    EventEvidence:
      description: Links a canonical event to the resolved event it supports, with its role and the groups of attributes
        whose values it provides. Its revisions rebuild what we believed at any write number.
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        resolved_event:
          type: string
          format: uuid
          description: ID of the ResolvedEvent.
        canonical_event:
          type: string
          format: uuid
          description: ID of the CanonicalEvent.
        role:
          type: string
          enum:
          - primary
          - supporting
          - duplicate
          - conflicting
          description: '`duplicate`: the same record emitted twice by one feed (export artefact).'
        wins:
          type: array
          items:
            type: string
            enum:
            - timing
            - classification
            - genetics
            - clinical
            - quantities
          uniqueItems: true
          description: Attribute groups whose values come from this evidence, chosen by SourceReliability. e.g.
            sire from the breed association, exit type from the most specific compatible source, products from the
            prescription.
        gap_days:
          type: integer
          description: Date gap to the primary evidence.
        revision:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/RecordRevision
          description: 'A link is valid from the write number of its revision until the next one (RecordRevision):
            this rebuilds what we believed at any time.'
        rule_set:
          type: string
          format: uuid
          description: ID of the ReconciliationRuleSet.
        created_at:
          type: string
          format: date-time
      required:
      - id
      - resolved_event
      - canonical_event
      - role
      - wins
      - gap_days
      - revision
      - rule_set
      - created_at
    AnimalLink:
      description: Records that two animal records are the same animal. The only automatic reason is an identical
        identifier after normalization, and incompatible identity evidence blocks the link. A link can be reverted.
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        survivor:
          type: string
          format: uuid
          description: ID of the Animal.
        other:
          type: string
          format: uuid
          description: ID of the Animal.
        reason:
          type: string
          enum:
          - same_normalized_identifier
          description: 'The only automatic merge: identifiers identical after normalization (e.g. IT020990691356
            and 380020990691356). Compatible identities sharing a scheme-qualified identifier reuse/link the known
            Animal. Incompatible identity evidence blocks the link and raises a DataIssue (kind `identity_conflict`):
            different sex, birth dates that differ beyond their precision, different sire or dam identifiers (AnimalProfileEvidence),
            or sessions of both records at the same time on different devices or farms. e.g. Lely Ponte Vecchio:
            one official ID carried by two cows.'
        status:
          type: string
          enum:
          - active
          - reverted
          description: 'Reverted = unmerge, e.g. after a normalization rule changes: the other animal and its evidence
            are restored and resolution is re-run.'
        rule_set:
          type: string
          format: uuid
          description: ID of the ReconciliationRuleSet.
        revision:
          allOf:
          - $ref: ../../../../common/v1/schemas.yaml#/components/schemas/RecordRevision
          description: Keep active/reverted decisions by system time; reversion cannot rewrite historical datasets.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - survivor
      - other
      - reason
      - status
      - rule_set
      - revision
      - created_at
      - updated_at
    DataIssue:
      description: 'A doubt, conflict or blocked publication found by the system, with what the system decided meanwhile
        and where the farm should fix the data. There is no human review step: issues are signals for correcting
        sources.'
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        farm:
          type: string
          format: uuid
          description: ID of the Organization that is a Farm.
        kind:
          type: string
          enum:
          - possible_same_event
          - value_conflict
          - impossible_sequence
          - date_disagreement
          - identity_conflict
          - invalid_identifier
          - events_after_exit
          - feed_disagreement_rate
          - submission_outdated
          - profile_conflict
          - ambiguous_local_time
        severity:
          type: string
          enum:
          - high
          - normal
          - low
          description: '`high`: affects an official export (PRES, ANAG) or a withdrawal; low: date disagreement
            only.'
        status:
          type: string
          enum:
          - open
          - resolved_at_source
          - obsolete
          description: '`obsolete`: the evidence it was about was cancelled at the source.'
        decision:
          type: string
          description: What the system did meanwhile, e.g. "linked the two calvings, kept 2016-08-13 from SiAlleva
            (official registry)".
        fix_at:
          type: array
          items:
            type: string
            format: uuid
          description: ID of the SourceFeed. Where the farm should correct the data.
        resolved_events:
          type: array
          items:
            type: string
            format: uuid
          description: ID of the ResolvedEvent.
        animals:
          type: array
          items:
            type: string
            format: uuid
          description: ID of the Animal.
        rule_set:
          type: string
          format: uuid
          description: ID of the ReconciliationRuleSet.
        detected_in:
          type: string
          format: uuid
          description: ID of the SyncRun.
        closed_in:
          type: string
          format: uuid
          description: ID of the SyncRun.
        observations:
          type: array
          items:
            type: string
            format: uuid
          description: ID of the CanonicalObservation.
        profile_evidence:
          type: array
          items:
            type: string
            format: uuid
          description: ID of the AnimalProfileEvidence. Exact evidence revisions, including conflicts between measurements;
            not only event conflicts.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
      - id
      - farm
      - kind
      - severity
      - status
      - decision
      - rule_set
      - created_at
      - updated_at
    ReconciliationRuleSet:
      description: A versioned set of matching and identifier rules, together with the version of the resolver code
        that applies them. Changing a window or the reliability ranking creates a new version, and resolution is
        re-run from the evidence.
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        version:
          type: string
          description: Unique.
        effective_from:
          type: string
          format: date-time
        event_rules:
          type: string
          description: 'Per event type: window kind (fixed days, or one per calving interval), link days, grey-zone
            days (linked and flagged), incompatible values, documented classification hierarchies and attribute
            groups; dispatch and death are not equivalent. Example windows are draft tolerances pending domain and
            country validation.'
        identifier_rules:
          type: string
          description: Normalization rules for identifiers and the version of the country code list.
        resolver_version:
          type: string
          description: Version of the resolution code that applies these rules. Rules + code + evidence at a write
            number give the same result, so a stored decision can always be checked by re-running it.
        created_at:
          type: string
          format: date-time
      required:
      - id
      - version
      - effective_from
      - event_rules
      - identifier_rules
      - resolver_version
      - created_at
    SourceReliability:
      description: A versioned preference between sources for an event or observation type and an attribute group,
        with optional farm exceptions and tolerances. It decides which source wins when comparable evidence disagrees.
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Key.
        applies_to:
          type: string
          description: An event type, an observation type code, or \* for all.
        attribute_group:
          type: string
          enum:
          - timing
          - classification
          - genetics
          - clinical
          - quantities
          - identity
          - all
          default: all
        ranking:
          type: array
          items:
            type: string
          description: 'Ordered, first = most reliable, e.g. genetics of a service: `official_registry` > `management_software`.'
        farm_exception:
          type: string
          format: uuid
          description: ID of the Organization that is a Farm. Only for an explicit exception, e.g. a management
            software that a farm does not keep up to date.
        time_tolerance_seconds:
          type: integer
          description: Candidate-search tolerance only; temporal proximity does not establish duplicate measurement
            identity.
        value_tolerance:
          type: number
          description: 'Observations only: beyond it the disagreement is counted for the feed.'
        rule_set:
          type: string
          format: uuid
          description: ID of the ReconciliationRuleSet.
        created_at:
          type: string
          format: date-time
      required:
      - id
      - applies_to
      - attribute_group
      - ranking
      - rule_set
      - created_at
    ResolvedEventView:
      type: object
      description: A resolved event with its evidence links.
      properties:
        resolved_event:
          $ref: '#/components/schemas/ResolvedEvent'
        evidence:
          type: array
          items:
            $ref: '#/components/schemas/EventEvidence'
      required:
      - resolved_event
      - evidence
    ReconciliationRuleSetInput:
      type: object
      description: A new rule set version. Before it is used, a sample of its automatic links is checked offline.
      properties:
        version:
          type: string
          description: Unique.
        effective_from:
          type: string
          format: date-time
        event_rules:
          type: string
          description: 'Per event type: window kind (fixed days, or one per calving interval), link days, grey-zone
            days (linked and flagged), incompatible values, documented classification hierarchies and attribute
            groups; dispatch and death are not equivalent. Example windows are draft tolerances pending domain and
            country validation.'
        identifier_rules:
          type: string
          description: Normalization rules for identifiers and the version of the country code list.
        resolver_version:
          type: string
          description: Version of the resolution code that applies these rules. Rules + code + evidence at a write
            number give the same result, so a stored decision can always be checked by re-running it.
      required:
      - version
      - effective_from
      - event_rules
      - identifier_rules
      - resolver_version
      additionalProperties: false
    SourceReliabilityInput:
      type: object
      description: Input to create or change a SourceReliability; server-managed fields are left out.
      properties:
        applies_to:
          type: string
          description: An event type, an observation type code, or \* for all.
        attribute_group:
          type: string
          enum:
          - timing
          - classification
          - genetics
          - clinical
          - quantities
          - identity
          - all
          default: all
        ranking:
          type: array
          items:
            type: string
          description: 'Ordered, first = most reliable, e.g. genetics of a service: `official_registry` > `management_software`.'
        farm_exception:
          type: string
          format: uuid
          description: ID of the Organization that is a Farm. Only for an explicit exception, e.g. a management
            software that a farm does not keep up to date.
        time_tolerance_seconds:
          type: integer
          description: Candidate-search tolerance only; temporal proximity does not establish duplicate measurement
            identity.
        value_tolerance:
          type: number
          description: 'Observations only: beyond it the disagreement is counted for the feed.'
      required:
      - applies_to
      - attribute_group
      - ranking
      additionalProperties: false
    ResolutionRunRequest:
      type: object
      description: Re-runs resolution from the evidence with a rule set, for one farm or for every farm. Changed
        resolutions append revisions; periods are recomputed.
      properties:
        rule_set:
          type: string
          format: uuid
        farm:
          type: string
          format: uuid
          description: 'Empty: every farm.'
      required:
      - rule_set
  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.'
