Files
homelab-frontend/tasks/2.15-dialect-scope-boundary.md
T
Story Crater BotandClaude Opus 5 058f11cf2b
CI / Test (push) Canceled after 0s
CI / Vet (push) Canceled after 0s
CI / Build (push) Canceled after 0s
CI / Security (govulncheck) (push) Canceled after 0s
chore: initial commit of Go API gateway
Baseline for the Kong replacement on api.riotpiao.com. Brings the working
tree under version control for the first time: gateway source, the task
board that drives the agent runs, test fixtures, and K8s manifests.

Anchor the gateway ignore rule to the repo root. Unanchored, "gateway"
also matched the cmd/gateway/ source directory, so the program entrypoint
was excluded from every commit.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-19 20:54:34 -07:00

2.7 KiB

2.15 — Anthropic dialect scope boundary (GREEN)

Phase: 2 — LLM surfaces Stage: GREEN Depends on: 2.10, 2.13

The only client of /llm/* is the first-party riotpiao frontend. It is not Claude Code and not the Anthropic SDK, so the surface implements a deliberately narrow slice of the Messages API. The narrowness is the design; the risk is a half-built feature that appears to work.

  • The unsupported set is enumerated in one place and covers at least: tools and tool_choice, tool_use blocks, tool_result turns, image content blocks, prompt-caching controls and cache headers, the batch API, and user messages carrying more than one content block
  • Each unsupported feature is detected during request translation, before any upstream is contacted
  • Rejection uses the Anthropic error shape {"type":"error","error":{"type":"invalid_request_error","message":"..."}} and the message names the specific unsupported feature, not just "unsupported"
  • No unsupported feature is silently ignored, stripped, or partially honoured; a request containing one never produces a 200
  • A request combining a supported and an unsupported field is rejected, not serviced with the unsupported part dropped
  • The /v1/* OpenAI surface is unaffected: tool calling continues to work there exactly as it does today
  • Every entry in the unsupported set has a test asserting the rejection, so widening scope forces a deliberate test change rather than a quiet code change
  • The list is documented on the surface, so the frontend can see the boundary without reading gateway code

Enabling any of these later must be an explicit config or code change accompanied by its own translation work and tests. A silent partial implementation is the specific failure this task exists to prevent.

Verify

curl -s localhost:8080/llm/v1/messages -H 'content-type: application/json' \
  -d '{"model":"reasoning","max_tokens":8,"tools":[{"name":"x"}],"messages":[{"role":"user","content":"hi"}]}'
# expected: 4xx, error.message names tools, no upstream stub hit

curl -s localhost:8080/llm/v1/messages -H 'content-type: application/json' \
  -d '{"model":"reasoning","max_tokens":8,"messages":[{"role":"user","content":[{"type":"image","source":{}}]}]}'
# expected: 4xx, error.message names image content blocks, no upstream stub hit

curl -s -o /dev/null -w '%{http_code}\n' localhost:8080/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{"model":"reasoning","messages":[{"role":"user","content":"hi"}],"tools":[{"type":"function","function":{"name":"x"}}]}'
# expected: 200, tool calling still works on the OpenAI surface