Repository navigation
chore: recover upstream v0.2.6 codex ticket integration - #184
Merged
Merged
Conversation
Paused (schedulable=false) active accounts were excluded from the background token refresh candidates, so their stored access_token silently expired. The admin usage-window quota probe uses the stored token verbatim (no token provider / no refresh), so the probe then gets HTTP 401 UNAUTHENTICATED and the dashboard reports a false "needs re-auth" for a perfectly healthy account, while Test Connection and live traffic (which refresh on demand via the token provider) keep working. Pause is not permanent rejection: error accounts are already excluded by the status = 'active' filter, and accounts whose refresh genuinely fails are rate-limited by the retry-cooldown exclusion (10-minute retry- exhausted cooldown). Refresh success only persists credentials and never touches schedulable, so a paused account cannot be silently un-paused. Drop the schedulable filter and update the SQL-filter test, the integration pagination test, and the service-level candidate fake.
GET /api/v1/admin/groups/usage-summary 在有一定数据量的库上会退化成
usage_logs 全表扫。根因是 getAllGroupUsageSummaryFromRollups 里,tail CTE
的 created_at 下界 state.tail_start 由同一条 SQL 的 state CTE 算出、再用
CROSS JOIN 交给 tail:这个值对 planner 来说要到运行期才知道,既进不了
index cond,也估不准选择性,于是只能顺序扫全表再逐行过滤。
生产实测(1721 万行 usage_logs / PostgreSQL 17):
Nested Loop (actual time=28161..48334 rows=34788)
Join Filter: (ul.created_at >= state_1.tail_start)
Rows Removed by Join Filter: 17178082
-> Seq Scan on usage_logs (actual time=0.030..47567 rows=17212870)
Buffers: shared hit=12863 read=951875
Execution Time: 48720 ms
改成先读一次水位行、在 Go 侧算出 tail_start / closed_before / retained
日期,再把它们当查询参数传进来。同一套数据上:
Index Scan using idx_usage_logs_created_at on usage_logs
Index Cond: (created_at >= $7)
Execution Time: 34 ms
水位有效性的判定(恰好一行、时区名与配置一致、水位不在未来)和无效时
退化成从 epoch 全量重算的行为,与原先 SQL 里 state_values / CASE WHEN
valid 的分支逐条对应,结果口径不变。
另外读取水位的语句不加锁,不参与 Wei-Shaw#6976 那条 FOR UPDATE / FOR KEY SHARE
的阻塞链。
DeepSeek native Responses rejects Codex view_image results when function_call_output.output contains input_image parts. Move media into a following user message and keep the tool output as a string so call_id pairing remains valid.
Security Scan / backend-security 自 2026-09-16 起在所有 PR 上失败,govulncheck 对
google.golang.org/grpc v1.82.1 报:
- GO-2026-6443 Server panic via missing authority or Host headers(修复于 v1.83.2)
- GO-2026-6348 Heap Memory Exhaustion via HTTP/2 DATA Frame Fragmentation(修复于 v1.83.1)
调用链在 pkg/pluginapi/v1/runtime.go 与 internal/service/plugin_runtime.go。
go get google.golang.org/grpc@v1.83.2 && go mod tidy。最小版本选择连带抬升了
golang.org/x/{crypto,mod,net,sync,term,sys,text,tools}、genproto/googleapis/rpc 与
go.opentelemetry.io/otel* 的间接依赖,均为补丁级别。
…ump-number fix(pagination): handle numeric jump input
…ta-negative fix(admin): reject negative platform quota limits before saving
…-ids fix(ui): keep dialog title IDs unique across instances
…nput-sync fix(auth): keep TOTP setup digits in sync with state
…llback-error fix(clipboard): report errors thrown by the copy fallback
…-read-results fix(announcements): preserve successful bulk read results
…edup fix(proxies): reuse in-flight test guards during batch testing
…r-page fix(payment): reset the order page when changing status
…essages fix(totp): display normalized API error messages
…b-navigation fix(channels): allow tabbing out of an empty model input
…nt-input fix(payment): restore accepted text after invalid amount input
…-loading-reset fix(subscriptions): reset loading when clearing state
…ce-warning fix(payment): base refund balance warnings on the requested amount
fix(openai): parse Codex models manifest envelope once
…-flicker fix: prevent promo code field flash on registration
…-accounts fix(account): keep refreshing OAuth tokens for paused accounts
…nse-binding-context fix(openai): 客户端断开后仍持久化 Responses 续聊绑定
…chat-role-compat fix(gateway): normalize developer roles for strict native Chat upstreams
…ion-pagination feat(redeem): paginate user redemption history
…ttribution-429 fix(antigravity): 过滤 Claude attribution 元数据,修复特定请求的 429
…ive-responses-tool-output-media fix(deepseek): lift Responses tool output images
…ne hour ChatGPT OAuth accounts can mint a 292-length x-codex-turn-state via a dedicated harvest proxy and reuse that header on residential production requests for ttl_seconds (default 3600). The feature stays off until gateway.openai_codex_ticket is enabled.
Add the admin harvest-proxy field with masked responses, URL validation, five-second runtime caching and escaped i18n examples. Protect tickets from account edits and concurrent model probes, respect configured status policy, and remove unused burst-harvest code. Validated focused Go tests and race checks, API contracts, 44 frontend tests, server compilation and the production frontend build.
When the switch is off, the gateway does not harvest or inject x-codex-turn-state and forwards traffic as usual. When on, it harvests 292 tickets in the background and overwrites the header on production requests. The setting is live and does not require a restart.
Route synthetic probes directly through the harvest transport and propagate cancellation through settings, account reads, HTTP probes and persistence. Make start/stop idempotent and avoid mutating shared startup config for the live toggle. Scrub private ticket data from account exports and legacy extras, consistently exempt credential shadows, and display setup-token ticket status. Add lifecycle, concurrency, export, policy and UI regression tests.
The scheduling gate resolved the ticket model with requireCompact forced to false, while Forward rewrites the outbound model of a /responses/compact request to the compact mapping or gateway.openai_compact_model, which is non-empty by default. A compact request for a gated model therefore blocked every ticketless account under fail_closed even though the request actually leaves as a non-gated model and needs no ticket at all. Predict the outbound model with the same chain Forward uses and thread the compact flag, which both sides derive from IsOpenAIResponsesCompactPath, through the runtime block gate. Every other selection entry point passes false, so their behavior is unchanged.
Ticket extras are not part of filterSchedulerExtra's projection, so the bucket rebuild event that every ticket refresh enqueued could never carry ticket state anywhere. Mark the key prefix scheduler-neutral: UpdateExtra still syncs the single-account snapshot, so nothing loses freshness, but a refresh no longer opens a transaction or enqueues a rebuild. lockAndMergeAccountProbeExtra now reads the current extra on every account update across all platforms. A row whose extra is not a JSON object made that unmarshal fail the entire edit. Degrade to skipping ticket preservation instead, which self-heals on the next harvest, while still stripping administrator-supplied ticket keys.
…n-state-ticket feat(openai): add one-hour Codex tickets with live harvest proxy settings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Recover the withdrawn upstream Sub2API v0.2.6 merge commit
49a39b6dc1abed30fd227611e8af1108bc427610into the codexrip downstream tree.The merge includes the upstream changes after v0.2.5 plus the Codex
x-codex-turn-stateticket implementation. Ticket collection and injection remain disabled by default; the harvest proxy and live switch are available through the admin settings surface for a later, explicit activation.Integration decisions
.downstream/upstream-risk.jsonand.downstream/upstream-review-v0.2.6.mdusing the exact commit and tree rather than a missing remote tag.Validation
git diff --checkand conflict-marker checks passed.go test -run '^$' ./...) passed.go vet ./...andgo mod verifypassed.Production deployment, if this PR is merged and released, will use the existing immutable-digest
deploy-preservepath. No harvest proxy will be written and no ticket switch will be enabled by this change.