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のUI変更が「見えない依存」を通って後続を沈黙的に壊す。
根因は依存関係が地図化されておらず、変更を捕まえる自動の仕組みが無いこと。
根因は依存関係が地図化されておらず、変更を捕まえる自動の仕組みが無いこと。
① 検知不在事前も事後も変更を捕まえる仕組みが無い。依存の地図そのものが存在しない
② 沈黙故障項目リネームはエラーにならずNULL化。気づくのは「ダッシュボードが変」と人が言った後
So What(だから何が必要か)
対症療法(壊れたら直す)では追いつかない。(1) SF項目→BQ→ダッシュボードの依存を地図化し、(2) 変更を自動で捕まえて、(3) 影響と直し方を提示してBQチームに通知する ——この3点が揃って初めて「事前に防ぐ」が成立する。
根拠(確認済みファクト・補足)
| 事故は既発生 | 2026-04-16 SurveyLpCurrentGoal__c→SurveyLpConcerns__c のリネームを integrated_customer_analytics.sql 等でCOALESCEで事後対応した痕跡 ★★★A |
| 2系統の依存 | Path A: SF→staging_*(毎時)→…→ダッシュボード。Path B: org-coaching.gs が OrganizationalCoaching__c を直読み ★★★A |
| 選択肢値依存 | org-coaching.gs が StageName__c の選択肢値9個を IN(...) でハードコード→値リネームで破壊 ★★★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)の設定だけ。=相手チームの運用を変えずに今すぐ始められる。
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アラート
2
Phase 2(提案+起票): アクション層
- 影響先(決定論)+Claude修正案→Backlog自動起票・担当割当
Exit: アラートに「何をどう直すか」が付く
3
Phase 3(上流): 既存依頼インテイク拡張
- フォームのClaude Q&AにSF影響ブランチ+Slack
/sf-impact(前提: インテイク基盤リポ確立)
Exit: 依頼の入口でSF影響が見える/変更前セルフチェック可
+
(任意・おまけ): SFDX/GitHub化 + 契約ビュー層
- SFをSFDX化して検知をデプロイ前ゲートへ昇格(下記おまけ章参照)。安定列名の契約ビューで結合を1箇所に集約
まず取る一手Phase 0→1 だけで「事故が激減する自動の安全網」が、データチーム側だけで完結して立ち上がる。ここが準備度×インパクトの高いクイックイン。
Optional / おまけ
おまけ:SFDX / GitHub化 — 土台が活きる「もう一段上」
SFDXは、SFの設定(項目・フロー等)をコード化してGitHubで管理するやり方。今回の検知システムはSFDX無しで完結するが、SFDX化すると検知が「事後の網」→「デプロイ前ゲート」に昇格し、事故を構造的に潰せる。
BQ連携以外に、どんな恩恵があるか
UIのまま続けるリスク
- 誰が・いつ・何を変えたか履歴が残らない
- レビュー・承認なしで即本番反映
- 変更前に影響もテストも確認できない
- ロールバックが手作業・属人化
SFDX+GitHub管理の恩恵
- 変更がコード化→履歴・差分・レビューが効く
- デプロイ時にCIゲート=検知が事前ゲートに昇格
- ロールバック・複数人並行が安全に
- AIが差分を読んで自動レビュー・修正できる
どのくらいクリティカルか
今すぐ必須ではない。が、人とAIの分担を進め、AI代替活用度を本格的に上げる段で効く中長期の本丸。設定がコード化されて初めてAIがレビュー・修正・テストを肩代わりできる。まずデジセン内部でやりきり価値を示すのが先。
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文脈での別途意思決定