# GENERATED by make generate from services/gateway/api/openapi.yaml (the paths served on the
# admin listener and the schemas they reach) - edit that contract, never this file.
openapi: 3.1.0
info:
  title: Flexway admin API
  description: |-
    The operational surface of a Flexway gateway, served on its admin port (9090 by default, moved by `FLEXWAY_ADMIN_ADDR`): the liveness and readiness probes, the configuration in force with its secrets masked, a request simulated without its upstream, the journals of events and errors of the replica that answers, and the Prometheus metrics.

    This port is never routable from outside: `/config` lists the issuers and the upstreams. Expose it to the orchestrator, the metrics scraper and the console only. Every error of this surface is an RFC 9457 problem document (`application/problem+json`).
  version: 0.9.0
servers:
- url: http://localhost:9090
  description: Admin listener
paths:
  /healthz:
    get:
      operationId: liveness
      summary: The process is alive - never about its configuration
      responses:
        '200':
          description: Alive.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Liveness'
  /readyz:
    get:
      operationId: readiness
      summary: A configuration is loaded and served; red first at shutdown
      responses:
        '200':
          description: Ready.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Readiness'
        '503':
          description: Not ready, with the reason - a probe's answer, not an error document.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Readiness'
  /config:
    get:
      operationId: getEffectiveConfig
      summary: The configuration in force, secrets masked, and what it composes to
      description: 'Every key of flexway.yaml as loaded, secret-looking values redacted, plus what the
        gateway derives from it: the catalogue of served operations and each operation''s chain with its
        provenance, the configuration version and the last reload''s outcome.

        '
      responses:
        '200':
          description: The effective configuration.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EffectiveConfig'
        '503':
          description: No configuration loaded yet (`not_ready`).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /simulate:
    post:
      operationId: simulateRequest
      summary: What the gateway would do with a described request, without calling the upstream
      description: 'The described request goes through the same decision as traffic - routing, origin,
        authorization against the described identity (no token is verified), whitelist, validation, policy
        chain - and stops before the upstream: no token exchanged, no bucket nor quota spent, nothing
        counted.

        '
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SimulationRequest'
      responses:
        '200':
          description: The verdict, and the outbound request when served.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SimulationResult'
        '400':
          description: The description is incomplete (`malformed_request`).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /simulate/mqtt:
    post:
      operationId: simulateMQTTPacket
      summary: What the MQTT device listener would do with a described packet, without the broker
      description: 'A described PUBLISH, SUBSCRIBE or will (a CONNECT''s) of a described device goes through
        the listener''s decision - the operations its identity satisfies, its channels with the bound
        values written, wildcards contained, $share/ groups, QoS, Response Topic - and stops before the
        broker: nothing dialled, no rate nor quota spent, nothing counted. Absent without listeners.mqtt
        (404).

        '
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MQTTSimulationRequest'
      responses:
        '200':
          description: The verdict, the operation, and the topic or filter as written toward the broker
            when served.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MQTTSimulationResult'
        '400':
          description: The description is incomplete (`malformed_request`).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: listeners.mqtt is not set (`not_found`).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events:
    get:
      operationId: listEvents
      summary: What happened on this replica - reloads, circuit breaker transitions, shedding
      description: 'A journal in memory: the last 128 events of each kind, newest first, lost at a restart
        - per replica, the one that answers. Never a tenant nor anything a caller sent: upstream names
        come from the configuration, versions and causes from the reloader (the text of /config''s last_reload).

        '
      responses:
        '200':
          description: The journal.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventLog'
  /errors:
    get:
      operationId: listErrors
      summary: The recent errors of this replica - upstream failures, refusals, internal errors
      description: 'A journal in memory: three rings of 256 (upstream, refused, internal), newest first,
        lost at a restart - per replica, the one that answers. Written on the error path only, without
        an allocation, at most 20 per second and per kind: past it, an error is counted in its kind''s
        dropped and not detailed. Every field is a name from the configuration, the verified tenant, or
        a member of a closed set; never a subject, an address, the path received, the request, its headers
        or body, nor an upstream''s or the network''s text. A 4xx an upstream answered is its business,
        not an error of the gateway.

        '
      responses:
        '200':
          description: The journal.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorLog'
  /sparkplug/nodes:
    get:
      operationId: listSparkplugNodes
      summary: The Sparkplug B edge nodes and host applications that cross this replica
      description: 'The table each replica keeps: an edge node is online from its NBIRTH on this replica,
        offline from its NDEATH or the end of its connection with its will, moved when this replica handed
        its connection over to another (a tombstone, never offline), unknown when only its admitted commands
        crossed here. Bounded by observability.sparkplug (max_nodes, max_nodes_per_tenant, offline_retention,
        max_devices_per_node); lost at a restart. The listing carries each node''s device counts, never
        its devices: an answer is at most max_nodes entries of bounded fields (an id is 255 bytes at most).
        With node (and tenant), the one node with its devices. The console reads it on every replica and
        keeps, per node, the entry with the latest birth. Names are the ones the topics carry - the tenant''s
        group, the node''s and its devices'' ids; never a metric value, a payload, an address or a certificate.
        Absent (404) when the gateway has no MQTT listener.

        '
      parameters:
      - name: tenant
        in: query
        required: false
        description: Only this tenant's nodes and host applications.
        schema:
          type: string
          maxLength: 128
      - name: node
        in: query
        required: false
        description: Only this edge node, with its devices - given with tenant.
        schema:
          type: string
          maxLength: 255
      responses:
        '200':
          description: The table.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SparkplugNodes'
  /metrics:
    get:
      operationId: getMetrics
      summary: Prometheus exposition of the gateway's metrics
      description: Names and dimensions are a frozen surface.
      responses:
        '200':
          description: Prometheus text exposition.
          content:
            text/plain:
              schema:
                type: string
components:
  schemas:
    SimulationRequest:
      type: object
      additionalProperties: false
      required:
      - method
      - host
      - path
      properties:
        method:
          type: string
          example: GET
        host:
          type: string
          example: api.example.com
        path:
          type: string
          description: With its query, as a client would send it.
          example: /orders/42?status=open
        headers:
          type: object
          additionalProperties:
            type: string
        identity:
          x-go-type-skip-optional-pointer: false
          allOf:
          - $ref: '#/components/schemas/SimulatedIdentity'
    SimulatedIdentity:
      type: object
      description: Who the caller is supposed to be - what a valid token would have proved. Nothing is
        verified.
      additionalProperties: false
      required:
      - issuer
      - subject
      properties:
        issuer:
          type: string
        subject:
          type: string
        tenant:
          type: string
        scopes:
          type: array
          items:
            type: string
        roles:
          type: array
          items:
            type: string
    MQTTSimulationRequest:
      type: object
      additionalProperties: false
      required:
      - packet
      - topic
      - identity
      properties:
        packet:
          type: string
          enum:
          - publish
          - subscribe
          - will
          description: 'will: a CONNECT''s will, judged as a PUBLISH.'
        topic:
          type: string
          description: A topic name (publish, will) or a filter (subscribe), $share/<group>/ included.
        qos:
          type: integer
          minimum: 0
          maximum: 2
          default: 0
        response_topic:
          type: string
          description: An MQTT 5 Response Topic
          judged as a subscription.: null
        identity:
          $ref: '#/components/schemas/MQTTSimulatedIdentity'
    MQTTSimulatedIdentity:
      type: object
      description: Who the device is supposed to be - nothing is verified. A key or a certificate is found
        by its id in the configuration in force.
      additionalProperties: false
      required:
      - kind
      properties:
        kind:
          type: string
          enum:
          - token
          - api_key
          - certificate
        id:
          type: string
          description: 'api_key: the key''s id; certificate: the auth.mtls client''s id.'
        issuer:
          type: string
        subject:
          type: string
        tenant:
          type: string
          description: 'token: its tenant claim; a key''s or a certificate''s is the configuration''s.'
        scopes:
          type: array
          items:
            type: string
        claims:
          type: object
          additionalProperties:
            type: string
          description: 'token: the claims a claim:<name> binding reads.'
        certificate:
          type: object
          description: 'certificate: the fields a cert:<field> binding reads - cn, serial, fingerprint,
            ou, o, san.dns, san.uri, san.ip, san.email (lists for the multi-valued ones).'
          additionalProperties: true
    MQTTSimulationResult:
      type: object
      required:
      - verdict
      properties:
        verdict:
          type: string
          enum:
          - served
          - refused
        reason_code:
          type: integer
          description: The MQTT 5 reason code a refusal answers (0x87 = 135...).
        cause:
          type: string
          enum:
          - authentication
          - not_authorized
          - binding
          - wildcard
          - payload_invalid
          - quota
          - packet_too_large
          - upstream_unavailable
          description: The refusal's cause - the label of flexway.mqtt.packets.
        operation:
          type: string
        upstream:
          type: string
        written:
          type: string
          description: The topic or filter as written toward the broker - a $share/ group in the tenant's
            name.
        qos:
          type: integer
          description: The QoS the broker sees - a subscription's granted at the operation's qos_max at
            most.
        client_id:
          type: string
          description: The client id the broker sees for this identity.
    SimulationResult:
      type: object
      required:
      - verdict
      - status
      properties:
        verdict:
          type: string
          enum:
          - served
          - refused
        status:
          type: integer
        code:
          type: string
          description: The refusal's problem code.
        operation:
          type: string
        upstream:
          type: string
        chain:
          type: array
          items:
            type: string
        applied:
          type: array
          items:
            type: string
        outbound:
          x-go-type-skip-optional-pointer: false
          allOf:
          - $ref: '#/components/schemas/Outbound'
    Outbound:
      type: object
      description: The request the upstream would receive, before the token exchange and the relay; credentials
        masked.
      required:
      - path
      - headers
      properties:
        path:
          type: string
        query:
          type: string
        headers:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
    Liveness:
      type: object
      required:
      - status
      - uptime_sec
      properties:
        status:
          type: string
          enum:
          - ok
        uptime_sec:
          type: integer
    Readiness:
      type: object
      required:
      - status
      properties:
        status:
          type: string
          enum:
          - ready
          - not ready
        operations:
          type: integer
          description: Operations served, when ready.
        reason:
          type: string
          description: Why not, when not ready.
    Problem:
      type: object
      description: 'RFC 9457 problem details - every error of the admin surface (the inference surface
        answers in OpenAI''s envelope, ErrorResponse). `code` is what a client switches on.

        '
      required:
      - type
      - title
      - status
      - code
      properties:
        type:
          type: string
          format: uri
        title:
          type: string
        status:
          type: integer
        detail:
          type: string
        instance:
          type: string
        code:
          type: string
          example: not_found
        request_id:
          type: string
        trace_id:
          type: string
        errors:
          type: array
          description: invalid_request only - each field that broke the contract, and the rule it broke.
          items:
            $ref: '#/components/schemas/FieldError'
        grpc:
          $ref: '#/components/schemas/GRPCStatus'
          x-go-type-skip-optional-pointer: false
    GRPCStatus:
      type: object
      description: 'upstream_status only - the google.rpc.Status a gRPC upstream answered to a call translated
        from REST (1.1.0): the upstream''s own answer, as it gave it. The HTTP status is the one google.rpc.Code
        maps the code to.

        '
      required:
      - code
      - status
      properties:
        code:
          type: integer
          example: 5
        status:
          type: string
          example: NOT_FOUND
          description: The code's name - what a client switches on.
        message:
          type: string
        details:
          type: array
          description: The status details in the proto3 JSON mapping; a type the gateway does not know
            keeps only its "@type".
          items:
            type: object
            additionalProperties: true
    FieldError:
      type: object
      required:
      - field
      - rule
      - code
      properties:
        field:
          type: string
          example: query.limit
        rule:
          type: string
          description: For a human.
        code:
          type: string
          description: The JSON Schema keyword broken, or the operator's name for it (errors.field_codes).
    KafkaOperation:
      type: object
      description: An AsyncAPI operation served to Kafka clients (x-flexway-kafka-proxy).
      required:
      - operation
      - identities
      properties:
        operation:
          type: string
        identities:
          type: array
          description: The alternatives of its security - token (with its scopes), apikey, certificate.
          items:
            type: object
            required:
            - kind
            properties:
              kind:
                type: string
                enum:
                - token
                - apikey
                - certificate
              scopes:
                type: array
                items:
                  type: string
        transactions:
          type: boolean
          description: A send operation that opens the transactional producer.
        admin_scope:
          type: string
          description: The scope a token carries to administer the topic.
        decrypt_scope:
          type: string
          description: A receive operation's scope a token carries to read the topic's encrypted fields
            in clear.
    EffectiveConfig:
      type: object
      additionalProperties: true
      required:
      - version
      - config_version
      - catalog
      - chains
      - build
      properties:
        version:
          type: integer
          description: The configuration schema's version - not the gateway's, see build.
        build:
          $ref: '#/components/schemas/BuildInfo'
        config_version:
          type: string
          description: Short digest of the bytes served.
        config_digest:
          type: string
          description: 'Short semantic digest of the configuration served: the decoded flexway.yaml in
            a canonical form and each contract under the path flexway.yaml writes, the API key store excluded.
            The same whatever the mount path or the chart''s rendering - what `flexway validate` prints,
            and what a pipeline or the console expects to see served after a merge.'
        last_reload:
          type: object
          properties:
            result:
              type: string
              enum:
              - applied
              - rejected
              - unchanged
            version:
              type: string
            at:
              type: string
              format: date-time
            cause:
              type: string
        catalog:
          type: array
          items:
            $ref: '#/components/schemas/CatalogEntry'
        fragments:
          type: array
          description: The policy fragments imported, in the order policies.fragments writes them; empty
            without one. Their definitions are also under policies.definitions, as <import>/<name>.
          items:
            $ref: '#/components/schemas/PolicyFragment'
        agents:
          type: object
          additionalProperties: true
          description: 'The agents section as loaded, when one is configured: mcp (path, resources, servers
            and clients) and delegation (max_depth, max_age, introspection).'
          properties:
            mcp:
              type: object
              additionalProperties: true
              properties:
                clients:
                  type: array
                  description: 'The OAuth clients the MCP surface admits, as written - the URL of a client
                    metadata document or a prefix ending with *. Absent: no list declared.'
                  items:
                    type: string
        kafka:
          type: object
          description: The Kafka listener's virtual clusters (1.6.0), read from the AsyncAPI contract
            in force; absent without listeners.kafka. Its bounds and quotas are under listeners.kafka,
            its signals' settings under observability.kafka. Never a key, a certificate, a tenant's name.
          required:
          - clusters
          - mechanisms
          properties:
            clusters:
              type: object
              description: By virtual cluster.
              additionalProperties:
                type: object
                required:
                - upstream
                - prefix
                - topics
                properties:
                  upstream:
                    type: string
                    description: The Kafka upstream the cluster fronts.
                  prefix:
                    type: string
                    description: What the physical names start with before the tenant - empty, or ending
                      with a dot.
                  topics:
                    type: object
                    description: By the name the clients see.
                    additionalProperties:
                      type: object
                      required:
                      - physical
                      - send
                      - receive
                      properties:
                        physical:
                          type: string
                          description: The physical form, {tenant} where the tenant goes.
                        send:
                          type: array
                          description: The operations that open producing.
                          items:
                            $ref: '#/components/schemas/KafkaOperation'
                        receive:
                          type: array
                          description: The operations that open reading and groups.
                          items:
                            $ref: '#/components/schemas/KafkaOperation'
                        encrypt:
                          type: object
                          description: The fields x-flexway-encrypt declares - names, never a value.
                          required:
                          - message
                          - format
                          - fields
                          properties:
                            message:
                              type: string
                            format:
                              type: string
                              enum:
                              - json
                              - avro
                              - protobuf
                            fields:
                              type: array
                              items:
                                type: string
            mechanisms:
              type: array
              description: The SASL mechanisms served (OAUTHBEARER, PLAIN).
              items:
                type: string
        devices:
          type: object
          description: The MQTT device listener's operations (1.7.0), read from the AsyncAPI contract
            in force; absent without listeners.mqtt. Its bounds are under listeners.mqtt, its signals'
            settings under observability.mqtt. Never a key, a certificate, a tenant's name.
          required:
          - upstream
          - operations
          properties:
            upstream:
              type: string
              description: The broker every device connection is relayed to.
            protocol_version:
              type: string
              description: The upstream's declared MQTT version - a device's own version is relayed.
            operations:
              type: array
              items:
                type: object
                required:
                - operation
                - action
                - channel
                - address
                - identities
                - qos_max
                - bind
                properties:
                  operation:
                    type: string
                  action:
                    type: string
                    enum:
                    - send
                    - receive
                    description: 'send: devices publish; receive: they subscribe.'
                  channel:
                    type: string
                  address:
                    type: string
                    description: The channel's address, {parameter} where the bound values go.
                  bind:
                    type: object
                    additionalProperties:
                      type: string
                    description: 'Each parameter''s fact: tenant, subject, claim:<name>, cert:<field>.'
                  identities:
                    type: array
                    items:
                      type: object
                      required:
                      - kind
                      properties:
                        kind:
                          type: string
                          enum:
                          - token
                          - apikey
                          - certificate
                        scopes:
                          type: array
                          items:
                            type: string
                  qos_max:
                    type: integer
                  messages_per_second:
                    type: number
                  bytes_per_second:
                    type: integer
                  shared:
                    type: boolean
                  validation:
                    type: string
        kms:
          type: object
          description: 'The KMS of field-level encryption on the Kafka listener (1.6.0), as loaded: its
            kind, host and key name - per_tenant_key when the name holds {tenant} -, the previous keys
            records may still name (previous_keys, read only), timeout, rotation, cache and tenant_calls
            bounds, and its kind''s section with references (${VAR}, file:/path) and mounted file paths
            - never a secret, never a key. The epochs in use and the keys cached are runtime state, in
            the metrics flexway.kafka.dek.epoch and flexway.kafka.dek.cached.'
          required:
          - kind
          - host
          - key
          - per_tenant_key
          - timeout
          - rotation
          - cache
          - tenant_calls
          properties:
            kind:
              type: string
              enum:
              - vault_transit
              - aws_kms
              - gcp_kms
              - local
            host:
              type: string
            key:
              type: string
            previous_keys:
              type: array
              items:
                type: string
            per_tenant_key:
              type: boolean
            timeout:
              type: string
            rotation:
              type: object
              properties:
                interval:
                  type: string
                max_encryptions:
                  type: integer
            cache:
              type: object
              properties:
                max_keys:
                  type: integer
                ttl:
                  type: string
                  description: An unwrapped data key's life from its unwrap, and the longest a write data
                    key goes without the KMS confirming its key - the longest an erasure waits.
                negative_ttl:
                  type: string
            tenant_calls:
              type: object
              properties:
                rate:
                  type: number
                burst:
                  type: integer
          additionalProperties: true
        listeners:
          type: object
          additionalProperties: true
          description: 'The listeners beside HTTP, as loaded: kafka - its addresses, bounds (max_connections,
            max_connections_per_tenant, max_tenant_in_flight_bytes, on_tenant_budget_exceeded...) and,
            when declared, quotas (client and tenant producer_byte_rate, consumer_byte_rate, request_rate;
            window, max_throttle, quota) - what the console shows as the bounds in force; mqtt - its address,
            TLS files, websocket, advertised_address, every bound (max_connections, max_connections_per_ip,
            max_connection_rate_per_tenant, topic_alias_maximum...), device and tenant rates, the tenant''s
            quota policy, failover (mode, reason, server_reference, redirect_above, handover_timeout,
            drain_spread).'
        mcp_federation:
          type: object
          description: 'Live, not the configuration: each federated MCP server''s last discovery, by server
            name - read at each GET /config, since discovery moves on its own.'
          additionalProperties:
            $ref: '#/components/schemas/FederationState'
        a2a:
          type: object
          description: 'The governed A2A agents (1.2.0): what each serves and how - from the configuration
            in force, read at each GET /config. Absent when no agent is declared. Never a key, never a
            token.'
          required:
          - agents
          properties:
            agents:
              type: array
              items:
                $ref: '#/components/schemas/A2AAgent'
        chains:
          type: object
          description: By host ("*" for every host without contracts of its own), then by operationId.
          additionalProperties:
            type: object
            additionalProperties:
              $ref: '#/components/schemas/ChainDetail'
        effective_chains:
          type: object
          description: The chain's policy names alone, by operationId, on hosts not configured otherwise.
          additionalProperties:
            type: array
            items:
              type: string
        policies:
          type: object
          description: The policies section as loaded - definitions and chains, secret-looking values
            masked.
          properties:
            definitions:
              type: object
              description: 'By policy name. config is the policy''s own, every value under a secret-looking
                name replaced by "[redacted]" - a header''s dashes read as underscores. phase and when
                as written: absent when not written.'
              additionalProperties:
                type: object
                required:
                - type
                properties:
                  type:
                    type: string
                  phase:
                    type: string
                    description: request, response or error.
                  when:
                    type: string
                    description: The CEL condition.
                  config:
                    description: The policy's configuration, masked.
            chains:
              type: object
              additionalProperties: true
        ai:
          type: object
          additionalProperties: true
          description: 'The ai section as loaded, when one is configured: budget (monthly_tokens, daily_tokens,
            monthly_eur, soft), overrides (match, backend, caps) and backends - the quotas the console
            compares a tenant''s consumption with.'
          properties:
            backends:
              type: object
              description: By backend name.
              additionalProperties:
                type: object
                required:
                - url
                - api_key
                - default_model
                - external
                - fallback
                properties:
                  url:
                    type: string
                  api_key:
                    type: string
                    description: The reference as written (env:..., file:...) - never resolved.
                  default_model:
                    type: string
                  external:
                    type: boolean
                  price:
                    type: object
                    description: Euros per million tokens; absent when the backend declares no price.
                    required:
                    - input_per_mtok
                    - output_per_mtok
                    properties:
                      input_per_mtok:
                        type: number
                      output_per_mtok:
                        type: number
                  fallback:
                    type: array
                    description: The backends tried in turn when this one fails before answering, in order;
                      empty when none.
                    items:
                      type: string
                  kind:
                    type: string
                    enum:
                    - openai
                    - relay
                    - grpc
                    description: Where the backend is; openai when unset.
                  capabilities:
                    type: array
                    description: What the backend serves, defaults applied - chat when unset, model for
                      a grpc backend.
                    items:
                      type: string
                      enum:
                      - chat
                      - vision
                      - embeddings
                      - model
                  metering:
                    type: string
                    enum:
                    - local
                    - upstream
                    description: 'Who meters the cost: local, or upstream - a relay to a gateway that
                      counts and caps it; the series of such a backend carry metered_by=upstream and are
                      never summed with local ones.'
                  models:
                    type: array
                    items:
                      type: string
                    description: The models a caller may name; absent when none is declared.
                  auth:
                    type: object
                    description: The authentication scheme and the key's reference as written - never
                      a key or a token read.
                    properties:
                      scheme:
                        type: string
                        enum:
                        - none
                        - bearer
                        - header
                        - token_file
                      key:
                        type: string
                      header:
                        type: string
                      path:
                        type: string
                  identity_headers:
                    type: object
                    description: The header names a relay receives the tenant, the agent and the sensitivity
                      under.
                    properties:
                      tenant:
                        type: string
                      agent:
                        type: string
                      sensitive:
                        type: string
                  upstream:
                    type: string
                    description: The upstream of a grpc backend.
            vision:
              type: object
              description: The bounds of the images a chat completion carries, defaults applied.
              properties:
                max_image_bytes:
                  type: integer
                max_body_bytes:
                  type: integer
                allowed_origins:
                  type: array
                  items:
                    type: string
    EventLog:
      type: object
      required:
      - replica
      - capacity
      - events
      properties:
        replica:
          type: string
          description: The answering process's host name - the pod's name.
        capacity:
          type: integer
          description: Events kept per kind.
        events:
          type: array
          items:
            $ref: '#/components/schemas/Event'
    Event:
      type: object
      description: 'One event. reload - result, version, and cause when rejected; breaker - upstream,
        from and to; shedding - state, and cause (latency of the shedder, in_flight_limit of the adaptive
        in-flight limit); delegation - a refused chain of agents: reason, client, tenant, actors, depth
        and age against the bounds in force, operation or tool, the token''s declared scopes. Never a
        subject, never a token; a tenant on the kind delegation only.'
      required:
      - at
      - kind
      properties:
        at:
          type: string
          format: date-time
        kind:
          type: string
          enum:
          - reload
          - breaker
          - shedding
          - delegation
        reason:
          type: string
          enum:
          - depth
          - age
          - revoked
          - widened
          - unverifiable
          description: Delegation - why the chain was refused.
        client:
          type: string
          description: 'Delegation - the agent''s client: a declared client_id, _undeclared, none or _other.'
        tenant:
          type: string
          description: Delegation - the tenant, bounded as on the metrics.
        actors:
          type: array
          description: Delegation - the agents of act, the current one first; at most max_depth + 1, 256
            characters each.
          items:
            type: string
            maxLength: 256
        depth:
          type: integer
          description: Delegation - the chain's measured depth.
        age_seconds:
          type: integer
          format: int64
          description: Delegation - the chain's measured age; -1 when the token carries no time it started.
        max_depth:
          type: integer
          description: Delegation - the depth bound in force for the operation.
        max_age_seconds:
          type: integer
          format: int64
          description: Delegation - the age bound in force for the operation.
        operation:
          type: string
          description: Delegation - the operation (REST or a tool's replay); absent at the MCP connection.
        tool:
          type: string
          description: Delegation - the tool; absent for a REST request and at the MCP connection.
        scopes:
          type: array
          description: Delegation - the presented token's scopes that a contract or a federated server
            declares.
          items:
            type: string
        result:
          type: string
          enum:
          - loaded
          - applied
          - rejected
          - unchanged
        version:
          type: string
        cause:
          type: string
        upstream:
          type: string
        from:
          type: string
          enum:
          - closed
          - half_open
          - open
        to:
          type: string
          enum:
          - closed
          - half_open
          - open
        state:
          type: string
          enum:
          - started
          - stopped
    SparkplugNodes:
      type: object
      additionalProperties: false
      required:
      - replica
      - capacity
      - offline_retention_seconds
      - dropped
      - nodes
      - hosts
      properties:
        replica:
          type: string
          description: The answering process's host name - the pod's name.
        capacity:
          type: integer
          description: observability.sparkplug.max_nodes.
        offline_retention_seconds:
          type: integer
          description: observability.sparkplug.offline_retention
          in seconds.: null
        dropped:
          type: integer
          format: int64
          description: Nodes and host applications not kept since the start - the table was full of online
            nodes.
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/SparkplugNode'
        hosts:
          type: array
          items:
            $ref: '#/components/schemas/SparkplugHost'
    SparkplugNode:
      type: object
      additionalProperties: false
      required:
      - tenant
      - edge_node
      - state
      - since
      - seq_gaps
      - bd_seq_gaps
      - protocol_version
      - auth
      - devices_online
      - devices_total
      - devices
      - devices_truncated
      - commands
      properties:
        tenant:
          type: string
          description: The node's group - the tenant it is bound to.
        edge_node:
          type: string
        state:
          type: string
          enum:
          - online
          - offline
          - moved
          - unknown
        since:
          type: string
          format: date-time
          description: When the node took its state on this replica.
        bd_seq:
          type: integer
          format: int64
          x-go-type-skip-optional-pointer: false
          description: The bdSeq of its last NBIRTH here; absent when none was read.
        will_bd_seq:
          type: integer
          format: int64
          x-go-type-skip-optional-pointer: false
          description: The bdSeq of the will (NDEATH) its connection registered; absent when none was
            read.
        seq_gaps:
          type: integer
          format: int64
          description: Messages whose seq was not the next since its birth here.
        bd_seq_gaps:
          type: integer
          format: int64
          description: Births whose bdSeq was not their will's.
        protocol_version:
          type: string
          description: 5 or 3.1.1; empty for an unknown node.
        auth:
          type: string
          description: The mode of identity of its connection - certificate, token, api_key; empty for
            an unknown node.
        devices_online:
          type: integer
          description: Its devices online (DBIRTH without a later DDEATH) since its birth.
        devices_total:
          type: integer
          description: Its devices kept since its birth.
        devices:
          type: array
          maxItems: 100000
          description: Its devices (DBIRTH, DDEATH) since its birth, sorted by id - listed only when the
            node is asked for (node); empty otherwise.
          items:
            $ref: '#/components/schemas/SparkplugDevice'
        devices_truncated:
          type: boolean
          description: Past observability.sparkplug.max_devices_per_node
          devices were not kept.: null
        commands:
          $ref: '#/components/schemas/SparkplugCommands'
    SparkplugDevice:
      type: object
      additionalProperties: false
      required:
      - device
      - state
      properties:
        device:
          type: string
        state:
          type: string
          enum:
          - online
          - offline
    SparkplugCommands:
      type: object
      additionalProperties: false
      required:
      - admitted
      - refused
      description: The commands (NCMD, DCMD) to the node that crossed this replica, admitted and refused.
      properties:
        admitted:
          type: integer
          format: int64
        refused:
          type: integer
          format: int64
    SparkplugHost:
      type: object
      additionalProperties: false
      required:
      - tenant
      - host_id
      - state
      - since
      description: A host application, read from its STATE (spBv1.0/STATE/{host_id}, the host id bound
        to the tenant).
      properties:
        tenant:
          type: string
        host_id:
          type: string
        state:
          type: string
          enum:
          - online
          - offline
        since:
          type: string
          format: date-time
    ErrorLog:
      type: object
      additionalProperties: false
      required:
      - replica
      - capacity
      - write_limit
      - kinds
      - errors
      properties:
        replica:
          type: string
          description: The answering process's host name - the pod's name.
        capacity:
          type: integer
          description: Errors kept per kind.
        write_limit:
          type: integer
          description: Errors detailed per second and per kind; past it they are counted in dropped.
        kinds:
          type: array
          description: Each kind's count of the errors it could not detail since the start.
          items:
            $ref: '#/components/schemas/ErrorKindCount'
        errors:
          type: array
          items:
            $ref: '#/components/schemas/GatewayError'
    ErrorKindCount:
      type: object
      additionalProperties: false
      required:
      - kind
      - dropped
      properties:
        kind:
          $ref: '#/components/schemas/ErrorKind'
        dropped:
          type: integer
          format: int64
          description: Errors past the write limit since the start.
        last_dropped_at:
          type: string
          format: date-time
          x-go-type-skip-optional-pointer: false
          description: The last of them; absent when none was dropped.
    ErrorKind:
      type: string
      description: upstream - an answer written for an upstream that failed (502, 503, 504), or an upstream's
        5xx relayed; refused - a refusal the gateway wrote (a 4xx, or the 503 of its shedding); internal
        - the gateway failing.
      enum:
      - upstream
      - refused
      - internal
    GatewayError:
      type: object
      additionalProperties: false
      description: 'One error. Its fields are a closed list: no subject, address, received path, request,
        header, body, nor an upstream''s or the network''s text.'
      required:
      - at
      - kind
      - operation
      - status
      - code
      - stage
      - duration_ms
      properties:
        at:
          type: string
          format: date-time
        kind:
          $ref: '#/components/schemas/ErrorKind'
        operation:
          type: string
          description: The operationId; _unmatched when no route matched.
        upstream:
          type: string
          description: The upstream's name in the configuration; absent when the request never reached
            one.
        tenant:
          type: string
          maxLength: 128
          description: 'The verified identity''s tenant; absent for an anonymous caller. A tenant longer
            than 128 characters is never truncated: it is written sha256:<hex digest of the whole tenant>.'
        status:
          type: integer
          description: The HTTP status answered - for a refusal answered in gRPC's status, the one its
            code maps to.
        code:
          type: string
          description: The problem code the gateway wrote; upstream_status for an upstream's 5xx relayed
            as is - never a code or a text of the upstream.
        stage:
          type: string
          description: Where the error was written, derived from its code.
          enum:
          - routing
          - identity
          - authorization
          - policies
          - validation
          - protection
          - upstream
          - response
          - internal
        cause:
          type: string
          description: Upstream errors only - why the upstream failed, a closed set; never the network's
            text.
          enum:
          - dial_refused
          - dns
          - tls
          - timeout
          - reset
          - circuit_open
          - bulkhead
          - buffer_full
          - rejected
          - status
          - other
        duration_ms:
          type: number
          format: double
          description: Time from the request's arrival to its answer.
        trace_id:
          type: string
          pattern: ^[0-9a-f]{32}$
          description: The request's trace when it was sampled.
    BuildInfo:
      type: object
      description: 'The binary serving, written at build time: the release tag for a release ("v1.0.0"),
        "dev" for any other build, and the commit it was built from.'
      required:
      - version
      - commit
      properties:
        version:
          type: string
          example: v1.0.0
        commit:
          type: string
          description: Short commit; empty when the build did not say.
          example: 9438ab3
    CatalogEntry:
      type: object
      required:
      - operation_id
      - method
      - path
      - hosts
      - upstream
      - deprecated
      - security
      - builtin
      - timeout_ms
      - security_detail
      - effective_rate_class
      - params
      - responses
      properties:
        operation_id:
          type: string
        method:
          type: string
        path:
          type: string
          description: The path template, never a concrete URL.
        hosts:
          type: array
          items:
            type: string
          description: '"*" stands for every host without contracts of its own.'
        upstream:
          type: string
        summary:
          type: string
        tags:
          type: array
          items:
            type: string
        deprecated:
          type: boolean
        security:
          type: array
          description: The alternatives, each the schemes it combines; an empty one is anonymous access.
          items:
            type: array
            items:
              type: string
        rate_class:
          type: string
        tool:
          type: string
          description: The tool name when offered to agents (x-flexway-tool).
        tool_unattended:
          type: boolean
          description: 'Present only with tool: false when the tool is kept for agents a person supervises
            (x-flexway-tool with unattended false), true otherwise.'
        builtin:
          type: boolean
          description: An operation the gateway declares itself (ai.*).
        protocol:
          type: string
          enum:
          - grpc
          description: 'grpc for a method of a Protobuf service (1.1.0): path is its gRPC path. Absent:
            HTTP.'
        rest:
          type: array
          description: The REST routes of a gRPC method (google.api.http), the same operation translated.
          items:
            $ref: '#/components/schemas/CatalogRoute'
        cache:
          type: array
          description: 'The operation''s response cache (1.2.0), one entry per distinct rule - from its
            x-flexway-cache, or a cache policy attached around it. Absent: nothing of it is cached.'
          items:
            $ref: '#/components/schemas/CatalogCache'
        timeout_ms:
          type: integer
          format: int64
          description: 'The operation''s total budget in milliseconds: its x-flexway-timeout, otherwise
            its upstream''s timeout. An external-call of the request phase consumes it; the upstream gets
            what is left.'
        owner:
          $ref: '#/components/schemas/CatalogOwner'
        sunset:
          type: string
          pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}$
          description: The date a deprecated operation is withdrawn (x-flexway-sunset), YYYY-MM-DD.
        stream:
          type: string
          enum:
          - sse
          - websocket
          - grpc
          description: 'How the operation answers when it is not one response - a text/event-stream, a
            protocol switch (101), a streaming gRPC method. The vocabulary of flexway.streams.open. Absent:
            one response.'
        security_detail:
          type: array
          description: The alternatives of security, in the same order, with each scheme's kind and what
            it requires.
          items:
            $ref: '#/components/schemas/CatalogAlternative'
        effective_rate_class:
          type: string
          description: 'The rate-limit class the operation counts against: rate_class when declared, read
            for a gRPC method without side effects, otherwise by method.'
        contract:
          type: string
          description: The contract file that declares it, as flexway.yaml writes the path; absent for
            the gateway's own operations.
        priority:
          type: string
          enum:
          - critical
          - normal
          - sheddable
          description: x-flexway-priority when declared.
        validation:
          type: string
          enum:
          - full
          - params
          - 'off'
          description: x-flexway-validation when declared; absent - the host's.
        delegation:
          type: object
          description: x-flexway-delegation when declared; a bound absent is the configuration's.
          properties:
            max_depth:
              type: integer
            max_age_seconds:
              type: integer
              format: int64
        added_scopes:
          type: array
          items:
            type: string
          description: The scopes x-flexway-scopes adds to every token alternative (already in security_detail).
        params:
          type: array
          description: The parameters in short - never a schema nor an example.
          items:
            $ref: '#/components/schemas/CatalogParam'
        body:
          type: object
          required:
          - required
          - media
          description: The request body in short; absent - none declared.
          properties:
            required:
              type: boolean
            media:
              type: array
              items:
                type: string
        responses:
          type: array
          description: The declared responses in short - status as written ("200", "2XX", "default") and
            media types.
          items:
            $ref: '#/components/schemas/CatalogResponse'
    CatalogOwner:
      type: object
      description: The team that answers for an operation (x-flexway-owner) - a team's channel, never
        a person.
      required:
      - team
      properties:
        team:
          type: string
          maxLength: 128
        contact:
          type: string
          maxLength: 128
    CatalogAlternative:
      type: object
      required:
      - anonymous
      - schemes
      properties:
        anonymous:
          type: boolean
          description: 'The empty alternative {}: no identity needed.'
        schemes:
          type: array
          items:
            type: object
            required:
            - name
            - kind
            properties:
              name:
                type: string
              kind:
                type: string
                enum:
                - oauth2
                - openIdConnect
                - http
                - apiKey
                - mutualTLS
                - trusted_headers
                - unsupported
        scopes:
          type: array
          items:
            type: string
        roles:
          type: array
          items:
            type: string
    CatalogParam:
      type: object
      required:
      - name
      - in
      - required
      properties:
        name:
          type: string
        in:
          type: string
          enum:
          - path
          - query
          - header
        required:
          type: boolean
        type:
          type: string
          description: The schema's type; "a|b" for a list of types.
        format:
          type: string
    CatalogResponse:
      type: object
      required:
      - status
      - media
      properties:
        status:
          type: string
        media:
          type: array
          items:
            type: string
    A2AAgent:
      type: object
      required:
      - agent
      - card
      - upstream
      - bindings
      - methods
      - verify
      - streaming
      - card_path
      properties:
        agent:
          type: string
          description: The agent's name in operation ids (a2a.<agent>.<Method>) and metrics.
        card:
          type: string
          description: The declared card, as flexway.yaml writes its path.
        upstream:
          type: string
        bindings:
          type: object
          description: The bindings served (JSONRPC, HTTP+JSON), each with the gateway's address.
          additionalProperties:
            type: string
        methods:
          type: object
          description: The methods served, each with its rate class - free debits nothing.
          additionalProperties:
            type: string
        verify:
          type: string
          enum:
          - none
          description: How the upstream's own card is verified - none until card verification is built.
        streaming:
          type: boolean
        max_streams:
          type: integer
          description: The streams one caller may hold open to the agent, per replica.
        max_task_duration:
          type: string
          description: The longest a stream of the agent runs, as a Go duration.
        card_path:
          type: string
          description: Where the gateway publishes the agent's card.
    FederationState:
      type: object
      required:
      - status
      - tools
      properties:
        status:
          type: object
          required:
          - state
          - at
          properties:
            state:
              type: string
              enum:
              - discovering
              - discovered
              - unreachable
            error:
              type: string
            at:
              type: string
              format: date-time
        tools:
          type: array
          items:
            type: string
          description: The tools discovered, under their names on the surface.
        descriptions:
          type: object
          description: What each tool says of itself, by name, 512 characters at most - a third party's
            text.
          additionalProperties:
            type: string
            maxLength: 512
        not_served:
          type: array
          items:
            type: string
          description: 'Tools announced and not served, their name taken: "<name> (taken by <who>)".'
    CatalogCache:
      type: object
      required:
      - ttl_seconds
      - scope
      - hosts
      properties:
        ttl_seconds:
          type: integer
          format: int64
          description: The longest a response is kept; the upstream's Cache-Control may shorten it.
        scope:
          type: string
          enum:
          - public
          - subject
          description: 'public: anonymous callers; subject: keyed by tenant and subject.'
        policy:
          type: string
          description: The cache policy it comes from; absent for the contract's x-flexway-cache.
        hosts:
          type: array
          items:
            type: string
          description: 'The hosts it applies on; "*" alone: every host.'
    CatalogRoute:
      type: object
      required:
      - method
      - path
      properties:
        method:
          type: string
        path:
          type: string
    ChainDetail:
      type: object
      required:
      - steps
      properties:
        steps:
          type: array
          items:
            type: object
            required:
            - policy
            - type
            - attached
            properties:
              policy:
                type: string
              type:
                type: string
              phase:
                type: string
              when:
                type: string
                description: The CEL condition, when the policy has one.
              attached:
                type: array
                items:
                  $ref: '#/components/schemas/Attachment'
              origin:
                $ref: '#/components/schemas/FragmentOrigin'
        removed:
          type: array
          items:
            allOf:
            - $ref: '#/components/schemas/Attachment'
            - type: object
              required:
              - policy
              properties:
                policy:
                  type: string
        replaced:
          type: array
          items:
            type: object
            required:
            - policy
            - by
            properties:
              policy:
                type: string
              by:
                type: string
    Attachment:
      type: object
      required:
      - level
      properties:
        level:
          type: string
          enum:
          - global
          - host
          - route
          - operation
        source:
          type: string
          description: The host, the route motif, x-flexway-policies, or policies.fragments for the enforced
            head of the chain.
    FragmentOrigin:
      type: object
      description: The fragment an imported policy comes from; absent for a local definition.
      required:
      - import
      - fragment
      - version
      - enforced
      properties:
        import:
          type: string
          description: The import name flexway.yaml gives it - the prefix of its definitions.
        fragment:
          type: string
          description: The fragment's own name.
        version:
          type: string
          description: The fragment's semantic version - informative; the digest says what runs.
        enforced:
          type: boolean
          description: 'At the head of every chain: never removed, never replaced.'
    PolicyFragment:
      type: object
      description: One imported policy fragment.
      required:
      - import
      - fragment
      - version
      - digest
      - path
      - signature
      - requires
      - requires_unchecked
      - definitions
      - enforced
      - unused
      properties:
        import:
          type: string
        fragment:
          type: string
        version:
          type: string
        digest:
          type: string
          description: sha256:<hex>, the digest pinned - equal to the file's.
        path:
          type: string
          description: The file
          as flexway.yaml writes it.: null
        signature:
          type: string
          enum:
          - none
          description: 'How the file was proven beyond its digest: none in this version.'
        requires_unchecked:
          type: boolean
          description: true when the fragment requires a gateway version and a development build (dev)
            loaded it without comparing - said here and in the log, never refused.
        requires:
          type: object
          required:
          - upstreams
          properties:
            flexway:
              type: string
              description: '>=MAJOR.MINOR.PATCH, when the fragment requires one.'
            upstreams:
              type: array
              items:
                type: string
        definitions:
          type: array
          items:
            type: string
          description: The imported names, <import>/<name>.
        enforced:
          type: array
          items:
            type: string
          description: The enforced definitions
          in their order.: null
        unused:
          type: array
          items:
            type: string
          description: The imported definitions no chain names - never an error.
