WebDAV Sync
概要
WebDAV Sync は、Synthesis Workbench のクロスデバイス同期メカニズムであり、非推奨となった Git Sync を置き換えるものである。WebDAV プロトコルを介して決定的な耐久状態バンドルスナップショットを交換する。
WebDAV 準拠のサーバー(Nextcloud、ownCloud、Synology など)で動作する。Git は不要。
前提条件
- アクセス可能な WebDAV サーバー
- WebDAV 認証情報(ユーザー名 + パスワード、またはアプリケーション固有トークン)
設定
Zotero → 設定 → Zotero Agents → WebDAV Sync
| 設定 | 型 | デフォルト | 説明 |
|---|---|---|---|
| WebDAV Sync を有効化 | boolean | false | マスタースイッチ |
| ベース URL | string | "" | WebDAV サーバー URL(例:https://nextcloud.example.com/remote.php/dav/files/user/) |
| リモートパス | string | "zotero-agents" | ベース URL 配下のリモートディレクトリ |
| ユーザー名 | string | "" | WebDAV ユーザー名(オプション) |
| パスワード / アプリケーショントークン | 暗号化 | "" | パスワードまたはトークン(AES-256-GCM 暗号化) |
| 自動同期 | boolean | false | Synthesis 変更後に自動的に同期をトリガー |
| 自動リトライ | boolean | false | 一時的な失敗を自動的にリトライ |
アクションボタン:
- 設定を保存: 認証情報以外の設定を保存
- 認証情報を保存: パスワード/トークンを暗号化して保存
- 接続テスト: PROPFIND リクエストを送信して接続を確認
リモートファイル構成
<remotePath>/
├── HEAD.json # 現在のスナップショットポインタ
└── snapshots/
└── <snapshotId>/
├── manifest.json # 耐久バンドルマニフェスト
└── bundles/ # 決定的耐久バンドルファイル
HEAD.json には snapshot_id、manifest_hash、updated_at、producer_version が含まれる。スナップショットは HEAD が更新される前に完全にアップロードされる。同期が中断されてもリモートが破損することはない。
同期対象
| 同期されるもの | 同期されないもの |
|---|---|
| トピック | SQLite ランタイムデータベース |
| 概念(概念、意味、別名、関係) | ランタイムログ |
| トピックグラフ(ノード、エッジ) | ワークスペースファイル |
| 参考文献(バインディング、リダイレクト) | キューとロック状態 |
| レビューアイテム | 再構築可能なプロジェクション(引用レイアウト、メトリクス、キャッシュ) |
| タグ(統制語彙) | 認証情報 |
| 関連アイテム | 一時ファイル |
同期フロー
idle → queued → syncing → idle
├── blocked_conflict(手動解決が必要)
└── failed_retryable / failed_permanent
| ステップ | 説明 |
|---|---|
| 1. HEAD | リモートの HEAD.json を読み取り |
| 2. ダウンロード | 新しいスナップショットが存在する場合、マニフェスト + バンドルをダウンロード |
| 3. プレビュー | インポートするスナップショットを検証し、エンティティハッシュを比較 |
| 4. 競合チェック | 両者の変更を検出 |
| 5. 適用 | リモートスナップショットをローカルの Canonical Store にインポート |
| 6. エクスポート | 現在のローカル状態をバンドルとしてエクスポート |
| 7. アップロード | マニフェスト + バンドルをアップロード |
| 8. HEAD 更新 | 最後に HEAD.json を更新(ETag/If-Match による並行性安全性) |
競合処理
競合検出はエンティティレベルのハッシュ比較に基づく。同じエンティティがローカルとリモートの両方で変更された場合に競合が発生する。
競合タイプ:
- 両者によるエンティティの変更
- 更新と削除(tombstone)の競合
- レビューアイテムの分岐
- 参考文献バインディング/リダイレクトターゲットの分岐
解決アクション:
| アクション | 説明 |
|---|---|
keep_local | ローカル状態を保持し、競合ゲートを閉じ、次のエクスポートをキューイング |
clear_after_manual_edit | 手動マージ後に再検証。解決時に競合マーカーをクリア |
Workbench の Home ページの同期パネルに、競合の詳細とアクションボタンが表示される。
セキュリティ
- 認証情報の暗号化: AES-256-GCM、Host Bridge マスタートークンに基づく鍵生成(PBKDF2-SHA256、100,000 イテレーション)
- プレーンテキストの非返却: 認証情報は保存後に読み取り不可
- URL サニタイズ: 認証情報はログ出力から除外される
- HTTP Basic 認証: HTTPS 経由の標準的な Basic 認証
制約事項
| 制約 | 詳細 |
|---|---|
| デフォルトで手動 | 自動同期と自動リトライはデフォルトでオフ |
| 圧縮なし | v1 スナップショットは生の JSON バンドル |
| 旧スナップショットの自動クリーンアップなし | リモートスナップショットが蓄積される。手動クリーンアップが必要 |
| フィールドレベルのマージなし | 競合はエンティティレベル |
| 単一デバイスを前提 | 複数デバイスからの同時書き込みは競合を引き起こす可能性がある |
次のステップ
- Home ダッシュボード — 同期状態を確認
- 環境設定 — WebDAV 同期を設定
- Git Sync(非推奨) — 過去の情報