# Supply chain and support policy

Source: https://docs.settlemint.com/docs/deployment/supply-chain-and-support
How a release image is built and verified, how a version maps to one build, which release lines take patches, and how a report becomes a fix.

Every DALP release publishes container images and a Helm chart, built by SettleMint's automated release build. A DALP Instance runs from those images, and each image carries a SLSA provenance record and an SPDX bill of materials in the registry you pull it from. Neither record is signed. At most two release lines take patches at a time, and a suspected vulnerability is reported to support@settlemint.com.

## What every image carries [#what-every-image-carries]

The DALP images come from `ghcr.io`, in a repository per component, and the chart comes from `pkg.distribution.settlemint.com`. A default install also pulls third-party images. PgBouncer, its metrics exporter and the `kubectl` helper come from `docker.io`, the PostgreSQL exporter from `quay.io`, and the `pause` placeholder from `registry.k8s.io`. Allow all five hosts where egress is restricted, or mirror every image and set `global.imageRegistry`. The records on this page are attached to the DALP images only.

Each DALP image is published with two records attached to it.

The first is a provenance attestation in the SLSA format: a record of the build that names the commit it was built from, its build definition, and the base images it resolved. The second is a software bill of materials in the SPDX format, listing the packages the image's final stage installs and their licences. A component that ships as a compiled binary keeps its JavaScript dependencies inside that binary, so no package listing enumerates them. Neither record is signed, so a reviewer reads what the build did and cannot check a signature against it. [Third-party components and licences](https://docs.settlemint.com/docs/deployment/third-party-components) lists the GPL-3.0 and AGPL-3.0 services and contract code that a deployment includes beside DALP's own images.

Read either record from any machine that holds credentials for the image registry. Those are the same credentials you gave the chart for its pull secrets, which [Prerequisites](https://docs.settlemint.com/docs/deployment/prerequisites) covers:

```sh
docker buildx imagetools inspect ghcr.io/settlemint/dalp-dapi:<version> --format '{{json .Provenance}}'
docker buildx imagetools inspect ghcr.io/settlemint/dalp-dapi:<version> --format '{{json .SBOM}}'
```

Substitute the reference the chart renders for the container you are checking. The first command prints the provenance document, the second the bill of materials. Check that the subject digest in the provenance document is the digest of the platform image it describes. Both records are part of the image's registry entry, not its contents, so a mirror that copies the whole reference keeps them and a copy taken from the platform image alone carries neither.

## How a version maps to one build [#how-a-version-maps-to-one-build]

A release builds each image once per set of inputs and names that build after its inputs. The release hashes the image build definition, the files the build reads, the digests of the base images, the dependency lockfile, the build configuration, and the hashes of the steps that produce the image. Those inputs produce a source tag of the form `source-<hash>`, the same tag on every run when nothing changed, and a new tag when anything did. Every image in a release is built for Linux on x86-64.

[Figure] A version tag is created from the same digest. The build inputs are hashed into a source tag. The image is built once with its provenance and bill of materials attached, and that build sits under the source tag. The version tags are then created from the same manifest digest, so no rebuild stands between the two. The Helm chart ships at the same version and selects those image tags through its app version. A later release run finds the existing source tag and creates only the new version tags from it. Labels: The version tag comes from the same digest; One commit, one build, one digest; 1. The build inputs are hashed into a source tag; Same inputs, same tag, on every run; 2. The image is built once; Provenance and a bill of materials attach to it; 3. The source tag holds that build; A digest that changes only when an input changes; 4. The version tags point at the same digest; No rebuild stands between the two tags; 5. The chart ships at that version; Its app version selects the image tags it renders.

A release hashes its inputs into a source tag, builds once under it, and creates the version tags from the same
digest.

The version tag is created from the digest the source tag holds. A later release run finds the source tag already present, creates the new version tags from that build, and starts no second build, so a version tag and the source tag it came from always name the same image.

The chart carries the number too. A release sets the chart version and the chart's app version to the same version, and the image tags it renders follow that app version, so the images and the chart come from one commit. Pin the chart version and leave a component's image tag empty, and that chart version selects the image builds released with it. A tag pinned to an older build than the chart is the combination that breaks, because the chart's probes and settings belong to the build it ships with.

The chart carries no attestation of its own, so its version is what you check, together with the packaged chart and the values it renders, which `helm show chart` and `helm show values` print before an upgrade. The release does not overwrite a published chart version: it refuses to push a chart version that already exists. The chart version you pin therefore names one chart, and the version tags created for it name one image per component.

## How a version is numbered [#how-a-version-is-numbered]

Versions follow major.minor.patch. The first release of a minor version, `X.Y.0`, opens a release line, and each patch release of `X.Y` ships on that line. A patch release keeps the minor version you run and carries the fix, so the version number you pin tells you which line a release belongs to.

The [changelog](https://docs.settlemint.com/docs/changelog) records what each version carries. Patch releases do not get entries of their own. The changes a patch carries are listed in the entry of the next minor release.

## Which release lines take patches [#which-release-lines-take-patches]

At most two release lines are live at a time: the current generally available line and the one before it. The first release of a new minor version opens its line, keeps the line before it, and retires the line before that. A retired line takes no further patches.

A line takes patches from its `X.Y.0` release until the second newer minor version ships, so the support window is counted in release lines, not in dates. No minimum calendar period is stated. A fix that affects a live line ships as a patch release on that line and reaches later releases too. When the line you run retires, [Upgrades and migrations](https://docs.settlemint.com/docs/deployment/upgrades-migrations) covers the move to a live one.

## What stays compatible across an upgrade [#what-stays-compatible-across-an-upgrade]

The API contract you integrate against keeps working on the terms its version carries. A stable version never loses an operation and never changes one incompatibly inside itself. A breaking change ships only as a new version beside the one you call, and an operation or a whole version is removed only after a deprecation announcement that gives at least 90 days' notice. [API versioning and deprecation](https://docs.settlemint.com/docs/api-reference/guides/versioning-and-deprecation) names which versions are stable and holds the headers, the contract fields, and the notice window.

On the deployment side, one Helm upgrade moves every component to the new version together, and on the default migration hook the database migration runs before the new pods start. The API promise does not cover the database schema or the chart's values. [Upgrades and migrations](https://docs.settlemint.com/docs/deployment/upgrades-migrations) covers the hook choice, the migration gate, what a failed migration leaves behind for you to inspect, and the checks to run before an upgrade.

## How a vulnerability report reaches a fix [#how-a-vulnerability-report-reaches-a-fix]

Report a suspected vulnerability in the platform to support@settlemint.com. It is the only published reporting route, and SettleMint publishes no response time, fix time or advisory channel.

A fix for a reported vulnerability follows the route any production fix takes. It ships as a patch release on the affected release line and reaches later releases too. A patch release that carries a fix changes the image digest, so a digest comparison confirms whether the build you run is the published build of the version that carries the fix.

## Frequently asked questions [#frequently-asked-questions]

### How do you confirm the image on your cluster is the published one?

Read the digest the cluster resolved and compare it with the digest the registry publishes for that version. Each running container reports the image it pulled:

```sh
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.containerStatuses[*].imageID}{"\n"}{end}'
docker buildx imagetools inspect <image-reference>
```

The second command prints the reference, the digest of the index the tag names, and one manifest per platform the index carries. Take the `linux/amd64` entry, which is the manifest a node runs, and compare it with the digest in the container's image ID. Equal digests mean the node runs the published build of that version. A difference means the copy came from another build, which happens when a build ran again from changed inputs, when a mirror republished the image under its own digest, or when the reference names an older version.

### Which value pins the image a chart renders?

Each component carries its own image block, so the value is component-scoped, such as `dapi.image.tag` or `dapp.image.tag` in the values you pass the DALP chart. There is no single top-level image tag over every component. A release sets the chart version and the chart's app version to the same number, and each component's tag defaults to that app version, so pinning the chart version and leaving the image tags empty follows the release.
