Appearance
Integrity
Integrity here means: "the bytes you install are the bytes the publisher shipped." This page covers what guarantees the artifact registry provides today and what is target state.
Present state
Integrity verification today is exactly what npm provides:
| Mechanism | Coverage | Source |
|---|---|---|
| Tarball SHA-1 | Computed at publish, returned in package metadata. Verified by npm/pnpm clients. | npm protocol |
Tarball SHA-512 (integrity field) | Computed at publish, returned in package metadata. Verified by modern npm/pnpm clients. | npm protocol |
| Lockfile pinning | Consumer locks the SHA-512 in pnpm-lock.yaml / package-lock.json. Re-installs verify. | npm/pnpm |
| TLS to registry | Gitea is fronted by Caddy with TLS. Tampering in transit is detected. | Caddy |
| Gitea internal storage | Gitea uses content-addressed blob storage internally. Tampering on disk would break Gitea's lookup. | Gitea |
This is the minimum bar for any npm-compatible registry. It defends against:
- Network tampering (TLS).
- Accidental re-upload-mutation (Gitea's blob store rejects different content for the same package-version key).
- Unintended dependency drift (lockfile SHA-512 mismatch fails install).
What it does NOT defend against
- Publisher compromise. A leaked Gitea token can publish anything as the victim. Without signing, there is no out-of-band proof of who published.
- Registry compromise. A compromised Gitea host could serve replaced tarballs. SHA values are computed by the same compromised host, so they cannot detect this.
- Supply-chain transitive risk. Dependencies pulled from npmjs.com are trusted at npm's bar, not Matrix's. A malicious upstream package is not blocked by Matrix's integrity layer.
These are real gaps. They are accepted today because the registry is private (Gitea behind admin token), not public.
Target state
Three additions are planned but not yet implemented:
1. Sigstore-style signing
Each published tarball gets an attached signature. The signing key is bound to the publisher's identity (Gitea user → keyless OIDC / cosign). Consumers verify the signature before extracting.
2. Provenance attestations
Per SLSA attestations: each tarball has a manifest describing how it was built (which CI run, which commit, which dependencies) and that manifest is signed.
3. Reproducible builds
Tarball SHA-512 should be deterministic given the same source tree. This requires removing build-time-injected timestamps and absolute paths from artifacts. The npm publish safety audit (projects/matrix-3/packages/docs/content/security/npm-publish-safety.md) identifies the current artifact path leakage:
38
matrix-artifact.jsonfiles in dist/ directories contain full local file paths including username [...] This leaks: developer username, project structure, build machine OS, build timestamps. Permanently. For every version ever published.
That leakage must be fixed before public npm publishing. It's a target-state item for the artifact registry too — a reproducible build is required before attestations are useful.
Verifying integrity by hand
For one-off verification of a Gitea-served tarball, compute SHA-512 yourself and compare to the registry-reported integrity:
bash
# Fetch the tarball
curl -fsS https://registry.hivecast.ai/api/packages/hivecast-admin/npm/@open-matrix/chat/-/chat-0.2.3.tgz \
-o chat-0.2.3.tgz
# Compute the local hash
shasum -a 512 chat-0.2.3.tgz | cut -d' ' -f1 | xxd -r -p | base64
# Compare against the metadata-reported integrity
curl -fsS https://registry.hivecast.ai/api/packages/hivecast-admin/npm/@open-matrix/chat \
| jq -r '.versions["0.2.3"].dist.integrity'A match proves the bytes are the bytes the registry has. It does not prove those bytes are what the original publisher meant to ship — that requires signing, which is target state.
See also
Source: Today's integrity story is the npm protocol. Target state lives in
WORKSTREAMS/product-launch/and the npm-publish-safety audit.