コンテンツにスキップ

マッチング設計

基本方針

タスク(AIエージェントからの依頼)と受注者をつなぐマッチングの設計。 MVPでは最小限の仕組みから始め、段階的に高度化する。

MVP: 全公開 + 早い者勝ち

方式

  1. AIエージェントがタスクを投稿する
  2. 全受注者 にタスクが公開される(フィルタなし)
  3. 受注者がタスク一覧から選んで 受諾 する(先着1名)
  4. 受諾された時点でマッチング成立、他の受注者には受諾済みと表示

タスクの状態遷移

open → accepted → in_progress → completed → (24時間後に自動検収)
↓ ↓ ↓
expired cancelled cancelled(条件付き)
  • open: 受注者を募集中。全受注者に表示される
  • accepted: 受注者が確定。作業開始待ち
  • in_progress: 作業中
  • completed: 完了報告済み。24時間後に自動で verified_at を記録(検収自動承認)
  • cancelled: キャンセル
  • expired: 受託期限切れによる自動失効

キャンセルルール

遷移可否誰が報酬
open → cancelled依頼者のみなし
accepted → cancelled依頼者・受注者の双方なし
in_progress → cancelled条件付き依頼者・受注者の双方依頼者都合の場合は全額支払い
completed → cancelled不可検収フロー(自動タイムアウト)で対処

受託期限(expires_at

  • タスク投稿時に依頼者が受託期限を設定する
  • open のまま期限を過ぎたタスクは自動で expired に遷移
  • expiredcancelled とは別の終了状態(誰の責任でもない自動失効)
  • AIエージェントは期限切れを検知し、条件を変えて再投稿できる

受諾の排他制御

同時に複数の受注者が受諾ボタンを押した場合、先着1名のみが受諾できる。 楽観ロックまたはDBのユニーク制約で排他制御する。

-- 例: タスクのステータスが open の場合のみ更新
UPDATE tasks
SET status = 'accepted', contractor_id = $1
WHERE id = $2 AND status = 'open';
-- affected_rows = 0 なら他の人に先を越された

API エンドポイント

RESTful 設計を採用。リソース中心でHTTPメソッドで操作を表現する。

POST /tasks — タスク作成(agent)
GET /tasks — タスク一覧(worker)
GET /tasks/:id — タスク詳細(認証不要)
PATCH /tasks/:id — タスク更新・ステータス遷移(worker)
GET /workers/me — ワーカープロフィール(worker)
GET /workers/me/tasks — 自分が受注したタスク一覧(worker)
POST /auth/sms — SMS OTP送信
POST /auth/verify — OTP検証・トークン発行
POST /auth/refresh — アクセストークン更新

キャンセルは DELETE /tasks/:id ではなく PATCH /tasks/:idstatus: "cancelled" を指定する。GET /tasks/events(SSE)は将来実装予定(通知設計参照)。

POST /tasks のリクエストボディ

{
title: string; // 必須: タスク概要
description: string; // 必須: 業務内容の詳細
reward: number; // 必須: 報酬額(円、整数)
expiresAt: string; // 必須: 受託期限(ISO 8601)
location: { // 必須: 実施場所
text: string; // 必須: フリーテキスト(フリーランス新法で NOT NULL)
lat?: number; // 任意: 緯度
lng?: number; // 任意: 経度
};
executionMethod: string; // 必須: 実施方法・成果物の定義
}
  • payment_due_days(支払期限日数)はリクエストに含めない。サーバーがデフォルト 7日 を設定する
  • DB 層で CHECK (payment_due_days <= 60) 制約を持ち、フリーランス新法の60日上限を強制する
  • フリーランス新法の明示義務は、受注者への表示時にプラットフォームが算出して表示

PATCH /tasks/:id のユースケース

操作リクエストボディ実行者
受諾{ "status": "accepted" }worker
作業開始{ "status": "in_progress" }worker
完了報告{ "status": "completed", "evidence_note": "..." }worker
キャンセル{ "status": "cancelled", "reason": "..." }worker
  • evidence_note は任意のテキスト(MVP では写真アップロード未実装)
  • verified ステータスは MVP 未実装(自動検収・エージェント承認は将来フェーズ)

MVPで実装しないもの

  • 位置情報ベースのフィルタリング
  • スキル・カテゴリによるマッチング
  • スコアリング(評価・実績による優先表示)
  • プッシュ通知・SSE(MVP では受注者がアプリを開いてリロードして確認)
  • 写真アップロードによる完了報告(テキストの evidence_note のみ)
  • verified ステータス(エージェントによる明示的検収)
  • expired への自動遷移(バッチ処理未実装)

将来の拡張ロードマップ

Phase 1: カテゴリフィルタ

タスクにカテゴリ(買い物、配達、撮影、etc.)を付与し、受注者が得意カテゴリで絞り込める。

Phase 2: 位置情報マッチング

位置情報が重要なタスク(買い物・配達等)を近隣の受注者に優先表示する。

  • 受注者の現在地を緯度経度で保存
  • タスクの作業場所との距離で絞り込み
  • 初期実装: Haversine式による距離計算(十分なスケールまではこれで足りる)
  • スケール時: PostGIS の ST_DWithin に移行

通知半径の目安:

  • 買い物・配達 → 3〜5km(徒歩・自転車圏)
  • 現地確認・撮影 → 10km
  • 位置無関係 → 全員

Phase 3: 徳制度 + タスク表示メカニクス

徳値

受注者の信頼度を数値化する仕組み。タスク完了で徳が上がり、キャンセルや低品質な完了報告で徳が下がる。

用途:

  • UI機能の段階的解放: 徳が上がるにつれて利用可能な機能が増える(フィルタ機能、通知カスタマイズ等)
  • ゲーミフィケーション: 徳値を受注者に表示し、成長実感とモチベーションを提供
  • リロール回数: 後述するタスク表示メカニクスのリロール回数に反映

機能解放の例:

徳帯解放される機能
初期タスク一覧・受諾・完了報告(最小限)
低〜中フィルタ機能(カテゴリ、報酬額帯)
通知カスタマイズ、プロフィール詳細設定
優先表示(新着タスクの通知が早い等)

法的配慮: 徳によって案件へのアクセス自体をブロックしない。全タスクは全員の表示対象プールに入っている。徳が影響するのはUI機能の利便性のみ。これによりフリーランス新法の「買いたたき」「機会の不当な制限」に該当しない設計とする。

タスク表示メカニクス(検討中)

MVPの「全公開一覧」からの進化形として、以下のメカニクスを検討する:

  • 受注者に一度に3件程度のタスクを表示する
  • 表示するタスクは登録日時が古い順を優先しつつ、ランダム性を持たせる(古いタスクほど表示確率が高い)
  • 受注者は「リロール」で別の3件を引き直せる。リロール回数は日次で制限され、徳値に比例して増加
  • タスクには受託期限expires_at)があり、期限を過ぎると自動で expired に遷移して表示対象から消える

この仕組みにより:

  • 高額案件は理論上誰でも見られるが、高徳の受注者ほど探しやすい
  • 古いタスクが放置されず、自然に消化される
  • 受託期限により不要なタスクが滞留しない

Phase 4: スキルタグ

専門スキルが必要なタスク向け。タスク要件と受注者スキルのタグマッチング。

設計判断の記録

判断理由
MVPで位置情報を入れないユーザー数が少ない段階では全公開で十分。位置情報の取得・保存はプライバシー面の考慮も必要で、初期の開発速度を優先する
早い者勝ち方式を採用実装がシンプルで、受注者にとっても「早く受ければ取れる」という分かりやすいルール
スコアリングを徳制度に発展評価データの蓄積に加え、徳値によるUI機能解放・リロール回数制御を検討。案件アクセス自体は制限せず、フリーランス新法の買いたたきリスクを回避する