mooracle/cost-attribution

Guía para construir un sistema personalizado de atribución de costos FinOps (asignación de costos) basado en exportaciones FOCUS de AWS, Azure o Google Cloud, adaptado a las cuentas, etiquetas, clústeres y proveedores SaaS de una organización, en su propia pila tecnológica (la pila de referencia es S3, Athena y Lambda). Escanea primero la factura del usuario, entrevista solo sobre lo que los datos no pueden mostrar, registra las respuestas en un perfil validado, determina si cada componente está LISTO / BLOQUEADO / NO_ES_ADE CUADO, luego construye fase por fase a partir de especificaciones y casos de prueba dorados, con una puerta de verificación después de cada fase. Úsalo cuando el usuario quiera chargeback o showback, para asignar o dividir el gasto en la nube por equipo, aplicación o centro de costos, para reemplazar o evitar una herramienta comercial de FinOps o costos, para trabajar con exportaciones FOCUS, para dividir costos compartidos como Enterprise Support, para atribuir espacios de nombres de Kubernetes o facturas de proveedores SaaS, para reanudar o actualizar una construcción iniciada con esta habilidad, o para probarla con una factura de muestra antes de darle acceso a la facturación.

¿Qué es cost-attribution?

Esta habilidad guía la construcción de un sistema de atribución de costos FinOps totalmente personalizado, directamente sobre las exportaciones FOCUS de AWS, Azure o Google Cloud, y se adapta a la estructura única de cuentas, etiquetas, clústeres y proveedores SaaS de la organización. En lugar de instalar una herramienta genérica, el agente descubre la forma de la organización a partir de sus datos de facturación, realiza una breve entrevista para llenar los vacíos que los datos no pueden cubrir, y construye el sistema fase por fase usando la propia pila del usuario (S3, Athena y Lambda como referencia). Cada componente se verifica rigurosamente con invariantes fijas (como que el total de costos nunca se pierda, la división se realice en tiempo de consulta mediante vistas, y que cada ejecución demuestre que los números coinciden) antes de pasar a la siguiente fase, asegurando precisión y transparencia. Es especialmente útil para equipos de operaciones en la nube, ingeniería de plataformas o FinOps que necesitan chargeback o showback detallados por equipo, aplicación o centro de costos, y que desean reemplazar herramientas comerciales, manejar costos compartidos complejos (como Enterprise Support), atribuir costos de Kubernetes y proveedores SaaS, o reanudar una construcción previamente iniciada con esta habilidad.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mooracle/finops-skills/tree/HEAD/skills/cost-attribution

Installed? Explore more Investigación y análisis de datos skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Construir atribución de costos adaptada a la organización

Estás guiando a una persona (y, donde la organización tenga una, a un socio financiero) a través de una construcción que es principalmente pegamento entre un esquema estándar (FOCUS) y un tiempo de ejecución sin servidor. Los patrones son fijos; la forma es suya. Tu trabajo es encontrar su forma en sus datos, escribirla y aplicar los patrones a ella — nunca instalar un producto genérico.

El artículo explica por qué cada patrón es correcto: https://mooracle.io/blog/build-custom-finops-tool/ (Partes 1–7). Cuando el usuario pregunte "por qué", apunta a la parte; mantén la sesión en el cómo.

Invariantes

Estos nunca varían según el perfil. Verifica el código generado contra ellos antes de mostrarlo.

  1. Cada división mantiene su total. SUM(out) == SUM(in) por columna de costo. Los divisores mueven dinero; nunca lo crean ni lo destruyen.
  2. Asignar en tiempo de consulta. Las categorías de la organización se adjuntan en una vista, a través de una búsqueda. Nunca escribas team en una fila del almacén.
  3. EffectiveCost para chargeback. BilledCost concilia facturas, ListCost mide ahorros. Nunca los mezcles.
  4. Reconstruir todo el mes. Cada partición (billing_period, provider) se borra y reescribe desde los datos sin procesar en cada entrega. Sin deltas, sin combinaciones.
  5. Límite hasta ayer. Nada fechado hoy o después ingresa al almacén.
  6. Cada división es una expansión. Una fila que se divide une sus pesos dentro de la carga regular y se convierte en una fila por peso; los pesos de una clave suman 1.0. Las divisiones equitativas, de Kubernetes y de proveedores funcionan todas así, a través de una tabla split_weights. Nada se excluye de la carga y se agrega después, por lo que no hay exclusión que olvidar, y nada se cuenta dos veces.
  7. Cada ejecución prueba sus números. Raw contiene exactamente los archivos que enumera el manifiesto del proveedor, y una verificación de totales bloqueante compara la factura con ambas tablas base y falla la ejecución (y borra lo que escribió) cuando no coinciden. Una vez que las vistas existen, cada ejecución y cada cierre también verifican que services_monthly sirve exactamente base_monthly (la verificación de vistas, que falla sin borrar nada).
  8. Nunca perder costos; el enrutamiento puede fallar. Cuando una división no se puede realizar de manera segura, el costo permanece entero donde se facturó. Una división omitida es visible; un costo perdido es silencioso.
  9. Las lecturas sin procesar son del mes exacto. WHERE billing_period = 'YYYY-MM', con el límite de escaneo del motor activado (un límite de bytes de grupo de trabajo en Athena). Las lecturas de todo el historial solo están permitidas sobre base_monthly (megabytes).
  10. Clasificar una columna compartida una vez, en una vista. x_namespace contiene espacios de nombres de Kubernetes y espacios de trabajo SaaS por igual; split_by dice cuál. Nunca inferir a partir de la forma del valor.

Archivos que mantienes en el repositorio del usuario

Crea finops/ en la Fase 0, o donde el usuario lo desee. Registra la ruta como el primer D-001; a continuación, finops/ significa esa ruta.

  • finops/profile.yaml — la forma de la organización. Comienza desde assets/profile.template.yaml. Cada fase lo lee; nada más contiene decisiones específicas de la organización.

  • finops/DECISIONS.md — registro de solo adición. Nunca edites una entrada; reemplázala.

    ## D-007 Enterprise Support es compartido (2026-10-17)
    Fuente: D5 del 2026-09; Q-S1 respondida por <usuario>
    Decisión: dividir por gasto de primera parte del mismo mes, por pagador
    Reemplaza a: —
    

    Los resultados del descubrimiento, respuestas, suposiciones, aprobaciones y decisiones negativas ("probé una tabla de pesos diaria; la revertí porque la combinación no varía dentro de un mes; no la propongas de nuevo") van aquí. Los campos evidence del perfil apuntan a estos ID.

  • finops/STATUS.md — una línea por fase: estado, resultado de la puerta con los números, el SHA de confirmación en el que la puerta pasó, y los campos del perfil de los que depende la fase.

    | Fase | Estado | Puerta | En | Depende de
    | 3 tablas base | pasado | factura 2026-09 120.000,00 = mensual 120.000,00 | a1b2c3d | proveedores, dimensiones, clave.enrutamiento, finanzas, cargos.periodo, costos.compartidos |
    

Bucle de ejecución

Entrada

  • finops/STATUS.md existe → reanudar: leer STATUS, DECISIONS y el perfil. Para cada fase pasada, git diff <su SHA> -- finops/profile.yaml; si un campo del que depende cambió, reabrir esa fase y cada fase posterior que lea su salida (1 → 2 → 3; 3 → 4, A, B, 5; 4 → 5). Volver a ejecutar la última puerta pasada contra los datos actuales (los datos también se mueven). Continuar desde la primera fase no pasada.
  • El usuario informa un cambio (reorganización, nueva familia de cuentas, nuevo proveedor, nuevo clúster) → actualización: volver a ejecutar las consultas de descubrimiento correspondientes, comparar con el perfil, volver a preguntar solo lo que cambió, volver a verificar, reabrir fases dependientes.
  • El usuario quiere verlo funcionar primero, o no dará acceso a la facturación todavía → la prueba (references/trial.md): un mes sintético en DuckDB, sin credenciales, verificado contra una clave de respuestas. Nada de esto se traslada a una construcción real.
  • De lo contrario → inicio a continuación.

1. Descubrir antes de preguntar

Leer references/discovery.md y ejecutar sus consultas en el último mes cerrado, contra la exportación donde ya reside (una tabla sobre sus archivos, o DuckDB sobre una entrega descargada cuando no hay motor), antes de que exista alguna construcción. Mostrar cada resultado. Registrar cada uno como D-NNN. El descubrimiento lee; no cambia nada en la cuenta, ni siquiera una activación de etiqueta.

Aún no hay exportación → la ruta de arranque: activar la exportación (references/focus-export.md), ejecutar las rondas de ingesta que no son de datos (Organización, Tiempo de ejecución, Categorías, Finanzas), construir la pila contra el diseño esperado, y ejecutar el descubrimiento en la próxima sesión una vez que la primera entrega haya llegado. Ofrecer la prueba (references/trial.md) mientras se espera.

2. Entrevistar para llenar los vacíos

Leer references/intake.md. La regla de detenerse o asumir:

  • la respuesta mueve dinero o propiedad → dejarlo null; el componente permanece BLOQUEADO;
  • es un nombre, ubicación o herramienta → usar el valor predeterminado, agregar una entrada assumptions: y un D-NNN, continuar.

Nunca llenes un hecho con una suposición plausible, un valor fijo o un valor de un ejemplo.

3. Verificar y acordar el plan

Escribir el verificador que references/plan.md describe en finops/ (una vez, con una prueba por regla) y ejecutarlo en el perfil. Imprime un veredicto por componente y qué está listo para construir (LISTO en toda su cadena de dependencias). Mostrarlo. Para cada línea BLOQUEADA, nombrar quién puede responder y la sonda exacta. Para cada NO_ES_ADECUADO, decir en voz alta la alternativa más simple — incluyendo "no construir esto" cuando la línea de la organización lo diga. Obtener la aprobación explícita del plan; registrarlo como un D-NNN.

4. Construir, fase por fase

Para cada fase en el mapa a continuación, en orden (las pistas opcionales A y B después de la Fase 4, solo cuando están LISTAS):

  1. Verificación de entrada. El verificador con --entering <fase> sale con 0, y cada fase de la que depende está pasada en STATUS.md.
  2. Leer su especificación (references/<archivo>, columna Especificación del mapa de fases): el contrato, las invariantes y los casos límite que muerden cuando se improvisa.
  3. Escribirlo en su pila. Construir los componentes de la fase en el motor y lenguaje del usuario (Athena, BigQuery, Snowflake, Databricks, dbt, …) y en el estilo de su repositorio, adaptado por su perfil: un adaptador por proveedor de providers.md, solo las divisiones que el perfil necesita, solo las columnas que enruta. Las especificaciones dicen lo que debe mantenerse y los casos lo que debe salir; el código es tuyo para escribir. Prestar la mayor atención donde un error es silencioso: los pesos, la distribución en días, las verificaciones de totales, los protectores de moneda.
  4. Portar los casos dorados (cases/*.yaml; cómo, en references/testing.md) que se aplican a lo que esta fase construyó, y agregar un caso para cada adaptación específica de la organización. Una fase no está construida hasta que sus casos pasan.
  5. Desplegar y ejecutar la puerta contra sus datos reales. Las puertas son SQL que devuelven cero filas cuando están saludables. Mostrar los números.
  6. Registrar el resultado, el SHA y las dependencias en STATUS.md.

Informe de puerta, cada vez:

Puerta 3 (tablas base), 2026-09, aws: PASÓ
  factura 120.000,00 · mensual 120.000,00 · diario 120.000,00 · desviación 0,00
  soporte: 1 fila → 12 cuentas, pesos suman 1,000000

Una puerta fallida detiene la construcción. Depurar con la tabla de fallos de la especificación (los nombres de problemas de cada verificación están en reconciliation-ops.md, "Modos de fallo"), corregir, volver a ejecutar.

Mapa de fases

FaseConstruyeCampos del perfilEspecificaciónCasosPuerta
0descubrimiento, entrevista, el verificador, plantodosdiscovery.md, intake.md, plan.md—plan aprobado (D-NNN)
1Exportaciones FOCUSprovidersfocus-export.md—un mes completo consultable (D0)
2diseño de almacenamiento, motor, tablas y las entregas que llenan raw (copia o sondeo, staging, paso de publicación de ETL)runtime, providersstack.md, data-model.md, pipeline.md ("Entrega")—un mes publicado coincide con su manifiesto; un mes raw consultable escanea una fracción de los archivos de ese mes
3adaptadores, tablas base con prorrateo y divisiones de costos compartidos, la reconstrucción de ETLproviders, dimensions, routing.key, finance, period_charges, shared_costsproviders.md, data-model.md, splitters.md, pipeline.mdadapters, load, share, checksfactura == mensual == diario por pagador en un mes cerrado
4reglas, búsqueda, vistascategories, routingrules-engine.mdrules, viewsaparecen categorías; No asignado reportado
ADivisiones SaaSsaas.vendorssaas.mdvendorel proveedor muestra split; los totales se mantienen
BEspacios de nombres de Kuberneteskuberneteskubernetes.mdk8spesos limpios; cobertura ≥ objetivo
5reconciliación, operaciones, cierrefinance, org.finance_partnerreconciliation-ops.md, testing.mdchecksdonde la organización ingresa totales de factura (Q-F5), un mes cerrado pasa la verificación de factura para cada proveedor, su resultado almacenado con el mes; una división deliberadamente rota falla la ejecución en una copia de desarrollo; un recorrido de los números con el socio financiero, o el propietario donde no lo hay

references/pipeline.md tiene el orden de procesamiento en el que estas piezas se ejecutan en tiempo de ejecución.

Grados de libertad

  • Fijos (cualquiera que sea el motor): las invariantes, y lo que los casos dicen que debe salir (adapters.yaml exceptuado: muestra las elecciones de un perfil sobre las formas sin procesar de las exportaciones): las reglas de prorrateo, la expansión con pesos que suman 1,0, las puertas de los productores (por pagador, gasto positivo, datos de proveedor de mes completo), las verificaciones y en qué se detienen, el orden de ejecución y la limpieza en caso de fallo, la negativa a parámetros de consulta no llenos.
  • Suyos (escribir libremente para que coincida con su base de código): el motor y el idioma, el diseño de archivos, la infraestructura como código, el empaquetado, la programación, los paneles, CI y los nombres de archivos, funciones e infraestructura (los nombres de tablas, columnas y problemas que los casos usan son fijos).

Cuando no estés seguro de en qué lado está un cambio, es fijo.

Cuando el usuario se resiste

references/pushback.md tiene los habituales ("asignar en el ETL", "mapear 100%", "un marco para cada proveedor", "precisión por pod") con la respuesta y dónde el artículo lo argumenta.

Hecho significa

  • Cada mes cerrado pasa la verificación de totales para cada proveedor, a través de cada división, y, donde la organización ingresa totales de factura, la verificación de factura.
  • Quien reporte costos (el socio financiero, o el propietario donde no lo haya) responde "¿cuánto costó el equipo X el mes pasado?" desde una vista, sin nuevo SQL.
  • Un cambio de regla es una solicitud de extracción: CI se expande, el revisor ve lo que se mueve, la combinación recategoriza todo el historial sin reconstrucción.
  • No asignado se alerta como una cantidad, en su moneda, y con tendencia decreciente.
  • El costo de ejecución es pequeño y medido (en la pila de referencia, alrededor de $10 al mes para S3, Athena y Lambda juntos con 15 millones de líneas de factura al mes; la parte de Athena está en las métricas de escaneo del grupo de trabajo).
  • STATUS.md muestra cada fase que el plan construye pasada con un SHA; DECISIONS.md explica cada elección que un recién llegado cuestionaría.

Skills relacionados