<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>設計書</title><link>https://Hitamuki.github.io/image-upload/</link><description>Recent content on 設計書</description><generator>Hugo</generator><language>ja</language><atom:link href="https://Hitamuki.github.io/image-upload/index.xml" rel="self" type="application/rss+xml"/><item><title>API一覧</title><link>https://Hitamuki.github.io/image-upload/design/api/0_api%E4%B8%80%E8%A6%A7/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/api/0_api%E4%B8%80%E8%A6%A7/</guid><description>&lt;h1 id="api一覧"&gt;API一覧&lt;a class="anchor" href="#api%e4%b8%80%e8%a6%a7"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;ID&lt;/th&gt;
 &lt;th style="text-align: left"&gt;メソッド&lt;/th&gt;
 &lt;th style="text-align: left"&gt;パス&lt;/th&gt;
 &lt;th style="text-align: left"&gt;概要&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api001-upload/"&gt;api001&lt;/a&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;POST&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;/images/presigned-url&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3アップロード用の署名付きURLを発行する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api002-upload/"&gt;api002&lt;/a&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;POST&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;/images&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像メタデータを登録する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api003-upload/"&gt;api003&lt;/a&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;GET&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;/images&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード済み画像の名前リスト取得&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api004-upload/"&gt;api004&lt;/a&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;GET&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;/images/:id&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像の閲覧用URL（Presigned）取得&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>画面一覧</title><link>https://Hitamuki.github.io/image-upload/design/ui/0_%E7%94%BB%E9%9D%A2%E4%B8%80%E8%A6%A7/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/ui/0_%E7%94%BB%E9%9D%A2%E4%B8%80%E8%A6%A7/</guid><description>&lt;h1 id="画面一覧"&gt;画面一覧&lt;a class="anchor" href="#%e7%94%bb%e9%9d%a2%e4%b8%80%e8%a6%a7"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;ID&lt;/th&gt;
 &lt;th style="text-align: left"&gt;画面名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;URI&lt;/th&gt;
 &lt;th style="text-align: left"&gt;概要&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/ui/scr001-upload/"&gt;SCR001&lt;/a&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像アップロード画面&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;/home&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像の選択・アップロード・閲覧を行う単一画面&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>署名付きURL 発行</title><link>https://Hitamuki.github.io/image-upload/design/api/images/api001-upload/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/api/images/api001-upload/</guid><description>&lt;h1 id="署名付きurl-発行"&gt;署名付きURL 発行&lt;a class="anchor" href="#%e7%bd%b2%e5%90%8d%e4%bb%98%e3%81%8durl-%e7%99%ba%e8%a1%8c"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="id"&gt;ID&lt;a class="anchor" href="#id"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;api001-upload&lt;/p&gt;
&lt;h2 id="エンドポイント"&gt;エンドポイント&lt;a class="anchor" href="#%e3%82%a8%e3%83%b3%e3%83%89%e3%83%9d%e3%82%a4%e3%83%b3%e3%83%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;メソッド&lt;/th&gt;
 &lt;th style="text-align: left"&gt;パス&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;POST&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;/images/presigned-url&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="概要"&gt;概要&lt;a class="anchor" href="#%e6%a6%82%e8%a6%81"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;S3アップロード用の署名付きURLを発行する。&lt;/p&gt;
&lt;h2 id="リクエスト"&gt;リクエスト&lt;a class="anchor" href="#%e3%83%aa%e3%82%af%e3%82%a8%e3%82%b9%e3%83%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="ボディ"&gt;ボディ&lt;a class="anchor" href="#%e3%83%9c%e3%83%87%e3%82%a3"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;物理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;論理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;型&lt;/th&gt;
 &lt;th style="text-align: center"&gt;必須&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;fileName&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイル名&lt;/td&gt;
 &lt;td style="text-align: left"&gt;string&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロードするファイル名&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;fileSize&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイルサイズ&lt;/td&gt;
 &lt;td style="text-align: left"&gt;number&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイルサイズ（バイト単位）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;contentType&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Content-Type&lt;/td&gt;
 &lt;td style="text-align: left"&gt;string&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MIMEタイプ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;fileName&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;fileSize&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;number&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;contentType&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="バリデーション"&gt;バリデーション&lt;a class="anchor" href="#%e3%83%90%e3%83%aa%e3%83%87%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;検証項目&lt;/th&gt;
 &lt;th style="text-align: left"&gt;条件&lt;/th&gt;
 &lt;th style="text-align: left"&gt;レスポンス&lt;/th&gt;
 &lt;th style="text-align: left"&gt;メッセージ&lt;/th&gt;
 &lt;th style="text-align: left"&gt;備考&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;ファイルサイズ&lt;/td&gt;
 &lt;td style="text-align: left"&gt;5MB 超&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;400 Bad Request&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MSG-API-001&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;Content-Type&lt;/td&gt;
 &lt;td style="text-align: left"&gt;許可リスト外&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;400 Bad Request&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MSG-API-002&lt;/td&gt;
 &lt;td style="text-align: left"&gt;許可 Content-Type: &lt;code&gt;image/jpeg&lt;/code&gt; &lt;code&gt;image/png&lt;/code&gt; &lt;code&gt;image/gif&lt;/code&gt; &lt;code&gt;image/webp&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;アップロード枚数上限&lt;/td&gt;
 &lt;td style="text-align: left"&gt;同一ユーザーが 5 枚以上保持&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;409 Conflict&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MSG-API-003&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;レート制限&lt;/td&gt;
 &lt;td style="text-align: left"&gt;同一 IP から 1 分間に 10 回超&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;429 Too Many Requests&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MSG-API-C001&lt;/td&gt;
 &lt;td style="text-align: left"&gt;共通仕様に準拠&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="presigned-url-有効期限"&gt;Presigned URL 有効期限&lt;a class="anchor" href="#presigned-url-%e6%9c%89%e5%8a%b9%e6%9c%9f%e9%99%90"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;発行から &lt;strong&gt;300 秒（5 分）&lt;/strong&gt; 以内に PUT が完了しない場合 URL は無効となる。期限切れ時はクライアントが発行から再試行する。&lt;/p&gt;</description></item><item><title>API共通仕様</title><link>https://Hitamuki.github.io/image-upload/design/api/1_api%E5%85%B1%E9%80%9A%E4%BB%95%E6%A7%98/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/api/1_api%E5%85%B1%E9%80%9A%E4%BB%95%E6%A7%98/</guid><description>&lt;h1 id="api共通仕様"&gt;API共通仕様&lt;a class="anchor" href="#api%e5%85%b1%e9%80%9a%e4%bb%95%e6%a7%98"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;全APIエンドポイントに共通して適用される仕様を定義する。&lt;/p&gt;
&lt;h2 id="ベースurl"&gt;ベースURL&lt;a class="anchor" href="#%e3%83%99%e3%83%bc%e3%82%b9url"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/api/v1&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="共通ヘッダー"&gt;共通ヘッダー&lt;a class="anchor" href="#%e5%85%b1%e9%80%9a%e3%83%98%e3%83%83%e3%83%80%e3%83%bc"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="リクエスト"&gt;リクエスト&lt;a class="anchor" href="#%e3%83%aa%e3%82%af%e3%82%a8%e3%82%b9%e3%83%88"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;ヘッダー名&lt;/th&gt;
 &lt;th style="text-align: center"&gt;必須&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;X-Trace-ID&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;トレーサビリティID（UUID v4）。フロントエンドで生成し全リクエストに付与する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;X-Request-ID&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;リクエスト識別ID（UUID v4）。フロントエンドで生成し、冪等性制御とキャンセルに使用する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;Content-Type&lt;/td&gt;
 &lt;td style="text-align: center"&gt;△&lt;/td&gt;
 &lt;td style="text-align: left"&gt;リクエストボディがある場合は &lt;code&gt;application/json&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="レスポンス"&gt;レスポンス&lt;a class="anchor" href="#%e3%83%ac%e3%82%b9%e3%83%9d%e3%83%b3%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;ヘッダー名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;Content-Type&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;application/json&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="共通エラーレスポンス形式"&gt;共通エラーレスポンス形式&lt;a class="anchor" href="#%e5%85%b1%e9%80%9a%e3%82%a8%e3%83%a9%e3%83%bc%e3%83%ac%e3%82%b9%e3%83%9d%e3%83%b3%e3%82%b9%e5%bd%a2%e5%bc%8f"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;code&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;フィールド名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;th style="text-align: left"&gt;例&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;code&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラーコード&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;INVALID_FILE_SIZE&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;message&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラーメッセージ&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;ファイルサイズが上限（5MB）を超えています&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="共通ステータスコード"&gt;共通ステータスコード&lt;a class="anchor" href="#%e5%85%b1%e9%80%9a%e3%82%b9%e3%83%86%e3%83%bc%e3%82%bf%e3%82%b9%e3%82%b3%e3%83%bc%e3%83%89"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;コード&lt;/th&gt;
 &lt;th style="text-align: left"&gt;メッセージID&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;429&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MSG-API-C001&lt;/td&gt;
 &lt;td style="text-align: left"&gt;レート制限超過&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;500&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MSG-API-C002&lt;/td&gt;
 &lt;td style="text-align: left"&gt;サーバー内部エラー&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="レート制限"&gt;レート制限&lt;a class="anchor" href="#%e3%83%ac%e3%83%bc%e3%83%88%e5%88%b6%e9%99%90"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;同一IPアドレスから1分間に10リクエストを超えた場合、&lt;code&gt;429 Too Many Requests&lt;/code&gt; を返す。&lt;/p&gt;
&lt;h2 id="トレーサビリティ"&gt;トレーサビリティ&lt;a class="anchor" href="#%e3%83%88%e3%83%ac%e3%83%bc%e3%82%b5%e3%83%93%e3%83%aa%e3%83%86%e3%82%a3"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="id-の役割"&gt;ID の役割&lt;a class="anchor" href="#id-%e3%81%ae%e5%bd%b9%e5%89%b2"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;X-Trace-ID&lt;/strong&gt;: セッション全体の横断的トレーサビリティを確保するためのID&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;X-Request-ID&lt;/strong&gt;: 単一操作の冪等性制御とキャンセルに使用するID&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="実装方針"&gt;実装方針&lt;a class="anchor" href="#%e5%ae%9f%e8%a3%85%e6%96%b9%e9%87%9d"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;フロントエンドは UUID v4 の &lt;code&gt;X-Trace-ID&lt;/code&gt; を生成し、全リクエストヘッダーに付与する。&lt;/li&gt;
&lt;li&gt;フロントエンドは UUID v4 の &lt;code&gt;X-Request-ID&lt;/code&gt; を生成し、各操作のリクエストヘッダーに付与する。&lt;/li&gt;
&lt;li&gt;バックエンドは両方のIDをリクエストヘッダーから受け取り、全レイヤのログに引き継ぐ。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X-Request-ID&lt;/code&gt; は冪等性チェックに使用し、DBには保存しない（メモリ内で管理）。&lt;/li&gt;
&lt;li&gt;ログは Pino で構造化（JSON）出力し、CloudWatch Logs に集約する。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="懸案事項"&gt;懸案事項&lt;a class="anchor" href="#%e6%87%b8%e6%a1%88%e4%ba%8b%e9%a0%85"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="認証認可方式の未確定"&gt;認証・認可方式の未確定&lt;a class="anchor" href="#%e8%aa%8d%e8%a8%bc%e8%aa%8d%e5%8f%af%e6%96%b9%e5%bc%8f%e3%81%ae%e6%9c%aa%e7%a2%ba%e5%ae%9a"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;現状&lt;/strong&gt;: API共通仕様に認証機構が定義されていない&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;影響&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;ユーザー識別が不可能で、アップロード枚数上限がグローバル制約となる&lt;/li&gt;
&lt;li&gt;アクセス制御ができず、全ユーザーが全画像にアクセス可能&lt;/li&gt;
&lt;li&gt;監査証跡が不完全で、誰がどの操作を行ったか追跡不可&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;対応方針&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;JWTトークンまたはセッションベース認証の選定&lt;/li&gt;
&lt;li&gt;Authorizationヘッダーの必須化&lt;/li&gt;
&lt;li&gt;ユーザーIDの全リクエストへの引き継ぎ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="hono-middlewareへの影響"&gt;Hono Middlewareへの影響&lt;a class="anchor" href="#hono-middleware%e3%81%b8%e3%81%ae%e5%bd%b1%e9%9f%bf"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;現状&lt;/strong&gt;: 認証ミドルウェアが未実装&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;影響&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;各APIエンドポイントで個別に認証チェックが必要&lt;/li&gt;
&lt;li&gt;コード重複とメンテナンス性の低下&lt;/li&gt;
&lt;li&gt;セキュリティポリシーの統一が困難&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;対応方針&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;認証ミドルウェアの共通化&lt;/li&gt;
&lt;li&gt;ユーザー情報のContextへの格納&lt;/li&gt;
&lt;li&gt;認可エラーハンドリングの統一&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="トレーサビリティと認証の連携"&gt;トレーサビリティと認証の連携&lt;a class="anchor" href="#%e3%83%88%e3%83%ac%e3%83%bc%e3%82%b5%e3%83%93%e3%83%aa%e3%83%86%e3%82%a3%e3%81%a8%e8%aa%8d%e8%a8%bc%e3%81%ae%e9%80%a3%e6%90%ba"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;現状&lt;/strong&gt;: trace_idのみでユーザー情報が紐づかない&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;影響&lt;/strong&gt;: ユーザー単位の障害調査や監査が困難&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;対応方針&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;trace_idとuser_idの両方をログに記録&lt;/li&gt;
&lt;li&gt;ユーザー操作のエンドツーエンド追跡を可能にする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="tbd"&gt;TBD&lt;a class="anchor" href="#tbd"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="認証方式の技術選定"&gt;認証方式の技術選定&lt;a class="anchor" href="#%e8%aa%8d%e8%a8%bc%e6%96%b9%e5%bc%8f%e3%81%ae%e6%8a%80%e8%a1%93%e9%81%b8%e5%ae%9a"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;JWTトークン方式&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;メリット: ステートレス、スケーラビリティ高、SPA親和性&lt;/li&gt;
&lt;li&gt;デメリット: トークン失効・リフレッシュ処理の複雑化&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;セッション方式&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;メリット: 実装シンプル、サーバー側制御容易&lt;/li&gt;
&lt;li&gt;デメリット: ステートフル、スケーラビリティ制約&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;選定基準&lt;/strong&gt;: セキュリティ要件、運用要件、パフォーマンス要件を考慮&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ミドルウェアアーキテクチャ設計"&gt;ミドルウェアアーキテクチャ設計&lt;a class="anchor" href="#%e3%83%9f%e3%83%89%e3%83%ab%e3%82%a6%e3%82%a7%e3%82%a2%e3%82%a2%e3%83%bc%e3%82%ad%e3%83%86%e3%82%af%e3%83%81%e3%83%a3%e8%a8%ad%e8%a8%88"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;認証ミドルウェアの実装順序（レート制限→認証→認可）&lt;/li&gt;
&lt;li&gt;エラーハンドリングの共通化&lt;/li&gt;
&lt;li&gt;Context情報の型定義と引き継ぎ仕様&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="認可モデルの設計"&gt;認可モデルの設計&lt;a class="anchor" href="#%e8%aa%8d%e5%8f%af%e3%83%a2%e3%83%87%e3%83%ab%e3%81%ae%e8%a8%ad%e8%a8%88"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;リソースベース認可&lt;/strong&gt;: 画像所有者のみアクセス許可&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ロールベース認可&lt;/strong&gt;: 管理者権限の定義（将来拡張）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;スコープ制御&lt;/strong&gt;: 読み取り専用・書き込み専用アクセスの制御&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="セキュリティ強化項目"&gt;セキュリティ強化項目&lt;a class="anchor" href="#%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e5%bc%b7%e5%8c%96%e9%a0%85%e7%9b%ae"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;トークン有効期限の最適設定&lt;/li&gt;
&lt;li&gt;リフレッシュトークンの導入検討&lt;/li&gt;
&lt;li&gt;CSRF対策の実装方針&lt;/li&gt;
&lt;li&gt;APIキー管理（将来的な外部連携向け）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="パフォーマンスへの影響評価"&gt;パフォーマンスへの影響評価&lt;a class="anchor" href="#%e3%83%91%e3%83%95%e3%82%a9%e3%83%bc%e3%83%9e%e3%83%b3%e3%82%b9%e3%81%b8%e3%81%ae%e5%bd%b1%e9%9f%bf%e8%a9%95%e4%be%a1"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;認証チェックのオーバーヘッド測定&lt;/li&gt;
&lt;li&gt;キャッシュ戦略との整合性&lt;/li&gt;
&lt;li&gt;負荷テストでの性能検証&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>アップロード完了・メタデータ登録</title><link>https://Hitamuki.github.io/image-upload/design/api/images/api002-upload/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/api/images/api002-upload/</guid><description>&lt;h1 id="アップロード完了メタデータ登録"&gt;アップロード完了・メタデータ登録&lt;a class="anchor" href="#%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89%e5%ae%8c%e4%ba%86%e3%83%a1%e3%82%bf%e3%83%87%e3%83%bc%e3%82%bf%e7%99%bb%e9%8c%b2"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="id"&gt;ID&lt;a class="anchor" href="#id"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;api002-upload&lt;/p&gt;
&lt;h2 id="エンドポイント"&gt;エンドポイント&lt;a class="anchor" href="#%e3%82%a8%e3%83%b3%e3%83%89%e3%83%9d%e3%82%a4%e3%83%b3%e3%83%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;メソッド&lt;/th&gt;
 &lt;th style="text-align: left"&gt;パス&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;POST&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;/images&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="概要"&gt;概要&lt;a class="anchor" href="#%e6%a6%82%e8%a6%81"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;S3への直接アップロード完了後、マジックナンバー検証を行いメタデータをDBに登録する。&lt;/p&gt;
&lt;h2 id="リクエスト"&gt;リクエスト&lt;a class="anchor" href="#%e3%83%aa%e3%82%af%e3%82%a8%e3%82%b9%e3%83%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="ボディ"&gt;ボディ&lt;a class="anchor" href="#%e3%83%9c%e3%83%87%e3%82%a3"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;物理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;論理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;型&lt;/th&gt;
 &lt;th style="text-align: center"&gt;必須&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;key&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3オブジェクトキー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;string&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3上の保存パス&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="バリデーション"&gt;バリデーション&lt;a class="anchor" href="#%e3%83%90%e3%83%aa%e3%83%87%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;検証項目&lt;/th&gt;
 &lt;th style="text-align: left"&gt;条件&lt;/th&gt;
 &lt;th style="text-align: left"&gt;レスポンス&lt;/th&gt;
 &lt;th style="text-align: left"&gt;メッセージ&lt;/th&gt;
 &lt;th style="text-align: left"&gt;備考&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;S3ファイル存在&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイルが存在しない&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;404 Not Found&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MSG-API-005&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;マジックナンバー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;許可フォーマット外&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;422 Unprocessable Entity&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MSG-API-004&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3ファイルを削除（失敗時422）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;S3削除失敗&lt;/td&gt;
 &lt;td style="text-align: left"&gt;削除操作のエラー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;500 Internal Server Error&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MSG-API-006&lt;/td&gt;
 &lt;td style="text-align: left"&gt;トランザクション不整合リスク&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;アップロード枚数上限&lt;/td&gt;
 &lt;td style="text-align: left"&gt;排他ロック取得後に5件以上&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;409 Conflict&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MSG-API-003&lt;/td&gt;
 &lt;td style="text-align: left"&gt;SELECT FOR UPDATEで競合防止後にチェック&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="マジックナンバー検証"&gt;マジックナンバー検証&lt;a class="anchor" href="#%e3%83%9e%e3%82%b8%e3%83%83%e3%82%af%e3%83%8a%e3%83%b3%e3%83%90%e3%83%bc%e6%a4%9c%e8%a8%bc"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;S3上のファイルの先頭バイト列を読み取り、実際のMIMEタイプを検証する。ファイルサイズはS3 HeadObjectメタデータから取得し、クライアント送信値に依存しない。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;フォーマット&lt;/th&gt;
 &lt;th style="text-align: left"&gt;マジックナンバー&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;JPEG&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;FF D8 FF&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;PNG&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;89 50 4E 47 0D 0A 1A 0A&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;GIF&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;47 49 46 38&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;WebP&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;52 49 46 46&lt;/code&gt; (offset 0) + &lt;code&gt;57 45 42 50&lt;/code&gt; (offset 8)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="レスポンス"&gt;レスポンス&lt;a class="anchor" href="#%e3%83%ac%e3%82%b9%e3%83%9d%e3%83%b3%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="201-created"&gt;201 Created&lt;a class="anchor" href="#201-created"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;物理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;論理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;型&lt;/th&gt;
 &lt;th style="text-align: center"&gt;必須&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;id&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像ID&lt;/td&gt;
 &lt;td style="text-align: left"&gt;string&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;登録された画像のID&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;url&lt;/td&gt;
 &lt;td style="text-align: left"&gt;閲覧用URL&lt;/td&gt;
 &lt;td style="text-align: left"&gt;string&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像の閲覧用URL&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ステータスコード"&gt;ステータスコード&lt;a class="anchor" href="#%e3%82%b9%e3%83%86%e3%83%bc%e3%82%bf%e3%82%b9%e3%82%b3%e3%83%bc%e3%83%89"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;コード&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;201&lt;/td&gt;
 &lt;td style="text-align: left"&gt;成功&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;404&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3上にファイルが存在しない&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;409&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード枚数上限超過（5件以上）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;422&lt;/td&gt;
 &lt;td style="text-align: left"&gt;マジックナンバー検証失敗（S3ファイルを削除）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;500&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3削除失敗またはDB登録失敗&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="内部処理シーケンス"&gt;内部処理シーケンス&lt;a class="anchor" href="#%e5%86%85%e9%83%a8%e5%87%a6%e7%90%86%e3%82%b7%e3%83%bc%e3%82%b1%e3%83%b3%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 autonumber
 actor User
 participant Hono as Hono Middleware
 participant Domain as Domain Service
 participant S3 as S3 Client
 participant DB as Repository

 User-&amp;gt;&amp;gt;+Hono: 完了通知 (key, request_id, trace_id )
 Hono-&amp;gt;&amp;gt;Domain: 完了通知 (key, request_id, trace_id)
 Domain-&amp;gt;&amp;gt;+S3: HeadObject（ファイルの存在確認・メタデータ取得）
 S3--&amp;gt;&amp;gt;-Domain: metadata (fileSize, ContentType, ...)
 Domain-&amp;gt;&amp;gt;+S3: GetObject（先頭バイト取得）
 S3--&amp;gt;&amp;gt;-Domain: fileBytes
 Domain-&amp;gt;&amp;gt;Domain: マジックナンバー検証
 alt 検証失敗
 Domain-&amp;gt;&amp;gt;+S3: DeleteObject
 S3--&amp;gt;&amp;gt;-Domain: result
 Domain--&amp;gt;&amp;gt;Hono: Error (422 Unprocessable Entity)
 else 検証成功
 Domain-&amp;gt;&amp;gt;+DB: SELECT FOR UPDATE（排他ロック取得 + 件数確認）
 DB--&amp;gt;&amp;gt;-Domain: currentCount
 alt 5件以上
 Domain--&amp;gt;&amp;gt;Hono: Error (409 Conflict)
 else 5件未満
 Domain-&amp;gt;&amp;gt;+DB: INSERT メタデータ (id, key, fileSize, contentType, ...)
 DB--&amp;gt;&amp;gt;-Domain: result
 alt DB保存成功
 Domain--&amp;gt;&amp;gt;Hono: Success (201, id, url)
 else DB保存失敗
 Domain--&amp;gt;&amp;gt;Hono: Error (500 Internal Server Error)
 end
 end
 end
 Hono--&amp;gt;&amp;gt;-User: Response&lt;/pre&gt;&lt;h2 id="懸案事項"&gt;懸案事項&lt;a class="anchor" href="#%e6%87%b8%e6%a1%88%e4%ba%8b%e9%a0%85"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="s3とdb間の分散トランザクション"&gt;S3とDB間の分散トランザクション&lt;a class="anchor" href="#s3%e3%81%a8db%e9%96%93%e3%81%ae%e5%88%86%e6%95%a3%e3%83%88%e3%83%a9%e3%83%b3%e3%82%b6%e3%82%af%e3%82%b7%e3%83%a7%e3%83%b3"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;現状&lt;/strong&gt;:&lt;/p&gt;</description></item><item><title>画面共通仕様</title><link>https://Hitamuki.github.io/image-upload/design/ui/1_%E7%94%BB%E9%9D%A2%E5%85%B1%E9%80%9A%E4%BB%95%E6%A7%98/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/ui/1_%E7%94%BB%E9%9D%A2%E5%85%B1%E9%80%9A%E4%BB%95%E6%A7%98/</guid><description>&lt;h1 id="画面共通仕様"&gt;画面共通仕様&lt;a class="anchor" href="#%e7%94%bb%e9%9d%a2%e5%85%b1%e9%80%9a%e4%bb%95%e6%a7%98"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="トレーサビリティ"&gt;トレーサビリティ&lt;a class="anchor" href="#%e3%83%88%e3%83%ac%e3%83%bc%e3%82%b5%e3%83%93%e3%83%aa%e3%83%86%e3%82%a3"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="使い分け"&gt;使い分け&lt;a class="anchor" href="#%e4%bd%bf%e3%81%84%e5%88%86%e3%81%91"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;ID&lt;/th&gt;
 &lt;th style="text-align: left"&gt;目的&lt;/th&gt;
 &lt;th style="text-align: left"&gt;生成場所&lt;/th&gt;
 &lt;th style="text-align: left"&gt;有効期間&lt;/th&gt;
 &lt;th style="text-align: left"&gt;主な用途&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;trace_id&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;横断的トレーサビリティ&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Frontend (セッション開始時)&lt;/td&gt;
 &lt;td style="text-align: left"&gt;セッション全体&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ログ集約・障害調査&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;request_id&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;操作的冪等性&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Frontend (各操作開始時)&lt;/td&gt;
 &lt;td style="text-align: left"&gt;単一操作&lt;/td&gt;
 &lt;td style="text-align: left"&gt;重複実行防止・キャンセル&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="trace_id-の生成と伝播"&gt;trace_id の生成と伝播&lt;a class="anchor" href="#trace_id-%e3%81%ae%e7%94%9f%e6%88%90%e3%81%a8%e4%bc%9d%e6%92%ad"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;用途&lt;/strong&gt;: ユーザーセッション全体の追跡、横断的なログ検索&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生成&lt;/strong&gt;: アプリ初期化時に UUID v4 を一度だけ生成し、グローバル状態で保持&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;伝播&lt;/strong&gt;: 全APIリクエストヘッダー &lt;code&gt;X-Trace-ID&lt;/code&gt; に自動付与&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可視化&lt;/strong&gt;: 開発者ツールで表示し、障害調査時に CloudWatch Logs Insights で横断検索&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="request_id-の生成と管理"&gt;request_id の生成と管理&lt;a class="anchor" href="#request_id-%e3%81%ae%e7%94%9f%e6%88%90%e3%81%a8%e7%ae%a1%e7%90%86"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;用途&lt;/strong&gt;: 操作の重複防止、非同期処理のキャンセル、リトライ制御&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生成&lt;/strong&gt;: 各操作開始時に UUID v4 を都度生成（ファイルアップロード、API呼び出しなど）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;管理&lt;/strong&gt;: 操作単位でローカルに管理し、処理完了まで保持&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;冪等性&lt;/strong&gt;: 同一操作の重複実行を防止するため、request_id を生成して管理&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;キャンセル対応&lt;/strong&gt;: 非同期処理のキャンセル時に request_id を使用して処理を特定&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="プログレスバー"&gt;プログレスバー&lt;a class="anchor" href="#%e3%83%97%e3%83%ad%e3%82%b0%e3%83%ac%e3%82%b9%e3%83%90%e3%83%bc"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="アップロードプログレスバー"&gt;アップロードプログレスバー&lt;a class="anchor" href="#%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89%e3%83%97%e3%83%ad%e3%82%b0%e3%83%ac%e3%82%b9%e3%83%90%e3%83%bc"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="mermaid"&gt;stateDiagram-v2
 [*] --&amp;gt; Idle: アップロード開始
 Idle --&amp;gt; Uploading: ファイル選択
 Uploading --&amp;gt; Processing: アップロード完了
 Uploading --&amp;gt; Error: エラー発生
 Processing --&amp;gt; Success: 処理完了
 Processing --&amp;gt; Error: エラー発生
 Error --&amp;gt; Idle: リトライ or キャンセル
 Success --&amp;gt; Idle: 完了&lt;/pre&gt;&lt;h3 id="プログレスバーの仕様"&gt;プログレスバーの仕様&lt;a class="anchor" href="#%e3%83%97%e3%83%ad%e3%82%b0%e3%83%ac%e3%82%b9%e3%83%90%e3%83%bc%e3%81%ae%e4%bb%95%e6%a7%98"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;表示条件&lt;/strong&gt;: ファイルアップロード時、API リクエスト時&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;進捗表示&lt;/strong&gt;: パーセンテージと残り時間を表示&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;キャンセル機能&lt;/strong&gt;: ユーザーがいつでもキャンセル可能&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;エラー表示&lt;/strong&gt;: エラー発生時に詳細メッセージを表示&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="懸案事項"&gt;懸案事項&lt;a class="anchor" href="#%e6%87%b8%e6%a1%88%e4%ba%8b%e9%a0%85"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="技術的懸案"&gt;技術的懸案&lt;a class="anchor" href="#%e6%8a%80%e8%a1%93%e7%9a%84%e6%87%b8%e6%a1%88"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ブラウザ互換性&lt;/strong&gt;: AbortController の IE サポート&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ネットワーク切断&lt;/strong&gt;: オフライン時の処理方針&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="uiux-懸案"&gt;UI/UX 懸案&lt;a class="anchor" href="#uiux-%e6%87%b8%e6%a1%88"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;エラーメッセージ&lt;/strong&gt;: ユーザーフレンドリーなエラー表現&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;アクセシビリティ&lt;/strong&gt;: スクリーンリーダー対応&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="tbd"&gt;TBD&lt;a class="anchor" href="#tbd"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="機能仕様"&gt;機能仕様&lt;a class="anchor" href="#%e6%a9%9f%e8%83%bd%e4%bb%95%e6%a7%98"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;ファイルサイズ制限&lt;/strong&gt;: 具体的な上限値の決定&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;同時アップロード数&lt;/strong&gt;: 複数ファイル同時アップロードの制限&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;プレビュー機能&lt;/strong&gt;: アップロード前の画像プレビュー要否&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="技術仕様"&gt;技術仕様&lt;a class="anchor" href="#%e6%8a%80%e8%a1%93%e4%bb%95%e6%a7%98"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;CDN 対応&lt;/strong&gt;: 静的アセットの配信戦略&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;PWA 対応&lt;/strong&gt;: Service Worker の導入要否&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;監視体制&lt;/strong&gt;: エラーログ収集方法&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="セキュリティ仕様"&gt;セキュリティ仕様&lt;a class="anchor" href="#%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e4%bb%95%e6%a7%98"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;CSP ポリシー&lt;/strong&gt;: Content Security Policy の詳細&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;XSS 対策&lt;/strong&gt;: 入力値検証の範囲&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;CSRF 対策&lt;/strong&gt;: トークン管理方式&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="非同期処理の制御"&gt;非同期処理の制御&lt;a class="anchor" href="#%e9%9d%9e%e5%90%8c%e6%9c%9f%e5%87%a6%e7%90%86%e3%81%ae%e5%88%b6%e5%be%a1"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;キャンセル機構&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>APIメッセージ一覧表</title><link>https://Hitamuki.github.io/image-upload/design/api/2_api%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E4%B8%80%E8%A6%A7%E8%A1%A8/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/api/2_api%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E4%B8%80%E8%A6%A7%E8%A1%A8/</guid><description>&lt;h1 id="apiメッセージ一覧表"&gt;APIメッセージ一覧表&lt;a class="anchor" href="#api%e3%83%a1%e3%83%83%e3%82%bb%e3%83%bc%e3%82%b8%e4%b8%80%e8%a6%a7%e8%a1%a8"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;APIレスポンスに含まれるエラーメッセージを管理する。&lt;code&gt;{変数名}&lt;/code&gt; は動的に置換される。&lt;/p&gt;
&lt;h2 id="共通メッセージ"&gt;共通メッセージ&lt;a class="anchor" href="#%e5%85%b1%e9%80%9a%e3%83%a1%e3%83%83%e3%82%bb%e3%83%bc%e3%82%b8"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;全APIで共通して使用するメッセージ。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;メッセージID&lt;/th&gt;
 &lt;th style="text-align: left"&gt;ステータスコード&lt;/th&gt;
 &lt;th style="text-align: left"&gt;code&lt;/th&gt;
 &lt;th style="text-align: left"&gt;メッセージテンプレート&lt;/th&gt;
 &lt;th style="text-align: left"&gt;変数&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-API-C001&lt;/td&gt;
 &lt;td style="text-align: left"&gt;429&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;RATE_LIMIT_EXCEEDED&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;リクエスト数が上限（{limit}回/{window}）を超えました&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;limit&lt;/code&gt;: 上限回数（例: 10）、&lt;code&gt;window&lt;/code&gt;: 時間窓（例: 1分）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-API-C002&lt;/td&gt;
 &lt;td style="text-align: left"&gt;500&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;INTERNAL_SERVER_ERROR&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;サーバーエラーが発生しました&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="個別メッセージ"&gt;個別メッセージ&lt;a class="anchor" href="#%e5%80%8b%e5%88%a5%e3%83%a1%e3%83%83%e3%82%bb%e3%83%bc%e3%82%b8"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;メッセージID&lt;/th&gt;
 &lt;th style="text-align: left"&gt;ステータスコード&lt;/th&gt;
 &lt;th style="text-align: left"&gt;code&lt;/th&gt;
 &lt;th style="text-align: left"&gt;メッセージテンプレート&lt;/th&gt;
 &lt;th style="text-align: left"&gt;変数&lt;/th&gt;
 &lt;th style="text-align: left"&gt;発生条件&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-API-001&lt;/td&gt;
 &lt;td style="text-align: left"&gt;400&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;INVALID_FILE_SIZE&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイルサイズが上限（{maxSize}）を超えています&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;maxSize&lt;/code&gt;: 上限サイズ（例: 5MB）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;fileSize &amp;gt; 5,242,880 bytes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-API-002&lt;/td&gt;
 &lt;td style="text-align: left"&gt;400&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;INVALID_CONTENT_TYPE&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;対応していないファイル形式です（許可形式: {allowedTypes}）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;allowedTypes&lt;/code&gt;: 許可MIMEタイプ一覧（例: jpeg, png, gif, webp）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;contentType が許可リスト外&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-API-003&lt;/td&gt;
 &lt;td style="text-align: left"&gt;409&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;UPLOAD_LIMIT_EXCEEDED&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード可能な枚数の上限（{maxCount}枚）に達しています&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;maxCount&lt;/code&gt;: 上限枚数（例: 5）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード済み枚数 &amp;gt;= 上限&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-API-004&lt;/td&gt;
 &lt;td style="text-align: left"&gt;422&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;INVALID_FILE_BINARY&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイルのバイナリ検証に失敗しました&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;マジックナンバー不一致&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-API-005&lt;/td&gt;
 &lt;td style="text-align: left"&gt;404&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;FILE_NOT_FOUND_ON_S3&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3上にファイルが存在しません&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;HeadObject で対象キーが見つからない&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-API-006&lt;/td&gt;
 &lt;td style="text-align: left"&gt;404&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;IMAGE_NOT_FOUND&lt;/code&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;指定された画像が存在しません（id: {id}）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;id&lt;/code&gt;: リクエストされた画像ID&lt;/td&gt;
 &lt;td style="text-align: left"&gt;DBに対象IDが存在しない&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>画像一覧取得</title><link>https://Hitamuki.github.io/image-upload/design/api/images/api003-upload/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/api/images/api003-upload/</guid><description>&lt;h1 id="画像一覧取得"&gt;画像一覧取得&lt;a class="anchor" href="#%e7%94%bb%e5%83%8f%e4%b8%80%e8%a6%a7%e5%8f%96%e5%be%97"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="id"&gt;ID&lt;a class="anchor" href="#id"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;api003-upload&lt;/p&gt;
&lt;h2 id="エンドポイント"&gt;エンドポイント&lt;a class="anchor" href="#%e3%82%a8%e3%83%b3%e3%83%89%e3%83%9d%e3%82%a4%e3%83%b3%e3%83%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;メソッド&lt;/th&gt;
 &lt;th style="text-align: left"&gt;パス&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;GET&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;/images&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="概要"&gt;概要&lt;a class="anchor" href="#%e6%a6%82%e8%a6%81"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;アップロード済み画像のメタデータ一覧（ID・ファイル名）を取得する。画像の実体（バイナリ・閲覧用URL）はここでは取得しない。ユーザーがリストから画像を選択した時点で api004-upload により個別取得する。&lt;/p&gt;
&lt;h2 id="レスポンス"&gt;レスポンス&lt;a class="anchor" href="#%e3%83%ac%e3%82%b9%e3%83%9d%e3%83%b3%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="200-ok"&gt;200 OK&lt;a class="anchor" href="#200-ok"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;物理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;論理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;型&lt;/th&gt;
 &lt;th style="text-align: center"&gt;必須&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;id&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像ID&lt;/td&gt;
 &lt;td style="text-align: left"&gt;string&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;登録された画像のID&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;fileName&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイル名&lt;/td&gt;
 &lt;td style="text-align: left"&gt;string&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロードされたファイル名&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;createdAt&lt;/td&gt;
 &lt;td style="text-align: left"&gt;作成日時&lt;/td&gt;
 &lt;td style="text-align: left"&gt;string&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ISO-8601形式の作成日時&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;fileName&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;createdAt&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;iso-8601&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ステータスコード"&gt;ステータスコード&lt;a class="anchor" href="#%e3%82%b9%e3%83%86%e3%83%bc%e3%82%bf%e3%82%b9%e3%82%b3%e3%83%bc%e3%83%89"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;コード&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;200&lt;/td&gt;
 &lt;td style="text-align: left"&gt;成功（0件の場合は空配列）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="内部処理シーケンス"&gt;内部処理シーケンス&lt;a class="anchor" href="#%e5%86%85%e9%83%a8%e5%87%a6%e7%90%86%e3%82%b7%e3%83%bc%e3%82%b1%e3%83%b3%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 autonumber
 actor User
 participant Hono as Hono Middleware
 participant Domain as Domain Service
 participant DB as Repository

 User-&amp;gt;&amp;gt;+Hono: 一覧取得リクエスト
 Hono-&amp;gt;&amp;gt;+Domain: 一覧取得リクエスト
 Domain-&amp;gt;&amp;gt;+DB: findAll()
 DB--&amp;gt;&amp;gt;-Domain: [{id, fileName, createdAt}]
 Domain--&amp;gt;&amp;gt;-Hono: Success
 Hono--&amp;gt;&amp;gt;-User: 200 OK&lt;/pre&gt;&lt;h2 id="懸案事項"&gt;懸案事項&lt;a class="anchor" href="#%e6%87%b8%e6%a1%88%e4%ba%8b%e9%a0%85"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="ユーザーごとの絞り込み未実装"&gt;ユーザーごとの絞り込み未実装&lt;a class="anchor" href="#%e3%83%a6%e3%83%bc%e3%82%b6%e3%83%bc%e3%81%94%e3%81%a8%e3%81%ae%e7%b5%9e%e3%82%8a%e8%be%bc%e3%81%bf%e6%9c%aa%e5%ae%9f%e8%a3%85"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;現状&lt;/strong&gt;: 全ユーザーの画像を返却している&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;影響&lt;/strong&gt;: 他ユーザーの画像が見えてしまう、プライバシー問題&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;対応方針&lt;/strong&gt;: 認証ミドルウェアから取得したユーザーIDで絞り込み&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="パフォーマンス問題"&gt;パフォーマンス問題&lt;a class="anchor" href="#%e3%83%91%e3%83%95%e3%82%a9%e3%83%bc%e3%83%9e%e3%83%b3%e3%82%b9%e5%95%8f%e9%a1%8c"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;現状&lt;/strong&gt;: 全件取得でページネーションなし&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;影響&lt;/strong&gt;: 画像数増加時のレスポンス悪化、メモリ消費&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;対応方針&lt;/strong&gt;: ページネーションとキャッシュ導入&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="tbd"&gt;TBD&lt;a class="anchor" href="#tbd"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="並び順とソート機能"&gt;並び順とソート機能&lt;a class="anchor" href="#%e4%b8%a6%e3%81%b3%e9%a0%86%e3%81%a8%e3%82%bd%e3%83%bc%e3%83%88%e6%a9%9f%e8%83%bd"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;作成日順のデフォルトソート&lt;/li&gt;
&lt;li&gt;ファイル名順、サイズ順のソートオプション&lt;/li&gt;
&lt;li&gt;昇順・降順の指定&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="検索機能拡張"&gt;検索機能拡張&lt;a class="anchor" href="#%e6%a4%9c%e7%b4%a2%e6%a9%9f%e8%83%bd%e6%8b%a1%e5%bc%b5"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ファイル名の部分一致検索&lt;/li&gt;
&lt;li&gt;メタデータによる検索（将来的な機能拡張）&lt;/li&gt;
&lt;li&gt;タグによる絞り込み&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>画面メッセージ一覧表</title><link>https://Hitamuki.github.io/image-upload/design/ui/2_%E7%94%BB%E9%9D%A2%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E4%B8%80%E8%A6%A7%E8%A1%A8/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/ui/2_%E7%94%BB%E9%9D%A2%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E4%B8%80%E8%A6%A7%E8%A1%A8/</guid><description>&lt;h1 id="画面メッセージ一覧表"&gt;画面メッセージ一覧表&lt;a class="anchor" href="#%e7%94%bb%e9%9d%a2%e3%83%a1%e3%83%83%e3%82%bb%e3%83%bc%e3%82%b8%e4%b8%80%e8%a6%a7%e8%a1%a8"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;画面上に表示されるすべてのメッセージを管理する。&lt;code&gt;{変数名}&lt;/code&gt; は動的に置換される。&lt;/p&gt;
&lt;h2 id="共通メッセージ"&gt;共通メッセージ&lt;a class="anchor" href="#%e5%85%b1%e9%80%9a%e3%83%a1%e3%83%83%e3%82%bb%e3%83%bc%e3%82%b8"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;操作結果に応じて汎用的に使用するメッセージ。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;メッセージID&lt;/th&gt;
 &lt;th style="text-align: left"&gt;種別&lt;/th&gt;
 &lt;th style="text-align: left"&gt;メッセージテンプレート&lt;/th&gt;
 &lt;th style="text-align: left"&gt;変数&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-C001&lt;/td&gt;
 &lt;td style="text-align: left"&gt;成功&lt;/td&gt;
 &lt;td style="text-align: left"&gt;{target}を登録しました&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;target&lt;/code&gt;: 対象名（例: 画像）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-C002&lt;/td&gt;
 &lt;td style="text-align: left"&gt;成功&lt;/td&gt;
 &lt;td style="text-align: left"&gt;{target}を更新しました&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;target&lt;/code&gt;: 対象名&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-C003&lt;/td&gt;
 &lt;td style="text-align: left"&gt;成功&lt;/td&gt;
 &lt;td style="text-align: left"&gt;{target}を削除しました&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;target&lt;/code&gt;: 対象名&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-C004&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;通信エラーが発生しました。再度お試しください&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-C005&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;サーバーエラーが発生しました。しばらくしてから再度お試しください&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="個別メッセージ"&gt;個別メッセージ&lt;a class="anchor" href="#%e5%80%8b%e5%88%a5%e3%83%a1%e3%83%83%e3%82%bb%e3%83%bc%e3%82%b8"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;メッセージID&lt;/th&gt;
 &lt;th style="text-align: left"&gt;種別&lt;/th&gt;
 &lt;th style="text-align: left"&gt;メッセージテンプレート&lt;/th&gt;
 &lt;th style="text-align: left"&gt;変数&lt;/th&gt;
 &lt;th style="text-align: left"&gt;発生条件&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-001&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;対応していないファイル形式です&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイル拡張子・MIMEタイプが許可リスト外&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-002&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイルサイズが上限（{maxSize}）を超えています&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;maxSize&lt;/code&gt;: 上限サイズ（例: 5MB）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイルサイズが上限超過&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-003&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロードがタイムアウトしました。再度お試しください&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3アップロード時のネットワークタイムアウト&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-004&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロードに失敗しました。URLの有効期限が切れている可能性があります&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Presigned URL有効期限切れ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-005&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイルアクセス権限がありません&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3アクセス権限エラー&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-006&lt;/td&gt;
 &lt;td style="text-align: left"&gt;警告&lt;/td&gt;
 &lt;td style="text-align: left"&gt;最大アップロード数に達しました&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード上限到達時&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;MSG-UI-007&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;署名付きURLの取得に失敗しました。再度お試しください&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Presigned URL取得レスポンスにuploadUrlまたはkeyが含まれない&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>画像アップロード画面</title><link>https://Hitamuki.github.io/image-upload/design/ui/scr001-upload/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/ui/scr001-upload/</guid><description>&lt;h1 id="画像アップロード画面"&gt;画像アップロード画面&lt;a class="anchor" href="#%e7%94%bb%e5%83%8f%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89%e7%94%bb%e9%9d%a2"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="id"&gt;ID&lt;a class="anchor" href="#id"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;scr001-upload&lt;/p&gt;
&lt;h2 id="関連仕様設計"&gt;関連仕様・設計&lt;a class="anchor" href="#%e9%96%a2%e9%80%a3%e4%bb%95%e6%a7%98%e8%a8%ad%e8%a8%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;種別&lt;/th&gt;
 &lt;th style="text-align: left"&gt;ドキュメント&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;要件&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;a href="https://Hitamuki.github.io/image-upload/requirements/req001-upload/"&gt;req001-upload&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;相互作用&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/interaction/ia001-upload/"&gt;ia001-upload&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;API&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api001-upload/"&gt;api001-upload&lt;/a&gt; / &lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api002-upload/"&gt;api002-upload&lt;/a&gt; / &lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api003-upload/"&gt;api003-upload&lt;/a&gt; / &lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api004-upload/"&gt;api004-upload&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="概要"&gt;概要&lt;a class="anchor" href="#%e6%a6%82%e8%a6%81"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ユーザーがローカル端末から画像を選択・プレビューし、S3へアップロードする&lt;/li&gt;
&lt;li&gt;アップロード済み画像のファイル名一覧を表示し、選択した画像をプレビュー閲覧できる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="レイアウト"&gt;レイアウト&lt;a class="anchor" href="#%e3%83%ac%e3%82%a4%e3%82%a2%e3%82%a6%e3%83%88"&gt;#&lt;/a&gt;&lt;/h2&gt;


 
 
 &lt;img src="https://Hitamuki.github.io/image-upload/images/%E7%94%BB%E5%83%8F%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E7%94%BB%E9%9D%A2_hu_b975c7e0bc0b1922.png" alt="画像アップロード画面"&gt;
 


&lt;hr&gt;
&lt;h2 id="遷移"&gt;遷移&lt;a class="anchor" href="#%e9%81%b7%e7%a7%bb"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;単一画面（画面遷移なし）&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="項目"&gt;項目&lt;a class="anchor" href="#%e9%a0%85%e7%9b%ae"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;No&lt;/th&gt;
 &lt;th style="text-align: left"&gt;項目名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;種類&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;th style="text-align: left"&gt;初期状態&lt;/th&gt;
 &lt;th style="text-align: left"&gt;制約&lt;/th&gt;
 &lt;th style="text-align: left"&gt;備考&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;1&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像選択ボタン&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Button / Input&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ローカルからファイル選択ダイアログを開く&lt;/td&gt;
 &lt;td style="text-align: left"&gt;活性&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード済み5枚時はDisabled&lt;/td&gt;
 &lt;td style="text-align: left"&gt;上限到達時は項目4に「最大アップロード数に達しました」を表示&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;2&lt;/td&gt;
 &lt;td style="text-align: left"&gt;選択画像プレビュー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Image&lt;/td&gt;
 &lt;td style="text-align: left"&gt;現在選択されている（未アップロード）画像のプレビュー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;非表示&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイル選択後に表示。アップロード完了後にクリア&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;3&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロードボタン&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Button&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3へのアップロードとDB登録を開始する&lt;/td&gt;
 &lt;td style="text-align: left"&gt;非活性&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像未選択時はDisabled&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;4&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ステータスメッセージ&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Text&lt;/td&gt;
 &lt;td style="text-align: left"&gt;成功・エラー・警告を表示する&lt;/td&gt;
 &lt;td style="text-align: left"&gt;空&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アクション結果に応じて動的に更新&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;5&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像リスト&lt;/td&gt;
 &lt;td style="text-align: left"&gt;List&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード済みのファイル名を一覧表示する&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画面表示時にDBから取得&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画面初期表示時に api003 を呼び出す&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;6&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ギャラリープレビュー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Image&lt;/td&gt;
 &lt;td style="text-align: left"&gt;リストで選択されたアップロード済み画像のプレビュー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;非表示&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;項目5のファイル名クリック時に api004 で取得したURLを表示&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="アクション"&gt;アクション&lt;a class="anchor" href="#%e3%82%a2%e3%82%af%e3%82%b7%e3%83%a7%e3%83%b3"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;No&lt;/th&gt;
 &lt;th style="text-align: left"&gt;アクション名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;トリガー&lt;/th&gt;
 &lt;th style="text-align: left"&gt;処理概要&lt;/th&gt;
 &lt;th style="text-align: left"&gt;期待結果&lt;/th&gt;
 &lt;th style="text-align: left"&gt;API&lt;/th&gt;
 &lt;th style="text-align: left"&gt;備考&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;1&lt;/td&gt;
 &lt;td style="text-align: left"&gt;初期表示&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画面表示時（自動）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード済み画像のメタデータ一覧を取得&lt;/td&gt;
 &lt;td style="text-align: left"&gt;項目5にファイル名リスト表示&lt;/td&gt;
 &lt;td style="text-align: left"&gt;api003&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;2&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイル選択&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像選択ボタン押下&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイル形式・サイズをクライアントバリデーション後、プレビューを生成&lt;/td&gt;
 &lt;td style="text-align: left"&gt;項目2にプレビュー表示、項目3を活性化&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;バリデーション違反時は項目4にエラー表示(MSG-UI-001/MSG-UI-002)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;3&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード実行&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロードボタン押下&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Presigned URL取得 → S3アップロード → メタデータ保存&lt;/td&gt;
 &lt;td style="text-align: left"&gt;項目4に成功メッセージ(MSG-UI-C001)表示、項目5のリスト更新&lt;/td&gt;
 &lt;td style="text-align: left"&gt;api001 → api002&lt;/td&gt;
 &lt;td style="text-align: left"&gt;完了後にアクション5を実行。失敗時はMSG-UI-C004/MSG-UI-C005を表示&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;4&lt;/td&gt;
 &lt;td style="text-align: left"&gt;リスト項目選択&lt;/td&gt;
 &lt;td style="text-align: left"&gt;項目5のファイル名クリック&lt;/td&gt;
 &lt;td style="text-align: left"&gt;選択画像の閲覧用Presigned URLを個別取得して表示&lt;/td&gt;
 &lt;td style="text-align: left"&gt;項目6にプレビュー表示&lt;/td&gt;
 &lt;td style="text-align: left"&gt;api004&lt;/td&gt;
 &lt;td style="text-align: left"&gt;初期表示時は取得しない（遅延取得）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;5&lt;/td&gt;
 &lt;td style="text-align: left"&gt;プレビュークリア&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード完了後（自動）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;選択状態と項目2のプレビューをリセット&lt;/td&gt;
 &lt;td style="text-align: left"&gt;項目3を非活性化&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アクション3の完了後に自動実行&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="バリデーションクライアントサイド"&gt;バリデーション（クライアントサイド）&lt;a class="anchor" href="#%e3%83%90%e3%83%aa%e3%83%87%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e3%82%b5%e3%82%a4%e3%83%89"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;アクション1（ファイル選択時）に実施する。違反時は項目4にエラーメッセージを表示し、リクエストを送信しない。&lt;/p&gt;</description></item><item><title>画像閲覧用URL取得</title><link>https://Hitamuki.github.io/image-upload/design/api/images/api004-upload/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/api/images/api004-upload/</guid><description>&lt;h1 id="画像閲覧用url取得"&gt;画像閲覧用URL取得&lt;a class="anchor" href="#%e7%94%bb%e5%83%8f%e9%96%b2%e8%a6%a7%e7%94%a8url%e5%8f%96%e5%be%97"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="id"&gt;ID&lt;a class="anchor" href="#id"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;api004-upload&lt;/p&gt;
&lt;h2 id="エンドポイント"&gt;エンドポイント&lt;a class="anchor" href="#%e3%82%a8%e3%83%b3%e3%83%89%e3%83%9d%e3%82%a4%e3%83%b3%e3%83%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;メソッド&lt;/th&gt;
 &lt;th style="text-align: left"&gt;パス&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;GET&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;/images/:id&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="概要"&gt;概要&lt;a class="anchor" href="#%e6%a6%82%e8%a6%81"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;指定した画像IDに対応する閲覧用Presigned URLを取得する。&lt;/p&gt;
&lt;h2 id="リクエスト"&gt;リクエスト&lt;a class="anchor" href="#%e3%83%aa%e3%82%af%e3%82%a8%e3%82%b9%e3%83%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="パスパラメータ"&gt;パスパラメータ&lt;a class="anchor" href="#%e3%83%91%e3%82%b9%e3%83%91%e3%83%a9%e3%83%a1%e3%83%bc%e3%82%bf"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;物理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;論理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;型&lt;/th&gt;
 &lt;th style="text-align: center"&gt;必須&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;id&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像ID&lt;/td&gt;
 &lt;td style="text-align: left"&gt;string (UUID)&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;閲覧したい画像のID&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="レスポンス"&gt;レスポンス&lt;a class="anchor" href="#%e3%83%ac%e3%82%b9%e3%83%9d%e3%83%b3%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="200-ok"&gt;200 OK&lt;a class="anchor" href="#200-ok"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;物理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;論理名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;型&lt;/th&gt;
 &lt;th style="text-align: center"&gt;必須&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;url&lt;/td&gt;
 &lt;td style="text-align: left"&gt;閲覧用URL&lt;/td&gt;
 &lt;td style="text-align: left"&gt;string&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像の閲覧用Presigned URL&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;expiresAt&lt;/td&gt;
 &lt;td style="text-align: left"&gt;有効期限&lt;/td&gt;
 &lt;td style="text-align: left"&gt;string&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;URLの有効期限（ISO-8601形式）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;expiresAt&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;iso-8601&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ステータスコード"&gt;ステータスコード&lt;a class="anchor" href="#%e3%82%b9%e3%83%86%e3%83%bc%e3%82%bf%e3%82%b9%e3%82%b3%e3%83%bc%e3%83%89"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;コード&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;200&lt;/td&gt;
 &lt;td style="text-align: left"&gt;成功&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;404&lt;/td&gt;
 &lt;td style="text-align: left"&gt;指定IDの画像が存在しない&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="内部処理シーケンス"&gt;内部処理シーケンス&lt;a class="anchor" href="#%e5%86%85%e9%83%a8%e5%87%a6%e7%90%86%e3%82%b7%e3%83%bc%e3%82%b1%e3%83%b3%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 autonumber
 actor User
 participant Hono as Hono Middleware
 participant Domain as Domain Service
 participant DB as Repository
 participant S3 as S3 Client

 User-&amp;gt;&amp;gt;+Hono: 閲覧URLリクエスト (id)
 Hono-&amp;gt;&amp;gt;+Domain: 閲覧URLリクエスト (id)
 Domain-&amp;gt;&amp;gt;+DB: findById(id)
 DB--&amp;gt;&amp;gt;-Domain: image (s3Key)
 Domain-&amp;gt;&amp;gt;+S3: getSignedUrl (GetObject, s3Key, expires=3600)
 S3--&amp;gt;&amp;gt;-Domain: url
 Domain--&amp;gt;&amp;gt;-Hono: Success (url, expiresAt)
 Hono--&amp;gt;&amp;gt;-User: 200 OK&lt;/pre&gt;&lt;h2 id="懸案事項"&gt;懸案事項&lt;a class="anchor" href="#%e6%87%b8%e6%a1%88%e4%ba%8b%e9%a0%85"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="アクセス権限の未実装"&gt;アクセス権限の未実装&lt;a class="anchor" href="#%e3%82%a2%e3%82%af%e3%82%bb%e3%82%b9%e6%a8%a9%e9%99%90%e3%81%ae%e6%9c%aa%e5%ae%9f%e8%a3%85"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;現状&lt;/strong&gt;: 画像IDさえ知っていれば誰でも閲覧可能&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;影響&lt;/strong&gt;: 他ユーザーのプライベート画像にアクセス可能になる&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;対応方針&lt;/strong&gt;: 画像所有者のみアクセス許可の認可チェック&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="tbd"&gt;TBD&lt;a class="anchor" href="#tbd"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="アクセス制御の細粒度化"&gt;アクセス制御の細粒度化&lt;a class="anchor" href="#%e3%82%a2%e3%82%af%e3%82%bb%e3%82%b9%e5%88%b6%e5%be%a1%e3%81%ae%e7%b4%b0%e7%b2%92%e5%ba%a6%e5%8c%96"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;画像ごとの公開・非公開設定&lt;/li&gt;
&lt;li&gt;特定ユーザーへのアクセス許可機能&lt;/li&gt;
&lt;li&gt;一時的なアクセスURL発行&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="キャッシュ戦略"&gt;キャッシュ戦略&lt;a class="anchor" href="#%e3%82%ad%e3%83%a3%e3%83%83%e3%82%b7%e3%83%a5%e6%88%a6%e7%95%a5"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;CloudFrontによるCDNキャッシュ&lt;/li&gt;
&lt;li&gt;閲覧URLのキャッシュ期間最適化&lt;/li&gt;
&lt;li&gt;画像の最適化（リサイズ）とキャッシュ&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ER図</title><link>https://Hitamuki.github.io/image-upload/design/db/er%E5%9B%B3/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/db/er%E5%9B%B3/</guid><description>&lt;h1 id="er図"&gt;ER図&lt;a class="anchor" href="#er%e5%9b%b3"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="関連ドキュメント"&gt;関連ドキュメント&lt;a class="anchor" href="#%e9%96%a2%e9%80%a3%e3%83%89%e3%82%ad%e3%83%a5%e3%83%a1%e3%83%b3%e3%83%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/db/%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E5%AE%9A%E7%BE%A9%E6%9B%B8/"&gt;テーブル定義書&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="er図-1"&gt;ER図&lt;a class="anchor" href="#er%e5%9b%b3-1"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="mermaid"&gt;erDiagram
 images {
 string id PK &amp;#34;UUID v4&amp;#34;
 string file_name &amp;#34;ファイル名&amp;#34;
 int file_size &amp;#34;ファイルサイズ&amp;#34;
 string content_type &amp;#34;MIMEタイプ&amp;#34;
 string s3_key UK &amp;#34;S3上の保存パス&amp;#34;
 datetime created_at &amp;#34;作成日時&amp;#34;
 datetime updated_at &amp;#34;更新日時&amp;#34;
 }&lt;/pre&gt;</description></item><item><title>アーキテクチャ図</title><link>https://Hitamuki.github.io/image-upload/design/common/%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E5%9B%B3/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/common/%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E5%9B%B3/</guid><description>&lt;h1 id="アーキテクチャ図"&gt;アーキテクチャ図&lt;a class="anchor" href="#%e3%82%a2%e3%83%bc%e3%82%ad%e3%83%86%e3%82%af%e3%83%81%e3%83%a3%e5%9b%b3"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="概要"&gt;概要&lt;a class="anchor" href="#%e6%a6%82%e8%a6%81"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;本システムの全体構造、モノレポ内の各パッケージの責務、およびそれらの依存関係を定義する。
本システムはモノレポ構成を採用し、関心の分離（SoC）を徹底する。&lt;/p&gt;
&lt;h2 id="レイヤー構造図"&gt;レイヤー構造図&lt;a class="anchor" href="#%e3%83%ac%e3%82%a4%e3%83%a4%e3%83%bc%e6%a7%8b%e9%80%a0%e5%9b%b3"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="mermaid"&gt;graph TD
 subgraph Apps [&amp;#34;apps/ (アプリケーション層)&amp;#34;]
 Frontend[frontend: React / React Router]
 Backend[backend: Hono / Bun]
 end

 subgraph Packages [&amp;#34;packages/ (共通基盤・ドメイン層)&amp;#34;]
 UI[ui: shadcn/uiベース共通コンポーネント]
 API[api: Orval 生成 Client]
 Domain[domain: ビジネスロジック・Entity/Policy]
 DB[db: Prisma/Repository]
 Infra[infra: Terraform/AWS設定]
 Shared[shared: Logger/Config/TraceID]
 end

 %% 依存関係
 Frontend --&amp;gt; UI
 Frontend --&amp;gt; API
 Frontend --&amp;gt; Shared
 
 Backend --&amp;gt; Domain
 Backend --&amp;gt; DB
 Backend --&amp;gt; Shared
 
 Domain --&amp;gt; DB
 Domain --&amp;gt; Shared
 
 DB --&amp;gt; Shared
 
 API -. &amp;#34;OpenAPIから生成&amp;#34; .-&amp;gt; Backend&lt;/pre&gt;&lt;h2 id="各パッケージの責務"&gt;各パッケージの責務&lt;a class="anchor" href="#%e5%90%84%e3%83%91%e3%83%83%e3%82%b1%e3%83%bc%e3%82%b8%e3%81%ae%e8%b2%ac%e5%8b%99"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;apps/frontend&lt;/strong&gt;: UI/UXの構築。React Routerによるルーティング、TanStack Queryによる状態管理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;apps/backend&lt;/strong&gt;: HonoによるAPIエンドポイント。ミドルウェア（CORS, Logger, TraceID）の適用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;packages/domain&lt;/strong&gt;: ビジネスロジックの中核。Entity, Value Object, Domain Service, およびポリシーの強制。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;packages/db&lt;/strong&gt;: データアクセス層。Prisma Clientを用いたデータベース操作、Repositoryパターン。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;packages/ui&lt;/strong&gt;: デザインシステムに基づく共通UIコンポーネント群。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;packages/api&lt;/strong&gt;: OpenAPI (specs/api) から生成されたフロントエンド用APIクライアント。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;packages/infra&lt;/strong&gt;: TerraformによるAWSリソース（S3, CloudFront, Lambda等）のコード化。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;packages/shared&lt;/strong&gt;: trace_id (UUID v4)、Pinoによる構造化ロガー、共通設定等の横断的関心事。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>システム構成図</title><link>https://Hitamuki.github.io/image-upload/design/common/%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E6%A7%8B%E6%88%90%E5%9B%B3/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/common/%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E6%A7%8B%E6%88%90%E5%9B%B3/</guid><description>&lt;h1 id="システム構成図"&gt;システム構成図&lt;a class="anchor" href="#%e3%82%b7%e3%82%b9%e3%83%86%e3%83%a0%e6%a7%8b%e6%88%90%e5%9b%b3"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="概要"&gt;概要&lt;a class="anchor" href="#%e6%a6%82%e8%a6%81"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;本システムのデプロイメント環境および AWS インフラストラクチャの構成を定義する。&lt;/p&gt;
&lt;h2 id="インフラ構成図"&gt;インフラ構成図&lt;a class="anchor" href="#%e3%82%a4%e3%83%b3%e3%83%95%e3%83%a9%e6%a7%8b%e6%88%90%e5%9b%b3"&gt;#&lt;/a&gt;&lt;/h2&gt;


 
 &lt;img src="https://Hitamuki.github.io/image-upload/images/AWS%E7%92%B0%E5%A2%83%E6%A7%8B%E6%88%90%E5%9B%B3.drawio.svg" alt="AWS環境構成図"&gt;
 


&lt;h2 id="使用サービス"&gt;使用サービス&lt;a class="anchor" href="#%e4%bd%bf%e7%94%a8%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;サービス名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;役割・用途&lt;/th&gt;
 &lt;th style="text-align: left"&gt;スペック・設定&lt;/th&gt;
 &lt;th style="text-align: left"&gt;月額料金（円）&lt;/th&gt;
 &lt;th style="text-align: left"&gt;補足&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Amazon CloudFront&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;CDN / SPA配信 / APIルーティング&lt;/td&gt;
 &lt;td style="text-align: left"&gt;価格クラス100&lt;/td&gt;
 &lt;td style="text-align: left"&gt;約1,500円&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エッジでのキャッシュ、HTTPS終端、WAF連携&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Amazon S3 (Static Assets)&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;フロントエンド(SPA)ホスティング&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Standard Storage, 5GB保存&lt;/td&gt;
 &lt;td style="text-align: left"&gt;約500円&lt;/td&gt;
 &lt;td style="text-align: left"&gt;HTML / JS / CSS 等の静的ファイル配信&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Amazon S3 (Image Storage)&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像ストレージ&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Standard Storage, 20GB保存&lt;/td&gt;
 &lt;td style="text-align: left"&gt;約500円&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード画像の実体保存（Presigned URL方式）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;API Gateway&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;APIエンドポイント管理&lt;/td&gt;
 &lt;td style="text-align: left"&gt;REST API, 10万リクエスト/月&lt;/td&gt;
 &lt;td style="text-align: left"&gt;約300円&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Lambda Proxy統合、レート制限、認証&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;AWS Lambda (Hono / Bun)&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;APIバックエンド&lt;/td&gt;
 &lt;td style="text-align: left"&gt;128MB, 0.5秒平均, 10万実行/月&lt;/td&gt;
 &lt;td style="text-align: left"&gt;無料&lt;/td&gt;
 &lt;td style="text-align: left"&gt;サーバーレス実行環境。Prisma ORMによるDB操作&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Amazon RDS (PostgreSQL)&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;マネージドデータベース&lt;/td&gt;
 &lt;td style="text-align: left"&gt;db.t3.micro, Single-AZ構成&lt;/td&gt;
 &lt;td style="text-align: left"&gt;約4,000円&lt;/td&gt;
 &lt;td style="text-align: left"&gt;画像のメタデータ・管理情報の永続化&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;AWS WAF&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Webアプリケーションファイアウォール&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Web ACL, 基本料金&lt;/td&gt;
 &lt;td style="text-align: left"&gt;約5,000円&lt;/td&gt;
 &lt;td style="text-align: left"&gt;レート制限、IP制限、SQLi/XSS等の攻撃防御&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;AWS Secrets Manager&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;秘密情報管理&lt;/td&gt;
 &lt;td style="text-align: left"&gt;標準, 5シークレット&lt;/td&gt;
 &lt;td style="text-align: left"&gt;約200円&lt;/td&gt;
 &lt;td style="text-align: left"&gt;DB認証情報、APIキー等のセキュアな保管&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Amazon CloudWatch Logs&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ログ管理&lt;/td&gt;
 &lt;td style="text-align: left"&gt;標準, 5GBログ&lt;/td&gt;
 &lt;td style="text-align: left"&gt;約750円&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Pinoによる構造化ログ(JSON)の収集・蓄積&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Amazon CloudWatch Alarms&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;監視・アラート&lt;/td&gt;
 &lt;td style="text-align: left"&gt;5個アラーム&lt;/td&gt;
 &lt;td style="text-align: left"&gt;約150円&lt;/td&gt;
 &lt;td style="text-align: left"&gt;メトリクス監視に基づいた異常検知・通知&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;AWS X-Ray&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;分散トレーシング&lt;/td&gt;
 &lt;td style="text-align: left"&gt;標準, 10万トレース&lt;/td&gt;
 &lt;td style="text-align: left"&gt;約100円&lt;/td&gt;
 &lt;td style="text-align: left"&gt;リクエストの追跡、パフォーマンスボトルネックの可視化&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;NAT Gateway&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ネットワーク変換&lt;/td&gt;
 &lt;td style="text-align: left"&gt;1AZ, 10GB転送/月&lt;/td&gt;
 &lt;td style="text-align: left"&gt;約500円&lt;/td&gt;
 &lt;td style="text-align: left"&gt;プライベートサブネットからインターネットへの外部通信&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Internet Gateway&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;VPCの出口&lt;/td&gt;
 &lt;td style="text-align: left"&gt;標準&lt;/td&gt;
 &lt;td style="text-align: left"&gt;無料&lt;/td&gt;
 &lt;td style="text-align: left"&gt;VPCとインターネット間の通信を可能にするゲートウェイ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;合計&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;-&lt;/td&gt;
 &lt;td style="text-align: left"&gt;-&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;約8,000円&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;個人開発想定（月1,000ユーザー未満）&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="ネットワークセキュリティ"&gt;ネットワーク・セキュリティ&lt;a class="anchor" href="#%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%af%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HTTPS&lt;/strong&gt;: 全通信は SSL/TLS で暗号化される。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CORS&lt;/strong&gt;: S3 バケットの設定により、特定のオリジンからの Direct Upload のみを許可する。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VPC (Virtual Private Cloud)&lt;/strong&gt;: RDS 等のバックエンドリソースはプライベートサブネット内に配置し、不必要な外部露出を避ける（Terraform にて定義）。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>セキュリティ設計指針</title><link>https://Hitamuki.github.io/image-upload/design/common/%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E8%A8%AD%E8%A8%88%E6%8C%87%E9%87%9D/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/common/%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E8%A8%AD%E8%A8%88%E6%8C%87%E9%87%9D/</guid><description>&lt;h1 id="セキュリティ設計指針"&gt;セキュリティ設計指針&lt;a class="anchor" href="#%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e8%a8%ad%e8%a8%88%e6%8c%87%e9%87%9d"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="1-基本方針"&gt;1. 基本方針&lt;a class="anchor" href="#1-%e5%9f%ba%e6%9c%ac%e6%96%b9%e9%87%9d"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;API定義書（OpenAPI等）で定義された制約を厳格に適用し、脆弱性の混入を未然に防ぐ。&lt;/p&gt;
&lt;h2 id="2-認証認可-authentication--authorization"&gt;2. 認証・認可 (Authentication &amp;amp; Authorization)&lt;a class="anchor" href="#2-%e8%aa%8d%e8%a8%bc%e8%aa%8d%e5%8f%af-authentication--authorization"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;認証&lt;/strong&gt;: MVPフェーズでは実施しない。将来的にIDP（Firebase Auth等）の導入を検討する。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;認可&lt;/strong&gt;: MVPフェーズでは実施しない。全てのリクエストを全権限ユーザーとして扱う。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="3-通信の保護"&gt;3. 通信の保護&lt;a class="anchor" href="#3-%e9%80%9a%e4%bf%a1%e3%81%ae%e4%bf%9d%e8%ad%b7"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;全ての外部通信は TLS 1.2 以上（HTTPS）で暗号化する。&lt;/li&gt;
&lt;li&gt;HSTS (HTTP Strict Transport Security) を有効化し、常時SSL化を強制する。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="4-入力値の検証とサニタイズ"&gt;4. 入力値の検証とサニタイズ&lt;a class="anchor" href="#4-%e5%85%a5%e5%8a%9b%e5%80%a4%e3%81%ae%e6%a4%9c%e8%a8%bc%e3%81%a8%e3%82%b5%e3%83%8b%e3%82%bf%e3%82%a4%e3%82%ba"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;バリデーション&lt;/strong&gt;: APIスペックに基づき、型、長さ、形式（正規表現）をリクエスト受領時に即座に検証する。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SQLインジェクション対策&lt;/strong&gt;: ORMの利用を原則とし、生のSQLを記述する場合は必ず静的プリペアードステートメント（プレースホルダ）を使用する。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;XSS対策&lt;/strong&gt;: フロントエンド（React/Next.js等）のエスケープ機能を活用し、サーバー側でも適切なContent-Type（application/json等）を強制する。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="5-データの暗号化"&gt;5. データの暗号化&lt;a class="anchor" href="#5-%e3%83%87%e3%83%bc%e3%82%bf%e3%81%ae%e6%9a%97%e5%8f%b7%e5%8c%96"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;保存時 (At Rest)&lt;/strong&gt;: データベースおよびオブジェクトストレージ（S3等）の暗号化を有効にする。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;機密情報&lt;/strong&gt;: APIキーやパスワード等は、暗号化した状態で環境変数またはシークレット管理ツールで管理する。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="6-秘匿情報の管理"&gt;6. 秘匿情報の管理&lt;a class="anchor" href="#6-%e7%a7%98%e5%8c%bf%e6%83%85%e5%a0%b1%e3%81%ae%e7%ae%a1%e7%90%86"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ソースコード内にパスワードやAPIキーを直接記述（ハードコード）することを厳禁とする。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.env.example&lt;/code&gt; を提供し、実際の値はシークレット管理サービスから動的に取得する。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>テーブル定義書</title><link>https://Hitamuki.github.io/image-upload/design/db/%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E5%AE%9A%E7%BE%A9%E6%9B%B8/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/db/%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E5%AE%9A%E7%BE%A9%E6%9B%B8/</guid><description>&lt;h1 id="テーブル定義書"&gt;テーブル定義書&lt;a class="anchor" href="#%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab%e5%ae%9a%e7%be%a9%e6%9b%b8"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="関連ドキュメント"&gt;関連ドキュメント&lt;a class="anchor" href="#%e9%96%a2%e9%80%a3%e3%83%89%e3%82%ad%e3%83%a5%e3%83%a1%e3%83%b3%e3%83%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/db/er%E5%9B%B3/"&gt;ER図&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="images-テーブル"&gt;images テーブル&lt;a class="anchor" href="#images-%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="テーブル情報"&gt;テーブル情報&lt;a class="anchor" href="#%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab%e6%83%85%e5%a0%b1"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;項目&lt;/th&gt;
 &lt;th style="text-align: left"&gt;値&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;テーブル名&lt;/td&gt;
 &lt;td style="text-align: left"&gt;&lt;code&gt;images&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;概要&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロードされた画像のメタデータを管理する&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;スキーマ&lt;/td&gt;
 &lt;td style="text-align: left"&gt;public&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="カラム情報"&gt;カラム情報&lt;a class="anchor" href="#%e3%82%ab%e3%83%a9%e3%83%a0%e6%83%85%e5%a0%b1"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;カラム名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;型&lt;/th&gt;
 &lt;th style="text-align: center"&gt;NOT NULL&lt;/th&gt;
 &lt;th style="text-align: left"&gt;デフォルト&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;id&lt;/td&gt;
 &lt;td style="text-align: left"&gt;VARCHAR(36)&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;主キー（UUID v4）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;file_name&lt;/td&gt;
 &lt;td style="text-align: left"&gt;VARCHAR(255)&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイル名&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;file_size&lt;/td&gt;
 &lt;td style="text-align: left"&gt;INTEGER&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;ファイルサイズ（bytes）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;content_type&lt;/td&gt;
 &lt;td style="text-align: left"&gt;VARCHAR(50)&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;MIMEタイプ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;s3_key&lt;/td&gt;
 &lt;td style="text-align: left"&gt;VARCHAR(512)&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3上の保存パス&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;created_at&lt;/td&gt;
 &lt;td style="text-align: left"&gt;TIMESTAMP&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;CURRENT_TIMESTAMP&lt;/td&gt;
 &lt;td style="text-align: left"&gt;作成日時&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;updated_at&lt;/td&gt;
 &lt;td style="text-align: left"&gt;TIMESTAMP&lt;/td&gt;
 &lt;td style="text-align: center"&gt;✓&lt;/td&gt;
 &lt;td style="text-align: left"&gt;CURRENT_TIMESTAMP&lt;/td&gt;
 &lt;td style="text-align: left"&gt;更新日時（自動更新）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="インデックス情報"&gt;インデックス情報&lt;a class="anchor" href="#%e3%82%a4%e3%83%b3%e3%83%87%e3%83%83%e3%82%af%e3%82%b9%e6%83%85%e5%a0%b1"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;インデックス名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;カラム&lt;/th&gt;
 &lt;th style="text-align: left"&gt;種類&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;images_pkey&lt;/td&gt;
 &lt;td style="text-align: left"&gt;id&lt;/td&gt;
 &lt;td style="text-align: left"&gt;PRIMARY KEY&lt;/td&gt;
 &lt;td style="text-align: left"&gt;主キーインデックス&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;images_s3_key_key&lt;/td&gt;
 &lt;td style="text-align: left"&gt;s3_key&lt;/td&gt;
 &lt;td style="text-align: left"&gt;UNIQUE&lt;/td&gt;
 &lt;td style="text-align: left"&gt;重複アップロード防止&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;images_created_at_idx&lt;/td&gt;
 &lt;td style="text-align: left"&gt;created_at&lt;/td&gt;
 &lt;td style="text-align: left"&gt;INDEX&lt;/td&gt;
 &lt;td style="text-align: left"&gt;一覧表示のソート用&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="制約情報"&gt;制約情報&lt;a class="anchor" href="#%e5%88%b6%e7%b4%84%e6%83%85%e5%a0%b1"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;制約名&lt;/th&gt;
 &lt;th style="text-align: left"&gt;種類&lt;/th&gt;
 &lt;th style="text-align: left"&gt;カラム&lt;/th&gt;
 &lt;th style="text-align: left"&gt;条件&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;images_pkey&lt;/td&gt;
 &lt;td style="text-align: left"&gt;PRIMARY KEY&lt;/td&gt;
 &lt;td style="text-align: left"&gt;id&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;主キー制約&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;images_s3_key_key&lt;/td&gt;
 &lt;td style="text-align: left"&gt;UNIQUE&lt;/td&gt;
 &lt;td style="text-align: left"&gt;s3_key&lt;/td&gt;
 &lt;td style="text-align: left"&gt;—&lt;/td&gt;
 &lt;td style="text-align: left"&gt;S3パスの一意性&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="外部キー情報"&gt;外部キー情報&lt;a class="anchor" href="#%e5%a4%96%e9%83%a8%e3%82%ad%e3%83%bc%e6%83%85%e5%a0%b1"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;現バージョンでは外部キーなし。ユーザー管理機能追加時に &lt;code&gt;user_id&lt;/code&gt; → &lt;code&gt;users.id&lt;/code&gt; の外部キーを追加予定。&lt;/p&gt;</description></item><item><title>ログ設計指針</title><link>https://Hitamuki.github.io/image-upload/design/common/%E3%83%AD%E3%82%B0%E8%A8%AD%E8%A8%88%E6%8C%87%E9%87%9D/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/common/%E3%83%AD%E3%82%B0%E8%A8%AD%E8%A8%88%E6%8C%87%E9%87%9D/</guid><description>&lt;h1 id="ログ設計指針"&gt;ログ設計指針&lt;a class="anchor" href="#%e3%83%ad%e3%82%b0%e8%a8%ad%e8%a8%88%e6%8c%87%e9%87%9d"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="1-出力形式"&gt;1. 出力形式&lt;a class="anchor" href="#1-%e5%87%ba%e5%8a%9b%e5%bd%a2%e5%bc%8f"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;ログの集約と解析を容易にするため、全てのログを &lt;strong&gt;JSON形式&lt;/strong&gt; で標準出力（stdout）に出力する。&lt;/p&gt;
&lt;h2 id="2-ログレベル"&gt;2. ログレベル&lt;a class="anchor" href="#2-%e3%83%ad%e3%82%b0%e3%83%ac%e3%83%99%e3%83%ab"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;レベル&lt;/th&gt;
 &lt;th style="text-align: left"&gt;説明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;FATAL&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;システム停止を伴う致命的なエラー。即時通知対象。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;ERROR&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;継続は可能だが、期待しない動作が発生したエラー。要調査。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;WARN&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;異常ではないが、リトライが発生した際やリソース不足の予兆など。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;INFO&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;業務上の重要なイベント（ファイルアップロード完了等）。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;DEBUG&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;開発時のデバッグ情報。本番環境では出力しない。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="3-共通ログ項目"&gt;3. 共通ログ項目&lt;a class="anchor" href="#3-%e5%85%b1%e9%80%9a%e3%83%ad%e3%82%b0%e9%a0%85%e7%9b%ae"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;全てのログには以下のフィールドを必須または推奨で含める。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;timestamp&lt;/code&gt;: ISO8601形式の時刻&lt;/li&gt;
&lt;li&gt;&lt;code&gt;level&lt;/code&gt;: ログレベル&lt;/li&gt;
&lt;li&gt;&lt;code&gt;trace_id&lt;/code&gt;: リクエスト間を横断して追跡するためのユニークなID（相関ID）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;request_id&lt;/code&gt;: 単一操作を識別するためのユニークなID（冪等性制御・キャンセル用）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;user_id&lt;/code&gt;: ユーザー識別子（MVPでは対象外とし、nullまたは固定値を出力する）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;message&lt;/code&gt;: ログの内容（人間が読める形式）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;context&lt;/code&gt;: 関連する補足データ（メタデータ）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="4-追跡可能性observability"&gt;4. 追跡可能性（Observability）&lt;a class="anchor" href="#4-%e8%bf%bd%e8%b7%a1%e5%8f%af%e8%83%bd%e6%80%a7observability"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;モノレポ内の各サービス間で &lt;code&gt;X-Trace-Id&lt;/code&gt; ヘッダーを伝播させ、フロントエンドからバックエンドまでの処理を単一のトレースIDで追跡可能にする。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X-Request-Id&lt;/code&gt; ヘッダーも併せて伝播させ、単一操作のログを特定して追跡可能にする。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="5-ログ出力の禁止事項-piiの保護"&gt;5. ログ出力の禁止事項 (PIIの保護)&lt;a class="anchor" href="#5-%e3%83%ad%e3%82%b0%e5%87%ba%e5%8a%9b%e3%81%ae%e7%a6%81%e6%ad%a2%e4%ba%8b%e9%a0%85-pii%e3%81%ae%e4%bf%9d%e8%ad%b7"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;以下の情報は、セキュリティおよびプライバシー保護のため、ログに出力してはならない。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;パスワード、アクセストークン、シークレットキー&lt;/li&gt;
&lt;li&gt;クレジットカード情報&lt;/li&gt;
&lt;li&gt;個人情報（氏名、生年月日、住所、電話番号等）を直接特定できる情報
&lt;ul&gt;
&lt;li&gt;必要がある場合はハッシュ化またはマスキング処理（例: &lt;code&gt;k****@example.com&lt;/code&gt;）を行う。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="6-ログの保存とモニタリング"&gt;6. ログの保存とモニタリング&lt;a class="anchor" href="#6-%e3%83%ad%e3%82%b0%e3%81%ae%e4%bf%9d%e5%ad%98%e3%81%a8%e3%83%a2%e3%83%8b%e3%82%bf%e3%83%aa%e3%83%b3%e3%82%b0"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;保存期間&lt;/strong&gt;: 運用要件に基づき、30日間（またはそれ以上）を標準とする。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;監視&lt;/strong&gt;: ERROR以上のログが発生した場合、Slack等のチャットツールへ通知を行う。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>画像アップロード</title><link>https://Hitamuki.github.io/image-upload/design/security/sec001-upload/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/security/sec001-upload/</guid><description>&lt;h1 id="画像アップロード"&gt;画像アップロード&lt;a class="anchor" href="#%e7%94%bb%e5%83%8f%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="id"&gt;ID&lt;a class="anchor" href="#id"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;sec001-upload&lt;/p&gt;
&lt;h2 id="関連仕様設計"&gt;関連仕様・設計&lt;a class="anchor" href="#%e9%96%a2%e9%80%a3%e4%bb%95%e6%a7%98%e8%a8%ad%e8%a8%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://Hitamuki.github.io/image-upload/requirements/req001-upload/"&gt;req001-upload&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/interaction/ia001-upload/"&gt;ia001-upload&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/common/%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E8%A8%AD%E8%A8%88%E6%8C%87%E9%87%9D/"&gt;セキュリティ設計指針&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="概要"&gt;概要&lt;a class="anchor" href="#%e6%a6%82%e8%a6%81"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;画像アップロード時における脅威と、それに対する具体的な防御策を定義する。&lt;/p&gt;
&lt;h2 id="セキュリティリスク分析"&gt;セキュリティリスク分析&lt;a class="anchor" href="#%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%83%aa%e3%82%b9%e3%82%af%e5%88%86%e6%9e%90"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="1-ファイル形式偽装攻撃"&gt;1. ファイル形式偽装攻撃&lt;a class="anchor" href="#1-%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e5%bd%a2%e5%bc%8f%e5%81%bd%e8%a3%85%e6%94%bb%e6%92%83"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;脅威&lt;/strong&gt;: 悪意のある実行ファイルを画像ファイルとして偽装してアップロードされる&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;防御策&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;バイナリ検証&lt;/strong&gt;: ファイルの拡張子だけでなく、マジックナンバー（バイナリヘッダ）を読み取り、許可された画像形式であることを検証する&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;許可リスト&lt;/strong&gt;: JPEG、PNG、WebPなど許可された画像形式のみを受け付ける&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ファイル内容スキャン&lt;/strong&gt;: アップロード後にウイルススキャンを実施する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-不正アクセスとデータ漏洩"&gt;2. 不正アクセスとデータ漏洩&lt;a class="anchor" href="#2-%e4%b8%8d%e6%ad%a3%e3%82%a2%e3%82%af%e3%82%bb%e3%82%b9%e3%81%a8%e3%83%87%e3%83%bc%e3%82%bf%e6%bc%8f%e6%b4%a9"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;脅威&lt;/strong&gt;: 認証されていないユーザーによる画像へのアクセスや第三者への漏洩&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;防御策&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;署名付きURL&lt;/strong&gt;: S3へのアップロード・ダウンロードには署名付きURLを使用する&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;有効期限制御&lt;/strong&gt;: 署名付きURLの有効期限を厳格に管理する（アップロード用5分、閲覧用1時間）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最小権限原則&lt;/strong&gt;: アップロードされたファイルはデフォルトで非公開とし、presigned URL経由のみ閲覧可能とする&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-リソース枯渇攻撃"&gt;3. リソース枯渇攻撃&lt;a class="anchor" href="#3-%e3%83%aa%e3%82%bd%e3%83%bc%e3%82%b9%e6%9e%af%e6%b8%87%e6%94%bb%e6%92%83"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;脅威&lt;/strong&gt;: 大量のアップロードによるストレージ容量の枯渇や、サービス妨害&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;防御策&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;サイズ制限&lt;/strong&gt;: ファイルサイズを5MB以下に制限する&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;レート制限&lt;/strong&gt;: IPアドレスまたはユーザーIDごとにアップロード回数を制限する（1分間に10回まで）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;クォータ管理&lt;/strong&gt;: ユーザーごとの総アップロード容量を制限する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="4-中間者攻撃"&gt;4. 中間者攻撃&lt;a class="anchor" href="#4-%e4%b8%ad%e9%96%93%e8%80%85%e6%94%bb%e6%92%83"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;脅威&lt;/strong&gt;: 通信経路でのデータ改ざんや盗聴&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;防御策&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TLS強制&lt;/strong&gt;: 全通信をHTTPS（TLS 1.2以上）に限定する&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;証明書検証&lt;/strong&gt;: SSL/TLS証明書の厳格な検証を行う&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HSTS&lt;/strong&gt;: HTTP Strict Transport Securityを有効化する&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="セキュリティ要件"&gt;セキュリティ要件&lt;a class="anchor" href="#%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e8%a6%81%e4%bb%b6"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="1-多層防御-defense-in-depth"&gt;1. 多層防御 (Defense in Depth)&lt;a class="anchor" href="#1-%e5%a4%9a%e5%b1%a4%e9%98%b2%e5%be%a1-defense-in-depth"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;バイナリ検証&lt;/strong&gt;: システムは、ファイルの拡張子だけでなく、マジックナンバー（バイナリヘッダ）を読み取り、許可された画像形式であることを検証しなければならない。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;署名付きURL&lt;/strong&gt;: S3 へのアップロードには署名付き URL を使用し、その有効期限は発行から &lt;strong&gt;5分間&lt;/strong&gt; としなければならない。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-最小権限の原則"&gt;2. 最小権限の原則&lt;a class="anchor" href="#2-%e6%9c%80%e5%b0%8f%e6%a8%a9%e9%99%90%e3%81%ae%e5%8e%9f%e5%89%87"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;S3 ACL&lt;/strong&gt;: アップロードされたファイルはデフォルトで非公開とし、認可用 presigned URL を介してのみ閲覧可能とする。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-リソース制限"&gt;3. リソース制限&lt;a class="anchor" href="#3-%e3%83%aa%e3%82%bd%e3%83%bc%e3%82%b9%e5%88%b6%e9%99%90"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Size Limit&lt;/strong&gt;: バックエンドは、署名付き URL 発行前にリクエストされたファイルサイズが 5MB 以下であることを厳密に検証しなければならない。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate Limit&lt;/strong&gt;: IP アドレスまたはユーザー ID ごとに、一定時間内のアップロード回数を制限しなければならない（1分間に 10回まで等）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="4-通信セキュリティ"&gt;4. 通信セキュリティ&lt;a class="anchor" href="#4-%e9%80%9a%e4%bf%a1%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TLS強制&lt;/strong&gt;: 全ての通信はHTTPS（TLS 1.2以上）でなければならない。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;証明書検証&lt;/strong&gt;: SSL/TLS証明書の有効性を検証しなければならない。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>画像アップロード機能</title><link>https://Hitamuki.github.io/image-upload/design/infra/infra001-upload/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/infra/infra001-upload/</guid><description>&lt;h1 id="画像アップロード機能"&gt;画像アップロード機能&lt;a class="anchor" href="#%e7%94%bb%e5%83%8f%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89%e6%a9%9f%e8%83%bd"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="id"&gt;ID&lt;a class="anchor" href="#id"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;infra001-upload&lt;/p&gt;
&lt;h2 id="関連仕様設計"&gt;関連仕様・設計&lt;a class="anchor" href="#%e9%96%a2%e9%80%a3%e4%bb%95%e6%a7%98%e8%a8%ad%e8%a8%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://Hitamuki.github.io/image-upload/requirements/req001-upload/"&gt;req001-upload&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/interaction/ia001-upload/"&gt;ia001-upload&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/common/%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E6%A7%8B%E6%88%90%E5%9B%B3/"&gt;システム構成図&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="使用リソース"&gt;使用リソース&lt;a class="anchor" href="#%e4%bd%bf%e7%94%a8%e3%83%aa%e3%82%bd%e3%83%bc%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;リソース&lt;/th&gt;
 &lt;th&gt;用途&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;AWS S3&lt;/td&gt;
 &lt;td&gt;画像ファイルの保存&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="s3-バケット設定"&gt;S3 バケット設定&lt;a class="anchor" href="#s3-%e3%83%90%e3%82%b1%e3%83%83%e3%83%88%e8%a8%ad%e5%ae%9a"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;パブリックアクセス&lt;/strong&gt;: Block Public Access を有効化し、直接公開を禁止する。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;オブジェクトアクセス&lt;/strong&gt;: Presigned URL 経由のみ許可（アップロード用 PUT・閲覧用 GET）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;暗号化&lt;/strong&gt;: SSE-S3（サーバーサイド暗号化）を有効化する。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CORS&lt;/strong&gt;: フロントエンドオリジンからの &lt;code&gt;PUT&lt;/code&gt; のみ許可する。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ストレージクラス&lt;/strong&gt;: Standard（頻繁アクセス向け）&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;CORSRules&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;AllowedOrigins&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;https://&amp;lt;frontend-domain&amp;gt;&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;AllowedMethods&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;PUT&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;AllowedHeaders&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;MaxAgeSeconds&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="s3-ストレージクラスと料金"&gt;S3 ストレージクラスと料金&lt;a class="anchor" href="#s3-%e3%82%b9%e3%83%88%e3%83%ac%e3%83%bc%e3%82%b8%e3%82%af%e3%83%a9%e3%82%b9%e3%81%a8%e6%96%99%e9%87%91"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="ストレージクラス"&gt;ストレージクラス&lt;a class="anchor" href="#%e3%82%b9%e3%83%88%e3%83%ac%e3%83%bc%e3%82%b8%e3%82%af%e3%83%a9%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;ストレージクラス&lt;/th&gt;
 &lt;th&gt;用途&lt;/th&gt;
 &lt;th&gt;特徴&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;S3 Standard&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;アクセス頻度の高い画像&lt;/td&gt;
 &lt;td&gt;頻繁アクセス、低レイテンシ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="料金東京リージョン2024年3月時点"&gt;料金（東京リージョン、2024年3月時点）&lt;a class="anchor" href="#%e6%96%99%e9%87%91%e6%9d%b1%e4%ba%ac%e3%83%aa%e3%83%bc%e3%82%b8%e3%83%a7%e3%83%b32024%e5%b9%b43%e6%9c%88%e6%99%82%e7%82%b9"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;ストレージクラス&lt;/th&gt;
 &lt;th&gt;保存料金（GB/月）&lt;/th&gt;
 &lt;th&gt;リクエスト料金（GET/1,000回）&lt;/th&gt;
 &lt;th&gt;リクエスト料金（PUT/1,000回）&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;S3 Standard&lt;/td&gt;
 &lt;td&gt;¥23&lt;/td&gt;
 &lt;td&gt;¥0.43&lt;/td&gt;
 &lt;td&gt;¥5&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="ライフサイクルポリシー"&gt;ライフサイクルポリシー&lt;a class="anchor" href="#%e3%83%a9%e3%82%a4%e3%83%95%e3%82%b5%e3%82%a4%e3%82%af%e3%83%ab%e3%83%9d%e3%83%aa%e3%82%b7%e3%83%bc"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;0日～30日&lt;/strong&gt;: S3 Standard（アップロード直後）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;30日～90日&lt;/strong&gt;: S3 Standard-IA（アクセス頻度低下）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;90日以降&lt;/strong&gt;: S3 Glacier Instant Retrieval（アーカイブ）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="presigned-url"&gt;Presigned URL&lt;a class="anchor" href="#presigned-url"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;種別&lt;/th&gt;
 &lt;th&gt;操作&lt;/th&gt;
 &lt;th&gt;有効期限&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;アップロード用&lt;/td&gt;
 &lt;td&gt;PutObject&lt;/td&gt;
 &lt;td&gt;300 秒（5 分）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;閲覧用&lt;/td&gt;
 &lt;td&gt;GetObject&lt;/td&gt;
 &lt;td&gt;3600 秒（1 時間）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="ネットワーク"&gt;ネットワーク&lt;a class="anchor" href="#%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%af"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;全通信は HTTPS（TLS 1.2 以上）。&lt;/li&gt;
&lt;li&gt;Terraform にて定義する（&lt;code&gt;packages/infra/&lt;/code&gt;）。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>画像アップロード機能</title><link>https://Hitamuki.github.io/image-upload/design/interaction/ia001-upload/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/interaction/ia001-upload/</guid><description>&lt;h1 id="画像アップロード機能"&gt;画像アップロード機能&lt;a class="anchor" href="#%e7%94%bb%e5%83%8f%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89%e6%a9%9f%e8%83%bd"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="id"&gt;ID&lt;a class="anchor" href="#id"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;ia001-upload&lt;/p&gt;
&lt;h2 id="概要"&gt;概要&lt;a class="anchor" href="#%e6%a6%82%e8%a6%81"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;画像アップロード機能の相互作用設計を定義する&lt;/p&gt;
&lt;h2 id="関連仕様設計"&gt;関連仕様・設計&lt;a class="anchor" href="#%e9%96%a2%e9%80%a3%e4%bb%95%e6%a7%98%e8%a8%ad%e8%a8%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;種別&lt;/th&gt;
 &lt;th&gt;ドキュメント&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;要件&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://Hitamuki.github.io/image-upload/requirements/req001-upload/"&gt;req001-upload&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UI&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/ui/scr001-upload/"&gt;scr001-upload&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api001-upload/"&gt;api001-upload&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api002-upload/"&gt;api002-upload&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api003-upload/"&gt;api003-upload&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/api/images/api004-upload/"&gt;api004-upload&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;インフラ&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/infra/infra001-upload/"&gt;infra001-upload&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;セキュリティ&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/security/sec001-upload/"&gt;sec001-upload&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="ユースケース"&gt;ユースケース&lt;a class="anchor" href="#%e3%83%a6%e3%83%bc%e3%82%b9%e3%82%b1%e3%83%bc%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="mermaid"&gt;graph LR
 Actor((ユーザー))

 subgraph アップロード
 UC1[画像を選択してプレビューする]
 UC2[画像をアップロードする]
 end

 subgraph 閲覧
 UC3[アップロード済み画像の一覧をファイル名で確認する]
 UC4[ファイル名を選択して画像を閲覧する]
 end

 Actor --&amp;gt; UC1
 Actor --&amp;gt; UC2
 Actor --&amp;gt; UC3
 Actor --&amp;gt; UC4&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="シーケンス"&gt;シーケンス&lt;a class="anchor" href="#%e3%82%b7%e3%83%bc%e3%82%b1%e3%83%b3%e3%82%b9"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="画像アップロード"&gt;画像アップロード&lt;a class="anchor" href="#%e7%94%bb%e5%83%8f%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 autonumber
 actor User as ユーザー
 participant FE as フロントエンド
 participant BE as バックエンド
 participant S3 as S3
 participant DB as DB

 User-&amp;gt;&amp;gt;FE: ファイル選択
 FE-&amp;gt;&amp;gt;FE: クライアントバリデーション
 FE-&amp;gt;&amp;gt;FE: プレビュー表示

 User-&amp;gt;&amp;gt;FE: アップロードボタン押下
 FE-&amp;gt;&amp;gt;BE: api001-upload
 Note over FE,BE: X-Trace-ID ヘッダー付与

 BE-&amp;gt;&amp;gt;BE: サーバーバリデーション
 BE-&amp;gt;&amp;gt;S3: PutObject 署名付きURL生成
 S3--&amp;gt;&amp;gt;BE: uploadUrl
 BE--&amp;gt;&amp;gt;FE: uploadUrl, key

 FE-&amp;gt;&amp;gt;S3: PUT uploadUrl（バイナリ直接送信）
 S3--&amp;gt;&amp;gt;FE: 200 OK

 FE-&amp;gt;&amp;gt;BE: api002-upload
 BE-&amp;gt;&amp;gt;S3: HeadObject（存在確認）
 BE-&amp;gt;&amp;gt;BE: サーバーバリデーション
 BE-&amp;gt;&amp;gt;DB: メタデータ保存
 DB--&amp;gt;&amp;gt;BE: 保存完了
 BE--&amp;gt;&amp;gt;FE: 201 Created（id, url）

 FE-&amp;gt;&amp;gt;User: 成功メッセージ・リスト更新&lt;/pre&gt;&lt;hr&gt;
&lt;h3 id="画像閲覧"&gt;画像閲覧&lt;a class="anchor" href="#%e7%94%bb%e5%83%8f%e9%96%b2%e8%a6%a7"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 autonumber
 actor User as ユーザー
 participant FE as フロントエンド
 participant BE as バックエンド
 participant DB as DB
 participant S3 as S3

 User-&amp;gt;&amp;gt;FE: 初期表示
 FE-&amp;gt;&amp;gt;BE: api003-upload
 Note over FE,BE: メタデータ（ID・ファイル名）のみ取得。画像実体は取得しない
 BE-&amp;gt;&amp;gt;DB: 画像一覧取得
 DB--&amp;gt;&amp;gt;BE: [{id, fileName, createdAt}]
 BE--&amp;gt;&amp;gt;FE: リスト返却
 FE-&amp;gt;&amp;gt;User: ファイル名リスト表示

 User-&amp;gt;&amp;gt;FE: ファイル名クリック
 Note over FE,BE: 選択時に初めて画像実体（閲覧用URL）を取得
 FE-&amp;gt;&amp;gt;BE: api004-upload
 BE-&amp;gt;&amp;gt;S3: GetObject 閲覧用 Presigned URL 生成
 BE--&amp;gt;&amp;gt;FE: url
 FE-&amp;gt;&amp;gt;User: プレビュー表示&lt;/pre&gt;</description></item><item><title>画像アップロード機能</title><link>https://Hitamuki.github.io/image-upload/requirements/req001-upload/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/requirements/req001-upload/</guid><description>&lt;h1 id="画像アップロード機能"&gt;画像アップロード機能&lt;a class="anchor" href="#%e7%94%bb%e5%83%8f%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89%e6%a9%9f%e8%83%bd"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="id"&gt;ID&lt;a class="anchor" href="#id"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;req001-upload&lt;/p&gt;
&lt;h2 id="概要"&gt;概要&lt;a class="anchor" href="#%e6%a6%82%e8%a6%81"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;ユーザーがアプリケーションを介して画像ファイルをアップロードし、永続化・閲覧できる機能を提供する。&lt;/p&gt;
&lt;h2 id="ビジネス要件"&gt;ビジネス要件&lt;a class="anchor" href="#%e3%83%93%e3%82%b8%e3%83%8d%e3%82%b9%e8%a6%81%e4%bb%b6"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ユーザーは画像を送信し、表示できる必要がある。&lt;/li&gt;
&lt;li&gt;不適切なファイルのアップロードを防止し、システムの安定性を担保する。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="as-is"&gt;As-Is&lt;a class="anchor" href="#as-is"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;なし&lt;/p&gt;
&lt;h3 id="to-be"&gt;To-Be&lt;a class="anchor" href="#to-be"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ユーザーがローカル端末から画像を選択し、クラウドストレージへアップロード・閲覧できる。&lt;/li&gt;
&lt;li&gt;不正ファイルの混入を防ぎ、安全かつ安定したファイル管理基盤を持つ。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="スコープ"&gt;スコープ&lt;a class="anchor" href="#%e3%82%b9%e3%82%b3%e3%83%bc%e3%83%97"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;画像の選択・プレビュー・アップロード・閲覧&lt;/li&gt;
&lt;li&gt;クライアント／サーバー双方でのバリデーション&lt;/li&gt;
&lt;li&gt;S3 Presigned URL を用いた直接アップロード方式&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ステークホルダー--ペルソナ"&gt;ステークホルダー / ペルソナ&lt;a class="anchor" href="#%e3%82%b9%e3%83%86%e3%83%bc%e3%82%af%e3%83%9b%e3%83%ab%e3%83%80%e3%83%bc--%e3%83%9a%e3%83%ab%e3%82%bd%e3%83%8a"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;発注者&lt;/strong&gt;: システム開発の依頼者であり、最初の利用者&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;エンドユーザー&lt;/strong&gt;: MVP段階では発注者のみを想定。将来的に一般ユーザーへの展開を想定&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="機能要件"&gt;機能要件&lt;a class="anchor" href="#%e6%a9%9f%e8%83%bd%e8%a6%81%e4%bb%b6"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="画像の選択とプレビュー"&gt;画像の選択とプレビュー&lt;a class="anchor" href="#%e7%94%bb%e5%83%8f%e3%81%ae%e9%81%b8%e6%8a%9e%e3%81%a8%e3%83%97%e3%83%ac%e3%83%93%e3%83%a5%e3%83%bc"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ユーザーはローカル端末から画像ファイルを選択できる。&lt;/li&gt;
&lt;li&gt;アップロード前に選択したファイルのプレビューを表示する。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="画像のアップロード"&gt;画像のアップロード&lt;a class="anchor" href="#%e7%94%bb%e5%83%8f%e3%81%ae%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;選択された画像をサーバー（S3）にアップロードする。&lt;/li&gt;
&lt;li&gt;アップロード成功後、メタデータ（ファイル名、URL、サイズ等）をDBに保存する。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="バリデーション"&gt;バリデーション&lt;a class="anchor" href="#%e3%83%90%e3%83%aa%e3%83%87%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ファイルサイズ制限: 最大 5MB。&lt;/li&gt;
&lt;li&gt;対応フォーマット: JPEG, PNG, GIF, WebP。&lt;/li&gt;
&lt;li&gt;MIMEタイプはバイナリヘッダ（マジックナンバー）で検証する。&lt;/li&gt;
&lt;li&gt;クライアントサイドとサーバーサイドの両方で検証を行う。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="アップロード済み画像の閲覧"&gt;アップロード済み画像の閲覧&lt;a class="anchor" href="#%e3%82%a2%e3%83%83%e3%83%97%e3%83%ad%e3%83%bc%e3%83%89%e6%b8%88%e3%81%bf%e7%94%bb%e5%83%8f%e3%81%ae%e9%96%b2%e8%a6%a7"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;アップロード済みの画像はファイル名のリストとして表示される。&lt;/li&gt;
&lt;li&gt;リストからファイル名を選択することで、その画像のプレビューを表示する。&lt;/li&gt;
&lt;li&gt;通信量削減のため、初期表示時にすべての画像の実体を取得しない。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="非機能要件"&gt;非機能要件&lt;a class="anchor" href="#%e9%9d%9e%e6%a9%9f%e8%83%bd%e8%a6%81%e4%bb%b6"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="可用性スケーラビリティ"&gt;可用性・スケーラビリティ&lt;a class="anchor" href="#%e5%8f%af%e7%94%a8%e6%80%a7%e3%82%b9%e3%82%b1%e3%83%bc%e3%83%a9%e3%83%93%e3%83%aa%e3%83%86%e3%82%a3"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;大容量ファイルの転送によるバックエンドサーバーの負荷を避けるため、&lt;strong&gt;S3 Presigned URL（署名付きURL）&lt;/strong&gt; を使用した直接アップロード方式を採用する。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="セキュリティ"&gt;セキュリティ&lt;a class="anchor" href="#%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;マジックナンバーによる検証&lt;/strong&gt;: 拡張子だけでなく、バイナリヘッダによるMIMEタイプ検証を行う。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;署名付きURLの有効期限&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;アップロード用: 5分以内に制限する&lt;/li&gt;
&lt;li&gt;閲覧用: 1時間以内に制限する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;公開設定&lt;/strong&gt;: アップロードされたファイルは適切なACL（またはPublic Access Block）を設定し、不要な公開を避ける。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="トレーサビリティ"&gt;トレーサビリティ&lt;a class="anchor" href="#%e3%83%88%e3%83%ac%e3%83%bc%e3%82%b5%e3%83%93%e3%83%aa%e3%83%86%e3%82%a3"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;アップロード処理全体に &lt;code&gt;trace_id&lt;/code&gt; を付与し、フロントエンドからS3、バックエンド、DBまでのログを紐づけ可能とする。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="前提条件制約"&gt;前提条件・制約&lt;a class="anchor" href="#%e5%89%8d%e6%8f%90%e6%9d%a1%e4%bb%b6%e5%88%b6%e7%b4%84"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;アップロード可能な画像数は最大 5枚 とする。&lt;/li&gt;
&lt;li&gt;1度の処理でアップロードできる画像数は 1枚 とする。&lt;/li&gt;
&lt;li&gt;ファイルストレージとして AWS S3 または互換ストレージを使用する。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mvp開発方針"&gt;MVP開発方針&lt;a class="anchor" href="#mvp%e9%96%8b%e7%99%ba%e6%96%b9%e9%87%9d"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="スコープ外"&gt;スコープ外&lt;a class="anchor" href="#%e3%82%b9%e3%82%b3%e3%83%bc%e3%83%97%e5%a4%96"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ユーザー管理機能&lt;/strong&gt;: ユーザー登録、認証、認可は実装しない&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;アクセス制御&lt;/strong&gt;: 画像の所有者制限や権限管理は実装しない&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;プライバシー設定&lt;/strong&gt;: 画像の公開・非公開設定は実装しない&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="理由"&gt;理由&lt;a class="anchor" href="#%e7%90%86%e7%94%b1"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MVP（Minimum Viable Product）として、まずは画像アップロード・表示の基本機能に集中し、ユーザー管理のような機能は後のバージョンで実装する。これにより早期に価値を提供しつつ、開発期間を短縮する。&lt;/p&gt;</description></item><item><title>運用設計指針</title><link>https://Hitamuki.github.io/image-upload/design/common/%E9%81%8B%E7%94%A8%E8%A8%AD%E8%A8%88%E6%8C%87%E9%87%9D/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://Hitamuki.github.io/image-upload/design/common/%E9%81%8B%E7%94%A8%E8%A8%AD%E8%A8%88%E6%8C%87%E9%87%9D/</guid><description>&lt;h1 id="運用設計指針"&gt;運用設計指針&lt;a class="anchor" href="#%e9%81%8b%e7%94%a8%e8%a8%ad%e8%a8%88%e6%8c%87%e9%87%9d"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="概要"&gt;概要&lt;a class="anchor" href="#%e6%a6%82%e8%a6%81"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;本システムの運用における監視・障害対応・ログ管理の方針を定義する。&lt;/p&gt;
&lt;h2 id="関連ドキュメント"&gt;関連ドキュメント&lt;a class="anchor" href="#%e9%96%a2%e9%80%a3%e3%83%89%e3%82%ad%e3%83%a5%e3%83%a1%e3%83%b3%e3%83%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/common/%E3%83%AD%E3%82%B0%E8%A8%AD%E8%A8%88%E6%8C%87%E9%87%9D/"&gt;ログ設計指針&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://Hitamuki.github.io/image-upload/design/common/%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E6%A7%8B%E6%88%90%E5%9B%B3/"&gt;システム構成図&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="監視"&gt;監視&lt;a class="anchor" href="#%e7%9b%a3%e8%a6%96"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="監視対象"&gt;監視対象&lt;a class="anchor" href="#%e7%9b%a3%e8%a6%96%e5%af%be%e8%b1%a1"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;対象&lt;/th&gt;
 &lt;th style="text-align: left"&gt;監視内容&lt;/th&gt;
 &lt;th style="text-align: left"&gt;ツール&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;バックエンド (Lambda)&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラー率、レイテンシ、タイムアウト&lt;/td&gt;
 &lt;td style="text-align: left"&gt;CloudWatch Metrics&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;S3&lt;/td&gt;
 &lt;td style="text-align: left"&gt;アップロード成功率、4xx/5xxエラー&lt;/td&gt;
 &lt;td style="text-align: left"&gt;CloudWatch Metrics&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;DB (RDS)&lt;/td&gt;
 &lt;td style="text-align: left"&gt;接続数、クエリレイテンシ、ストレージ使用量&lt;/td&gt;
 &lt;td style="text-align: left"&gt;CloudWatch Metrics&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;ログ&lt;/td&gt;
 &lt;td style="text-align: left"&gt;エラーログの検出&lt;/td&gt;
 &lt;td style="text-align: left"&gt;CloudWatch Logs Insights&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="アラート基準目安"&gt;アラート基準（目安）&lt;a class="anchor" href="#%e3%82%a2%e3%83%a9%e3%83%bc%e3%83%88%e5%9f%ba%e6%ba%96%e7%9b%ae%e5%ae%89"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;条件&lt;/th&gt;
 &lt;th style="text-align: left"&gt;閾値&lt;/th&gt;
 &lt;th style="text-align: left"&gt;対応&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;バックエンドエラー率&lt;/td&gt;
 &lt;td style="text-align: left"&gt;1% 超&lt;/td&gt;
 &lt;td style="text-align: left"&gt;即時調査&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;アップロード成功率&lt;/td&gt;
 &lt;td style="text-align: left"&gt;99% 未満&lt;/td&gt;
 &lt;td style="text-align: left"&gt;即時調査&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;Lambda タイムアウト&lt;/td&gt;
 &lt;td style="text-align: left"&gt;連続3回以上&lt;/td&gt;
 &lt;td style="text-align: left"&gt;即時調査&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="障害対応"&gt;障害対応&lt;a class="anchor" href="#%e9%9a%9c%e5%ae%b3%e5%af%be%e5%bf%9c"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="調査手順"&gt;調査手順&lt;a class="anchor" href="#%e8%aa%bf%e6%9f%bb%e6%89%8b%e9%a0%86"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;CloudWatch Logs Insights で &lt;code&gt;trace_id&lt;/code&gt; をキーに横断検索する。&lt;/li&gt;
&lt;li&gt;特定の操作に問題がある場合は &lt;code&gt;request_id&lt;/code&gt; で絞り込んで検索する。&lt;/li&gt;
&lt;li&gt;フロントエンド → バックエンド → S3 → DB の順にログを追跡する。&lt;/li&gt;
&lt;li&gt;エラー発生箇所を特定し、原因を切り分ける。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="ログ検索クエリ例"&gt;ログ検索クエリ例&lt;a class="anchor" href="#%e3%83%ad%e3%82%b0%e6%a4%9c%e7%b4%a2%e3%82%af%e3%82%a8%e3%83%aa%e4%be%8b"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id="セッション全体の調査trace_id"&gt;セッション全体の調査（trace_id）&lt;a class="anchor" href="#%e3%82%bb%e3%83%83%e3%82%b7%e3%83%a7%e3%83%b3%e5%85%a8%e4%bd%93%e3%81%ae%e8%aa%bf%e6%9f%bbtrace_id"&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;fields @timestamp, @message, request_id
| filter trace_id = &amp;#34;&amp;lt;対象のtrace_id&amp;gt;&amp;#34;
| sort @timestamp asc&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="特定操作の調査request_id"&gt;特定操作の調査（request_id）&lt;a class="anchor" href="#%e7%89%b9%e5%ae%9a%e6%93%8d%e4%bd%9c%e3%81%ae%e8%aa%bf%e6%9f%bbrequest_id"&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;fields @timestamp, @message, level
| filter request_id = &amp;#34;&amp;lt;対象のrequest_id&amp;gt;&amp;#34;
| sort @timestamp asc&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="エラー発生時の調査"&gt;エラー発生時の調査&lt;a class="anchor" href="#%e3%82%a8%e3%83%a9%e3%83%bc%e7%99%ba%e7%94%9f%e6%99%82%e3%81%ae%e8%aa%bf%e6%9f%bb"&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;fields @timestamp, @message, level, error_code
| filter trace_id = &amp;#34;&amp;lt;対象のtrace_id&amp;gt;&amp;#34; and level = &amp;#34;ERROR&amp;#34;
| sort @timestamp desc&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="バックアップリカバリ"&gt;バックアップ・リカバリ&lt;a class="anchor" href="#%e3%83%90%e3%83%83%e3%82%af%e3%82%a2%e3%83%83%e3%83%97%e3%83%aa%e3%82%ab%e3%83%90%e3%83%aa"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;対象&lt;/th&gt;
 &lt;th style="text-align: left"&gt;方針&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;RDS&lt;/td&gt;
 &lt;td style="text-align: left"&gt;自動バックアップ（保持期間: 7日）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;S3&lt;/td&gt;
 &lt;td style="text-align: left"&gt;バージョニング有効化（誤削除対策）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="デプロイ"&gt;デプロイ&lt;a class="anchor" href="#%e3%83%87%e3%83%97%e3%83%ad%e3%82%a4"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GitHub Actions による CI/CD で &lt;code&gt;main&lt;/code&gt; ブランチへのマージをトリガーに自動デプロイする。&lt;/li&gt;
&lt;li&gt;デプロイ前にAPIテスト・E2Eテストが通過していることを必須とする。&lt;/li&gt;
&lt;li&gt;ロールバックは直前の Lambda バージョンへの切り戻しで対応する。&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>