Repository navigation
chore: merge upstream v0.2.13 preserving downstream contracts - #232
Merged
Merged
Conversation
分组开启 claude_code_only 并配置降级分组时,/v1/messages 会在选号入口的 checkClaudeCodeRestriction 中把非 Claude Code 请求解析到降级分组;但 GatewayHandler.ChatCompletions / Responses 在 handler 层只要分组开了 claude_code_only 就直接返回 403,不看降级分组,请求到不了调度层:只会发 Chat Completions / Responses 的第三方客户端拿这类分组的 Key 一律 403。 - handler 层提前拒绝只在未配置降级分组时生效,拒绝的状态码与文案不变 - 配置了降级分组时请求继续,由 SelectAccountWithLoadAwareness 解析到降级分组 选号,再经已有的 Chat Completions / Responses ⇄ Anthropic Messages 转换转发; service 层无改动 - 与 /v1/messages 的降级语义一致:选号与渠道限制预检按降级分组,计费与用量 记录仍按 API Key 所属分组 新增 handler 单测覆盖两个入口在有/无降级分组时的行为。
Replace the static priority number in the accounts table with a compact stepper: hover reveals -/+ buttons, clicking the value allows typing (Enter to save, Esc to cancel, arrow keys to nudge). Rapid clicks are debounced into a single priority-only PUT, failures revert the value and surface a toast, and the row is patched in place without a full reload. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
disabled:opacity-30 overrode opacity-0, so the decrement button stayed faintly visible on every row already at the minimum. Style disabled buttons via text colour instead, and raise idle icon contrast. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
POST /api/v1/payment/public/orders/verify is unauthenticated and still used by PaymentResultView as a fallback, so keep it but cap it at 20 req/min per client IP (fail-open on Redis errors) to make out_trade_no enumeration impractical without affecting users mid-payment. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ient The antigravity Gemini forward path returned the raw upstream Google error body to end users, which can contain consumer project numbers, GCP project IDs and service account emails. Return a Gemini-style error body with only code/status and a scrubbed message; raw body stays in ops logging. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…okens - Verification code attempts (register + notify email) are now reserved via an atomic Redis INCR (Lua) before comparing, so concurrent wrong guesses cannot exceed the 5-attempt cap. - Password reset tokens are stored as SHA-256 hashes and consumed with an atomic Lua compare-and-delete, so a token can only be used once even under concurrent requests. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Balance-mode admission only checked cached balance > threshold, so N concurrent expensive requests could all pass and overdraw the user. Add a Redis in-flight reservation: at admission estimate a conservative per-request cost (input estimate + output price x max_tokens, times rate multiplier) and atomically require cached_balance - inflight >= estimate (first in-flight request always admitted). Reservations are released via defer on every path and expire by TTL. Fails open on estimation / Redis errors. Configurable via billing.inflight_reservation (enabled by default). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…timate like billing; wire remaining endpoints Address gaps found in adversarial verification of the in-flight balance reservation: - Early release: the reservation is now a ref-counted handle carried on the request context. Billing tasks submitted via submit*UsageRecordTask take a ref and return it only after RecordUsage has run; with reservation enabled the balance cache is deducted synchronously inside the billing task, so the reservation is released only after admission can see the deduction. Dropped tasks return their ref immediately. The reservation is renewed every ttl/3 while the handler runs; after the handler returns it is no longer renewed, so the post-handler hold is bounded by one TTL. - Estimate: use the same billing model (channel mapping + BillingModelSource, max over requested/mapped when ambiguous) and ModelPricingResolver (group ModelPricing incl. wildcards, channel per_request/image/video/token overrides), default/group/user rate + peak multiplier, plus image, video, audio and search surcharge kinds. Unpriced requests fail open with a throttled log; new billing.inflight_reservation.fail_closed_on_unpriced (default false) rejects them instead. - Wire images, embeddings, web/x search, alpha search, grok media generation, grok realtime/voice, OpenAI-platform /v1/messages and ResponsesWebSocket (session-level reservation with renewal). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…don't renew expired reservations - Inflight estimate now mirrors billableModelWithFallback: when the primary billing model has no price, fall back to the channel-mapped model (also for billing_model_source=requested) and to account-level mapped models (max over schedulable accounts in the group, cached 30s). - Composite groups also consider concrete account-mapped models (max) so the alias' family fuzzy price cannot underestimate. - Renew Lua refuses (and purges) members whose score <= now. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…y when unpriced - only consult account mappings after primary/channel candidates fail to price (or composite) - source mappings from the scheduler snapshot (same pool as account selection), no direct DB query and no per-model cache - ungrouped API keys use the scheduler's ungrouped pool - no negative caching: new mappings take effect on the next request Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The create form shows the upstream billing auto-probe toggle for every
API-key platform and enables it by default. TypeSafe was added as an
API-key platform but not to IsUpstreamBillingProbeIdentity, so creating a
TypeSafe account with the default form state fails with
400 UPSTREAM_BILLING_PROBE_ACCOUNT_INVALID ("account is not an API key
account").
TypeSafe accounts store credentials.api_key/base_url like every other
API-key platform, which is all the probe reads. Add TypeSafe to the probe
identity set, and add typesafe.ai to the official API domains so accounts
on the default https://api.typesafe.ai base URL record "unsupported"
without sending the key to a path that cannot exist, matching the other
official providers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs: add security policy with private vulnerability reporting
… completes When an API key with quota or rate limits was deleted while a request was still in flight, the key counter update matched no rows and returned ErrAPIKeyNotFound, rolling back the whole billing transaction including the balance/subscription charge. Skip the key-scoped counters in that case and keep settling the user and account side as usual.
…ted-key fix(billing): settle usage when the API key is deleted before billing completes
…am-billing-probe fix(billing): allow upstream billing probe for TypeSafe API-key accounts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream v0.2.13 (3040209) merged at upstream/main b8dece9, which adds only the VERSION sync. v0.2.12 lies inside the range. 26 upstream commits, 157 paths; 16 conflicted. Adopted as upstream: the TypeSafe / Jev System One platform (POST /v1/systemone, API-key accounts, jev-latest), recharge bonus tiers, the account priority quick adjust, the public order verify rate limit, the Antigravity client error scrubbing, atomic verification codes with hashed single-use reset tokens, the Grok CLI identity update, usage settlement for deleted API keys and API key sorting by group. Downstream contracts kept at the conflicts: - GatewayHandler.Models keeps the generic non-Anthropic fallback; defaultModelIDsForPlatform gains the TypeSafe case. - Quota tables, default quota settings and dashboard cards keep the lists derived from CONCRETE_PLATFORM_VALUES; platformColors keeps accent(). - The TypeSafe API-key-only check runs before the downstream credential normalization and capacity override validation. - The TypeSafe connection test joins the downstream test dispatcher. - The jev-latest fallback price is added; the DeepSeek fallback block stays removed. Adaptations of auto-merged code: accountTestCatalog returns the TypeSafe entry instead of writing the response, and parseTestSSEOutput returns three values. Fixtures that pinned ten concrete platforms pin eleven; the name filter of the downstream-verify quota step follows the two renamed tests. frontend/package.json, pnpm-lock.yaml, go.mod and go.sum are unchanged: axios 1.20.0 was already downstream. Generated ent code matches the schema. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Connection and batch tests resolve jev-latest for a TypeSafe account instead of a Claude model name; the reasoning resolver offers no effort. - The TypeSafe connection test reports the transport error and the whole upstream body, like every downstream connection test. Upstream sanitized the error and cut the body to 2000 bytes. - TypeSafe accounts are not eligible for the API-key model catalog refresh: System One has no model list and the sync request rejects the platform, so a refresh could only fail and back off. - The composite capacity pool uses matchingPlatforms(PlatformComposite) instead of a second platform list, so TypeSafe accounts of a composite group contribute their capacity rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…abases Upstream's 241_add_typesafe_platform.sql sorts before the downstream files that re-create user_platform_quotas_platform_check (241 compat, 251, 260). A new database therefore ended with ten platforms and no typesafe, while a database already past 260 applies upstream's file last and keeps eleven. 264 states the eleven-platform CHECK once more at the tail: SET LOCAL lock and statement timeouts, DROP IF EXISTS plus ADD, no row written, a no-op when repeated. The composite route CHECK needs nothing: no downstream file re-creates it after upstream's 241. TestTypeSafeStaysInTheFinalPlatformChecks pins the last file that defines each constraint and the shape of the tail file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Accounts table: a click inside the priority control no longer reaches the row, which opens the details drawer downstream. The control is the value of the stacked priority line and its steppers take the label tone. - Create account dialog: the eleventh platform segment (TypeSafe) takes the sky identity glyph. - Recharge tier editor: the mode toggle carries the static seg-box hook. Behaviour stays upstream's. No :has() and no runtime-bound hook is added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fest upstream-risk.json is regenerated with .github/scripts/upstream_risk.py for v0.2.11..v0.2.13 against 06e865f: review_required, 157 upstream paths, 65 overlapping, 31 critical, no remaining conflict. The 16 initially conflicted paths are recorded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n Ops Upstream's System One forwarder recorded only the extracted error message (empty unless the body has error.message, detail or message) and, for a 2xx response it cannot relay, only "typesafe invalid response". The client gets a fixed sentence and no log line carried the body, so an administrator had no way to read what the upstream answered. Every other forward path keeps the body in the Ops record. - handleSystemOneErrorResponse records the body bounded by gateway.log_upstream_error_body[_max_bytes], as handleErrorResponse does: in the top-level Ops detail, in the event's Detail and (the event is passthrough) UpstreamResponseBody, and in the service body log line. - DecodeSystemOneResponse returns the body it read but did not accept in a SystemOneResponseError, so the response_error event carries it too. The error text and errors.Is(err, ErrSystemOneResponseTooLarge) are unchanged. - The client response is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…swer
Upstream's TypeSafe connection test passes on any HTTP 200 JSON object, so
a relay or a wrong base URL that answers {} or an error envelope with 200
counted as a healthy account, and a passed test recovers the account's
error and rate-limit state (single, batch and scheduled tests).
Downstream connection tests need a valid protocol terminal. The test now
passes only when the response answers the question it asked:
answers.connection_test of type noul with a probability between 0 and 1.
typesafe.NoulScore checks that with the answer validator Evaluate applies,
now one shared function. Any other 200 body fails with the body as it was
received and changes no account state.
The two upstream fixtures that passed without a valid answer get one, and
TestTypeSafeAccountTestRequiresAnswerToItsQuestion pins the failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…m file Upstream's 241_add_typesafe_platform.sql relies on its quota list being a superset of 238's. The downstream 238 (and 237) list cindy, so with upstream's bytes a downstream database that has not reached 260 and still holds cindy quota rows fails on this file and startup stops, although the same database upgrades in one start on the current release, where 260 deletes those rows before it re-creates the CHECK. Carry cindy in the quota list of the still unrecorded file, as 237 and 238 do. 260 then removes the rows and the value, and 264 states the final eleven platforms on every path. Production (past 263, no cindy row) is unaffected: it gets the wider list from 241 and the final one from 264 in the same start. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Coverage: 84 of the 93 upstream-only paths are byte-identical to upstream/main and the nine adapted ones are named; 44 of the 48 auto-merged overlapping paths carry exactly upstream's line changes, and platforms.spec.ts is listed as adapted next to account_handler.go. - SettingsView.spec.ts and UserPlatformQuotaModal.spec.ts had four conflict hunks each, not five. - The Codex catalog exclusion of TypeSafe holds for composite groups; a TypeSafe group's own manifest lists jev-latest, as upstream. - Record the System One Ops body, the connection test success rule and cindy in the 241 quota list; the known restriction for databases older than 260 is gone. List the checks run again on the final tree. - settings-ops-public.css 2.2: the positional p-4 body rule also reaches upstream's RechargeBonusTierEditor card; the comment names both cards (rule unchanged). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The connection test's success rule relies on the noul answer shape that upstream's own client requires of every content moderation answer. Record that it was not checked against the live API here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The upstream event for a 2xx response the gateway cannot relay carried the decoder's error text, which is either the invalid response or the size limit error. - A TypeSafe connection test whose 200 body cannot be read reports the read error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
264 is taken by a separate downstream change (Codex runtime plugin state removal) that merges on its own schedule. Neither file has been applied anywhere, so only the name and the references to it change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One conflict, backend/internal/service/admin_account.go: upstream's TypeSafe API-key-only check stays, and the maps.Clone(accountExtra) line that #233 removed stays removed. The risk manifest is regenerated against the new downstream commit and the review document names it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HTExplicit
added a commit
that referenced
this pull request
Oct 4, 2026
…ired settings and options deleted (#235) Ships with the upstream v0.2.13 integration (#232) as v0.2.13-codexrip.1. Owner decisions of 2026-10-03 and 2026-10-04. Group profit control is upstream's again: the kill switch, the 400 on profit_* fields, the snapshot constants and the read-only "retired" block are gone; the code and its tests equal upstream v0.2.13, and the Codex models manifest stays outside the gate. Auth snapshot version 28. Signature recovery keeps its logic and follows one global switch, default on: settings row reasoning_recovery_config, read from memory on the forwarding path, GET/PUT /api/v1/admin/reasoning-recovery, page 推理恢复 under 扩展功能. Chat reasoning replay and the two per-account reasoning options are deleted. The rejected-cipher memory runs on one long-lived Redis client with the budget as the absolute deadline. Deleted: the two retired OpenAI API-key compatibility settings with their read-only block, the stop reason policy_unavailable, the dated live reasoning diagnostic. TypeSafe account dialogs show their own hints, and an upstream model sync is offered and started only where the backend can list models. A system prompt binding is offered and stored only for platforms with an insertion point. Migrations: 266 deletes the two retired settings rows, 267 removes the two reasoning option keys from accounts.extra, 268 removes system prompt bindings from accounts on a platform without an insertion point. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Integrates official
v0.2.13(3040209f2, plus the VERSION syncb8dece900) on top ofv0.2.11-codexrip.8. Covers the two official releases since the last integration: 26 non-merge commits, 157 paths.Do not merge yet. The owner decided on 2026-10-03 to ship the upgrade together with the follow-up changes (profit control back to upstream, reasoning recovery as one global setting, removal of the deprecated-settings block) as a single
v0.2.13-codexrip.1. This PR is open so that the required checks run early.What is adopted
Every official change, with official behaviour:
POST /v1/systemoneDownstream contracts kept
Details and per-file resolutions are in
.downstream/upstream-review-v0.2.13.md.CONCRETE_PLATFORM_VALUES,defaultModelIDsForPlatform,accent()colour tokens, composite capacity pool) instead of upstream's literal lists.jev-latestgets no static window.Migrations
241_add_payment_order_bonus_amount.sqlis byte-identical.241_add_typesafe_platform.sqlcarriescindyin the quota list, as the downstream copies of 237 and 238 do, so a database that has not reached 260 still upgrades in one start.265_user_platform_quota_typesafe_union.sqlstates the final eleven-platform quota CHECK. Without it a new database ends withouttypesafe, because upstream's 241 sorts before the downstream files that re-create that CHECK.Verification
Run locally on the final tree: backend build (windows and linux),
go vetwith every build tag,golangci-linton the touched packages, the Go tests that live in conflicted files or pin the adapted behaviour,vue-tsc,eslinton changed files, and vitest for the conflicted, new and modified-component specs.Not run locally: full and race suites, database-backed integration tests, any migration rehearsal against PostgreSQL (the migration analysis is by reading), real TypeSafe or model calls. The noul answer shape required by the TypeSafe connection test comes from upstream's own client and was not checked against the live API.
Closes #225, closes #228.
🤖 Generated with Claude Code