Skip to content

fix(ai-gateway): merge request and organization privacy with deny precedence - #6696

Merged
chrarnoldus merged 11 commits into
mainfrom
fix/gateway-effective-privacy-settings
Sep 25, 2026
Merged

chrarnoldus merged 11 commits into
mainfrom
fix/gateway-effective-privacy-settings

Conversation

@chrarnoldus

@chrarnoldus chrarnoldus commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Preparatory PR for #6681, independently based on main. The shared getEffectiveProviderPrivacy and providerPrivacySchema helpers validate and merge request and organization privacy in one place. Each endpoint now sends only the privacy fields its upstream actually supports.

  • Merge rule: data_collection: deny wins if either the request or the organization denies collection. Request zdr is preserved independently.
  • Organization and group provider overrides carry the same privacy; their non-privacy semantics are unchanged.
  • Chat completions, Responses, Messages: privacy is normalized before Auto resolution and provider selection. It goes to OpenRouter as provider.data_collection / provider.zdr, which OpenRouter documents for these endpoints (ZDR per-request enforcement).
  • Embeddings: merged privacy goes to OpenRouter in provider, which OpenRouter documents for /embeddings. For Vercel BYOK it is translated into providerOptions.gateway.zeroDataRetention/disallowPromptTraining.
  • TypeSafe: only validated privacy fields are accepted and merged into the provider sent to OpenRouter /systemone. Client routing, credential, and identity overrides are still stripped.
  • Transcriptions: the gateway no longer sends a provider object upstream. OpenRouter's Create transcription reference lists no provider field for multipart. For JSON, provider is limited to options, a provider-specific passthrough. Routing and privacy preferences (only, order, ignore, data_collection, zdr) are not supported there. The organization/group model-access gate still applies.
  • The shared organization restriction handling reuses the helper instead of duplicating the data_collection mapping.

Intentional Behavior Changes

  • Organization allow no longer weakens a request deny, and organization/group overrides no longer discard request ZDR. Managed gateway restrictions are cumulative.
  • On chat completions, Responses, Messages, embeddings, and TypeSafe, invalid provider.data_collection/provider.zdr values now return 400 instead of being silently forwarded or ignored.
  • Transcriptions no longer send organization provider_allow_list (only) or data_collection upstream; main did before this PR. OpenRouter does not document these fields for the endpoint, so this removes the appearance of enforcement, not actual enforcement. A client-supplied JSON provider object is still passed through unchanged and is not validated, matching main.

Boundaries

  • The existing bypassAccessCheck access-policy gating is unchanged. Bypass routes get no extra restoration of the request provider property; native providers keep their own request handling.
  • Direct FIM/edit APIs have no equivalent per-request gateway privacy interface and are unchanged. Their existing organization behavior is preserved, and this PR does not claim new privacy enforcement for them.
  • Catalog/validation endpoints perform no inference and need no request merge.
  • No Auto candidate filtering or training metadata from fix(ai-gateway): respect data policies in auto model selection #6681 is included.
  • No new settings fetches or timeout handling.

Verification

  • 170daceef: chat, embeddings, transcription, TypeSafe, provider-privacy, and llm-proxy-helpers suites pass (8 suites, 256 tests). Redundant per-endpoint privacy matrices were trimmed; the full merge table lives in provider-privacy.test.ts. apps/web typecheck (tsgo), oxfmt, and oxlint pass on the changed files.
  • Earlier, at 0d8d36f35: an isolated real-HTTP E2E matrix passed 105/105 cases across chat, Responses, Messages, embeddings, transcription JSON/multipart, and TypeSafe. The loopback capture upstream replaced only the external AI provider, with gateway auth, settings, and privacy merging not mocked. The supporting route/schema regression run passed 398/398. The transcription privacy rows of that matrix covered behavior this PR has since removed. Since then, the other surfaces have changed only through the CI type fix in 4d53eb5c3, the behavior-preserving embeddings refactor in 3f87750e7, and the test trimming in 170daceef.
  • The HTTP matrix used synthetic upstream responses. It does not establish live-provider data-retention behavior, and it did not cover streaming, Auto selection, BYOK/Vercel conversion, or asynchronous billing persistence end to end.

@chrarnoldus chrarnoldus self-assigned this Sep 24, 2026
@kilo-code-bot

kilo-code-bot Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental range 3f87750e7..170daceef is test-only (4 test files that trim redundant per-endpoint privacy matrices). The retained expectations still match current source behavior, no imports or fixtures were orphaned by the trims, and no new defects were found.

Files Reviewed (4 files)
  • apps/web/src/app/api/openrouter/[...path]/route.test.ts
  • apps/web/src/app/api/openrouter/embeddings/route.test.ts
  • apps/web/src/lib/ai-gateway/typesafe/handler.test.ts
  • apps/web/src/lib/ai-gateway/typesafe/schemas.test.ts
Previous Review Summaries (8 snapshots, latest commit 3f87750)

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

Previous review (commit 3f87750)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Incremental follow-up 3f87750e7 reads organization data_collection directly in the embeddings proxy and relaxes the transcription JSON provider field to an unvalidated passthrough record; the changed lines are behavior-preserving or intentional and contain no new defects.

Files Reviewed (3 files)
  • apps/web/src/app/api/openrouter/embeddings/route.ts
  • apps/web/src/lib/ai-gateway/transcriptions/transcription-request.ts
  • apps/web/src/lib/ai-gateway/transcriptions/transcription-request.test.ts

Previous review (commit 6ee8f2f)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

Follow-up 6ee8f2ffa stops forwarding provider policy/privacy on transcription requests, removing organization data_collection: deny enforcement (and enterprise provider_allow_list routing) that existed on main, so a JSON client's own provider object now passes through unmerged.

Overview

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

WARNING

File Line Issue
apps/web/src/app/api/openrouter/audio/transcriptions/route.ts 316 Transcription requests no longer forward effective provider privacy; organization data_collection: deny is not enforced and a JSON client's provider is passed through unmerged.
Files Reviewed (2 files)
  • apps/web/src/app/api/openrouter/audio/transcriptions/route.ts - 1 issue
  • apps/web/src/app/api/openrouter/audio/transcriptions/route.test.ts - 0 issues

Fix these issues in Kilo Cloud

Previous review (commit 9c647c7)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental baseline edc14a774 is not an ancestor of HEAD, so this run reviewed the full current PR diff (15 files) against main at 59b57e56a. The shared getEffectiveProviderPrivacy/providerPrivacySchema implement deny-wins merging while preserving request zdr across chat, embeddings, transcription, and TypeSafe paths, and the previously flagged organization data_collection injection is resolved on the existing inline thread. No new issues found.

Files Reviewed (15 files)
  • apps/web/src/app/api/openrouter/[...path]/route.ts
  • apps/web/src/app/api/openrouter/[...path]/route.test.ts
  • apps/web/src/app/api/openrouter/audio/transcriptions/route.ts
  • apps/web/src/app/api/openrouter/audio/transcriptions/route.test.ts
  • apps/web/src/app/api/openrouter/embeddings/route.ts
  • apps/web/src/app/api/openrouter/embeddings/route.test.ts
  • apps/web/src/lib/ai-gateway/llm-proxy-helpers.ts
  • apps/web/src/lib/ai-gateway/provider-privacy.ts
  • apps/web/src/lib/ai-gateway/provider-privacy.test.ts
  • apps/web/src/lib/ai-gateway/transcriptions/transcription-request.ts
  • apps/web/src/lib/ai-gateway/transcriptions/transcription-request.test.ts
  • apps/web/src/lib/ai-gateway/typesafe/handler.ts
  • apps/web/src/lib/ai-gateway/typesafe/handler.test.ts
  • apps/web/src/lib/ai-gateway/typesafe/schemas.ts
  • apps/web/src/lib/ai-gateway/typesafe/schemas.test.ts

Previous review (commit edc14a7)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Follow-up edc14a774 restores the requestBodyText Sentry extra field for malformed-JSON and schema-validation transcription failures as a [REDACTED] placeholder plus requestBodyLength, so raw bodies are never sent to Sentry. The two added lines are safe and introduce no new issues.

Files Reviewed (1 file)
  • apps/web/src/app/api/openrouter/audio/transcriptions/route.ts

Previous review (commit 4d53eb5)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Follow-up commit 4d53eb5c3 validates the selected embeddings provider with the shared privacy schema before reading data_collection, resolving the CI type error without changing effective-privacy semantics. No new issues were found in the changed lines.

Files Reviewed (1 file)
  • apps/web/src/app/api/openrouter/embeddings/route.ts

Previous review (commit 0d8d36f)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Follow-up commit 0d8d36f35 simplifies privacy composition in the chat, embeddings, and transcription routes into semantically equivalent expressions, and removes the bypassAccessCheck provider restoration as an intentional, requester-approved behavior change already reconciled on the existing inline thread. No new issues were found in the changed lines.

Files Reviewed (4 files)
  • apps/web/src/app/api/openrouter/[...path]/route.ts
  • apps/web/src/app/api/openrouter/[...path]/route.test.ts
  • apps/web/src/app/api/openrouter/audio/transcriptions/route.ts
  • apps/web/src/app/api/openrouter/embeddings/route.ts

Previous review (commit d979e27)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit resolves the prior bypassAccessCheck organization-privacy injection by restoring the original request provider after provider selection, and the new privacy normalization across chat, transcription, embeddings, and TypeSafe paths is consistent with deny-wins semantics; no new issues found in the changed lines.

Files Reviewed (14 files)
  • apps/web/src/app/api/openrouter/[...path]/route.ts
  • apps/web/src/app/api/openrouter/[...path]/route.test.ts
  • apps/web/src/app/api/openrouter/audio/transcriptions/route.ts
  • apps/web/src/app/api/openrouter/audio/transcriptions/route.test.ts
  • apps/web/src/app/api/openrouter/embeddings/route.ts
  • apps/web/src/app/api/openrouter/embeddings/route.test.ts
  • apps/web/src/lib/ai-gateway/provider-privacy.ts
  • apps/web/src/lib/ai-gateway/provider-privacy.test.ts
  • apps/web/src/lib/ai-gateway/transcriptions/transcription-request.ts
  • apps/web/src/lib/ai-gateway/transcriptions/transcription-request.test.ts
  • apps/web/src/lib/ai-gateway/typesafe/handler.ts
  • apps/web/src/lib/ai-gateway/typesafe/handler.test.ts
  • apps/web/src/lib/ai-gateway/typesafe/schemas.ts
  • apps/web/src/lib/ai-gateway/typesafe/schemas.test.ts

Previous review (commit 516a6d4)

Status: 1 Issue Found | Recommendation: Address before merge

Fix: Fix these issues in Kilo Cloud

Executive Summary

The privacy normalization correctly implements deny-wins merging and preserves request ZDR, but applying it before provider selection now injects organization data_collection into direct-BYOK and custom-LLM requests that are documented to bypass organization policy.

Overview

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

WARNING

File Line Issue
apps/web/src/app/api/openrouter/[...path]/route.ts 347 Organization data_collection is injected into body.provider for bypassAccessCheck direct-BYOK/custom-LLM routes, which previously skipped organization policy.
Files Reviewed (5 files)
  • apps/web/src/app/api/openrouter/[...path]/route.ts - 1 issue
  • apps/web/src/app/api/openrouter/[...path]/route.test.ts - 0 issues
  • apps/web/src/lib/ai-gateway/llm-proxy-helpers.ts - 0 issues
  • apps/web/src/lib/ai-gateway/provider-privacy.ts - 0 issues
  • apps/web/src/lib/ai-gateway/provider-privacy.test.ts - 0 issues

Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0

Review guidance: REVIEW.md from base branch main

@chrarnoldus
chrarnoldus force-pushed the fix/gateway-effective-privacy-settings branch from edc14a7 to 4d53eb5 Compare September 25, 2026 06:38
@chrarnoldus chrarnoldus changed the title fix(ai-gateway): resolve privacy preferences before routing fix(ai-gateway): apply effective privacy only where upstreams support it Sep 25, 2026
@chrarnoldus chrarnoldus changed the title fix(ai-gateway): apply effective privacy only where upstreams support it fix(ai-gateway): merge request and organization privacy with deny precedence Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants