# Compatibility policy

Open Print treats a certificate as a long-lived record, not a short-lived API
response. Someone should be able to keep a certificate and verify it years
later with an independent copy of the format. That makes compatibility a
record-preservation concern as much as a software concern.

## What is frozen for v1

The committed baseline at `compatibility/v1-baseline.json` records the public
contract frozen for `1.0.0`. It covers:

- every published JSON Schema, including its identifier and exact bytes;
- the signed conformance fixtures;
- package export paths and command names;
- runtime named exports and TypeScript declarations;
- the supported Node.js floor; and
- the files promised in the package.

The schemas use `additionalProperties: false`. An older verifier would reject
a record containing a newly introduced field, even if that field were called
optional. For that reason, the complete v1 record shape is frozen. Adding,
removing, renaming, or changing the meaning of a field requires a new record
version and a new major package release.

Canonicalization, digest scopes, signature inputs, fixed notices, registry
rules, and verification meanings are also part of the v1 contract. They must
not change under an existing schema identifier.

## Changes allowed in 1.x

A 1.x release may fix an implementation bug when the fix brings the code back
to the frozen contract. It may improve documentation, diagnostics, or internal
performance without changing accepted records or verification results.

New public helpers may be considered for a minor release, but the compatibility
check will fail until the addition is reviewed. A new helper must not alter an
existing type, export path, record, or command. Deprecation may be documented
in 1.x; removal waits for the next major release.

## When the baseline changes

`npm run compatibility:check` rebuilds the package, compiles a small external
TypeScript consumer, and compares the current public surface with the committed
baseline. CI runs it on Node.js 20.10, 22, and 24.

Do not update the baseline merely to make CI green. First decide whether the
drift is:

1. a bug that should be reverted;
2. a compatible addition that belongs in a documented minor release; or
3. a breaking format or API change that requires a new major version.

After that decision is recorded in the changelog and reviewed, the baseline
can be regenerated deliberately:

```bash
OPEN_PRINT_ACCEPT_V1_CONTRACT_CHANGE=1 npm run compatibility:update
```

The environment variable is an acknowledgement, not an override. The updated
JSON and the code that required it must be reviewed together.

## Release history

The beta baseline became the v1 freeze after adversarial review and remediation.
Accidental drift remains a failure. If a confirmed security finding requires a
contract correction, the change must be documented, reviewed, captured in a new
baseline, and released under a new record or major package version. It must
never be accepted merely to make the compatibility check pass.
