Repository navigation
Description
Area
Authentication and account pool
What are you trying to accomplish?
Stop one OAuth account from being used by sessions on several machines at the same time. Two cases matter to us:
- One OpenCodex instance serves clients on several machines (for example a laptop forwards its port to a second PC over SSH). Requests from both machines reach the same pool and can land on the same account at once.
- Independent OpenCodex instances on two machines pick the same account at once.
What prevents this today?
For case 1, conversation affinity binds a conversation to an account, but nothing stops two conversations from different client machines from being bound to the same account at the same time. The pool does not know which machine a request came from. For case 2, each instance keeps its own pool selection and cooldown state, and independent instances have no shared lease. A first-party client that does not use OpenCodex cannot take part in a lease. Our concern is that one account used from several machines at once may look like account sharing to the provider and raise suspension risk; we have no measurement of provider behavior.
What should OpenCodex do?
For case 1, offer an opt-in per-provider rule: an account serves sessions from one client machine at a time. The client machine could be identified by a configured client label or header. A request from a second machine would get another eligible account, or a clear refusal when none is free. For case 2, consider an optional shared lease, or a supported coordination interface, with bounded expiry, owner identity, renewal, crash recovery and fencing. Define clearly what happens with clients that cannot take part.
Example usage or interface
Case 1: machine A and machine B both send requests through one instance with different client labels. While A holds account 1, B is given account 2. Case 2: two instances share a lease store. One claims an account; the other selects a different eligible account. A first-party client is protected only if it takes part or an operator reserves its account.
Alternatives or workarounds
Assign a distinct account to each instance and keep the split by hand.
Additional context
This is a proposed contract. We do not claim that an external client can be locked without its cooperation. On 2026-10-27 we searched issues and PRs for lease, multiple instances and multi-device and found no duplicate. Related: #5157 adds a writer lease for the spend journal in one state directory; #6077 proposed a single cloud container writer. Neither is a per-account lease across independent instances.
Checks
- I searched existing issues and documentation.
- This request describes a concrete OpenCodex workflow rather than merely naming a desired technology.
- I removed secrets and personal data.
Activity
lidge-jun commentedon Oct 28, 2026
On
devfdc6dd82d930295880dcf6d10bbb9f2c61994574, generic OAuth affinity stores conversation-to-account bindings in a process-local map (src/oauth/generic-session-affinity.ts:14, binding at:113). Its identity inputs are client/thread/session/cache keys (src/oauth/session-affinity-key.ts:4), not an authenticated machine owner. Kiro's existing capacity leases count requests per provider/account (src/oauth/kiro-account-load.ts:19); they do not express machine exclusivity. Neither merged #5157's state-directory writer lease nor closed #6077's container-writer proposal supplies the requested per-account coordination.Three options have different guarantees:
I recommend the second option first, behind a per-provider opt-in, then reuse its ownership contract if a coordinator is approved. Bind configured machine identities to dedicated authenticated client keys.
src/server/auth-cors.ts:436already distinguishes configured-key admission from anonymous loopback, but SSH-forwarded loopback traffic does not acquire a machine identity by itself. An arbitrary label/header or source IP should not be treated as proof of ownership. Under the opt-in, missing identity must have a documented refusal or explicitly configured shared-owner mode.Ownership should survive gaps between requests according to a declared idle lifetime, retain active-request references, and release only after the old owner's requests drain. Merely expiring a timestamp while an upstream send continues would permit the very overlap this feature promises to prevent. Re-login and duplicate provider rows also need a stable physical-account identity, rather than independent leases per local slot.
There is no clearly safe implementation slice yet: first settle identity provisioning, session ownership lifetime and drain/expiry behavior. Then introduce a small ownership module at final credential admission, initially for one named provider. Proposed tests beside
tests/oauth/generic-session-affinity.test.tsshould prove same-owner sharing, competing-owner exclusion, unknown-owner refusal, cancellation/drain, credential replacement and expiry without overlapping live sends. This is source analysis; no provider suspension behavior or runtime result is claimed.