corroborate

package
v0.17.0-rc1 Latest Latest
Warning

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

Go to latest
Published: Jul 13, 2026 License: Apache-2.0 Imports: 21 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 (
	LinkGitHub  = "https://github.com/NVIDIA/aicr"
	LinkDocs    = "https://docs.aicr.run/"
	LinkInstall = "curl -sfL https://get.aicr.run | bash"
)

Outbound header targets, baked into index.json meta so the renderer stays data-driven (a maintainer flips one literal here, not the template). An empty value renders nothing (the renderer fails soft). LinkInstall is a shell command (copied to the clipboard), not a URL; LinkDocs/LinkGitHub are http(s) links opened in a new tab.

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.

Variables

This section is empty.

Functions

This section is empty.

Types

type Allowlist

type Allowlist = allowlist.Allowlist

Allowlist is the in-tree, PR-reviewed signer allowlist (recipes/evidence/allowlist.yaml, owned by GP1). GP4 consumes the shared authoritative loader in pkg/evidence/allowlist so producer (GP2) and consumer (GP4) parse the identical identityPattern/source schema (#1505).

func LoadAllowlist

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

LoadAllowlist reads and validates the allowlist at path via the shared loader. The read is size-bounded before parse, the schema version is gated (1.0.x), and the anti-sybil invariants (anchored entries, disjoint classes, no overlaps) are enforced — a malformed file fails closed.

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 = Class(allowlist.ClassFirstParty)

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

	// ClassPartner is an allowlisted partner signer.
	ClassPartner Class = Class(allowlist.ClassPartner)
)

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 Counts added in v0.17.0

type Counts struct {
	Recipes int `json:"recipes"`
	CSPs    int `json:"csps"`
	Sources int `json:"sources"`
}

Counts are the landing-page summary tallies (validated recipes, CSPs, and distinct signing sources).

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"`

	// Meta is presentation metadata (outbound links, summary counts, and the
	// deterministic generated-at stamp). Additive; never feeds consensus.
	Meta Meta `json:"meta"`

	// 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 Links struct {
	Install string `json:"install"`
	Docs    string `json:"docs"`
	GitHub  string `json:"github"`
}

Links are the outbound header navigation targets. An empty value hides that link in the renderer.

type Meta added in v0.17.0

type Meta struct {
	// Links are the outbound header navigation targets.
	Links Links `json:"links"`

	// Counts are the landing summary tallies.
	Counts Counts `json:"counts"`

	// GeneratedAt is the newest run AttestedAt rendered "YYYY-MM-DD HH:MM UTC",
	// or "" (omitted) when no run carried a parseable AttestedAt. Derived from
	// evidence, never the publish clock, so it stays byte-reproducible.
	GeneratedAt string `json:"generatedAt,omitempty"`
}

Meta is presentation metadata for the renderer header and landing summary. Purely additive — none of it feeds the consensus math.

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"`

	// Versions holds one baked consensus grid per AICR version present in the
	// evidence, newest-first.
	Versions []TabVersion `json:"versions"`
}

Tab is one recipe (intent[-platform]). Its consensus is split per AICR version so that corroboration only counts agreement at the SAME version (cross-version agreement is not reproduction). Versions are newest-first; the overview/landing summarize the newest (Versions[0]).

type TabVersion added in v0.17.0

type TabVersion struct {
	// AICRVer is the AICR version this grid's consensus was computed at.
	AICRVer string `json:"aicrVer"`

	// 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"`
}

TabVersion is one recipe's baked consensus grid for a single AICR version.

Jump to

Keyboard shortcuts

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