Skip to content

[Crop] 画像領域を永続化し派生cropを管理する #617

Description

@hmjn023

Parent: #612

Depends on: #615

背景

現在の人物検出/cropはBase64画像を返す一時previewで、UIにも「保存されない」と明記されている。crop単位のCCIP抽出には安定したregion IDが必要だが、全検出結果や画像blobを無条件に保存すると容量・lifecycle・watcher処理が複雑になる。remote AI実行では transparent が転送されない既存不整合もある。

設計方針

  • 検出結果はephemeralのまま維持する
  • ユーザーが選択・保存したものだけ media_regions へ登録する
  • bbox、元画像寸法、label/score、detector/version、source revisionを正本とし、Base64/blobはDBへ保存しない
  • 表示画像は元画像から生成し、region revision・source更新時刻・render/segmenter versionをkeyに派生cacheする
  • 独立ファイルが必要な場合だけ明示的にmaterializeし、child mediaと derivative relationを作る

スコープ

  • regionの保存・一覧・更新・削除・render・materialize API/UI
  • bbox範囲、元画像revision、削除cascade、cache invalidation
  • remote crop呼び出しへの transparent 転送修正
  • domain/contract/OpenAPIとPostgreSQL/PGliteのテスト

非スコープ

  • 検出結果の自動全件保存
  • crop画像本体のDB保存
  • crop CCIP embedding・類似検索

受け入れ条件

  • previewだけではDBへ書き込まれない
  • 保存したregionを再起動後も復元できる
  • 元画像・bbox・renderer更新後に古いcacheを返さない
  • materialize時だけmediaとderivative relationが作られる
  • remote実行でもtransparent指定が維持される
  • OpenAPIと関連testが更新される

主な参照

  • apps/server/src/infrastructure/api/routers/ai-router.ts:100
  • apps/server/src/infrastructure/api/routers/ai-router.ts:111
  • packages/ui/src/character-crop-modal.tsx:72
  • packages/core/src/domain/tagging/schemas.ts:102
  • packages/db/src/schema.ts:678

評価反映(2026-07-18)

本節をregion永続化の最終仕様とする。本文にある「検出結果はephemeral」「選択したものだけ保存」「自動全件保存は非スコープ」および対応する旧受け入れ条件は、本節で置き換える。

永続化境界

登録済みmediaを対象とする処理では、検出済み・手動作成済みのregionを常にmedia_regionsへ保存する。保存するのは座標と再現用metadataであり、crop画像本体ではない。

  • 検出APIは永続化済みregion IDを返す
  • 再検出・再送で同じregionが無制限に増えないよう、media revision、detector/model version、検出結果を基にした決定的なidempotency規則を定義する
  • 手動追加・bbox編集も保存対象とする
  • 元画像revisionが変わったregionはcurrentとして黙って再利用せず、staleとして再検出・再確認の対象にする
  • crop画像は必要時に元画像から生成し、materializeを明示した場合だけchild mediaとderivative relationを作る

一方、file inputなど登録済みmedia IDを持たないpreviewはFKの親がないためephemeralのままとする。保存操作を提供する場合は、先にmediaとしてimport/materializeしてからregionを関連付ける。

UI契約

現在の「データは保存されない」という一律の説明は削除し、実行modeごとに次を明示する。

  • media-backed mode: 「検出した領域情報(座標・検出metadata)は保存されます。crop画像本体は保存されません」
  • file-preview mode: 「このファイルの検出結果はpreviewのみで保存されません」

media-backed modeでmodal open時の自動検出を維持する場合、modalを開くことでregionが永続化されることをUIとテストで明示する。見えない副作用を避けるため明示的な検出操作へ変更する場合も、検出実行後は同じ永続化規則を適用する。

追加受け入れ条件

  • media-backed検出で返された全regionに永続IDがあり、再起動後も復元できる
  • 同じrevision・detector/versionで再検出しても重複が無制限に増えない
  • 手動作成・bbox編集が永続化される
  • file-previewはDBへ書き込まず、media化後にだけregionを保存できる
  • media-backed/file-previewで保存有無の説明が正しく切り替わる
  • 元画像revision変更後に古いregion/cacheをcurrentとして返さない
  • 通常のregion保存ではBase64/blob/child mediaを作成しない
  • materialize時だけchild mediaとderivative relationを作成する

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