[h1-request] 同期v2: 合議(伝票の競合解決)と訂正提案 #55
Labels
No labels
h1-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
joe/o2#55
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景
v1 は競合を LWW で自動決着し、修正はフィールド単位で確定伝票を上書きする。伝票の競合は人が判断する(合議)、確定(発行ロック)済み伝票の訂正は赤黒のみ、と決定した。
依頼内容(ADR-0002 §7・§5 の行き違い規則)
SyncConflict(tenant, entity_type, uuid, base_rev, candidates[], status)POST /api/sync/v2/conflicts/{id}/resolve(take_local|take_remote|edited+バンドル)。先に解決した側が有効、後着はalready_resolvedconflict_opened/conflict_resolved(採用版+新 rev)correction_proposalとして h1 へ配信(h1 は承認時に赤黒伝票を発行。フィールド上書きはしない)受け入れ条件
already_resolved)のテストと fixture契約の正本: ADR-0002(ブランチ
docs/adr-0002-offline-first-sync-v2。未マージなら先に main へマージしてから着手)https://git.cyberius.biz/joe/o2/src/branch/docs/adr-0002-offline-first-sync-v2/docs/adr/0002-offline-first-sync-v2.md
h1 側の内部設計(参考): https://git.cyberius.biz/joe/h1-c2/src/branch/main/docs/superpowers/specs/2026-10-09-offline-first-sync-design.md
前提: h1 は本体単体で完全稼働し、o2 接続時のみ同期する。v1(
/api/sync/push|pull・/api/sync/corrections*)は h1 の移行完了まで並行稼働を維持すること(v1 を壊さない)。検証データ: 入出力例を
tests/fixtures/sync_v2/*.jsonに追加する。h1 は同じ fixture を Dart テストで検証する(sales_calculationfixture と同じ運用)。実装完了(o2側)— 合議(伝票の競合解決)と訂正提案
実装
SyncConflictに解決列(resolution/resolved_rev/resolved_by_device_id)POST /api/sync/v2/conflicts/{id}/resolve(take_local/take_remote/edited、先着有効・既解決はalready_resolved)。採用版を新 rev で確定conflict_opened、解決でconflict_resolvedをSyncV2Eventに積み pull 配信false→true)を拒否base_revで届いたらロック版を accepted とし、ロック前の o2 編集をcorrection_proposalとして h1 へ配信(フィールド上書きしない/赤黒前提)/sync-conflicts(競合一覧・差分表示・解決)f7a8b9c0d1e2、fixtures(conflict_resolve / correction_proposal)インフラ注意: 現在リモートへの git push が SSH タイムアウト(
www.cyberius.biz:18)で失敗中。実装はローカル main にマージ済み・o2.db適用済みで、push は回復後に実施します。回帰確認: 全 6422 passed, 1 skipped。