Skip to content

fix(codex): block the main account when either the 5h or weekly window reaches 98% - #5870

Merged
lidge-jun merged 1 commit into
devfrom
codex/main-hard-lock-any-window
Sep 25, 2026
Merged

lidge-jun merged 1 commit into
devfrom
codex/main-hard-lock-any-window

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Summary

The main-account 98% hard lock (#5694) looked at only one usage window: the 5h window when the account had one, otherwise the weekly window. So a main account at 98–100% weekly with 5h headroom stayed ready, and ocx kept sending it traffic until the weekly window drained. That is exactly the state that disables Codex Desktop's send button.

Now the 5h and weekly windows each block on their own:

5h weekly before after
98 50 blocked blocked
97 98 ready blocked
20 100 ready blocked
97 97.99 ready ready
unreadable 99 unknown (admits) blocked

A block holds until every blocking window reports a fresh reading below 98%. For example, clearing 5h to 0% no longer releases a weekly 99% block. The reported resetAt is the latest reset among the blocking windows, and it is omitted when any blocking window has no reset time, so the UI never promises an early unlock. Monthly still governs only monthly-only accounts. An unreadable window still admits by itself, but it can no longer hide a block in the other window.

The retained policy snapshot also gained a guard that mirrors the existing 5h rule: an observation that carries a weekly reset time but no weekly percentage keeps a blocking weekly reading. A governing monthly-primary observation still replaces it, so that release path is unchanged. Today's parsers never emit that shape, so this closes a latent hole instead of fixing live behavior.

Every consumer (admission fence, pool usability, auto refresh, background recovery, account DTO, and settings) already reads getMainAccountHardLockStatus, so the change lives in that one evaluator. The settings description, in all 10 locales, the en/ko docs, and structure/providers/openai-tiers.md now describe the any-window rule.

Settings → Codex → Multi-auth → Advanced settings, new description text (ko):

Main account 98% block setting

Verification

  • bun test tests/codex-integration/main-account-hard-lock-*.test.ts tests/codex-integration/main-quota-*.test.ts tests/codex-integration/codex-quota-auto-refresh-main-admission.test.ts tests/codex-integration/codex-account-threshold-api.test.ts tests/config/settings-main-account-hard-lock.test.ts → 476 pass, 0 fail.
  • New cases pin each row of the table above, release only after every blocking window lowers, resetAt selection, unknown 5h with weekly high and low, and the reset-only weekly guard with monthly-primary release. Existing pins that encoded "5h wins over weekly" (in main-account-hard-lock-policy, main-quota-evidence-validation, and main-quota-window-observation) were flipped deliberately to the new rule.
  • bun run typecheck → exit 0. bun run structure:check → passed. bun run build:gui → ok.
  • bun run test:changed ran about 25k tests locally, but the run is not usable as evidence. This checkout is a Codex-app worktree under ~/.codex, and the test home guard refuses to remove fixture directories inside the real Codex home, which produced 943 unrelated cleanup failures (for example account-pool-management-api). None of them are in hard-lock or quota tests. The full suite is left to hosted CI.
  • Read-only audits by a DeepSeek subagent covered consumer inventory, retention paths, and a plan review (near-pass; its three findings were folded in).

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • Bug Fixes
    • Main-account protection now blocks when either the 5-hour or weekly usage reaches 98%. Monthly usage applies to monthly-only accounts.
    • Blocking clears only when every window contributing to the block falls below 98%, so a reset or low reading in one window won’t override another window still at the threshold.
    • The displayed reset time reflects the latest reset among blocking windows and is omitted when any blocking window lacks a valid future reset.
  • Documentation
    • Updated protection descriptions across supported languages to reflect the revised blocking and clearing behavior.

…w reaches 98%

The hard lock picked one window (5h when present, else weekly), so a weekly reading at 98-100% with 5h headroom kept admitting main-account traffic. Each of 5h and weekly now governs alone; a block holds until every blocking window reads lower, resetAt is the latest blocking reset, and an unreadable 5h reading cannot hide a weekly block. The policy snapshot also keeps a blocking weekly tuple across a reset-only weekly observation.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 25, 2026 18:08
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 25, 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-25T18:12:37.971509Z e6d32c6 PR opened
ℹ️ 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.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

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

coderabbitai Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: ab2c4ca3-ffd8-4169-84a7-8608b3b2c628

📥 Commits

Reviewing files that changed from the base of the PR and between f353aac and e6d32c6.

📒 Files selected for processing (19)
  • devlog/_plan/260926_main_hard_lock_any_window/010_plan.md
  • docs-site/src/content/docs/ko/reference/cli/providers-accounts.md
  • docs-site/src/content/docs/reference/cli/providers-accounts.md
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/fr.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/tr.ts
  • gui/src/i18n/vi.ts
  • gui/src/i18n/zh-TW.ts
  • gui/src/i18n/zh.ts
  • src/codex/main-account-hard-lock.ts
  • src/codex/quota.ts
  • structure/providers/openai-tiers.md
  • tests/codex-integration/main-account-hard-lock-policy.test.ts
  • tests/codex-integration/main-quota-evidence-validation.test.ts
  • tests/codex-integration/main-quota-window-observation.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The main-account hard lock now evaluates short and weekly quota windows independently. Monthly usage governs only when neither window is present. A blocking weekly reading is retained across qualifying reset-only observations, and the documentation and translations describe the updated policy.

Changes

Main-account hard-lock policy

Layer / File(s) Summary
Evaluate governing windows and retain blocking evidence
src/codex/main-account-hard-lock.ts, src/codex/quota.ts, tests/codex-integration/main-account-hard-lock-policy.test.ts, tests/codex-integration/main-quota-evidence-validation.test.ts, tests/codex-integration/main-quota-window-observation.test.ts, devlog/_plan/260926_main_hard_lock_any_window/010_plan.md
A valid short or weekly reading at or above 98% blocks. A block remains until all blocking windows read below 98%. resetAt uses the latest future reset only when every blocking window has one. Tests cover unknown readings and retained weekly evidence.
Update policy descriptions
structure/providers/openai-tiers.md, docs-site/src/content/docs/reference/cli/providers-accounts.md, docs-site/src/content/docs/ko/reference/cli/providers-accounts.md, gui/src/i18n/*.ts
Provider documentation, CLI documentation, and GUI translations describe independent short and weekly blocking, monthly-only behavior, and release conditions.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to e6d32

The updated descriptions match when the account is blocked and released. No identified issue needs resolution before merge.

Security Architecture Review

Security architecture risk: 🔵 Low · up to e6d32

The change closes a case where a full weekly quota could still receive traffic. No new account-routing or authentication bypass was identified, but the complete source and consumption of quota observations remain unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The policy change affects admission and reported status for the main Codex account, rather than granting a caller a new account identity or credential path.

Trust Boundaries and Controls

  • observed — Identity-mismatched retained quota is not supplied to the evaluator, and the main-account hard-lock check precedes subsequent credential checks. A missing or wholly unreadable quota still admits under the existing unknown-state contract.
  • observed — The server applies its management-auth gate before dispatching API requests to the management handler that serves settings. This PR’s evaluator change does not add an unauthenticated settings route.

Resilience and Maintainability Implications

  • inferred — Retaining blocking weekly evidence through a reset-only update strengthens the admission fence against partial observations. The separate, pre-existing unknown-admits behavior is not resolved by this change.

Hardening Proposals

  • proposed — Document and verify the intended availability-versus-admission policy for absent or aged quota evidence, including its producer identity and observation freshness, before changing the existing unknown-admits behavior.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 15 files. (4 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: the main account now blocks when either the 5-hour or weekly window reaches 98%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 15 files. (4 skipped: 4 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 43 / 80

이 글은 메인 계정 98% 잠금이 사용량 창을 하나만 보던 구멍을 막아요.

잠금은 기본으로 켜져 있어요. 예전 코드는 5시간 창이 하나라도 있으면 5시간 사용률만 봤어요. 5시간이 97%이고 주간이 98% 이상이어도 상태는 ready였어요. ocx는 그 메인 계정으로 요청을 계속 보냈고, 주간 사용량이 바닥날 때까지 갔어요. Codex 데스크톱은 그 주간이 바닥이면 보내기 버튼을 꺼요.

이제는 5시간 창과 주간 창을 따로 봐요. 어느 쪽이든 98% 이상이면 막아요. 5시간이 98%이고 주간이 50%여도 막히고, 5시간이 20%이고 주간이 100%여도 막혀요. 둘 다 98% 미만이면 통과하고, 97.99%도 통과예요.

한 번 막히면, 막은 창이 모두 98% 미만으로 새로 읽혀야 풀려요. 5시간이 0%로 리셋돼도 주간 99%는 그대로예요. 화면에 보여주는 다시 열리는 시각은, 막힌 창들의 리셋 시각 중 가장 늦은 것이에요. 막힌 창 중에 앞으로의 리셋 시각이 없는 것이 있으면 그 시각을 빼요. 더 빨리 풀린다고 말하지 않아요.

월간 숫자만 있는 계정은 월간을 봐요. 5시간이나 주간 기록이 있으면 월간은 잠금에 안 들어가요. 월간 100%와 주간 97%는 여전히 통과예요.

5시간 숫자를 못 읽으면 그 창만으로는 막지 않아요. 그런데 주간이 99%로 읽혀 있으면, 5시간을 못 읽어도 막아요. 못 읽은 5시간이 주간 차단을 숨기던 경우가 이번 고침이에요.

정책 기록에는 가드를 하나 더 넣었어요. 주간 리셋 시각만 오고 주간 퍼센트는 없는 관측은, 이미 98% 이상으로 막아 둔 주간 숫자를 지우지 않아요. 5시간 창에 있던 규칙과 같아요. 월간이 본창인 관측은 그 주간 숫자를 지우고 풀 수 있어요. 작성자는 지금 파서가 그 모양을 안 낸다고 했어요. 나중에 생길 구멍을 미리 닫은 거예요.

설정 문장 열 개 언어, 영어와 한국어 문서, structure/providers/openai-tiers.md가 같은 말을 해요. 입장, 계정 풀, 자동 새로고침, 백그라운드 복구, 계정 목록은 전부 getMainAccountHardLockStatus를 봐요. 판정을 그 함수 안에서 바꿨어요.

라인 - src/codex/quota.ts의 preserveKnownWeekly. 기존 주간이 98% 이상이고 새 policy 관측에 주간 퍼센트가 없으면, 새 weeklyResetAt도 버리고 옛 퍼센트와 옛 리셋 시각을 같이 남겨요. 테스트가 리셋 시각 now + 60_000이 남는 것을 고정해요. 그 시각이 getMainAccountHardLockStatus의 resetAt이 되고, src/codex/auth-context.ts의 CodexMainAccountHardLockError가 그 값으로 Retry-After를 적어요. 나중에 온 리셋 시각이 더 멀면, 클라이언트는 더 이른 옛 시각에 다시 시도해요. 5시간의 preserveKnownShort도 새 리셋 시각을 옛 퍼센트에 붙이지 않아요.

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

5시간 창이 방금 0%인데 주간이 98% 이상이면, 이번 주 남은 5시간 창도 메인 계정으로는 못 써요. 메인 계정을 끝까지 쓰고 Reserve로 넘기려면 스위치를 꺼야 해요. 문서에 그 문장이 있어요. 이번 요청이 그 동작이면 그대로 두면 돼요.

월간을 5시간·주간과 함께 막을지는 이 글이 범위 밖으로 적어 두었어요. 주간 97%와 월간 100%는 통과로 남아요.

너의 추천

바탕은 dev가 맞아요. types.ts와 config.ts를 나누는 일과 겹쳐서 닫을 중복은 없어요. 닫지 마세요. 표의 경우와 풀리는 조건이 코드와 테스트에 있어요. 테스트 샤드도 통과했어요. preserveKnownWeekly가 옛 리셋 시각을 남기는 것은 5시간과 같은 선택이니, 그 선택을 유지한 채로 넣으면 돼요.

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

@lidge-jun
lidge-jun merged commit cd9866b into dev Sep 25, 2026
35 checks passed
@lidge-jun
lidge-jun deleted the codex/main-hard-lock-any-window branch September 25, 2026 18:28
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.

1 participant