Files
NotesAgentic/docs/contracts/Sync-v1契约.md
T

6.0 KiB
Raw Blame History

Sync Protocol v1

状态:服务端协议原型已实现,生产运维与桌面客户端尚未验收。入口为 server sync/sync_server;运行时 /openapi.json 是字段约束来源。不能将 SQLite Fixture 结果称为 PostgreSQL / MinIO 验收。

Rust 上传客户端增量

Workspace schema 3 新增持久绑定、上传作业与远端 heads。首次向已验证为空的远端绑定后,队列保留每次本地操作;大正文转入按摘要命名的 spool,清除已物化 outbox 的正文副本。提交基线来自远端确认值,首次发送时冻结,超时重试不得重算。确认响应逐字段核对后,heads、作业与 outbox 同事务更新。解绑封存旧绑定与队列,重新绑定从当前文件快照生成新操作,旧回调不能修改新绑定。

Rust HTTP 客户端已实现握手、登录、空远端复核、1 MiB 分块上传、查询 offset 续传、complete 和 Revision 提交。默认 HTTPS,测试 HTTP 必须显式启用;不跟随重定向,令牌不进入 URL,响应有大小限制。真实本地 HTTP Fixture 已验证 20 次编辑形成 20 个正确远端基线、同一提交重复 100 次无重复 revision。此 Fixture 使用 SQLite/磁盘对象,不替代生产 PostgreSQL/MinIO 验收。

此增量尚未开放桌面 Sync capabilityStronghold 会话接入、冲突解决与 UI、附件故障矩阵及数据分类仍在实施。

Workspace schema 4 增加持久 inbox、分页 boundary 和冲突记录,并为文件移动/删除日志记录 local/remote 来源。下载先验证长度与摘要,再登记 inbox;文件操作通过 Workspace journal 应用后才推进 cursor。进程在文件提交与 cursor 提交之间重启时使用操作回执去重。远端新增保留 file_id,远端移动/删除不回流 outbox。本机历史提交回放仅确认操作,不回退新编辑。本地待上传修改或摘要不符产生冲突,保存本地与远端内容引用后推进接收游标;同一文件保留最新待处理冲突,旧冲突记录仍保留。空本地库可以绑定已有远端并仅拉取。

真实本地 HTTP 集成已验证第二设备拉取 20 个历史 revision、稳定 file_id、零回流 outbox、本机旧历史不覆盖新编辑,以及离线同改时保留本地内容和远端冲突。重启边界测试验证文件提交前后 cursor 都不会提前推进。冲突解决事务、完整附件故障矩阵和真实双机 UI 验收尚未完成。

身份与数据边界

生产 CLI 只接受 postgresql+psycopg,账号通过 python -m sync_server create-user 交互初始化。无开放注册、默认密码或内置共享账号。设备由每次登录注册;Access Token 有效 900 秒,Refresh Token 30 天,数据库只保存摘要。刷新轮换使旧会话立即失效。注销删除当前会话;设备撤销使该设备所有会话与上传立即不可访问。社区与 Sync 身份完全独立。

普通读写须带 Authorization: Bearer …。访问对象也必须验证 Vault 所有者和设备;摘要不是访问凭证。服务器可见明文,不支持 E2EE、多人共享和 CRDT。

接口

所有业务接口位于 /sync/v1。错误为 {error:{code,details}};校验错误不回显输入。无正文与凭据访问日志。

方法与路径 行为
GET /handshake?protocol=1 限额、协议与保留策略;不兼容为 426
POST /auth/sessions username/password/device_name,登录失败限流
POST /auth/refresh refresh_token,轮换会话
DELETE /auth/sessions 注销
GET /devicesDELETE /devices/{id} 列出及撤销当前用户设备
POST、GET /vaults 创建、列出当前用户 Vault
POST /vaults/{id}/uploads content_hash/size,预留配额,一小时上传期
GET、PUT、DELETE /vaults/{id}/uploads/{upload} 查询 offset、按 offset 写入、取消
POST /vaults/{id}/uploads/{upload}/complete 长度和 SHA-256 复核,写入对象存储
POST /vaults/{id}/revisions 幂等提交与 CAS
GET /vaults/{id}/changes cursor/limit/boundary,一致分页边界
GET /vaults/{id}/history/{file_id} before/limit 倒序历史
GET /vaults/{id}/objects/{hash} 经鉴权读取与摘要复核

上传分块最大 1 MiB,对象最大 100 MiB。offset 冲突为 409 UPLOAD_OFFSET,响应给出已确认偏移;客户端查询偏移后续传。完成请求响应丢失时重新预申请同一摘要即可确认对象已存在。未完成上传不允许提交 Revision。

提交字段:operation_id、file_id、base_revision、path、operation (put/delete)、content_hash、size。device_id 从会话取得,客户端不能冒充。移动使用同一 file_id、新 path 及当前对象;恢复历史使用历史摘要、新 operation_id 和当前 base_revision,生成新 Revision。删除必须携带当前基线、空摘要和 size=0。

Vault 行锁内执行幂等键验证、CAS、路径检查、序列分配及历史和当前元数据写入。相同请求重试返回原结果;改变请求内容或设备重用同一幂等键为 409 IDEMPOTENCY_REUSED。基线不匹配返回 REVISION_CONFLICT 及当前 Revision,客户端必须保留本地内容并显示冲突。

路径须为 NFC,拒绝 Windows 保留名、控制符、穿越、反斜杠、绝对路径、尾随点/空格与 .ainote/.git。大小写折叠后检查同名及文件/目录前缀冲突。文件身份不由路径推导。

保留与未交付边界

当前历史和 tombstone 永久保留,游标不主动过期;不启用 GC,以免缺少恢复演练时删除历史对象。配额包含全部历史对象,未完成上传预留额度。通知尚未实现,客户端必须主动按 cursor 拉取。上传过期清理、对象 GC、限速指标、完整备份恢复工具与生产负载验收仍未交付。/ready 目前只检查数据库 schema,不证明 S3 就绪。

验证向量见 server sync/tests/test_protocol.py:双设备 CAS、幂等重放、移动与删除、历史恢复、稳定分页、隔离、撤销、刷新、配额、路径冲突、摘要与断点。