asyncapi: 3.0.0
info:
  title: Freedome cloud — socket.io /v1
  version: 1.0.0
  description: >
    Connect to `https://freedome.nativemind.us/api/socket.io/` (Engine.IO v4 /
    socket.io v5), namespace **`/v1`**,

    `auth: { token }` = access JWT or API key. The server joins the socket to
    `user:{userId}` and to `org:{orgId}` for

    every membership; installations (`fdi_` keys) join `installation:{id}`.
    `join` asks for additional rooms the

    principal may read (ack `(err, {rooms})`). Server events are the common
    envelope with `topic` cloud/{orgId}/… or

    user/{userId}/… and kinds catalogue.item.published,
    catalogue.version.available, sync.changed, licence.updated,

    installation.status, notification.created, agent.message.delta. **Outline**
    — payload detail in 6.CT.2.
  license:
    name: NativeMindNONC
    url: https://freedome.nativemind.us/license
defaultContentType: application/json
servers:
  cloud:
    host: freedome.nativemind.us
    protocol: wss
    pathname: /api/socket.io/
    description: Public cloud host (Cloudflare Tunnel).
    security:
      - type: httpApiKey
        name: token
        in: query
        description: >-
          Sent as `auth: { token }` in the socket.io CONNECT packet: access JWT
          or `fdk_` / `fdi_` API key.
channels:
  v1:
    address: /v1
    title: socket.io namespace /v1
    servers:
      - $ref: '#/servers/cloud'
    messages:
      join:
        name: join
        title: join (C→S, ack)
        payload:
          type: object
          required:
            - rooms
          properties:
            rooms:
              type: array
              minItems: 1
              items:
                type: string
                pattern: ^(user|org|installation):[0-9a-f-]{36}$
          additionalProperties: false
        examples:
          - name: installation
            payload:
              rooms:
                - installation:0192f3a4-5b6c-7d8e-9f01-23456789c005
      event:
        name: event
        title: event (S→C)
        payload:
          description: >-
            Cloud realtime event (socket.io /v1 on /api/socket.io/, GraphQL
            subscriptions): the common envelope with `topic` = cloud/{orgId}/…
            or user/{userId}/…
          type: object
          allOf:
            - $schema: https://json-schema.org/draft/2020-12/schema
              $id: >-
                https://freedome.nativemind.us/schemas/common/1.0/envelope.schema.json
              $comment: >-
                NativeMindNONC — freedome_contract (see LICENSE). Message
                envelope for plain WS (sub-protocol freedome.v1), socket.io
                `event` payload, GraphQL Event and OSC JSON events, 02e §7.1 /
                §8.1. `type`, `id`, `ts`, `data` on every message; `topic` on
                events; `replyTo` on result / error replies. Message types are
                open (readers ignore unknown ones).
              title: Message envelope
              type: object
              required:
                - type
                - id
                - ts
                - data
              properties:
                type:
                  description: >-
                    Known: hello, welcome, subscribe, unsubscribe, call, result,
                    event, error, resync, ping, pong, bye.
                  type: string
                  pattern: ^[a-z][a-zA-Z0-9]*$
                id:
                  description: Unique per message; the idempotency key of `call`.
                  type: string
                  pattern: >-
                    ^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                  examples:
                    - 0192f3a4-5b6c-7d8e-9f01-23456789abcd
                ts:
                  description: >-
                    RFC 3339 UTC with milliseconds, e.g.
                    2026-10-19T12:00:00.000Z.
                  type: string
                  format: date-time
                  pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$
                topic:
                  description: >-
                    Concrete event topic (02e §7.2), e.g.
                    venues/default/players/main.
                  type: string
                  maxLength: 512
                  pattern: ^[A-Za-z0-9._@-]+(/[A-Za-z0-9._@-]+)*$
                replyTo:
                  description: >-
                    Server-owned resource id: UUIDv7, lowercase, sortable by
                    creation time.
                  type: string
                  pattern: >-
                    ^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                  examples:
                    - 0192f3a4-5b6c-7d8e-9f01-23456789abcd
                data: {}
              allOf:
                - if:
                    properties:
                      type:
                        const: event
                    required:
                      - type
                  then:
                    required:
                      - topic
                    properties:
                      data:
                        type: object
                        required:
                          - seq
                          - kind
                        properties:
                          seq:
                            type: integer
                            minimum: 0
                            description: >-
                              Per-server monotonically increasing sequence
                              (resume with sinceSeq).
                          kind:
                            type: string
                            pattern: ^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)+$
                            description: >-
                              Event kind from events/topics.yaml, e.g.
                              player.state.
                          resource:
                            description: Full new representation.
                          patch:
                            type: object
                            description: JSON merge patch (high-rate kinds).
                          revision:
                            description: >-
                              Monotonic resource revision; the strong ETag is
                              derived from it.
                            type: integer
                            minimum: 0
                        not:
                          required:
                            - resource
                            - patch
                        additionalProperties: true
                - if:
                    properties:
                      type:
                        const: result
                    required:
                      - type
                  then:
                    required:
                      - replyTo
                - if:
                    properties:
                      type:
                        const: error
                    required:
                      - type
                  then:
                    properties:
                      data:
                        $schema: https://json-schema.org/draft/2020-12/schema
                        $id: >-
                          https://freedome.nativemind.us/schemas/common/1.0/problem.schema.json
                        $comment: >-
                          NativeMindNONC — freedome_contract (see LICENSE). RFC
                          9457 problem details with the Freedome `code`
                          catalogue, 02e §3.3. Also the `data` of WS `error`,
                          the socket.io ack error and GraphQL
                          errors[].extensions.problem. The catalogue is open:
                          unknown codes are allowed; known codes are bound to
                          their HTTP status.
                        title: Problem details
                        type: object
                        required:
                          - type
                          - title
                          - code
                        properties:
                          type:
                            type: string
                            format: uri
                            description: >-
                              https://freedome.nativemind.us/problems/<code> for
                              catalogue codes.
                          title:
                            type: string
                            minLength: 1
                          status:
                            type: integer
                            minimum: 100
                            maximum: 599
                          detail:
                            type: string
                          instance:
                            type: string
                            format: uri-reference
                          code:
                            description: >-
                              Stable machine key; also the last path segment of
                              `type`. Open set: see knownCode.
                            type: string
                            pattern: ^[a-z][a-z0-9]*(-[a-z0-9]+)*$
                          traceId:
                            type: string
                            pattern: ^[0-9a-f]{16,32}$
                          errors:
                            type: array
                            items:
                              type: object
                              required:
                                - pointer
                                - detail
                              properties:
                                pointer:
                                  type: string
                                  format: json-pointer
                                detail:
                                  type: string
                                code:
                                  description: >-
                                    Stable machine key; also the last path
                                    segment of `type`. Open set: see knownCode.
                                  type: string
                                  pattern: ^[a-z][a-z0-9]*(-[a-z0-9]+)*$
                              additionalProperties: true
                        allOf:
                          - if:
                              properties:
                                code:
                                  const: validation-failed
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 422
                          - if:
                              properties:
                                code:
                                  const: not-found
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 404
                          - if:
                              properties:
                                code:
                                  const: conflict
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 409
                          - if:
                              properties:
                                code:
                                  const: precondition-failed
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 412
                          - if:
                              properties:
                                code:
                                  const: precondition-required
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 428
                          - if:
                              properties:
                                code:
                                  const: unauthenticated
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 401
                          - if:
                              properties:
                                code:
                                  const: forbidden
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 403
                          - if:
                              properties:
                                code:
                                  const: rate-limited
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 429
                          - if:
                              properties:
                                code:
                                  const: payload-too-large
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 413
                          - if:
                              properties:
                                code:
                                  const: unsupported-format
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 415
                          - if:
                              properties:
                                code:
                                  const: engine-unavailable
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 503
                          - if:
                              properties:
                                code:
                                  const: engine-incompatible
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 503
                          - if:
                              properties:
                                code:
                                  const: degraded
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 503
                          - if:
                              properties:
                                code:
                                  const: upload-checksum-mismatch
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 422
                          - if:
                              properties:
                                code:
                                  const: legacy-unsupported
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 501
                          - if:
                              properties:
                                code:
                                  const: internal
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 500
                          - if:
                              properties:
                                code:
                                  const: clock-unlocked
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 409
                          - if:
                              properties:
                                code:
                                  const: not-configured
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 503
                          - if:
                              properties:
                                code:
                                  const: authorization-pending
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 400
                          - if:
                              properties:
                                code:
                                  const: slow-down
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 400
                          - if:
                              properties:
                                code:
                                  const: access-denied
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 403
                          - if:
                              properties:
                                code:
                                  const: expired-token
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 400
                          - if:
                              properties:
                                code:
                                  const: token-reused
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 401
                          - if:
                              properties:
                                code:
                                  const: idempotency-key-reused
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 409
                          - if:
                              properties:
                                code:
                                  const: idempotency-in-progress
                              required:
                                - code
                            then:
                              properties:
                                status:
                                  const: 409
                        additionalProperties: true
                        examples:
                          - type: >-
                              https://freedome.nativemind.us/problems/engine-unavailable
                            title: Visual engine unavailable
                            status: 503
                            detail: >-
                              freedome-engined not reachable at
                              unix:/run/freedome/engine.sock
                            instance: /api/v1/venues/default/players/main/play
                            code: engine-unavailable
                            traceId: 4bf92f3577b34da6a3ce929d0e0e4736
                        $defs:
                          knownCode:
                            enum:
                              - validation-failed
                              - not-found
                              - conflict
                              - precondition-failed
                              - precondition-required
                              - unauthenticated
                              - forbidden
                              - rate-limited
                              - payload-too-large
                              - unsupported-format
                              - engine-unavailable
                              - engine-incompatible
                              - degraded
                              - job-failed
                              - upload-checksum-mismatch
                              - legacy-unsupported
                              - internal
                              - clock-unlocked
                              - not-configured
                              - authorization-pending
                              - slow-down
                              - access-denied
                              - expired-token
                              - token-reused
                              - idempotency-key-reused
                              - idempotency-in-progress
                          code:
                            description: >-
                              Stable machine key; also the last path segment of
                              `type`. Open set: see knownCode.
                            type: string
                            pattern: ^[a-z][a-z0-9]*(-[a-z0-9]+)*$
                          fieldError:
                            type: object
                            required:
                              - pointer
                              - detail
                            properties:
                              pointer:
                                type: string
                                format: json-pointer
                              detail:
                                type: string
                              code:
                                description: >-
                                  Stable machine key; also the last path segment
                                  of `type`. Open set: see knownCode.
                                type: string
                                pattern: ^[a-z][a-z0-9]*(-[a-z0-9]+)*$
                            additionalProperties: true
                - if:
                    properties:
                      type:
                        const: call
                    required:
                      - type
                  then:
                    properties:
                      data:
                        type: object
                        required:
                          - op
                        properties:
                          op:
                            description: >-
                              OpenAPI operationId (camelCase); also the `op` of
                              WS / socket.io `call`.
                            type: string
                            pattern: ^[a-z][a-zA-Z0-9]*$
                          params:
                            type: object
                          body: {}
                          ifMatch:
                            type: string
                        additionalProperties: true
              additionalProperties: true
              examples:
                - type: event
                  id: 0192f3a4-5b6c-7d8e-9f01-23456789abcd
                  ts: '2026-10-19T12:00:00.123Z'
                  topic: venues/default/players/main
                  data:
                    seq: 48213
                    kind: player.state
                    resource:
                      status: playing
                      position: 12.5
              $defs:
                knownType:
                  enum:
                    - hello
                    - welcome
                    - subscribe
                    - unsubscribe
                    - call
                    - result
                    - event
                    - error
                    - resync
                    - ping
                    - pong
                    - bye
                eventData:
                  type: object
                  required:
                    - seq
                    - kind
                  properties:
                    seq:
                      type: integer
                      minimum: 0
                      description: >-
                        Per-server monotonically increasing sequence (resume
                        with sinceSeq).
                    kind:
                      type: string
                      pattern: ^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)+$
                      description: Event kind from events/topics.yaml, e.g. player.state.
                    resource:
                      description: Full new representation.
                    patch:
                      type: object
                      description: JSON merge patch (high-rate kinds).
                    revision:
                      description: >-
                        Monotonic resource revision; the strong ETag is derived
                        from it.
                      type: integer
                      minimum: 0
                  not:
                    required:
                      - resource
                      - patch
                  additionalProperties: true
                callData:
                  type: object
                  required:
                    - op
                  properties:
                    op:
                      description: >-
                        OpenAPI operationId (camelCase); also the `op` of WS /
                        socket.io `call`.
                      type: string
                      pattern: ^[a-z][a-zA-Z0-9]*$
                    params:
                      type: object
                    body: {}
                    ifMatch:
                      type: string
                  additionalProperties: true
          required:
            - type
            - id
            - ts
            - topic
            - data
          properties:
            type:
              const: event
            data:
              type: object
              required:
                - seq
                - kind
              properties:
                seq:
                  type: integer
                  minimum: 0
                kind:
                  anyOf:
                    - enum:
                        - catalogue.item.published
                        - catalogue.version.available
                        - sync.changed
                        - licence.updated
                        - installation.status
                        - notification.created
                        - agent.message.delta
                    - type: string
                      pattern: ^[a-z][A-Za-z0-9.]{0,63}$
                resource: {}
                patch:
                  type: object
              additionalProperties: true
        examples:
          - name: installation.status
            payload:
              type: event
              id: 0192f3a4-5b6c-7d8e-9f01-23456789c0aa
              ts: '2026-10-19T12:00:00.000Z'
              topic: >-
                cloud/0192f3a4-5b6c-7d8e-9f01-23456789c002/installations/0192f3a4-5b6c-7d8e-9f01-23456789c005
              data:
                seq: 1
                kind: installation.status
                resource:
                  status: online
          - name: catalogue.item.published
            payload:
              type: event
              id: 0192f3a4-5b6c-7d8e-9f01-23456789c0ab
              ts: '2026-10-19T12:00:00.000Z'
              topic: >-
                cloud/0192f3a4-5b6c-7d8e-9f01-23456789c002/catalogue/0192f3a4-5b6c-7d8e-9f01-23456789c008
              data:
                seq: 2
                kind: catalogue.item.published
                resource:
                  id: 0192f3a4-5b6c-7d8e-9f01-23456789c008
                  slug: intro-show
operations:
  emitJoin:
    action: send
    channel:
      $ref: '#/channels/v1'
    summary: Join extra rooms (e.g. installation:{id} of an org the user administers).
    messages:
      - $ref: '#/channels/v1/messages/join'
  receiveEvent:
    action: receive
    channel:
      $ref: '#/channels/v1'
    summary: Events of the joined rooms.
    messages:
      - $ref: '#/channels/v1/messages/event'
components:
  securitySchemes:
    handshakeToken:
      type: httpApiKey
      name: token
      in: query
      description: >-
        Sent as `auth: { token }` in the socket.io CONNECT packet: access JWT or
        `fdk_` / `fdi_` API key.
  messages:
    join:
      name: join
      title: join (C→S, ack)
      payload:
        type: object
        required:
          - rooms
        properties:
          rooms:
            type: array
            minItems: 1
            items:
              type: string
              pattern: ^(user|org|installation):[0-9a-f-]{36}$
        additionalProperties: false
      examples:
        - name: installation
          payload:
            rooms:
              - installation:0192f3a4-5b6c-7d8e-9f01-23456789c005
    event:
      name: event
      title: event (S→C)
      payload:
        description: >-
          Cloud realtime event (socket.io /v1 on /api/socket.io/, GraphQL
          subscriptions): the common envelope with `topic` = cloud/{orgId}/… or
          user/{userId}/…
        type: object
        allOf:
          - $schema: https://json-schema.org/draft/2020-12/schema
            $id: >-
              https://freedome.nativemind.us/schemas/common/1.0/envelope.schema.json
            $comment: >-
              NativeMindNONC — freedome_contract (see LICENSE). Message envelope
              for plain WS (sub-protocol freedome.v1), socket.io `event`
              payload, GraphQL Event and OSC JSON events, 02e §7.1 / §8.1.
              `type`, `id`, `ts`, `data` on every message; `topic` on events;
              `replyTo` on result / error replies. Message types are open
              (readers ignore unknown ones).
            title: Message envelope
            type: object
            required:
              - type
              - id
              - ts
              - data
            properties:
              type:
                description: >-
                  Known: hello, welcome, subscribe, unsubscribe, call, result,
                  event, error, resync, ping, pong, bye.
                type: string
                pattern: ^[a-z][a-zA-Z0-9]*$
              id:
                description: Unique per message; the idempotency key of `call`.
                type: string
                pattern: >-
                  ^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                examples:
                  - 0192f3a4-5b6c-7d8e-9f01-23456789abcd
              ts:
                description: RFC 3339 UTC with milliseconds, e.g. 2026-10-19T12:00:00.000Z.
                type: string
                format: date-time
                pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$
              topic:
                description: >-
                  Concrete event topic (02e §7.2), e.g.
                  venues/default/players/main.
                type: string
                maxLength: 512
                pattern: ^[A-Za-z0-9._@-]+(/[A-Za-z0-9._@-]+)*$
              replyTo:
                description: >-
                  Server-owned resource id: UUIDv7, lowercase, sortable by
                  creation time.
                type: string
                pattern: >-
                  ^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                examples:
                  - 0192f3a4-5b6c-7d8e-9f01-23456789abcd
              data: {}
            allOf:
              - if:
                  properties:
                    type:
                      const: event
                  required:
                    - type
                then:
                  required:
                    - topic
                  properties:
                    data:
                      type: object
                      required:
                        - seq
                        - kind
                      properties:
                        seq:
                          type: integer
                          minimum: 0
                          description: >-
                            Per-server monotonically increasing sequence (resume
                            with sinceSeq).
                        kind:
                          type: string
                          pattern: ^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)+$
                          description: >-
                            Event kind from events/topics.yaml, e.g.
                            player.state.
                        resource:
                          description: Full new representation.
                        patch:
                          type: object
                          description: JSON merge patch (high-rate kinds).
                        revision:
                          description: >-
                            Monotonic resource revision; the strong ETag is
                            derived from it.
                          type: integer
                          minimum: 0
                      not:
                        required:
                          - resource
                          - patch
                      additionalProperties: true
              - if:
                  properties:
                    type:
                      const: result
                  required:
                    - type
                then:
                  required:
                    - replyTo
              - if:
                  properties:
                    type:
                      const: error
                  required:
                    - type
                then:
                  properties:
                    data:
                      $schema: https://json-schema.org/draft/2020-12/schema
                      $id: >-
                        https://freedome.nativemind.us/schemas/common/1.0/problem.schema.json
                      $comment: >-
                        NativeMindNONC — freedome_contract (see LICENSE). RFC
                        9457 problem details with the Freedome `code` catalogue,
                        02e §3.3. Also the `data` of WS `error`, the socket.io
                        ack error and GraphQL errors[].extensions.problem. The
                        catalogue is open: unknown codes are allowed; known
                        codes are bound to their HTTP status.
                      title: Problem details
                      type: object
                      required:
                        - type
                        - title
                        - code
                      properties:
                        type:
                          type: string
                          format: uri
                          description: >-
                            https://freedome.nativemind.us/problems/<code> for
                            catalogue codes.
                        title:
                          type: string
                          minLength: 1
                        status:
                          type: integer
                          minimum: 100
                          maximum: 599
                        detail:
                          type: string
                        instance:
                          type: string
                          format: uri-reference
                        code:
                          description: >-
                            Stable machine key; also the last path segment of
                            `type`. Open set: see knownCode.
                          type: string
                          pattern: ^[a-z][a-z0-9]*(-[a-z0-9]+)*$
                        traceId:
                          type: string
                          pattern: ^[0-9a-f]{16,32}$
                        errors:
                          type: array
                          items:
                            type: object
                            required:
                              - pointer
                              - detail
                            properties:
                              pointer:
                                type: string
                                format: json-pointer
                              detail:
                                type: string
                              code:
                                description: >-
                                  Stable machine key; also the last path segment
                                  of `type`. Open set: see knownCode.
                                type: string
                                pattern: ^[a-z][a-z0-9]*(-[a-z0-9]+)*$
                            additionalProperties: true
                      allOf:
                        - if:
                            properties:
                              code:
                                const: validation-failed
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 422
                        - if:
                            properties:
                              code:
                                const: not-found
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 404
                        - if:
                            properties:
                              code:
                                const: conflict
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 409
                        - if:
                            properties:
                              code:
                                const: precondition-failed
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 412
                        - if:
                            properties:
                              code:
                                const: precondition-required
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 428
                        - if:
                            properties:
                              code:
                                const: unauthenticated
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 401
                        - if:
                            properties:
                              code:
                                const: forbidden
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 403
                        - if:
                            properties:
                              code:
                                const: rate-limited
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 429
                        - if:
                            properties:
                              code:
                                const: payload-too-large
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 413
                        - if:
                            properties:
                              code:
                                const: unsupported-format
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 415
                        - if:
                            properties:
                              code:
                                const: engine-unavailable
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 503
                        - if:
                            properties:
                              code:
                                const: engine-incompatible
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 503
                        - if:
                            properties:
                              code:
                                const: degraded
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 503
                        - if:
                            properties:
                              code:
                                const: upload-checksum-mismatch
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 422
                        - if:
                            properties:
                              code:
                                const: legacy-unsupported
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 501
                        - if:
                            properties:
                              code:
                                const: internal
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 500
                        - if:
                            properties:
                              code:
                                const: clock-unlocked
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 409
                        - if:
                            properties:
                              code:
                                const: not-configured
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 503
                        - if:
                            properties:
                              code:
                                const: authorization-pending
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 400
                        - if:
                            properties:
                              code:
                                const: slow-down
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 400
                        - if:
                            properties:
                              code:
                                const: access-denied
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 403
                        - if:
                            properties:
                              code:
                                const: expired-token
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 400
                        - if:
                            properties:
                              code:
                                const: token-reused
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 401
                        - if:
                            properties:
                              code:
                                const: idempotency-key-reused
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 409
                        - if:
                            properties:
                              code:
                                const: idempotency-in-progress
                            required:
                              - code
                          then:
                            properties:
                              status:
                                const: 409
                      additionalProperties: true
                      examples:
                        - type: >-
                            https://freedome.nativemind.us/problems/engine-unavailable
                          title: Visual engine unavailable
                          status: 503
                          detail: >-
                            freedome-engined not reachable at
                            unix:/run/freedome/engine.sock
                          instance: /api/v1/venues/default/players/main/play
                          code: engine-unavailable
                          traceId: 4bf92f3577b34da6a3ce929d0e0e4736
                      $defs:
                        knownCode:
                          enum:
                            - validation-failed
                            - not-found
                            - conflict
                            - precondition-failed
                            - precondition-required
                            - unauthenticated
                            - forbidden
                            - rate-limited
                            - payload-too-large
                            - unsupported-format
                            - engine-unavailable
                            - engine-incompatible
                            - degraded
                            - job-failed
                            - upload-checksum-mismatch
                            - legacy-unsupported
                            - internal
                            - clock-unlocked
                            - not-configured
                            - authorization-pending
                            - slow-down
                            - access-denied
                            - expired-token
                            - token-reused
                            - idempotency-key-reused
                            - idempotency-in-progress
                        code:
                          description: >-
                            Stable machine key; also the last path segment of
                            `type`. Open set: see knownCode.
                          type: string
                          pattern: ^[a-z][a-z0-9]*(-[a-z0-9]+)*$
                        fieldError:
                          type: object
                          required:
                            - pointer
                            - detail
                          properties:
                            pointer:
                              type: string
                              format: json-pointer
                            detail:
                              type: string
                            code:
                              description: >-
                                Stable machine key; also the last path segment
                                of `type`. Open set: see knownCode.
                              type: string
                              pattern: ^[a-z][a-z0-9]*(-[a-z0-9]+)*$
                          additionalProperties: true
              - if:
                  properties:
                    type:
                      const: call
                  required:
                    - type
                then:
                  properties:
                    data:
                      type: object
                      required:
                        - op
                      properties:
                        op:
                          description: >-
                            OpenAPI operationId (camelCase); also the `op` of WS
                            / socket.io `call`.
                          type: string
                          pattern: ^[a-z][a-zA-Z0-9]*$
                        params:
                          type: object
                        body: {}
                        ifMatch:
                          type: string
                      additionalProperties: true
            additionalProperties: true
            examples:
              - type: event
                id: 0192f3a4-5b6c-7d8e-9f01-23456789abcd
                ts: '2026-10-19T12:00:00.123Z'
                topic: venues/default/players/main
                data:
                  seq: 48213
                  kind: player.state
                  resource:
                    status: playing
                    position: 12.5
            $defs:
              knownType:
                enum:
                  - hello
                  - welcome
                  - subscribe
                  - unsubscribe
                  - call
                  - result
                  - event
                  - error
                  - resync
                  - ping
                  - pong
                  - bye
              eventData:
                type: object
                required:
                  - seq
                  - kind
                properties:
                  seq:
                    type: integer
                    minimum: 0
                    description: >-
                      Per-server monotonically increasing sequence (resume with
                      sinceSeq).
                  kind:
                    type: string
                    pattern: ^[a-z][a-zA-Z0-9]*(\.[a-z][a-zA-Z0-9]*)+$
                    description: Event kind from events/topics.yaml, e.g. player.state.
                  resource:
                    description: Full new representation.
                  patch:
                    type: object
                    description: JSON merge patch (high-rate kinds).
                  revision:
                    description: >-
                      Monotonic resource revision; the strong ETag is derived
                      from it.
                    type: integer
                    minimum: 0
                not:
                  required:
                    - resource
                    - patch
                additionalProperties: true
              callData:
                type: object
                required:
                  - op
                properties:
                  op:
                    description: >-
                      OpenAPI operationId (camelCase); also the `op` of WS /
                      socket.io `call`.
                    type: string
                    pattern: ^[a-z][a-zA-Z0-9]*$
                  params:
                    type: object
                  body: {}
                  ifMatch:
                    type: string
                additionalProperties: true
        required:
          - type
          - id
          - ts
          - topic
          - data
        properties:
          type:
            const: event
          data:
            type: object
            required:
              - seq
              - kind
            properties:
              seq:
                type: integer
                minimum: 0
              kind:
                anyOf:
                  - enum:
                      - catalogue.item.published
                      - catalogue.version.available
                      - sync.changed
                      - licence.updated
                      - installation.status
                      - notification.created
                      - agent.message.delta
                  - type: string
                    pattern: ^[a-z][A-Za-z0-9.]{0,63}$
              resource: {}
              patch:
                type: object
            additionalProperties: true
      examples:
        - name: installation.status
          payload:
            type: event
            id: 0192f3a4-5b6c-7d8e-9f01-23456789c0aa
            ts: '2026-10-19T12:00:00.000Z'
            topic: >-
              cloud/0192f3a4-5b6c-7d8e-9f01-23456789c002/installations/0192f3a4-5b6c-7d8e-9f01-23456789c005
            data:
              seq: 1
              kind: installation.status
              resource:
                status: online
        - name: catalogue.item.published
          payload:
            type: event
            id: 0192f3a4-5b6c-7d8e-9f01-23456789c0ab
            ts: '2026-10-19T12:00:00.000Z'
            topic: >-
              cloud/0192f3a4-5b6c-7d8e-9f01-23456789c002/catalogue/0192f3a4-5b6c-7d8e-9f01-23456789c008
            data:
              seq: 2
              kind: catalogue.item.published
              resource:
                id: 0192f3a4-5b6c-7d8e-9f01-23456789c008
                slug: intro-show
