目次
1. なぜ LINE 双方向化が必要か
マネージャーが Talent Hub で task を approve した後、 そのまま LINE group で タレント / クライアント / 第三者に 「タスクを承りました」 「明日 10:00 撮影リマインダー」 を手入力するのは 二度手間。
- 業務フローの分断: approve → LINE 手入力 で「忘れた」 「コピペミス」 が発生
- group 参加者にも可視化: タレント本人 / マネージャー / クライアントが同じ group にいる場合、 task の合意状態が group 内で記録される
- リマインダー / escalation: 「明日撮影」 「5/15 まで返信ください」 を schedule で自動投稿
- 外部 stakeholder: Talent Hub にログインできない clients / talent にも情報が届く
2. 投稿トリガー (5 種)
① task 承認 (manager approve)
トリガー: task_candidates.status: pending → approved
投稿例: 「✅ 明日 10:00 撮影 衣装持参 の件、 承りました。 マネージャーの XXX が当日確認します。」
② scheduled reminder
トリガー: internal_tasks.remind_at 到達 (cron 1h 周期)
投稿例: 「⏰ 明日 10:00 撮影 のリマインダー。 衣装 2 パターン (黒ワンピ / 白シャツ) 持参でお願いします。」
③ escalation (24h 未対応 P0)
トリガー: task_candidates: P0 + immediate + pending + age > 24h (cron 1h 周期)
投稿例: 「🚨 NIKKEI TVCM 撮影詳細メール送付 が 24h 未対応です。 manager XXX に確認をお願いします。」 (executive 通知の後、 group にも通知するかは opt-in)
④ profile signal 確定通知
トリガー: profile_signal_candidates.status: pending → approved
投稿例: 「📝 talent のプロフィール (狙い / 能力) を更新しました。 詳細は talent page で確認できます。」 (manager 操作の record として group 共有)
⑤ 朝サマリー (talent 個別 / group 個別)
トリガー: cron 毎日 09:00 (talent 個別の active task が 1 件以上)
投稿例: 「☀️ 今日のタスク: 衣装持参 (10:00) / 17:00 打ち合わせ / 制作会社へ辞退連絡。 詳細は talent page。」
3. アーキテクチャ
[トリガー]
│
├─ Talent Hub UI (manager の approve / reject 操作)
│ │
│ └→ webhook → talent_mgmt.task_candidates 更新
│ │
│ └→ AFTER UPDATE trigger or Worker poller
│ │
├─ scheduled cron (Cloudflare Worker、 1h / 24h 周期)
│ │
│ └→ talent_mgmt.line_push_queue に enqueue
│
└→ talent_mgmt.line_push_queue
│
└→ line-push-worker (Cloudflare Worker、 5min 周期)
│
├─ idempotency check (dedupe_key)
├─ tenant の LINE_CHANNEL_TOKEN を Supabase 経由で取得
├─ rate limit check (per tenant, per group)
└→ LINE Messaging API push (https://api.line.me/v2/bot/message/push)
│
└→ 結果を line_push_queue.status 更新
3.1 主要コンポーネント
- line_push_queue (Supabase テーブル): 投稿予定の event を一時保管、 dedupe_key で重複排除
- line-push-worker (Cloudflare Worker): 5min cron で queue を pull → LINE push API 呼び出し
- LINE Messaging API push:
POST https://api.line.me/v2/bot/message/pushで group 指定投稿
4. スキーマ追加
CREATE TABLE talent_mgmt.line_push_queue (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id text NOT NULL,
ext_group_id text NOT NULL, -- 投稿先 LINE group_id (C...)
trigger_type text NOT NULL, -- 'task_approved' | 'reminder' | 'escalation' | 'signal_approved' | 'morning_digest'
payload jsonb NOT NULL, -- LINE Messaging API messages array (1-5 件)
source_table text, -- 'task_candidates' | 'internal_tasks' | ...
source_id text, -- source の primary key
dedupe_key text NOT NULL, -- idempotency 用 unique key (例: 'task:abc-123:approved')
scheduled_at timestamptz NOT NULL DEFAULT now(),
status text NOT NULL DEFAULT 'pending', -- pending | sent | failed | skipped (opt-out)
attempt_count smallint NOT NULL DEFAULT 0,
last_error text,
approved_by uuid REFERENCES talent_mgmt.handlers(id), -- manual approval の場合
sent_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (dedupe_key)
);
CREATE INDEX line_push_queue_status_scheduled_idx
ON talent_mgmt.line_push_queue(status, scheduled_at);
4.1 tenant ごとの push 設定
-- tenant_slack_integrations と同様に LINE 設定も Supabase に持つ
ALTER TABLE talent_mgmt.line_sources
ADD COLUMN IF NOT EXISTS allow_outbound_push boolean NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS push_opt_in_triggers text[] DEFAULT '{}'::text[];
-- e.g. ['task_approved', 'reminder'] のみ許可、 'escalation' 'morning_digest' は除外
5. 承認フロー (誤投稿防止)
LINE group は タレント本人 / クライアント / 第三者 が含まれることが多いため、 誤投稿は信用問題に直結する。 トリガー種別ごとに人手承認の有無を分ける。
| トリガー | 承認 | 備考 |
|---|---|---|
| ① task 承認 (approve) | 自動 (approve 操作が既に承認) | approve 時に「LINE 投稿あり」 chip を UI で明示 |
| ② scheduled reminder | 自動 (task approve 時に reminder schedule を合わせて確定) | approve modal で「リマインダー投稿あり / なし」 を選択 |
| ③ escalation | 手動承認 (executive が再投稿ボタン押下) | group 内信用 risk あるため自動は禁止 |
| ④ profile signal 確定 | 自動 (signal approve が既に承認) | group 内で manager 操作を可視化 |
| ⑤ 朝サマリー | opt-in per group | line_sources.push_opt_in_triggers に morning_digest を含む group のみ |
タレント本人がいる group には escalation / 急かす系 通知を投稿しないこと。 マネージャー間のみの group は別途識別。 line_sources.raw_metadata.audience で internal / mixed / external を区別。
6. 安全策 (idempotency / rate limit / opt-out)
6.1 idempotency (重複投稿防止)
dedupe_keyを unique 制約 (例:'task:abc-123:approved')- 同じ event が複数回 enqueue されても DB 制約で 1 件のみ insert
- worker は
status: pendingを取得して send、 send 後sentに遷移 - 失敗時 (5xx) は exponential backoff で retry (max 3 回)、 4xx は即 failed
6.2 rate limit
- LINE Messaging API push の rate limit: free plan で月 1,000 通 → 商用化は paid (lite/standard)
- per-tenant / per-group の bucket で internal rate limit を設定 (例: 同一 group へ 5min 内 3 件まで)
- 超過時は
status: failed+ last_error で記録、 再送ループしない
6.3 opt-out
line_sources.allow_outbound_push: falseなら全 push を skippush_opt_in_triggers[]で trigger 種別ごとの許可を設定- LINE Routing UI に「この group への自動投稿を許可」 toggle を追加
6.4 LINE Messaging API 課金
- 無料: 月 500 通 / public account
- ライトプラン: 月 5,000 円 / 15,000 通 (フリー account)
- スタンダードプラン: 月 15,000 円 / 45,000 通 + 超過 〜3 円/通
- 事務所単位 (LUV/LIS/PR 等) で 1 アカウント = 1 plan、 plan 課金は tenant 負担 / 自社負担を契約で確定
商用化時は LINE plan 費用を tenant が直接 LINE 公式に支払い、 LINE Memory Pro は channel_secret / channel_token を受け取って動かす方式が clean。 自社が代行支払いすると消費税処理 + 利益計算が複雑化。
7. 実装 Phase
| Phase | 時期 | 達成内容 |
|---|---|---|
| Phase 1 | 2026-06 | line_push_queue migration + line-push-worker (Cloudflare Worker) で ① task 承認 / ② reminder の 2 トリガー実装。 承認は manager の approve 操作で自動、 audience=internal/mixed は manager 確認 |
| Phase 2 | 2026-07 | ③ escalation (手動承認) + ④ profile signal。 Talent Hub UI に 「LINE 再通知」 button、 audience 分類 UI |
| Phase 3 | 2026-08 | ⑤ 朝サマリー opt-in 機能。 LINE Routing UI に push 設定 panel、 per-trigger opt-in、 task summary template 編集 |
| Phase 4 | 2026-09 以降 | LINE Flex Message でリッチ表示、 LINE 内の talent quick view、 LINE 内 task approve ボタン (LINE LIFF or webhook reply) |