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
- type Allowlist
- type Class
- type Consensus
- type Counts
- type Dashboard
- type GenerateResult
- type Group
- type Index
- type Latest
- type Links
- type Meta
- type Options
- type Result
- type Row
- type RunMeta
- type RunMetaCoordinate
- type RunMetaSigner
- type Series
- type SeriesBuild
- type SeriesHealth
- type SignerResult
- type Source
- type State
- type Tab
- type TabVersion
Constants ¶
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.
const RunMetaSchemaVersion = "aicr-corroboration-meta/v1"
RunMetaSchemaVersion is the meta.json schema GP4 reads (Contract 3, written by the GP2 ingest job).
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 ¶
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 ¶
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 ¶
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 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 ¶ added in v0.17.0
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 ¶
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 ¶
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.