Skip to content

fix(trae): 15 位设备号通过签到形态闸门 / mint 15-digit device ids so check-in claims pass - #475

Merged
caigee-cmd merged 1 commit into
caigee-cmd:mainfrom
BrianBoyCN:fix/trae-device-bound-checkin
Nov 8, 2026
Merged

caigee-cmd merged 1 commit into
caigee-cmd:mainfrom
BrianBoyCN:fix/trae-device-bound-checkin

Conversation

@BrianBoyCN

Copy link
Copy Markdown
Contributor

中文

问题现象

通过登录流程添加的 Trae CN 账号,每日签到固定失败:

trae checkin claim rejected (code 9074): 当前参与用户太多,请稍后再试

status 接口一切正常(enable/credits/checked_in 均正确),仅 claim 单独被拒;重新登录、更换设备号、统一请求指纹均无效。

根因

在两个全新账号(签到前、未签状态)上做了组合矩阵实测:

x-device-id body claim 结果
16 位数字 {"req_source":1} 9074
16 位数字 {"req_source":2} 9074(此前实测的"通过"是当日已签的幂等 code:0 假成功)
15 位数字 {"req_source":1} code:0,checked_in 真实翻转,积分到账
无该头 {"req_source":1} 9004(参数错误,可区分)

结论:claim 的校验闸门是设备号位数形态——15 位放行、16 位拒绝,与 req_source 无关(保持官方契约 req_source:1),与是否真实客户端设备无关。9074 的「当前参与用户太多」是误导性文案;status 是只读接口,对设备号完全不校验,因此"status 正常、claim 被拒"的所有现象都指向同一个闸门。

社区既有结论的偏差由此可解释:报告"16 位可用"的账号当时已签到(幂等假成功);报告"必须真机设备号"的实现里 15/16 位混用,15 位的那部分成功了,归因给了真机号。

修复

  • randomNumericDeviceID() 由 16 位改为 15 位(新登录生效;既有凭据不改,避免破坏已配对的续期身份)
  • 签到 body 固定为官方契约 {"req_source":1},删除实验期引入的 req_source/位数配对逻辑
  • token 续期改走官方设备绑定交换(POST /trae/api/v3/oauth/ExchangeToken,DeviceInfo + ECDSA P-256 DeviceProof,签名原文逐字节对齐官方客户端),被拒时回退旧 /cloudide 路径;此路径正常不轮换 refreshToken
  • 统一登录与续期的 DeviceInfo 指纹(此前两处 OSInfo/OSVersion/DeviceBrand 互相矛盾,存在 20403/20405 指纹漂移风险)

测试

  • 新增 TestSignDeviceProofMatchesOfficialPayload(签名原文逐字节对齐官方客户端,公钥可验签)
  • 新增 TestExchangeTokenUsesDeviceBoundRenewal / ...FallsBackWhenDeviceRenewalRejected / ...UsesLegacySoloIdentity(绑定续期请求形状、回退链、谱系身份)
  • TestCheckinClaimFlow 断言 claim body 为 {"req_source":1}
  • go build ./... / go vet ./... / go test ./... 全部通过

验证边界

15 位规律来自两个新账号的单变量实测(均已确认积分到账);14/17 位等其它形态未测,留待维护者或更多样本补充。指纹统一与绑定续期参考了 bluechonk/trae-credential-reverse-engineering 的逆向报告与 magpie #808 的对照实验。


English

Problem

Trae CN accounts added through the login flow fail the daily check-in every time:

trae checkin claim rejected (code 9074): too many users, try later

status works fine (enable/credits/checked_in all correct); only claim is refused. Re-login, new device ids, and unified request fingerprints made no difference.

Root cause

Matrix-tested on two fresh accounts (unclaimed at the time):

x-device-id body claim
16-digit {"req_source":1} 9074
16-digit {"req_source":2} 9074 (an earlier "pass" was the idempotent code:0 of an already-claimed day)
15-digit {"req_source":1} code:0, checked_in flips, credits granted
header absent {"req_source":1} 9004

The claim gate checks the shape of the device id: 15 digits pass, 16 digits are refused — independent of req_source (the official req_source:1 contract is kept) and independent of whether the id came from a real client. The "too many users" message is misleading; status is read-only and ignores the device id entirely.

This also explains the divergent community findings: "16 digits work" reports came from already-claimed days (idempotent false success); "a real client device is required" implementations mixed 15/16-digit ids, and the 15-digit ones succeeded for the wrong reason.

Fix

  • randomNumericDeviceID() mints 15-digit ids (new logins; existing credentials keep their id so renewal keeps pairing with the identity the account was created with)
  • Check-in body fixed to the official contract {"req_source":1}; the experimental req_source/shape pairing from an earlier draft is removed
  • Token renewal goes through the official device-bound exchange (POST /trae/api/v3/oauth/ExchangeToken, DeviceInfo + ECDSA P-256 DeviceProof, payload byte-aligned with the official client), falling back to the legacy /cloudide path on refusal; this path normally does not rotate the refresh token
  • The DeviceInfo fingerprint is unified across login and renewal (the two sites previously disagreed on OSInfo/OSVersion/DeviceBrand, a 20403/20405 drift risk)

Tests

  • New: TestSignDeviceProofMatchesOfficialPayload, TestExchangeTokenUsesDeviceBoundRenewal, ...FallsBackWhenDeviceRenewalRejected, ...UsesLegacySoloIdentity
  • TestCheckinClaimFlow now asserts the claim body
  • go build ./..., go vet ./..., go test ./... all pass

Verification scope

The 15-digit rule rests on two fresh single-variable experiments (credits confirmed landed in both); other shapes were not tested. Fingerprint unification and the bound renewal follow bluechonk/trae-credential-reverse-engineering and the magpie #808 controlled experiments.

… gate

## 问题现象

通过登录流程添加的 Trae CN 账号,每日签到固定失败:

    trae checkin claim rejected (code 9074): 当前参与用户太多,请稍后再试

status 接口一切正常(enable/credits/checked_in 均正确),claim 单独被拒;
重新登录、换设备号、统一请求指纹均无效。

## 根因

在两个全新账号(签到前、未签状态)上做了组合矩阵实测:

    x-device-id 16 位数字 + {"req_source":1} -> 9074
    x-device-id 16 位数字 + {"req_source":2} -> 9074(此前实测的"通过"是当日已签的幂等 code:0 假成功)
    x-device-id 15 位数字 + {"req_source":1} -> code:0,checked_in 真实翻转,积分到账

结论:claim 的校验闸门是**设备号位数形态**——15 位放行、16 位拒绝,
与 req_source 无关(保持官方契约 req_source:1),与是否真实客户端设备无关。
9074 的"当前参与用户太多"文案是误导;status 是只读接口,对设备号完全不校验,
因此此前所有"status 正常、claim 被拒"的现象都指向同一个闸门。

社区既有结论的偏差也能由此解释:报告"16 位可用"的账号当时已签到(幂等假成功),
报告"必须真机设备号"的实现里 15/16 位混用,15 位的那部分成功了,归因给了真机号。

## 修复

- randomNumericDeviceID() 由 16 位改为 15 位(新登录生效)
- 签到 body 固定为官方契约 {"req_source":1},删除此前引入的 req_source/位数配对逻辑
- token 续期改走官方设备绑定交换(/trae/api/v3/oauth/ExchangeToken,
  DeviceInfo + ECDSA P-256 DeviceProof),指纹与登录保持一致,被拒时回退旧 /cloudide 路径
- 统一登录与续期的 DeviceInfo 指纹(此前两处 OSInfo/OSVersion/DeviceBrand 互相矛盾)

## 测试

- 新增 TestSignDeviceProofMatchesOfficialPayload(签名原文逐字节对齐官方客户端,公钥可验)
- 新增 TestExchangeTokenUsesDeviceBoundRenewal / ...FallsBackWhenDeviceRenewalRejected /
  ...UsesLegacySoloIdentity(绑定续期请求形状、回退、谱系身份)
- TestCheckinClaimFlow 断言 claim body 为 {"req_source":1}
- go build ./... / go vet ./... / go test ./... 全部通过

## 验证边界

15 位规律来自两个新账号的单变量实测;14/17 位等其它形态未测。
DeviceInfo 指纹统一与绑定续期参考了 bluechonk/trae-credential-reverse-engineering
的逆向报告与 magpie #808 的对照实验。
@BrianBoyCN
BrianBoyCN force-pushed the fix/trae-device-bound-checkin branch from 21c02b7 to 2da778e Compare November 8, 2026 04:26
@caigee-cmd
caigee-cmd merged commit 6206813 into caigee-cmd:main Nov 8, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants