SOLUTION ARCHITECTURE · DESIGN PROPOSAL v4
SF改修 → BQ / ダッシュボード
SF改修 → BQ / ダッシュボード
影響事前検知システム 設計提案
Salesforceの宣言的なスキーマ変更が、後続のBigQuery・経営コクピットのダッシュボードを「壊れてから気づく」状態を解消する。依存関係の地図(辞書)と自動スキーマ差分検知を土台に、データチーム側だけで完結して動かす。
How to read
読み方・凡例
凡例
- 結論ファースト: 各章は「要は何か(So What)」を先に置き、根拠は小さく添える
- 確信度: ★★★A 一次情報(コード/データ実体) / ★★B 二次情報(本人回答・部分確認)
- 2つの依存経路: Path A=SF→SQL→…→ダッシュボード(SQL経由) / Path B=ダッシュボードのGASがSFを直読み(SQLを通らない近道)
Section 1 · Problem
課題:要は何が問題なのか(結論ファースト)
SFの変更(スキーマもデータも)が、テスト・検証・可視化の仕組みが無いまま後続を沈黙的に壊す。
根因は依存と整合性が地図化されておらず、変更・不整合を捕まえる自動の仕組みが無いこと。
根因は依存と整合性が地図化されておらず、変更・不整合を捕まえる自動の仕組みが無いこと。
① 検知不在事前も事後も変更を捕まえる仕組みが無い。依存の地図そのものが存在しない
② 沈黙故障リネームやデータ同期漏れはエラーにならず欠落化。気づくのは「ダッシュボードが変」と人が言った後
So What(だから何が必要か)
対症療法(壊れたら直す)では追いつかない。SFの変更には2系統あり(スキーマ変更/データ品質)、どちらも (1) 依存と整合性を地図化し、(2) 変更・不整合を自動で捕まえ、(3) 影響と直し方を提示して通知する 仕組みが要る。加えてSFチーム側のテスト・レビュー・脱属人化が根本対策になる。
問題は2クラスある(重要)
| 観点 | クラス① スキーマ変更 | クラス② データ品質・同期 |
|---|---|---|
| 中身 | 項目リネーム/型/選択肢値の変更が後続BQ・ダッシュを沈黙破壊 | SFへのデータ同期漏れ・件数不整合(例: VISION申込10件が ReboostData__c に来ない/SF・スプシ・BQで件数バラバラ) |
| 根因 | 依存の不可視 + 検知不在 | テストフロー不在・属人化・リリース前の差分照合プロセス無し |
| 直接効く打ち手 | 依存の地図 + スキーマ差分検知(本設計の中核) | リリース前のデータ差分照合ゲート + 脱属人化(本設計の検知エンジンを"データ照合"に拡張) |
| 出典 | 2026-04-16 事故 ★★★A | SYSDEVREQ-1714 / Slack(西川「移行時に差分チェックするプロセスを必ずリリース前に」) ★★★A |
SFDXとの関係(先出し)
SFDX(設定のコード化・GitHub管理)は両クラスの根因にある「テスト・レビュー・脱属人化の欠如」の構造的な解。ただしSFDXは設定(メタデータ)のソース管理であって、クラス②のデータ照合そのものを肩代わりはしない。=SFDXは"必要性が実証された構造の本丸"だが、特効薬ではなく順番で入れる(詳細は最終章)。
根拠(確認済みファクト・補足)
| スキーマ事故 | 2026-04-16 SurveyLpCurrentGoal__c→SurveyLpConcerns__c のリネームを integrated_customer_analytics.sql 等でCOALESCEで事後対応した痕跡 ★★★A |
| データ事故 | THE VISION:申込19件中SFに9件しか同期されず10件欠落、SF/スプシ/BQで件数不整合→スコアカード集計を一時停止(SYSDEVREQ-1714) ★★★A |
| テスト不在・属人化 | 福原「テストというより項目作成とインポートをこちらで実施」/「このシート触るの怖いのでそのまま」=SF側にQA・差分照合プロセス無し、特定個人依存 ★★★A |
| 2系統の依存 | Path A: SF→staging_*(毎時)→…→ダッシュボード。Path B: org-coaching.gs が OrganizationalCoaching__c を直読み ★★★A |
| 土台は揃う | sf_utils.py でSFスキーマ全取得可、Slack/Backlog即通知可、コクピットGASはパース可能 ★★★A |
| 変更手段 | SF変更は基本「管理画面の宣言的UI変更」=デプロイ・履歴・レビューが存在しない ★★B |
Section 2 · Architecture
推奨アーキテクチャ(理想形)
設計の核は 依存関係の地図(辞書)を土台に置き、2方向の入口(事後の自動検知/事前の人間起点)から同じ1つの出口(影響の提示+通知)へ繋ぐこと。
flowchart TB
classDef core fill:#e8eef7,stroke:#1A365D,color:#1A365D
classDef auto fill:#dcfce7,stroke:#15803d,color:#14532d
classDef human fill:#ede9fe,stroke:#7c3aed,color:#4c1d95
subgraph BASE["土台:依存関係の地図(辞書)"]
psql["SQLを読み解いて依存を抜き出す"]:::core
pgas["コクピットGASを読み解いて依存を抜き出す"]:::core
dg["依存の地図(辞書)
『この項目を変えたら、どのBQ表・SQL・
ダッシュボードのKPIが倒れるか』を引ける"]:::core
psql --> dg
pgas --> dg
end
subgraph AUTO["事後(自動・必須):SF変更を毎時みはる"]
snap["describe で SFの設計図
(項目・型・選択肢値)を読み取る"]:::auto
diff["前回と差分をとる
(消えた / 増えた / 型変更 / 選択肢値変更)"]:::auto
snap --> diff
end
subgraph PRE["事前(人間):既存の依頼フローを拡張"]
form["既存:依頼フォーム→Backlog→Slack→Claude要件Q&A"]:::human
lookup["変更前に影響を引く /sf-impact (Slack)"]:::human
end
engine["影響を照合する
変更 × 依存の地図"]:::auto
act["影響と直し方をまとめて知らせる
Claude修正案 + Slack通知 + Backlog起票"]:::auto
dg --> engine
diff --> engine
form --> engine
lookup --> engine
engine --> act
図1:依存の地図(土台)の上に、事後(自動)と事前(人間)の2入口が共通エンジン→出口へ繋がる
So What
土台(依存の地図)+自動検知を先に作れば、人が何を忘れても事故は激減する。 事前の入口(既存フォーム拡張・Slackルックアップ)は「より早く・上流で」捕まえる付加価値。土台はあくまで地図と自動検知。
運用の独立性(重要)
毎時自動で検知するので、SFチームに「デプロイ前に確認して」と依頼する必要がない。検知・差分・通知・起票はraftel(データチーム)側で完結して動く。必要なのは最初のSF接続認証(Connected App/JWT)の設定だけ。=相手チームの運用を変えずに今すぐ始められる。
拡張:データ差分照合(クラス②対応)
同じ「スナップショット + 差分 + 照合」の仕組みは、スキーマだけでなくデータの整合性照合にそのまま広げられる。SF ↔ スプレッドシート ↔ BQ の件数・主キーの一致を毎時照合し、ズレたら通知。THE VISIONの10件同期漏れ(SYSDEVREQ-1714)のようなデータ事故の安全網になり、これもデータチーム側で完結する。=検知エンジンは1つで、スキーマ差分/データ差分の両方を担える。
Section 3 · Operational Flow
業務フローとシーケンス
運用は2つの流れ。事後(安全網)=SF変更が起きたら自動で検知して通知。事前(上流)=開発依頼フォームでSF項目変更の意図を検知したら、影響を要件Q&Aにインライン提示してBQチームへ事前連携。
フロー① 事後(自動の安全網)
sequenceDiagram
autonumber
actor admin as SF変更者
participant sf as Salesforce
participant sys as 検知システム(raftel)
participant dg as 依存の地図
participant slack as Slack(西川/稲川)
participant bl as Backlog
admin->>sf: 項目/選択肢値をUI変更
loop 毎時
sys->>sf: describe で設計図を読み取る
sys->>sys: 前回スナップと差分をとる
end
sys->>dg: 変更項目/値を照合
alt 後続に影響あり
dg-->>sys: 影響先(SQL・ダッシュボード・KPI)
sys->>slack: 影響 + Claude修正案を通知
sys->>bl: SYSDEVREQ に自動起票
else 影響なし
sys->>sys: 記録のみ(通知しない=ノイズ抑制)
end
図2:SF変更を毎時の差分で検知し、地図に当たった時だけ通知・起票する
フロー② 事前(依頼インテイク拡張)
sequenceDiagram
autonumber
actor req as 依頼者
participant form as 開発依頼フォーム
participant claude as ClaudeCode(要件Q&A)
participant dg as 依存の地図
participant slack as Slack(西川/稲川)
req->>form: 開発依頼を送信
form->>claude: Backlog起票 + 要件整理を開始
claude->>claude: SF項目変更の意図を検知
alt SF項目変更を含む
claude->>dg: 変更前に影響を引く
dg-->>claude: 影響先一覧
claude->>req: 要件Q&Aに影響をインライン提示
claude->>slack: 西川/稲川へ事前連携
else 通常依頼
claude->>req: 通常の要件Q&A
end
図3:既存の依頼フロー(稼働中)にSF影響ブランチを差し込む。新ツールは増やさない
Section 4 · How it works
仕組みの具体例(describe / 依存の地図)
① describe=「SFの設計図を読み取る」
あるオブジェクト(テーブル相当)の全項目の仕様(設計図)を一発で取るSFの機能。sf_utils.py が裏で SF CLI を叩いて返す。これを毎時取って前回と比べる=検知の心臓。
# describe("OrganizationalCoaching__c") が返す1項目の例 { "name": "StageName__c", // API名(リネーム検知の主キー) "label": "商談フェーズ", // 画面表示名 "type": "picklist", // 型(変更を検知) "custom": true, "nillable": true, "picklistValues": [ // ← 選択肢値(StageName__c問題の検知) {"label": "担当者ビジネスMTG", "active": true}, {"label": "フロント受注", "active": true}, ... ] }
ポイントdescribe は設計図を読み取るだけ。SF管理画面でUI変更しても変更後の設計図に反映される → UI運用のままで検知できる。
② 依存の地図(dependency-graph.json)=「何が倒れるかを引ける辞書」
「SFのこの項目を変えたら、どのBQテーブル・SQL・ダッシュボードのどのKPIが倒れるか」を機械が引ける地図(辞書)。SQL/GASをパースして自動生成し、手では持たない(CIで再生成=腐らせない)。
// 変更項目をキーに引くと、影響先(consumed_by)が一覧で返る { "OrganizationalCoaching__c.StageName__c": { "type": "picklist", "使われている選択肢値": ["担当者ビジネスMTG", "フロント受注", "本契約受注"], "consumed_by": [ { "経路": "B(GAS直結)", "資産": "management-cockpit/org-coaching.gs", "KPI": ["組織コーチング_ファネル各段階"] } ] }, "Lead__c.SurveyLpConcerns__c": { "type": "picklist", "consumed_by": [ { "経路": "A(SQL経由)", "資産": "sql/staging/staging_Lead__c.sql" }, { "経路": "A(SQL経由)", "資産": "sql/analytics/integrated_customer_analytics.sql" }, { "経路": "A(SQL経由)", "資産": "management-cockpit/carispi.gs", "KPI": ["キャリスピ商談フェーズ"] } ] } }
使い方変更項目をキーに引く→
consumed_by が影響先一覧。これが「何をどう直すか提案」の事実の源。LLMはこの事実を文章化するだけで、依存を推測させない。Section 5 · Implementation Gaps
実装論点:現状から理想形への差分
「当初の2ポイント案(①依頼フォーム連携 ②デプロイ前テスト)」で既に実現できている点も含め、理想形に対して何が足りないか=何を実装するかを差分で整理する。
| 論点 | 現状(当初2点で実現済み含む) | 理想形への差分=実装すること |
|---|---|---|
| ① 依存の地図(土台) | 無い。依存の地図そのものが存在しない。当初案の「事前用意の辞書」は着想として◎ | SQL+GASをパースして自動生成。Path A/B・選択肢値もカバー。これが全部の土台 |
| ② 自動差分検知(事後) | 無い。当初Point2は「デプロイ前テスト」を意図したが、SFはUI変更中心でデプロイが存在しない | describe 毎時スナップ→差分に作り替え。人手非依存の安全網。リネームは「旧消滅+新出現」、選択肢値も差分 |
| ③ 事前トリガ(依頼拡張) | フォーム→Backlog→Slack→Claude要件Q&Aは稼働中(当初Point1で実現済み・SYSDEVREQ-1679) | SF項目変更を検知→影響をQ&Aにインライン提示+事前連携。Slack /sf-impact 追加 |
| ④ アクション層 | Slack/Backlog即実行可(西川/稲川ID既知) | 決定論の影響+Claude修正案を生成し自動起票・通知(LLMは提案文に限定) |
UX観点(So Whatで要約)
新しいポータルを作らず、既存導線(Slack/フォーム)に溶かす。 SF変更者はCLIを使わない前提で、依頼Q&Aが自動で影響を出す+
/sf-impactで即答。BQチームには「影響+修正案+課題ワンクリック」、依頼者の体験は劣化させない。
運用保守観点(So Whatで要約)
依存の地図はコードからCI再生成(手で持たない=腐らせない)。 検知はCloud Run Jobで毎時(日次ダッシュ更新前に通知)。前提はSF接続認証(Connected App/JWT)。リポ境界は「検知コア=raftel/インテイク=別リポ」。
QA上の急所(事故らせない)
偽陰性を最優先で潰す:①リネームは沈黙NULL化→差分で必ず捕捉、②選択肢値ハードコード→picklist値も差分、③静的パースで漏れる経路(動的補間/clasp外Sheets/KUZEN)は「未カバー」と正直に明示し段階拡張。偽陽性(通知疲れ)対策:地図に当たった変更のみ通知、99%+NULLの死蔵473項目は除外。受入条件=2026-04-16事故の再現で影響先が正しく出ること。
Section 6 · Roadmap
段階導入ロードマップ
0
Phase 0(土台): 依存の地図 + 検知エンジン
- raftel SQL/コクピットGAS(CIでclone)をパース→ SF項目・選択肢値・Path A/B を抽出
Exit: 2026-04-16事故カラム投入→影響先(SQL群+4ダッシュボード)を正しく列挙
1
Phase 1(安全網・クラス①): 自動スキーマ差分検知+通知
describe毎時スナップ→差分→照合→Slack通知。死蔵473項目は除外、BQ失敗監視も併設
Exit: SFテスト項目/選択肢値の変更→1時間以内にSlackアラート
1+
Phase 1+(安全網・クラス②): データ差分照合
- 同じエンジンで SF ↔ スプシ ↔ BQ の件数・主キーを毎時照合。ズレたら通知。リリース前検証ゲートにも転用
Exit: VISION型(件数欠落)の不整合を自動検知→スコアカード停止のような事態を未然に
2
Phase 2(提案+起票): アクション層
- 影響先(決定論)+Claude修正案→Backlog自動起票・担当割当
Exit: アラートに「何をどう直すか」が付く
3
Phase 3(上流): 既存依頼インテイク拡張
- フォームのClaude Q&AにSF影響ブランチ+Slack
/sf-impact(前提: インテイク基盤リポ確立)
Exit: 依頼の入口でSF影響が見える/変更前セルフチェック可
4
Phase 4(構造の本丸・段階導入): SFDX/GitHub化 + 契約ビュー層
- SFを段階的にSFDX化し、検知をデプロイ前ゲートへ昇格+設定の属人化を解消(最終章参照)。安定列名の契約ビューで結合を1箇所に集約
Exit: SF設定変更がレビュー+CIを通る/脱属人化が進む
まず取る一手Phase 0→1→1+ だけで「スキーマ事故もデータ事故も激減する自動の安全網」が、データチーム側だけで完結して立ち上がる。ここが準備度×インパクトの高いクイックイン。SFDX(Phase 4)は必要性が実証された今、価値を示しつつ段階導入する。
Structural Core / 構造の本丸
SFDX / GitHub化 — 必要性が実証された構造の本丸(段階導入)
SFDXは、SFの設定(項目・フロー等)をコード化してGitHubで管理するやり方。直近のVISION事故は「テストフロー不在・属人化・レビュー無し」が根因で、SFDXはその根因の構造的な解。検知システムはSFDX無しで完結するが、SFDX化すると検知が「事後の網」→「デプロイ前ゲート」に昇格する。
正直な線引き(盛らない)
SFDXは設定(メタデータ)のソース管理=設定変更の履歴・レビュー・CI・脱属人化に効く。一方、VISION事故の核であるデータ同期漏れ・データ照合は、SFDX単体では直接解けない(それは Phase 1+ のデータ差分照合が担う)。=SFDXは"必要性が実証された本丸"だが万能薬ではない。だから「今すぐ全面SFDX化」ではなく順番で入れる。
BQ連携以外に、どんな恩恵があるか
UIのまま続けるリスク
- 誰が・いつ・何を変えたか履歴が残らない
- レビュー・承認なしで即本番反映
- 変更前に影響もテストも確認できない
- ロールバックが手作業・属人化
SFDX+GitHub管理の恩恵
- 変更がコード化→履歴・差分・レビューが効く
- デプロイ時にCIゲート=検知が事前ゲートに昇格
- ロールバック・複数人並行が安全に
- AIが差分を読んで自動レビュー・修正できる
どのくらいクリティカルか(評価更新)
スキーマ事故(4/16)に加えデータ事故(VISION/1714)、さらにテストフロー不在・属人化・ブラックボックス化という運用そのものの脆さが立て続けに露呈。「過剰」ではなく必要性は実証済み。ただしGitHub文化ゼロのSFチームに一気に乗せると形骸化する。=判断は「やるか否か」ではなく「順番」。設定がコード化されて初めて人とAIの分担(AI代替活用度の引き上げ)が成立する、全社DXの足場。
UI → SFDX へ移行するステップ(ざっくり)
| ステップ | 内容 | 工数感 |
|---|---|---|
| 1. 環境準備 | SF CLI + GitHubリポ + 接続認証 | 数日(技術) |
| 2. 現状をコード化 | 既存の項目・フロー等を取り出してGit管理に載せる | 1〜2週(技術) |
| 3. 運用切替+CI | UI直変更をやめ「ブランチ→レビュー→デプロイ」へ。GitHub Actionsで自動チェック。+SFチームのトレーニング(最大の山) | 数週〜数ヶ月 |
| 4. 段階移行 | 一部のオブジェクト/フローから試して拡大 | 継続 |
越え方(他チームを巻き込む)
技術構築(1〜3)はエンジニア1人で1〜2ヶ月の桁。本当のコストはSFチームの習慣変更。だから正論で一気に押さず、①内部で価値実証 → ②低摩擦な接点(/sf-impact)だけ渡す → ③必要性を体感させる → ④段階移行。Whyを腑に落としてからHow。
Appendix
付録:再利用資産・検証・リスク
再利用する既存資産
| SFスキーマ取得/picklist | scripts/sf_utils.py |
| Slack/Backlog通知・起票 | scripts/slack_utils.py, scripts/backlog_utils.py |
| BQ SQL(パース対象) | bq_schedule_query/sql/{staging,marts,analytics}/*.sql |
| ダッシュボードGAS(パース対象) | mizukara-corp/management-cockpit/scripts/*.gs |
| 既存インテイク参照 | Backlog SYSDEVREQ-1679、Slack C0851DE6QEB |
| CF/CI雛形・死蔵項目 | cloud_functions/slack_engagement_ingest/, docs/GitHubActions構築.md, docs/sf-null-rate-scan.md |
検証方法
| 1 | ゴールデン再現: SurveyLpCurrentGoal__c/StageName__c値 投入→影響SQL・4ダッシュボードが正しく出るか |
| 2 | picklist差分: サンドボックスで選択肢値を1つリネーム→検知されるか |
| 3 | describe差分: SFテスト項目変更の前後スナップ差分検知(Phase1 Exit) |
| 4 | 腐敗テスト: SQL/GASに新列追加PR→CIで地図が自動再生成されるか |
未解決リスク・要確認
- SF接続認証(Connected App/JWT)の整備可否=自動検知の前提(これだけはデータチーム側で要設定)
- リポ配置の合意: 検知コア=raftel_gcp、インテイク拡張=新設リポ の境界でよいか
- インテイク基盤リポ(琴哉さん)の確立タイミング=事前トリガ(Phase3)の前提
- 未カバー消費先: clasp外Connected Sheets・KUZEN・n8n のカバー要否と優先度
- SFDX化(おまけ): 着手するかは全社DX文脈での別途意思決定