mirror of
https://github.com/pgsty/minio.git
synced 2026-09-15 23:14:04 +03:00
Merge main after R4 validation into R7 candidate
Signed-off-by: Feng Ruohang <rh@vonng.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
# R4 plan consensus and review disposition
|
||||
|
||||
## Agreed version
|
||||
|
||||
- Plan: [plan v1](plan-v1.md), SHA-256 `ad539f2071155de6955b583991684ed33c4bfe2e29660005840cdc97d7e1a754`. The frozen file remains unchanged.
|
||||
- Baseline: `9ebe81c1b3611f9cc73e676b5b741c2be62c467a`.
|
||||
- Actual reviewer: Claude Code 2.1.270, every assistant model in the review stream is `claude-opus-5`; explicit `--effort max`.
|
||||
- Opus: **GO_WITH_NONBLOCKING_NOTES**, zero blockers; explicitly agrees that this exact plan can enter local implementation. [Unedited returned review](opus-v1-review.md), [machine-readable provenance](opus-v1.metadata.json).
|
||||
- Codex: agrees that adding the already-parsed timestamp to the KMS literal fixes R4, and accepts the nonblocking dispositions below. **No blocking disagreement remains on plan v1.** No production source edits were made before this record was saved.
|
||||
- The agreement permits the planned local implementation and tests; it is not implementation acceptance, a merge decision or production release approval.
|
||||
|
||||
## Item-by-item disposition
|
||||
|
||||
| Opus ID | Disposition |
|
||||
|---|---|
|
||||
| R4-01 | Accepted citation correction here, leaving the agreed hash frozen: `ReplicaLockReconcile` is at baseline `object-handlers.go:1847`; encryption merge is at `:1903`. |
|
||||
| R4-02 | Accepted scope clarification: ErasureSD and Erasure16 are both single-pool local backends. KMS rewrites use PutObject under-lock reconciliation. Multi-pool and multi-site validation are optional and deferred to the wider integration gate. Test comments and the final report will identify this boundary. |
|
||||
| R4-03 | Accepted wording clarification: source encryption alone does not request destination encryption. Source-only SSE-C copy headers do not prevent destination bucket/default auto-KMS from selecting KMS. The three destination trigger categories stay unchanged. |
|
||||
| R4-04 | Accepted intent. The regression matrix uses identical expected mtime, ETag, trust and all three source timestamps across all encryption modes, giving field-by-field equivalence without constructing expected values through the production function. The temporary expanded baseline matrix fails only trusted valid KMS tag timestamps. |
|
||||
| R4-05 | Accepted optional test within the existing scope: a signed KMS COPY with nonempty tags and no source tag timestamp must preserve the stored value/time. This adds evidence, not production behavior. |
|
||||
| R4-06 | Registered as a separate unverified-impact finding: KMS construction also omits `ProxyHeaderSet`, `ProxyRequest`, `Speedtest` relative to `getDefaultOpts`. No R4 fix or correctness claim for those flags. Send the observation to the parent for separate triage; do not assign it to R5. |
|
||||
| R4-07 | Accepted. Assertions target final disk state; the REPLACE handler rebuilds metadata, while final stored-tag rejection occurs under the storage write lock. HTTP 200 alone is not acceptance. |
|
||||
| R4-08 | Resolved provenance uncertainty by Codex: SHA-256 recomputed before/after review, baseline identity and current GitHub main/PR query captured in `baseline-identity.txt`. History was inspected locally with `git blame` / `git show`. Opus's read-only tools did not independently recompute the hash or check GitHub; those facts remain attributed to the local commands. |
|
||||
|
||||
## Raw evidence
|
||||
|
||||
Directory: `/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/`.
|
||||
|
||||
- `review-prompt-v1.md`, `opus-review-v1.jsonl`, `opus-review-v1.stderr.log`, `opus-review-v1.exit`.
|
||||
- `baseline-identity.txt`, `r4_repro_test.go`, `overlay.json`, `baseline-repro.log`.
|
||||
- `options_repro_test.go`, `options-overlay.json`, `baseline-options.log`.
|
||||
|
||||
The stream includes an attempted Write to Claude's own plan file. Its tool was disabled; the reviewer returned the full result in text and did not edit production source. The successful result and actual assistant models are checked separately from rate-limit status and auxiliary-model usage.
|
||||
@@ -0,0 +1,39 @@
|
||||
已完成独立复核:读了三份改动文件在 HEAD 的实际内容、`putOptsFromHeaders` 全函数与两条返回路径、`CopyObjectHandler` 的默认加密与标签排序段、`reconcileStoredObjectTags` 的三处生产调用点,以及全部指定日志与证据文件。
|
||||
|
||||
# R4 实现复核结论
|
||||
|
||||
**Verdict: GO_WITH_NONBLOCKING_NOTES(0 阻断项)**
|
||||
|
||||
- 复核 HEAD:`dbcf8dec589deb5d91e17d295cb70997635f5b55`
|
||||
- 代码/测试 diff SHA-256(按提供值记录):`c8cd6648f8ecea835ec74a038cdeaa82acaa3f36250395f97ead3260dc2fc0a5`
|
||||
- 本会话无 shell,未重算该哈希;改为逐行比对 diff 与工作树三份文件,内容完全一致(`cmd/object-api-options.go`、`cmd/object-api-options-replication_test.go`、`cmd/object-copy-replication-tagging_test.go`)。
|
||||
|
||||
## 核验到的事实
|
||||
|
||||
- 生产改动确为一个字段 + 相邻注释:`cmd/object-api-options.go:459` 的 `ReplicationSourceTaggingTimestamp: taggingtimestmp`,变量来自 `:419-425` 已解析值,与非 KMS 路径 `:473` 对齐。未动解析、信任判定、KMS key/context、返回结构。
|
||||
- 影响面封闭:全仓该字段唯一消费点是 `cmd/object-handlers.go:1820`(COPY 标签排序)。PUT/POST/multipart 虽同经 `putOptsFromReq`,但无消费者,故不可能回归——与 R4/R5 切分一致。
|
||||
- 三条 KMS 触发路径真实可达:`object-handlers.go:1428-1433` 在 `copyDstOpts`(`:1454`)之前套用目的端默认;`bucket-sse-config.go:139-151` 在 `nil 配置 + AutoEncrypt` 与桶默认 KMS 两种情况下都写入 `aws:kms`,因此 explicit / auto / bucket 三种模式均进入 KMS 分支。
|
||||
- 回归证明成立:`baseline-final.log` 用 `-overlay` 换回未修复 constructor,失败面精确为「trusted × 有效标签时间戳 × SSE-KMS / SSE-KMS-context」和 6 个 KMS COPY 子测试(`tags="key=old"`、`kms=true`、HTTP 200),`none`/`SSE-S3`/`SSE-C`/非 trusted 全通过。修复后 `focused.log:194-204` 全 PASS。
|
||||
- 测试确实覆盖被要求的维度:信任边界(trusted=false 时 mtime/ETag/三时间戳全归零)、错误路径(trusted + 畸形值必须报错且错误串含头名)、SSE 序列化回环(KMS keyID/context 原样还原)、磁盘终态(每事件 `obj.GetObjectInfo` 读真实盘)、版本一致性、签名 GET 明文可读。全局 `GlobalKMS`/`globalAutoEncryption`/`set.getDisks` 均 defer 还原。
|
||||
- `race` exit 0、`vet` 空输出、`golangci-lint` 0 issues,均记录了与 HEAD 一致的三文件哈希。
|
||||
- 未发现 `verification.md` / `verification.json` / `consensus.md` 中与日志矛盾的陈述。(评审者版本/模型/effort 这类 provenance 声明不在我可验证范围,未作背书。)
|
||||
|
||||
## 发现清单
|
||||
|
||||
| ID | 内容 | 阻断 |
|
||||
|---|---|---|
|
||||
| IMPL-01 | 单字段修复正确且充分,位置、变量、注释与 `:473` 语义一致 | 否(确认项) |
|
||||
| IMPL-02 | 基线失败/修复通过的判别力成立,对照组不误报 | 否(确认项) |
|
||||
| IMPL-03 | KMS 字面量相对 `getDefaultOpts` 仍缺 `ProxyHeaderSet`/`ProxyRequest`/`Speedtest`(`object-api-options.go:40-44` vs `:449-460`)。R4 范围外,已登记为 R4-06 | 否,不设为新合并门槛 |
|
||||
| IMPL-04 | `metadata-directive: REPLACE` 下 `getCpObjMetadataFromHeader`(`:1143-1156`)返回全新 map,故 `:1818` 的 `lastTaggingTimestamp` 为空、`:1822` 解析失败使 handler 侧比较恒「incoming 胜」;真正的 stale 拒绝发生在写锁内的 `reconcileStoredObjectTags`(`erasure-object.go:1312-1315`)。测试终态断言仍正确,文档 R4-07 已明示此分工 | 否(R5 上下文) |
|
||||
| IMPL-05 | 测试卫生:`bucket-kms` 模式写入的 `bucketSSEConfig` 未还原,仅因它是最后一个 mode、且 `ExecObjectLayerAPITest` 每后端重建对象层并 `resetTestGlobals()` 才安全;后续若在其后追加 mode 会继承默认 KMS | 否 |
|
||||
| IMPL-06 | `object-api-options-replication_test.go:35` 局部变量名 `context` 遮蔽标准包名(本文件未导入该包),纯观感 | 否 |
|
||||
| IMPL-07 | `focused.log` exit 1 的唯一失败是既有 `TestAPICopyObjectReplicaRetentionRemovalUnderBucketKMS`(`replication-trust_test.go:1284`,"Storage reached its minimum free drive threshold"),属本机磁盘余量环境问题,非本次引入;容量 overlay 是测试专用、未提交。新增 COPY 测试自带 `tagTestCapacityDisk` 包装,不受该阈值影响 | 否 |
|
||||
|
||||
**没有发现阻断性正确性问题。** 生产语义、存储格式、API 与既有排序规则均未改变,无任何既有测试断言旧(缺陷)行为。
|
||||
|
||||
## 合并适配性
|
||||
|
||||
`dbcf8dec5` 直接位于实时 main `9ebe81c1b` 之上,可快进合并。按仓库 CI 通过为前提,本实现适合合入 main。
|
||||
|
||||
*(我未运行任何测试,也未查询 GitHub;以上仅基于源码阅读与所提供日志。)*
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"baseline": "9ebe81c1b3611f9cc73e676b5b741c2be62c467a",
|
||||
"reviewed_head": "dbcf8dec589deb5d91e17d295cb70997635f5b55",
|
||||
"requested_model": "claude-opus-5",
|
||||
"requested_effort": "max",
|
||||
"cli_version": "2.1.270",
|
||||
"diff_sha256": "c8cd6648f8ecea835ec74a038cdeaa82acaa3f36250395f97ead3260dc2fc0a5",
|
||||
"started_at": "2026-09-15T15:59:41.004963+00:00",
|
||||
"status": "completed",
|
||||
"command": "/opt/homebrew/bin/claude --print --model claude-opus-5 --effort max --safe-mode --permission-mode plan --tools Read,Grep,Glob --strict-mcp-config --no-session-persistence --add-dir /Users/vonng/tmp/silo-r4-evidence-20260915-a9cb --output-format stream-json --verbose",
|
||||
"completed_at": "2026-09-15T16:03:52.331640+00:00",
|
||||
"assistant_models": [
|
||||
"claude-opus-5"
|
||||
],
|
||||
"observed_model": "claude-opus-5",
|
||||
"verdict": "GO_WITH_NONBLOCKING_NOTES",
|
||||
"blocking_findings": 0,
|
||||
"session_id": "c09bc4fb-85f1-4af8-a1de-c453398e4a20",
|
||||
"duration_ms": 161469,
|
||||
"subtype": "success",
|
||||
"is_error": false,
|
||||
"used_tools": {
|
||||
"Read": 20,
|
||||
"Glob": 3,
|
||||
"Grep": 14,
|
||||
"ExitPlanMode": 1
|
||||
},
|
||||
"raw_stream": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/merge-review-1/opus.jsonl",
|
||||
"stream_sha256": "875f617454b27e15ab44d9b777de89643ee352e0ccb948faad570fc546261acc",
|
||||
"review_sha256": "962ff88d2ffcb75cd692ec17017411d624de80dc120f8dedc675e0fe25009335",
|
||||
"prompt_sha256": "e1341c721161229431b943ba18d89b740e94470803c099b9ae3d597fd50544a4",
|
||||
"review_extraction": "The substantive review is an earlier assistant text block; result.result only repeats CLI plan-mode merge limitations. Full raw stream and all assistant text are retained."
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"original_reviewed_head": "dbcf8dec589deb5d91e17d295cb70997635f5b55",
|
||||
"dco_signed_equivalent_head": "03027727d1d1b97d8beb83ac55569ea9a83dab23",
|
||||
"notice_equivalence": {
|
||||
"cmd/object-api-options-replication_test.go": {
|
||||
"before_sha256": "1ea2a060987e32a4c76fce96ee974df475944c2d6ab482a4893e33daf7bca849",
|
||||
"after_sha256": "c21fc8889a079085d9a882499a1cbe868278a3517580651f3bed1102e2a6aef8",
|
||||
"package_body_sha256": "096f143c0b0a068581f9bb892f35ded0d65b6b60ab711f043236d27fbf51ca33",
|
||||
"body_unchanged": true
|
||||
},
|
||||
"cmd/object-copy-replication-tagging_test.go": {
|
||||
"before_sha256": "5437a77e68736b4ce69de9c777675251fef24b0352dfe30bd8a836fc7ee810e3",
|
||||
"after_sha256": "73f066ed7258d430f078ecc90e551ece878bd3d4672bc762094d434ff8fec23d",
|
||||
"package_body_sha256": "6b5173db2ded2d54055073c3259be208a4d7c8eac0367687082877f1fd3bef15",
|
||||
"body_unchanged": true
|
||||
}
|
||||
},
|
||||
"checks": {
|
||||
"verifiers": {
|
||||
"command": [
|
||||
"make",
|
||||
"verifiers",
|
||||
"GOLANGCI=/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/merge-review-1/golangci-serial"
|
||||
],
|
||||
"exit_code": 0,
|
||||
"started_at": "2026-09-15T16:04:55.536605+00:00",
|
||||
"finished_at": "2026-09-15T16:07:03.252820+00:00",
|
||||
"cwd": "/Users/vonng/.codex/worktrees/a9cb/silo",
|
||||
"env_override": {
|
||||
"GOMAXPROCS": "2",
|
||||
"GOFLAGS": "-p=2"
|
||||
},
|
||||
"source_sha256": {
|
||||
"cmd/object-api-options.go": "25e2e9484fafd94d1b2c857b94373758e481893ad93fb1a063edf7746277accc",
|
||||
"cmd/object-api-options-replication_test.go": "c21fc8889a079085d9a882499a1cbe868278a3517580651f3bed1102e2a6aef8",
|
||||
"cmd/object-copy-replication-tagging_test.go": "73f066ed7258d430f078ecc90e551ece878bd3d4672bc762094d434ff8fec23d"
|
||||
},
|
||||
"log_sha256": "e42a5bb55f5c1ebfcf02cebebf6d82cf1ec5a2d74590cdf838deba16dd80bfdf"
|
||||
},
|
||||
"build": {
|
||||
"command": [
|
||||
"make",
|
||||
"build"
|
||||
],
|
||||
"exit_code": 0,
|
||||
"started_at": "2026-09-15T16:07:03.253715+00:00",
|
||||
"finished_at": "2026-09-15T16:07:35.594062+00:00",
|
||||
"cwd": "/Users/vonng/.codex/worktrees/a9cb/silo",
|
||||
"env_override": {
|
||||
"GOMAXPROCS": "2",
|
||||
"GOFLAGS": "-p=2"
|
||||
},
|
||||
"source_sha256": {
|
||||
"cmd/object-api-options.go": "25e2e9484fafd94d1b2c857b94373758e481893ad93fb1a063edf7746277accc",
|
||||
"cmd/object-api-options-replication_test.go": "c21fc8889a079085d9a882499a1cbe868278a3517580651f3bed1102e2a6aef8",
|
||||
"cmd/object-copy-replication-tagging_test.go": "73f066ed7258d430f078ecc90e551ece878bd3d4672bc762094d434ff8fec23d"
|
||||
},
|
||||
"log_sha256": "6ba9b545236be964861749c72e7609edf12b8f470df30d1ede8fd62f497e629b"
|
||||
},
|
||||
"binary-version": {
|
||||
"command": [
|
||||
"./silo",
|
||||
"--version"
|
||||
],
|
||||
"exit_code": 0,
|
||||
"started_at": "2026-09-15T16:07:35.594918+00:00",
|
||||
"finished_at": "2026-09-15T16:07:37.616706+00:00",
|
||||
"cwd": "/Users/vonng/.codex/worktrees/a9cb/silo",
|
||||
"env_override": {
|
||||
"GOMAXPROCS": "2",
|
||||
"GOFLAGS": "-p=2"
|
||||
},
|
||||
"source_sha256": {
|
||||
"cmd/object-api-options.go": "25e2e9484fafd94d1b2c857b94373758e481893ad93fb1a063edf7746277accc",
|
||||
"cmd/object-api-options-replication_test.go": "c21fc8889a079085d9a882499a1cbe868278a3517580651f3bed1102e2a6aef8",
|
||||
"cmd/object-copy-replication-tagging_test.go": "73f066ed7258d430f078ecc90e551ece878bd3d4672bc762094d434ff8fec23d"
|
||||
},
|
||||
"log_sha256": "36317d06b691593fe0d74f88d053a24485500c15fc2001e857f2fc6fa5ba752a"
|
||||
}
|
||||
},
|
||||
"binary_version": "silo version DEVELOPMENT.2026-09-15T16-03-52Z (commit-id=03027727d1d1b97d8beb83ac55569ea9a83dab23)\nRuntime: go1.27.1 darwin/arm64\nLicense: GNU AGPLv3 - https://www.gnu.org/licenses/agpl-3.0.html\nCopyright: 2015-2025 MinIO, Inc.\nModifications: Copyright 2025-2026 PGSTY\nSource compatibility: based on MinIO technology\n",
|
||||
"raw_evidence_directory": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/merge-review-1",
|
||||
"all_function_and_test_bodies_identical_to_opus_reviewed_version": true
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# R4 合并前复核
|
||||
|
||||
用户已明确追加授权:使用 Opus 5 max 核实最终实现,确认无误后合并 main。本轮授权取代此前只交付本地补丁的范围限制。
|
||||
|
||||
## 真实实现评审
|
||||
|
||||
- 独立新调用:Claude Code 2.1.270,`--model claude-opus-5 --effort max`。
|
||||
- 复核代码提交:`dbcf8dec589deb5d91e17d295cb70997635f5b55`;当时实时 main 与 fetch 结果均为 `9ebe81c1b3611f9cc73e676b5b741c2be62c467a`。
|
||||
- 实际 assistant 模型只有 `claude-opus-5`。结论 **GO_WITH_NONBLOCKING_NOTES,0 阻断项**,明确表示仓库 CI 通过后适合合入 main。
|
||||
- [原始实现评审正文](implementation-review.md)、[实际模型与输出哈希](implementation-review.metadata.json) 已保存。
|
||||
- 原始流、全部 assistant 正文与最终 result 位于 `/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/merge-review-1/`。实质评审出现在较早的 assistant 消息;最终 result 只重复 Claude 只读会话不能自行合并的工具限制,不是对修复结论的撤回。本任务由 Codex 按用户明确授权完成合并。
|
||||
|
||||
## 意见处置
|
||||
|
||||
| 条目 | 处置 |
|
||||
|---|---|
|
||||
| IMPL-01 / IMPL-02 | 确认单字段修复和基线失败/修复通过的测试判别力,无需追加修改。 |
|
||||
| IMPL-03 | Proxy/Speedtest 选项遗漏已交父任务单独核验,维持范围外,不纳入 R4 合并。 |
|
||||
| IMPL-04 | REPLACE 请求的旧标签拒绝由写锁内对账完成,测试断言真实落盘状态,已有文档准确说明。 |
|
||||
| IMPL-05 | 当前测试固定以 bucket-kms 为最后一种模式,且每后端重新初始化;现有执行顺序安全。后续增添模式需同步隔离桶默认配置,本次保持已评审测试逻辑。 |
|
||||
| IMPL-06 | 局部变量 context 命名建议为可选观感项,不改动已评审逻辑。 |
|
||||
| IMPL-07 | 既有锁测试的磁盘余量限制及仅测试容量 overlay 已如实记录;新测试和 race 不使用生产代码 overlay。 |
|
||||
|
||||
## 提交规范调整
|
||||
|
||||
按 `CONTRIBUTING.md` 补齐提交作者对应的 DCO sign-off,并将两个新原创测试文件的文件头改为 `Copyright (c) 2026 Feng Ruohang`,保留 AGPL-3.0-or-later。原有生产文件的继承声明保持原样。
|
||||
|
||||
生产函数和测试的 `package cmd` 之后内容与 Opus 审查版本逐字节相同。`merge-review-1/notice-equivalence.json` 记录了旧/新文件哈希及不变的代码正文哈希。原 `verification.json` 保留当时原始验证记录,不覆盖历史哈希;本轮 PR 的 CI 对最终提交重新验证。
|
||||
|
||||
## 合并门槛
|
||||
|
||||
`make verifiers` 已通过:全仓 lint 为 0 issues,生成文件检查通过,rebrand 兼容性清单未变化,交付/运行时标识检查和 entrypoint 参数兼容性测试通过。首次执行曾遇到其他任务持有 golangci-lint 进程锁;使用工具自带 `--allow-serial-runners` 串行等待后完成全部检查。可选 typos 工具未安装,由仓库 Makefile 按既有规则跳过。
|
||||
|
||||
`make build` 通过,已生成本地 `silo` 并成功执行 `./silo --version`。最终三个源文件哈希与本轮校验记录一致,详情见 [本轮验证清单](merge-verification.json)。
|
||||
|
||||
接下来由 PR CI 验证最终候选,并在合并前再次核对 main 和精确 PR head。CI 与合并事实以 GitHub PR 状态和本机原始合并证据为准,评审意见不等同于合并或发布。
|
||||
@@ -0,0 +1,46 @@
|
||||
## R4 独立评审(Opus 5.0,只读复核)
|
||||
|
||||
**计划**:plan v1 — `docs/investigations/r4/plan-v1.md`
|
||||
**哈希(按任务给定)**:`ad539f2071155de6955b583991684ed33c4bfe2e29660005840cdc97d7e1a754`
|
||||
**Baseline**:`9ebe81c1b3611f9cc73e676b5b741c2be62c467a`
|
||||
|
||||
### 裁定:GO_WITH_NONBLOCKING_NOTES
|
||||
|
||||
无阻断项。**我同意这份 exact plan(上述哈希)可以进入本地实现。** 下列 R4-01…R4-08 均为非阻断;其中 R4-02/04/05 的测试建议是**可选**的,不自动并入必做范围。
|
||||
|
||||
(说明:本会话 Write 工具被禁用,评审仅以正文返回,未写入任何文件,也未改动任何源码。)
|
||||
|
||||
### 我实际核验到的关键事实(支撑"单字段补丁正确且充分")
|
||||
|
||||
1. **缺陷确认**:`cmd/object-api-options.go:449-460` 的 KMS 字面量带了 MTime/PreserveETag/ReplicationRequest + 两个 Object Lock 时间戳,独缺 tagging;默认路径 `:473` 有。补丁片段中的变量名 `taggingtimestmp` 与 `:419` 完全一致,可直接编译;gofmt 对齐由更长的两个 Lock 键决定,不会扰动他行。
|
||||
2. **影响面封闭**:全仓 `ReplicationSourceTaggingTimestamp` 只在 `cmd/object-handlers.go:1820` 被读取(定义于 `object-api-interface.go:99`)。因此该字段对 PUT/分段路径天然无效果——既印证 R4/R5 的切分合理,也说明补丁不可能回归其他路径。
|
||||
3. **充分性的关键点(我重点查证的风险)**:`encMetadata` 只有在 SSE-C 轮换分支 `object-handlers.go:1648-1659` 才批量快照全部保留键,而该分支与 KMS options 分支互斥(目的端是 SSE-C 时 `crypto.S3KMS.IsRequested` 为假)。故 `:1903` 的 `maps.Copy(srcInfo.UserDefined, encMetadata)` **不会**覆盖 KMS COPY 新写入的 tags/时间戳 —— 单字段补丁在 R4 边界内充分。
|
||||
4. **三个触发点准确**:`bucket-sse-config.go:135-153`(显式请求优先 → nil 配置 + AutoEncrypt → KMS → bucket 默认 KMS 写 header+keyID;默认 AES 走 AES 分支),配合 `object-handlers.go:1428-1433` 仅在非联邦时套用目的端默认。
|
||||
5. **REPLACE 副本路径准确**:`reconcileStoredObjectTags`(`erasure-server-pool-consistency.go:232-243`)语义即"存量有效时间戳胜过缺失/更旧/相等的 incoming,并连同 tag 值一起还原"。KMS 目的端因 `isTargetEncrypted` 使 `metadataOnly=false`,实际落到 `erasure-server-pool.go:1499-1513`(`ReplicaLockReconcile` 经 `:1509` 透传)→ `erasure-object.go:1276-1316`,在 `cloneMSS`(:1324) 之前于写锁内完成对账;纯元数据路径走 `erasure-object.go:136-139`。计划同时引用 `:136` 与 `:1509`,判断正确。
|
||||
6. **证据可信**:`baseline-repro.log` 中 options 用例非 KMS 保留 `...123456789Z`、KMS 返回零值;COPY 用例 6/6(ErasureSD + Erasure16 × explicit/auto/bucket KMS)失败,且均为 200、`kms=true`、明文 GET 通过、tags 停在 `key=old`。即"请求成功、加密正常,但复制标签被静默丢弃",与计划表述一致,未夸大。
|
||||
7. **修复后推演**:newer/stale/duplicate/newer-again 在 handler(:1817-1833) 与写锁对账的双重排序下分别得到 new/new/new/latest,与测试期望吻合;旧发送端不带 `X-Minio-Source-Tagging-Timestamp` 时仍为零值 → 行为不变,兼容性主张成立。
|
||||
|
||||
### 问题清单
|
||||
|
||||
| ID | 阻断 | 内容与建议 |
|
||||
|---|---|---|
|
||||
| **R4-01** | 否 | 行号漂移:计划写的 `1851/1910`,实际是 `object-handlers.go:1847`(`ReplicaLockReconcile`)与 `:1903`(encMetadata merge)。建议更正引用。 |
|
||||
| **R4-02** | 否(建议可选) | `ExecObjectLayerAPITest` 两种后端均为**单 pool**(`test-utils_test.go:216` `mustGetPoolEndpoints(0, ...)`),故 `erasure-server-pool.go:1443` 多池分支未被覆盖;且 KMS 目的端命中的是 PutObject 重写对账而非 `CopyObject:136`。建议在计划或测试注释中点明"单盘/16 盘均为单池";补多池覆盖**可选**,不必进必做范围。 |
|
||||
| **R4-03** | 否 | 措辞:`crypto.Requested`(`internal/crypto/sse.go:74`)只检查**目的端** SSE 头,因此仅带 SSE-C *copy-source* 头的请求在 KMS 默认桶/自动加密下仍会进入 KMS 分支(归入触发点 2/3,枚举仍完整)。建议澄清 "source encryption alone…" 一句。 |
|
||||
| **R4-04** | 否(**可选**) | 建议在 options 矩阵里加一条 KMS 分支 vs 默认分支的**逐字段等价断言**(MTime/PreserveETag/ReplicationRequest/三个复制时间戳)。这是阻止第三次复发最廉价的护栏(2021 漏、2026 补了两个 Lock 时间戳仍漏此项)。计划第 1 条已基本覆盖,此为结构化建议。 |
|
||||
| **R4-05** | 否(**可选**) | 建议加一例"KMS 目的端 + 有 tags 但无 tagging 时间戳头 → 存量不变",把兼容性主张钉在 handler 层而不仅在 options 层。 |
|
||||
| **R4-06** | 否(范围外,仅登记) | 同一 KMS 字面量相对 `getDefaultOpts`(`object-api-options.go:40-44`) 还遗漏 `ProxyHeaderSet/ProxyRequest/Speedtest`;`opts.Speedtest` 在 `erasure-object.go:1625` 被读取,全局自动加密下 speedtest PUT 会丢该标志。**不要在 R4 修**,且当前也不在 R5 声明范围内,建议单列条目登记。 |
|
||||
| **R4-07** | 否 | REPLACE 时 `getCpObjMetadataFromHeader:1143-1156` 会重建 map,`lastTaggingTimestamp` 为空 → handler 对 stale 事件**恒接受**,真正的拒绝来自写锁内对账。因此回归测试必须断言**最终落盘状态**(现有复现已如此),不要改为断言 handler 层行为。 |
|
||||
| **R4-08** | 否(不确定性) | 本会话无 shell,无法独立复算计划 SHA-256、验证 `c4373ef290 / b2dca43fda / cfefc049c` 历史归属与 PR #184/#187。可由 `shasum -a 256 docs/investigations/r4/plan-v1.md` 与 `git log -L` 输出消解;均不影响补丁正确性。`cfefc049c` 的 KMS context 编码修复实体(`:436-444` 的 `sdkContext`)仍在,补丁不触碰。 |
|
||||
|
||||
### 对计划各主张的逐项裁定
|
||||
|
||||
- 单字段补丁**正确且对本 bounded issue 充分**:同意(依据 2/3/7)。
|
||||
- 三个目的端 KMS 触发点**描述准确**:同意(R4-03 仅措辞澄清)。
|
||||
- 当前 REPLACE 副本路径**描述准确**:同意(R4-01/02 属引用精度)。
|
||||
- 回归矩阵与存量状态说明**充分**:同意;存量部分"不自动回填、丢失源时间不可重建、并列/更旧事件不保证修复"的表述与 `reconcileStoredObjectTags` 实际语义一致。
|
||||
- 信任边界、错误行为、加密 key/context、tie 语义、兼容性:补丁均未触碰,维持不变。
|
||||
|
||||
### 交付
|
||||
|
||||
本轮为**计划共识**,非实现验收。我未作任何源码或文件修改;R4 可按 plan v1 在本地实施,实施后的差异与测试证据需另行验收。
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"baseline": "9ebe81c1b3611f9cc73e676b5b741c2be62c467a",
|
||||
"plan": "docs/investigations/r4/plan-v1.md",
|
||||
"plan_sha256": "ad539f2071155de6955b583991684ed33c4bfe2e29660005840cdc97d7e1a754",
|
||||
"requested_model": "claude-opus-5",
|
||||
"requested_effort": "max",
|
||||
"cli_version": "2.1.270",
|
||||
"started_at": "2026-09-15T15:45:46.438630+00:00",
|
||||
"status": "completed",
|
||||
"raw_output": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/opus-review-v1.jsonl",
|
||||
"raw_stderr": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/opus-review-v1.stderr.log",
|
||||
"command": "/opt/homebrew/bin/claude --print --model claude-opus-5 --effort max --safe-mode --permission-mode plan --tools Read,Grep,Glob --strict-mcp-config --no-session-persistence --add-dir /Users/vonng/tmp/silo-r4-evidence-20260915-a9cb --output-format stream-json --verbose",
|
||||
"completed_at": "2026-09-15T15:49:48.150062+00:00",
|
||||
"assistant_models": [
|
||||
"claude-opus-5"
|
||||
],
|
||||
"observed_model": "claude-opus-5",
|
||||
"verdict": "GO_WITH_NONBLOCKING_NOTES",
|
||||
"blocking_findings": 0,
|
||||
"result_subtype": "success",
|
||||
"is_error": false,
|
||||
"session_id": "63e14a68-8565-41fa-9746-3e405fb63e9f",
|
||||
"duration_ms": 161784,
|
||||
"num_turns": 35,
|
||||
"used_tools": {
|
||||
"Read": 18,
|
||||
"Glob": 4,
|
||||
"Grep": 11,
|
||||
"Write": 1
|
||||
},
|
||||
"stream_sha256": "eb0918d8a6185b180dddcfc664a96682f05502ecf3b686b08a0547f09879d57d",
|
||||
"review_sha256": "e1dc12dd99326ae432623ff8de201813e6e84e7ed16a5556c21f9c514d663676",
|
||||
"prompt_sha256": "07c225beff1523e056c154b3a387cf1ae345def4b4d0173065b882140ac5abdf",
|
||||
"tool_scope_note": "Read/Grep/Glob allowed. Claude attempted Write to its own plan; the tool was disabled and no file was written. git diff before consensus showed no production source changes.",
|
||||
"auxiliary_model_note": "assistant_models records actual reviewing assistant messages. Auxiliary usage is distinct. --effort max is explicit in the command, not inferred from model usage."
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
# R4 plan v1: preserve the replicated tag timestamp for SSE-KMS
|
||||
|
||||
## Baseline and ownership
|
||||
|
||||
- Baseline: `9ebe81c1b3611f9cc73e676b5b741c2be62c467a`, verified against GitHub main on 2026-09-15.
|
||||
- Branch: `codex/r4-kms-tag-timestamp`; worktree: `/Users/vonng/.codex/worktrees/a9cb/silo`.
|
||||
- Live open PRs at inspection: #184 and #187, neither owns this options change.
|
||||
- The worktree lacks the ignored `AGENTS.md`; the parent explicitly confirms `/Users/vonng/pgsty/silo/AGENTS.md` applies. Maintain the PGSTY product graph and inexpensive compatibility.
|
||||
- R4 owns only the missing field in `cmd/object-api-options.go` and its regression tests. R5 owns DELETE/empty tags, PUT/multipart receiving, sender propagation and full receiver ordering. R4 will supply a standalone source patch to R5; neither task edits the other's worktree.
|
||||
|
||||
## Proven defect and actual trigger
|
||||
|
||||
`putOptsFromHeaders` parses the trusted source tag timestamp before selecting encryption. The SSE-KMS branch constructs and returns another `ObjectOptions` carrying mtime, ETag, replication trust and both Object Lock timestamps, but omits `ReplicationSourceTaggingTimestamp`. The normal path retains it. The parser accepts and preserves RFC3339 fractional seconds even though its layout is `time.RFC3339`; the reproduction uses nanoseconds.
|
||||
|
||||
`CopyObjectHandler` applies local destination encryption configuration before `copyDstOpts` → `putOptsFromReq` → `putOpts` → `putOptsFromHeaders`. The omission is reached by:
|
||||
|
||||
1. Explicit destination SSE-KMS request headers (with or without a key ID/context).
|
||||
2. A destination bucket with default SSE-KMS, when the request has no explicit SSE choice.
|
||||
3. Global automatic encryption with no bucket SSE override and no explicit SSE choice.
|
||||
|
||||
Explicit AES256/SSE-C takes its existing branch; source encryption alone does not select the destination KMS branch. Remote federation skips local destination defaults. The relevant trigger is trusted metadata entering the destination KMS branch, not every SSE-KMS object or every tag operation.
|
||||
|
||||
At `CopyObjectHandler`'s tag decision, a zero source timestamp skips the tag update. Current under-lock reconciliation can preserve the stored tag/timestamp when metadata REPLACE reconstructs the map with no timestamp. In the observed same-version replica COPY, the request succeeds, destination encryption is valid, and the old tags/timestamp remain. A missing field in the options layer is not itself proof of a content-read failure.
|
||||
|
||||
PUT and multipart consumers' independent failure to persist a parsed tag timestamp remain R5's responsibility. R4 does not claim to fix all tag replication by correcting this constructor.
|
||||
|
||||
## Source and reproduction evidence
|
||||
|
||||
- `cmd/object-api-options.go`: trusted parsing at 383–426; KMS construction at 433–460; normal assignments at 469–475.
|
||||
- `cmd/object-handlers.go`: destination default encryption at 1425–1435; `copyDstOpts` at 1454; tag timestamp consumption at 1807–1834; replica reconciliation enabled at 1851; encryption metadata merge at 1910.
|
||||
- `internal/bucket/encryption/bucket-sse-config.go:135`: explicit request wins, absent config + auto encryption selects KMS, otherwise configured bucket algorithm/key ID applies.
|
||||
- `cmd/erasure-server-pool-consistency.go:232`: stored valid timestamp wins over absent, older or equal incoming timestamp; writes preserve the stored tag value alongside its timestamp.
|
||||
- `cmd/erasure-object.go:136` and `cmd/erasure-server-pool.go:1509`: same-version replica COPY reaches existing under-lock tag reconciliation, including object-data rewrites.
|
||||
- History: the omission exists in `c4373ef290` (2021-09-18); `b2dca43fda` (2026-09-05) added the two Object Lock timestamps but not the tag timestamp. `cfefc049c` fixed KMS context encoding independently and must remain intact.
|
||||
- Fresh temporary reproduction: `/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/r4_repro_test.go` and `baseline-repro.log` (overlay; no production edits).
|
||||
- Command: `GOMAXPROCS=2 go test -p 2 -overlay /Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/overlay.json ./cmd -run '^TestReviewR4' -count=1 -timeout 5m -v`.
|
||||
- Result: expected failure. Unencrypted and AES256 options preserve `2026-09-15T01:00:00.123456789Z`; KMS returns zero. Signed metadata REPLACE COPY on ErasureSD and Erasure (16 disks), across explicit/default/automatic KMS, returns 200 but retains `key=old` and the old timestamp for newer events. Actual encrypted metadata and plaintext GET roundtrips pass. Test deltas are 1–3 nanoseconds.
|
||||
- These are in-process signed HTTP router and real local disk tests. `kms.NewStub` replaces the remote key service; the normal server encryption/decryption code still runs. Existing `tagTestCapacityDisk` avoids the host's free-space percentage threshold; it delegates all object data/metadata I/O to real test disks.
|
||||
|
||||
## Proposed production change
|
||||
|
||||
Add exactly this field to the existing KMS `ObjectOptions` literal:
|
||||
|
||||
```go
|
||||
ReplicationSourceTaggingTimestamp: taggingtimestmp,
|
||||
```
|
||||
|
||||
Update the neighboring explanatory comment to include tagging alongside retention/legal hold. Do not refactor the common return paths, change parsing/fallback/equal-timestamp semantics, change encryption context encoding, modify trust decisions, add SDK dependencies, or change storage/wire format. Those changes are unnecessary to restore the missing existing contract.
|
||||
|
||||
## Required validation after consensus
|
||||
|
||||
1. Add an options regression matrix covering unencrypted, SSE-S3, SSE-KMS with no context, SSE-KMS with a context, and SSE-C. Validate trusted/untrusted requests, missing/valid/malformed tag timestamps, nanosecond and timezone/whitespace handling, all three replication timestamps, mtime/ETag/trust, nonnil metadata, and unchanged SSE header serialization (including KMS key/context).
|
||||
2. Promote the temporary COPY reproduction into a named, isolated regression test. Use actual signed same-version metadata COPY with REPLACE metadata and tagging directives, on single-disk and 16-disk backends. For explicit, bucket-default and automatic SSE-KMS, check newer update, older delivery, duplicate replay, and a second newer update. Verify stored tags, exact timestamp, version ID, encryption kind and plaintext GET after each operation. Include an unencrypted/SSE-S3 control if the fixture can do so without expanding implementation scope.
|
||||
3. Fail the final regression tests against unmodified baseline using an overlay. Then run them on the fixed source, alongside existing replication-trust/options and bucket-KMS Object Lock tests. Check `gofmt`, `git diff --check`, and `go vet ./cmd`.
|
||||
4. Run the new focused tests under `-race`. Use `GOMAXPROCS=2` and `-p 2` while sibling tasks share the host. A one-field pure option fix does not justify concurrent full-repository suites in all five tasks; full Linux CI and multi-site validation remain separate delivery gates.
|
||||
5. If a test exposes a separate handler/storage defect, report evidence and coordinate with R5. Do not broaden R4's production patch to make unrelated tests pass.
|
||||
|
||||
## Compatibility, existing state, effort and delivery
|
||||
|
||||
- Public API, header names, stored key names, KMS context/key handling and supported dependencies remain unchanged. Untrusted source headers stay ignored; malformed trusted timestamps continue to fail; absent timestamp remains zero. Existing non-KMS behavior remains unchanged.
|
||||
- No automatic rewrite/backfill. Lost source tag times cannot be reconstructed from the receiver alone. Upgrading permits subsequent properly timestamped events to be consumed. Review source-of-truth and target state before any targeted resync; full historical convergence also depends on R5. Repeated events subject to existing timestamp/tie semantics are not a universal repair guarantee.
|
||||
- The source fix can land independently; complete deletion/empty-tag and mixed-encryption convergence needs R5 plus its integration evidence.
|
||||
- Expected effort: approximately 0.5–1 engineer-day including reproduction, review and local validation; key-service deployment, multi-site failures and existing-state remediation are separate.
|
||||
- After actual Opus 5.0/max agreement on this exact plan hash, implement locally without another user permission prompt. Preserve raw review, assistant model identity, request effort, baseline and plan hash, issue-by-issue disposition and explicit consensus before source edits.
|
||||
- Deliver a reviewable local diff, tests and evidence. No main merge, remote publication/release, deployment or existing-state rewrite is authorized by this plan.
|
||||
@@ -0,0 +1,18 @@
|
||||
# R4 research log
|
||||
|
||||
## Verified baseline
|
||||
|
||||
2026-09-15: local clean HEAD and GitHub main both `9ebe81c1b3611f9cc73e676b5b741c2be62c467a`. Branch created as `codex/r4-kms-tag-timestamp`. Live GitHub open PRs #184 (`6addf9eb916b5a4b837480cf534cd1efa5407d3c`) and #187 (`b8f2fdde41dff3dc3b8db669c1d42d30ca5c1d3d`) concern other tasks. Claude Code reports `2.1.270`; Go reports `go1.27.1 darwin/arm64`.
|
||||
|
||||
## Coordination
|
||||
|
||||
- Parent task: `01a0a5ab-ee43-7911-bddd-1aca6f8afcc8`.
|
||||
- R5: `01a0a5b9-602d-7470-9882-4817cf5fdcd1`, `/Users/vonng/.codex/worktrees/77ad/silo`.
|
||||
- Parent and R5 acknowledged the ownership boundary: R4 options constructor and nonempty KMS COPY tests; R5 producer/receiver ordering and empty values. R5 will consume R4's minimal patch for combined KMS acceptance.
|
||||
- Initial conservative expectation separated metadata COPY from REPLACE ordering. Inspection of current `ReplicaLockReconcile` and `reconcileStoredObjectTags` shows that stored timestamps are also reconciled under the write lock for REPLACE. The temporary reproduction therefore uses REPLACE directly; the fix must demonstrate the actual sender-shaped path without changing the handler.
|
||||
|
||||
## Baseline reproduction
|
||||
|
||||
Temporary overlay test source and output are in `/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/`. The options and HTTP/disk reproductions fail for the expected missing timestamp. Every KMS HTTP request completed with 200; newer tags remained old; encrypted object metadata and subsequent ordinary plaintext GET succeeded. The result is narrower than claiming all KMS replication fails, and stronger than merely comparing options.
|
||||
|
||||
The temporary source is not a production implementation. See [plan v1](plan-v1.md) for exact scope and required acceptance. The plan is frozen by SHA-256 before invoking real Opus.
|
||||
@@ -0,0 +1,358 @@
|
||||
{
|
||||
"baseline": "9ebe81c1b3611f9cc73e676b5b741c2be62c467a",
|
||||
"branch": "codex/r4-kms-tag-timestamp",
|
||||
"source_sha256": {
|
||||
"cmd/object-api-options.go": "25e2e9484fafd94d1b2c857b94373758e481893ad93fb1a063edf7746277accc",
|
||||
"cmd/object-api-options-replication_test.go": "1ea2a060987e32a4c76fce96ee974df475944c2d6ab482a4893e33daf7bca849",
|
||||
"cmd/object-copy-replication-tagging_test.go": "5437a77e68736b4ce69de9c777675251fef24b0352dfe30bd8a836fc7ee810e3"
|
||||
},
|
||||
"source_files_match_all_test_runs": true,
|
||||
"checks": [
|
||||
{
|
||||
"name": "baseline-final",
|
||||
"command": [
|
||||
"go",
|
||||
"test",
|
||||
"-p",
|
||||
"2",
|
||||
"-overlay",
|
||||
"/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/baseline-final-overlay.json",
|
||||
"./cmd",
|
||||
"-run",
|
||||
"^Test(PutOptsFromHeadersReplicationTimestamps|APICopyObjectReplicaTaggingTimestampUnderKMS)$",
|
||||
"-count=1",
|
||||
"-timeout=5m",
|
||||
"-v"
|
||||
],
|
||||
"cwd": "/Users/vonng/.codex/worktrees/a9cb/silo",
|
||||
"env_override": {
|
||||
"GOMAXPROCS": "2"
|
||||
},
|
||||
"started_at": "2026-09-15T15:50:49.430860+00:00",
|
||||
"finished_at": "2026-09-15T15:51:20.637630+00:00",
|
||||
"exit_code": 1,
|
||||
"log": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/baseline-final.log",
|
||||
"source_sha256": {
|
||||
"cmd/object-api-options.go": "25e2e9484fafd94d1b2c857b94373758e481893ad93fb1a063edf7746277accc",
|
||||
"cmd/object-api-options-replication_test.go": "1ea2a060987e32a4c76fce96ee974df475944c2d6ab482a4893e33daf7bca849",
|
||||
"cmd/object-copy-replication-tagging_test.go": "5437a77e68736b4ce69de9c777675251fef24b0352dfe30bd8a836fc7ee810e3"
|
||||
},
|
||||
"log_sha256": "f849c2082235213764e3db7a314d52af75c4859102478a1e8f837afcaa8f1ea8",
|
||||
"overlay_sha256": "f4cbc16e4ffccaf63191de2e8476162876055796adb4c38cda2d8c569a3bbabc",
|
||||
"overlay_sources": {
|
||||
"/Users/vonng/.codex/worktrees/a9cb/silo/cmd/object-api-options.go": {
|
||||
"path": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/object-api-options.baseline.go",
|
||||
"sha256": "16a560d0990ae929393f682f22b32ecd2e7f4d9390484b03b54e176fcd00cff5"
|
||||
}
|
||||
},
|
||||
"assessment": "Expected baseline regression failure; KMS timestamp loss. Non-KMS controls pass."
|
||||
},
|
||||
{
|
||||
"name": "focused",
|
||||
"command": [
|
||||
"go",
|
||||
"test",
|
||||
"-p",
|
||||
"2",
|
||||
"./cmd",
|
||||
"-run",
|
||||
"^Test(PutOptsFromHeadersReplicationTimestamps|APICopyObjectReplicaTaggingTimestampUnderKMS|ReplicationTrustControlsInternalOptionsAndEvents|GetAndValidateAttributesOpts.*|APICopyObjectReplicaRetentionRemovalUnderBucketKMS)$",
|
||||
"-count=1",
|
||||
"-timeout=5m",
|
||||
"-v"
|
||||
],
|
||||
"cwd": "/Users/vonng/.codex/worktrees/a9cb/silo",
|
||||
"env_override": {
|
||||
"GOMAXPROCS": "2"
|
||||
},
|
||||
"started_at": "2026-09-15T15:51:20.638633+00:00",
|
||||
"finished_at": "2026-09-15T15:51:48.382212+00:00",
|
||||
"exit_code": 1,
|
||||
"log": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/focused.log",
|
||||
"source_sha256": {
|
||||
"cmd/object-api-options.go": "25e2e9484fafd94d1b2c857b94373758e481893ad93fb1a063edf7746277accc",
|
||||
"cmd/object-api-options-replication_test.go": "1ea2a060987e32a4c76fce96ee974df475944c2d6ab482a4893e33daf7bca849",
|
||||
"cmd/object-copy-replication-tagging_test.go": "5437a77e68736b4ce69de9c777675251fef24b0352dfe30bd8a836fc7ee810e3"
|
||||
},
|
||||
"log_sha256": "9a64cbc46e9fd6186b1d3031034b720857851ce70b1466b1da5da6d1a52b76ba",
|
||||
"assessment": "New tests and options/trust pass; pre-existing KMS lock fixture blocked by host disk free-space percentage."
|
||||
},
|
||||
{
|
||||
"name": "focused-capacity-adapted",
|
||||
"command": [
|
||||
"go",
|
||||
"test",
|
||||
"-p",
|
||||
"2",
|
||||
"-overlay",
|
||||
"/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/capacity-overlay.json",
|
||||
"./cmd",
|
||||
"-run",
|
||||
"^Test(PutOptsFromHeadersReplicationTimestamps|APICopyObjectReplicaTaggingTimestampUnderKMS|ReplicationTrustControlsInternalOptionsAndEvents|GetAndValidateAttributesOpts.*|APICopyObjectReplicaRetentionRemovalUnderBucketKMS)$",
|
||||
"-count=1",
|
||||
"-timeout=5m",
|
||||
"-v"
|
||||
],
|
||||
"cwd": "/Users/vonng/.codex/worktrees/a9cb/silo",
|
||||
"env_override": {
|
||||
"GOMAXPROCS": "2"
|
||||
},
|
||||
"started_at": "2026-09-15T15:52:20.113475+00:00",
|
||||
"finished_at": "2026-09-15T15:52:50.842773+00:00",
|
||||
"exit_code": 0,
|
||||
"log": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/focused-capacity-adapted.log",
|
||||
"source_sha256": {
|
||||
"cmd/object-api-options.go": "25e2e9484fafd94d1b2c857b94373758e481893ad93fb1a063edf7746277accc",
|
||||
"cmd/object-api-options-replication_test.go": "1ea2a060987e32a4c76fce96ee974df475944c2d6ab482a4893e33daf7bca849",
|
||||
"cmd/object-copy-replication-tagging_test.go": "5437a77e68736b4ce69de9c777675251fef24b0352dfe30bd8a836fc7ee810e3"
|
||||
},
|
||||
"log_sha256": "13f7aa54564a433bef4dddcf2c5ad1fe46fa03869527fb902a255ce4c3263bc9",
|
||||
"overlay_sha256": "76a7e6fb364bdaaa3469b1dc79f9ea318059f287a4888f322639920c76dfe53a",
|
||||
"overlay_sources": {
|
||||
"/Users/vonng/.codex/worktrees/a9cb/silo/cmd/replication-trust_test.go": {
|
||||
"path": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/replication-trust-capacity_test.go",
|
||||
"sha256": "c81b526ae51983881bbf464199e6b90f074fa695300fa8ff005e427e4d3c8208"
|
||||
}
|
||||
},
|
||||
"assessment": "PASS"
|
||||
},
|
||||
{
|
||||
"name": "race",
|
||||
"command": [
|
||||
"go",
|
||||
"test",
|
||||
"-p",
|
||||
"2",
|
||||
"-race",
|
||||
"./cmd",
|
||||
"-run",
|
||||
"^Test(PutOptsFromHeadersReplicationTimestamps|APICopyObjectReplicaTaggingTimestampUnderKMS)$",
|
||||
"-count=1",
|
||||
"-timeout=5m",
|
||||
"-v"
|
||||
],
|
||||
"cwd": "/Users/vonng/.codex/worktrees/a9cb/silo",
|
||||
"env_override": {
|
||||
"GOMAXPROCS": "2"
|
||||
},
|
||||
"started_at": "2026-09-15T15:52:50.843898+00:00",
|
||||
"finished_at": "2026-09-15T15:53:43.789325+00:00",
|
||||
"exit_code": 0,
|
||||
"log": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/race.log",
|
||||
"source_sha256": {
|
||||
"cmd/object-api-options.go": "25e2e9484fafd94d1b2c857b94373758e481893ad93fb1a063edf7746277accc",
|
||||
"cmd/object-api-options-replication_test.go": "1ea2a060987e32a4c76fce96ee974df475944c2d6ab482a4893e33daf7bca849",
|
||||
"cmd/object-copy-replication-tagging_test.go": "5437a77e68736b4ce69de9c777675251fef24b0352dfe30bd8a836fc7ee810e3"
|
||||
},
|
||||
"log_sha256": "ae66a8c9e569a5c4b57ae56e75afc85c06a8b76f1567187519da0726605a4de4",
|
||||
"assessment": "PASS"
|
||||
},
|
||||
{
|
||||
"name": "vet",
|
||||
"command": [
|
||||
"go",
|
||||
"vet",
|
||||
"-p",
|
||||
"2",
|
||||
"./cmd"
|
||||
],
|
||||
"cwd": "/Users/vonng/.codex/worktrees/a9cb/silo",
|
||||
"env_override": {
|
||||
"GOMAXPROCS": "2"
|
||||
},
|
||||
"started_at": "2026-09-15T15:53:43.790197+00:00",
|
||||
"finished_at": "2026-09-15T15:53:51.129773+00:00",
|
||||
"exit_code": 0,
|
||||
"log": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/vet.log",
|
||||
"source_sha256": {
|
||||
"cmd/object-api-options.go": "25e2e9484fafd94d1b2c857b94373758e481893ad93fb1a063edf7746277accc",
|
||||
"cmd/object-api-options-replication_test.go": "1ea2a060987e32a4c76fce96ee974df475944c2d6ab482a4893e33daf7bca849",
|
||||
"cmd/object-copy-replication-tagging_test.go": "5437a77e68736b4ce69de9c777675251fef24b0352dfe30bd8a836fc7ee810e3"
|
||||
},
|
||||
"log_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"assessment": "PASS"
|
||||
},
|
||||
{
|
||||
"name": "lint",
|
||||
"command": [
|
||||
"/Users/vonng/pgsty/silo/.bin/golangci/v2.13.1/golangci-lint",
|
||||
"run",
|
||||
"--build-tags",
|
||||
"kqueue",
|
||||
"--timeout=10m",
|
||||
"--config",
|
||||
"./.golangci.yml",
|
||||
"./cmd/..."
|
||||
],
|
||||
"cwd": "/Users/vonng/.codex/worktrees/a9cb/silo",
|
||||
"env_override": {
|
||||
"GOMAXPROCS": "2"
|
||||
},
|
||||
"started_at": "2026-09-15T15:53:51.130456+00:00",
|
||||
"finished_at": "2026-09-15T15:55:39.114303+00:00",
|
||||
"exit_code": 0,
|
||||
"log": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/lint.log",
|
||||
"source_sha256": {
|
||||
"cmd/object-api-options.go": "25e2e9484fafd94d1b2c857b94373758e481893ad93fb1a063edf7746277accc",
|
||||
"cmd/object-api-options-replication_test.go": "1ea2a060987e32a4c76fce96ee974df475944c2d6ab482a4893e33daf7bca849",
|
||||
"cmd/object-copy-replication-tagging_test.go": "5437a77e68736b4ce69de9c777675251fef24b0352dfe30bd8a836fc7ee810e3"
|
||||
},
|
||||
"log_sha256": "e92606b0bf483111dff0a120c315ea165821348f31365020e2468a0059095c47",
|
||||
"assessment": "PASS"
|
||||
}
|
||||
],
|
||||
"format_checks": [
|
||||
{
|
||||
"command": [
|
||||
"gofmt",
|
||||
"-l",
|
||||
"cmd/object-api-options.go",
|
||||
"cmd/object-api-options-replication_test.go",
|
||||
"cmd/object-copy-replication-tagging_test.go"
|
||||
],
|
||||
"exit_code": 0,
|
||||
"output": ""
|
||||
},
|
||||
{
|
||||
"command": [
|
||||
"git",
|
||||
"diff",
|
||||
"--check"
|
||||
],
|
||||
"exit_code": 0,
|
||||
"output": ""
|
||||
}
|
||||
],
|
||||
"evidence_directory": "/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb",
|
||||
"evidence_files": {
|
||||
"baseline-final-overlay.json": {
|
||||
"size": 177,
|
||||
"sha256": "f4cbc16e4ffccaf63191de2e8476162876055796adb4c38cda2d8c569a3bbabc"
|
||||
},
|
||||
"baseline-final.json": {
|
||||
"size": 1584,
|
||||
"sha256": "5bf7be51e5a0eb41a40dc5fc5d3a1aba5df7733ad5dcb001f8d870a01c4233ba"
|
||||
},
|
||||
"baseline-final.log": {
|
||||
"size": 22493,
|
||||
"sha256": "f849c2082235213764e3db7a314d52af75c4859102478a1e8f837afcaa8f1ea8"
|
||||
},
|
||||
"baseline-identity.txt": {
|
||||
"size": 1676,
|
||||
"sha256": "9b21841e19a0cbb8ded18c2597488a527a27bedc65109d05d4ff598103073b68"
|
||||
},
|
||||
"baseline-options.log": {
|
||||
"size": 11395,
|
||||
"sha256": "d692f0a4bc9c58e2ac0087afa356ddf48f86e1040ea8138d68ffc4d0992bf3cb"
|
||||
},
|
||||
"baseline-repro.log": {
|
||||
"size": 5693,
|
||||
"sha256": "aa89b76f4723c6a3ce224faa7796403628d978a8707544bd97848b8887de2113"
|
||||
},
|
||||
"capacity-fixture.diff": {
|
||||
"size": 870,
|
||||
"sha256": "8d01e0b0068441f37ecee37125b81424d1f30d7c4fb37d435ea0cfe2e4617e5e"
|
||||
},
|
||||
"capacity-overlay.json": {
|
||||
"size": 185,
|
||||
"sha256": "76a7e6fb364bdaaa3469b1dc79f9ea318059f287a4888f322639920c76dfe53a"
|
||||
},
|
||||
"final_copy_repro_test.go": {
|
||||
"size": 5942,
|
||||
"sha256": "8949e07d96d2949a79f5a9e83c7a7c0473733d77b407e9c51da477d4ab74f1a8"
|
||||
},
|
||||
"focused-capacity-adapted.json": {
|
||||
"size": 1661,
|
||||
"sha256": "1a599b41caabfc5eb44db8d89c8b7e4f4f84f5f036d008369155fd337f65bdf9"
|
||||
},
|
||||
"focused-capacity-adapted.log": {
|
||||
"size": 20384,
|
||||
"sha256": "13f7aa54564a433bef4dddcf2c5ad1fe46fa03869527fb902a255ce4c3263bc9"
|
||||
},
|
||||
"focused.json": {
|
||||
"size": 1253,
|
||||
"sha256": "d9bb4979ea8aeaabb809cdc6e400a8673530bc83abf3dc2b2a06853a8523d0d9"
|
||||
},
|
||||
"focused.log": {
|
||||
"size": 20475,
|
||||
"sha256": "9a64cbc46e9fd6186b1d3031034b720857851ce70b1466b1da5da6d1a52b76ba"
|
||||
},
|
||||
"format-checks.json": {
|
||||
"size": 352,
|
||||
"sha256": "7569260900a799d5efdfb39db1f575ab1dadbbb04ace222e036968e66b6b59e7"
|
||||
},
|
||||
"lint.json": {
|
||||
"size": 991,
|
||||
"sha256": "a7144713b069f470a94b1ebe6fca6683a4b866a891a2756e15f28c280666ca14"
|
||||
},
|
||||
"lint.log": {
|
||||
"size": 10,
|
||||
"sha256": "e92606b0bf483111dff0a120c315ea165821348f31365020e2468a0059095c47"
|
||||
},
|
||||
"object-api-options.baseline.go": {
|
||||
"size": 16653,
|
||||
"sha256": "16a560d0990ae929393f682f22b32ecd2e7f4d9390484b03b54e176fcd00cff5"
|
||||
},
|
||||
"options-overlay.json": {
|
||||
"size": 185,
|
||||
"sha256": "5506b9c3b998b32f01c45af3cf01605eae9e4fb262c9ff3a6b0040abe719d4d9"
|
||||
},
|
||||
"options_repro_test.go": {
|
||||
"size": 4192,
|
||||
"sha256": "1a57a47bdd370042fa0f0d2d90efe447abedee9b9ef48a938d4bed631d83ec0b"
|
||||
},
|
||||
"opus-review-v1.exit": {
|
||||
"size": 2,
|
||||
"sha256": "9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa"
|
||||
},
|
||||
"opus-review-v1.jsonl": {
|
||||
"size": 410466,
|
||||
"sha256": "eb0918d8a6185b180dddcfc664a96682f05502ecf3b686b08a0547f09879d57d"
|
||||
},
|
||||
"opus-review-v1.stderr.log": {
|
||||
"size": 0,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"overlay.json": {
|
||||
"size": 158,
|
||||
"sha256": "95f7c3f7e206fe36731e6d7e4a48f90c7403f07ae8155c125c6b86d2f1c2d487"
|
||||
},
|
||||
"r4-kms-tag-timestamp.patch": {
|
||||
"size": 874,
|
||||
"sha256": "2d4806d986bbd94ba4bc3951f3aeee48401ee1921c28ded0988fa09ca76ca26f"
|
||||
},
|
||||
"r4_repro_test.go": {
|
||||
"size": 5508,
|
||||
"sha256": "9bcefb6da2416b577b58085485cad60f677c2265e9dfa84d02e465e1b203766b"
|
||||
},
|
||||
"race.json": {
|
||||
"size": 1026,
|
||||
"sha256": "50b73e4acbc2426f3dcfadde78d0f0a86f10702345d2939a30204600bc750a13"
|
||||
},
|
||||
"race.log": {
|
||||
"size": 18566,
|
||||
"sha256": "ae66a8c9e569a5c4b57ae56e75afc85c06a8b76f1567187519da0726605a4de4"
|
||||
},
|
||||
"replication-trust-capacity_test.go": {
|
||||
"size": 61271,
|
||||
"sha256": "c81b526ae51983881bbf464199e6b90f074fa695300fa8ff005e427e4d3c8208"
|
||||
},
|
||||
"review-prompt-v1.md": {
|
||||
"size": 2770,
|
||||
"sha256": "07c225beff1523e056c154b3a387cf1ae345def4b4d0173065b882140ac5abdf"
|
||||
},
|
||||
"run-checks.py": {
|
||||
"size": 2266,
|
||||
"sha256": "ddecea5220bc9c286df18c0e9eca101f3d8ab731c307cd4acef937f3ecd11e65"
|
||||
},
|
||||
"vet.json": {
|
||||
"size": 853,
|
||||
"sha256": "e0964444bc91640ed6cf78229050bad5b94af4210bdf44b11d1a848f1ee930a6"
|
||||
},
|
||||
"vet.log": {
|
||||
"size": 0,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
}
|
||||
},
|
||||
"scope": "Darwin arm64; real signed HTTP + disk I/O; KMS service stub; single-pool single/16-disk fixtures; no remote CI, multi-site, release or deployment."
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
# R4 修复与本地验收
|
||||
|
||||
这是 2026-09-15 的本地验收快照。用户后续授权的实现级复核、提交规范调整与合并流程见 [合并前复核](merge-verification.md);以下原始测试记录及哈希保留当时状态。
|
||||
|
||||
## 结果
|
||||
|
||||
在 `putOptsFromHeaders` 的 SSE-KMS 选项构造中补齐 `ReplicationSourceTaggingTimestamp`。目的端使用显式 SSE-KMS、桶默认 KMS 或自动加密时,可信复制 COPY 现在能消费来源标签时间戳,并在现有存储锁内完成排序。
|
||||
|
||||
生产修改只有一个字段和相邻注释。API、存储格式、KMS key/context、信任判断和既有排序规则保持兼容。R5 的删除/空标签及 PUT/multipart 时间戳传播独立交付。
|
||||
|
||||
## 方案与 Opus 共识
|
||||
|
||||
- 基线:`9ebe81c1b3611f9cc73e676b5b741c2be62c467a`,已重新查询 GitHub main。
|
||||
- 分支:`codex/r4-kms-tag-timestamp`。
|
||||
- [冻结方案 v1](plan-v1.md):SHA-256 `ad539f2071155de6955b583991684ed33c4bfe2e29660005840cdc97d7e1a754`。
|
||||
- 真实评审为本机 Claude Code 2.1.270,实际 assistant 模型 `claude-opus-5`,显式 `--effort max`。结论 **GO_WITH_NONBLOCKING_NOTES,0 个阻断项**。
|
||||
- [逐条意见处置与双方共识](consensus.md)、[原始返回评审正文](opus-v1-review.md)、[模型与哈希记录](opus-v1.metadata.json) 已保存。先保存共识,再修改生产源码。
|
||||
|
||||
## 变更与测试
|
||||
|
||||
| 文件 | 内容 |
|
||||
|---|---|
|
||||
| `cmd/object-api-options.go` | 在 KMS 字面量中保留已解析的来源标签时间戳。 |
|
||||
| `cmd/object-api-options-replication_test.go` | 无加密、SSE-S3、SSE-KMS、带 key/context 的 KMS、SSE-C;可信/非可信;缺失、有效、无效标签时间;纳秒、时区与空格;mtime/ETag/三个时间戳、metadata 与 SSE 序列化。 |
|
||||
| `cmd/object-copy-replication-tagging_test.go` | 两种单池后端 × 五种目的端加密模式 × 五个有序事件,共 50 次签名 COPY 和 50 次普通 GET。每步检查最终标签、精确时间戳、对象版本、加密类型及明文内容。 |
|
||||
|
||||
COPY 使用 `metadata=REPLACE`、`tagging=REPLACE` 和可信复制身份。事件为较新更新、乱序旧更新、重复事件、再次更新,以及不带来源标签时间戳的请求。更新间隔仅 1–3 纳秒,防止时间精度退化被秒级测试掩盖。无加密与 AES256 是对照;KMS 覆盖显式、桶默认和自动加密入口。
|
||||
|
||||
## 验证状态
|
||||
|
||||
| 检查 | 结果 | 证据文件 |
|
||||
|---|---|---|
|
||||
| 最终测试 + 未修复基线 constructor overlay | 预期失败;只有可信 KMS 有效标签时间戳及 KMS COPY 更新失败,对照通过 | `baseline-final.log/json` |
|
||||
| 修复后最终新增测试与既有 trust/options 测试 | 通过;未使用生产源码 overlay | `focused.log` |
|
||||
| 既有 KMS Object Lock 回归 | 首次受宿主机磁盘余量阈值阻挡;仅适配测试容量报告后,与上述定向测试一起通过 | `focused-capacity-adapted.log/json`、`capacity-fixture.diff` |
|
||||
| 新增测试 `-race` | 通过 | `race.log/json` |
|
||||
| `go vet -p 2 ./cmd` | 通过 | `vet.log/json` |
|
||||
| 仓库配置的 golangci-lint,范围 `./cmd/...`、`kqueue` build tag | 通过,0 issues | `lint.log/json` |
|
||||
| gofmt、git diff --check | 通过 | `format-checks.json` |
|
||||
|
||||
原始日志和每条命令的运行记录位于 `/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/`。每份检查 JSON 都记录命令、退出码、时间和三个源码/测试文件的 SHA-256;最终交付已逐一确认文件哈希一致。[验证清单](verification.json) 另记录 overlay 的实际替换文件哈希,避免混淆基线与修复版执行代码。
|
||||
|
||||
测试使用真实签名 HTTP 路由、实际本地对象数据/元数据读写、服务器加解密代码;远程密钥服务由 `kms.NewStub` 代替。ErasureSD 与 16 盘 Erasure 均为单池。容量适配只使用已有 `tagTestCapacityDisk`,避免本机磁盘使用比例触发防写阈值,所有对象 I/O 仍由真实测试磁盘承担;未调整生产容量保护。
|
||||
|
||||
## 交付与剩余边界
|
||||
|
||||
- 本地实现和要求的定向验证均已完成,将源码、回归、研究、共识和验收记录作为一个本地提交交付。
|
||||
- R4 的独立生产补丁已提供给 R5:`/Users/vonng/tmp/silo-r4-evidence-20260915-a9cb/r4-kms-tag-timestamp.patch`,SHA-256 `2d4806d986bbd94ba4bc3951f3aeee48401ee1921c28ded0988fa09ca76ca26f`。
|
||||
- Opus 共识为方案级共识;本地测试结论来自实际运行,不把它记作 Opus 执行了测试。
|
||||
- 多池/多站点故障恢复、外部 KMS 服务、完整 Linux CI、主干合并、远端发布和部署尚未执行。
|
||||
- 没有改写存量。丢失的来源时间戳不能仅从接收端推导;后续重放/重同步须核对来源权威性及 R5 的全链路处理,不保证旧事件重放可以修复全部历史状态。
|
||||
- 另登记 KMS 字面量缺少 Proxy/Speedtest 标志的范围外观察,已交父任务单独核验,本次未扩大修复。
|
||||
Reference in New Issue
Block a user