Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions PRIVACY.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ Codex Desktop, its local app-server, Claude Code, and Anthropic's API remain gov

Optional Codex account management reads local Codex `auth.json` for explicit registration, switching, and identity checks while refreshing registered-account usage. Replacement happens only on an explicit switch. Additional accounts use official Codex browser login in a restricted temporary home; temporary credentials are removed after import or cancellation. The separate account vault and recovery transaction are DPAPI encrypted and ACL restricted to the Windows user; the login staging directory also permits SYSTEM. They are never sent to this project's developers. DPAPI protects data at rest; it does not protect against other software already running as the same Windows user. The active Codex credential remains owned by the live authentication file: saved snapshots never override its newer tokens during recovery. Uninstall intentionally preserves the separate account vault to avoid losing saved logins.

An explicit **사용량 조회** request for an inactive account temporarily places that account's credential in a separate, user-only private home for the official local app-server. It never replaces the active login. The helper may refresh authentication while reading usage; after its confirmed exit, updated credentials are atomically saved back to the DPAPI vault even on request failure or cancellation. A DPAPI recovery journal retains the selected commit credentials before the vault write, including recovery interrupted by another crash. Temporary plaintext files are removed after verified persistence. If the process crashes or cleanup cannot finish, the restricted staging directory and journal remain until **중단된 조회 복구** completes after Codex writers stop. Each account retains only its latest successful percentages, reset times, and check time; the application does not attribute usage to people or retain a usage timeline.

When reporting a bug, do not attach Codex or Claude logs, credential/configuration files, tokens, or screenshots containing information you do not want to publish.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ Choose **+ 다른 계정 추가**, optionally name the account, then select **

Select the saved account and click **이 계정으로 전환**. The preparation dialog shows the source and target names and waits while you finish your work and close Codex Desktop and other Codex CLI/engine processes. **전환하고 Codex 열기** becomes available when they have stopped; cancellation keeps the current login. The widget stops its own usage helper, verifies once more that no Codex writers remain, saves the latest current login, and applies the selected login. It attempts to reopen the previously observed packaged desktop; if necessary, launch Codex from the Start menu and confirm the account there. File application and desktop login verification are separate outcomes.

Only explicit selections cause a switch. There is no automatic quota rotation, proxy, inactive-account polling, or quota pooling. Inactive usage figures show the last observation and its time; values past their reset time are marked **갱신 필요**. A pending encrypted transaction blocks polling until **미완료 전환 복구** reconciles it with the actual live authentication; unknown third-party login changes are not overwritten. The management window supports display scaling, and its details scroll when the window is made smaller.
Select any registered account and click **사용량 조회** to fetch its latest weekly and 5-hour remaining usage, reset times, and last successful check time. **목록 갱신** only reloads saved values. Inactive accounts are queried only on an explicit click, using a short-lived official app-server in a private isolated home. Codex Desktop and the current account stay signed in; the current widget helper is not suspended. Active-account queries reuse that helper and require Codex Desktop to be open. **조회 취소**, a timeout, or a failed request preserves the last successful usage observation. Refreshed credentials are saved even if the usage request fails or is canceled. Expired logins can be renewed through **+ 다른 계정 추가** using the same inactive account; for the active account, sign in again in Codex.

Only explicit selections cause a switch. There is no automatic quota rotation, proxy, inactive-account background polling, quota pooling, usage history, or per-person attribution. Values past their reset time are marked **갱신 필요**. A pending switch transaction blocks polling until **미완료 전환 복구** reconciles it with actual live authentication. A query interrupted before credential cleanup offers **중단된 조회 복구**; finish Codex work and close remaining Codex writers before this exceptional recovery. Its encrypted journal preserves refreshed credentials before staging is removed. Recovery never overwrites newer live authentication. The management window supports display scaling, and its details scroll when the window is made smaller.

The first version supports local Windows file-based ChatGPT authentication. Unsupported keyring/managed configurations fail closed. The vault is stored separately at `%LOCALAPPDATA%\CodexWeeklyUsageIndicator.Accounts`; uninstall preserves it. Delete inactive accounts from the manager before removing the app if you no longer want their saved credentials. This convenience tool does not establish that any particular multi-account usage pattern is permitted by the service terms.

Expand Down
10 changes: 10 additions & 0 deletions docs/manual-accounts-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

The existing WinForms widget owns the small usage surface and opens a separate account manager. The user selects accounts explicitly. Inactive usage is a dated observation, not a background login or synthetic combined quota. The current widget geometry and Claude source/cache contracts remain intact.

## On-demand usage (1.6)

An explicit selected-account button reads weekly and optional 5-hour windows with the official `account/rateLimits/read` interface. List selection, list refresh, and the manager's five-second local refresh never query inactive accounts. The UI stores one successful snapshot/time, with no history, delta, or attribution. Failed and canceled requests retain that observation. The active account reuses the widget helper; an inactive account uses a separate private file-store `CODEX_HOME` without copying user configuration or passing tokens in arguments.

Inactive requests hold the existing process-wide mutex and vault file lock on one synchronous worker thread across the async protocol operation. The UI remains responsive, and the active helper continues polling; its optional vault cache write is skipped while the query owns storage. Switching, import, rename, removal, duplicate query, and installer replacement cannot interleave with the transaction.

Rate-limit reads can implicitly refresh authentication even with `account/read.refreshToken=false`. Query staging therefore has a separate encrypted journal, never the disposable `login-*` cleanup path. The owned helper uses a non-breakaway kill-on-close Job and must exit before credential read-back. Success, protocol failure, and cancellation all save its validated same-account credentials before removing staging. Shutdown uncertainty retains staging and journal. Before writing the vault, the chosen auth and expected prior digest are durably written to the encrypted journal; recovery can be interrupted repeatedly and the desktop can independently change accounts without reverting a committed refresh. Active live authentication remains authoritative and is never written by this path.

Crash recovery is explicit and conservatively requires all potential Codex writers to exit, accounting for the narrow process-start/Job-assignment interval. A pending query is announced on startup and blocks account mutations, while active-account usage polling remains available. Missing/corrupt credentials or inconsistent vault revisions preserve recovery evidence and fail closed.

## Authentication and recovery

The local live authentication file is authoritative for the active account. Every switch stops the widget's own app-server, checks for remaining native Codex writers, reads the latest source credential, writes an encrypted recovery transaction, saves the source, and atomically applies the selected credential. File replacement is read back. Saved auth JSON is treated as opaque data so future fields survive.
Expand Down
21 changes: 21 additions & 0 deletions docs/manual-usage-delivery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Manual account usage delivery — 1.6.0

The account manager can fetch a selected account's latest weekly and 5-hour remaining usage, reset times, and successful check time without switching the desktop login. List refresh remains local. No history, comparison, attribution, or inactive background polling is included.

## Verification (2026-09-10)

- Synthetic store tests cover inactive success, request failure and cancellation with rotated credentials; live auth byte preservation; selected-account observation binding; transaction exclusion; disk failure; staged identity mismatch; external activation; and interruption/recovery at durable boundaries. Repeated recovery is tested after another external login.
- App-server tests exercise initialized and canceled owned processes, account-read consistency, helper restart isolation, and parsing of a separate optional 5-hour window.
- UI tests run the actual WinForms message loop for one-click/one-request, busy actions, failure and cancellation, last-observation preservation, and zero helper suspension/resumption. Existing native focus, registration, rename, minimum-size scrolling, and scaled action-bound checks remain in the suite. Synthetic screenshots were inspected locally and are not published.
- An explicit opt-in live smoke invoked the real manager button with one inactive saved account while Codex Desktop remained running. It verified a new observation, byte-for-byte unchanged active authentication, unchanged active snapshot/account, zero suspend/resume callbacks, and removed query staging/journal after the official helper exited. No credentials, account identities, or usage values were printed or committed.
- Two inherited fork-team advisors checked authentication/persistence and UX/lifecycle/release. A separate fresh code reviewer inspected the candidate and its affected regression surfaces without implementing it. The review identified repeated-recovery durability and helper-start failure handling; fixes were adopted. Final code review recommended ready with no remaining confirmed blocker. The reviewer did not run live authentication or tests.

## Operational boundaries

Successful button-level live verification is engineering evidence, not a new user acceptance claim. The previous main-to-secondary switching acceptance remains separate. A new browser login was not required for this live query.

If an inactive login has expired, use account addition to sign into that same account again. If a query is interrupted before credential persistence/cleanup, the manager offers recovery; finish work and close Codex writers before running it. No recovery or query silently replaces active authentication.

## Release and rollback

The tag workflow builds and packages a draft release. Publish only after checking its EXE hash against SHA256SUMS and the ZIP's EXE, lifecycle scripts, and public documents. Install through the existing per-user interactive scheduled-task path, retaining final-path validation. Rollback can reinstall 1.5.1 after any pending query is recovered in 1.6.0; resolve the new query journal before downgrading because older versions do not understand it. The account vault keeps its existing version and supports older snapshots without a 5-hour field.
2 changes: 1 addition & 1 deletion src/AccountDialogs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ internal AccountSwitchDialog(string sourceName, string targetName, Action? asser
_assertWritersStopped = assertWritersStopped ?? CodexAccountRuntime.AssertWritersStopped;
Name = "AccountSwitchDialog";
AccountUiTheme.SetForm(this);
Text = recovery ? "미완료 전환 복구" : "계정 전환 준비";
Text = recovery ? "중단된 계정 작업 복구" : "계정 전환 준비";
StartPosition = FormStartPosition.CenterParent;
FormBorderStyle = FormBorderStyle.FixedDialog;
MinimizeBox = false; MaximizeBox = false; ShowInTaskbar = false;
Expand Down
Loading