yoi/tickets/scope-lock.review.md
2026-04-18 19:25:03 +09:00

101 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# レビュー: Scope lock file
対象差分: `crates/pod/src/scope_lock.rs` (新規 992行), `crates/manifest/src/scope.rs`, `crates/pod/src/{pod,lib,runtime_dir}.rs`, `crates/pod/Cargo.toml`(未コミット)
## 要件達成状況
| 要件 | 状態 |
|---|---|
| lock file に Pod の scope allocation を記録 | ✅ `register_pod` / `delegate_scope` で JSON に書き込み |
| flock による排他アクセス | ✅ `LockFileGuard::open``lock_exclusive`、Drop で `unlock` |
| write 衝突の検出 | ✅ `find_conflict_owner` が delegation tree を下降して真の所有者を特定 |
| stale エントリの自動回収 (PID 死活) | ✅ `reclaim_stale``kill(pid, 0)` で判定、dead を削除・子を reparent |
| scope 分譲の記録 (`delegated_from`) | ✅ `delegate_scope` が spawner の effective scope 内か検証してから登録 |
| 分譲チェーンの reparent (A→B→D、B 死亡時 D を A に付け替え) | ✅ `release_pod` / `reclaim_stale` ともに `delegated_from` を親に付け替え |
| Pod 正常終了時の allocation 解放 | ✅ `ScopeAllocationGuard` の Drop で `release_pod` を呼ぶ |
| Pod 起動時 (`from_manifest`) に自動登録 | ✅ `scope_lock::install_top_level``from_manifest` 内で呼出 |
| テストで衝突検出・stale 回収・分譲/返却を検証 | ✅ 16 テストケース |
| パーミッション制御 (0600) | — チケットに記載あるが、ファイル作成時の umask 制御は未実装。`OpenOptions` に mode 設定なし |
## アーキテクチャ
### 良い点
**`LockFileGuard` の RAII 設計**: `open` で flock 取得、`save` で書き込み、Drop で unlock。mutate-but-don't-save のパスでは変更が破棄される(エラー時に安全)。
**`ScopeAllocationGuard` で Pod ライフサイクルに紐付け**: Pod 構造体が `Option<ScopeAllocationGuard>` を保持し、Drop で lock file から自動削除。`Pod::new` / `Pod::restore`(テスト用)は `None` でバイパス。
**`find_conflict_owner` が delegation tree を下降**: 衝突エラーに「真の所有者」(最深のノード)を表示。`conflict_detection_descends_to_real_owner` テストで lock-in。
**`reclaim_stale_with` のテストシーム**: PID 生存判定を引数で差し替え可能。テストで任意の PID を「dead」にできる。
**`is_within_effective_write`**: spawner の allow set から子に委譲済みの部分を差し引いた「実効 scope」を計算。`delegate_scope` のバリデーションに使用。
**`rules_overlap` の 4 パターン分岐** (recursive×recursive, recursive×non, non×recursive, non×non): 非再帰ルールの覆域target 自身 + 直下の子)を正しく考慮。
### 指摘事項
#### 1. 🟡 ファイルパーミッションの明示設定
チケットの「セキュリティとアクセス」セクション:
> ファイルパーミッション `0600`owner only、ディレクトリは `0700`
`LockFileGuard::open``OpenOptions::new().create(true)` で作成しているが、パーミッションの明示設定がない。umask がデフォルト (0022) なら `0644` になり、他ユーザーから読めてしまう。
```rust
// 現状
let file = OpenOptions::new()
.read(true).write(true).create(true).truncate(false)
.open(path)?;
// 修正案: Unix 拡張で mode を設定
use std::os::unix::fs::OpenOptionsExt;
let file = OpenOptions::new()
.read(true).write(true).create(true).truncate(false)
.mode(0o600)
.open(path)?;
```
ディレクトリも `create_dir_all` の後に `std::fs::set_permissions``0700` に制限する。
**判断**: セキュリティ要件。修正すべき。
#### 2. 🟢 `socket` フィールドの予測パス
`pod.rs` で socket path を `runtime_dir::default_base()?.join(&manifest.pod.name).join("sock")` と予測しているが、実際の `RuntimeDir` が作る socket path と一致するか保証がない(`RuntimeDir` のパス構築ロジックが変わったら乖離する)。
現時点では一致しているが、将来 `RuntimeDir` のパス規則が変わったとき scope_lock の socket 情報が嘘になる。`RuntimeDir` 側に `fn socket_path_for(pod_name: &str) -> PathBuf` のような static メソッドを置いて、両者が同じ関数を呼ぶようにするとより堅牢。
**判断**: 現時点では問題なし。リファクタ余地として認識。
#### 3. 🟢 `covers_fully` の permission 比較
```rust
fn covers_fully(cover: &ScopeRule, inner: &ScopeRule) -> bool {
if cover.permission < inner.permission {
return false;
}
...
}
```
`Permission``Ord``Read < Write`。`cover.permission < inner.permission` = cover Read inner Write なら不十分」。正しい
#### 4. 🟢 テストの網羅性
16 ケース:
- ファイル操作: open creates / save-reopen roundtrip
- overlap 判定: prefix relation / non-recursive
- 登録: write conflict / duplicate name / read doesn't conflict
- 分譲: must be subset / succeeds within parent / rejects sibling overlap
- 解放: reparents children / reopens scope / returns to parent
- stale: reparents and removes dead entries
- guard: releases on drop
- conflict detection: descends to real owner
delegation tree の主要シナリオ (ABD) がカバーされている
## 結論
**指摘1 (ファイルパーミッション 0600) の修正を条件に受け入れ可**他は問題なし実装の核心delegation tree walk, effective scope 計算, stale reclaim + reparentが正確でテストが充実している