5.9 KiB
5.9 KiB
| title | state | created_at | updated_at | assignee | queued_by | queued_at |
|---|---|---|---|---|---|---|
| Persist local Workspace identity in .yoi/workspace.toml | closed | 2026-06-23T06:43:28Z | 2026-06-23T07:39:10Z | null | workspace-panel | 2026-06-23T06:47:18Z |
背景
Workspace server の local dev bootstrap は現在、workspace_id を local:{display} のように workspace root の basename から導出している。これは暫定 namespace としては分かりやすいが、DB の primary key / Workspace identity としては不適切である。
問題:
workspace_idが表示名 / path basename から予測可能に作られている。- 同じ basename の workspace が複数あると衝突しうる。
- workspace root の rename / move で identity が変わる。
local:namespace と display label が DB PK に混ざっている。--workspace .のような相対 path では display fallback に落ちるなど、初期化責務がServerConfig::local_devに寄りすぎている。
Workspace identity は .yoi/workspace.toml を local Workspace record として永続化し、未作成なら Workspace backend の初期化処理で払い出す。これにより、DB を再作成しても Workspace identity は維持され、将来の DB authority / hosted Workspace / migration でも扱いやすくなる。
方針
.yoi/workspace.tomlを local Workspace identity の authority とする。workspace_idは path / display name から導出しない。- 新規 local Workspace 初期化時に UUIDv7 を発行して
workspace_idとして保存する。 display_nameは identity ではなく UI label として保存する。- 初期値は canonicalized workspace root の basename でよい。
- 将来的に rename 可能な field として扱う。
ServerConfig::local_devは Workspace ID を生成しない。- CLI/bootstrap 層で workspace root canonicalization と
.yoi/workspace.tomlload-or-init を行い、結果をServerConfigに渡す。
- CLI/bootstrap 層で workspace root canonicalization と
.yoi/workspace.tomlが壊れている場合は勝手に上書きせず、明示的な error で止める。- 既存
.yoi/workspace.db内のlocal:*workspace row については、初期実装では destructive migration を必須にしない。- 新しい UUIDv7 workspace row を upsert し、古い row は残してよい。
- 必要なら後続で cleanup/migration policy を設計する。
.yoi/workspace.toml v0
最小 schema:
workspace_id = "0197..." # UUIDv7 canonical string
created_at = "2026-06-23T...Z"
display_name = "yoi"
Validation:
workspace_idは UUID として parse できること。- 可能なら UUID version 7 であることを検証する。
created_atは RFC3339 UTC timestamp として parse できること。display_nameは空文字列でないこと。- unknown fields の扱いは将来拡張を考え、明示的に決める。
- v0 では deny でも preserve でもよいが、選択理由を実装に残す。
初期化フロー
yoi-workspace-server serve --workspace <path> の local bootstrap は将来的に以下の責務分離にする。
--workspaceを canonicalize する。- workspace root 配下の
.yoi/を確認し、なければ作成する。 .yoi/workspace.tomlを読む。- 存在しない場合:
- UUIDv7
workspace_idを発行する。 created_atを現在 UTC にする。display_nameを canonicalized workspace root basename から作る。.yoi/workspace.tomlを atomic-ish に書き込む。
- UUIDv7
- 存在する場合:
- parse / validate する。
- 壊れていたら停止し、上書きしない。
ServerConfigには canonicalized workspace root と Workspace identity を渡す。- SQLite
workspacesrow は.yoi/workspace.tomlのworkspace_id/display_nameで upsert する。 - API
/api/workspaceは DB row / identity record を元に stable id と display name を返す。
実装候補
crates/workspace-serverに Workspace identity loader を追加する。- 例:
workspace_identity.rsまたはidentity.rs。
- 例:
- 型例:
struct WorkspaceIdentity {
workspace_id: Uuid,
created_at: DateTime<Utc>,
display_name: String,
}
impl WorkspaceIdentity {
fn load_or_init(root: &Path) -> Result<Self, WorkspaceIdentityError>;
}
uuidcrate の UUIDv7 support を確認し、必要なら依存 feature を追加する。- TOML parse/write には既存 dependency を優先し、なければ最小 dependency を検討する。
ServerConfig::local_devはworkspace_id/display_nameを引数または identity object で受け取る形に寄せる。
Non-goals
- Hosted / multi-user Workspace identity の完全設計。
- Workspace rename UI。
- 既存
.yoi/workspace.dbの destructive migration。 - Ticket / Objective storage の DB authority migration。
.yoi/workspace.tomlを全 Workspace settings store に拡張すること。
受け入れ条件
- local Workspace identity が
.yoi/workspace.tomlに永続化される。 .yoi/workspace.toml未作成時、Workspace backend 初期化時に UUIDv7workspace_idが払い出される。workspace_idが path basename / display name から導出されなくなる。display_nameは.yoi/workspace.tomlの field として扱われ、identity と分離されている。--workspace .でも canonicalized workspace root をもとに初期化される。.yoi/workspace.tomlが壊れている場合、勝手に再生成/上書きせず error で停止する。ServerConfig::local_devまたは同等の bootstrap helper が workspace id を自前生成しない。- SQLite
workspacesrow は.yoi/workspace.tomlの identity を使って upsert される。 - 既存
local:{display}形式は新規 workspace id として生成されない。 cargo test -p yoi-workspace-server、git diff --check、nix build .#yoi --no-linkが通る。