Skip to content

fix(config): validate provider send paths before management writes - #4523

Draft
luvs01 wants to merge 4 commits into
lidge-jun:devfrom
luvs01:agent/provider-send-paths-20260913
Draft

luvs01 wants to merge 4 commits into
lidge-jun:devfrom
luvs01:agent/provider-send-paths-20260913

Conversation

@luvs01

@luvs01 luvs01 commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Validate provider-relative send paths at the management boundary before storing them. The validator is independent of configuration-schema initialization, so loading the management module first no longer triggers a runtimeRoleSchema temporal-dead-zone error. Existing schema exports and rejection messages remain compatible.

Current validation

  • Published head: 10801f4e9dc1c59bff1597047afd44f090db6335. The branch remains within the allowed dev-drift window; this follow-up does not rebase only to chase the tip.
  • A new fresh-process regression fails with the original runtimeRoleSchema initialization error before the fix and passes after it. Existing management validation, fresh-import and test-layout coverage passed: 155 tests, 1,649 assertions. Typecheck, structure, privacy, file-size and diff checks passed.
  • Exact-head independent CI run 34994442423 was dispatched once and is in_progress (pending). The upstream workflow requires maintainer approval to run. Prior-head success is not claimed as validation of this revision.
  • Known findings are corrected; current-head automated re-review and CI completion remain pending.

Review readiness checklist

  • All CI tests are green on my local testing.
  • I pushed my PR to the latest dev commit.
  • I resolved all correct Codex and CodeRabbit findings.
  • My PR is ready for review.

@coderabbitai

coderabbitai Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the intake: hygiene-blocked Deterministic PR hygiene checks failed label Sep 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Deterministic hygiene checks failed.

  • unsponsored_surface — This changes an authentication, workflow, release-automation, or dependency surface. MAINTAINERS.md requires security review for these; ask a maintainer to apply maintainer-sponsored once they have reviewed it. Paths: src/server/auth-cors.ts.

@github-actions github-actions Bot added the bug Something isn't working label Sep 13, 2026
@github-actions

github-actions Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • review readiness checklist open (2/4 boxes ticked).

What to do

  • Tick all four boxes in the PR description once you're done (currently 2/4).

Review readiness checklist

  • ⬜ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ⬜ My PR is ready for review.

2/4 boxes ticked.

This PR stays in draft until every box above is ticked.

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 71 / 80

이 PR은 지금 dev(HEAD df7dc1be5, package 2.54.0)에서 관리 API로 provider를 만들거나 바꿀 때 responsesPath / chatCompletionsPath가 깨진 값이어도 통과하던 구멍을 막습니다. 디스크에서 config를 읽을 때는 이미 src/config.tsproviderRelativeSendPathConfigError가 상대 경로만 허용하는데, POST /api/providers 쪽 관리 write 경계에서는 그 검사가 빠져 있어서 같은 값이 메모리·파일에 먼저 들어간 뒤 DNS/카탈로그 refresh까지 갈 수 있었습니다. 보고대로면 예전에는 잘못된 create/replace가 200을 돌려줬습니다.

고치는 방식은 새 규칙을 만들지 않고 이미 있는 검사기를 공유하는 쪽입니다. providerRelativeSendPathConfigError를 export하고, 입력이 문자열이 아니면 ``field must be a string으로 거절하게 넓힌 뒤, `src/server/auth-cors.ts`의 `providerManagementConfigError`가 destination 검사 직후·headers 검사 전에 두 필드를 돌립니다. Editor PATCH가 결과 provider를 다시 검증할 때도 남아 있는 잘못된 경로를 잡습니다. pacing-only 같은 기존 bypass는 그대로 두고, send-path를 바꾸는 새 PATCH 필드는 추가하지 않습니다.

테스트가 이 PR의 핵심입니다. tests/server/management-provider-validation.test.ts에 management write 경계 그룹을 넣어서 잘못된 값이 메모리/디스크를 바꾸기 전에 400이 나고, DNS·catalog refresh가 호출되지 않는지, 올바른 /custom/... 경로는 persist/reload 되는지까지 실제 handleManagementAPI로 확인합니다. 문서도 8개 언어 providers 참고서와 structure/config.md의 Provider relative send paths 절, 여러 structure 맵 링크를 같이 맞췄습니다. types.ts/config.ts 분할 캠페인과 충돌하지 않는 독립 수정입니다.

지금 dev 방향(웹검색 패스스루 브릿지, desktop restart, reasoning ladder)과는 축이 다르지만, 관리 API로 잘못된 send path가 살아 남는 건 운영·보안 경계 문제라 우선순위는 높습니다. 구조 맵에 같은 한 줄을 여러 파일 맨 위에 반복한 부분은 약간 시끄럽지만, 계약 추적용으로는 이해됩니다.

라인 - src/config.ts providerRelativeSendPathConfigError - 예전 시그니처는 string | undefined만 받았고 관리 JSON의 number/null/object는 타입 밖으로 새어 들어갈 수 있었다. 이번 export + unknown 가드가 그 구멍을 막는다.
라인 - src/server/auth-cors.ts providerManagementConfigError - destination 검사 뒤에 send-path를 넣었다. 순서는 맞지만, destination DNS가 비싸다면 send-path를 더 앞에 두는 편이 실패 빠르게 끝날 수 있다(지금은 테스트가 DNS mock을 안 부르게 막아 둔 상태).
경로/심볼 - PATCH + 이미 깨진 live row - 본문이 말한 대로 send-path setter는 없고, 다른 필드 PATCH 때 retained path를 재검증해 400으로 막는다. 레거시 깨진 값을 GUI에서 고치는 UX는 이 PR 범위 밖이다.
경로/심볼 - structure/*.md 상단 반복 링크 - catalog/images/runtime 등 관련 약한 맵까지 같은 문장이 들어갔다. 계약 추적은 되지만 노이즈가 크다.
경로/심볼 - CI - 로컬 typecheck/structure/privacy와 focused 9+137 테스트는 통과했다고 했으나 full cross-platform CI는 이 head에서 아직이다.

메인테이너의 판단이 필요한 지점

  • 이미 디스크에 남아 있는 잘못된 send-path row를 마이그레이션/경고로 드러낼지, PATCH 거절만으로 충분할지
  • structure 맵 전면 링크를 유지할지, structure/config.md + gui-and-management-api만 남길지
  • send-path 검사를 destination보다 앞으로 당겨 실패 비용을 줄일지

너의 추천
tip CI 초록 확인 후 merge 후보로 본다. 범위가 작고 회귀 테스트가 실제 management handler를 치므로 독립 랜딩이 맞다. structure 노이즈는 후속 정리로 미뤄도 된다.

이 댓글은 grok-bot이 작성했습니다

@luvs01

luvs01 commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Author follow-up on the Cross-platform CI failure for this head.

The failing shard is Windows 5/6, and all nine failures come from tests/clients/desktop-app-restart-posix.test.ts. None of them touch this PR: the change here is confined to provider send-path validation, its management-boundary test, and documentation. The Ubuntu and macOS shards passed.

The failure reproduces on a Windows host at current dev with no local changes, so it is a pre-existing condition on the branch rather than a regression introduced here. Two independent causes: isUnderRoot derives its boundary from path.sep alone, so a member path written with forward slashes reads as outside the install root on Windows; and the macOS and Linux adapters scope enumeration through process.getuid(), which a Windows host does not provide, so the probe reports that it could not run.

I opened a separate fix for that so it is not mixed into this PR. Once it lands, this head should be re-run before any readiness claim. This PR is also beyond the latest-dev tolerance, so it stays Draft until a coordinated rebase.

@luvs01
luvs01 force-pushed the agent/provider-send-paths-20260913 branch 2 times, most recently from 47537ac to 3dc6d47 Compare September 14, 2026 01:07
@luvs01

luvs01 commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto latest dev and updated the readiness checklist. Two follow-ups on the gate state.

Hygiene gate needs a maintainer decision, not an author change. PR hygiene fails with unsponsored_surface because this PR touches src/server/auth-cors.ts, which .github/scripts/pr-sponsored-surface.cjs lists as a restricted authentication surface. The touch there is three lines: it imports providerRelativeSendPathConfigError and calls it for responsesPath and chatCompletionsPath inside the existing providerManagementConfigError validation chain, immediately after the destination check. No authentication, credential, CORS, or admission logic is read or modified, and the provider name is passed through the existing redactSecretString before it reaches a message. The validator itself lives in src/config.ts.

The reason it has to be called from that file is the point of the change: providerManagementConfigError is the single boundary the management write path runs, so a send-path override that src/config.ts would reject on load could previously be stored through the management API and only fail later at send time. Moving the call elsewhere would reintroduce that gap.

Could a maintainer review the auth-surface touch and apply maintainer-sponsored if it looks right? I cannot apply that label as the author, and it is the only thing keeping this PR in Draft.

Superseding my earlier CI note. The comment above about the Windows shard and the latest-dev tolerance is resolved. This head is rebased onto dev at 15fbd49f3 with no conflicts, and the Windows failures I reported there were the dev regression in tests/clients/desktop-app-restart-posix.test.ts, fixed separately in #4564.

Local verification on the published head 3dc6d474d: bun run typecheck, bun run structure:check, bun run privacy:scan and git diff --check pass; bun test tests/server/management-provider-validation.test.ts reports 137 pass / 0 fail; the docs-site build completes 441 pages and the generated docs-site/dist was removed afterward.

@luvs01
luvs01 force-pushed the agent/provider-send-paths-20260913 branch from 3dc6d47 to c8f7030 Compare September 14, 2026 06:04
@lidge-jun

Copy link
Copy Markdown
Owner

Sponsoring. .github/scripts/pr-sponsored-surface.cjs lists src/server/auth-cors.ts as a restricted surface, so enforce-target and hygiene fail with unsponsored_surface until a maintainer reviews it. This comment is that review.

The whole restricted-path change is one import and four lines inside the existing providerManagementConfigError chain, placed after the destination check:

for (const field of ["responsesPath", "chatCompletionsPath"] as const) {
  const sendPathError = providerRelativeSendPathConfigError(field, raw[field]);
  if (sendPathError) return `provider ...`;
}

No authentication, credential, CORS or admission logic is read or modified. The file is restricted because it hosts the provider management validator, not because this change goes near auth. Two things I checked rather than assumed: the new branch is the only one in that chain that redacts the provider name before interpolating it, which is inconsistent with its neighbours but errs safe; and the widening of leaf-validators.ts to unknown with a non-string rejection is fail-closed.

Applying maintainer-sponsored.

@lidge-jun lidge-jun added the maintainer-sponsored Maintainer sponsors this change to an auth, workflow, release, or dependency surface label Sep 15, 2026
@github-actions github-actions Bot removed the intake: hygiene-blocked Deterministic PR hygiene checks failed label Sep 15, 2026
…lization

Move the shared shape validator into an import-free config leaf and retain the schema export. The management boundary no longer enters config initialization through the schema before the facade can initialize its dependencies.

A fresh-process regression fails with the runtimeRoleSchema TDZ before this fix. The management, import and layout checks pass: 155 tests, 1649 assertions. Typecheck, structure, privacy and file-size checks pass. Full hosted CI remains a separate publication gate.
@luvs01

luvs01 commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

The corrective follow-up is published at 10801f4e9dc1c59bff1597047afd44f090db6335. The description records the failed-before/passed-after regression and current validation.

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 15, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-15T16:31:58.416218Z 10801f4 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 10801f4e9d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working maintainer-sponsored Maintainer sponsors this change to an auth, workflow, release, or dependency surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants