{
  "version": "chem-api-versions-2026.1",
  "documentationUrl": "https://apis.allanninal.dev/chem/versioning.html",
  "current": "v1",
  "note": "The contract version in the URL path changes ONLY on a breaking change. Dataset versions move independently and are never breaking on their own. The full algorithm is in VERSIONING.md; this file is the machine-readable form of it, served at /chem/api/v1/versions.json and enforced by scripts/check-contract.mjs.",
  "policy": {
    "breakingChangeRequires": "a new path version (/v2). The previous version keeps serving.",
    "minimumSupportWindowMonths": 12,
    "minimumDeprecationNoticeMonths": 6,
    "deprecationSignals": [
      "Deprecation header (RFC 9745) carrying the date the version was deprecated",
      "Sunset header (RFC 8594) carrying the date it stops serving",
      "Link header with rel=\"deprecation\" pointing at the migration notes",
      "a deprecation block in every JSON response body"
    ],
    "breaking": [
      "removing or renaming a response field",
      "changing the type or units of a response field",
      "removing an endpoint, or changing its path",
      "adding a required request parameter",
      "tightening validation so a previously accepted request now fails",
      "changing a default value, page size or sort order",
      "changing the meaning of an existing field without renaming it",
      "changing the shape of a record inside a published dataset"
    ],
    "additive": [
      "adding a new endpoint",
      "adding a new response field",
      "adding a new OPTIONAL request parameter",
      "adding a new enum value to a field documented as open",
      "widening validation so a previously rejected request now succeeds",
      "correcting data values, or refreshing a dataset to a newer upstream edition",
      "a new CFR issue changing a published limit — the limits are data, not contract"
    ]
  },
  "versions": [
    {
      "version": "v1",
      "status": "current",
      "releasedOn": "2026-09-21",
      "deprecatedOn": null,
      "sunsetOn": null,
      "basePath": "/chem/v1",
      "changelog": [
        {
          "release": "1.0.0",
          "date": "2026-09-21",
          "kind": "initial",
          "summary": "Federal wine composition limits, the TTB treatment-material register, and deterministic cellar chemistry.",
          "justification": "Briefed as a wine quality PREDICTION API over the UCI dataset. That dataset is CC BY 4.0, which this fleet's licence rule excludes, and no CC0 chemistry-to-sensory dataset exists. Shipped instead as a public-domain compliance and chemistry service for the same audience, with the gap declared at /v1/sources. There is no model and no prediction endpoint.",
          "changes": [
            "POST /v1/lab/check — a lab panel in, per-analyte federal compliance out, with citation, verbatim regulation text and the arithmetic",
            "GET /v1/limits, /v1/limits/{analyte} — 27 CFR 4.21/4.22/4.32 composition maxima",
            "GET /v1/materials, /v1/materials/{id} — 27 CFR 24.246 treatment materials",
            "GET /v1/production — 27 CFR part 24 amelioration and cellar-treatment sections",
            "POST /v1/calc/molecular-so2, /v1/calc/potential-alcohol — cellar chemistry",
            "GET /v1/sources — upstreams and the full rejection register",
            "GET /v1/plans, /v1/usage, /v1/version, /v1/changes, /v1/history/coverage"
          ]
        }
      ]
    }
  ],
  "datasetVersioning": {
    "scheme": "<source>-<year>.<edition>",
    "example": "ecfr-title27-part4-2026.1",
    "rule": "A dataset version increments when the upstream data or the build that shapes it changes. Every response carries datasetVersions so a caller can pin, cache and reproduce. Refreshing a dataset is ADDITIVE: values may change, record shape may not. A change to the SHAPE of a dataset record is a breaking API change and takes a new path version.",
    "reproducibility": "Any response can be reproduced from its datasetVersions plus the build in this repo at the matching tag.",
    "cfrIssueDateIsSeparate": "cfrIssueDate (e.g. 2026-09-17) is eCFR's own issue date for title 27, carried verbatim. It is not this service's dataset version: the dataset version moves when the build that shapes the data changes, the issue date moves when TTB revises the regulation. Both are served at /v1/version so a caller can pin either."
  }
}
