社内資料本番環境では削除予定
内部仕様・法務参考資料
PEPPER LIKES の技術仕様・DB設計・API仕様(開発者・法務担当向け)
目次
1. 技術スタック
バックエンド(likes-api)
- Laravel 10 / PHP 8.4
- Laravel Sanctum(Bearer トークン認証)
- Spatie Laravel Permission(ロール管理)
- Laravel Cashier(Stripe サブスクリプション)
- MySQL(本番・ステージング)/ SQLite(ローカル)
- GitHub Actions → SSH 自動デプロイ(Cloudways)
フロントエンド(likes-web)
- Next.js 16 / React 19 / TypeScript 5
- Tailwind CSS v4 / shadcn/ui
- Zustand v5(状態管理)/ Axios(APIクライアント)
- @dnd-kit(ドラッグ&ドロップ)
- next-intl(多言語: ja/en/zh-TW/zh-CN/ko)
- Vercel 自動デプロイ
外部サービス
- Stripe(サブスクリプション・Connect・Checkout)
- TRUSTDOCK(eKYC 本人確認)
- OpenAI GPT-4o(メッセージモデレーション)/ gpt-4o-mini(翻訳・AIアドバイス)
- Google Maps Geocoding API(住所自動補完)
- Web Push(VAPID キー・Push通知)
2. 認証・ロール
ロール
| ロール | 説明 | ログインエンドポイント |
|---|---|---|
| seller | インフルエンサー | POST /api/auth/inf/login |
| buyer | 企業 | POST /api/auth/company/login |
Cookie
gifting_token: Sanctum Bearer トークン(30日)gifting_role: ロール(seller / buyer)
表示言語の自動切り替え(preferred_language)
- ログイン成功時に APIレスポンスの
preferred_language(ja/en/zh-TW/zh-CN/ko)を取得 - 現在のURL locale と異なる場合は
window.location.replaceでリダイレクト - 例: ブラウザが
/ja/homeで preferred_language=en の場合 →/en/homeへ即時遷移 - ブラウザリフレッシュ後にも同様の判定を実行(next-intl middleware 経由)
- 言語設定変更時は PATCH /api/auth/inf/profile で preferred_language を更新
3. DBスキーマ(主要テーブル)
users(インフルエンサー・企業共通)
| カラム | 型 | 説明 |
|---|---|---|
| is_overseas | boolean | 海外在住フラグ |
| overseas_country/zipcode/address | string/text | eKYC 海外在住登録住所 |
| shipping_country | string | 配送先住所: 国(IPから自動検出して初期値に設定) |
| shipping_zipcode | string | 配送先住所: 郵便番号 |
| shipping_address | text | 配送先住所: 都道府県・市区町村・番地 |
| shipping_address_2 | string | 配送先住所: マンション名・部屋番号(任意) |
| kyc_status | string | pending / verified |
| stripe_connect_id | string | Stripe Connect アカウントID |
| stripe_connect_status | string | Stripe Connect 接続ステータス |
| preferred_language | string | ja/en/zh-TW/zh-CN/ko(ログイン後自動切り替え) |
| rank | string | silver / gold / platinum / null |
projects(キャンペーン)
| カラム | 型 | 説明 |
|---|---|---|
| type | string | gifting / paid |
| project_format | string | offline / remote |
| remote_delivery_type | string | physical / digital / null |
| overseas_ok | boolean | 海外在住INF参加可否 |
| status | string | draft / publish / pending |
| proposal_status | string | open / closed |
| reward_type | string | fixed / negotiable(有償のみ) |
proposals(応募)
| カラム | 型 | 説明 |
|---|---|---|
| status | string | pending/new/hired/awaiting_confirmation/active/payment_pending/completed/declined |
| post_url / post_urls | string/json | SNS投稿URL |
| became_active_at | timestamp | 提供済みになった日時 |
| comment_translations | json | special_comments の翻訳キャッシュ(全5言語) |
| digital_content | text | デジタルコンテンツ送付テキスト(URL/コード等) |
| digital_attachment_urls | json | デジタル添付ファイルURL配列 |
| shipping_tracking_number | string | 送り状番号(物品配送案件) |
| shipping_carrier | string | 発送業者(yamato/sagawa/japanpost/dhl/fedex/ems/other 等) |
| shipped_at | timestamp | 発送日時 |
| digital_delivered_at | timestamp | デジタルコンテンツ送付日時 |
| pinned_at | timestamp | 企業側ピン留め日時 |
| pinned_order | int | 企業側ピン留め並び順 |
| company_memo | text | 企業側社内メモ(INF非表示) |
| company_label | string | hot(赤)/ watching(青)/ pending(黒)/ null |
| inf_pinned_at | timestamp | INF側ピン留め日時 |
| inf_pinned_order | int | INF側ピン留め並び順 |
| inf_memo | text | INF側個人メモ(本人のみ表示) |
application_messages
| カラム | 型 | 説明 |
|---|---|---|
| type | string | message / schedule_proposal |
| image_url | string | 画像添付URL |
| attachment_urls | json | [{url, original_name, size}] ファイル添付配列 |
| translations | json | { ja:"...", en:"...", "zh-TW":"...", "zh-CN":"...", ko:"..." } 翻訳キャッシュ。送信時に TranslateMessageJob で全5言語を事前生成 |
| read_at | timestamp | 既読日時 |
4. ステータス仕様
proposals.status 遷移
| ステータス | 表示名 | 説明 |
|---|---|---|
| pending / new | 審査中 | 企業が確認中 |
| awaiting_confirmation | オファー中 | 有償応相談: INF承認待ち |
| hired | 調整中 | マッチング完了・メッセージで調整 |
| active | 提供済み | 提供確認済み・アンケート・投稿URL受付(旧「体験済み」から変更) |
| payment_pending | 支払い処理中 | 有償案件: 請求処理中 |
| completed | 完了 | アンケート + 投稿URL 提出済み |
| declined | 見送り | 企業による不採用 or INF辞退(旧「不採用」から変更) |
提供済み移行ボタン名(project_format 別)
| 案件形式 | ボタン表示名 | 遷移条件 |
|---|---|---|
| offline | 提供済みにする | PATCH status=active |
| remote(physical) | 商品提供済みにする | PATCH status=active |
| remote(digital) | コンテンツを送付する | POST /digital-delivery → active 移行 |
デジタル案件のみ「コンテンツを送付する」ボタンで別エンドポイントを呼び出す。送付完了と同時に active に遷移する。
自動完了条件(無償・active時)
キャンペーン固有のアンケート提出 AND 投稿URL提出 → 自動で completed に移行。グローバルサーベイ(campaign_id=null)は条件に含まない。
5. API エンドポイント一覧(主要)
認証
- POST /api/auth/inf/login・logout・register・me
- POST /api/auth/company/login・logout・register・me
- PATCH /api/auth/inf/profile(shipping_country/zipcode/address/address_2/preferred_language 含む)
案件
- GET /api/campaigns(一覧・フィルター)
- POST /api/campaigns(作成: remote_delivery_type 含む)
- PATCH /api/campaigns/[id](更新)
- GET /api/campaigns/[id]/applications(応募一覧)
応募(企業側)
- PATCH /api/applications/[id]/status(hired/declined/active/completed 等)
- PATCH /api/applications/[id]/tracking(発送業者 shipping_carrier + 送り状番号の登録)
- POST /api/applications/[id]/digital-delivery(デジタルコンテンツ送付 + active 移行)
- PATCH /api/applications/[id]/meta(企業側: pinned/label/memo の更新)
応募(INF側)
- POST /api/campaigns/[id]/apply
- PATCH /api/my/applications/[id]/post-url
- PATCH /api/my/applications/[id]/confirm-scout
- PATCH /api/my/applications/[id]/meta(INF側: pinned/memo の更新)
ファイルアップロード
- POST /api/upload/campaign-image(案件画像: max 5MB)
- POST /api/upload/message-image(チャット画像: max 10MB)
- POST /api/upload/digital-content(デジタルコンテンツ: PDF/動画/ZIP等 max 50MB)
- POST /api/upload/report-evidence(通報証拠: max 10MB)
翻訳
- POST /api/translate/text(任意テキストを全5言語に翻訳してキャッシュ)
リクエスト:
レスポンス:
{ "text": "...", "source_locale": "ja" }レスポンス:
{ "translations": { "ja": "...", "en": "...", "zh-TW": "...", "zh-CN": "...", "ko": "..." } }メッセージ
- GET/POST /api/applications/[id]/messages(企業側)
- GET/POST /api/my/applications/[id]/messages(INF側)
- PATCH /api/applications/[id]/messages/read-all
- PATCH /api/applications/[id]/messages/[msgId]/proposal(日程確定)
モデレーション
- POST /api/moderation/preview(送信前プレチェック)
6. リモート配送フロー
物品配送(physical)フロー
- 案件作成時に
remote_delivery_type=physicalを設定 - INFが応募 → 企業がマッチング(hired)→ 自動メッセージ送信
- INFがアカウント設定で配送先住所を登録(shipping_address_2: マンション・部屋番号も任意入力可)
- 企業側応募詳細に住所(address + address_2)が表示される
- 企業が商品を発送 → 発送業者(
shipping_carrier)を選択し送り状番号を入力(PATCH /tracking → INFにメッセージ通知) - 企業が「商品提供済みにする」→ active 移行
- INFの詳細ページに「📦 商品を発送しました」セクション(水色)表示(発送業者・送り状番号を記載)
- INFがアンケート + 投稿URL提出 → completed
デジタル配信(digital)フロー
- 案件作成時に
remote_delivery_type=digitalを設定 - INFが応募 → 企業がマッチング(hired)→ 自動メッセージ送信
- 企業が「コンテンツを送付する」フォームでテキスト + ファイルを入力
- 送付ボタンで POST /digital-delivery → active 移行 + メッセージ通知
- INFの詳細ページに「💻 デジタルコンテンツが届きました」セクション(紫)表示
- テキストコンテンツ表示 + ファイルのダウンロードボタン
- INFがアンケート + 投稿URL提出 → completed
配送先住所フィールドの設計
users.shipping_address: 全INF共通の配送先(都道府県・市区町村・番地)users.shipping_address_2: マンション名・部屋番号(任意・追加フィールド)users.overseas_address: eKYC 海外在住登録用(別目的)users.shipping_country: 登録時にIPアドレスから自動検出して初期値を設定- Google Maps Geocoding API で郵便番号から住所自動補完
7. 画面仕様(主要)
INF アカウント設定(/account)
- 配送先住所フォームに
shipping_address_2(マンション名・部屋番号)フィールドを追加 - 言語設定セクション: preferred_language をドロップダウンで選択 → PATCH 後に自動リダイレクト
- 国籍(nationality)フィールドは必須。一度登録すると変更不可(変更はCS対応)
INF 応募一覧(/applications)
- タブ: Pill chips形式(調整中 / 提供済み / 完了 / 審査中 / 見送り)。各タブに件数バッジ表示
- 「すべて」タブは廃止
- 調整中タブを開くと紙吹雪アニメーションが表示される
- 未読メッセージバッジ(赤数字)をカードに表示
- ピン留めカードは一覧上部に固定表示(inf_pinned_order 順)
- ピン留め・メモボタンはカード右上のアイコンから操作
INF 応募詳細(/applications/[id])
- 横タイムライン: 応募日 → マッチング日 → 提供済み日 → 完了日 などをステップ表示
- ステータスウィジェット(2段階): 現在ステータス表示 + 次のアクション案内
- チャット部分: 各メッセージに AI翻訳トグル(TranslatableBody コンポーネント)
- 応募文(special_comments): TranslatableText コンポーネントで翻訳トグル付き表示
- デジタルコンテンツ受信時: 「💻 デジタルコンテンツが届きました」セクションを紫背景で表示
- 物品発送通知時: 「📦 商品を発送しました」セクションを水色背景で表示(発送業者 + 送り状番号含む)
- 個人メモ(inf_memo)入力エリア: 本人のみ表示
企業側 応募管理(/company/applications)
- タブ: Pill chips形式(未対応 / 調整中 / 提供済み / 完了 / 見送り)。各タブに件数バッジ表示
- ステータス別集計バー(審査中/調整中/提供済み/完了/見送り)
- company_label によるバッジカラー: hot=赤 / watching=青 / pending=黒
- ピン留めカードは一覧上部に固定(pinned_order 順)
- マッチング時の自動メッセージ送信(案件形式に応じたテンプレート)
企業側 応募詳細(/company/applications/[id])
- 2カラムレイアウト: 左=INF情報(SNS・応募文等)、右=ステータス+アクション
- 横タイムライン: マッチング日・提供済み日・完了日をステップ表示
- ランクバッジはアバター右下に重なって表示
- 審査中の右カラムに「AIアドバイス」が自動表示(GPT-4o-mini使用、採用判断の参考情報)
- 「マッチングする」ボタンは右カラムに配置(審査中時のみ)
- 物品配送案件: 発送業者セレクト(国内: ヤマト/佐川/日本郵便等、国際: DHL/FedEx/EMS等)+ 送り状番号入力フォーム + 「商品提供済みにする」ボタン
- デジタル案件: テキスト + ファイルアップロードフォーム(ドラッグ&ドロップ対応、max 50MB)+ 「コンテンツを送付する」ボタン
- ラベル選択(hot/watching/pending)・社内メモ入力・ピン留めトグル
- INFの配送先住所(address + address_2)をコピー可能な形式で表示
案件作成(/company/projects/new)
- 実施形式選択: オフライン / リモート(物品)/ リモート(デジタル)
- リモート選択時: 配信方式(physical/digital)ラジオボタンを追加表示
- 海外INF参加可否チェックボックス(リモート時のみ)
8. AI翻訳アーキテクチャ
TranslationService(gpt-4o-mini)
- モデル: gpt-4o-mini(コスト削減)
- 対応言語: ja / en / zh-TW / zh-CN / ko
- 「ターゲット言語に必ず翻訳せよ」という直接指示プロンプト(言語自動検出なし)
- 改行・段落構造を保持する指示を含む
TranslateMessageJob
メッセージ送信時にディスパッチされ、全5言語を一括翻訳して application_messages.translations にキャッシュ。受信者がチャットを開いた際に即表示される。QUEUE_CONNECTION=sync の場合は同期実行。
翻訳対象
| 対象 | キャッシュ先 | タイミング |
|---|---|---|
| チャットメッセージ本文 | application_messages.translations | 送信時(TranslateMessageJob) |
| 応募文(special_comments) | proposals.comment_translations | 応募時 or 初回表示時 |
| 任意テキスト | サーバー側一時キャッシュ | POST /api/translate/text 呼び出し時 |
フロントエンドコンポーネント
- TranslatableBody: チャットメッセージバブル内(両サイド)の翻訳トグル
- TranslatableText: 応募文等の任意テキストに使用する汎用コンポーネント
- 翻訳中スピナー → 完了後「🌐 AI翻訳 · 原文」ラベル表示
- 翻訳が
translationsに既にキャッシュされている場合はAPIコール不要(即時表示)
9. 通知・メール
通知チャンネル
- database: アプリ内ベルアイコン(常時)
- mail: メール通知(MAIL_MAILER 設定時)
- webpush: プッシュ通知(VAPID キー設定時のみ)
VAPID / WebPush
VAPID_PUBLIC_KEY と VAPID_PRIVATE_KEY が未設定の場合、webpush チャンネルは自動的にスキップされる(500エラーにならない)。
メールテンプレート
MAIL_MAILER=log の場合メールは送信されず storage/logs/laravel.log に記録される。
10. メッセージモデレーション
仕組み
- 送信前に POST /api/moderation/preview でプレチェック
- ルールベース(NGワードリスト)+ GPT-4o によるスコアリング
- action=block: 送信不可(エラー表示)
- action=warn: 警告ダイアログ表示 → ユーザーが選択
- 多言語対応(日本語・英語・中国語・韓国語)
操作ログ・同意ログ
operation_logs: ステータス変更・スカウト・採用等の企業操作証跡を記録consent_logs: スカウト承認・辞退・報酬合意等のINF同意記録- 両テーブルとも法務上の証跡として保存(削除不可)
11. ランクシステム
計算ロジック
- 毎日深夜2時に自動再計算(rank:calculate Artisanコマンド)
- 対象: 公開済みレビュー(published)のみ
- 累計応募数・累計完了数・過去1年の完了数・過去1年のレビュー平均 で判定
12. 法務・利用規約
本セクションは参考情報です。正式な法務資料は別途管理してください。
個人情報の取り扱い
- INFの配送先住所(address / address_2 含む)は企業が商品発送目的のみに使用
- eKYC データは TRUSTDOCK が管理(当システムには書類画像を保存しない)
- 銀行口座情報は Stripe が管理(当システムには保存しない)
- 操作ログ(operation_logs)は企業の操作証跡として保存
同意管理
consent_logs: スカウト承認・辞退・報酬合意等の同意記録- eKYC 同意: プライバシーポリシー + 第三者提供への同意(チェックボックス)
ステマ対策
SNS投稿時は「#PR」表記を必須としており、タイアップ投稿機能・公式アカウントタグ付けを推奨(ガイドライン記載)。
アカウント停止
- 虚偽通報・ガイドライン違反・モデレーションルール違反が確認された場合
- 管理者(Filament)から停止操作が可能
