project

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: 17 Imported by: 0

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

View Source
const MetaFilename = "meta.json"

MetaFilename is the bundle-relative name of the synthesized metadata file in each run directory.

View Source
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

func SignerIDHash(issuer, identity string) string

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 {
	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). The three class sections are disjoint and non-overlapping. A nil *Allowlist is valid and applies only the interim first-party heuristic plus the community fail-closed default.

func LoadAllowlist

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

LoadAllowlist reads, parses, and validates the allowlist at path. The read is size-bounded before parse so an attacker-influenced path cannot OOM the process. Returns ErrCodeInvalidRequest on a bad file.

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. Resolution order:

  1. The first matching allowlist entry wins (allowlisted=true).
  2. When no allowlist is loaded (nil receiver, the interim state before GP1 ships recipes/evidence/allowlist.yaml), the built-in first-party heuristic admits AICR's own UAT identity so it is not mislabeled community. Once the allowlist file exists this branch is never reached — classification then matches the GP4 consumer exactly.
  3. Otherwise community, not allowlisted — the fail-closed default.

func (*Allowlist) Validate

func (a *Allowlist) Validate() error

Validate enforces the anti-sybil invariants so the allowlist is not itself an attack surface: every entry has a non-empty issuer and identity; no identity is over-broad (no unbounded wildcard segment); and the classes are disjoint (one verified identity matches at most one entry). The producer re-checks these (defense in depth) even though GP1 lints the file in its own repo CI.

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 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.

The schema and matching semantics here intentionally mirror the consumer-side loader in pkg/corroborate so the producer and the GP4 generator read the identical recipes/evidence/allowlist.yaml (owned by GP1) and classify a verified signer identically.

const (
	// ClassFirstParty marks evidence produced by AICR's own UAT pipeline.
	ClassFirstParty Class = "first-party"

	// 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 = "community"

	// ClassPartner marks evidence from an allowlisted partner signer.
	ClassPartner Class = "partner"
)

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

func (m *Meta) MarshalDeterministic() ([]byte, error)

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

func Synthesize(ctx context.Context, in In) (*Result, error)

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.

Jump to

Keyboard shortcuts

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