Skip to content

fix(content): 未附修订签名时拒绝客户端 revision_id/content_created_at - #152

Merged
LIghtJUNction merged 1 commit into
mainfrom
fix/next-slice-20260928
Sep 28, 2026
Merged

LIghtJUNction merged 1 commit into
mainfrom
fix/next-slice-20260928

Conversation

@LIghtJUNction

Copy link
Copy Markdown
Contributor

摘要

对应 #79(内容/文件编辑与 Revision 完整契约)中的一个单点校验。本 PR 不关闭 #79,只是其中一个切片。

revise_resource 之前的行为:

  • 请求带了客户端指定的 revision_id 或 content_created_at,但没有 content_signature,写入仍会被接受:客户端选定的 Revision ID 直接落库,content_created_at 被静默丢弃,响应看起来和签名写入一样成功。
  • 请求带了 content_signature 却没有 revision_id,服务端会生成随机 ID,签名必然验不过,最后只返回一个笼统的 invalid_signature。

这些字段只有作为签名 Revision manifest 的一部分时才有定义(见 client_content.signed_patch_arguments,以及 identity.*_put@2 要求同时提供)。现在:

  • 没有签名但出现 revision_id 或 content_created_at:拒绝,返回 content_signature_required。
  • 有签名但缺 revision_id:拒绝,返回 revision_id_required。
  • 校验放在写入内容之前,被拒绝的请求不会产生 blob、Revision,也不会改动引用或 generation。
  • 不带这些字段的普通写入,以及字段齐全的签名写入,行为不变。内部发布路径(transfer.seal)不携带客户端参数,照常工作。

覆盖范围是所有经过 revise_resource 的客户端写入:content.post_create/post_write/post_edit/post_rollback、content.post_patch@2、content.text_patch@3、content.text_patch_batch@2、discussion.reply/quote/repost。

范围边界

测试

  • 新增 tests/issue_78_80/test_revision_signature_fields.py:修复前 5 个失败,修复后全部通过。
  • tests/issue_78_80、test_personal_content_signatures、test_personal_documents、test_custodial_vault、test_custodial_upgrade、test_legacy_directive、test_notes_todos、test_transfer:129 passed。
  • 全量测试结果见下方评论。

Made with Cursor

A client-chosen revision_id or content_created_at is only meaningful as part of
the signed Revision manifest. Unsigned writes that carried them were accepted
with an unproven ID/time; a signature without revision_id could never verify.
Refs #79.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copilot AI lite review requested due to automatic review settings September 28, 2026 16:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review ✅ Completed 2026-09-28T16:42:18.475140Z bba4e6b PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@LIghtJUNction

Copy link
Copy Markdown
Contributor Author

本地全量测试(head bba4e6b)

  • 第一次串行全量:1148 passed,其余 error/fail 都出在 PG fixture 上。原因是每个测试各建一个库,把 /tmp 写满了(psycopg.errors.DiskFull),与本改动无关。
  • 之后把受影响的 138 个测试文件分成小批次、逐文件重跑,每批使用新的临时 PG 集群。除下面一项外全部通过。
  • tests/test_legacy_ledger_snapshot.py 的 16 个 error:需要把 MSG_TEST_LEGACY_SOURCE 指向旧版源码 checkout,本机没有,所以跑不了,与本改动无关。
  • 在 origin/main 基线上单独运行此前失败的 test_delivery::test_revoked_buyer_key_cannot_accept、test_money_config::test_market_selftest_features_require_the_actual_isolated_flow,本分支上也单独运行一次,都通过。说明它们只是在高负载全量运行时失败。
  • tests/test_postgres.py 需要 MSG_TEST_POSTGRES_DSN 指向一个可丢弃的数据库。本机没有可安全清空的库,所以没跑。本改动不涉及存储层。

@LIghtJUNction
LIghtJUNction merged commit 1fc5074 into main Sep 28, 2026
11 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