# Trusted OpenAI State Ownership
# Requires `--features openai-conversations,store-sqlite` because these filters are opt-in.
#
# Provider-neutral owner isolation for persisted OpenAI Responses and Conversations.
# A trusted authentication boundary must replace (not merely preserve) the
# configured header before traffic reaches this listener. Direct untrusted
# access to this listener would let a caller forge an owner assertion.
#
# The assertion wire format is:
#
#   x-authenticated-state-owner: v1.<base64url-no-padding(JSON [tenant, issuer, subject])>
#
# The three strings form one immutable storage owner. Subjects are not assumed
# to be globally unique, so tenant and issuer are always part of the key. The
# filter validates the assertion, installs request-local ownership context, and
# strips the transport header before any upstream request is sent.
#
# This enforces resource ownership only. It does not evaluate authorization
# policy. A later policy integration can decide whether the authenticated owner
# may perform an operation, without changing the storage ownership contract.
#
# `single_tenant` is available only when the whole deployment is one trust
# domain: it assigns every caller the same tenant, issuer, and `shared` subject,
# so it cannot provide per-user attribution, cache separation, or state
# isolation. Shared multi-user deployments must use `trusted_owner` as below
# (or `trusted_headers` when the trusted boundary supplies separate fields).

listeners:
  - name: ai-gateway
    address: "127.0.0.1:8080"
    filter_chains: [owned-state-pipeline]

filter_chains:
  - name: owned-state-pipeline
    filters:
      - filter: state_owner
        mode: trusted_owner
        header: x-authenticated-state-owner

      # Publishes the typed operation consumed by openai_conversations.
      - filter: openai_operation

      - filter: openai_responses_request
        # Only POST /v1/responses reaches this filter, so Conversations API
        # bodies pass through untouched to their handler later in this chain.
        # on_invalid still governs malformed create bodies.
        on_invalid: continue

      - filter: openai_response_store
        backend: sqlite
        database_url: "sqlite://owned-state.db?mode=rwc"
        responses_table: openai_responses
        conversations_table: openai_conversations

      - filter: openai_responses_rehydrate

      - filter: openai_conversations
        backend: sqlite
        database_url: "sqlite://owned-state.db?mode=rwc"
        conversations_table: openai_conversations
        items_table: openai_conversation_items

      - filter: router
        routes:
          - path_prefix: "/"
            cluster: "inference-backend"

      - filter: load_balancer
        clusters:
          - name: "inference-backend"
            endpoints:
              - "127.0.0.1:8000"

insecure_options:
  allow_private_endpoints: true # example proxies to a local backend
