Skip to content

fix(ai-gateway): bound and normalize opt-out model entries at the admin write boundary - #8725

Merged
iscekic merged 4 commits into
mainfrom
drain/gateway-routing-input-bounds
Oct 24, 2026
Merged

iscekic merged 4 commits into
mainfrom
drain/gateway-routing-input-bounds

Conversation

@iscekic

@iscekic iscekic commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

Evidence

Evidence: demonstrated — the admin write contract was compared with both read schemas over one stored routing value, and the admin Gateway routing form was driven in Chromium on the local dev stack with an owned fake admin account: a submission beyond the entry limit renders the field error inline and writes no row, and a valid list saves, normalizes, and reloads from Postgres in that form. Captures are scoped to the routing card, and the card text was checked for excluded-feature content before capture.

Change

  • GatewayConfigInputSchema.vercel_routing_opt_out_models now requires trimmed, non-empty entries of at most VERCEL_ROUTING_OPT_OUT_MODEL_MAX_LENGTH (200) characters, caps the list at VERCEL_ROUTING_OPT_OUT_MODELS_MAX_COUNT (200), lowercases entries, and collapses duplicates. Every accepted input therefore parses with GatewayConfigSchema and GatewayRoutingConfigSchema.
  • The admin set mutation stores the validated list as-is: the write schema is the single place that defines the stored form, and the router no longer carries its own normalization.
  • The routing form validates its submission with the same schema before mutating, renders a rejected entry in the existing admin validation block (pre with role="alert"), and reports server-side rejection through formatZodError.

Tests

  • packages/web-shared/src/lib/ai-gateway/gateway-config.test.ts: blank and whitespace entries, an over-length entry, and an over-count list are refused; an entry at the length boundary is accepted; entries are trimmed, lowercased, and collapsed; an accepted input round-trips through both read schemas.
  • apps/web/src/routers/admin/gateway-config-router.test.ts: set stores the normalized list, get returns it, and a refused input writes nothing.
  • pnpm --filter @kilocode/web-shared typecheck, pnpm --filter web typecheck, oxlint and oxfmt on the changed paths, and both jest suites (23 tests).

Proxy answers

  1. Question: Which bounds should the admin write schema enforce on the opt-out model list?
    Answer: 200 entries, 200 characters each.
    Confidence: 0.75
  2. Question: Should the two read schemas also gain trim and length bounds?
    Answer: Leave the read schemas permissive.
    Confidence: 0.60
  3. Question: Where should trim, lowercase, and de-duplication live?
    Answer: In the input schema, with the router dropping its own normalization.
    Confidence: 0.75

…rite schema

The admin set-mutation input now applies the same element rule the stored and hot-path readers require, and owns the stored form of the list: trimmed, lowercase, non-empty, length-bounded, capped, and duplicate-free.
The routing form validates its submission with the write schema before the mutation and renders the field error in the admin validation block; a rejected request shows the server's field message.
Adds schema cases for blank, over-length, and over-count entries, duplicate collapsing, and a round-trip through both read schemas, plus a router case that a refused input writes nothing.
@iscekic iscekic added drain Work item from the findings drain janitor:trust Janitor finding: trust boundary hardening labels Oct 23, 2026
@iscekic

iscekic commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Verified the admin Gateway routing form on the local dev stack with an owned fake admin account.

  • A submission with an entry beyond the per-entry limit renders the field error inline and writes no configuration row.
  • A valid multi-line list saves once, normalizes its entries, and reloads from Postgres in that form.

Both captures are scoped to the routing card; the card text was checked for excluded-feature content before capture.

Routing form showing the inline field error for an over-limit entry

Routing form after a successful save showing the normalized stored list

@kilo-code-bot

kilo-code-bot Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit only relocates the opt-out validation alert into its field section and wires aria-describedby/aria-invalid; the change is correct and resolves the prior accessibility finding.

Assumptions: Targeted verification only for unchanged files from the prior review; no test suite or dev stack was available to execute in this read-only session.

Files Reviewed (1 file)
  • apps/web/src/app/admin/gateway/RoutingContent.tsx
Previous Review Summary (commit 71d3d2b)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 71d3d2b)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

The bounds and normalization added around the admin routing write boundary are sound and covered by tests; the only finding is that the new form validation error is not associated with the opt-out field it describes.

Assumptions: Zod 4 string-transform ordering (trim().toLowerCase() before min(1)/max(200)) was verified indirectly via existing repo schemas/tests of the same shape (inference-provider-id.test.ts) since node_modules is not installed here; whitespace-rejection and round-trip tests were not executed.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
apps/web/src/app/admin/gateway/RoutingContent.tsx 143 Validation alert sits below the Note field and is not connected to the opt-out textarea via aria-describedby
Files Reviewed (5 files)
  • apps/web/src/app/admin/gateway/RoutingContent.tsx - 1 issue
  • apps/web/src/routers/admin/gateway-config-router.ts - 0 issues
  • apps/web/src/routers/admin/gateway-config-router.test.ts - 0 issues
  • packages/web-shared/src/lib/ai-gateway/gateway-config.ts - 0 issues
  • packages/web-shared/src/lib/ai-gateway/gateway-config.test.ts - 0 issues

Fix these issues in Kilo Cloud


Reviewed by deepseek-flash-latest · Input: 24.3K · Output: 1.4K · Cached: 112.4K

Review guidance: REVIEW.md from base branch main

The validation block now renders inside the opt-out section, and the textarea advertises the error through aria-describedby and aria-invalid.
@iscekic

iscekic commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Updated capture after the review fix (a34301c): the field error now renders inside the opt-out section, and the textarea advertises it through aria-describedby and aria-invalid. Same local dev stack, same owned fake admin account; capture scoped to the routing card and checked for excluded-feature content.

Routing form with the field error attached to the opt-out list input

@iscekic iscekic added merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. intent:ok Janitor change confirmed as a real bug fix, not intended behavior labels Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

drain Work item from the findings drain intent:ok Janitor change confirmed as a real bug fix, not intended behavior janitor:trust Janitor finding: trust boundary hardening merge:bot Bot-owned review; merge when ready once readiness passes and a review approves.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants