corroborate

package
v0.16.0 Latest Latest
Warning

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

Go to latest
Published: Jun 30, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package corroborate computes the recipe corroboration consensus model and emits the deterministic interim-evidence dashboard (GP4, design doc docs/design/013-interim-evidence-dashboard.md).

The model answers one question per recipe row (a CTRF check within a phase): how many DISTINCT, verified, allowlisted signers agree on the result? It counts signers, never builds — N nightly runs from a single CI loop count as one source, so a sybil cannot manufacture a CONFIRMED cell. Each signer's latest in-scope CTRF status is bucketed totally and explicitly:

passed         -> S_pass
failed, other  -> S_fail
skipped, pending, missing -> NOT-RUN (a coverage gap, never a corroboration)

The five cell states fall out of the (S_pass, S_fail) cardinalities over allowlisted signers (see ComputeConsensus): CONFIRMED, SINGLE, CONTESTED, FAILING, UNTESTED. A verified-but-unallowlisted signer is admitted as a zero-weight "reported" dot that can never reach CONFIRMED on its own.

The generator (Generate) reads the source-keyed GCS layout (Contract 3: results/<group>/<dashboard>/<tab>/<signer-id-hash>/<run-id>/{meta.json, ctrf/<phase>.json}) from a local directory, derives each recipe's coordinate via the shared pkg/recipe.CoordinateFor helper (never parsing metadata.name), and emits the Contract 4 dashboard JSON (index.json + per-recipe series/<recipe>.json) plus a self-contained static HTML/CSS/JS renderer that fetches them.

Every emit is byte-deterministic from the same inputs: no time.Now, no random, no UUID on the emit path. All timestamps come from the bundle predicate's AttestedAt (carried in meta.json), and every collection is sorted (coordinate, PhaseOrder, CTRF name, signer-id-hash, JSON map keys).

Index

Constants

View Source
const RunMetaSchemaVersion = "aicr-corroboration-meta/v1"

RunMetaSchemaVersion is the meta.json schema GP4 reads (Contract 3, written by the GP2 ingest job).

View Source
const SchemaVersion = "aicr-corroboration/v1"

SchemaVersion is the emitted dashboard JSON schema identifier (Contract 4). v1 splits the v0 prototype's inlined per-source history: index.json keeps the latest-per-signer grid with baked consensus, and the heavy time-series moves to series/<recipe>.json.

View Source
const SupportedAllowlistSchemaVersion = "1.0.0"

SupportedAllowlistSchemaVersion is the allowlist schema (GP1-owned, Contract 2) this classifier understands. The loader fails closed on any other value: a future GP1 schema bump may carry semantics these classification rules do not enforce, so GP4 must be updated rather than silently classifying under stale assumptions.

Variables

This section is empty.

Functions

This section is empty.

Types

type Allowlist

type Allowlist struct {
	SchemaVersion string           `yaml:"schemaVersion" json:"schemaVersion"`
	FirstParty    []AllowlistEntry `yaml:"firstParty" json:"firstParty"`
	Community     []AllowlistEntry `yaml:"community" json:"community"`
	Partner       []AllowlistEntry `yaml:"partner" json:"partner"`
}

Allowlist is the in-tree, PR-reviewed signer allowlist (recipes/evidence/allowlist.yaml, owned by GP1; this is the consumer-side loader/classifier). The three class sections are disjoint and non-overlapping.

func LoadAllowlist

func LoadAllowlist(path string) (*Allowlist, error)

LoadAllowlist reads and validates the allowlist at path. The read is bounded (maxAllowlistBytes) before parse so an attacker-influenced path cannot OOM the generator.

func (*Allowlist) Classify

func (a *Allowlist) Classify(issuer, identity string) (Class, bool)

Classify resolves a verified (issuer, identity) to its class and whether it counts toward corroboration. A signer matching no entry is admitted as a zero-weight reported dot: class community, allowlisted false.

func (*Allowlist) Validate

func (a *Allowlist) Validate() error

Validate enforces the anti-sybil invariants on the allowlist so it is not itself an attack surface:

  • every entry has a non-empty issuer and identity;
  • no identity is over-broad (no unbounded wildcard org/repo segment);
  • the classes are disjoint and no two entries overlap (one verified identity matches at most one entry).

type AllowlistEntry

type AllowlistEntry struct {
	Issuer   string `yaml:"issuer" json:"issuer"`
	Identity string `yaml:"identity" json:"identity"`
}

AllowlistEntry pins one verified signer: an exact issuer and an identity that is either an exact string or a tightly-bounded regex (recognized by a leading "^"). Over-broad identities are rejected by Allowlist.Validate.

type Class

type Class string

Class is a corroboration source class. A signer's class is derived from its verified OIDC identity against the allowlist — never a free-text field.

const (
	// ClassFirstParty is the project's own UAT signer (GH-Actions OIDC pinned
	// to NVIDIA/aicr).
	ClassFirstParty Class = "first-party"

	// ClassCommunity is an allowlisted community signer (and the fallback class
	// for a verified-but-unallowlisted "reported" signer).
	ClassCommunity Class = "community"

	// ClassPartner is an allowlisted partner signer.
	ClassPartner Class = "partner"
)

type Consensus

type Consensus struct {
	// State is the cell state.
	State State

	// PassAllow is the count of allowlisted signers in S_pass.
	PassAllow int

	// FailAllow is the count of allowlisted signers in S_fail.
	FailAllow int

	// Reported is the count of non-allowlisted signers that actually ran the
	// row (passed or failed). Shown on the board, never counted toward state.
	Reported int
}

Consensus is the computed verdict for a single row.

func ComputeConsensus

func ComputeConsensus(signers []SignerResult) Consensus

ComputeConsensus derives the cell state for one row from its distinct-signer results. The decision is driven entirely by the allowlisted (S_pass, S_fail) cardinalities; unallowlisted signers only increment Reported.

UNTESTED  no allowlisted signer ran the row
CONTESTED allowlisted S_pass and S_fail both non-empty
FAILING   allowlisted S_fail non-empty, S_pass empty
CONFIRMED allowlisted S_pass >= 2, S_fail empty
SINGLE    allowlisted S_pass == 1, S_fail empty

not-run results are excluded from both buckets, so a skipped latest neither promotes a row to CONFIRMED nor suppresses a CONTESTED.

type Dashboard

type Dashboard struct {
	Accelerator string `json:"accelerator"`
	OS          string `json:"os"`
	Tabs        []Tab  `json:"tabs"`
}

Dashboard is one accelerator-os pairing within a service.

type GenerateResult

type GenerateResult struct {
	Recipes int
	Sources int
	Runs    int
}

GenerateResult summarizes a Generate run for logging.

func Generate

func Generate(ctx context.Context, opts Options) (GenerateResult, error)

Generate reads the corroboration evidence under opts.InputDir, computes the consensus model, and writes the deterministic dashboard (index.json, series/<recipe>.json, index.html) under opts.OutputDir.

The directory walk, per-run reads, and output writes are unbounded in the size of the evidence tree, so they observe ctx: a canceled or deadline-exceeded ctx stops the walk, the per-run collect loop, and the series-emit loop and returns ErrCodeTimeout. Pure in-memory aggregation/build between those phases is not a cancellation point.

type Group

type Group struct {
	Service    string      `json:"service"`
	Dashboards []Dashboard `json:"dashboards"`
}

Group is one service's subtree (group = service in the locked taxonomy).

type Index

type Index struct {
	// Schema is always SchemaVersion.
	Schema string `json:"schema"`

	// Criteria holds the facet dropdown values per axis (service, accelerator,
	// os, intent, platform), ordered by the criteria registry's canonical
	// order and filtered to values actually present in the data.
	Criteria map[string][]string `json:"criteria"`

	// Sources maps each signer-id-hash to its display source record.
	Sources map[string]Source `json:"sources"`

	// Groups is the CSP-first catalog tree, ordered by service.
	Groups []Group `json:"groups"`
}

Index is the boot payload (index.json): the facet value sets, the source catalog, and the CSP-first navigation tree (groups -> dashboards -> tabs) with baked-in consensus. The static renderer fetches this on load and needs no further request to draw the catalog and per-recipe grids.

type Latest

type Latest struct {
	// Src is the signer-id-hash (a key into Index.Sources).
	Src string `json:"src"`

	// Result is "pass" or "fail" (not-run signers are omitted from the grid).
	Result string `json:"result"`

	// AICRVer is the AICR version from the bundle predicate (a facet axis).
	AICRVer string `json:"aicrVer"`

	// K8sVer is the observed Kubernetes major.minor (a facet axis).
	K8sVer string `json:"k8sVer"`

	// When is the predicate AttestedAt rendered for display — never the
	// publish clock.
	When string `json:"when"`

	// Build is the run identifier.
	Build string `json:"build"`

	// EvidenceRef is the OCI ref of the signed bundle, for the drilldown link.
	EvidenceRef string `json:"evidenceRef"`
}

Latest is one signer's latest in-scope result for a row in index.json. The full per-build history lives in series/<recipe>.json.

type Options

type Options struct {
	// InputDir is the root of the source-keyed GCS layout (Contract 3),
	// synced to a local directory. Generate finds every meta.json beneath it.
	InputDir string

	// OutputDir is where index.html and data/{index.json,series/*.json} are
	// written.
	OutputDir string

	// AllowlistPath, when set, re-derives each signer's class from its verified
	// (issuer, identity) against the allowlist instead of trusting meta.json's
	// pre-derived class. When empty, the class/allowlisted fields in meta.json
	// are trusted as-is — safe only because GP2 (the trusted ingest job, Contract
	// 3) writes them post-verification; point -allowlist at the in-tree allowlist
	// to re-verify when the input tree is not from a trusted ingest.
	AllowlistPath string
}

Options configures Generate.

type Result

type Result string

Result is a single signer's bucketed outcome for one row, after mapping the raw CTRF status through BucketStatus.

const (
	// ResultPass is a passing run (CTRF "passed").
	ResultPass Result = "pass"

	// ResultFail is a failing run (CTRF "failed" or "other").
	ResultFail Result = "fail"

	// ResultNotRun is a coverage gap for this signer+row (CTRF "skipped"/
	// "pending", or the CTRF Name absent from the signer's report). It is
	// never counted as a pass or a fail, so it can neither promote a row to
	// CONFIRMED nor suppress a CONTESTED. Its wire value ("not-run") is the one
	// the renderer's series cells use; the index.json grid omits not-run signers
	// entirely, so it only appears in series/<recipe>.json.
	ResultNotRun Result = "not-run"
)

func BucketStatus

func BucketStatus(status string) Result

BucketStatus maps a raw CTRF test status to its corroboration Result bucket. The mapping is total: the five CTRF statuses are covered explicitly, and any unrecognized (malformed) status fails closed to ResultFail so a garbled report can never masquerade as a passing corroboration.

type Row

type Row struct {
	Phase     string   `json:"phase"`
	Name      string   `json:"name"`
	Consensus string   `json:"consensus"`
	Reported  int      `json:"reported"`
	Signers   []Latest `json:"signers"`
}

Row is one CTRF check within a phase, with its baked consensus and the latest-per-signer results that carried it (pass/fail only; not-run signers are omitted and render as empty cells).

type RunMeta

type RunMeta struct {
	SchemaVersion string            `json:"schemaVersion"`
	Coordinate    RunMetaCoordinate `json:"coordinate"`
	Recipe        string            `json:"recipe"`
	Signer        RunMetaSigner     `json:"signer"`
	RunID         string            `json:"runId"`
	AICRVersion   string            `json:"aicrVersion"`
	K8sVersion    string            `json:"k8sVersion"`
	K8sConstraint string            `json:"k8sConstraint"`
	BundleDigest  string            `json:"bundleDigest"`
	EvidenceRef   string            `json:"evidenceRef"`
	RekorLogIndex *int64            `json:"rekorLogIndex,omitempty"`
	AttestedAt    string            `json:"attestedAt"`
}

RunMeta is the verified, per-run metadata GP2 writes beside ctrf/ (Contract 3). Every field is sourced from the verified bundle predicate / snapshot — never the publish clock and never a free-text pointer field.

type RunMetaCoordinate

type RunMetaCoordinate struct {
	Group     string `json:"group"`
	Dashboard string `json:"dashboard"`
	Tab       string `json:"tab"`
}

RunMetaCoordinate is the GP2-derived coordinate carried in meta.json. GP4 re-verifies it against pkg/recipe.CoordinateFor on the inverted criteria.

type RunMetaSigner

type RunMetaSigner struct {
	IDHash      string `json:"idHash"`
	Identity    string `json:"identity"`
	Issuer      string `json:"issuer"`
	Class       string `json:"class"`
	Allowlisted bool   `json:"allowlisted"`
}

RunMetaSigner is the verified signer identity and its derived class.

type Series

type Series struct {
	// Recipe is the overlay metadata.name.
	Recipe string `json:"recipe"`

	// Builds maps each signer-id-hash to its build columns, newest first.
	Builds map[string][]SeriesBuild `json:"builds"`

	// Health maps each signer-id-hash to its derived run-health summary.
	Health map[string]SeriesHealth `json:"health"`
}

Series is the lazy per-recipe payload (series/<recipe>.json): the heavy per-source x per-build history the renderer loads on a source-column drilldown.

type SeriesBuild

type SeriesBuild struct {
	ID          string `json:"id"`
	AICRVer     string `json:"aicrVer"`
	K8sVer      string `json:"k8sVer"`
	When        string `json:"when"`
	Newest      bool   `json:"newest"`
	EvidenceRef string `json:"evidenceRef"`

	// Results maps every CTRF name in the recipe's union test set to this
	// build's outcome: "pass", "fail", or "not-run".
	Results map[string]string `json:"results"`
}

SeriesBuild is one signer run rendered as a build column.

type SeriesHealth

type SeriesHealth struct {
	// FlakePct is the percentage of build-to-build result transitions across
	// the recipe's union test set (0 when there is at most one build).
	FlakePct int `json:"flakePct"`

	// LastPassBuild is the newest build id in which every test this signer ran
	// passed, or "" when none.
	LastPassBuild string `json:"lastPassBuild"`

	// Builds is the number of build columns shown.
	Builds int `json:"builds"`
}

SeriesHealth is a signer's derived run-health summary for one recipe.

type SignerResult

type SignerResult struct {
	// SignerID is the distinct-signer counting key: the verified (issuer,
	// identity) pair (see signerIdentityKey), never a contributor-controlled
	// IDHash. Duplicate SignerIDs are collapsed by the defensive de-dup below
	// (the anti-sybil guarantee that one identity is one signer); callers should
	// still pre-reduce to latest-per-signer.
	SignerID string

	// Allowlisted reports whether this signer's verified identity is on the
	// in-tree allowlist. Only allowlisted signers carry corroboration weight;
	// an unallowlisted signer is a zero-weight "reported" dot.
	Allowlisted bool

	// Result is the bucketed outcome (see BucketStatus).
	Result Result
}

SignerResult is one distinct signer's latest in-scope result for a single row. Callers must pre-reduce to latest-per-signer (one entry per distinct SignerID) before calling ComputeConsensus; the consensus is computed over the set's cardinality, never the raw run count.

type Source

type Source struct {
	// Label is the human-readable source name.
	Label string `json:"label"`

	// Class is the derived source class: first-party | community | partner.
	Class string `json:"class"`

	// Allowlisted reports whether the source carries corroboration weight.
	// A false value renders as a zero-weight "reported" dot.
	Allowlisted bool `json:"allowlisted"`

	// SignerID is the verified OIDC identity (the human-auditable count key).
	SignerID string `json:"signerId"`
}

Source is one signer's public catalog record, keyed in Index.Sources by its signer-id-hash.

type State

type State string

State is a corroboration cell state. Its ordering under PhaseRollup is given by phasePriority (worst-first), not the declaration order here.

const (
	// StateConfirmed means >= 2 distinct allowlisted signers passed the row
	// and none failed it — the strongest positive signal.
	StateConfirmed State = "CONFIRMED"

	// StateSingle means exactly one allowlisted signer ran the row and it
	// passed: reported, not yet corroborated.
	StateSingle State = "SINGLE"

	// StateContested means allowlisted signers disagree (>= 1 pass and
	// >= 1 fail). First-class and surfaced, never averaged away.
	StateContested State = "CONTESTED"

	// StateFailing means every allowlisted signer that ran the row failed it.
	StateFailing State = "FAILING"

	// StateUntested means no allowlisted signer ran the row — a coverage gap,
	// distinct from FAILING.
	StateUntested State = "UNTESTED"
)

func RollupPhase

func RollupPhase(states []State) State

RollupPhase folds a set of row states into a single phase state using the worst-first precedence. An empty set (no rows in the phase) rolls up to UNTESTED.

type Tab

type Tab struct {
	// Recipe is the overlay metadata.name (the series-file slug).
	Recipe string `json:"recipe"`

	// Coord is the full five-dimension criteria for display and facet
	// filtering (service, accelerator, os, intent, platform).
	Coord map[string]string `json:"coord"`

	// PhaseRollup maps each phase to its worst-first rollup state.
	PhaseRollup map[string]string `json:"phaseRollup"`

	// Tests is the per-row grid, ordered by PhaseOrder then CTRF name.
	Tests []Row `json:"tests"`
}

Tab is one recipe (intent[-platform]) with its baked grid.

Jump to

Keyboard shortcuts

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