Documentation
¶
Overview ¶
Package project synthesizes the source-keyed evidence tree that the GP4 corroborate consensus generator consumes. Given an already-verified evidence bundle plus its verified signer claims, Synthesize writes
<root>/results/<group>/<dashboard>/<tab>/<idHash>/<runId>/
meta.json
ctrf/<phase>.json (only the phases the run produced)
where the coordinate comes from the bundle recipe's criteria (recipe.CoordinateFor) and idHash is the stable per-signer dedup key (SignerIDHash). meta.json carries schema aicr-corroboration-meta/v1.
This package performs no verification and no network I/O: the caller (tools/evidence-project) runs pkg/evidence/verifier first and passes only verified inputs. Every signer field recorded here is the cryptographically verified value, never an unverified pointer claim; Synthesize fails closed when no verified signer is present.
Determinism: identical inputs always produce byte-identical output, and a re-ingest of the same bundle replaces its run directory in place rather than duplicating it — so the tree (and any digest taken over it) is reproducible.
Index ¶
Constants ¶
const MetaFilename = "meta.json"
MetaFilename is the bundle-relative name of the synthesized metadata file in each run directory.
const MetaSchemaVersion = "aicr-corroboration-meta/v1"
MetaSchemaVersion is the schema constant the GP4 corroborate consumer expects in every meta.json. A mismatch only warns there, but the producer always writes the current version.
Variables ¶
This section is empty.
Functions ¶
func SignerIDHash ¶
SignerIDHash derives the stable source-dedup key for a verified signer from its (issuer, identity) pair. It is the contract between this producer (GP2 ingest) and the GP4 corroborate consumer, which counts consensus by distinct idHashes: the same verified signer must hash to the same value across every recipe and every run, and two different signers must not collide.
The derivation is the first idHashLen (32) hex characters of sha256(issuer + "\n" + identity). It is intentionally simple and dependency-free so both sides can reproduce it byte-for-byte; do not change the algorithm without coordinating a migration of the GCS tree and the consumer.
Inputs must be the *verified* issuer and identity (Fulcio cert SAN + OIDC issuer), never a raw, unverified pointer claim.
Types ¶
type Allowlist ¶
type Allowlist struct {
// contains filtered or unexported fields
}
Allowlist wraps the shared GP1 allowlist loader (pkg/evidence/allowlist) for the GP2 producer. A nil *Allowlist is valid and applies only the interim first-party heuristic plus the community fail-closed default.
func LoadAllowlist ¶
LoadAllowlist reads, parses, and validates the allowlist at path via the shared loader: size-bounded read, schema-version gate (1.0.x), anchored entries, disjoint classes, no overlaps. A malformed file fails closed with ErrCodeInvalidRequest (ErrCodeNotFound when missing).
func (*Allowlist) Classify ¶
Classify resolves a verified (issuer, identity) to its class and whether it counts toward corroboration. Resolution order:
- With an allowlist loaded, the shared classifier decides: a matching entry wins (allowlisted=true); an unmatched signer is community, not allowlisted — the fail-closed default (reported, never counted).
- When no allowlist is loaded (nil receiver), the built-in first-party heuristic admits AICR's own UAT identity so it is not mislabeled community; everything else falls through to community, not allowlisted.
type Class ¶
type Class string
Class is the trust classification recorded for a verified signer. It drives how the GP4 consensus model weighs a source: only allowlisted sources count toward consensus; everything else is reported but contributes zero weight.
Classification delegates to the shared authoritative loader in pkg/evidence/allowlist so the producer (GP2) and the GP4 consumer (pkg/corroborate) read the identical recipes/evidence/allowlist.yaml (owned by GP1, identityPattern/source schema) and classify a verified signer identically (#1505).
const ( // ClassFirstParty marks evidence produced by AICR's own UAT pipeline. ClassFirstParty Class = Class(allowlist.ClassFirstParty) // ClassCommunity marks evidence from an allowlisted community signer, // and is also the fail-closed fallback for a verified-but-unallowlisted // signer (reported, but never counted). ClassCommunity Class = Class(allowlist.ClassCommunity) // ClassPartner marks evidence from an allowlisted partner signer. ClassPartner Class = Class(allowlist.ClassPartner) )
type Coordinate ¶
type Coordinate struct {
Group string `json:"group"`
Dashboard string `json:"dashboard"`
Tab string `json:"tab"`
}
Coordinate is the recipe's placement in the navigation space, mirrored from recipe.Coordinate so meta.json carries the canonical segments the consumer round-trips through recipe.CoordinateFor.
type In ¶
type In struct {
// BundleDir is the unpacked, verified summary-bundle directory. Its
// recipe.yaml supplies the coordinate and K8s constraint; its
// ctrf/<phase>.json files are copied into the run directory.
BundleDir string
// Predicate is the verified predicate body (preferably from the
// signed DSSE payload). Supplies attestedAt, aicrVersion, recipe
// name, k8s version, and the bundle (manifest) digest.
Predicate *attestation.Predicate
// SignerIdentity and SignerIssuer are the verified OIDC claims. An
// empty SignerIdentity means no verified signer and Synthesize
// fails closed — unverified evidence must never reach the tree.
SignerIdentity string
SignerIssuer string
// RekorLogIndex is the verified transparency-log index, or nil when
// no Rekor entry exists. Omitted from meta.json when nil.
RekorLogIndex *int64
// Class and Allowlisted are the trust verdict from Allowlist.Classify.
Class Class
Allowlisted bool
// EvidenceRef is the OCI reference of the signed bundle, recorded as
// the drilldown link. Empty is allowed (e.g. a local-only ingest).
EvidenceRef string
// RunID overrides the run identifier. When empty, it is derived
// deterministically from the predicate's attestedAt.
RunID string
// OutRoot is the root directory the source-keyed tree is written
// under (the tree lives at <OutRoot>/results/...).
OutRoot string
}
In is the input to Synthesize. Every signer field must be the cryptographically *verified* value (Fulcio cert SAN + OIDC issuer + Rekor index), never an unverified pointer claim — the caller is responsible for having run verification first.
type Meta ¶
type Meta struct {
SchemaVersion string `json:"schemaVersion"`
Coordinate Coordinate `json:"coordinate"`
Recipe string `json:"recipe"`
Signer Signer `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"`
}
Meta is the synthesized per-run metadata the GP4 corroborate consumer reads. It is the authoritative coordinate source — the directory layout is convention only. Field order is fixed so the JSON encoding is deterministic across runs from identical input.
func (*Meta) MarshalDeterministic ¶
MarshalDeterministic renders meta.json bytes that are byte-identical across runs from identical input. Meta is a flat struct with no Go maps, so encoding/json emits fields in declaration order; a trailing newline matches the conventional on-disk form.
type Result ¶
type Result struct {
// RunDir is the absolute-or-relative path of the per-run directory
// (…/results/<group>/<dashboard>/<tab>/<idHash>/<runId>).
RunDir string
// Coordinate is the recipe placement the meta.json records.
Coordinate recipe.Coordinate
// IDHash is the source-dedup key derived from the verified signer.
IDHash string
// Phases lists the ctrf/<phase>.json files copied, in canonical order.
Phases []string
}
Result reports what Synthesize wrote.
func Synthesize ¶
Synthesize verifies the inputs, derives the recipe coordinate and signer id-hash, and writes the source-keyed run directory (meta.json plus the present ctrf/<phase>.json reports) under In.OutRoot. It is idempotent on identical input: re-ingesting the same bundle replaces the run directory in place rather than duplicating it.
Synthesize never consults the network and performs no verification of its own — the caller must pass already-verified inputs.
type Signer ¶
type Signer struct {
IDHash string `json:"idHash"`
Identity string `json:"identity"`
Issuer string `json:"issuer"`
Class Class `json:"class"`
Allowlisted bool `json:"allowlisted"`
}
Signer is the verified-signer block of meta.json. Every field is derived from the cryptographically verified certificate/Rekor entry, never from an unverified pointer claim. IDHash is the source-dedup key (see SignerIDHash); Identity drives the display label in the grid.