From eb998f0ad4ba39105b4b92ba95f88ee748abf105 Mon Sep 17 00:00:00 2001 From: Hare Date: Tue, 23 Jun 2026 15:44:29 +0900 Subject: [PATCH] ticket: add workspace identity initialization --- .yoi/tickets/00001KVSKGDYS/artifacts/.gitkeep | 0 .yoi/tickets/00001KVSKGDYS/item.md | 117 ++++++++++++++++++ .yoi/tickets/00001KVSKGDYS/thread.md | 24 ++++ 3 files changed, 141 insertions(+) create mode 100644 .yoi/tickets/00001KVSKGDYS/artifacts/.gitkeep create mode 100644 .yoi/tickets/00001KVSKGDYS/item.md create mode 100644 .yoi/tickets/00001KVSKGDYS/thread.md diff --git a/.yoi/tickets/00001KVSKGDYS/artifacts/.gitkeep b/.yoi/tickets/00001KVSKGDYS/artifacts/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/.yoi/tickets/00001KVSKGDYS/item.md b/.yoi/tickets/00001KVSKGDYS/item.md new file mode 100644 index 00000000..de69390f --- /dev/null +++ b/.yoi/tickets/00001KVSKGDYS/item.md @@ -0,0 +1,117 @@ +--- +title: 'Persist local Workspace identity in .yoi/workspace.toml' +state: 'ready' +created_at: '2026-06-23T06:43:28Z' +updated_at: '2026-06-23T06:44:19Z' +assignee: null +--- + +## 背景 + +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.toml` load-or-init を行い、結果を `ServerConfig` に渡す。 +- `.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: + +```toml +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 ` の local bootstrap は将来的に以下の責務分離にする。 + +1. `--workspace` を canonicalize する。 +2. workspace root 配下の `.yoi/` を確認し、なければ作成する。 +3. `.yoi/workspace.toml` を読む。 +4. 存在しない場合: + - UUIDv7 `workspace_id` を発行する。 + - `created_at` を現在 UTC にする。 + - `display_name` を canonicalized workspace root basename から作る。 + - `.yoi/workspace.toml` を atomic-ish に書き込む。 +5. 存在する場合: + - parse / validate する。 + - 壊れていたら停止し、上書きしない。 +6. `ServerConfig` には canonicalized workspace root と Workspace identity を渡す。 +7. SQLite `workspaces` row は `.yoi/workspace.toml` の `workspace_id` / `display_name` で upsert する。 +8. API `/api/workspace` は DB row / identity record を元に stable id と display name を返す。 + +## 実装候補 + +- `crates/workspace-server` に Workspace identity loader を追加する。 + - 例: `workspace_identity.rs` または `identity.rs`。 +- 型例: + +```rust +struct WorkspaceIdentity { + workspace_id: Uuid, + created_at: DateTime, + display_name: String, +} + +impl WorkspaceIdentity { + fn load_or_init(root: &Path) -> Result; +} +``` + +- `uuid` crate の 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 初期化時に UUIDv7 `workspace_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 `workspaces` row は `.yoi/workspace.toml` の identity を使って upsert される。 +- 既存 `local:{display}` 形式は新規 workspace id として生成されない。 +- `cargo test -p yoi-workspace-server`、`git diff --check`、`nix build .#yoi --no-link` が通る。 diff --git a/.yoi/tickets/00001KVSKGDYS/thread.md b/.yoi/tickets/00001KVSKGDYS/thread.md new file mode 100644 index 00000000..63ef5c37 --- /dev/null +++ b/.yoi/tickets/00001KVSKGDYS/thread.md @@ -0,0 +1,24 @@ + + +## 作成 + +LocalTicketBackend によって作成されました。 + +--- + + + +## Intake summary + +Marked ready by `yoi ticket state`. + +--- + + + +## State changed + +Marked ready by `yoi ticket state`. + + +---