Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
06ec553
Merge pull request #3678 from lidge-jun/codex/promote-main-243-01a07240
lidge-jun Sep 5, 2026
116c2ac
Merge commit '44ea9576e27c6be8be7f13a86e32bb349368c54d' into codex/re…
invalid-email-address Sep 6, 2026
07b48da
Merge pull request #3785 from lidge-jun/codex/release-244-main-07c0
lidge-jun Sep 6, 2026
bcdf559
chore(release): promote validated 2.45.0 to main [skip ci]
invalid-email-address Sep 6, 2026
b0900e5
chore(release): promote 2.45.0 to main (#3813)
lidge-jun Sep 6, 2026
3970601
chore(release): prepare 2.46.0 stable promotion
invalid-email-address Sep 7, 2026
bba6322
Merge pull request #3851 from lidge-jun/codex/release-246-main
lidge-jun Sep 7, 2026
3d53e5f
release: prepare 2.47.0 from audited regression candidate
invalid-email-address Sep 7, 2026
eda8754
Merge commit '48ab3e1e66cfa6e0c873de2fafa4540ac61d6c7d' into codex/re…
invalid-email-address Sep 7, 2026
f9e3515
Merge commit '57252193b' into codex/release-247-main
invalid-email-address Sep 7, 2026
6f71931
release: promote 2.47.0 to main (#3929)
lidge-jun Sep 7, 2026
9a60256
Merge commit 'd0737cff3' into codex/release-247-main-final
invalid-email-address Sep 7, 2026
9e9b1d3
Merge commit 'f48c322c0' into codex/release-247-main-final
invalid-email-address Sep 7, 2026
947bae9
Merge commit '0d7652ad1' into codex/release-247-main-final
invalid-email-address Sep 7, 2026
f7f890f
release: apply final roster correction to main (#3933)
lidge-jun Sep 7, 2026
544ebee
release: promote 2.48.0 to main
invalid-email-address Sep 8, 2026
d24ff57
release: set main channel version 2.48.0
invalid-email-address Sep 8, 2026
9a27e86
Merge pull request #4011 from lidge-jun/codex/release-248-main
lidge-jun Sep 8, 2026
62849df
release: promote verified 2.49.0 product tree to main
lidge-jun Sep 9, 2026
2f3f736
Merge pull request #4117 from lidge-jun/codex/release-249-main-01a08498
lidge-jun Sep 9, 2026
3a3de88
release: promote verified 2.50.0 product tree to main
lidge-jun Sep 10, 2026
2d4d7a2
Merge pull request #4195 from lidge-jun/codex/release-250-main-01a08a81
lidge-jun Sep 10, 2026
cf456e8
release: promote verified 2.51.0 product tree to main
lidge-jun Sep 11, 2026
c155cc7
Merge pull request #4271 from lidge-jun/codex/release-251-main
lidge-jun Sep 11, 2026
95c4875
release: promote verified 2.52.0 product tree to main
lidge-jun Sep 12, 2026
4d37c35
Merge pull request #4407 from lidge-jun/codex/release-2520-main
lidge-jun Sep 12, 2026
caf03d0
fix(codex): drop expired non-blocking quota evidence
luvs01 Sep 14, 2026
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: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bitkyc08/opencodex",
"version": "2.53.0",
"version": "2.52.0",
"description": "Universal provider proxy for OpenAI Codex & Claude Code — use any LLM with Codex CLI/App/SDK and Claude Code",
"type": "module",
"main": "./bin/package-main.mjs",
Expand Down
4 changes: 2 additions & 2 deletions src/codex/main-account-hard-lock.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { OcxConfig } from "../types";
import { getMainPolicyQuota } from "./quota";

export const MAIN_ACCOUNT_HARD_LOCK_PERCENT = 99;
export { MAIN_ACCOUNT_HARD_LOCK_PERCENT } from "./quota-types";
import { MAIN_ACCOUNT_HARD_LOCK_PERCENT } from "./quota-types";

export interface MainAccountHardLockStatus {
enabled: boolean;
Expand Down
2 changes: 2 additions & 0 deletions src/codex/quota-types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/** Quota wire/storage shapes. This leaf must not import credential or config owners. */
export const MAIN_ACCOUNT_HARD_LOCK_PERCENT = 99;

export type StoredAccountQuota = {
weeklyPercent?: number;
monthlyPercent?: number;
Expand Down
19 changes: 14 additions & 5 deletions src/codex/quota.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { isThirtyDayOnlyCodexPlan } from "./plan";
import { MAIN_CODEX_ACCOUNT_ID } from "./account-id";
import { getObservedMainQuotaIdentityKey, isMainQuotaWriterLive, type MainQuotaWriter } from "./main-account-cache";

import type { StoredAccountQuota, WhamUsageResponse, WhamUsageWindow } from "./quota-types";
import { MAIN_ACCOUNT_HARD_LOCK_PERCENT, type StoredAccountQuota, type WhamUsageResponse, type WhamUsageWindow } from "./quota-types";
export type { StoredAccountQuota, WhamUsageResponse } from "./quota-types";

/** Disk snapshot under OPENCODEX_HOME — quota and policy identity only, never credential tags. */
Expand Down Expand Up @@ -142,7 +142,7 @@ export function isCompleteCodexQuotaRecoverySnapshot(
return quota.monthlyIsPrimaryWindow === true && finitePercent(quota.monthlyPercent);
}

function finitePercent(value: number | undefined): boolean {
function finitePercent(value: number | undefined): value is number {
return typeof value === "number" && Number.isFinite(value);
}

Expand Down Expand Up @@ -241,14 +241,19 @@ function shortResetHasElapsed(resetAt: number | undefined, now: number): boolean
return resetAtToMs(resetAt) <= now;
}

/** Display/rotation carry expires; a reset clock cannot retract hard-lock evidence. */
/** Display/rotation carry expires; a reset clock cannot retract blocking hard-lock evidence. */
function assignCarriedShort(
next: StoredAccountQuota,
existing: StoredAccountQuota | undefined,
now: number,
policyEvidence = false,
): void {
if (!existing || (!policyEvidence && shortResetHasElapsed(existing.shortResetAt, now))) return;
if (!existing) return;
const existingShortPercent = existing.shortPercent;
const preserveBlockingEvidence = policyEvidence
&& finitePercent(existingShortPercent)
&& existingShortPercent >= MAIN_ACCOUNT_HARD_LOCK_PERCENT;
if (!preserveBlockingEvidence && shortResetHasElapsed(existing.shortResetAt, now)) return;
if (existing.shortPercent !== undefined) next.shortPercent = existing.shortPercent;
if (existing.shortObservedAt !== undefined) next.shortObservedAt = existing.shortObservedAt;
if (existing.shortResetAt !== undefined) next.shortResetAt = existing.shortResetAt;
Expand Down Expand Up @@ -349,7 +354,11 @@ function mergeAccountQuota(
if (existing.monthlyIsPrimaryWindow === true) next.monthlyIsPrimaryWindow = true;
}

const preserveKnownShort = policyEvidence && quota.shortPercent === undefined && finitePercent(existing?.shortPercent);
const existingShortPercent = existing?.shortPercent;
const preserveKnownShort = policyEvidence
&& quota.shortPercent === undefined
&& finitePercent(existingShortPercent)
&& existingShortPercent >= MAIN_ACCOUNT_HARD_LOCK_PERCENT;
if (snapshotHasShort(quota) && !preserveKnownShort) {
if (quota.shortPercent !== undefined) {
next.shortPercent = quota.shortPercent;
Expand Down
2 changes: 1 addition & 1 deletion structure/catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ provider wire mapping; unpinned native requests retain their existing pass-throu

> Decision record: [ADR-0026](decisions/ADR-0026-ultra-reasoning-level.md)

Codex display-cache expiry, retained main-policy evidence, and reset history follow the
Codex display-cache expiry, retained blocking main-policy evidence, and reset history follow the
[quota cache contract](providers/openai-tiers.md#quota-cache-and-short-window-history).

Chat helper admission in `src/server/responses/core.ts` follows the
Expand Down
2 changes: 1 addition & 1 deletion structure/codex-home.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ a deliberate user choice:
(`src/codex/project-config-warnings.ts`), surfaced by `ocx doctor` as a warning rather than an
override.

Codex display-cache expiry, retained main-policy evidence, and reset history follow the
Codex display-cache expiry, retained blocking main-policy evidence, and reset history follow the
[quota cache contract](providers/openai-tiers.md#quota-cache-and-short-window-history).

## Paginated history writer boundary
Expand Down
2 changes: 1 addition & 1 deletion structure/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ the residual directory for manual review; there is no recursive-delete fallback.

Client connection metadata stores a stable `apiKeyId` and a non-secret rotation `pendingOperation`. The current data secret remains only in `service-api-token`; a bounded rotation temporarily keeps the old secret in owner-only `service-api-token.prev`. Commit or recovery clears the marker before orphan cleanup. `ocx disconnect` is local-only and leaves remote revocation to the hub's **Integrations → API Keys** page. Hub and local usage stores are not mirrored.

Codex display-cache expiry, retained main-policy evidence, and reset history follow the
Codex display-cache expiry, retained blocking main-policy evidence, and reset history follow the
[quota cache contract](providers/openai-tiers.md#quota-cache-and-short-window-history).

## Paginated history writer boundary
Expand Down
2 changes: 1 addition & 1 deletion structure/gui-and-management-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ and catalog invariants documented in this folder rather than inventing parallel
Codex quota cards consume the display cache from `src/codex/quota.ts`. A partial refresh
removes an omitted short tuple whose reset deadline has elapsed, so a stale Spark-derived
5h row does not persist on a weekly-only account. This is independent of the main-account
hard-lock evidence and reset-notification history; their retention rules are documented in
blocking hard-lock evidence and reset-notification history; their retention rules are documented in
[OpenAI account modes](providers/openai-tiers.md#quota-cache-and-short-window-history).

## Dashboard surfaces
Expand Down
2 changes: 1 addition & 1 deletion structure/ops/docs-and-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ This keeps release runs short and makes release a deployment of a verified commi

The Remote Hub guide and affected CLI, server-config, management-API, and dashboard references have eight sources: root English plus `fr`, `ko`, `zh-cn`, `zh-tw`, `ru`, `ja`, and `tr`. English is canonical; commands, defaults, endpoint auth, and warnings remain exact in translations. A release requires the remote-only focused/full gates, privacy scan, GUI/docs builds, protocol compatibility receipts, and the MAINTAINERS security review for the exact head.

Codex display-cache expiry, retained main-policy evidence, and reset history follow the
Codex display-cache expiry, retained blocking main-policy evidence, and reset history follow the
[quota cache contract](../providers/openai-tiers.md#quota-cache-and-short-window-history).

The Combo guides describe the distinction between display quota and single-credential inference evidence used by routing. See [scoped provider quota](../runtime.md#scoped-provider-quota-for-combo-selection).
Expand Down
8 changes: 5 additions & 3 deletions structure/providers/openai-tiers.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,11 @@ future or missing deadlines remain carried, and explicit incoming short readings
This stops partial weekly/Spark or credits-only refreshes from renewing obsolete Spark-derived
5h rows through the cache-wide `updatedAt` timestamp. Plan labels do not suppress real windows.

The separately retained main-policy snapshot preserves omitted short evidence even after its
reset clock passes. Credits-only, weekly-only, and metadata-only updates cannot remove an
existing short usage reading or release its hard lock; a fresh short reading can replace it.
The separately retained main-policy snapshot preserves omitted blocking short evidence even after
its reset clock passes. Credits-only, weekly-only, and metadata-only updates cannot remove an
existing blocking short usage reading or release its hard lock; a fresh short reading can replace
it. Expired non-blocking short evidence is dropped, so it cannot take priority over a fresh blocking
weekly reading.

The Codex writer explicitly asks `src/quota/reset-observer.ts` to retain an absent short window
in `src/quota/reset-seen-store.ts`, with its original observation time. Detection compares only
Expand Down
2 changes: 1 addition & 1 deletion structure/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ Routed Responses continuations whose local replay state is missing resolve their

`src/remote/protocol.ts` owns pure interval/feature negotiation. `src/remote/hub-state.ts` owns the `GET|HEAD /v1/hub-state` contract, its caps, and the parser both sides share. `src/client/hub-client.ts` owns bounded, schema-validated remote catalog consumption, hub-state reads, and key-id probes; `src/client/hub-state.ts` owns the resolution and the owner-stamped 0600 cache, and a failed read reports "unavailable" rather than degrading to the client's own local provider and login state. `src/client/hub-relay.ts` is a fixed-authority management relay with URL, header, body, redirect, and stream bounds. The public data listener remains the direct client→hub path; the loopback management ingress never serves data-plane routes.

Codex display-cache expiry, retained main-policy evidence, and reset history follow the
Codex display-cache expiry, retained blocking main-policy evidence, and reset history follow the
[quota cache contract](providers/openai-tiers.md#quota-cache-and-short-window-history).

Chat helper admission in `src/server/responses/core.ts` follows the
Expand Down
2 changes: 1 addition & 1 deletion structure/subagents.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ It orders routed output groups after alias deduplication, preserving the collisi
base/1M/Fast siblings. Native groups and explicit Desktop profile ownership are unchanged.
Native Codex advertisements still follow display priority; private guidance ranks do not freeze them.

Codex display-cache expiry, retained main-policy evidence, and reset history follow the
Codex display-cache expiry, retained blocking main-policy evidence, and reset history follow the
[quota cache contract](providers/openai-tiers.md#quota-cache-and-short-window-history).

Chat helper admission in `src/server/responses/core.ts` follows the
Expand Down
13 changes: 13 additions & 0 deletions tests/codex-integration/main-account-hard-lock-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ describe("identity-bound main-account hard-lock policy", () => {
expect(getMainAccountHardLockStatus(enabled).state).toBe("ready");
});

test("an expired non-blocking short reading cannot hide a fresh weekly block", () => {
const elapsed = Math.floor(Date.now() / 1000) - 60;
observe({ shortPercent: 4, shortWindowSeconds: 18_000, shortResetAt: elapsed, weeklyPercent: 20 });

observe({ weeklyPercent: 99 });

expect(getMainPolicyQuota()).toMatchObject({ weeklyPercent: 99 });
expect(getMainPolicyQuota()?.shortPercent).toBeUndefined();
expect(getMainPolicyQuota()?.shortResetAt).toBeUndefined();
expect(getMainPolicyQuota()?.shortWindowSeconds).toBeUndefined();
expect(getMainAccountHardLockStatus(enabled).state).toBe("blocked");
});

test("one missing reset prevents a false scheduled-unlock promise", () => {
observe({ weeklyPercent: 99, monthlyPercent: 99, monthlyResetAt: now + 60_000 });
expect(getMainAccountHardLockStatus(enabled, now)).toEqual({ enabled: true, state: "blocked" });
Expand Down
Loading