Commit Graph
783 Commits
Author SHA1 Message Date
erio 14bb922a92 chore: bump version to 0.1.114.16 2026-04-20 18:20:31 +08:00
erio 7207c5553b chore: bump version to 0.1.114.15 2026-04-20 18:07:46 +08:00
erio 26e7d969e8 fix(tlsfingerprint): realign TLS+headers to Claude Code 2.1.114 baseline
Merge hai/snapshot fingerprint update into release branch, preserving
our architectural optimizations (SOCKS5 ContextDialer, identity_service
refactoring, slog migration, capture_fingerprint multi-file structure).

TLS defaults: 52→17 ciphers, 5→3 curves (drop MLKEM768/P521),
2→1 key share (X25519 only), 3→1 point format, 26→9 sig algs.
New probabilistic ECH GREASE + padding (~50% per handshake).
Extension order realigned: server_name first, encrypt_then_mac removed,
status_request/SCT added.

Headers: UA 2.1.114, Runtime v24.3.0 (bundled Node), Timeout 600.
New BetaStructuredOutputs20251215 for Haiku title-sidecar requests.
2026-04-19 22:21:51 +08:00
erio e20a57f53e refactor(scheduled-test): switch to minimal PR 1753 approach
Replace the 4-file service-layer cleanup with the upstream PR's simpler
transaction-level DELETE in accountRepository.Delete.

Bump version to 0.1.114.13.
2026-04-19 20:44:19 +08:00
erio f68894191b chore: bump version to 0.1.114.12 2026-04-19 20:30:01 +08:00
erio edf20829ba Merge remote-tracking branch 'origin/feat/fix-orphaned-scheduled-tests' into release/custom-0.1.114 2026-04-19 20:26:49 +08:00
erio 79e100a1cf fix: delete scheduled test plans when account is deleted
Accounts use soft-delete (setting deleted_at), so PostgreSQL's
ON DELETE CASCADE on scheduled_test_plans.account_id never fires.
This leaves orphaned plans that continue executing and cannot be
managed from the frontend since the account no longer exists.

Closes Wei-Shaw/sub2api#1728
2026-04-19 20:22:18 +08:00
erio a4209ab4f8 chore: bump version to 0.1.114.11 2026-04-19 19:14:59 +08:00
erio 35bdd1400e chore: bump version to 0.1.114.10 2026-04-19 15:18:14 +08:00
erio 78de54b693 feat(signature): activate PoolRectifier + harvester hookup
Introduces the pool-replace retry strategy end-to-end. When
RectifierSettings has SignaturePoolSize>0 and the account's per-type
sub-switch is on, the factory returns a PoolClaudeRectifier /
PoolAntigravityRectifier that fetches the freshest signatures from the
Redis pool and cycles them through the request's thinking blocks
(M>N cycling). Rule A: an empty pool transparently passes the
original upstream error back — no fallback to strip.

Key pieces:
  - PoolClaudeRectifier / PoolAntigravityRectifier in internal/service/signature
  - signatureRectifierFactory in the service package selects strategy per
    request via shouldUsePool(ctx, account) which implements the agreed
    decision table (Enabled + SignaturePoolSize>0 + per-type sub-switch)
  - WrapResponseBody helper on the factory is invoked at each Claude-native
    DoWithTLS entry point (main Forward, Anthropic passthrough, Bedrock) to
    run the Harvester over the upstream body; no-op when pool disabled
  - ctxkey.IsSignatureRectifyRetry is set on all retry contexts (Claude
    two-stage, count_tokens, Antigravity signature retries) so the harvester
    skips ingesting signatures from retry responses and does not pollute the
    pool with values we ourselves injected
  - NewGatewayService / NewAntigravityGatewayService now accept
    signature.SignaturePool; wire_gen.go updated accordingly

Antigravity responses are raw Gemini format so WrapResponseBody is not
called there — harvesting stays Claude-only as designed. Antigravity can
still *read* from the shared OAuth pool on retry; whether cross-ecosystem
signatures verify upstream is the question the future PoC will answer.
2026-04-19 13:51:22 +08:00
erio 2a7272429f fix(payment): size popup to fit alipay checkout without any scrolling
Alipay's page is ~1200x900; a fixed 1250x780 still clipped vertically.
Replace the constant with getPaymentPopupFeatures(): it prefers
1250x900, clamps to window.screen.avail*, and centers the popup so
it never overflows the visible work area on smaller laptops.

Drop POPUP_WINDOW_FEATURES and STRIPE_POPUP_WINDOW_FEATURES in favor of
the helper — all five call sites migrated.

Bump version to 0.1.114.9
2026-04-19 01:32:17 +08:00
erio 4b948e3917 fix(payment): widen popup to 1250x780 so alipay checkout fits without scrolling
Alipay's standard checkout (QR + account login panel) needs ~1200px
width. The default popup was 1000x750, forcing a horizontal scrollbar.
Unify to the wider size that the Stripe-alipay popup already used.

Bump version to 0.1.114.8
2026-04-19 01:24:53 +08:00
erio b3897940b8 fix(payment): stripe publishableKey must not be masked in admin GET
Previous pattern-based isSensitiveConfigField treated any key containing
"key" as a secret and stripped it from the admin response, which wrongly
hid Stripe's publishableKey (a public value). Edit dialogs then failed
its required-field validation because the backend no longer returned it.

Replace the pattern matcher with an explicit per-provider registry that
mirrors the frontend PROVIDER_CONFIG_FIELDS, so only true secrets are
masked/preserved:

- alipay: privateKey, publicKey, alipayPublicKey
- wxpay: privateKey, apiV3Key, publicKey
- stripe: secretKey, webhookSecret (publishableKey stays plaintext)
- easypay: pkey

Bump version to 0.1.114.7
2026-04-19 01:10:43 +08:00
erio 2599b9f278 feat(payment): hide secret config fields in admin GET and preserve on empty PUT
- Strip sensitive provider config keys (privateKey/publicKey/apiV3Key/
  secretKey/webhookSecret/pkey/password/etc.) from admin list/detail API
- mergeConfig: empty value for a sensitive key preserves the stored secret
- Admin dialog: sensitive inputs add autocomplete="new-password" +
  data-*ignore + spellcheck="false" to block browser password managers;
  edit-mode placeholder shows "leave empty to keep"; skip required
  validation for sensitive fields when editing

Bump version to 0.1.114.6
2026-04-19 01:01:19 +08:00
erio dcf56340be chore: bump version to 0.1.114.5 2026-04-18 23:46:28 +08:00
erio ad754c905c chore: bump version to 0.1.114.4 2026-04-18 23:28:29 +08:00
erio 73c87fe3c5 chore: bump version to 0.1.114.3 2026-04-18 23:16:09 +08:00
erio cfd9566905 feat(tls-fingerprint): show binding count + fix randomized fingerprint visibility (v0.1.114.2)
## Bug fixes
- EditAccountModal: auto-generated profiles (__auto__:acc-*) are no longer
  hidden from the dropdown; accounts bound to their own auto profile can
  now see and keep the selection.
- AccountResponse DTO: emit tls_fingerprint_randomized so the "randomized"
  badge and reshuffle affordance render on subsequent edits.

## Feature
- TLS fingerprint profile list returns bound_account_count per profile,
  aggregated via a single grouped SQL query over accounts.extra.
- Dropdowns and admin management table surface the binding count so admins
  can judge whether a fingerprint is shared before editing or deleting it.

## Performance
- Migration 108 adds a partial + expression index on
  (extra->>'tls_fingerprint_profile_id') WHERE extra ? '...',
  enabling Index Only Scan + HashAggregate for the new query.
- Extraction uses (extra->>'...')::bigint so PostgreSQL performs the cast;
  Go-side parsing and NullString plumbing are removed.

## Backend
- AccountRepository: add CountByTLSFingerprintProfile; implement in ent
  repo via grouped raw SQL.
- TLSFingerprintProfileService: add ProfileWithBinding + ListWithBindingCount.
- Admin handler List now returns the enriched payload.
- AccountResponse DTO: add tls_fingerprint_randomized (optional, omitempty).
- Update all five AccountRepository test stubs for the new interface method
  (account_service_delete_test, gateway_multiplatform_test,
  gemini_multiplatform_test, ratelimit_session_window_test,
  server/api_contract_test).

## Frontend
- TLSFingerprintProfile type: add optional bound_account_count.
- EditAccountModal + CreateAccountModal: show " (N)" suffix on options
  with active bindings; drop the auto-profile filter.
- TLSFingerprintProfilesModal admin table: new "使用中 / In use" column
  with amber-highlighted count.
- i18n zh/en: add columns.boundAccounts.

## Compatibility
- New fields are all optional (omitempty) — existing OAuth accounts and
  older frontends behave as before.
- No data migration required; empty extra entries are ignored by index
  and aggregation alike.
2026-04-18 21:45:17 +08:00
erio 6d0e056244 feat(fingerprint): Claude Code CLI fingerprint mimicry suite (v0.1.114.1)
Squash-merge feat/fingerprint-mimic into release/custom-0.1.114.

Functional changes:
- TLS ClientHello mimicry: 17→52 cipher suites, ALPN http/1.1 only,
  X25519MLKEM768, JA3/JA4 aligned with official CLI baseline
- HTTP layer: User-Agent 2.1.112 sdk-cli, 3 new anthropic-beta tokens,
  Stainless headers synced
- Sidecar traffic: usage poll + count_tokens injection + startup probe
  (three fire-and-forget channels with jittered intervals)
- Sticky session UUID: per-account metadata.user_id reuse via Redis,
  WithSessionHash propagation through gateway
- 429 no-switch: short-circuit on rate-limit instead of cross-account fail-over
- Admin UI: per-account "randomize fingerprint" button + ConfirmDialog +
  i18n (zh/en, 9 keys)

Engineering hardening (fixes carried over from hai/snapshot):
- safe.Go/Run package: panic-recovering goroutine helper with slog
- redis.Nil treated as cache miss in identity cache
- SOCKS5 dialer uses ContextDialer for ctx cancellation propagation
- Token refresh selects on stopCh during retry backoff
- Sidecar goroutines wrapped with safe.Go
- .gitattributes forces LF for *.json (fixes baseline file CRLF drift)

Refactoring (zero behavior change):
- sidecar probe constants centralized
- identity_service rewrite preflight extracted into helpers
- capture_fingerprint tool split from 894 lines into 9 files
- gofmt sweep on all hai-imported files

Tests:
- safe package: panic recovery + attrs propagation
- tlsfingerprint: SOCKS5 dialer + capture parity
- identity sticky-session preflight paths (early-return + cache-hit)
- sidecar probe: jittered interval + dry-run
- token refresh: graceful shutdown during backoff

Beta-validated on 0.1.112.21 (commit 565da163 of feat/fingerprint-mimic).
Bumps VERSION 0.1.112.20 -> 0.1.114.1.
2026-04-18 16:07:36 +08:00
erio d359c1f762 chore: bump version to 0.1.112.20 2026-04-17 19:34:52 +08:00
erio 7acec3a60d chore: bump version to 0.1.112.19 2026-04-17 18:32:53 +08:00
erio 017f517a38 chore: bump version to 0.1.112.18 2026-04-17 17:01:26 +08:00
github-actions[bot] 6cfdf4ec05 chore: sync VERSION to 0.1.114 [skip ci] 2026-04-17 02:51:18 +00:00
erio 645271d07a chore: bump version to 0.1.112.17 2026-04-16 01:34:03 +08:00
github-actions[bot] be7551b9f4 chore: sync VERSION to 0.1.113 [skip ci] 2026-04-15 09:34:24 +00:00
erio dc743a91b9 feat(usage): add account cost display to admin dashboard and usage pages
- Add account_cost column to dashboard aggregation tables (migration 107)
- DashboardStats: add TotalAccountCost/TodayAccountCost fields
- ModelStat/GroupStat: add AccountCost field with SQL aggregation
- GetStatsWithFilters: always return TotalAccountCost (remove accountID filter)
- Dashboard Token cards: show user(green)/cost(orange)/standard(gray)
- Usage stats card: show account cost and standard below main value
- Model/Group distribution tables: add orange cost column
2026-04-15 13:47:38 +08:00
erio 2436478dfe chore: bump version to 0.1.112.15 2026-04-15 11:13:04 +08:00
erio 374211bbe4 chore: bump version to 0.1.112.14 2026-04-15 01:56:50 +08:00
erio 40797fda77 chore: bump version to 0.1.112.13 2026-04-15 01:43:37 +08:00
erio 6c87ee45aa chore: bump version to 0.1.112.12 2026-04-15 01:41:03 +08:00
erio a0beed6616 chore: bump version to 0.1.112.11 2026-04-15 01:20:46 +08:00
erio 36fc547fbd chore: bump version to 0.1.112.10 2026-04-15 01:11:49 +08:00
erio e7963b3ddc chore: bump version to 0.1.112.9 2026-04-15 01:04:01 +08:00
erio 509b451c9a chore: bump version to 0.1.112.8 2026-04-15 00:41:49 +08:00
erio c83283b9e8 chore: bump version to 0.1.112.7 2026-04-15 00:18:40 +08:00
erio 358eb897e4 chore: bump version to 0.1.112.6 2026-04-14 21:55:25 +08:00
erio d19e8385fa refactor: align Antigravity/ClaudeMax/Sora code with upstream main
- Restore 14 Antigravity/model-mapping files to upstream/main versions
  - Remove fork-specific credits pre-check and degraded retry logic
  - Revert sonnet 4.5→4.6 model mapping back to upstream defaults
  - Remove accountUsageService dependency from AntigravityGatewayService
  - Restore original applyThinkingModelSuffix behavior
- Delete 6 fork-only migration files:
  - 056/057 (Antigravity model mapping)
  - 060 (Claude Max simulation)
  - 070 (Sora tasks table)
  - 077/078 (sonnet rollback/migration)
- Fix wire_gen.go to match updated constructor signature
2026-04-14 21:28:20 +08:00
erio 3d2027227b fix: update wire_gen.go to use ProvideSchedulerCache with config injection
wire_gen.go was calling NewSchedulerCache(redisClient) but wire.go had
been updated to register ProvideSchedulerCache(redisClient, config),
which reads SnapshotMGetChunkSize and SnapshotWriteChunkSize from config.
Without this fix, those config values were silently ignored.
2026-04-14 20:22:45 +08:00
erio 6ac8ccde46 fix: merge 30 general improvements from release branch
Bug fixes:
- Detached context for GetAccountConcurrencyBatch (prevent all-zero on request cancel)
- Filter soft-deleted users in GetByGroupID
- Stripe CSP policy (allow Stripe.js in script-src and frame-src)
- WebSearch API key validation on save
- RECHARGING status in payment result success check
- Windows test fixes (logger Sync deadlock, config path escaping)

Feature enhancements:
- Webhook multi-instance dispatch (extractOutTradeNo + GetWebhookProvider)
- EasyPay mobile H5 payment (device param + PayURL2)
- SSE error propagation in WebSearch emulation
- AccountStatsCost DTO field for admin usage logs
- Plans sort by sort_order instead of created_at
- UsageMapHook for streaming response usage data
- apicompat Instructions field passthrough
- EffectiveLoadFactor for ops concurrency/metrics
- Usage billing RETURNING balance for notify system
- BulkUpdate mixed channel warning with details
- println to slog migration in auth cache
- Wire ProviderSet cleanup
- CI cache-dependency-path optimization

Frontend:
- Refund eligibility check per provider (canRequestRefund)
- Plan sort_order editing
- Dead code cleanup (simulate_claude_max, client_affinity)
- GroupsView platform switch guard
- channels features_config API type
- UsageView account_stats_cost export
2026-04-14 17:35:27 +08:00
erio 24e16b7f59 fix: restore resolveOpenAIMessagesDispatchMappedModel and reset VERSION
- Restore function deleted during cherry-pick conflict resolution
- Reset VERSION to upstream 0.1.112
2026-04-14 10:58:51 +08:00
erio d6965b0676 fix: resolve cherry-pick conflicts and restore compilation
- Restore gateway_cache.go to upstream (no lua embeds)
- Restore payment_order.go to upstream (use out_trade_no lookup)
- Restore payment_fulfillment.go to upstream (same reason)
- Add FeaturesConfig field and IsWebSearchEmulationEnabled to Channel
- Add applyAccountStatsCost wrapper function
- Add SettingKeyWebSearchEmulationConfig constant
- Add WebSearchEmulationEnabled to SystemSettings
- Add notify code rate limiting methods to EmailCache interface
- Remove AllowUserRefund references (ent schema not present)
- Fix duplicate import in payment_handler.go
- Fix wire_gen.go argument mismatches
2026-04-14 10:18:39 +08:00
erio 3be0321bfe fix: Stripe payment type matching in load balancer
Checkout page aggregates Stripe sub-types (card,link,alipay,wxpay) under
"stripe", but SelectInstance matched against supported_types literally,
which doesn't contain "stripe". Now matches by provider_key for Stripe.
2026-04-14 09:50:12 +08:00
erio 7c7292935e feat: websearch quota enhancements and balance notify hint
- QuotaLimit changed to *int64 (null=unlimited, >0=limited)
- Add reset-usage endpoint (POST /admin/settings/web-search-emulation/reset-usage)
- Show quota usage in header always (collapsed and expanded)
- Add reset quota button in expanded provider view
- Quota input: empty=unlimited with ∞ placeholder, must be >0 if set
- Add email verification hint on balance notify card
2026-04-14 09:36:40 +08:00
erio 9e0d12d3b0 fix: show websearch API key visibility/copy buttons for saved providers
The buttons were hidden because v-if only checked provider.api_key,
which is always empty for saved providers (backend sanitizes it).
Now also checks api_key_configured. Copy button is disabled when
no actual key is available (only configured placeholder shown).
2026-04-14 09:35:46 +08:00
erio 1b7c295199 refactor: M5 useQuotaNotifyState composable + H14 Vue file splits
M5: New composable frontend/src/composables/useQuotaNotifyState.ts
  - Replaces 9 individual refs in both Create/Edit modals with reactive state
  - Provides loadFromExtra/writeToExtra/reset helpers
  - Eliminates ~120 lines of duplicated code across the two modals

H14: Vue file length violations fixed
  - AdminPaymentPlansView.vue: 325 → 183 lines (extracted PlanEditDialog.vue)
  - QuotaLimitCard.vue: 327 → 268 lines (extracted QuotaDimensionRow.vue)
  - PlanEditDialog.vue: 181 lines (new, plan create/edit form)
  - QuotaDimensionRow.vue: 108 lines (new, single quota dimension row)
2026-04-14 09:33:39 +08:00
erio 594f0d17d1 refactor: batch 3 — decompose CheckBalanceAfterDeduction, merge crossing checks, add QuotaNotifyConfig
M1: CheckBalanceAfterDeduction (63→18 lines) decomposed into:
    canNotifyBalance, resolveUserEffectiveThreshold, crossedDownward, dispatchBalanceLowEmail
M3: New Account.QuotaNotifyConfig(dim) method replaces 9 hardcoded getters
    (getters kept as thin wrappers for backward compatibility)
M4: checkQuotaDimCrossings + checkQuotaDimCrossingsFromState merged into one
    function taking pre-built []quotaDim; caller builds dims conditionally
2026-04-14 09:33:00 +08:00
erio 9d319cfa2d fix: batch 2 audit fixes — diffSettings notify fields, slog migration, frontend constants
H5: diffSettings now tracks 5 balance/quota notify fields in audit log
M15: log.Printf audit log migrated to slog.Info, removed "log" import
M14: New frontend/src/constants/account.ts with shared constants
     QuotaNotifyToggle.vue uses QUOTA_THRESHOLD_TYPE_FIXED/PERCENTAGE
L2: UsageTable.vue uses BILLING_MODE_TOKEN/IMAGE from billingMode.ts
2026-04-14 09:32:24 +08:00
erio ed8a9d975b fix: batch 1 audit fixes — quota SQL fixed mode, public recharge URL, WebSearch bool fallback, UpdatePlan validation
H1: incrementUsageBillingAccountQuota now uses shared dailyExpiredExpr/weeklyExpiredExpr
    constants (supporting fixed reset mode) instead of hardcoded '24 hours'/'168 hours'
H4: public settings endpoint now maps balance_low_notify_recharge_url
H6: GetWebSearchEmulationMode tolerates legacy bool values (true→enabled)
H7: UpdatePlan validates non-nil patch fields (rejects negative price, empty name, etc.)
H8: UsageTable accountBilled() helper with total_cost ?? 0 null guard
H9: AdminUsageLog TS type adds channel_id + billing_tier
M2: account.go "fixed" literals replaced with thresholdTypeFixed constant
M13: SystemSettings TS type adds web_search_emulation_enabled
UI: QuotaLimitCard title labels now use flex-1 to align with flex-1 input boxes
2026-04-14 09:32:11 +08:00
erio a43da62254 fix(accounts): unify modal width, add notify props to create, fix quota layout
- EditAccountModal width changed from "normal" to "wide" (match CreateAccountModal)
- CreateAccountModal now passes all quota notify props to QuotaLimitCard
- QuotaLimitCard: when global notify disabled, hide title row, input takes full width
- Quota alert email: show remaining quota + threshold (fixed/$, percentage/%) instead of usage trigger point
2026-04-14 09:31:32 +08:00
erio 6e9146e746 fix(notify): add recharge URL to admin settings GET response 2026-04-14 09:31:08 +08:00