LINE CRM マルチテナント設計
cherimi × Ledian Spa の管理画面統合 / 2026-04-15
cherimi(アパレル)
Ledian Spa(脱毛)
そもそもの3つの選択肢
A
完全別建て
採用
サーバー(Worker)もDB(D1)も別物のまま、ログインUIだけ統合
[統合ログイン] ├─ cherimi選択
→
Worker① → DB①
└─ Spa選択
→
Worker② → DB②
👉
今すでにこの状態
。フロントだけ統合工事で済む。事故りにくい。
B
全部1つにまとめる
絶対NG
サーバーもDBも1つ。テーブルに
tenant_id
列を追加して見分ける
[統合ログイン]
→
1つのWorker
→
1つのDB SELECT * FROM users WHERE tenant_id='cherimi'
WHERE句を1回でも書き忘れたら全員に誤配信。取り消し不能。
C
サーバー1つ・DBは別物
不要
1Workerに2つのDBバインド、URLで切替
👉 Bよりマシだが、もう分かれてるAをわざわざ統合する理由がない
RECOMMEND
A を採用 + フロント側だけ統合
既存の物理分離を維持したまま、ログインUIだけ1つにする。一番事故らない。
誤配信を絶対起こさない 6層防御
1
物理分離(最重要)
D1・Worker・LINEチャネルトークン・配信ドメインを完全別建てで維持。Workers Secrets は各Worker内に閉じ込め、共有禁止。
2
ドメイン分離(強く推奨)
cherimi-crm.example.com
/
spa-crm.example.com
のサブドメイン強制
Cookie はサブドメインスコープ → セッション混在不能
統合ログインは
auth.example.com
に置き、認証後にテナント選択 → 該当サブドメインへリダイレクト(Stripe方式)
URLバーで常に視認できる = 一番誤操作しにくい
3
UIガードレール
ヘッダー帯をテナント別カラー固定(cherimi=ピンク / Spa=ネイビー)
配信ボタン押下時、テナント名を手入力させる確認モーダル("cherimi" とタイプ)
配信先サンプル3名(マスク済表示名)プレビュー必須
4
配信フロー
dry-run で対象人数+サンプル userId 必須表示
即時送信禁止 → Cloudflare Queues で30秒猶予(キャンセル可)
テスト送信で自分のLINEに必ず流す
5
サーバー側API
テナント識別はサブドメインから抽出(クライアント送信値は信用しない)
hostname / セッション / Worker
の三点照合、不一致は即拒否
監査ログ(誰が・いつ・どのテナントで・何人に配信したか)を immutable 保存
6
認証
Google OAuth + メールallowlist + テナント別メンバーシップ
Cookie:
Secure / HttpOnly / SameSite=Strict
CSRFトークンに tenant_id を埋め込み、テナント切替時はセッション再発行
見落としがちな事故源
CSV取込時のテナント誤投入
→ ファイル名にテナントprefix強制、不一致は弾く
同じ人が両公式の友だち
→ line_user_id 単独で突合せず内部IDで管理
テスト用LINE公式の本番混入
→ Worker自体を別建てにし到達不能化
バックアップのPII漏洩
→ 取得者ローカルに降ろさない
次のアクション
1
ドメイン設計確定(auth / cherimi-crm / spa-crm のサブドメイン取得)
2
Next.js管理画面を auth用ログイン + テナント別ビルドに分割
3
Worker側に「hostnameチェック+session照合」ミドルウェア追加
4
dry-run / Queues猶予 / タイプ確認モーダルを配信フローに組込み
5
テスト用LINEチャネルでSpa側を素通し配信、防御が想定通り効くか検証
cherimi LINE CRM Design Doc / generated 2026-04-15