Skip to content

Remove user_id from mutating repository method signatures #233

@hiterm

Description

@hiterm

背景

PR #232 でトランザクション境界をユースケース層に移した結果、user_id のソースが2箇所になった:

  1. TransactionManager::begin(user_id, operation)event_set 行に記録される
  2. 各リポジトリのmutatingメソッド (create / update / delete / restore / find_or_create_by_name) の user_id 引数 — WHERE句やINSERTに使用される

両者が乖離すると監査記録が不整合になるため、レビュー指摘 (PR #232) を受けて暫定対策としてランタイムチェックを導入済み: PgTransactionbegin 時の UserId を保持し、各mutatingメソッドが冒頭の tx.ensure_user(user_id)? で照合、不一致なら DomainError::Unexpected を返す。

ランタイムチェックは乖離を検出できるが、型レベルで防止はできない。本Issueはレビューで提示されたもう一方の案(シグネチャから user_id を除去し、トランザクションを単一の信頼源にする)を扱う。

提案

mutatingメソッドのシグネチャから user_id 引数を削除する:

// Before
async fn create(&self, tx: &mut Self::Transaction, user_id: &UserId, book: &Book) -> Result<(), DomainError>;

// After
async fn create(&self, tx: &mut Self::Transaction, book: &Book) -> Result<(), DomainError>;

Pg* リポジトリ実装は具体型 PgTransaction を知っているため、tx.user_id() から user を取得してWHERE句・INSERTに使用できる。ドメイントレイトの Self::Transaction は不透明な関連型のままでよく、use_case層への sqlx 漏れは発生しない。誤った user_id を渡すことが型レベルで不可能になり、ensure_user のランタイムチェックは不要になる。

影響範囲

  • ドメイントレイト: BookRepository / AuthorRepository のmutatingメソッド 9件のシグネチャ変更(read系 find_* はプール直アクセスのため user_id 引数を維持 — 非対称性が残る点は設計上のトレードオフ)
  • 全mutatingインタラクターの呼び出し箇所
  • ユニットテスト: mockallの expect_*().with(...) / returning(...) の引数が1つ減る(全インタラクターテストに波及)
  • インフラDBテスト(test-with-database)のヘルパー群
  • PgTransaction::ensure_user と各メソッド冒頭のガード、および test_create_rejects_user_mismatched_transaction の削除
  • CLAUDE.md / AGENTS.md の Event Recording セクションと .agent/plans/ の Decision Log 更新

完了条件

  • mutatingメソッドが user_id 引数を持たず、PgTransaction 由来の user で動作すること
  • ensure_user ランタイムチェックが削除されていること
  • cargo fmt --check / cargo clippy --all-targets -- -D warnings / cargo test / cargo test --features test-with-database / E2E がすべて通ること

関連

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions