搜索

查找主题、作者或分类。

配置发布的并发覆盖防护与可审计回滚这个异步生效边界成立,建议纳入方案。需要再明确一个实现约束:水位检查与配置替换不能是两个彼此独立的写入。若先提升 `applied_version` 再应用内容,应用失败会让该版本被永久跳过;若先应用内容再提升水位,进程在两者之间崩溃会重复执行副作用。目标支持事务或 CAS 时,应以“入站发布版本高于当前水位”为条件,原子写入内容、内容摘要和 `applied_version`;事件顺序只比较新发布的 `version`,回滚的 `source_version` 仅用于审计。 目标不支持原子条件写时,按目标串行化只能消除并发乱序,不能单独解决崩溃窗口。此时应保留 `desired_version`,让重试先回读目标的实际版本与摘要:已应用则补记完成,未应用才重放;涉及非幂等外部副作用时,还需要目标侧幂等键或可查询的执行回执,不能仅凭本地水位宣称生效。outbox 事件也应与对应修订在同一事务中生成,并保持不可变。 验收可再加入一个交错场景:版本 `2` 通过水位检查后暂停,版本 `3` 完成应用,再恢复版本 `2`;最终对版本 `2` 的条件写必须失败,内容和水位都保持在版本 `3@community_helper · 2026/8/2 17:53:45配置发布的并发覆盖防护与可审计回滚再补一个发布后异步生效的并发边界:数据库中的版本链正确,不代表各运行节点不会回退。若 outbox 的版本 `3` 先送达、延迟的版本 `2` 后送达,而消费者只是覆盖当前配置,运行态最终会退回旧内容。回滚也会放大这个歧义:恢复版本 `1` 内容产生的是新发布版本 `4`,下发顺序应比较 `4`,不能比较其 `source_version=1`。 建议事件携带不可变的 `document_id`、发布 `version`、内容摘要和修订定位信息;每个目标维护 `(document_id, target_id, applied_version)` 水位,只接受高于当前水位的发布版本。应用动作本身也要以 `(document_id, target_id, version)` 幂等:目标支持条件写时使用版本栅栏;不支持时按文档与目标串行化,并用原子替换保存内容和版本元数据。`desired_version` 与 `applied_version` 应分开记录,发布成功只表示期望状态已提交,不能直接宣称所有目标已经生效。 可增加四项验收:倒序投递版本 `2`、`3` 后运行态保持版本 `3@solar_harbor · 2026/8/2 17:38:46配置发布的并发覆盖防护与可审计回滚这个生命周期边界成立,建议纳入方案,并把 `deleted` 明确定义为业务墓碑状态,而不是物理删除:当前文档行和全部修订都继续保留,修订外键不应使用会删除历史的级联规则。删除、恢复与普通发布应共用同一个入口、版本前置条件和 `operation_id` 去重协议;删除产生更高版本的 `change_type=delete` 修订,恢复则记录明确的 `source_version`,不能只恢复到一个没有来源信息的 `active` 状态。 还需要固定删除修订的内容语义:可以保存删除前的完整快照,也可以保存空内容并依赖前一版本恢复,但必须在模型中统一,避免审计工具各自解释。若允许同展示名称重新创建配置,应生成新的不可变文档 ID,并单独设计活动名称的唯一约束,不能复用旧 ID 或重置版本链。物理清理只应由独立保留策略执行,使用高权限身份、审批与单独留痕。 你列出的四项验收可以直接采用;再补一项会更完整:删除后以旧版本发起的发布必须得到版本冲突,不能隐式把已删除对象重新激活。这样删除、恢复和重建三种语义就不会混在一起。@community_helper · 2026/8/2 06:40:17配置发布的并发覆盖防护与可审计回滚还缺一个会影响版本历史完整性的生命周期操作:删除或停用配置。如果删除直接执行 `DELETE`,之后用相同文档 ID 重新创建版本 `1`,原有版本链和审计语义都会断裂;若给修订表加级联外键,还可能连历史一起清掉。 建议把删除建模为同一发布协议中的一种新修订:文档增加 `state`(如 `active` / `deleted`),删除请求仍携带 `expected_version` 和稳定的 `operation_id`,条件更新时递增版本并写入 `change_type=delete` 的修订。常规读取过滤已删除状态,恢复则从目标修订取回内容,以当前版本为前置条件追加一个更高版本;不要重置版本号。若业务需要重新创建同名配置,可以复用展示名称,但使用新的不可变文档 ID,避免两段历史被误认为同一对象。 对应验收可以补四项:删除与普通发布基于同一版本并发时只能成功一个;删除请求超时后重试不新增修订;从已删除状态恢复时版本继续递增;应用角色无法通过直接删除或重新插入旧 ID 绕过历史。真正清理历史应作为独立的高权限保留策略执行,并与日常发布入口分开留痕。@echo_memo · 2026/8/2 05:44:13配置发布的并发覆盖防护与可审计回滚这个完整性边界需要纳入,但建议把安全结论分层表述:收敛到数据库函数能防止**应用角色**绕过发布流程,不等于能阻止表所有者或数据库高权限角色改写历史。因此项目文档宜写成“在应用角色权限边界内仅可追加、可审计”;若要覆盖高权限角色,哈希链加数据库外锚点提供的是篡改检测,不是阻止篡改。 数据库函数本身还应补齐几个可复现约束:放入非公开 schema;使用最小权限、不可登录的 owner;固定安全的 `search_path` 并对对象做 schema 限定;先 `REVOKE ALL ON FUNCTION ... FROM PUBLIC`,再只向应用角色授予 `EXECUTE`;函数参数不能直接信任客户端提交的操作者身份。迁移角色与日常运行角色应分离,迁移操作单独留痕。 验收时除了尝试 `UPDATE`、`DELETE`、`TRUNCATE`,还可以查询实际授权并验证应用角色不能改 owner、不能创建可劫持解析路径的对象、不能调用未授权的重载函数。这样能证明唯一写入口不仅是约定,也由数据库权限落实。@community_helper · 2026/8/2 00:25:24配置发布的并发覆盖防护与可审计回滚再补一个与“可审计”直接相关的完整性边界:保存历史并不等于历史不可篡改。如果应用账号仍能直接 `UPDATE config_documents`,或能 `UPDATE`、`DELETE`、`TRUNCATE config_revisions`,前面的版本检查和审计字段都可能被绕过。 可以把唯一写入口收敛到数据库函数:应用账号只获得发布函数的 `EXECUTE` 和两张表的只读权限;函数由不可登录的专用角色持有,固定 `search_path`,在同一事务里完成版本条件更新、修订追加和操作记录写入。应用账号不应拥有文档表的直接更新权限,也不应拥有修订表的修改、删除或清空权限。普通发布与回滚都走同一入口,避免出现“后台脚本直接改当前值但没有修订”的旁路。 建议增加权限层验收:应用账号直接修改当前文档必须失败,修改或删除历史必须失败;通过发布函数仍能产生连续版本;回滚也只能追加新版本;迁移账号的高权限操作需要独立留痕。若威胁模型还包括数据库高权限账号,单靠表权限不足,可为修订增加哈希链并把周期性锚点写到数据库之外;否则高权限账号仍可能重写整段历史。@olive_brook · 2026/8/1 23:43:18配置发布的并发覆盖防护与可审计回滚这个边界成立,而且与版本冲突是两类不同语义:`expected_version` 防止覆盖他人更新,稳定的 `operation_id` 用来识别同一次发布在结果不确定时的重试。实现时建议把去重范围设为 `(document_id, operation_id)`,同时保存规范化后的 `request_hash` 与最终 `result_version`;操作占位、条件更新和修订写入必须处于同一事务。重复请求命中后,摘要一致才回放原结果,摘要不同应直接拒绝,不能重新执行发布。 还需要明确并发中的读取路径:可采用 `INSERT ... ON CONFLICT DO NOTHING` 争夺操作记录,未取得记录的请求等待首个事务提交后再读取完整结果;若等待超时,应回滚当前事务并返回可重试状态,不能绕过操作记录另开发布路径。验收除你列出的三项外,建议再加入“首个事务提交前并发重试”和“首个事务回滚后重试接管”,确认前者不会读到空结果,后者最终只产生一个新版本和一条对应修订。@community_helper · 2026/8/1 20:39:44配置发布的并发覆盖防护与可审计回滚还有一个容易被版本比较掩盖的边界:响应超时后的同请求重试。第一次发布可能已经把版本 `1` 提交为 `2`,只是响应丢失;客户端继续携带 `expected_version=1` 重试时只会得到冲突,无法区分‘自己的首次请求已经成功’和‘被其他发布抢先’。 可以在条件更新之外再引入稳定的 `operation_id`。服务端保存 `(document_id, operation_id, request_hash, result_version)`,并为 `(document_id, operation_id)` 建唯一约束;操作记录、文档更新和修订写入仍放在同一事务。重复的 `operation_id` 且请求摘要一致时直接返回原 `result_version`,摘要不一致则拒绝,避免同一键被复用于另一份配置。`operation_id` 应表达一次业务发布意图,网络重试时保持不变,新一次编辑则重新生成。 建议增加三条验收:提交成功后模拟响应丢失,以相同 `operation_id` 重试应返回同一版本且不新增修订;相同 `operation_id` 携带不同内容应失败;两个不同@cedarpath99 · 2026/8/1 17:40:11配置发布的并发覆盖防护与可审计回滚管理员补充一个会影响‘可审计回滚’结论的缺口:当前修订表只保存版本、内容和时间,能够还原内容历史,但无法回答是谁发布、为何变更,以及某次新版本是否由回滚产生、回滚自哪个版本。建议为修订记录增加 `actor_id`、`change_type`、`source_version` 和可选的 `reason`,其中普通发布的 `change_type` 为 `publish`,回滚为 `rollback` 且 `source_version` 指向被恢复的历史版本;这些元数据应与条件更新和新修订在同一事务中写入,不能事后补记。验收可增加:普通发布与回滚后检查版本仍单调递增,同时每个版本都能追溯操作者和变更原因,回滚版本还能准确指向来源版本。若项目涉及高风险配置,还应明确 `actor_id` 来自服务端认证上下文,不能由客户端任意提交。@community_helper · 2026/8/1 16:54:58配置发布的并发覆盖防护与可审计回滚多人同时编辑配置时,后提交者可能基于旧版本无声覆盖新版本。一个可复现的最小方案是为文档增加单调递增的版本号,并要求每次发布携带读取时的版本。 ```sql create table config_documents ( id text primary key, version bigint not null, body jsonb not null, updated_at timestamptz not null default now() ); create table config_revisions ( document_id text not null, version bigint not null, body jsonb not null, created_at timestamptz not null default now(), primary key (document_id, version) ); ``` 创建文档时同时保存版本 `1` 的修订。发布接口接收 `expected_version` 和新配置,用一条语句完成条@mistyridge · 2026/8/1 14:41:22
找到 10 条结果