conformance

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Sep 13, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package conformance is an independent reader for the DevProof bundle format.

It exists to answer one question: does the format specification, read on its own, describe the artifacts DevProof actually produces? A test that checks a writer against its own reader proves only that the two agree. If both share a constant, a sort order, or an encoding helper, they share its bugs, and a round trip passes while the artifact is unreadable by anyone else.

So this package is deliberately built from docs/bundle-format.md and nothing else. It imports no other DevProof package — not the media-type constants, not the canonical encoders, not the digest helpers. Every value it compares against is written out here from the specification text, and every structure it parses it parses again from scratch. Where this package and the main implementation disagree, one of them is wrong, and finding out which is the entire point.

It reads raw tar blocks rather than using archive/tar. That package is lenient by design: it accepts GNU and base-256 encodings, silently joins the USTAR prefix field onto the name, and hides how a value was spelled. Every one of those kindnesses conceals exactly the deviation this package exists to find, and a reader built on it accepted archives no conforming writer produces. The one outside dependency is a Unicode normalizer, because NFC is a specification rule and its tables are not in the standard library.

It is intentionally simple and unoptimized. It buffers what a streaming reader would not, because being obviously correct matters more here than being fast, and a second implementation that is clever enough to be wrong in the same way as the first has no value.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CheckCanonicalJSON added in v0.4.0

func CheckCanonicalJSON(data []byte) error

CheckCanonicalJSON verifies that bytes are RFC 8785 canonical JSON.

The config and the manifest are the two documents whose digests are the artifact's identity, so "the same document" has to mean "the same bytes". Two writers that agree on every value and disagree on key order produce two different subject digests for one payload, and the disagreement is invisible to anything that compares decoded values.

This used to be a json.Compact round trip, which only catches insignificant whitespace. Reordered keys, a non-minimal string escape, and a number spelled with a leading plus or an exponent all survived it.

The scan is over the raw bytes rather than over a decoded value, because a decoder has already thrown away the spelling that is the thing in question.

Types

type BlobFetcher

type BlobFetcher func(digest string) ([]byte, error)

BlobFetcher supplies a blob by digest.

The digest is the caller's to verify or not; this package verifies every blob it receives regardless, which is what lets the same code check a layout on disk and a response from a registry.

type FileRecord

type FileRecord struct {
	Path   string
	Mode   uint32
	Size   int64
	Digest string
}

FileRecord is one canonical file.

type Level added in v0.4.0

type Level int

Level selects how much of the specification a verification applies.

The three levels answer three different questions, and conflating them is how an implementation ends up claiming more than it checked:

  • LevelStructure asks whether the artifact is intact and internally consistent, and whether expanding it is safe. Every digest is recomputed, the inventory is compared against what the layer actually held, and no path may escape the destination.
  • LevelCanonical asks whether these are the only bytes a conforming writer could have produced for this tree. Entry order, fixed header fields, the extended-header restriction, the frozen gzip header, RFC 8785 member order, and the portable path rules are all in this level and none of them affect whether the artifact can be read.
  • LevelBytes asks whether a writer reproduces the published vectors exactly. That is a property of an implementation rather than of an artifact: it is checked by building the documented input tree and comparing the result with vectors/format/v1. VerifyVectors runs the comparison for the published files themselves.

A deviation found above the requested level is reported in Report.Deviations rather than discarded, so a level-1 pass still says what it tolerated.

const (
	// LevelStructure verifies structure and integrity.
	LevelStructure Level = iota + 1
	// LevelCanonical adds every rule that makes the encoding the only one.
	LevelCanonical
	// LevelBytes adds agreement with the published byte vectors.
	LevelBytes
)

func (Level) String added in v0.4.0

func (l Level) String() string

String names a level for diagnostics.

type Report

type Report struct {
	// Level is the level the read was performed at.
	Level Level
	// Deviations are canonical-encoding differences found while reading.
	//
	// At [LevelCanonical] a read fails on the first one, so this is empty or
	// the read returned an error. At [LevelStructure] it is the list of things
	// the pass tolerated, which is the difference between "verified" and
	// "verified, and here is what a stricter reader would have said".
	Deviations []string

	// ManifestDigest is the subject identity: sha256 over the manifest bytes.
	ManifestDigest string
	// TreeDigest is recomputed here from the layer, not read from the config.
	TreeDigest string
	// ConfigTreeDigest is what the config claimed.
	ConfigTreeDigest string
	FileCount        int64
	TotalSize        int64
	// Files is the inventory as recomputed from the layer.
	Files []FileRecord
}

Report is what an independent read established.

func VerifyLayout

func VerifyLayout(dir, reference string, level Level) (*Report, error)

VerifyLayout reads a bundle from an OCI image layout and checks it against the format specification.

reference selects the subject: a tag matched against org.opencontainers.image.ref.name, or a "sha256:..." digest. An empty reference is accepted only when the layout holds exactly one manifest, because guessing which of several a caller meant is how the wrong artifact gets verified.

func VerifyManifest

func VerifyManifest(manifestBytes []byte, fetch BlobFetcher, level Level) (*Report, error)

VerifyManifest checks a manifest and everything it references.

func VerifyVectors added in v0.4.0

func VerifyVectors(fsys fs.FS) (*Report, error)

VerifyVectors checks a set of published byte vectors against each other and against this reader.

This is LevelBytes. The manifest, config, and layer in the set are read as one artifact at LevelCanonical, and the subject digest the set publishes is compared with the one recomputed from the manifest bytes. An implementation demonstrates byte conformance by producing files that pass this from the documented input tree: identical values are not enough, because two encoders that agree on every value and disagree on a spelling give one payload two identities.

fsys is the directory holding the vector files, which lets the same check run against this repository's vectors/format/v1 and against another implementation's output.

type Vector added in v0.4.0

type Vector string

Vector names one published byte vector.

const (
	VectorManifest      Vector = "manifest.json"
	VectorConfig        Vector = "config.json"
	VectorLayer         Vector = "layer.tar.gz"
	VectorLayerTar      Vector = "layer.tar"
	VectorTreeRecords   Vector = "tree-records.bin"
	VectorTreeDigest    Vector = "tree-digest.txt"
	VectorSubjectDigest Vector = "subject-digest.txt"
	VectorGzipSample    Vector = "gzip-sample.gz"
)

The published vectors for format v1.

They live in vectors/format/v1 at the repository root rather than under a testdata directory, because an implementation in another language has to be able to read them. Regenerating them is correct only when introducing a new format version.

Jump to

Keyboard shortcuts

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