Skip to content

docs: 明确 Cobo Auth Nonce 取值 - #377

Open
rcsh1 wants to merge 1 commit into
CoboGlobal:masterfrom
rcsh1:playbook/run-run_4fd6b95d04624100-nonce
Open

docs: 明确 Cobo Auth Nonce 取值#377
rcsh1 wants to merge 1 commit into
CoboGlobal:masterfrom
rcsh1:playbook/run-run_4fd6b95d04624100-nonce

Conversation

@rcsh1

@rcsh1 rcsh1 commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

意图

本次变更来自对 /developers/v2_cn/guides/overview/cobo-authNONCE 含义的反馈:现有表述让读者无法判断 Biz-Api-Nonce 到底是任意随机字符串,还是当前 Unix 毫秒时间戳。文档需要明确 Cobo Auth 签名流程中 Biz-Api-Noncestr_to_sign 里的 NONCE 组件如何对应,并避免写入代码证据未能支撑的公开 replay/time-window 规则。

变更摘要

  • v2_cn/guides/overview/cobo-auth.mdx:将 Biz-Api-Nonce 从“随机字符串”改为 Nonce,并说明 Cobo 签名辅助工具使用当前 Unix 毫秒时间戳,且请求头值必须与 str_to_sign 中的 NONCE 完全一致;补充有效和无效示例,减少中文读者对取值格式的歧义。
  • v2/guides/overview/cobo-auth.mdx:同步英文 Cobo Auth 指南中的 Nonce 说明和匹配/不匹配示例,保持中英文文档规则一致。

代码证据

  • waas2/developers/api_key_sign_helper.py:57:SDK/helper 通过 now_ms() 生成 nonce 值,证明文档中的客户端生成策略是当前 Unix 毫秒时间戳。
  • waas2/developers/api_key_sign_helper.py:87:SDK/helper 将生成的时间戳作为 nonce 组件参与签名。
  • waas2/developers/api_key_sign_helper.py:98:SDK/helper 将同一个生成的时间戳字符串发送到 Biz-Api-Nonce 请求头。
  • waas2/authentications/universal_access_control/authentications/api_key_authentication.py:47:Public WaaS2 auth 从请求头读取 biz-api-nonce
  • waas2/authentications/universal_access_control/authentications/api_key_authentication.py:51:Public WaaS2 auth 使用 method、path、nonce、params、body 构造签名原文。
  • waas2/authentications/universal_access_control/authentications/api_key_authentication.py:63:Public WaaS2 auth 校验包含 nonce 请求头值的 Ed25519 签名。
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:84:Shared EdDSA authentication 将 biz-api-nonce 作为字符串从请求头读取。
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:88:Shared EdDSA verifier 使用 method、path、nonce、query params、body 构造签名原文。
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:97:Shared EdDSA verifier 校验该签名原文上的签名。
  • cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:63:Shared signing helper 通过 now_ms() 生成 nonce 值。
  • cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:102:Shared signing helper 将生成的时间戳作为 Biz-Api-Nonce 发送。
  • custody/api/base_internal_api.py:56:Legacy internal API 将 CUS_NONCE 解析为整数,说明这是另一条内部 nonce 路径。
  • custody/api/base_internal_api.py:62:Legacy internal API 对 CUS_NONCE 执行毫秒时间窗口校验,因此本 PR 未将该内部路径的 time-window 规则写入公开 Cobo Auth 文档。

⚠️ 待确认事项

@rcsh1

rcsh1 commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator Author

运行过程记录(自动生成)

本评论记录本次 doc 运行的内部过程,便于审查每个结论的来源。

1. 意图(确认后)

Problem nonce-format-ambiguity: Evidence: inline feedback says "/developers/v2_cn/guides/overview/cobo-auth 里面的NONCE到底是随机字符串还是以毫秒为单位的当前 Unix 时间戳?" The suspected faulty doc is /developers/v2_cn/guides/overview/cobo-auth, specifically the Cobo Auth/NONCE description or signing example, because the wording leaves readers unable to tell whether NONCE must be an arbitrary random string or the current Unix timestamp in milliseconds. Category: Unclear or incomplete content. Documentation team should verify the authoritative behavior in code before editing: inspect the request authentication/signature validation path that reads the nonce header/field, any replay-protection or timestamp-window checks, and SDK request-signing helpers/examples that generate NONCE. Confirm whether the API accepts any unique random string, requires millisecond Unix time, or uses timestamp examples only as one valid nonce strategy; then update the page with an explicit rule, valid/invalid examples, and any uniqueness/time-window requirements.

2. 探索发现(按仓库 × explorer)

waas2 / Public WaaS2 auth 与 signing helper:

  • waas2/developers/api_key_sign_helper.py:57 通过 now_ms() 生成 nonce。
  • waas2/developers/api_key_sign_helper.py:87 将该 timestamp 作为 nonce 参与签名。
  • waas2/developers/api_key_sign_helper.py:98 将同一个 timestamp 字符串放入 Biz-Api-Nonce 请求头。
  • waas2/authentications/universal_access_control/authentications/api_key_authentication.py:47 从请求头读取 biz-api-nonce
  • waas2/authentications/universal_access_control/authentications/api_key_authentication.py:51 使用 method、path、nonce、params、body 构造签名原文。
  • waas2/authentications/universal_access_control/authentications/api_key_authentication.py:63 校验包含 nonce 的 Ed25519 签名。

cobo-libs / Shared authentication 与 helper:

  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:83 读取 biz-api-key
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:84biz-api-nonce 作为字符串读取。
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:86 要求 api_keyapi_nonceapi_sign 都存在。
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:88 使用 method、path、nonce、query params、body 构造签名原文。
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:97 校验该签名原文上的签名。
  • cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:26 将第三个签名输入命名为 timestamp。
  • cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:63 通过 now_ms() 生成 nonce。
  • cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:102 将生成的 timestamp 作为 Biz-Api-Nonce 发送。
  • cobo-libs/cobo_libs/clients/tools.py:20 签名内容 helper 接收 nonce 字符串参数。

其他相关路径:

  • custody/api/base_internal_api.py:56 将 legacy internal API 的 CUS_NONCE 解析为整数。
  • custody/api/base_internal_api.py:62 对 legacy internal API 的 CUS_NONCE 应用毫秒时间窗口校验。
  • cobo-libs/cobo_libs/clients/context_timestamp.py:25 内部 context timestamp 使用 Snowflake ID 字符串,不是裸毫秒时间戳。
  • cobo-libs/cobo_libs/webhook/client/auth.py:89 Webhook client 从 ContextTimestampStore.get_context_timestamp() 设置 Biz-Api-Nonce,属于内部 Snowflake-style 值。
  • cobo-libs/cobo_libs/clients/cobo_oauth/client.py:17 Internal OAuth client 生成纳秒精度 timestamp 字符串作为 nonce。
  • custody-2.0-website/src/network/interceptors.ts:13 Portal frontend 设置 BIZ-ORG-ID,不是公开 Cobo Auth nonce/signature header。
  • custody-2.0-website/src/network/interceptors.ts:16 Portal frontend interceptor 没有公开 Cobo Auth nonce/signature 处理。
3. 综合结论

综合结论:公开 WaaS2 Cobo Auth 的签名校验路径读取 Biz-Api-Nonce 请求头,并将该值作为 canonical signed content 中的 nonce 参与签名校验;Cobo 提供的 signing helpers 使用当前 Unix 毫秒时间戳生成该值,并将同一个值放入请求头和签名原文。因此文档应明确 helper 生成策略和“请求头值必须与 str_to_signNONCE 完全一致”。

confidence: high

open_questions: 未发现公开 WaaS2 Cobo Auth 路径的 replay cache 或 timestamp-window 代码证据;只在 legacy internal CUS_NONCE 路径看到时间窗口校验,因此文档不写公开 replay/time-window 规则。

汇总代码证据清单:waas2/developers/api_key_sign_helper.py:57waas2/developers/api_key_sign_helper.py:87waas2/developers/api_key_sign_helper.py:98waas2/authentications/universal_access_control/authentications/api_key_authentication.py:47waas2/authentications/universal_access_control/authentications/api_key_authentication.py:51waas2/authentications/universal_access_control/authentications/api_key_authentication.py:63cobo-libs/cobo_libs/api/restful/authentications/signature.py:84cobo-libs/cobo_libs/api/restful/authentications/signature.py:88cobo-libs/cobo_libs/api/restful/authentications/signature.py:97cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:63cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:102custody/api/base_internal_api.py:56custody/api/base_internal_api.py:62

4. 编辑计划
[
  {
    "task_id": "clarify-cobo-auth-nonce-cn",
    "action": "fix_docs",
    "doc_file": "v2_cn/guides/overview/cobo-auth.mdx",
    "repo_alias": "primary",
    "doc_edit_description": "Clarify the Cobo Auth nonce wording in Chinese. Replace ambiguous uses of `随机数` that imply an arbitrary random value with `Nonce` / timestamp-focused wording. State that `Biz-Api-Nonce` is the nonce value included in the signing string and sent in the request header, that Cobo signing helpers generate it as the current Unix timestamp in milliseconds such as `1718587017026`, and that the header value must exactly match the `NONCE` component in `str_to_sign`. Add a valid example with the same millisecond timestamp in both places and an invalid example where the header and signing-string nonce differ or a stale signed pair is reused. Do not document a specific public replay/time-window rule.",
    "code_evidence": [
      "waas2/developers/api_key_sign_helper.py:57 — SDK/helper generates the nonce value from now_ms(), proving the documented client strategy is a millisecond Unix timestamp.",
      "waas2/developers/api_key_sign_helper.py:98 — SDK/helper sends the same generated timestamp string in the Biz-Api-Nonce header.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:47 — Public WaaS2 auth reads biz-api-nonce from the request header as a header value.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:51 — Public WaaS2 auth builds canonical signed content from method, path, nonce, params, and body.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:63 — Public WaaS2 auth verifies the Ed25519 signature against the canonical string containing the nonce header value.",
      "cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:63 — Shared signing helper generates the nonce value with now_ms().",
      "cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:102 — Shared signing helper sends that generated timestamp as Biz-Api-Nonce."
    ],
    "code_evidence_missing": false
  },
  {
    "task_id": "clarify-cobo-auth-nonce-en",
    "action": "fix_docs",
    "doc_file": "v2/guides/overview/cobo-auth.mdx",
    "repo_alias": "primary",
    "doc_edit_description": "Mirror the nonce clarification in the English Cobo Auth guide. Keep `Biz-Api-Nonce` and `NONCE` identifiers untranslated, and add explicit prose that the nonce used by Cobo signing helpers is the current Unix timestamp in milliseconds, for example `1718587017026`; the same value must appear in the `Biz-Api-Nonce` header and the `NONCE` segment of `str_to_sign`. Add matching valid/invalid examples. Avoid claiming a public timestamp-window or replay-cache rule because code evidence only confirms such a window for the separate legacy `CUS_NONCE` path.",
    "code_evidence": [
      "waas2/developers/api_key_sign_helper.py:57 — SDK/helper generates the nonce value from now_ms(), proving the documented client strategy is a millisecond Unix timestamp.",
      "waas2/developers/api_key_sign_helper.py:98 — SDK/helper sends the same generated timestamp string in the Biz-Api-Nonce header.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:47 — Public WaaS2 auth reads biz-api-nonce from the request header as a header value.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:51 — Public WaaS2 auth builds canonical signed content from method, path, nonce, params, and body.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:63 — Public WaaS2 auth verifies the Ed25519 signature against the canonical string containing the nonce header value.",
      "cobo-libs/cobo_libs/api/restful/authentications/signature.py:84 — Shared EdDSA authentication reads biz-api-nonce from the request header as a string.",
      "cobo-libs/cobo_libs/api/restful/authentications/signature.py:88 — Shared EdDSA verifier builds signed content from method, path, nonce, query params, and body.",
      "cobo-libs/cobo_libs/api/restful/authentications/signature.py:97 — Shared EdDSA verifier validates the signature over that signed content.",
      "cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:63 — Shared signing helper generates the nonce value with now_ms().",
      "cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:102 — Shared signing helper sends that generated timestamp as Biz-Api-Nonce."
    ],
    "code_evidence_missing": false
  }
]
5. 评审轮次

最终评审结论:Approved。v2_cn/guides/overview/cobo-auth.mdx 第 16 行将 Biz-Api-Nonce(随机字符串)替换为 Biz-Api-Nonce(Nonce),与第 27 行的 Biz-Api-Nonce bullet 和第 140-156 行的 Nonce section 对齐。未添加 replay/time-window 声明,所有 identifiers 保持未翻译。英文文件已在上一轮正确。

6. 基线与同步

编辑前同步到的 upstream 基线 commit:7bdc98eabab5f31af2d26f36bac97afdda09f1e9

api-spec 同步结果:不适用,本次未修改 api-spec 源 YAML,也未同步 dev_openapi.yaml

验证:在 /Users/rebeccacao/workmate/scratch/playbooks/run_4fd6b95d04624100/worktree 执行 mintlify validate,退出码为 0。

@rcsh1

rcsh1 commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator Author

运行过程记录(自动生成)

本评论记录本次 doc 运行的内部过程,便于审查每个结论的来源。

1. 意图(确认后)

Problem nonce-format-ambiguity: Evidence: inline feedback says "/developers/v2_cn/guides/overview/cobo-auth 里面的NONCE到底是随机字符串还是以毫秒为单位的当前 Unix 时间戳?" The suspected faulty doc is /developers/v2_cn/guides/overview/cobo-auth, specifically the Cobo Auth/NONCE description or signing example, because the wording leaves readers unable to tell whether NONCE must be an arbitrary random string or the current Unix timestamp in milliseconds. Category: Unclear or incomplete content. Documentation team should verify the authoritative behavior in code before editing: inspect the request authentication/signature validation path that reads the nonce header/field, any replay-protection or timestamp-window checks, and SDK request-signing helpers/examples that generate NONCE. Confirm whether the API accepts any unique random string, requires millisecond Unix time, or uses timestamp examples only as one valid nonce strategy; then update the page with an explicit rule, valid/invalid examples, and any uniqueness/time-window requirements.

2. 探索发现(按仓库 × explorer)

说明:原始探索记录较长;本节按 explorer 保留 findings、handoff_brief 与 code_evidence 要点,避免超过 GitHub 单评论长度限制。

Explorer b1 / branch b1

findings:

  • CN page v2_cn/guides/overview/cobo-auth.mdxNONCE 标为 随机数,同时又定义为当前 Unix 毫秒时间戳,直接造成“随机字符串还是时间戳”的歧义。
  • EN page v2/guides/overview/cobo-auth.mdx 已说明 current Unix timestamp in milliseconds,但未显式排除任意随机字符串。

handoff_brief:

  • SDK waas2/developers/api_key_sign_helper.py 总是用 str(now_ms()) 生成 nonce,并写入 Biz-Api-Nonce
  • WaaS2 auth 将 nonce 当作签名原文中的字符串读取和校验,legacy internal API 的 CUS_NONCE 有毫秒时间窗口校验。
  • 建议改 v2_cn/guides/overview/cobo-auth.mdxv2/guides/overview/cobo-auth.mdx,说明 nonce 使用当前 Unix 毫秒时间戳,并避免文档继续暗示任意随机字符串。

code_evidence:

  • waas2/developers/api_key_sign_helper.py:57timestamp = str(now_ms()) 证明 SDK 使用 Unix 毫秒时间戳作为 nonce。
  • waas2/developers/api_key_sign_helper.py:98Biz-Api-Nonce header 设置为 timestamp 字符串。
  • waas2/authentications/universal_access_control/authentications/api_key_authentication.py:47 — auth 从 header 读取 biz-api-nonce
  • waas2/authentications/universal_access_control/authentications/api_key_authentication.py:55 — nonce 原样进入签名内容。
  • custody/api/base_internal_api.py:62 — legacy CUS_NONCE 有 timestamp window 校验,但不是公开 Biz-Api-Nonce 路径。

Explorer b1 / branch b2

findings:

  • CN doc line 27、142、157 使用 随机数 和 timestamp-only 描述混杂,导致读者无法判断 arbitrary random string 是否有效。
  • Public WaaS2 auth 读取 biz-api-nonce 并将其纳入 METHOD|PATH|NONCE|PARAMS|BODY,本地 signing helper 通过 now_ms() 生成并发送相同值。
  • 未在 public WaaS2 auth 路径中确认 replay cache 或 timestamp-window;时间窗口只在 legacy internal CUS_NONCE 中出现。

handoff_brief:

  • 更新 CN 与 EN Cobo Auth 页面,说明 Biz-Api-Nonce 是签名字符串中的 NONCE 值,Cobo 示例使用当前 Unix 毫秒时间戳,header 与 signed NONCE 必须完全一致。
  • 添加有效示例和无效示例;不要写 arbitrary-random-string allowance,也不要写 public timestamp-window/replay-protection 规则。

code_evidence:

  • custody/waas2/authentications/universal_access_control/authentications/api_key_authentication.py:47 — public auth 读取 biz-api-nonce
  • custody/waas2/authentications/universal_access_control/authentications/api_key_authentication.py:51 — canonical string 包含 nonce。
  • custody/waas2/authentications/universal_access_control/authentications/api_key_authentication.py:63 — Ed25519 signature 校验 canonical string。
  • custody/waas2/developers/api_key_sign_helper.py:57 — helper 用 now_ms() 生成 nonce。
  • custody/waas2/developers/api_key_sign_helper.py:87 — helper 签名生成的 timestamp。
  • custody/waas2/developers/api_key_sign_helper.py:96 — helper 将同一 timestamp 放入 Biz-Api-Nonce
  • custody/custody/api/base_internal_api.py:56:62 — legacy CUS_NONCE parse integer 并做 window check,不等同于 public Biz-Api-Nonce

Explorer b2 / branch b1

findings:

  • CN page only gap:随机数 字面含义是 random number,与“当前 Unix 毫秒时间戳”的实际要求冲突。
  • custody-2.0-website 是 Portal frontend,使用 session auth,不包含 Cobo Auth nonce validation。
  • EN page 在该 explorer 看来已较明确。

handoff_brief:

  • 建议 CN line 27 和 Nonce section 明确“并非任意随机字符串,而是当前 Unix 毫秒时间戳”。
  • 需要 backend 代码确认严格 timestamp format、replay protection 与 window 后再写更强规则。

code_evidence:

  • custody-2.0-website/src/network/interceptors.ts:13-16 — Portal frontend 使用 BIZ-ORG-ID,无 public Cobo Auth nonce/signature handling。
  • v2_cn/guides/overview/cobo-auth.mdx:27 — 使用 随机数 label。
  • v2_cn/guides/overview/cobo-auth.mdx:141-142 — section header/body 继续使用 ambiguous 随机数
  • v2/guides/overview/cobo-auth.mdx:26,140,154 — EN page 说明 current time in Unix timestamp format, measured in milliseconds。

Explorer b2 / branch b2

findings:

  • custody-2.0-website 与本 intent 不相关,因为 nonce-format ambiguity 属于 developer API auth/signature validation 与 replay behavior。

handoff_brief:

  • Repo skipped: authoritative evidence should come from custody backend authentication path and SDK signing helpers, not frontend repo.

code_evidence:

  • 无;该 repo 被判定为不相关并跳过。

Explorer b3 / branch b1

findings:

  • CN page 使用 随机数 但定义为 millisecond Unix timestamp;EN/CN signing table 使用 {NONCE},有 explorer 提到 source docs 中用 {TIMESTAMP}
  • 未确认 public time-window 或 replay-protection 信息。

handoff_brief:

  • 建议编辑 v2_cn/guides/overview/cobo-auth.mdxv2/guides/overview/cobo-auth.mdx,显式说明 nonce 是 current Unix timestamp in milliseconds,不是任意随机字符串。
  • 建议更改 signing placeholder 为 {TIMESTAMP},但该点最终计划未采用;最终文档保留 NONCE 以匹配 public header/签名说明。

code_evidence:

  • developer-site-waas2/v2/guides/overview/cobo-auth.mdx:132 — EN source 说 nonce 是 current time in Unix timestamp format, measured in milliseconds。
  • developer-site-waas2/v2/guides/overview/cobo-auth.mdx:140 — source signing template 使用 {TIMESTAMP}
  • developer-site-waas2/v2/guides/overview/cobo-auth.mdx:146 — TIMESTAMP 必须与 request header nonce 相同。
  • developer-site-waas2/v2_cn/guides/overview/cobo-auth.mdx:144:150 — CN source 也使用 {TIMESTAMP} 并说明需与 header nonce 相同。
  • developer-site-waas2/v2/apps/authentication.mdx:49 — app auth page 也说明 {Nonce} 替换为当前 Unix 毫秒时间戳。

Explorer b3 / branch b2

findings:

  • developer-site-waas2 是 docs/OpenAPI source,不是 runtime code;无法确认 request-auth validation、replay cache、timestamp-window 或 SDK nonce generator 的最终权威行为。
  • CN/EN 页面都需要在 backend verification 后给出明确 accepted nonce rule、valid/invalid examples、uniqueness/reuse guidance 与 matching signing-table wording。

handoff_brief:

  • 先确认 custody backend request authentication/signature validation 与 SDK signing helpers,再更新 CN/EN Cobo Auth 页面。
  • 若 timestamp-only 确认,则让要求无歧义;若任意 unique string 被接受,则把毫秒 timestamp 描述为推荐策略。

code_evidence:

  • developer-site-waas2/v2/guides/overview/cobo-auth.mdx:26 — EN guide 定义 Biz-Api-Nonce 为 Unix 毫秒 timestamp。
  • developer-site-waas2/v2/guides/overview/cobo-auth.mdx:140 — EN Nonce section 重复 timestamp 定义。
  • developer-site-waas2/v2/guides/overview/cobo-auth.mdx:154 — EN signing table 要求 NONCEBiz-Api-Nonce 相同。
  • developer-site-waas2/v2/guides/get-started/get-started-with-waas.mdx:83 — get-started guide 也重复 timestamp-only nonce 定义。
  • developer-site-waas2/v2/cobo_waas2_openapi_spec/dev_main.yaml:3101:3105 — OpenAPI security scheme 定义 BIZ-API-NONCE 并描述为 Unix epoch milliseconds。

Explorer b4 / branch b1

findings:

  • EN line 26/140 说 nonce 是 current Unix time in milliseconds,但没有显式排除 arbitrary random string。
  • CN line 27/142 使用 随机数,强烈暗示随机生成值。
  • cobo-libs 中部分 internal nonce generation 使用 Snowflake IDs 或 nanosecond timestamp,不等同于 public WaaS2 timestamp 规则。

handoff_brief:

  • 建议 EN 明确 “do not use an arbitrary random string”;CN 将 随机数 label 改为 Nonce/时间戳相关措辞。
  • Server-side public API nonce validation 在 custody repo,未能从 cobo-libs 确认 time-window 或 format enforcement。

code_evidence:

  • cobo-libs/cobo_libs/clients/tools.py:20 — shared signing helper 接收 nonce: str,不强制 timestamp format。
  • cobo-libs/cobo_libs/clients/context_timestamp.py:25 — internal nonce-like value 使用 Snowflake ID。
  • cobo-libs/cobo_libs/webhook/client/auth.py:89 — webhook client 使用 ContextTimestampStore.get_context_timestamp() 设置 Biz-Api-Nonce
  • cobo-libs/cobo_libs/clients/cobo_oauth/client.py:17 — internal OAuth client 使用 nanosecond-precision timestamp string。

Explorer b4 / branch b2

findings:

  • Shared auth 读取 biz-api-nonce 为字符串并放入签名内容,shared signing helper 生成 now_ms() 并作为 Biz-Api-Nonce
  • 在已读 shared-library 文件中未发现 replay cache、timestamp-window check 或 integer validation。

handoff_brief:

  • 推荐改 CN/EN Cobo Auth 页面:Biz-Api-Noncestr_to_sign 中完全相同的 nonce string;Cobo SDKs 生成当前 Unix 毫秒时间戳。
  • 是否允许 arbitrary unique strings 仍需 custody replay checks 或 product/code owner 确认;未确认前不写 uniqueness/time-window requirement。

code_evidence:

  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:83 — 读取 biz-api-key
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:84 — 读取 biz-api-nonce 为字符串。
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:86 — 要求 api_key、api_nonce、api_sign 存在。
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:88 — verifier 用 method、path、nonce、query params、body 生成签名内容。
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:97 — 校验签名;未见 integer parsing 或 timestamp-window。
  • cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:26 — helper 将第三个 signing input 命名为 timestamp
  • cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:63 — helper 使用 now_ms() 生成 nonce。
  • cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:102 — helper 将该 timestamp 作为 Biz-Api-Nonce 发送。
3. 综合结论

result:
Convergent themes: the primary doc defect is terminology, especially in Chinese where 随机数 literally implies a random value while the prose says current Unix timestamp in milliseconds. SDK/helper code consistently generates a millisecond timestamp with now_ms() and sends it as Biz-Api-Nonce. Public/shared auth code includes the nonce header value verbatim in the canonical signing string and verifies the signature over that content. Legacy internal CUS_NONCE has integer timestamp-window validation, but that is a different header/path and should not be generalized without confirmation. There is no real evidence-backed contradiction: timestamp generation and string-based signature verification can coexist, so the docs should describe the Cobo helper strategy and exact header/signing-string match while avoiding unsupported public replay/time-window claims.

confidence: 0.82

open_questions:

  1. Is public WaaS2 Biz-Api-Nonce contractually required to be a current millisecond Unix timestamp, or does the public verifier accept any unique string as long as it is signed? The inspected auth/signature code treats it as signed string input, while SDKs generate now_ms().
  2. Is there any public WaaS2 replay cache or timestamp-window enforcement outside the inspected authentication/signature files? A 600s-style window is confirmed only for legacy internal CUS_NONCE, not for public Biz-Api-Nonce.
  3. Should the signing-string placeholder remain NONCE for public docs, or be aligned to TIMESTAMP where source docs reportedly use TIMESTAMP? Final plan preferred retaining NONCE for consistency with the public header and current public signing terminology.

汇总代码证据清单:

  • waas2/developers/api_key_sign_helper.py:57 — SDK/helper generates the nonce value from now_ms(), proving the documented client strategy is a millisecond Unix timestamp.
  • waas2/developers/api_key_sign_helper.py:87 — SDK/helper signs the generated timestamp value as the nonce component.
  • waas2/developers/api_key_sign_helper.py:98 — SDK/helper sends the same generated timestamp string in the Biz-Api-Nonce header.
  • waas2/authentications/universal_access_control/authentications/api_key_authentication.py:47 — Public WaaS2 auth reads biz-api-nonce from the request header as a header value.
  • waas2/authentications/universal_access_control/authentications/api_key_authentication.py:51 — Public WaaS2 auth builds canonical signed content from method, path, nonce, params, and body.
  • waas2/authentications/universal_access_control/authentications/api_key_authentication.py:63 — Public WaaS2 auth verifies the Ed25519 signature against the canonical string containing the nonce header value.
  • custody/api/base_internal_api.py:56 — Legacy internal API parses CUS_NONCE as an integer.
  • custody/api/base_internal_api.py:62 — Legacy internal API rejects CUS_NONCE when its millisecond timestamp differs from current time beyond API_EXPIRE_TIME, showing timestamp-window behavior for that legacy internal nonce path.
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:83 — Shared EdDSA authentication reads the public API key from the biz-api-key request header.
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:84 — Shared EdDSA authentication reads biz-api-nonce from the request header as a string.
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:86 — Shared EdDSA authentication requires api_key, api_nonce, and api_sign to be present.
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:88 — Shared EdDSA verifier builds signed content from method, path, nonce, query params, and body.
  • cobo-libs/cobo_libs/api/restful/authentications/signature.py:97 — Shared EdDSA verifier validates the signature over that signed content.
  • cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:26 — Shared signing helper names the third signing input timestamp.
  • cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:63 — Shared signing helper generates the nonce value with now_ms().
  • cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:102 — Shared signing helper sends that generated timestamp as Biz-Api-Nonce.
  • cobo-libs/cobo_libs/clients/tools.py:20 — Shared signing content helper accepts nonce as a str parameter.
  • cobo-libs/cobo_libs/clients/context_timestamp.py:25 — Internal context timestamp generation uses a Snowflake ID string for internal nonce-like values, not a bare millisecond timestamp.
  • cobo-libs/cobo_libs/webhook/client/auth.py:89 — Webhook client sets Biz-Api-Nonce from ContextTimestampStore.get_context_timestamp(), an internal Snowflake-style value.
  • cobo-libs/cobo_libs/clients/cobo_oauth/client.py:17 — Internal OAuth client generates a nanosecond-precision timestamp string as nonce.
  • custody-2.0-website/src/network/interceptors.ts:13 — Portal frontend sets BIZ-ORG-ID for session-oriented portal requests, not Cobo Auth nonce/signature headers.
  • custody-2.0-website/src/network/interceptors.ts:16 — Portal frontend request interceptor path contains no public Cobo Auth nonce/signature handling.
4. 编辑计划
[
  {
    "task_id": "clarify-cobo-auth-nonce-cn",
    "action": "fix_docs",
    "doc_file": "v2_cn/guides/overview/cobo-auth.mdx",
    "repo_alias": "primary",
    "doc_edit_description": "Clarify the Cobo Auth nonce wording in Chinese. Replace ambiguous uses of `随机数` that imply an arbitrary random value with `Nonce` / timestamp-focused wording. State that `Biz-Api-Nonce` is the nonce value included in the signing string and sent in the request header, that Cobo signing helpers generate it as the current Unix timestamp in milliseconds such as `1718587017026`, and that the header value must exactly match the `NONCE` component in `str_to_sign`. Add a valid example with the same millisecond timestamp in both places and an invalid example where the header and signing-string nonce differ or a stale signed pair is reused. Do not document a specific public replay/time-window rule.",
    "code_evidence": [
      "waas2/developers/api_key_sign_helper.py:57 — SDK/helper generates the nonce value from now_ms(), proving the documented client strategy is a millisecond Unix timestamp.",
      "waas2/developers/api_key_sign_helper.py:98 — SDK/helper sends the same generated timestamp string in the Biz-Api-Nonce header.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:47 — Public WaaS2 auth reads biz-api-nonce from the request header as a header value.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:51 — Public WaaS2 auth builds canonical signed content from method, path, nonce, params, and body.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:63 — Public WaaS2 auth verifies the Ed25519 signature against the canonical string containing the nonce header value.",
      "cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:63 — Shared signing helper generates the nonce value with now_ms().",
      "cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:102 — Shared signing helper sends that generated timestamp as Biz-Api-Nonce."
    ],
    "code_evidence_missing": false
  },
  {
    "task_id": "clarify-cobo-auth-nonce-en",
    "action": "fix_docs",
    "doc_file": "v2/guides/overview/cobo-auth.mdx",
    "repo_alias": "primary",
    "doc_edit_description": "Mirror the nonce clarification in the English Cobo Auth guide. Keep `Biz-Api-Nonce` and `NONCE` identifiers untranslated, and add explicit prose that the nonce used by Cobo signing helpers is the current Unix timestamp in milliseconds, for example `1718587017026`; the same value must appear in the `Biz-Api-Nonce` header and the `NONCE` segment of `str_to_sign`. Add matching valid/invalid examples. Avoid claiming a public timestamp-window or replay-cache rule because code evidence only confirms such a window for the separate legacy `CUS_NONCE` path.",
    "code_evidence": [
      "waas2/developers/api_key_sign_helper.py:57 — SDK/helper generates the nonce value from now_ms(), proving the documented client strategy is a millisecond Unix timestamp.",
      "waas2/developers/api_key_sign_helper.py:98 — SDK/helper sends the same generated timestamp string in the Biz-Api-Nonce header.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:47 — Public WaaS2 auth reads biz-api-nonce from the request header as a header value.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:51 — Public WaaS2 auth builds canonical signed content from method, path, nonce, params, and body.",
      "waas2/authentications/universal_access_control/authentications/api_key_authentication.py:63 — Public WaaS2 auth verifies the Ed25519 signature against the canonical string containing the nonce header value.",
      "cobo-libs/cobo_libs/api/restful/authentications/signature.py:84 — Shared EdDSA authentication reads biz-api-nonce from the request header as a string.",
      "cobo-libs/cobo_libs/api/restful/authentications/signature.py:88 — Shared EdDSA verifier builds signed content from method, path, nonce, query params, and body.",
      "cobo-libs/cobo_libs/api/restful/authentications/signature.py:97 — Shared EdDSA verifier validates the signature over that signed content.",
      "cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:63 — Shared signing helper generates the nonce value with now_ms().",
      "cobo-libs/cobo_libs/api/restful/utils/api_key_sign_helper.py:102 — Shared signing helper sends that generated timestamp as Biz-Api-Nonce."
    ],
    "code_evidence_missing": false
  }
]
5. 评审轮次

最终评审记录:

  • approved: false
  • feedback: v2_cn/guides/overview/cobo-auth.mdx:16 仍将 Biz-Api-Nonce 描述为 随机字符串,保留了原始歧义,并与 explorer 支持的编辑方向冲突。应将 Biz-Api-Nonce(随机字符串)替换为 Biz-Api-Nonce(Nonce)。对应的 CN Nonce section 和 EN edits otherwise match explorer findings and avoid unsupported replay/time-window claims.

后续处理:

  • 已根据评审反馈修正 v2_cn/guides/overview/cobo-auth.mdx 中 line 16 的表述,将 Biz-Api-Nonce(随机字符串)替换为 Biz-Api-Nonce(Nonce)。
  • 上游 handoff 确认该单行修正通过:intro sentence now aligns with the Biz-Api-Nonce bullet and Nonce section; no replay/time-window claims were added; identifiers remain untranslated; EN file was already correct.
6. 基线与同步

编辑前同步到的 upstream 基线 commit:执行者未报告。

api-spec 同步结果:不适用,本次未修改 api-spec 源 YAML,也未同步 dev_openapi.yaml

Primary doc edits:

  • v2_cn/guides/overview/cobo-auth.mdx 更新为将 Biz-Api-Nonce random-string wording 替换为 Nonce wording,并添加 timestamp/matching examples。
  • v2/guides/overview/cobo-auth.mdx 包含对应的英文 nonce clarification。
  • Diff stat: 2 files changed, 33 insertions(+), 5 deletions(-)。

验证:

  • /Users/rebeccacao/workmate/scratch/playbooks/run_4fd6b95d04624100/worktree 执行 mintlify validate,退出码为 0。

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