# The GAVR specification

GAVR (GAdvisory Vulnerability Record) is a vulnerability record format, an
identifier namespace, and the protocol a participant uses to publish into a
registry.

**This specification exists so it can be implemented without reading our
TypeScript.** A participant running a Python, Go or vendor advisory system
cannot use an npm package, and handing them one answers a question they did not
ask. `@gadvisory/gavr` is the reference implementation and
`@gadvisory/gavr-client` is a client for participants who happen to be on Node;
neither is the interoperability story. This is.

## Documents

| Document                                 | Covers                                                               |
| ---------------------------------------- | -------------------------------------------------------------------- |
| [identifiers.md](identifiers.md)         | `GAVR-A7K2QXR8`, `GAVLR-42-7-A7K2QX`, normalisation, resolution      |
| [canonical-json.md](canonical-json.md)   | RFC 8785, and the one trap no naive implementation gets right        |
| [signing.md](signing.md)                 | Ed25519, the pre-image, custody, and what a signature does not prove |
| [record.md](record.md)                   | The document: identity, versions, severity, remediation, relations   |
| [companion-rules.md](companion-rules.md) | The rules the published JSON Schema cannot carry. **Generated.**     |
| [lifecycle.md](lifecycle.md)             | One primary state, orthogonal facets, the transition table           |
| [scope.md](scope.md)                     | An authority's scope of authority: enforcement and routing           |
| [protocol.md](protocol.md)               | Action envelopes, freshness, replay, intake, the countersignature    |

Two artefacts sit beside them and are the operative part of the contract:

- **[`../src/schemas/gavr-record-1.0.json`](../src/schemas/gavr-record-1.0.json)**,
  the JSON Schema. Draft-07, so a stock validator in any language can load it.
- **[`../conformance/`](../conformance/)**, the corpus: inputs and the verdicts
  a conforming implementation must reach.

## What conformance means

An implementation is conformant when it reaches the corpus's verdict on every
case in every suite. Not when it validates against the schema — that is
necessary and **not sufficient**, and the gap is asymmetric in the dangerous
direction: an implementation checking only the schema ACCEPTS records the
registry refuses, so it looks conformant right up until submission fails. The
nine rules in that gap are the companion rules, and each has cases in the
corpus.

The reference implementation runs the same corpus. That is deliberate: a corpus
only third parties run is a corpus that rots, and "one implementation of the
specification" has to mean something checkable.

## The closed sets are frozen at 1.0

Every enumerated set and every object shape in this specification is fixed.
Adding a member is a breaking change for you: your validator will refuse a
record carrying a value it has never heard of, and that refusal will arrive as a
record you cannot read rather than as an error anybody warned you about.

Two things are extensible, and only these two.

- **`x_`-prefixed properties on a CONTAINER**, per GAVR-R-027. The pattern is
  CVE's own (`^x_[^.]*$`), so an implementer who has written that check already
  has written this one. **You MUST preserve unknown `x_` keys verbatim when you
  re-serialise a record**: the document is canonicalised and signed, so dropping
  a key you do not understand produces bytes that fail every signature over
  them — and it fails for a record you were handed rather than one you wrote.
  The record's own fields are NOT extensible, because an extension there could
  carry a lifecycle claim this specification cannot see.
- **Generic members**, where a real source format forced one: `other` on
  `TIMELINE_EVENTS`, `REMEDIATION_KINDS` and `CREDIT_TYPES`, and free text on
  `ecosystem` and a detection artifact's `kind`. The first two require a note or
  a description beside them (GAVR-R-025, GAVR-R-026), because "something
  happened and we will not say what" is worse than the entry's absence.

## Versioning

Three version numbers, deliberately independent, because they change for
different reasons.

**The record schema version** is `schemaVersion` inside every document, `1.0`
today. It changes only when a document written under the old version stops
meaning what it meant, or stops being acceptable. Adding an optional field is
not that; removing one, tightening one, or changing what a value implies is. A
consumer branches on this field, which is why it is a `const` in the JSON
Schema rather than a free string.

**The specification edition** is the date on each document. It moves whenever
the prose is clarified, corrected or expanded — frequently, and without any
implication for a document already written. An edition never changes what is
conformant. If it appears to, the specification was wrong and the corpus is the
tie-break.

**The npm package versions** (`@gadvisory/gavr`, `@gadvisory/cve-record`,
`@gadvisory/gavr-client`) follow their own semver and mean nothing to an
implementation in another language. Do not infer a schema version from a package
version.

The protocol carries its own version inside the signing context prefix
(`GAVR-SIG/v1/...`), separately from all three, because a change there
invalidates signatures rather than documents.

## Where the authority lies

When these disagree, this is the order:

1. **The conformance corpus.** It is executable, and both sides run it.
2. **The JSON Schema**, for anything structural.
3. **These documents.**
4. **The reference implementation.**

Prose loses to the corpus on purpose. A specification whose text is the final
authority is a specification with no way to settle an argument.

## Licence and scope

The specification, the schema, the corpus and the reference implementation are
Apache-2.0. `apps/api` and `apps/web`, the GAdvisory product, are not part of
this and are not open source. Nothing here depends on them.
