💻 システム開発

SCALE_FORM_開発依頼書

最終更新 2026年07月20日 / 31_システム開発部/_SCALE_FORM_開発依頼書.md

SCALE FORM 開発依頼書

これは新セッションでSCALE FORMをゼロから作るための正本ドキュメント。
SCALE CRM(scale-lead)で2026-04〜07に起きた全事故・全FB・全設計教訓を反映済み。
開発セッションは最初にこれを全文Readし、「§9 初動チェックリスト」から着手すること。
発注者: 大串勇輝 / 起草: Claude(SCALE CRM v11.6.x 改修セッション・2026-07-20)


0. 最初に確認すべき1点(命名衝突)

「SCALE Form」という名前の既存プロダクトが存在する~/株式会社SCALE/scale-form/・Next.js製・サービス資料PDF/PPTX作成済みの外販プロダクト)。今回の「フォーム営業自動化」とは別物。
→ 着手前に大串に確認: ①既存SCALE Formを置き換える/廃止する ②本ツールを別名にする(例: SCALE FORM Sales / SCALE Autoform) ③同名で世代交代。リポ名・Cloudflare project名・チャンネル名が衝突するため、ここだけは決めてから作る。


1. プロダクト定義

  • SCALE FORM = フォーム営業の完全自動化ツール
  • コア価値: 「リストを入れれば、企業HPの問い合わせフォームを見つけて、精度高く・制限なく・自動で営業文を送り続けてくれる」
  • 利用者: まず自社(SCALE社内+パートナー)。将来外販(この前提が設計に効く→§4)。
  • SCALE CRMとの関係: CRMのチャネル概念(teleapo / linkedin / both)に form を追加できる姉妹システム。リスト資産(リストプール/SalesNow CSV)と成果報告(Slack)はCRMの型を流用する。
  • ゴール指標: 送信成功数 / 送信成功率(フォーム検出率×送信完了率)/ 返信数。「数を撃てる」だけでなく「誤送信ゼロ・二重送信ゼロ」が製品の信頼=外販の生命線。

2. 技術スタック(ベース=SCALE CRM・実績構成を踏襲)

採用 備考
フロント 静的SPA(素のHTML/CSS/JS・フレームワークなし) CRMと同型。style.cssのCSS変数・UIパターンを流用(§7)
ホスティング Cloudflare Pages GitHub(scale-group-jp・private) + GitHub Actions自動デプロイ + deploy.sh(退化チェック付き・CRMのdeploy.shを雛形に)
DB Cloudflare D1 最初から1レコード=1行のper-rowテーブル設計(§4-1)
API Pages Functions (TypeScript) CRMの functions/ 構成を踏襲
送信エンジン(新規要素) Cloudflare Queues + Cron Triggers + Browser Rendering API(Puppeteer互換) フォーム巡回・送信はクライアントでなくサーバー側ワーカーで実行。ブラウザを閉じても送信が続く=「制限なく送る」の実現手段。CRMに無い要素なので技術検証(PoC)をPhase 1に含める
AI 既存AIプロキシ(scale-ai-proxy.y-ogushi.workers.dev)流用 文面パーソナライズ・フォーム項目マッピング補助
Slack Bot Token(scale-ai-team)+ /api/slack/proxy 型 チャンネル自動作成・通知・メンションはCRMの現行仕様を最初から実装(§8)

3. SCALE CRMの実事故から継承する設計原則(最重要・全部必須)

CRMは「動いてから直す」で以下を全部本番事故として踏んだ。SCALE FORMは最初から組み込む。
各原則の詳細は _SCALE_共通_トラブルシューティング集 のA1〜A13・E1〜E2を参照。

3-1. データを消さない・巻き戻さない(事故: A10/A11/A12/A13)

  1. 「1件の変更のために全体を書き戻す」実装は全面禁止。保存・削除・PW処理は必ず行単位のUPSERT/DELETE(CRM実事故: ログイン処理が全メンバーを古いスナップショットで上書きし、新メンバーの設定が消えた=A11)。
  2. 重要な書き込みは「即時await+1.5秒後にD1実読で一致検証+不一致なら自動修復+警告表示」の完了保証型をヘルパーとして最初に作り、全書き込みで使う(CRM: _memVerifySavedOne/_memVerifyDeleted が後付けになった反省)。「ローカル反映+バックグラウンド送信」だけの保存を作らない(A12: 削除がリロードで復活)。
  3. blob(配列全体を1キーに保存)方式は採用しない。ミラー・後方互換blobも作らない(A13: per-row/blobの二重世界に保存が分裂・orphan自己修復がゾンビ復活を起こした)。
  4. 機能フラグで読み書き経路を分岐させない。分岐が必要な場合も「未ロード時の既定」を全端末で一意にする(A13の根因)。
  5. 削除は「自動復元機構(自己修復・キャッシュ・バックアップ同期)の復元材料を先に断ってから本体を消す」順序で。

3-2. 性能はO(1)を最初から(事故: E1・v11.6.3の後追い一掃)

  1. 行数に比例する処理をイベントごとに走らせない: 一覧は最初から仮想スクロール(CRMの _clRenderRows/_clVirtualRender を移植)・頻出計算はメモ化(WeakMap+キー検証型)・ソートは事前計算(Schwartzian)・統計は短命キャッシュ+編集時無効化。
  2. 定期同期は差分(since+10秒オーバーラップ)を主とし、全件再取得はdigest(件数+MAX(updated_at)の軽量プローブ)一致でスキップ(CRM v11.6.3実装を移植。保険として30分に1回は本物のfullを走らせる)。
  3. 初回ロードは並列チャンク取得(CRM v11.6.5の4並列を移植)。
  4. 配信: 版付きアセットは ! 記法つき_headersでimmutable 1年キャッシュ(Pagesの_headersは同名ヘッダを結合する仕様・CRM実測)+ deploy.shの?v=自動更新 + Service Worker + 左下バージョンバッジ&新版検知をCRMから移植。

3-3. 外部連携はsilent failさせない(事故: v11.6.9/v11.6.11/v11.6.14)

  1. Slack通知・招待・送信系の失敗を握りつぶさない。結果は「成功N/失敗M+理由+対処ヒント」で必ず画面表示。Promise.allSettledで潰して成功風トーストを出す実装は禁止。
  2. 一括APIは「1件の失敗が全体を失敗させる」仕様がある(Slack conversations.invite実証済み)→ 一括失敗時は1件ずつ自動フォールバックし、失敗だけ名前つき報告。
  3. 設定値(Bot Token等)の解決を端末のキャッシュ状態に依存させない: ローカル→D1直接fetchの多段フォールバック(CRM _slackResolveBotToken型)を最初から。
  4. 観測ログを最初から仕込む([TAG]付きconsole・PerformanceObserver longtask)。「メンバーの報告頼み」にしない。

3-4. 認証・権限(事故: v11.6.2/E2・外販前提)

  1. 最初から個人アカウント制: メール+個人PW(作成時からPBKDF2ハッシュ・平文保存と遅延ハッシュ化を採用しない=lazy-hash構造そのものを作らない)。セッションはHMAC署名cookie+スライディング延長(CRM v11.5.82型)+名簿照合による退職者即時遮断。
  2. 権限は「表示の制限」でなく「実行点のゲート」(CRM v11.6.2の教訓: UIで隠しても、案件切替・古いセッション経由で所属外を操作できた)。切替関数・送信実行・API全てで検証。
  3. 認証失敗はサイレントにしない: 401/403検知→再ログインバナー(E2: 無限スピナーの反省)。
  4. 外販を見据え、テナント境界(クライアント企業ごとのデータ分離)を最初からデータモデルに持つ(project_id相当を全テーブル必須カラムに。マルチテナント化はやらないが、やれる形にしておく)。

3-5. 集計・表示のお作法(大串FB群)

  1. 時刻はUTCのISO文字列を直接sliceして表示しない。必ずnew Date()経由のJST表示(A13実事故: 依頼時刻が9時間ズレ)。
  2. 集計は「最新の真実」: 削除・取消データを母集団から除外するフィルタを最初から(feedback_always_latest_truth)。
  3. 重複防止は「既存データに一切触れない完全スキップ」が既定(CRMセグメント被り事故: 既存行への追記が「他人の担当リストに混入」を生んだ)。スキップwas何件かは結果メッセージに明示。

3-6. 運用・デプロイ(恒久ルール)

  1. リポ直下にスタートカード(CLAUDE.md)を初日に作る。GitHub(scale-group-jp)接続・git logが現在地。
  2. changelog機構(CRMのCOCREATE_VERSIONS型)をservice.js相当に内蔵し、左下バージョンバッジ(クリックで履歴・PMのみ詳細)を付ける。deploy.shの必須関数チェックも初日に整備(意図的削除時はリストも更新)。
  3. デプロイ報告は「本番URL+アプリ表示verの実測」をセットで。wrangler成功表示を信じず本番実バイト(MD5/文字列)で検証
  4. 調査で「0件/空」という結果が出たら生出力で再確認(wrangler出力のパース失敗を0と誤断定した反省)。

4. SCALE FORM固有の設計(ここが製品の心臓)

4-1. データモデル(最初からper-row・D1)

  • form_targets(送信対象企業): project_id / target_id / data(JSON: company, url, form_url, status, 送信履歴参照...) / updated_at / updated_by。generated column + index を最初から(c_status, c_company, c_deleted 等。CRM Phase1の型)。
  • form_sends(送信ログ・証跡): 1送信=1行・絶対に上書きしない追記型。送信日時/使用文面/フォームURL/結果(成功・失敗理由)/スクリーンショットR2キー。外販時の信頼性はこのログが担保する。
  • form_campaigns(キャンペーン=文面×リストの単位)/ form_templates(文面・差し込み変数)。
  • メンバー・案件はCRMと同型(member_rows/projects)。将来CRMと名簿を共通化する前提でスキーマを揃える

4-2. 送信エンジン(精度=製品価値)

  • パイプライン: リスト投入 → フォームURL探索 → フィールド解析 → 文面差し込み → 送信 → 結果記録 → 通知。各段の状態を form_targets.status で明示(未処理/フォーム検出済/送信待ち/送信済/フォームなし/送信失敗/営業お断り検出/CAPTCHA/重複スキップ/対象外)。
  • 冪等性が最優先: 送信前に必ず form_sends を照会し「同一企業×同一キャンペーン」は構造的に二重送信不能にする(DBのUNIQUE制約レベルで)。リスト再投入・リトライ・並行ワーカーでも二重送信しない。
  • 「営業お断り」尊重を製品仕様に: フォームページに「営業目的の問い合わせはお断り」等の文言を検出したら自動スキップ+status記録。これは外販時の営業トークにもなる(マナー設計)。
  • CAPTCHA/reCAPTCHA検出時は無理をしない: 自動スキップ+「人間フォールバックキュー」に積む(手動送信リストとしてUI表示)。突破の試みはしない。
  • レート制御: ドメインごと・全体の送信間隔を設定可能に(既定は保守的に)。時間帯制御(営業時間内のみ等)。
  • 検証モード(ドライラン)を最初から: 「送信直前まで実行し、実際には送らずフィールドマッピング結果とプレビューを人が確認できる」モード。精度のチューニングと初期の信頼獲得はこれで行う
  • 失敗理由の分類を細かく記録(フォーム未検出/必須項目マッピング不能/送信ボタン特定不能/確認画面で停止/reCAPTCHA/タイムアウト)→ 精度改善のループを回せる。

4-3. AI活用

  • フォームフィールドのマッピング(label/name/placeholder→ 会社名/氏名/メール/本文...)はルールベース+AI補助のハイブリッド。AI結果はキャッシュ(同一フォーム構造の再解析禁止)。
  • 文面パーソナライズ: テンプレート+変数差し込みを基本とし、AI生成はオプション(全文AIは検閲コスト高・まず差し込み精度で勝つ)。

4-4. SCALE CRM連携(Phase 4)

  • projects.channel に form を追加できる形(CRM側は channel 概念を温存済み)。
  • リストプールから「フォーム営業へ分配」導線(分配時は既存対象の完全スキップ・セグメント追記なし=CRM v11.6.12の教訓そのまま)。
  • 成果(返信・アポ化)はCRMのアポ報告フローに接続。

5. 法務・マナー(外販前提の必須確認)

  • 問い合わせフォーム営業は特定電子メール法の直接対象外だが、「営業お断り」明記先への送信・過度な頻度は苦情/レピュテーションリスク。①お断り検出スキップ ②同一企業への再送クールダウン(既定90日等・設定可)③送信元情報(社名・連絡先・オプトアウト案内)を文面に必須挿入、を製品仕様として実装。
  • 外販時の利用規約で「利用者が送信内容の責任を負う」建付けが必要になる→ Phase 4で大串と法務整理(契約書は別セッション管理ルール)。

6. フェーズ計画(各Phase完了ごとに大串レビュー)

Phase 内容 完了条件
1. 基盤+PoC リポ/スタートカード/認証/デプロイ一式(§3の基盤全部)+ リストCSV取込 + Browser Renderingでのフォーム検出・送信PoC(実在サイト3種で検証) 技術検証レポート+ドライランが動く
2. 送信エンジン Queues+Cronの自動送信・冪等性・レート制御・全ステータス・送信ログ・Slack通知 自社リスト100件でドライラン→少量実送信
3. 精度改善 失敗分類ループ・AIマッピング補助・人間フォールバックキュー・ダッシュボード(KPI) フォーム検出率/送信成功率の実測レポート
4. CRM連携+外販準備 channel=form・リストプール連携・アポ報告接続・テナント境界の検証 自社運用1ヶ月の実績

7. デザイン

  • SCALE CRMのstyle.css(ダークテーマ・CSS変数・カード/バッジ/モーダル/トースト/サイドバー構成)をそのまま流用して統一感を出す(将来SCALEプロダクト群としての外販にも効く)。
  • 大串FBの既定: セクションに説明文を置かない(タイトルのみ・OK例外=件数/KPIライブ数値)/ 入力欄に初期値を入れない(placeholder例示はOK)/ リンクは本番URLのみ/ 絵文字はタイトル行のみ・本文には付けない/ モバイル対応(パートナーはスマホ操作あり)。
  • 新UIは「既存画面に溶け込む最小形」を基本に。新しい画面/モード/操作体系を足す提案は着手前に大串へ1行確認(連続架電モード作り直しの教訓: 大串のイメージは「今の画面のまま1手間消える」であることが多い)。

8. Slack連携(CRM現行仕様を最初から)

  • 案件専用チャンネル自動作成(<slug>_フォーム営業支援_送信報告 等・命名はCRM準拠)+ 担当パートナー/PM自動招待(招待は個別フォールバック+失敗の名前つき表示=v11.6.11実装を移植)。
  • 通知: 送信サマリ(日次)/ 返信検知(可能なら)/ エラー多発アラート。PM+担当メンションつき(現行のメンション方針・_slackBuildMentions型)。スレ型は親タイトルにメンションなし・中身に付ける。
  • Bot Token解決は3段フォールバック(§3-12)。

9. 開発セッションの初動チェックリスト(この順で)

  1. 本依頼書を全文Read+大串に命名(§0)の決定だけ確認
  2. Read: _SCALE_全システム実装ルール / _SCALE_共通_トラブルシューティング集(A10〜A13・E1〜E2は精読)/ ~/dev/scale-lead/CLAUDE.md
  3. gh repo create scale-group-jp/<リポ名> --private → リポ直下CLAUDE.md(スタートカード)作成 → 22_AI運用ルール/_ルールブック 7章に登録
  4. CRMから流用するファイルの写経元: style.css / deploy.sh / service-worker.js / _headers(!記法込み)/ functions/_lib/(auth系は「行単位書き込み・作成時ハッシュ」に改めて新規実装)/ 仮想スクロール・メモ化・digest等の性能部品
  5. Phase 1着手。コード変更→デプロイ→本番実バイト検証→changelog→commit+push を毎回セットで
  6. 毎Phase完了時に大串レビュー+Vault作業ログ

10. この依頼書の根拠(参照元)