Merged
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #7 +/- ##
===========================================
- Coverage 95.08% 66.83% -28.26%
===========================================
Files 58 71 +13
Lines 3888 7095 +3207
===========================================
+ Hits 3697 4742 +1045
- Misses 191 2353 +2162 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Phase 1: Keycloak → Ory 移行 - Keycloak 依存を全て削除 (axum-keycloak-auth, KeycloakAuthLayer, KeycloakToken, expect_role!) - JWT 検証ミドルウェア実装 (OIDC Discovery, JWKS キャッシュ, RS256) - OAuth2 Login/Consent Provider エンドポイント (GET/POST /oauth2/login, /oauth2/consent) - Hydra Admin API クライアント + Kratos セッションクライアント - ルートハンドラ書き換え (AuthClaims ベース) - Handler/AppModule に Hydra/Kratos クライアント統合 - compose.yml で開発環境一括起動 (PostgreSQL, Redis, Kratos, Hydra) - E2E 検証完了 (Kratos login → OAuth2 flow → JWT → API access)
wiremockでHydra/Kratosをモックし、OAuth2エンドポイントの統合テスト10件を追加。 - GET /oauth2/login: skip/session有効/cookie無し/session無効の4ケース - GET /oauth2/consent: skip/client skip/通常表示の3ケース - POST /oauth2/consent: accept/scope不正/rejectの3ケース その他の変更: - tower 0.4→0.5にアップグレード(axum 0.7互換) - Handler::init_with_urls()を抽出しコンストラクタの重複を解消
dotenvy::varでDATABASE_URLの存在を確認し、未設定時はテストをスキップするように変更。 CIなどDB未起動環境でテストが失敗しないようにする。
test_withのコンパイル時envチェックにより、DATABASE_URL未設定時は テストがignoredとして正しく表示されるようにした。
kernel層にPermission/PermissionReq/Relation/Resource型とPermissionChecker/PermissionWriter traitを定義。 driver層にKetoClient (HTTP API実装)を追加。 application層にポリシー関数(account_view/edit/delete/sign, instance_moderate)とcheck_permissionヘルパーを追加。 全UseCase traitのインライン所有者チェック(find_by_auth_id)をKeto経由のpermissionチェックに置換。 Account作成時にowner tupleを自動作成、削除時に自動削除。 インフラ: compose.ymlにketo-migrate/ketoサービス追加、ory/keto/keto.yml設定ファイル追加。
- Account: Deleted → Deactivated (論理削除、entity は Some のまま deleted_at をセット) - serde alias "deleted" で旧イベント後方互換性を維持 - 二重退会防止ガード追加 - Profile/AuthAccount: 独立した Deleted イベントを除去(ドメイン的に不要) - AccountApplier: 退会時のカスケード処理を追加 - Profile 削除、全 Metadata 削除、全 Follow 削除、auth link 解除 - AccountReadModel: delete() → deactivate() + unlink_all_auth_accounts() 追加 - update() SQL に deleted_at カラムを追加 - DeleteProfileUseCase を完全削除、Profile の DELETE エンドポイントを除去 - DeleteAccountUseCase → DeactivateAccountUseCase にリネーム
個別ID取得エンドポイントをバッチ取得APIに統一し、N+1問題を解消。 - GET /accounts?ids=a,b,c でアカウントのバッチ取得(既存のページネーション一覧と共存) - GET /profiles?account_ids=a,b,c でプロフィールのバッチ取得 - GET /metadata?account_ids=a,b,c でメタデータのバッチ取得 - GET /accounts/:id, GET /accounts/:account_id/profile(GET), GET /accounts/:account_id/metadata(GET) を削除 - CUD routes (POST/PUT/DELETE) は変更なし 各層の変更: - kernel: ReadModelにfind_by_nanoids/find_by_account_idsトレイトメソッド追加 - driver: WHERE ... = ANY($1) によるPostgreSQL実装 - adapter: QueryProcessorにバッチメソッド追加(blanket impl) - application: DTOにaccount_nanoidフィールド追加、バッチUseCaseメソッド追加 - server: バッチハンドラ追加、バッチサイズ上限(100)、空文字列フィルタ、ids+pagination排他チェック 権限チェックはアカウント単位でイテレートし、権限のないアカウントは結果から除外。
Relation enumにリソース関連(Owner, Editor, Signer)とインスタンスRole(Admin, Moderator)が 混在していたため、型安全に分離。 - Relation → AccountRelation + InstanceRole に分離 - Resource 削除、PermissionReq を struct → enum 化 - PermissionWriter用に RelationTarget enum を導入 - namespace/object_id の定数を共通化(ACCOUNT_NAMESPACE, INSTANCE_NAMESPACE, INSTANCE_OBJECT_ID) - Keto 5xx レスポンス時にサイレント拒否ではなくエラーを返すように修正
モデレーション機能として、アカウントの Suspend(一時停止)/ Ban(永久追放)操作を実装。 - AccountStatus enum (Active/Suspended/Banned) を追加し、Account エンティティに status フィールドを導入 - AccountEvent に Suspended/Unsuspended/Banned バリアントを追加(タイムスタンプはイベントペイロードに含めてリプレイ決定性を保証) - KernelError::Rejected を追加(状態遷移エラー用、422 にマッピング) - AccountReadModel に unfiltered クエリ(suspended/banned 含む)と suspend/unsuspend/ban 操作を追加 - 通常クエリ(find_by_id/name/nanoid/nanoids)は suspended/banned を除外、find_by_auth_id は除外しない(自分の停止状態確認用) - 期限付き suspend は SQL クエリ時 + From<AccountRow> 変換時の両方で期限切れ判定 - SuspendAccountUseCase / UnsuspendAccountUseCase / BanAccountUseCase を追加(instance_moderate 権限必須) - POST /accounts/:id/suspend, /unsuspend, /ban エンドポイントを追加 - reason の長さバリデーション(1-1000文字)、expires_at の未来日バリデーションを実装 - マイグレーションに CHECK 制約を追加(suspend/ban フィールドの整合性保証) - Applier を find_by_id_unfiltered に切り替え、suspended/banned 状態の projection 更新に対応
routeモジュールからRequest/Response構造体と変換関数をschemaモジュールに分離
- utoipa 5.4.0を導入し、全ルートハンドラに#[utoipa::path]アトリビュートを追加 - スキーマ型にToSchema deriveを追加(account, profile, metadata, oauth2) - openapi.rsにOpenApi定義を集約、SecurityScheme(Bearer JWT)を設定 - create_accountのレスポンスを200→201に修正(他のcreateエンドポイントと統一) - CIでopenapi.jsonの差分チェックジョブを追加(openapi-check) - openapi.json生成テストは#[ignore]で通常テストから除外
Profileレスポンスのicon/bannerフィールドでImageId(UUIDv7)が外部APIに露出していた問題を修正。 - icon_id/banner_id (UUID) → icon_url/banner_url (String) に変更 - リクエスト側もURL文字列で画像を指定するように変更 - ImageRepositoryを使ってURL↔ImageIdの相互変換を実装 - UpdateProfileRequestでOption<Option<String>>による3状態サポート (absent=変更なし, null=クリア, "url"=設定) - EventApplierでicon/bannerのクリア(Some(None))に対応 - 空URL入力のバリデーション追加 - 参照先Image消失時のwarningログ追加 - create_profileのレスポンスをDB解決URLで返すよう修正
ImageRepositoryにfind_by_idsバッチメソッドを追加し、get_profiles_batchでの プロファイルごとの個別画像クエリ(2N回)を1回のバッチクエリに置換。 重複ImageIdはHashSetで除去してからクエリに渡すよう最適化。
Profile更新時のnullable fieldの3状態(変更なし/クリア/設定)を
Option<Option<T>>から明示的なFieldAction<T> enumに置き換え。
- kernel: FieldAction<T> {Unchanged, Clear, Set(T)} を定義
- kernel: ProfileEvent::Updated, Profile::update()で使用
- adapter: ProfileCommandProcessor::updateシグネチャ変更
- application: EditProfileUseCase, resolve_field_action_image_id
- server: schema層にinto_field_action()変換関数を配置
- serde互換: skip_serializing_if + defaultで既存イベントと後方互換
全エンティティIDをUUIDv7(128bit, PostgreSQL UUID)からferroid Snowflake ID (64bit, PostgreSQL BIGINT)に移行。 - kernel: Snowflake ID基盤モジュール(id.rs)追加、カスタムエポック2026-01-01 - define_snowflake_id! マクロで1+41+10+12ビットレイアウト定義 - OnceLockベースのグローバルジェネレータ(スレッドセーフ) - WORKER_IDバリデーション(0-1023) - ensure_generator_initialized()をtest-utils feature gateに制限 - kernel: 全エンティティID型、EventId、EventVersionをUuid→i64に変更 - kernel: CreatedAtのタイムスタンプ抽出をfrom_timestamp_ms()に変更 - driver: 全Row構造体、EventStore、ReadModel、RepositoryをUuid→i64に変更 - adapter/application: uuid依存削除、generate_id()使用に移行 - server: main.rsにinit_generator(worker_id)追加 - migrations: 全テーブルのUUID列をBIGINTに変更、event_streams削除 - dead feature flags(uuid, time)をkernel/Cargo.tomlから削除
kernel/src/test_utils/ にBuilderパターンのテストデータファクトリを導入し、 全クレートのテストコードを統一的なAPIで書き換え。 - AccountBuilder, ProfileBuilder, MetadataBuilder 等の各エンティティ用Builder - account_create_command() 等のCommandEnvelopeファクトリ - unique_account_name(), unique_image_url() 等のユニーク値ヘルパー - 意味のあるデフォルト値定数 (DEFAULT_ACCOUNT_NAME="alice" 等) - 重複テストヘルパー関数の削除 (make_account, make_profile, url, acct_url 等) - test-utils featureゲートで本番ビルドへの混入を防止 約600行の削減、テストの可読性と一貫性を向上。
nextest はテストごとに別プロセスで実行するため、プロセスローカルな AtomicUsize カウンターが毎回0からスタートし、UNIQUE制約違反が発生していた。 - next_unique() を AtomicUsize から Snowflake ID 生成に変更 - テスト用 ensure_generator_initialized() の worker_id を PID ベースに変更し、 プロセス間での Snowflake ID 衝突を回避
- workspace resolverを"2"に設定 - clippy警告を修正(too_many_arguments, useless_conversion, derivable_impls, needless_lifetimes) - テスト専用コードに#[cfg(test)]を付与 - デシリアライズ用構造体にallow(dead_code)を理由付きで付与 - OAuth2 loginフローでKratosセッション検証失敗時にHydraへreject_loginを通知するよう修正(401を返すのではなくリダイレクトURLを返す)
各層に専用のデータ構造を導入し、関数引数を構造体にまとめた。 - adapter層: *Param (CreateProfileParam, UpdateProfileParam 等) - application層: 入力用 *Dto (CreateProfileDto, UpdateProfileDto 等) - server層: Request に into_dto() メソッドを追加 併せて以下も実施: - Edit*UseCase を Update*UseCase にリネーム (adapter/kernel との命名統一) - CLAUDE.md の UseCase トレイト名を実態に合わせて更新 - clippy::too_many_arguments の #[allow] を削除
- 6つのマイグレーションファイルを1つに統合 - accountsテーブルにモデレーション列とCHECK制約を初期定義に含める - profiles.account_idのUNIQUE制約を初期定義に含める - 4つのイベントテーブル(account/auth_account/profile/metadata)を統合 - auth_emumet_accounts.auth_idにON DELETE CASCADEを追加(既存バグ修正) - 不要なdbml関連ファイル(init.dbml, gensql.sh, dbml-error.log)を削除
- begin_transaction → get_executor にリネーム(実態に合った命名)
- CORS設定を環境変数(CORS_ALLOWED_ORIGINS)から読み込むよう変更
- Keto設定からハードコードDSNを削除(compose.ymlの環境変数を使用)
- Suspend/Ban済みアカウントへのmutation操作を拒否するステータスチェック追加
- ProfileのUpdatedイベントでdisplay_name/summaryをFieldAction<T>に変更(クリア操作対応)
- CIにadapterクレートを追加
- 未使用依存関係を削除(async-trait, rand, zeroize, tower→dev-deps)
- Axumルートパスを非推奨の:param構文から{param}構文に移行
- GET /accountsの空結果を404から200+空リストに変更
- 重複テスト属性の削除、Snowflake IDキャストにコメント追加
- EventStoreの楽観的並行制御をCTE化しレースコンディションを緩和 - auth_accountsに(host_id, client_id) UNIQUE制約、followsに排他CHECK制約追加 - AccountPrivateKey/EncryptedPrivateKeyのDebug出力をマスク - KeyEncryptor::decryptの戻り値をZeroizing<Vec<u8>>に変更 - Deactivate時に全リレーション(Owner/Editor/Signer)を削除 - AuthAccount ReadModel失敗時にSignal発行でリカバリ対応 - ReadModel/Repositoryのupdate/deleteに影響行数チェック追加 - Keto 4xxレスポンスをエラーとして処理 - 入力バリデーション追加(最大長チェック) - 値オブジェクトにvalidate()メソッド追加(空文字/URL形式検証) - AuthAccountReadModelからupdate/delete削除(YAGNI) - Account Applierにパーミッション同期追加 - Signal失敗ログをerrorレベルに統一 - metadatas.account_idインデックス追加 - PREVページネーションで昇順統一 - password.rsのTOCTOU修正、JwksCache fetch失敗時rate limit適用 - ErrorStatusにログ出力追加、clippy警告修正
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.
/account/user/metadata