world

package
v0.0.0-...-09d6bc6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 29, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package world defines the estate the console opens onto: the teams that spend, the desks that watch them, the analysts hired to each desk, and the events planted in the cost series.

The planted events are the part worth explaining. The original generated plausible noise and then detected whatever the detector happened to find, which means nothing could say whether the detector was right: a missed anomaly and an estate with no anomalies look identical from the outside.

Here every irregularity is placed on purpose and carries the answer with it, including the ones that must NOT be reported. A generator that only plants true positives cannot catch a detector that flags everything.

Index

Constants

View Source
const (
	FirstDay = "2025-06-01"
	LastDay  = "2026-08-15"
)

The estate spans fourteen and a half months, which is what makes a year-on-year comparison possible and a twelve-month commitment expire inside the window.

View Source
const Waterline = 80.0

Waterline is the eighty percent line: below it, the discount is costing more than it saves.

Variables

View Source
var Catalogue = buildCatalogue()

Catalogue is the whole estate, written out rather than generated, so that what the console shows can be read here and argued with.

The shape of it matters as much as the size: a few large series and a long tail of small ones, because that is what a real account looks like and it is what makes a money floor necessary rather than fussy.

View Source
var Commitments = buildCommitments()

Commitments is what each desk has bought in advance, as a share of the spend a commitment can actually cover.

Committable spend is compute, database and accelerator: storage and egress are not covered by a savings plan, and a commitment sized against the whole bill would look prudent while covering things it cannot.

View Source
var Crew = buildCrew()

Crew is thirty-six analysts. The variety is the point: a console that only ever shows healthy agents never gets its unhappy paths looked at, and the unhappy paths are where a governance product earns its place.

View Source
var Desks = []Desk{
	{"aws", "cloud", "USD"},
	{"gcp", "cloud", "USD"},
	{"azure", "cloud", "USD"},
	{"onprem", "on-premises", "USD"},
	{"ai", "ai", "USD"},
	{"saas", "saas", "USD"},
}
View Source
var Licences = buildLicences()

Licences is the seat estate, read off the SaaS invoices.

Issued seats are what the invoice actually pays for, at the vendor's list price. That is the whole point: "we pay for 60 seats" is a claim somebody can check against a line in the ledger, and a claim nobody can check is what this table used to be.

View Source
var Planted = []Event{
	{
		ID: "E01", Source: "aws", Team: "ml-platform", Service: "Amazon EC2",
		Day: "2026-07-14", Shape: Spike, Factor: 5.4, Excess: money.Cents(184_000),
		Detect: true,
		Why:    "A training run left forty instances up over a weekend. Nothing in the registry explains it.",
	},
	{
		ID: "E02", Source: "gcp", Team: "research", Service: "GKE",
		Day: "2026-06-22", Shape: Spike, Factor: 4.1, Excess: money.Cents(96_500),
		Detect: true, Driver: "Quarterly model refresh, planned",
		Why: "Real and large, and the registry explains it. It is reported and annotated, never hidden.",
	},
	{
		ID: "E03", Source: "azure", Team: "security", Service: "Microsoft Sentinel",
		Day: "2026-08-03", Shape: Drop, Factor: 0.08, Excess: money.Cents(-71_200),
		Detect: true,
		Why:    "The log feed stopped delivering. A fall this steep is a data-quality incident, not a saving.",
	},
	{
		ID: "E04", Source: "onprem", Team: "data-eng", Service: "Batch cluster",
		Day: "2026-07-02", Shape: Drop, Factor: 0.35, Excess: money.Cents(-42_800),
		Detect: true, Driver: "Batch cluster decommission, tranche 1",
		Why: "A deliberate switch-off. Reported so somebody confirms the saving was intended and stuck.",
	},
	{
		ID: "E05", Source: "ai", Team: "product-web", Service: "Anthropic API",
		Day: "2026-07-28", Shape: Step, Factor: 2.6, Excess: money.Cents(238_400),
		Detect: true, CausedBy: "deep-analysis",
		Why: "An agent was moved to the strong model and left there. A step, not a spike: it does not come back down.",
	},
	{
		ID: "E06", Source: "ai", Team: "ml-platform", Service: "OpenRouter",
		Day: "2026-08-11", Shape: Spike, Factor: 6.8, Excess: money.Cents(151_900),
		Detect: true, CausedBy: "unit-econ-ai",
		Why: "A retry loop. The clearest case for a runtime kill-switch in the whole fixture.",
	},
	{
		ID: "E07", Source: "aws", Team: "product-mobile", Service: "Amazon S3",
		Day: "2026-06-09", Shape: Step, Factor: 1.9, Excess: money.Cents(88_300),
		Detect: true,
		Why:    "Lifecycle rules were removed, so nothing ages out any more. Steps are the ones people miss.",
	},
	{
		ID: "E08", Source: "gcp", Team: "growth", Service: "BigQuery",
		Day: "2026-08-05", Shape: Spike, Factor: 3.7, Excess: money.Cents(64_100),
		Detect: true,
		Why:    "One unpartitioned query scanned the whole table, repeatedly.",
	},
	{
		ID: "E09", Source: "saas", Team: "support-tools", Service: "Zendesk",
		Day: "2026-07-01", Shape: Step, Factor: 1.45, Excess: money.Cents(10_800),
		Detect: true,
		Why:    "Seats bought for a hiring plan that slipped. Money in unused licences.",
	},

	{
		ID: "N01", Source: "aws", Team: "sre-platform", Service: "Amazon EC2",
		Day: "2026-07-19", Shape: Natural, Factor: 1, Detect: false,
		Why: "A Sunday, with nothing done to it. This desk runs at 64 percent of a " +
			"weekday at the weekend, and a detector without a same-day-type baseline " +
			"reports that rhythm as an incident every single week.",
	},
	{
		ID: "N02", Source: "gcp", Team: "product-web", Service: "Cloud Run",
		Day: "2026-06-01", Shape: Ramp, Factor: 1.8, Detect: false,
		Why: "Eighty percent growth spread over three months. Real, worth a forecast, " +
			"and not an incident on any single day.",
	},
	{
		ID: "N03", Source: "azure", Team: "finance-systems", Service: "Azure Functions",
		Day: "2026-08-07", Shape: Spike, Factor: 4.2, Excess: money.Cents(310),
		Detect: false,
		Why: "Four times a baseline of eighty cents. Statistically loud, worth three dollars. " +
			"Below the money floor, and a queue full of these teaches people to ignore the queue.",
	},
	{
		ID: "N04", Source: "onprem", Team: "sre-platform", Service: "Storage array",
		Day: "2026-06-30", Shape: Natural, Factor: 1, Detect: false,
		Driver: "Month-end batch on the storage array",
		Why: "The month-end batch runs every month and the generator puts it in the " +
			"series itself. A 28-day window holds only one month-end, so the median " +
			"never learns it: the registry is what makes a monthly rhythm expected.",
	},
	{
		ID: "N05", Source: "ai", Team: "research", Service: "GPU training cluster",
		Day: "2026-07-08", Shape: Spike, Factor: 3.1, Excess: money.Cents(58_000),
		Detect: false, Driver: "Scheduled weekly training window",
		Why: "Large, and it happens every Wednesday on a published schedule. The registry " +
			"covers it as recurring, so it is expected rather than merely explained.",
	},
}

Planted is the fixture's ground truth. Fourteen events: nine that a correct detector must find and five it must leave alone.

View Source
var SharedCosts = []Shared{
	{"aws", "Savings Plan", "Purchase", money.Cents(420_000), 1},
	{"aws", "Reserved Instances", "Purchase", money.Cents(180_000), 1},
	{"aws", "Tax", "Tax", money.Cents(96_000), 28},
	{"aws", "Enterprise Discount", "Credit", money.Cents(-140_000), 28},
	{"gcp", "Committed Use Discount", "Purchase", money.Cents(260_000), 1},
	{"gcp", "Tax", "Tax", money.Cents(52_000), 28},
	{"azure", "Reservations", "Purchase", money.Cents(150_000), 1},
	{"azure", "Tax", "Tax", money.Cents(38_000), 28},
	{"onprem", "Depreciation", "Purchase", money.Cents(310_000), 1},
	{"saas", "Annual platform fee", "Purchase", money.Cents(88_000), 15},
}
View Source
var Teams = []Team{
	{"ml-platform", "engineering", "weekly"},
	{"data-eng", "engineering", "weekly"},
	{"product-web", "product", "weekly"},
	{"product-mobile", "product", "fortnightly"},
	{"sre-platform", "engineering", "weekly"},
	{"security", "risk", "monthly"},
	{"growth", "commercial", "fortnightly"},
	{"finance-systems", "corporate", "monthly"},
	{"research", "engineering", "monthly"},
	{"support-tools", "corporate", "monthly"},
}
View Source
var UtilisationRows = buildUtilisation()

UtilisationRows names the resources inside a line, and they SUM to the line.

That is the property the page is worth having: the resources listed under aws / Amazon EC2 / ml-platform add up, to the cent, to what that line cost last month. A rightsizing table whose rows do not add up to anything is a list of assertions, and the saving column on it cannot be trusted either.

Functions

func DayBefore

func DayBefore(day string, n int) string

DayBefore is n days before a "2006-01-02" date, as the same string.

It exists so a fixture can stagger dates without every caller re-deriving the parse and the format, and so an unparseable input comes back unchanged rather than as the zero time, which would render as year one.

func LastFullMonth

func LastFullMonth() string

lastFullMonth is the month before the estate's last day.

The planes are monthly figures, and the open month is a part-month: a seat count derived from eleven days of an invoice would say the organisation had halved its licences overnight. LastFullMonth is exported so a reconciliation can measure the same month these planes were derived from. Measuring them against a different month is the one way to make a correct derivation look broken.

func ResourceKind

func ResourceKind(service string) string

resourceKind classifies a service so the page can say what it is looking at. Anything that is not compute, storage-adjacent or an accelerator is not something a rightsizing page has anything useful to say about. ResourceKind is exported so a reconciliation can classify a service the same way the derivation did.

Types

type AIUnit

type AIUnit struct {
	Month     string
	Team      string
	Model     string
	Tokens    int64
	Cost      money.Cents
	Actions   int
	Deflected int
}

AIUnit is the AI desk's economics: price separated from volume.

A bill that doubled because the price went up and a bill that doubled because twice as much was done are different facts with different answers, and a console that reports only dollars cannot tell them apart.

func AIUnits

func AIUnits() []AIUnit

AIUnits is derived from the same generated series the charges come from, so the two agree by construction rather than by a reconciliation nobody runs.

func (AIUnit) PerAction

func (a AIUnit) PerAction() money.Cents

func (AIUnit) PerMillion

func (a AIUnit) PerMillion() money.Cents

func (AIUnit) String

func (a AIUnit) String() string

type Agent

type Agent struct {
	Name       string
	Role       string
	Desk       string
	State      AgentState
	Reason     string // required whenever State is not Active
	Engine     string
	PerTaskUSD string
	MonthlyUSD string
	Skills     []string
}

type AgentState

type AgentState string

AgentState is what an analyst is doing right now, and every value here exists because some screen has to render it honestly.

const (
	Active     AgentState = "active"     // on the rota
	Suspended  AgentState = "suspended"  // off it, with a reason, work untouched
	Onboarding AgentState = "onboarding" // hired, nothing finished yet
	Restricted AgentState = "restricted" // may propose, may not act
	OverGuard  AgentState = "over-guard" // this month's spend passed its ceiling
	Probation  AgentState = "probation"  // first-pass rate under the bar
)

type Commitment

type Commitment struct {
	Source  string
	Name    string
	Kind    string // savings-plan, reserved, cud
	Hourly  money.Cents
	Used    float64 // percentage of what was committed
	Expires string
	Term    string
	Note    string
}

Commitment is a discount bought in advance: cheaper per hour, and only if you use it.

func ExpiringWithin

func ExpiringWithin(days int, from string) []Commitment

ExpiringWithin is the calendar question: what has to be decided soon.

func (Commitment) BelowWaterline

func (c Commitment) BelowWaterline() bool

func (Commitment) Wasted

func (c Commitment) Wasted() money.Cents

Wasted is what is being paid for and not used, per month.

type Desk

type Desk struct {
	Name     string
	Kind     string // cloud, on-premises, ai, saas
	Currency string
}

Desk is a place spend comes from and an analyst watches.

type Driver

type Driver struct {
	Start, End, Scope, Label, Kind, Source string
}

RecurringDrivers are the registry entries that cover the events which are expected rather than merely explained.

func Drivers

func Drivers() []Driver

type Event

type Event struct {
	ID       string
	Source   string
	Team     string
	Service  string
	Day      string // ISO date; for Step and Ramp, the day it starts
	Shape    Shape
	Factor   float64     // multiple of baseline at the peak, or the step's new level
	Excess   money.Cents // roughly what it adds or removes, for ranking
	Detect   bool        // must the detector report this?
	Driver   string      // registry label that explains it, if any
	CausedBy string      // an agent, when the spend is an agent's own
	Why      string      // why it is or is not an anomaly, in a person's words
}

Event is one planted irregularity and the answer that goes with it.

Detect is the ground truth. A false entry is as valuable as a true one: weekends, slow growth and amounts below the money floor are exactly what a naive detector reports, and without them in the fixture nothing measures that.

func MustDetect

func MustDetect() []Event

MustDetect is the ground truth a detector is scored against.

func MustIgnore

func MustIgnore() []Event

MustIgnore is the other half, and the half that catches a detector which simply flags everything loud.

type Licence

type Licence struct {
	Vendor   string
	Product  string
	Team     string
	Issued   int
	Active30 int // signed in at least once in the last thirty days
	PerSeat  money.Cents
	Renews   string
	Term     string
	Note     string
}

func (Licence) Idle

func (l Licence) Idle() int

func (Licence) Waste

func (l Licence) Waste() money.Cents

Waste is money in seats nobody signed into. Monthly, at the per-seat price actually being paid.

type Row

type Row struct {
	Source   string
	Day      string
	Service  string
	Team     string
	Category string
	Billed   money.Cents
	Quantity float64
	Unit     string
	Meter    string
	Model    string
}

Row is one charge as the store holds it.

func Generate

func Generate() []Row

Generate builds the whole estate: every series, every day, with the planted events applied on top, plus the shared costs that belong to nobody.

type Series

type Series struct {
	Source  string
	Team    string
	Service string
	Base    money.Cents // typical weekday spend
	Weekend float64     // weekend level as a fraction of a weekday
	Growth  float64     // annual growth, 0.20 being twenty percent a year
	Noise   float64     // day-to-day variation as a fraction of the base
	Meter   string      // AI desks carry consumption alongside cost
	Unit    string
	Model   string
}

Series is one daily cost line: a team's use of one service on one desk.

type Shape

type Shape string

Shape is how an irregularity looks in the series.

const (
	Spike Shape = "spike" // one day well above the baseline
	Drop  Shape = "drop"  // one day well below it
	Step  Shape = "step"  // a sustained change in level
	Ramp  Shape = "ramp"  // a gradual climb, which is NOT an anomaly

	// Natural changes nothing at all. The control is the series behaving
	// normally on a day a careless detector reports anyway: a Sunday, a
	// month-end batch. Planting a synthetic dip and then calling it normal
	// would test the opposite of what it claims.
	Natural Shape = "natural"
)

type Shared

type Shared struct {
	Source   string
	Service  string
	Category string // Purchase, Tax, Credit
	Monthly  money.Cents
	Day      int // day of the month it lands on
}

Shared is a cost with no team of its own: a commitment bought for a desk, tax on the whole bill, a credit applied to the account.

The estate needs these or allocation is a page with nothing to do. They are also the honest part of a real bill: on most accounts somewhere between a tenth and a quarter of the money arrives with nobody's name on it, and what a FinOps team is actually asked to do is give it one.

type Team

type Team struct {
	Name    string
	Unit    string // the business unit chargeback rolls up to
	Cadence string // how often they want to hear from FinOps
}

Team is a spending team. Ten of them, because a FinOps console with three teams never shows the thing that makes allocation hard, which is a shared cost nobody owns and two teams that both think they are the small one.

type Utilisation

type Utilisation struct {
	Source   string
	Service  string
	Team     string
	Resource string
	Kind     string // compute, database, accelerator
	P95CPU   float64
	P95Mem   float64
	Days     int
	Monthly  money.Cents // what it costs now
	Advice   string      // the smaller size, when there is one
	Saving   money.Cents // what the smaller size would cost less
	Why      string
}

Utilisation is what a machine actually did, as opposed to what it cost.

Cost alone cannot tell you whether something is the wrong size. A box at four percent CPU and a box at eighty percent bill identically, and only one of them is a finding. This is the evidence half of a rightsizing case, and without it a recommendation is a guess with a dollar sign on it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL