---
openapi: 3.1.0
components:
  schemas:
    ApiDocs:
      type: object
      properties:
        entity:
          type: string
        spec:
          type: string
        admin:
          type: string
    AtomicLong:
      type: object
      properties:
        value:
          type: integer
          format: int64
        andIncrement:
          type: integer
          format: int64
        andDecrement:
          type: integer
          format: int64
        plain:
          type: integer
          format: int64
        opaque:
          type: integer
          format: int64
        acquire:
          type: integer
          format: int64
        release:
          type: integer
          format: int64
    Charset:
      type: object
      properties:
        name:
          type: string
        aliases:
          type: array
          items:
            type: string
        aliasSet:
          type: array
          uniqueItems: true
          items:
            type: string
        registered:
          type: boolean
    EngineImpl:
      type: object
      properties:
        sectionHelperFactories:
          type: object
          additionalProperties:
            type: object
            properties:
              defaultAliases:
                type: array
                items:
                  type: string
              parameters:
                $ref: "#/components/schemas/ParametersInfo"
              blockLabels:
                type: array
                items:
                  type: string
        sectionHelperFunc:
          $ref: "#/components/schemas/FunctionStringSectionHelperFactoryObject"
        valueResolvers:
          type: array
          items:
            $ref: "#/components/schemas/ValueResolver"
        namespaceResolvers:
          type: array
          items:
            $ref: "#/components/schemas/NamespaceResolver"
        evaluator:
          $ref: "#/components/schemas/Evaluator"
        templates:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/Template"
        locators:
          type: array
          items:
            $ref: "#/components/schemas/TemplateLocator"
        resultMappers:
          type: array
          items:
            $ref: "#/components/schemas/ResultMapper"
        idGenerator:
          $ref: "#/components/schemas/AtomicLong"
        parserHooks:
          type: array
          items:
            $ref: "#/components/schemas/ParserHook"
        initializers:
          type: array
          items:
            $ref: "#/components/schemas/Initializer"
        removeStandaloneLines:
          type: boolean
        timeout:
          type: integer
          format: int64
        useAsyncTimeout:
          type: boolean
        traceManager:
          $ref: "#/components/schemas/TraceManagerImpl"
        parserConfigurator:
          $ref: "#/components/schemas/ParserConfigurator"
        templateInstanceInitializers:
          type: array
          items:
            $ref: "#/components/schemas/Initializer"
    Entity:
      type: object
      properties:
        resource:
          type: string
        entityApiPath:
          type: string
        identifier:
          type: string
        keyFields:
          type: array
          items:
            type: string
        fields:
          type: array
          items:
            $ref: "#/components/schemas/Field"
    Evaluator:
      type: object
    Expression:
      type: object
      properties:
        namespace:
          type: string
        parts:
          type: array
          items:
            $ref: "#/components/schemas/Part"
        literal:
          type: boolean
        literalValue: {}
        origin:
          $ref: "#/components/schemas/Origin"
        generatedId:
          type: integer
          format: int32
    Field:
      type: object
      properties:
        name:
          type: string
        type:
          type: string
        required:
          type: boolean
        allowedValues:
          type: array
          items:
            type: string
    FunctionStringSectionHelperFactoryObject:
      type: object
    Initializer:
      type: object
    Links:
      type: object
      properties:
        contractYaml:
          type: string
        contractJson:
          type: string
        productYaml:
          type: string
        productJson:
          type: string
        entityApi:
          type: string
        swaggerUi:
          type: string
        openapi:
          type: string
        apiDocs:
          $ref: "#/components/schemas/ApiDocs"
        health:
          type: string
    Locale:
      type: object
      properties:
        language:
          type: string
        script:
          type: string
        country:
          type: string
        variant:
          type: string
        extensionKeys:
          type: array
          uniqueItems: true
          items:
            type: string
            format: char
        unicodeLocaleAttributes:
          type: array
          uniqueItems: true
          items:
            type: string
        unicodeLocaleKeys:
          type: array
          uniqueItems: true
          items:
            type: string
        ISO3Language:
          type: string
        ISO3Country:
          type: string
        displayLanguage:
          type: string
        displayScript:
          type: string
        displayCountry:
          type: string
        displayVariant:
          type: string
        displayName:
          type: string
    NamespaceResolver:
      type: object
      properties:
        priority:
          type: integer
          format: int32
        namespace:
          type: string
    Origin:
      type: object
      properties:
        line:
          type: integer
          format: int32
        lineCharacterStart:
          type: integer
          format: int32
        lineCharacterEnd:
          type: integer
          format: int32
        templateId:
          type: string
        templateGeneratedId:
          type: string
        variant:
          anyOf:
          - $ref: "#/components/schemas/Variant"
          - type: "null"
        sourceUri:
          type:
          - string
          - "null"
          format: uri
        synthetic:
          type: boolean
    Parameter:
      type: object
      properties:
        name:
          type: string
        defaultValue:
          type: string
        optional:
          type: boolean
        valuePredicate:
          $ref: "#/components/schemas/PredicateString"
    ParameterDeclaration:
      type: object
      properties:
        typeInfo:
          type: string
        key:
          type: string
        defaultValue:
          $ref: "#/components/schemas/Expression"
        origin:
          $ref: "#/components/schemas/Origin"
    ParametersInfo:
      type: array
      items:
        type: array
        items:
          $ref: "#/components/schemas/Parameter"
    ParserConfigurator:
      type: object
    ParserHook:
      type: object
    Part:
      type: object
      properties:
        name:
          type: string
        typeInfo:
          type: string
        virtualMethod:
          type: boolean
    PredicateString:
      type: object
    ProblemDetails:
      description: Fehlerobjekt nach RFC 9457 (application/problem+json). Bei Validierungsfehlern
        (400/422) trägt das Feld violations die Einzelverstöße.
      type: object
      properties:
        type:
          type: string
          description: Kategorie-URI des Fehlertyps (RFC 9457); "about:blank" wenn
            nicht kategorisiert. Feature-spezifische URIs werden feature-seitig dokumentiert.
          examples:
          - about:blank
        title:
          type: string
          description: "Kurzer, menschenlesbarer Titel des Fehlers."
          examples:
          - Validierung fehlgeschlagen
        status:
          type: integer
          format: int32
          description: HTTP-Statuscode des Fehlers.
          examples:
          - 422
        detail:
          type: string
          description: Erläuterung dieses konkreten Vorkommens.
          examples:
          - Der Datensatz verletzt im Contract deklarierte Regeln
        violations:
          type: array
          items:
            type: object
            additionalProperties:
              type: string
          description: "Einzelverstöße. Entity-Schemafehler tragen den Schlüssel field,\
            \ Fachregel-Verstöße den Schlüssel rule, Dokument-Schemaverstöße (ODCS/ODPS\
            \ gegen JSON-Schema) den Schlüssel path, jeweils mit message."
          examples:
          - - rule: meldepflicht-konsistenz
              message: Bei kategorie=meldepflichtig muss meldepflichtig=true sein
    ResultMapper:
      type: object
      properties:
        priority:
          type: integer
          format: int32
    SectionBlock:
      type: object
      properties:
        origin:
          $ref: "#/components/schemas/Origin"
        id:
          type: string
        label:
          type: string
        parameters:
          type: object
          additionalProperties:
            type: string
        expressions:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/Expression"
        nodes:
          type: array
          items:
            $ref: "#/components/schemas/TemplateNode"
        positionalParameters:
          type: array
          items:
            type: string
        empty:
          type: boolean
        paramDeclarations:
          type: array
          items:
            $ref: "#/components/schemas/ParameterDeclaration"
    SectionHelper:
      type: object
    SectionNode:
      type: object
      properties:
        constant:
          type: boolean
        section:
          type: boolean
        text:
          type: boolean
        expression:
          type: boolean
        name:
          type: string
        blocks:
          type: array
          items:
            $ref: "#/components/schemas/SectionBlock"
        helper:
          $ref: "#/components/schemas/SectionHelper"
        origin:
          $ref: "#/components/schemas/Origin"
        traceLevel:
          type: boolean
        engine:
          $ref: "#/components/schemas/EngineImpl"
        expressions:
          type: array
          items:
            $ref: "#/components/schemas/Expression"
        parameterDeclarations:
          type: array
          items:
            $ref: "#/components/schemas/ParameterDeclaration"
    ServiceIndex:
      type: object
      properties:
        service:
          type: string
        title:
          type: string
        version:
          type: string
        entity:
          $ref: "#/components/schemas/Entity"
        links:
          $ref: "#/components/schemas/Links"
    Template:
      type: object
      properties:
        expressions:
          type: array
          items:
            $ref: "#/components/schemas/Expression"
        generatedId:
          type: string
        id:
          type: string
        variant:
          anyOf:
          - $ref: "#/components/schemas/Variant"
          - type: "null"
        parameterDeclarations:
          type: array
          items:
            $ref: "#/components/schemas/ParameterDeclaration"
        fragmentIds:
          type: array
          uniqueItems: true
          items:
            type: string
        fragment:
          type: boolean
        nodes:
          type: array
          items:
            $ref: "#/components/schemas/TemplateNode"
        rootNode:
          $ref: "#/components/schemas/SectionNode"
        source:
          type:
          - string
          - "null"
          format: uri
    TemplateInstance:
      type: object
      properties:
        timeout:
          type: integer
          format: int64
        template:
          $ref: "#/components/schemas/Template"
    TemplateLocator:
      type: object
      properties:
        priority:
          type: integer
          format: int32
    TemplateNode:
      type: object
      properties:
        expressions:
          type: array
          items:
            $ref: "#/components/schemas/Expression"
        parameterDeclarations:
          type: array
          items:
            $ref: "#/components/schemas/ParameterDeclaration"
        origin:
          $ref: "#/components/schemas/Origin"
        constant:
          type: boolean
        section:
          type: boolean
        text:
          type: boolean
        expression:
          type: boolean
    TraceListener:
      type: object
    TraceManagerImpl:
      type: object
      properties:
        listeners:
          type: array
          items:
            $ref: "#/components/schemas/TraceListener"
    ValueResolver:
      type: object
      properties:
        priority:
          type: integer
          format: int32
        supportedProperties:
          type: array
          uniqueItems: true
          items:
            type: string
        supportedMethods:
          type: array
          uniqueItems: true
          items:
            type: string
    Variant:
      type: object
      properties:
        locale:
          $ref: "#/components/schemas/Locale"
        contentType:
          type: string
        encoding:
          $ref: "#/components/schemas/Charset"
        hashCode:
          type: integer
          format: int32
        mediaType:
          type: string
        charset:
          $ref: "#/components/schemas/Charset"
  securitySchemes:
    SecurityScheme:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Authentication
tags:
- name: Admin API
  description: "Betriebsendpunkte: Voll-Export und Bulk-Import der Datensätze (implementiert),\
    \ sowie Re-Validierung, Purge, Reconciliation, Merge, Issues und Audit (im Walking\
    \ Skeleton als 501-Stub). Import prüft pro Satz die Contract-Regeln."
- name: Entity API
  description: "Lesen und Schreiben der Fachdatensätze. Repräsentation als JSON:API\
    \ (Default) oder Flat-JSON (Accept: application/json). Struktur und Validierung\
    \ kommen generisch aus dem ODCS-Contract; Schreibzugriffe prüfen Schema und Fachregeln\
    \ (parsebar, aber regelwidrig → 422). Schreiben ist append-only versioniert."
- name: OpenAPI (intern)
- name: Service-Index
  description: "Einstiegsseite des Datendienstes: Entity-Typ, Contract/Product-Links,\
    \ API-Doku."
- name: Specification API – Data Contracts (ODCS)
  description: "Lesezugriff auf den Data Contract (Open Data Contract Standard, ODCS).\
    \ Antwort als JSON (Default) oder YAML (Accept: application/x-yaml). Schreibende\
    \ Endpunkte (anlegen, neue Version, fork, rebase, deaktivieren) sind im Walking\
    \ Skeleton 501-Stubs."
- name: Specification API – Data Products (ODPS)
  description: "Lesezugriff auf das Data Product (Open Data Product Standard, ODPS)\
    \ mit seinen Output-Ports und Contract-Referenzen. Antwort als JSON (Default)\
    \ oder YAML (Accept: application/x-yaml). Schreibende Endpunkte sind im Walking\
    \ Skeleton 501-Stubs."
paths:
  /:
    get:
      summary: Service-Index (HTML)
      description: Menschlesbare Info-Seite des Datendienstes.
      tags:
      - Service-Index
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ServiceIndex"
            text/html:
              schema:
                $ref: "#/components/schemas/TemplateInstance"
  /admin/audit/export:
    get:
      summary: Audit-Log-Export (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      responses:
        "501":
          description: Nicht implementiert.
  /admin/entities/merge:
    post:
      summary: Entity-Merge (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      responses:
        "501":
          description: Nicht implementiert.
  /admin/entities/{boid}:
    delete:
      summary: Anlassbezogene Löschung (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      parameters:
      - name: boid
        in: path
        required: true
        schema:
          type: string
      responses:
        "501":
          description: Nicht implementiert.
  /admin/export:
    get:
      summary: Vollständiger Export der Datensätze
      description: "Liefert alle Datensätze als {records:[…]}; jeder Satz ist ein\
        \ Export-Envelope (boid/version/status/erstelltAm/createdAt/data). createdAt\
        \ trägt die stabile Erstanlage, damit ein Restore meta.created erhält. Mit\
        \ includeHistory=true auch abgelöste Versionen. Das Ergebnis-Array eignet\
        \ sich direkt als Body für POST /admin/import."
      tags:
      - Admin API
      parameters:
      - description: Auch abgelöste (superseded) Versionen exportieren
        name: includeHistory
        in: query
        schema:
          type: boolean
          default: false
      responses:
        "200":
          description: "Export-Dokument {records:[…]}."
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
  /admin/import:
    post:
      summary: Import von Datensätzen (bare JSON-Array; Verstöße pro Satz nach RFC
        9457 begründet)
      description: "Importiert ein nacktes Array von Export-Envelopes. Pflichtfelder\
        \ je Satz: boid, version, status, erstelltAm, data; optional createdAt (stabile\
        \ Erstanlage — fehlt es, wird erstelltAm verwendet, Alt-Export-Kompatibilitä\
        t). Jeder Satz wird gegen Envelope-Struktur, das aktuelle Schema und die Contract-Regeln\
        \ geprüft. **Partielle Annahme (#83):** gültige Sätze werden importiert, verworfene\
        \ tragen pro Satz eine RFC-9457-Begründung (status 400 = ungültiger Envelope,\
        \ 422 = Schema-/Fachregel-Verstoß) mit violations[] und 0-basiertem index.\
        \ Antwort: {imported, rejected:[{index, status, title, violations}]}. Ein\
        \ malformter Request-Body (kein JSON-Array) liefert 400 problem+json. **Modus\
        \ (#86):** mode=validate (Default) prüft Schema + Regeln; mode=restore umgeht\
        \ die inhaltliche Validierung (nur Envelope-Strukturprüfung) für verbatim-Restore\
        \ (Exit-Strategie / Disaster-Recovery, damit ein alter Export auch nach Contract-Verschä\
        rfung zurückspielbar bleibt). AuthZ: Import ist maintain-pflichtig (@RequiresAccess\
        \ MAINTAIN, beide Modi); eine spätere Verschärfung von mode=restore auf die\
        \ admin-Stufe ist ein möglicher Folgeschritt. Hinweis: boid wird wie geliefert\
        \ gespeichert (keine Neuberechnung)."
      tags:
      - Admin API
      parameters:
      - description: "Import-Modus: validate (Default, prüft Schema + Regeln) oder\
          \ restore (verbatim, nur Envelope-Struktur)."
        schema:
          default: validate
          enum:
          - validate
          - restore
        name: mode
        in: query
      requestBody:
        description: Array von Export-Envelopes.
        content:
          application/json:
            examples:
              import:
                value:
                - boid: 11111111-1111-1111-1111-111111111111
                  version: 1
                  status: active
                  erstelltAm: 2026-05-28T10:00:00Z
                  createdAt: 2026-05-28T10:00:00Z
                  data:
                    bezeichnung: Tollwut
                    kategorie: meldepflichtig
                    meldepflichtig: true
                    erfasstAm: 2026-05-28T10:00:00
            schema:
              type: array
              items:
                type: object
                additionalProperties: {}
        required: true
      responses:
        "200":
          description: "Import-Ergebnis {imported, rejected:[{index, status, title,\
            \ violations}]}. Verworfene Sätze (ungültiger Envelope 400, Schema-/Fachregel-Verstoß\
            \ 422) stehen mit Begründung in rejected[]."
          content:
            application/json:
              schema: {}
        "400":
          description: Request-Body ist kein wohlgeformtes JSON-Array oder mode ist
            unbekannt.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
  /admin/integrations/export:
    get:
      summary: Integrations-Export (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      responses:
        "501":
          description: Nicht implementiert.
  /admin/issues:
    get:
      summary: Offene Notification-Issues (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      responses:
        "501":
          description: Nicht implementiert.
  /admin/issues/{id}:
    get:
      summary: Einzel-Issue (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "501":
          description: Nicht implementiert.
  /admin/issues/{id}/acknowledge:
    post:
      summary: Issue bestätigen (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "501":
          description: Nicht implementiert.
  /admin/mandanten/{mandantId}:
    delete:
      summary: Mandanten-Schema vernichten (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      parameters:
      - name: mandantId
        in: path
        required: true
        schema:
          type: string
      responses:
        "501":
          description: Nicht implementiert.
  /admin/purge:
    post:
      summary: Purge-Job (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      responses:
        "501":
          description: Nicht implementiert.
  /admin/purge/{jobId}:
    get:
      summary: Purge-Status (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      parameters:
      - name: jobId
        in: path
        required: true
        schema:
          type: string
      responses:
        "501":
          description: Nicht implementiert.
  /admin/reconcile:
    post:
      summary: Reconciliation-Job (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      responses:
        "501":
          description: Nicht implementiert.
  /admin/reconcile/{jobId}:
    get:
      summary: Reconciliation-Status (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      parameters:
      - name: jobId
        in: path
        required: true
        schema:
          type: string
      responses:
        "501":
          description: Nicht implementiert.
  /admin/revalidate:
    post:
      summary: Re-Validierungs-Job (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      responses:
        "501":
          description: Nicht implementiert.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
  /admin/revalidate/{jobId}:
    get:
      summary: Re-Validierungs-Status (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Admin API
      parameters:
      - name: jobId
        in: path
        required: true
        schema:
          type: string
      responses:
        "501":
          description: Nicht implementiert.
  /api-docs/admin:
    get:
      summary: Admin-API OpenAPI-Spec (gefiltert)
      tags:
      - OpenAPI (intern)
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema: {}
  /api-docs/entity:
    get:
      summary: Entity-API OpenAPI-Spec (gefiltert)
      tags:
      - OpenAPI (intern)
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema: {}
  /api-docs/spec:
    get:
      summary: Specification-API OpenAPI-Spec (gefiltert)
      tags:
      - OpenAPI (intern)
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema: {}
  /contracts:
    get:
      summary: Alle Data Contracts (aktuelle Versionen)
      description: Liefert die aktuellen Data Contracts dieses Dienstes als Liste
        von Registry-Einträgen (Metadaten + verschachteltes ODCS-Dokument). Optional
        filterbar nach dataProductId und status. JSON-Array (Default) oder YAML-Sequenz
        via Accept.
      tags:
      - Specification API – Data Contracts (ODCS)
      parameters:
      - description: Nur Contracts dieses Datenprodukts (Produkt-URN)
        name: dataProductId
        in: query
        schema:
          type: string
      - description: Nur Contracts mit diesem Lifecycle-Status (draft|active|suspended|deprecated|retired)
        name: status
        in: query
        schema:
          type: string
      responses:
        "200":
          description: Registry-Einträge der (gefilterten) aktuellen Data Contracts
            (ODCS).
          content:
            application/json:
              schema: {}
            application/x-yaml: {}
            application/yaml: {}
            '*/*': {}
        "400":
          description: Ungültiger status-Filter (nicht im Status-Kanon).
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
  /contracts/{id}:
    post:
      summary: Neue Contract-Version einspielen
      description: "Ersetzt den Contract dieser Dienst-Instanz zur Laufzeit durch\
        \ das übergebene ODCS-Dokument (YAML oder JSON). Das Dokument wird vollstä\
        ndig validiert (parsebar, ODCS v3.1.0 JSON-Schema (KKS-Profil), Fachschlü\
        ssel-Set vorhanden, quality.rules[] als JMESPath kompilierbar, passende Contract-ID)\
        \ und erst dann atomar aktiv. Schlägt die Validierung fehl, bleibt der bisherige\
        \ Contract unverändert. Bestehende Datensätze werden nicht migriert; ab dem\
        \ Update gelten die neuen Regeln an den Schreibpunkten (POST/PUT/Import).\
        \ Ermöglicht Contract-Evolution ohne Dev-Mode-Hot-Reload (Demo/Cluster)."
      tags:
      - Specification API – Data Contracts (ODCS)
      parameters:
      - description: Contract-URN; muss der instanzgebundenen ID entsprechen
        example: urn:avs:tierseuche:contract
        name: id
        in: path
        required: true
        schema:
          type: string
      requestBody:
        description: Vollständiges ODCS-Contract-Dokument (YAML oder JSON).
        content:
          application/x-yaml:
            schema:
              type: string
        required: true
      responses:
        "200":
          description: Contract übernommen; neuer Registry-Eintrag im Body.
          content:
            application/json:
              schema: {}
            application/x-yaml: {}
            application/yaml: {}
        "400":
          description: "Ungültiges Dokument; ODCS-Schemaverletzung trägt type urn:kks:problem:odcs-schema-violation\
            \ mit violations[].path."
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "404":
          description: Pfad-ID passt nicht zur instanzgebundenen Contract-ID.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "409":
          description: Contract-ID im Dokument weicht von der instanzgebundenen ID
            ab.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
    delete:
      summary: Contract deaktivieren (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Specification API – Data Contracts (ODCS)
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "501":
          description: Nicht implementiert.
    get:
      summary: Einzelner Data Contract nach ID
      description: Liefert den Registry-Eintrag des Data Contracts zur angegebenen
        Contract-URN.
      tags:
      - Specification API – Data Contracts (ODCS)
      parameters:
      - description: Contract-URN
        example: urn:avs:tierseuche:contract
        name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: Registry-Eintrag des Data Contracts (ODCS).
          content:
            application/json:
              schema: {}
            application/x-yaml: {}
            application/yaml: {}
            '*/*': {}
        "404":
          description: Unbekannte Contract-ID.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
  /contracts/{id}/fork:
    post:
      summary: Sekundärkontrakt forken (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Specification API – Data Contracts (ODCS)
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "501":
          description: Nicht implementiert.
  /contracts/{id}/rebase:
    post:
      summary: Sekundärkontrakt rebasen (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Specification API – Data Contracts (ODCS)
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "501":
          description: Nicht implementiert.
  /contracts/{id}/versions:
    get:
      summary: Alle Versionen eines Data Contracts
      description: "Liefert die vollständige Versionshistorie des Contracts als Liste\
        \ (append-only, aufsteigend nach Versionsnummer). JSON-Array (Default) oder\
        \ YAML-Sequenz via Accept."
      tags:
      - Specification API – Data Contracts (ODCS)
      parameters:
      - description: Contract-URN
        name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: Contract-Versionen (ODCS) als Liste.
          content:
            application/json:
              schema: {}
            application/x-yaml: {}
            application/yaml: {}
            '*/*': {}
        "404":
          description: Unbekannte Contract-ID.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
  /contracts/{id}/versions/{n}:
    get:
      summary: Data Contract nach ID und Version
      description: "Liefert eine konkrete, historische Contract-Version aus der Registry.\
        \ JSON (Default) oder YAML via Accept-Header."
      tags:
      - Specification API – Data Contracts (ODCS)
      parameters:
      - description: Contract-URN
        name: id
        in: path
        required: true
        schema:
          type: string
      - description: 1-basierte Versionsnummer
        example: 1
        name: "n"
        in: path
        required: true
        schema:
          type: integer
          format: int32
      responses:
        "200":
          description: Registry-Eintrag der angeforderten Contract-Version (ODCS).
          content:
            application/json:
              schema: {}
            application/x-yaml: {}
            application/yaml: {}
            '*/*': {}
        "404":
          description: Unbekannte Contract-ID oder Version.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
  /products:
    get:
      summary: Alle Data Products (aktuelle Versionen)
      description: Liefert die aktuellen Data Products dieses Dienstes als Liste von
        Registry-Einträgen. Optional filterbar nach status. JSON (Default) oder YAML
        via Accept-Header.
      tags:
      - Specification API – Data Products (ODPS)
      parameters:
      - description: Nur Products mit diesem Lifecycle-Status (draft|active|suspended|deprecated|retired)
        name: status
        in: query
        schema:
          type: string
      responses:
        "200":
          description: Registry-Einträge der (gefilterten) aktuellen Data Products
            (ODPS).
          content:
            application/json:
              schema: {}
            application/x-yaml: {}
            application/yaml: {}
            '*/*': {}
        "400":
          description: Ungültiger status-Filter (nicht im Status-Kanon).
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
  /products/versions:
    get:
      summary: Alle Versionen des Data Products
      description: "Liefert die vollständige Versionshistorie des Data Products als\
        \ Liste (append-only, aufsteigend nach Versionsnummer). JSON-Array (Default)\
        \ oder YAML-Sequenz via Accept."
      tags:
      - Specification API – Data Products (ODPS)
      responses:
        "200":
          description: Product-Versionen (ODPS) als Liste.
          content:
            application/json:
              schema: {}
            application/x-yaml: {}
            application/yaml: {}
            '*/*': {}
  /products/versions/{n}:
    get:
      summary: Data Product in bestimmter Version
      description: "Liefert eine konkrete, historische Product-Version aus der Registry.\
        \ JSON (Default) oder YAML via Accept-Header."
      tags:
      - Specification API – Data Products (ODPS)
      parameters:
      - description: 1-basierte Versionsnummer
        example: 1
        name: "n"
        in: path
        required: true
        schema:
          type: integer
          format: int32
      responses:
        "200":
          description: Registry-Eintrag der angeforderten Product-Version (ODPS).
          content:
            application/json:
              schema: {}
            application/x-yaml: {}
            application/yaml: {}
            '*/*': {}
        "404":
          description: Keine solche Product-Version.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
  /products/{id}:
    post:
      summary: Neue Product-Version einspielen
      description: "Erzeugt eine neue Version des Data Products dieser Instanz. Validierung:\
        \ parsebar + passende Product-ID + ODPS v1.0.0 JSON-Schema-Konformität."
      tags:
      - Specification API – Data Products (ODPS)
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              type: string
          application/x-yaml:
            schema:
              type: string
          application/yaml:
            schema:
              type: string
          text/plain:
            schema:
              type: string
        required: true
      responses:
        "200":
          description: Product übernommen; neuer Registry-Eintrag im Body.
          content:
            application/json:
              schema: {}
            application/x-yaml: {}
            application/yaml: {}
        "400":
          description: "Dokument nicht parsebar oder ODPS-Schemaverletzung (violations[]\
            \ mit path/message)."
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "409":
          description: Product-ID (im Pfad oder im Dokument) weicht von der instanzgebundenen
            ID ab.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
    delete:
      summary: Product deaktivieren (Stub)
      description: Im Referenz-Datendienst noch nicht implementiert (Walking-Skeleton-Stub).
      tags:
      - Specification API – Data Products (ODPS)
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "501":
          description: Nicht implementiert.
  /tierseuche:
    get:
      summary: Collection der aktiven Datensätze (filter-/sortier-/paginierbar)
      description: "Liefert die aktiven Datensätze. JSON:API-Dokument ({data:[…],\
        \ meta:{total,page}}) oder Flat-JSON-Array (Accept: application/json). Query:\
        \ filter[feld]([gt|lt|gte|lte]), sort (-=absteigend), page[number]/page[size]\
        \ (max 100), fields[type] (Sparse Fieldsets). Filter-/Sortier-/fields-Felder\
        \ müssen Contract-Felder oder meta.(status|version|created) sein.Hinweis:\
        \ meta.total/page liefert nur die JSON:API-Repräsentation; Flat-JSON ist ein\
        \ reines Array ohne Paginierungs-Metadaten."
      tags:
      - Entity API
      responses:
        "200":
          description: Gefilterte/sortierte/paginierte Liste (JSON:API oder Flat-JSON).
          content:
            application/vnd.api+json: {}
            application/json:
              schema: {}
        "400":
          description: "Ungültiger Query-Parameter (unbekanntes Feld, unzulässiger\
            \ Bereichsoperator)."
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "404":
          description: Unbekannter Contract-Slug.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
    post:
      summary: "Datensatz anlegen (Neuanlage, Version 1)"
      description: "Legt einen neuen Datensatz als Version 1 an. Die BOID wird serverseitig\
        \ deterministisch aus dem Fachschlüssel-Set (primaryKey-Felder) abgeleitet\
        \ — kein boid im Body. Existiert die abgeleitete BOID schon, ist es ein Konflikt\
        \ (409); für eine neue Version PUT auf die BOID nutzen."
      tags:
      - Entity API
      requestBody:
        description: Fachdaten gemäß ODCS-Schema (ohne boid).
        content:
          application/json:
            examples:
              gueltig:
                value:
                  bezeichnung: Schweinepest
                  kategorie: meldepflichtig
                  meldepflichtig: true
                  erfasstAm: 2026-05-28T10:00:00
            schema:
              type: object
              additionalProperties: {}
        required: true
      responses:
        "201":
          description: Datensatz angelegt; Repräsentation der Version 1.
        "409":
          description: Datensatz mit dieser BOID existiert bereits.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "422":
          description: "Schemaverletzung (Pflichtfeld/Typ/Enum) oder Fachregel-Verstoß\
            \ (quality.rules[], JMESPath); Quelle in violations[]: field = Schema,\
            \ rule = Fachregel."
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "400":
          description: Bad Request
  /tierseuche/{id}:
    put:
      summary: "Neue Version eines Datensatzes (Komplettersatz, append-only)"
      description: "Ersetzt den Datensatz vollständig und legt eine neue Version an;\
        \ vorige Versionen bleiben als Historie erhalten (append-only). {id} muss\
        \ eine BOID (UUID) sein. Optimistic Locking: If-Match mit dem aktuellen ETag\
        \ (Version) ist Pflicht — erst GET/HEAD für den ETag, dann PUT. Veraltete\
        \ Version → 412, fehlender Header → 428."
      tags:
      - Entity API
      parameters:
      - description: BOID (UUID) des zu ersetzenden Datensatzes
        name: id
        in: path
        required: true
        schema:
          type: string
      - description: "Aktueller ETag (Version) des Datensatzes, z. B. \"3\". Pflicht:\
          \ erst GET/HEAD für den ETag, dann PUT mit diesem If-Match."
        in: header
        name: If-Match
        required: true
        schema:
          type: string
      requestBody:
        description: Vollständige Fachdaten der neuen Version gemäß ODCS-Schema.
        content:
          application/json:
            examples:
              gueltig:
                value:
                  bezeichnung: Schweinepest
                  kategorie: meldepflichtig
                  meldepflichtig: true
                  erfasstAm: 2026-05-28T10:00:00
            schema:
              type: object
              additionalProperties: {}
        required: true
      responses:
        "200":
          description: Neue Version angelegt; deren Repräsentation.
          content:
            application/vnd.api+json: {}
            application/json:
              schema: {}
        "400":
          description: "Ungültiger If-Match-Header (malformt, schwach oder Wildcard)."
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "404":
          description: Kein Datensatz zu dieser BOID.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "412":
          description: If-Match-Version ist nicht die aktuelle (Optimistic Locking).
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "428":
          description: If-Match-Header fehlt (Vorbedingung erforderlich).
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "422":
          description: "Schemaverletzung (Pflichtfeld/Typ/Enum) oder Fachregel-Verstoß\
            \ (quality.rules[], JMESPath); Quelle in violations[]: field = Schema,\
            \ rule = Fachregel."
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
    head:
      summary: "Existenz-/Aktivitätsprüfung (200 aktiv, 410 abgelöst, 404 unbekannt)\
        \ per BOID-UUID oder Identitäts-URN"
      description: "Prüft ohne Body, ob ein Datensatz existiert und ob er aktiv oder\
        \ bereits abgelöst ist."
      tags:
      - Entity API
      parameters:
      - description: BOID (UUID) oder fachliche Identitäts-URN
        name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: Datensatz existiert und ist aktiv.
          content:
            application/json:
              schema: {}
        "410":
          description: "Datensatz existiert, ist aber abgelöst (superseded)."
        "404":
          description: Kein Datensatz zu dieser BOID/URN bzw. unbekannter Slug.
    get:
      summary: Aktuelle Version eines Datensatzes (per BOID-UUID oder Identitäts-URN)
      description: "Liefert die aktuelle Version eines Datensatzes. Das {id}-Segment\
        \ ist entweder die BOID (UUID) oder eine fachliche Identitäts-URN, die mandantenstrippend\
        \ per UUIDv5 in die BOID umgerechnet wird."
      tags:
      - Entity API
      parameters:
      - description: BOID (UUID) oder fachliche Identitäts-URN
        example: Schweinepest
        name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: Aktuelle Version des Datensatzes.
          content:
            application/vnd.api+json: {}
            application/json:
              schema: {}
        "404":
          description: Kein Datensatz zu dieser BOID/URN bzw. unbekannter Slug.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
  /tierseuche/{id}/versions:
    get:
      summary: Alle Versionen eines Datensatzes
      description: Liefert die vollständige Versionshistorie eines Datensatzes (aktive
        + abgelöste).
      tags:
      - Entity API
      parameters:
      - description: BOID (UUID) des Datensatzes
        name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: Liste aller Versionen.
          content:
            application/vnd.api+json: {}
            application/json:
              schema: {}
        "404":
          description: Kein Datensatz zu dieser BOID.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
  /tierseuche/{id}/versions/{n}:
    get:
      summary: Bestimmte Version eines Datensatzes
      description: Liefert eine konkrete Version eines Datensatzes per 1-basierter
        Versionsnummer.
      tags:
      - Entity API
      parameters:
      - description: BOID (UUID) des Datensatzes
        name: id
        in: path
        required: true
        schema:
          type: string
      - description: 1-basierte Versionsnummer
        example: 1
        name: "n"
        in: path
        required: true
        schema:
          type: integer
          format: int32
      responses:
        "200":
          description: Die angeforderte Version des Datensatzes.
          content:
            application/vnd.api+json: {}
            application/json:
              schema: {}
        "404":
          description: Kein Datensatz zu dieser BOID oder keine solche Version.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
info:
  title: Tierseuche
  version: 1.0.0
  description: "Referenzimplementierung eines DP-Blueprint-Datendienstes. Walking\
    \ Skeleton: implementierter Slice + 501-Stubs."
