Documentation
¶
Overview ¶
Package spdx validates and canonicalizes SPDX license expressions for the grc.store publication-license field (ADR-0036).
(The package lives at spdx/ rather than license/ because the module's case-insensitive checkout cannot hold both a license/ directory and the top-level LICENSE file.)
A publisher declares a publication license at publish time; grcli stamps it as the OCI manifest annotation org.opencontainers.image.licenses and the hub reads it back. Both ends must agree on what a valid license is and on its canonical spelling, or the index fragments (Apache-2.0 vs apache-2.0 vs ASL2 as three "licenses"). This package is that one shared definition.
The two ends use it differently, by design (ADR-0036 decision 4):
- grcli is the STRICT gate. It calls Canonicalize and hard-fails the publish before any network call on a malformed expression OR an unknown leaf id — so typos never reach the registry.
- The hub is LENIENT. It calls Parse (syntax only) and stores Expression.String() — the structurally-canonicalized form, with known ids re-cased but unknown-but-well-formed ids passed through unchanged. It never rejects a sync over the license field: a publisher on a newer SPDX list than the hub must not have their already-pushed bytes orphaned. A malformed annotation parses with an error and the hub stores NULL.
Canonicalization (String) is what protects the index, not rejection: it collapses divergent spellings of the SAME license regardless of which path ran.
SPDX grammar supported: simple ids, the "or-later" "+" suffix, "WITH" exception, "AND"/"OR" (OR binds loosest), parentheses, and LicenseRef-/DocumentRef- custom identifiers. Operators are case-sensitive uppercase per the SPDX spec.
STABILITY: the canonical OUTPUT of String for a given input is contract — two importers on the same SPDXListVersion must produce byte-identical output. Bumping SPDXListVersion is additive (it can only make a previously-unknown id known, never change a known id's canonical casing), so it is a minor release; any change that alters String's output for an already-known id is BREAKING.
Index ¶
Constants ¶
const SPDXListVersion = "3.28.0"
SPDXListVersion is the SPDX license-list-data release the bundled id tables below were generated from.
Variables ¶
var ErrSyntax = errors.New("malformed SPDX license expression")
ErrSyntax means the string is not a well-formed SPDX license expression (the grammar is violated). The hub treats this as "no license" (store NULL).
var ErrUnknownID = errors.New("unknown SPDX license or exception id")
ErrUnknownID means the expression is well-formed but contains a license or exception id not in SPDXListVersion's list (excluding LicenseRef-/DocumentRef-, which are custom by definition). grcli treats this as fatal; the hub does not.
Functions ¶
func Canonicalize ¶
Canonicalize is the strict entry point (grcli's gate). It returns the canonical form of a well-formed expression whose every leaf id is known to SPDXListVersion, or an error wrapping ErrSyntax / ErrUnknownID otherwise.
Types ¶
type Expression ¶
type Expression struct {
// contains filtered or unexported fields
}
Expression is a parsed SPDX license expression. Its zero value is not usable; obtain one from Parse.
func Parse ¶
func Parse(expr string) (*Expression, error)
Parse validates SPDX expression GRAMMAR only and returns the parsed expression. It does NOT fail on unrecognized (but well-formed) ids — call UnknownIDs to check those. This is the hub's lenient entry point: on success store String(); on error store NULL.
func (*Expression) String ¶
func (e *Expression) String() string
String returns the canonical form: operators uppercased and single-spaced, known ids re-cased to their official SPDX spelling, "+" preserved, LicenseRef-/DocumentRef- preserved verbatim (those are case-sensitive), and the minimum parentheses needed to preserve OR/AND precedence.
func (*Expression) UnknownIDs ¶
func (e *Expression) UnknownIDs() []string
UnknownIDs returns the sorted, de-duplicated set of leaf license and exception ids in the expression that are NOT in SPDXListVersion's list. LicenseRef- and DocumentRef- identifiers are never reported (they are custom by definition). Empty means every id is recognized.