feat: sync billing header cc_version with User-Agent and add opt-in CCH signing

- Sync cc_version in x-anthropic-billing-header with the fingerprint
  User-Agent version, preserving the message-derived suffix
- Implement xxHash64-based CCH signing to replace the cch=00000
  placeholder with a computed hash
- Add admin toggle (enable_cch_signing) under gateway forwarding settings,
  disabled by default
This commit is contained in:
shaw
2026-04-08 16:11:19 +08:00
parent 5088e91566
commit e51c9e50b5
12 changed files with 317 additions and 17 deletions

View File

@@ -89,6 +89,7 @@ export interface SystemSettings {
// Gateway forwarding behavior
enable_fingerprint_unification: boolean
enable_metadata_passthrough: boolean
enable_cch_signing: boolean
}
export interface UpdateSettingsRequest {
@@ -146,6 +147,7 @@ export interface UpdateSettingsRequest {
allow_ungrouped_key_scheduling?: boolean
enable_fingerprint_unification?: boolean
enable_metadata_passthrough?: boolean
enable_cch_signing?: boolean
}
/**

View File

@@ -4268,6 +4268,8 @@ export default {
fingerprintUnificationHint: 'Unify X-Stainless-* headers across users sharing the same OAuth account. Disabling passes through each client\'s original headers.',
metadataPassthrough: 'Metadata Passthrough',
metadataPassthroughHint: 'Pass through client\'s original metadata.user_id without rewriting. May improve upstream cache hit rates.',
cchSigning: 'CCH Signing',
cchSigningHint: 'Sign the billing header in forwarded requests with CCH hash. When disabled, the placeholder is preserved.',
},
site: {
title: 'Site Settings',

View File

@@ -4431,6 +4431,8 @@ export default {
fingerprintUnificationHint: '统一共享同一 OAuth 账号的用户的 X-Stainless-* 请求头。关闭后透传客户端原始请求头。',
metadataPassthrough: 'Metadata 透传',
metadataPassthroughHint: '透传客户端原始 metadata.user_id不进行重写。可能提高上游缓存命中率。',
cchSigning: 'CCH 签名',
cchSigningHint: '对转发请求的 billing header 进行 CCH 哈希签名。关闭时保留原始占位符。',
},
site: {
title: '站点设置',

View File

@@ -1376,6 +1376,19 @@
</div>
<Toggle v-model="form.enable_metadata_passthrough" />
</div>
<!-- CCH Signing -->
<div class="flex items-center justify-between">
<div>
<label class="text-sm font-medium text-gray-700 dark:text-gray-300">
{{ t('admin.settings.gatewayForwarding.cchSigning') }}
</label>
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">
{{ t('admin.settings.gatewayForwarding.cchSigningHint') }}
</p>
</div>
<Toggle v-model="form.enable_cch_signing" />
</div>
</div>
</div>
</div><!-- /Tab: Gateway Claude Code, Scheduling -->
@@ -2248,7 +2261,8 @@ const form = reactive<SettingsForm>({
allow_ungrouped_key_scheduling: false,
// Gateway forwarding behavior
enable_fingerprint_unification: true,
enable_metadata_passthrough: false
enable_metadata_passthrough: false,
enable_cch_signing: false
})
const defaultSubscriptionGroupOptions = computed<DefaultSubscriptionGroupOption[]>(() =>
@@ -2556,7 +2570,8 @@ async function saveSettings() {
max_claude_code_version: form.max_claude_code_version,
allow_ungrouped_key_scheduling: form.allow_ungrouped_key_scheduling,
enable_fingerprint_unification: form.enable_fingerprint_unification,
enable_metadata_passthrough: form.enable_metadata_passthrough
enable_metadata_passthrough: form.enable_metadata_passthrough,
enable_cch_signing: form.enable_cch_signing
}
const updated = await adminAPI.settings.updateSettings(payload)
Object.assign(form, updated)