profile-transfer: Profile 移管 (個人→組織) — 2段階フロー + 所有移転 + 参照ファイルコピー要求 - #62
Merged
Merged
Conversation
…d model, and storage port
…t/accept/reject/cancel)
…fileMediaCopyGateway wiring
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #62 +/- ##
==========================================
- Coverage 76.28% 75.47% -0.81%
==========================================
Files 211 232 +21
Lines 24930 27216 +2286
==========================================
+ Hits 19018 20542 +1524
- Misses 5912 6674 +762 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Goal
Closes #61
個人の Profile を組織へ移管する 2段階フロー (申請 → 承認) を実装。承認時に Profile の所有 (
account_id) が組織へ移転し、参照ファイル (icon/banner) のコピー要求が port に発行される。あわせてprofiles.account_idを部分ユニーク化し、組織が複数 Profile を持てるようにする。What changed
kernel):Requested/Accepted/Rejected/Cancelledイベント +pending → accepted|rejected|cancelled状態遷移。ES 永続化は AccountReport と同型 (profile_transfer_request_events+AggregateRepository+ read model)。tailing projector は持たない (外部イベント producer がなく、use case が同一 tx で read model を同期更新するため —close_reportと同パターン)。kernel):Profile::transfer_account(last-write-wins) + apply でaccount_idを付け替え。acct/Actor URI・nanoid・署名鍵・フォロー関係は Profile スコープで不変 (grill Q6)。serde 後方互換 (既存 profile_events 行はそのまま読める)。application): request / accept / reject / cancel。申請=プロフィール所有者かつ移管先 org の active メンバー、承認/却下=移管先 org の Owner/Admin (個人 identity のメンバーロール判定)、取消=申請者本人 (pending のみ)。受理後の取消・却下・再承認は 422。server):POST /api/v1/profiles/{profile_nanoid}/transfer-requests(201)、POST /api/v1/profile-transfer-requests/{nanoid}/accept|reject|cancel(204)。OpenAPI 登録 + contract test + 仕様再生成済み。20260904000001_profile_transfer.sql:profiles.owner_kind非正規化カラム (accounts.kind から backfill、read model SQL が subselect で維持) +profiles.account_idの全件 UNIQUE をWHERE owner_kind='personal'の部分ユニーク index に置換。個人 1:1 は維持、組織は複数 Profile を持てる。移管申請の二重 pending は DB の部分ユニーク index でも backstop。kernel::interfaces::storage::ProfileMediaCopyGateway(request_copy(ProfileMediaCopyRequest { from_account_id, to_account_id, image_ids }))。実装はNoopProfileMediaCopyGatewaystub (driver)。承認 tx commit 後に icon/banner のImageIdを集めて発行 (空なら skip、失敗は warn ログのみ)。Booskiff 実連携は別 packet。影響ノート
CreateOrganizationProfileUseCaseの org 重複プロフィール拒否ガードを削除 (複数所持が仕様化)。既存テストcreate_second_profile_for_same_organization_*を新仕様 (201 成功) に書き換え済み。find_by_account_idは従来通り単一返し (任意の1件)。複数列挙・選択 UI は後続 packet の論点。Verification
cargo fmt --all --check/cargo check --workspace/cargo clippy --workspace -- -D warnings全緑cargo test --workspace(実 Postgres 16, migration を空 DB から適用): kernel 166 / driver 157 / application 104 / server 67 passed, 0 failedwrite_openapi_spec_to_file再生成 ↔ コミット済み openapi.json の no-diff 確認済み (CI openapi-check 対応)Closeout writeback 想定 (host 側)
ProfileEvent::AccountTransferred+ profiles.account_id 部分ユニーク化 + コピー port/stub、及び非正規化owner_kindカラム (Postgres partial index predicate は他テーブル参照不可のため)