service:
  name: kb-query
  owner_node: piha
  role: kb-search-api            # module 5 phase 4: first user-facing HTTP entry point to the KB (API + minimal search UI, plan §7)
  exposure: private               # LAN/Tailscale only, npm@PIHA vhost (kb.kapala.org) is a later step
  dependencies:
    - kb-postgres
    - ollama-piha                 # soft: local CPU embed fallback (Krok 2) -- kb-query starts without it
    - forgejo                     # OIDC identity provider, wired in a later step (plan §8); not yet enforced
  # ollama@SOLARIA is an external, optional runtime dependency (primary embed backend), not
  # a hard dependency here -- SOLARIA sleeps ~16 h/day; the embed router (app/embed_router.py)
  # then falls back to ollama-piha on this host. /search 503s only when BOTH legs are down;
  # /healthz always answers (same tolerance pattern as llm-gateway).
  ports:
    - container: 8080
      host: 8230                  # LAN_BIND_IP only, never 0.0.0.0
      protocol: tcp
  healthcheck:
    type: http
    endpoint: http://192.168.31.5:8230/healthz   # LAN bind — localhost does not answer
    interval: 30s
    timeout: 10s
    retries: 5
  restart_policy: unless-stopped
  persistence:
    paths: []                     # stateless — kb-postgres holds all state
  runtime:
    config_files:
      - .env                      # KB_DSN, LAN_BIND_IP (gitignored, from env.example)
    env_vars:
      - LAN_BIND_IP                # required — compose port-bind interpolation
      - KB_DSN                     # required — asyncpg DSN for kb-postgres@PIHA
      - EMBED_PRIMARY_URL          # optional — primary embed backend, defaults to http://solaria:11434
      - EMBED_FALLBACK_URL         # optional — local fallback (ollama-piha); empty disables the fallback leg
      - EMBED_PRIMARY_NAME         # optional — log/response label, defaults to solaria
      - EMBED_FALLBACK_NAME        # optional — log/response label, defaults to piha
      - EMBED_HEALTH_TTL_S         # optional — primary health verdict cache, defaults to 30
      - EMBED_HEALTH_TIMEOUT_S     # optional — /api/tags probe timeout, defaults to 1.5
      - EMBED_PRIMARY_TIMEOUT_S    # optional — hard timeout for a primary embed call, defaults to 3
      - EMBED_MODEL                 # optional — defaults to bge-m3; startup invariant vs document_chunk/document_summary + per-backend /api/tags check
      - SUMMARY_MODEL               # optional — defaults to claude-haiku-4-5; cascade stage-1 model
