Skip to content

fix(codex): preserve request-owned main pins - #3166

Merged
lidge-jun merged 1 commit into
devfrom
ingw/fix-request-owned-main-pin-3157
Sep 1, 2026
Merged

fix(codex): preserve request-owned main pins#3166
lidge-jun merged 1 commit into
devfrom
ingw/fix-request-owned-main-pin-3157

Conversation

@Ingwannu

@Ingwannu Ingwannu commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • honor an effective, healthy manual __main__ pin when a Pool-mode request carries its own forwardable Codex bearer
  • validate that caller credential's account-gated model roster before using it
  • preserve the shared main pin when an unentitled caller needs a stored-account model-only detour
  • keep paused or quota-drained main accounts on the ordinary Pool promotion path
  • document the request-owned credential and pin boundary in the OpenAI account-mode SOT

Root cause

Request-owned Codex credentials are deliberately excluded from stored-account entitlement discovery and physical-main reads. During a gated Pool request, the shared-selection path interpreted that deliberate exclusion as evidence that the manually pinned main account was dead. It cleared activeCodexAccountPinned, persisted the stored Pool account, and dispatched to it even when cached quota showed main at 16% and that Pool account at 100%.

Trust boundary

This patch does not persist the caller bearer, add it to Pool affinity/health/entitlement state, or read the physical main credential. It uses the existing forwardable-bearer admission check, the effective manual pin, pause state, cached quota, and the caller credential's own authenticated gated-model check. If that check denies the model, routing may use an entitled stored-account detour while leaving the healthy shared pin intact.

Because this changes authentication/credential selection, explicit maintainer security review is required before merge.

Relation to #3135

#3135 handles the bounded alternate after a stored Pool credential is rejected. This PR fixes the earlier initial-selection/persistence boundary: a healthy explicit main pin should not be replaced by an already-exhausted stored account before the first send. The two changes are complementary and may need a small rebase conflict resolution if #3135 lands first.

Verification

Exact head 17f01162ad404f1bcee7d7f00998fc0e143365e5:

  • bun test tests/codex-auth-context.test.ts — 68 passed, 0 failed
  • focused [Bug]: quota routing replaces healthy main pin with a weekly-exhausted pool account in 2.39.0 #3157 cases cover healthy main 16% vs Pool 100%, drained main 100% vs healthy Pool, and caller entitlement denial with a model-only detour
  • bun run typecheck reports the same three pre-existing fetch(..., { timeout }) errors as an unmodified current-dev worktree; this diff adds no type errors
  • git diff --check — passed
  • all local runs used isolated HOME, OPENCODEX_HOME, and CODEX_HOME, nice -n 10, and two-CPU affinity

Full exact-head CI, privacy checks, and explicit credential-boundary review remain required before merge.

Closes #3157.

@Ingwannu
Ingwannu requested a review from lidge-jun as a code owner September 1, 2026 15:42
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Sep 1, 2026
@lidge-jun
lidge-jun merged commit 75090d4 into dev Sep 1, 2026
39 of 41 checks passed
@lidge-jun
lidge-jun deleted the ingw/fix-request-owned-main-pin-3157 branch September 1, 2026 16:04
@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 75 / 80

설명

이 PR은 이슈 #3157을 고칩니다. Pool 모드 요청이 자기 forwardable Codex 베어러를 들고 있고, 수동 __main__ 핀이 살아 있으며, 캐시 쿼터가 main에 여유가 있으면 그 핀을 지우고 소진된 저장 계정으로 갈아타지 않게 합니다. 지금 HEAD 2f2629f27 기준 베이스 dev, 브랜치 ingw/fix-request-owned-main-pin-3157, MERGEABLE, +150/−2 입니다. 파일은 src/codex/auth-context.ts, structure/08_openai-provider-tiers.md, tests/codex-auth-context.test.ts 입니다. types/config 분할과 무관합니다.

루트 원인 설명은 본문이 정확합니다. 요청 소유 자격은 저장 계정 entitlement·물리 main 읽기에서 빠집니다. 게이트된 Pool 선택이 그 빠짐을 main 사망으로 해석해 activeCodexAccountPinned 을 지웠습니다. 패치는 유효하고 건강한 수동 핀을 존중하고, 그 caller 자격의 계정 게이트 모델 roster를 확인한 뒤에만 쓰고, entitlement 없는 caller가 저장 계정 model-only 우회가 필요할 때는 공유 핀을 보존하며, pause/소진 main은 기존 Pool 승격 경로로 둡니다. 새 헬퍼 requestOwnedMainPinHasQuotaHeadroom 은 물리 auth.json을 읽지 않고 캐시 WHAM 사용량만 보며, unknown-plan 보수 규칙으로 헤드룸을 판단합니다.

신뢰 경계도 본문에 적혀 있습니다. caller 베어러를 persist하지 않고, Pool affinity/health/entitlement 상태에 넣지 않으며, 물리 main 자격도 읽지 않습니다. 기존 forwardable-bearer admission과 effective manual pin, pause, cached quota만 씁니다. #2847 request-scoped native main, #2845 drain, #3110 exhausted ranking 위에 얹히는 핀 보존 패치입니다. 인접 #3135 는 풀 거절 후 caller main alternate 이며 같은 파일을 만집니다. 충돌 나면 #3157 재현(핀 persist 소실)을 먼저 지키는 쪽이 사용자 피해가 큽니다.

테스트는 auth-context에 요청 소유 핀 보존·소진 시 승격·unentitled detour 핀 보존 케이스를 더합니다. structure SOT에 request-owned credential/pin 경계를 문서화합니다. 점수는 75입니다. 2.39.0 체감 502/핀 오염을 직접 막습니다.

라인 src/codex/auth-context.ts requestOwnedMainPinHasQuotaHeadroom - 물리 plan을 못 읽으니 unknown-plan 보수 규칙을 씁니다. 주간 16%가 캐시에 있으면 핀을 지키고, 관측되지 않은 창은 핀을 지킵니다. threshold 이상만 보통 Pool로 보냅니다. 이 보수성이 #3157 재현을 깨지 않는지(16% vs 100%) 테스트가 잠가야 합니다
라인 tests/codex-auth-context.test.ts 추가 블록 - weekly 100% pool vs 16% main 숫자가 이슈 재현과 같은지 확인하십시오. threshold 90 설정도 같이 가야 합니다
경로 structure/08_openai-provider-tiers.md - SOT 문서는 좋습니다. 구현과 문구가 "핀 보존 vs model-only detour" 를 같은 용어로 쓰는지 보세요
경로 PR #3135 - 같은 auth-context.ts 를 만집니다. 머지 순서를 정하지 않으면 한쪽이 conflict로 미뤄질 수 있습니다
경로 issue #3157 - PR 본문에 Closes가 보이는지 확인하고, 없으면 머지 커밋/설명에 이슈를 닫으십시오

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

  • #3166과 fix(codex): retain caller main after pool rejection #3135 중 무엇을 먼저 랜딩할지. 둘 다 auth-context입니다
  • unknown-plan 보수 핀 보존이 pause/소진 main의 정상 승격을 과도하게 막지 않는지
  • 보안: 요청 베어러를 로그/affinity에 남기지 않는다는 본문 주장을 테스트가 잠그는지

너의 추천
#3157 재현을 기준으로 이 PR을 먼저 머지하는 쪽을 추천합니다. #3135는 이어서 rebase하거나 순차 랜딩합니다. 머지 후 #3157을 닫습니다. close-don't-rebase 대상이 아닙니다. 라벨은 바꾸지 않습니다.

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

lidge-jun pushed a commit that referenced this pull request Sep 1, 2026
lidge-jun pushed a commit that referenced this pull request Sep 1, 2026
lidge-jun pushed a commit that referenced this pull request Sep 2, 2026
lidge-jun pushed a commit that referenced this pull request Sep 2, 2026
lidge-jun added a commit that referenced this pull request Sep 2, 2026
…sion audit (#3218)

* docs(devlog): open the bug/PR closeout stack roadmap

* docs(devlog): fold the A-gate import-boundary finding into phase 5

* docs(devlog): record the #3163 and #3166 landings

* docs(devlog): record why #2986 does not land in this train

* docs(devlog): close out the bug/PR closeout stack

* docs(devlog): record the final green CI verdict on dev

* docs(devlog): open the bug-label drawdown roadmap with audit corrections

* docs(devlog): record the Batch A landings and first rebase carry

* docs(devlog): record the Batch B rebase carries

* docs(devlog): record why the rebase service earned its keep

* docs(devlog): record the Batch C rebases and the one real review finding

* docs(devlog): record the #2999 scope boundary that survived execution

* docs(devlog): record Batch D - every bug PR closed

* docs(devlog): record what the PR half of the campaign cost

* docs(devlog): replan the remaining issues to one per cycle

* docs(devlog): carry the i3141 evidence into the replan

* docs(devlog): diagnose i3141 - fix predates the reported version

* docs(devlog): retire the second bundle

* docs(devlog): record the i3141 re-triage action and outcome

* docs(devlog): diagnose i3152 log table jitter

* docs(devlog): i3152 - measurement disproved the layout diagnosis

* docs(devlog): diagnose i3136 slashed-id price lookup

* docs(devlog): diagnose i3150 citation marker passthrough

* docs(devlog): diagnose i3155 capacity plan allowlist

* docs(devlog): i1419 stays open pending crash frames

* docs(devlog): record the i1419 re-triage ask

* docs(devlog): diagnose i2999 publication overwrite race

* docs(devlog): record the i2999 outcome and remaining scope

* docs(devlog): diagnose i2813 as a client-side reserve gate

* docs(devlog): diagnose i1527 residuals as trace-blocked

* docs(devlog): correct i1527 envelope-cap wording (192 blobs, HTTP 400)

* docs(devlog): plan p3193 loopback alpha-search reimplementation

* docs(devlog): record p3193 landing (#3205 -> 53c09a2)

* docs(devlog): plan the main->dev regression audit

* docs(devlog): pin regaudit counts, add tests-only/security passes and the exact-head dispatch

* docs(devlog): record regaudit reviewer verdicts

* docs(devlog): record the exact-head dev CI verdict and Windows classification

* docs(devlog): record the main control run proving the Windows failures predate the range

* docs(devlog): record the pass-1 recount and the #3217 root cause

* docs(devlog): plan i3217 (Spark functions-namespace flattening)

* docs(devlog): record i3217 landing (#3224 -> d23eab4)

* docs(devlog): regaudit2 recount and disposition table

* docs(devlog): regaudit2 CI verdict on d23eab4 and the four PR arrivals

* docs(devlog): plan p3226 (scoped namespace scrub)

* docs(devlog): p3226 audit finding and carry plan

* docs(devlog): record p3226 landing (#3234 -> b732b0d)

* docs(devlog): plan p3227 (combo zero-output incomplete failover)

* docs(devlog): record p3227 landing

* docs(devlog): plan p3228 (encrypted V2 spawn native fallback)

* docs(devlog): record p3228 landing

* docs(devlog): plan p3229 (Codexless originator in task recovery)

* docs(devlog): record p3229 landing and the #3239 regression repair

* docs(devlog): r3239 regression repair record

* docs(devlog): r3239 audit note

* docs(devlog): record p3232 (merged by maintainer)

* docs(devlog): p3232 verification result

* docs(devlog): regaudit3 recount and landing table

* docs(devlog): record the #3239/#3240 revert and correct the #3228 disposition

* docs(devlog): rv3239 revert record

* docs(devlog): rv3239 audit note

* docs(devlog): regaudit3 second-dispatch verdict

* docs(devlog): regaudit3 recount refreshed (#1419 closed by maintainer; count 4)

* docs(devlog): regaudit3 final CI verdict and c-7

---------

Co-authored-by: jun <jun@lidge.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants