attribution

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package attribution resolves who pays for whose usage: one breadth-first walk over the attributing relations of a billing period, started from every project no relation attributes away. Resolve is a pure function over the project registry a caller already read. It reads nothing and writes nothing itself.

Attribution is exclusive. A project an attributing relation names is billed under its attributor and nowhere else, so no cost is counted twice and none is dropped. Chains flatten onto the project they start at: in A → B → C both B and C bill under A, and C carries the relation type of the B → C edge it was claimed over, because that edge is what its costs travel to A along.

The walk is deterministic, because the same graph and the same period have to yield the same invoice however often they are billed. The shortest path claims a project first, and among paths of equal length the smallest relation id does, which the walk gets from taking the relations in the id order they are loaded in. Every further edge into a project already claimed is a WarningMultiplePaths, so the path not taken is visible to an operator rather than silently discarded.

A project that is attributed away but that no top-level project reaches sits in a cycle. That does not fail the run: the project is reported as orphaned with a WarningCycle and billed standalone, because a corrupt graph should cost one wrongly rooted statement rather than a whole period's billing. The registry refuses to create a cycle (Phase 1, WP 1.9), and the walk does not rely on that alone. Its termination is structural, not a guard: a project is claimed at most once, so a level that claims nothing empties the frontier.

The normative specification is roadmap/03-phase-3-metering-rating.md, WP 3.7.

Index

Constants

View Source
const WarningCycle = "attribution_cycle"

WarningCycle marks a project that is attributed away but that no top-level project reaches, which only a cycle among attributing relations can produce. The project is billed standalone.

View Source
const WarningMultiplePaths = "attribution_multiple_paths"

WarningMultiplePaths marks a project more than one attributing path reaches. It names the losing relation: the walk claimed the project over a shorter path, or over a path of the same length whose relation id is smaller.

Variables

This section is empty.

Functions

This section is empty.

Types

type Attribution

type Attribution struct {
	// Root is the top-level project the costs appear on the statement of, which
	// is where the walk started rather than the project one edge back.
	Root uuid.UUID
	// RelationType is the type of the winning edge, the one that claimed the
	// project. A statement shows it beside the related costs it introduces.
	RelationType string
}

Attribution is where one project's costs are billed.

type Resolution

type Resolution struct {
	// TopLevel holds the projects that get a statement of their own, in the
	// order the projects came in.
	TopLevel []uuid.UUID
	// Attributed maps every project billed under another one to the attribution
	// it was claimed by. Its keys and TopLevel are disjoint.
	Attributed map[uuid.UUID]Attribution
	// Warnings is what the resolution reports to an operator through the run's
	// stats, in the order it was found. It does not fail the run.
	Warnings []Warning
}

Resolution is who the period bills what under.

func Resolve

func Resolve(projects []source.Project, relations []source.Relation) Resolution

Resolve walks the project graph and returns what the period bills where. Every relation is a directed edge from the attributor to the project it attributes away, and relations are expected in ascending id order, the order source.Snapshot.Relations returns them in, because that order is what breaks ties between paths of equal length.

Relations are taken as given: filtering them by attributing type and by overlap with the period happened when they were loaded (D4). Without relations every project is top level. Without projects there is nothing to bill and the zero Resolution comes back.

type Warning

type Warning struct {
	// Code is WarningMultiplePaths or WarningCycle.
	Code string `json:"code"`
	// ProjectID is the project the finding is about: the one claimed twice, or
	// the one sitting in the cycle.
	ProjectID uuid.UUID `json:"project_id"`
	// RelationID is the losing relation as text, absent on a cycle warning,
	// which is about a project rather than about any one of its edges.
	RelationID string `json:"relation_id,omitempty"`
}

Warning is one finding of the walk. It is JSON-tagged because the run writes the warnings into runs.stats verbatim.

Jump to

Keyboard shortcuts

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