ストレージ
一言でいうと
storage は「テナントのドキュメントがどこに実体として存在するか」を表す StorageDevice(+ その配下の複数ルート StorageDeviceRoot)を管理するモジュール。LOCAL(ユーザーのPC・Tauriデスクトップアプリ経由)と NETWORK_DRIVE(事務所のNAS・Go agent 経由)はどちらも agent-based(WebSocket 常時接続)で、"あるメンバーのローカルにしかない" という状態は存在しない — オンラインなデバイス上のファイルは接続中の全メンバーに配信される。実際のファイル同期処理そのものは sync モジュールが担当し、storage はデバイスのライフサイクル(登録・接続状態・ルート構成)を管理する。
主要ドメイン概念
| 概念 | 役割 |
|---|---|
StorageDevice | 1台の物理/仮想ストレージ拠点。type(LOCAL / NETWORK_DRIVE)と connectionMode(AGENT / CLI)を持つ |
StorageDeviceRoot | デバイス内の名前付きサブツリー(マルチルート)。rootKey == "" は multi-root 導入前からの legacy root で / に固定マウントされる |
ConnectionMode | AGENT(astar-agent 常駐・WebSocket 常時接続・ファイル同期あり)/ CLI(本人PCの astar CLI・トークン疎通のみでファイル同期なし) |
StorageMode(workspace モジュール側) | ワークスペースがどのストレージを使うか。CLOUD(既定)/ LOCAL / NETWORK_DRIVE / EXTERNAL_CLOUD の4種、詳細は ワークスペース |
| WebDAV 資格情報 | core/webdav が発行するネットワークドライブマウント用の認証情報。UI は storage モジュールに同居 |
Backend 構造
core/storage/ は規約どおりの3層構造。
api/controller/:StorageController(GET /local-path— DocumentNode をエージェントホストの絶対パスへ解決し、Tauri opener やms-word:ofe|u|...URI でネイティブアプリを起動する)、StorageDeviceController(デバイス CRUD、ルート CRUD、接続トークン発行・再発行、登録コード発行、Codex device-auth フロー、SSE ストリーム)domain/service/:StorageDeviceService(デバイス作成・接続状態記録・ハートビート・ルート追加/削除・トークン検証・削除)、LocalPathResolutionService(上記 local-path 解決。CLOUD モードのワークスペースは 503 で拒否し、呼び出し元に in-app 編集へのフォールバックを促す)domain/model/:StorageDevice・StorageDeviceRoot・StorageDeviceType・ConnectionMode・AgentUpdateStatus・LocalPathResolutiondomain/event/:StorageDeviceConnectedEvent(エージェントが WebSocket 認証されオンラインになった時に発火。AFTER_COMMITで消費され、デバイスオフライン中に失敗した処理をオンライン復帰時にリトライさせる)、StorageDeviceDeletedEventinfrastructure/adapter/:StorageTenantResolutionAdapter
Frontend 構造
app/modules/storage/ は規約の4分類に加えて stores・utils を持つ。
components/:StorageDeviceList.vue(デバイス一覧・選択の共通UI)、StorageDeviceListPanel.vue、StorageDeviceForm.vue/StorageDeviceEditDialog.vue、StorageDeviceRootsEditor.vue/StorageDeviceRootRow.vue(マルチルート編集)、StorageDeviceReconnectDialog.vue、NasFolderPickerField.vue、MountDriveLetterDialog.vue、WinFspGuidanceDialog.vue、WorkspaceMountCard.vue/WorkspaceMountCardBody.vue、AgentSidecarBadge.vue、StorageUsageSummary.vuecomposables/:useStorageDevices(デバイス一覧取得)、useStorageStats、useCodexDeviceAuth、useWinFspCheck(Windows の WinFsp 前提条件チェック)、useWorkspaceAutoReconnect/useWorkspaceMountPreferences、useStableOfflineDevices、useNasTreePickerDataLoaderrepositories/:StorageDeviceRepository、WebDavCredentialRepository(WebDAV 資格情報の発行・一覧・失効)
WebDAV (core/webdav)
core/webdav はテナントのドキュメントツリーを WebDAV サーバーとして公開するバックエンド専用モジュール(frontend モジュールは持たず、UI は storage に同居)。api/servlet/WebDavServlet が実際の WebDAV プロトコル(PROPFIND/PUT/LOCK 等)を処理し、api/controller/WebDavCredentialController が資格情報の発行/一覧/失効 API を提供する。frontend 側は WebDavCredentialRepository 経由で MountDriveLetterDialog.vue などから呼び出す。
他モジュールとの辺
sync:storageはデバイスの存在・接続状態・ルート構成を管理し、実際のファイルスキャン・同期はsync(+core/agentの WebSocket ハンドラ)が行う。デバイス追加 UI(DeviceConnectDialog.vue)はsyncモジュール側にあり、デバイス選択・一覧 UI(StorageDeviceList.vue)はstorage側にあるworkspace:WorkspaceStorageLinkedEventを受けてワークスペースが agent-based デバイスに紐づいた際に再スキャンを起動するeditor:LocalPathResolutionServiceはDocumentNodeRepositoryを使い、ノードのローカルファイルパスを解決するagent: WebSocket 接続そのもの(AgentWebSocketHandler等)はcore/agentが持ち、storageはその上のデバイスレコードを管理する
共通デバイス選択 UI は2つのモジュールに分かれている(自作禁止)— 選択・一覧は storage モジュールの StorageDeviceList.vue、新規追加は sync モジュールの DeviceConnectDialog.vue。デバイス関連 UI を新設するときにどちらか一方だけを見て「同種コンポーネントがない」と誤判定しやすいので、両モジュールを横断して確認すること。