建造符合組織形狀的成本歸因系統
您正在引導一個人(以及組織中有財務夥伴時,一位財務夥伴)進行一項建構,該建構主要是標準模式(FOCUS)與無伺服器執行環境之間的粘合程式碼。模式是固定的;形狀是他們的。您的工作是在他們的資料中找到他們的形狀,將其記錄下來,並將模式應用到其中——永遠不要安裝一個通用產品。
文章解釋了每種模式為何是正確的: https://mooracle.io/blog/build-custom-finops-tool/(第 1–7 部分)。當使用者問「為什麼」時,指向對應部分;將對話保持在「如何做」上。
不變原則
這些原則不會因設定檔而異。在顯示生成的程式碼之前,請根據它們進行檢查。
- 每項拆分都保持總額不變。
SUM(out) == SUM(in)每個成本欄位。分配器移動金錢;它們從不創造或銷毀金錢。 - 在查詢時進行分配。 組織類別透過查詢附加在檢視中。永遠不要將
team寫入倉儲行。 - 計費使用
EffectiveCost。BilledCost用於調節發票,ListCost用於衡量節省。永遠不要混合它們。 - 重建整個月份。 每個
(billing_period, provider)分區在每次交付時都會被清除並從原始資料重新寫入。沒有增量,沒有合併。 - 截止於昨天。 日期為今天或之後的任何內容都不會進入倉儲。
- 每項拆分都是一次扇出。 進行拆分的行會在其常規載入內部聯結其權重,並成為每個權重一行;一個鍵的權重加起來為 1.0。公平份額、Kubernetes 和供應商拆分都透過一個
split_weights表以這種方式運作。沒有任何內容被排除在載入之後再添加回來,因此沒有要忘記的排除項,也沒有任何東西被計算兩次。 - 每次運行都證明其數字。 Raw 準確包含供應商清單所列的檔案,一個阻塞性的總額檢查將帳單與兩個基礎表進行比較,並在它們不一致時使運行失敗(並清除它所寫的內容)。一旦檢視存在,每次運作和每次結算也會檢查
services_monthly是否準確地服務於base_monthly(檢視檢查,失敗時不清除任何內容)。 - 永遠不要遺失成本;路由可能失敗。 當無法安全地進行拆分時,成本會保持完整,仍在被記帳的地方。跳過的拆分是可見的;遺失的成本是無聲的。
- Raw 讀取是精確月份的。
WHERE billing_period = 'YYYY-MM',並啟用引擎的掃描上限(Athena 上的工作組位元組上限)。僅允許在base_monthly(MB 級)上進行全歷史讀取。 - 在檢視中對共享欄位進行一次分類。
x_namespace同時容納 Kubernetes 和 SaaS 工作空間;split_by說明是哪一種。永遠不要從值的形狀推斷。
您在使用者儲存庫中保留的檔案
在第 0 階段在 finops/ 中建立,或者在使用者想要的任何地方建立。將路徑記錄為第一個 D-001;下面,finops/ 指的是該路徑。
-
finops/profile.yaml— 組織的形狀。從assets/profile.template.yaml開始。每個階段都讀取它;沒有其他東西持有組織特定的決策。 -
finops/DECISIONS.md— 僅追加的日誌。永遠不要編輯一個條目;用新的取代它。## D-007 Enterprise Support 是共享的 (2026-10-17) 來源: D5 on 2026-09; Q-S1 由 <使用者> 回答 決策: 根據同月的第一方支出拆分,按付款人 取代: —發現結果、答案、假設、批准和否定決策(「嘗試了每日權重表;由於混合在一個月內沒有變化而回滾;不要再提出」)都放在這裡。設定檔的
evidence欄位指向這些 ID。 -
finops/STATUS.md— 每個階段一行:狀態、包含數字的關卡結果、關卡通過時的提交 SHA,以及該階段依賴的設定檔欄位。| Phase | State | Gate | At | Depends on | | 3 base tables | passed | 2026-09 bill 120,000.00 = monthly 120,000.00 | a1b2c3d | providers, dimensions, routing.key, finance, period_charges, shared_costs |
運行循環
進入
finops/STATUS.md存在 → 恢復:讀取 STATUS、DECISIONS 和設定檔。對於每個已通過的階段,執行git diff <其 SHA> -- finops/profile.yaml;如果它所依賴的欄位發生了變化,則重新打開該階段以及其後每個讀取其輸出的階段(1 → 2 → 3;3 → 4, A, B, 5;4 → 5)。根據當前資料重新運行最後通過的關卡(資料也會移動)。從第一個未通過的階段繼續。- 使用者報告了變更(重組、新的帳戶系列、新的供應商、新的叢集)→ 刷新:重新運行匹配的發現查詢,與設定檔進行差異比較,僅重新詢問已移動的內容,重新檢查,重新打開依賴的階段。
- 使用者想先看看它是否有效,或者還不願授予帳單存取權限 → 試用 (
references/trial.md):在 DuckDB 上運作一個合成月份,無需憑證,並根據答案鍵進行檢查。試用中的任何內容都不會帶入真正的建構。 - 否則 → 從下面的開始。
1. 在詢問之前先發現
在任何建構存在之前,讀取 references/discovery.md 並對最後一個已關閉的月份執行其查詢,針對其已落地(在其檔案上的表,或在沒有引擎時,針對一個已下載交付的 DuckDB)的匯出。顯示每個結果。將每個結果記錄為 D-NNN。發現只讀取;它不會更改帳戶中的任何內容,甚至不會啟用標籤。
還沒有匯出 → 引導路徑:開啟匯出 (references/focus-export.md),運作非資料的訪談輪次(組織、執行環境、類別、財務),根據預期佈局建構技術棧,並在下一個階段(等待第一個交付落地時)執行發現。在等待期間提供試用 (references/trial.md)。
2. 訪談以填補缺口
讀取 references/intake.md。停止或假設規則:
- 答案涉及金錢或所有權的移動 → 將其保留為
null;該元件保持 BLOCKED 狀態; - 這是名稱、位置或工具 → 使用預設值,添加一個
assumptions:條目和一個D-NNN,然後繼續。
永遠不要用似是而非的猜測、固定裝置或來自範例的值來填充事實。
3. 檢查並同意計劃
將 references/plan.md 描述的檢查器寫入 finops/(一次,每個規則一個測試)並在設定檔上運行它。它會為每個元件列印一個判決,以及準備好建構的內容(在其依賴鏈上全部為 READY)。顯示它。
對於每個 BLOCKED 行,說出誰可以回答以及確切的探針。對於每個 NOT_A_FIT,大聲說出更簡單的替代方案——包括當組織方針如此說時的「不要建構這個」。獲得對計劃的明確批准;將其記錄為 D-NNN。
4. 逐階段建構
對於下面地圖中的每個階段,按順序(可選軌道 A 和 B 在第 4 階段之後,僅當 READY 時):
- 進入檢查。 使用
--entering <phase>的檢查器退出碼為 0,並且它所依賴的每個階段在 STATUS.md 中都已通過。 - 讀取其規格(
references/<file>,階段地圖的 Spec 欄位):合約、不變原則,以及那些在臨時構建時會出問題的邊緣案例。 - 在他們的技術棧中編寫它。 在使用者的引擎和語言(Athena、BigQuery、Snowflake、Databricks、dbt……)中,以他們儲存庫的風格,根據他們的設定檔塑造:來自
providers.md的每個供應商的轉接器,僅設定檔需要的拆分,僅它路由的欄位。規格說明了必須保持的內容,案例說明了必須產出的內容;程式碼由您編寫。在錯誤是無聲的地方要格外小心:權重、按天的分攤、總額檢查、貨幣防護。 - 移植黃金案例(
cases/*.yaml;如何在references/testing.md中)適用於此階段建構的內容,並為每個組織特定的調整添加一個案例。在案例通過之前,階段不算建構完成。 - 部署並運行關卡針對他們的真實資料。關卡是 SQL,在健康時返回零行。顯示數字。
- 記錄結果、SHA 和依賴項到 STATUS.md。
關卡報告,每次都一樣:
Gate 3 (base tables), 2026-09, aws: PASSED
bill 120,000.00 · monthly 120,000.00 · daily 120,000.00 · drift 0.00
support: 1 row → 12 accounts, weights sum 1.000000
失敗的關卡會停止建構。使用規格的失敗表(每個檢查的問題名稱都在 reconciliation-ops.md 的「Failure modes」中)進行除錯,修復,重新運行。
階段地圖
| Phase | Builds | Profile fields | Spec | Cases | Gate |
|---|---|---|---|---|---|
| 0 | 發現、訪談、檢查器、計劃 | all | discovery.md, intake.md, plan.md | — | 計劃已批准 (D-NNN) |
| 1 | FOCUS 匯出 | providers | focus-export.md | — | 一個完整的月份可查詢 (D0) |
| 2 | 儲存佈局、引擎、表,以及填充 raw 的交付(複製或輪詢器、暫存、ETL 的發布步驟) | runtime, providers | stack.md, data-model.md, pipeline.md ( |