最終更新: 2026-08-29
ユーザーが日時、時間帯、キーワード、公開半径を指定した募集カードを公開し、閲覧者の関心をカード所有者が承認したときだけマッチを成立させます。承認後はチャットと会合セッションを別APIで開放します。
現行コードでは募集・検索・関心・承認/辞退のGo APIと、外国人/日本人画面からの募集・募集管理・応募履歴フロー接続コードが存在します。日時入力の初期パース問題はISO内部値/Asia/Tokyo固定化と自動テストで解消済みです。2026-08-29時点で公開APIのhealthzとreadyzは確認済みで、iPhone実機では表示言語の設定変更が現在表示中の画面にも直ちに反映されることを確認しています。一方、日時pickerから公開・応募・通知遷移・取消・ログアウト後の戻る操作までを単一の手順として再現する全通しE2Eは未完了です。
対応要件:FR-007、FR-009、C-001、C-003、C-004、C-005
| 項目 | 必須 | 仕様 |
|---|---|---|
| 日時 | Yes | available_date。国内利用向けにAsia/Tokyo固定の壁時計として扱う |
| 時間帯 | Yes | start_time / end_time |
| キーワード | Yes | 交流目的、言語、興味分野等。複数可 |
| 公開半径 | Yes | 1 km / 3 km / 5 km の選択式 |
| 位置 | 自動 | 有効な現在地から取得。正確な値は非公開 |
| 有効期限 | 自動 | 時間帯終了後に非表示 |
| 状態 | 自動 | draft / open / matched / closed / expired |
| 案内カテゴリ | 自動 | 募集文をサーバー側のgemini-3.1-flash-liteでFood / Places / Activity / Otherの1つに分類する。Gemini APIキーはサーバー環境変数だけに置く |
card: draft -> open -> matched
├-> closed
└-> expired
match: pending -> accepted -> completed
└-> cancelled(応募者が取り下げ)
draft:未公開。作成者だけが閲覧可能。open:公開中。公開半径と検索条件を満たすユーザーへ表示。matched:少なくとも 1 件のマッチが成立。カードを閉じるか期限切れになるまで、追加の関心を受け付ける。カード自体は今回のAPIではcompletedへ遷移しない。closed:作成者が停止。expired:日時または有効期限を過ぎた状態。matches.status = accepted となる。completed にして評価を有効にする。| 処理 | 言語 / 場所 |
|---|---|
| カード入力・プレビュー・状態表示 | TypeScript / TSX |
| 入力値の一次検証・フォーム状態 | TypeScript |
| 状態遷移、重複、期限、権限 | Go |
| 距離・公開条件 | GoのHaversine + PostgreSQL(PostGIS未導入) |
| 永続化 | PostgreSQL / SQL |
local/traveler)は別の保存設定です。片方の変更で、もう片方を切り替えてはいけません。GET /api/v1/recruitmentsGET /api/v1/recruitments/minePOST /api/v1/recruitmentsPOST /api/v1/recruitments/classifyGET /api/v1/recruitments/{id}PATCH /api/v1/recruitments/{id}DELETE /api/v1/recruitments/{id}(物理削除ではなくclosed化)POST /api/v1/recruitments/{id}/interestGET /api/v1/matches?role=owner&status=pending&limit=50GET /api/v1/matches/{id}POST /api/v1/matches/{id}/acceptPOST /api/v1/matches/{id}/rejectPOST /api/v1/matches/{id}/withdrawPOST /api/v1/matches/{id}/completePOST /api/v1/matches/{id}/meetingrecruitment_cards、matches、blocks募集カードの公開には名前・国コードが揃ったプロフィールが必要です。作成・更新の成功レスポンスは { "data": { ...card } }、検索は { "data": [ ...card ] } です。カードのレスポンスには正確な緯度・経度を含めず、現在地を使った場合だけ distance_band(within_1_km / within_3_km / within_5_km)を返します。
外国人側の募集確認に入る前に、POST /api/v1/recruitments/classifyが入力文をGeminiへ送り、Food、Places、Activity、Otherの案内カテゴリと最大5件の短いキーワード候補を返します。クライアントはAPIキーを保持せず、公開前にカテゴリ・候補キーワードを選び直せます。応答が契約外、未設定、またはGemini障害の場合はカテゴリを推測して公開せず、明示的なエラーにします。
検索条件は keyword(複数可)、available_date、start_time、end_time、radius_km(1/3/5)、verified_only、latitude、longitude、limit(最大50)です。緯度経度を省略した場合は、期限内の user_locations を使います。位置がない場合はキーワード・日時検索として扱い、位置による絞り込みは行いません。
現行のPostgreSQLイメージにはPostGISを追加していないため、距離計算はGoのHaversine計算です。座標はDB内だけで扱い、PostGISへの置換は性能改善タスクとして残します。
timezoneを省略または空にした募集入力はAsia/Tokyoへ正規化し、他のtimezoneは拒否します。created_atやexpires_atなどの絶対時刻はUTCで扱います。ISO内部値、JST固定の日時正規化、期限境界は自動テストで確認済みですが、過去時刻・日跨ぎ・端末日時pickerの実機確認は未完了です。
応募者はpending中に関心を取り下げられ、matchの状態はcancelledになります。取り下げ後の行は履歴と通知の冪等性のため保持します。
chat_threadsを遅延作成する。409 interest_already_sent。accepted前のチャットAPIは存在しない。承認後はRESTの暗号化メッセージ、既読、短命transport tokenを利用できる。本項の全項目が同じ公開API環境で確認できるまで、この機能を実機E2E完了とは扱わない。
pendingなら取消できることを確認する。募集者は募集管理で応募者と状態を確認する。