Skip to content

Sign provenance again: publish via pnpm --provenance#163

Merged
MrRefactoring merged 12 commits into
masterfrom
develop
Jul 21, 2026
Merged

Sign provenance again: publish via pnpm --provenance#163
MrRefactoring merged 12 commits into
masterfrom
develop

Conversation

@MrRefactoring

Copy link
Copy Markdown
Owner

Fixes the provenance regression by returning to the only publish command that actually signs the attestation. No release — provenance comes back on the next version.

The problem

3.0.2 and 3.0.3 shipped without an SLSA provenance attestation (3.0.1 had one). Both went out via changeset publish, which delegates to pnpm's native publish; with an id-token present, pnpm takes the OIDC trusted-publishing path and produces no attestation, ignoring .npmrc provenance=true and NPM_CONFIG_PROVENANCE alike. Only the explicit pnpm publish --provenance flag makes it sign — which is exactly what 3.0.1 used.

The fix

  • release:publishscripts/publish.ts: it checks the registry and no-ops if the version is already published (keeping a no-release master push clean, the one thing changeset publish did for us), otherwise runs pnpm publish --no-git-checks --provenance.
  • Restores the custom "tag and release" step — pnpm publish prints no New tag: line for the action to act on. It reads the version from the committed HEAD, so it tags only the real version-PR merge, on the right commit (as the auto-tag did for v3.0.2/v3.0.3).
  • Drops the ineffective .npmrc provenance=true.

No release here

This carries no changeset, so merging it publishes nothing: the release run will find 3.0.3 already on npm and no-op — which also confirms the registry guard works. Provenance is restored on the next actual version.

Closes the uniform half of what the schema audit found: 161 -> 83
undocumented fields, 93 -> 50 endpoints, with the suite still passing.

The `_links` group is gone entirely, and it was the bulk — 61 fields,
57% of all occurrences. v1 declared its links object with no properties
at all while using it for every entity, so `_links.webui` existed at
runtime and nowhere in the types. Now it is typed.

`version.ncsStepVersion` and `version.contributorIds` follow, along with
the `_expandable` keys Confluence has grown since the spec was written.

Types are what the API actually returned. `ncsStepVersion` is nullable
because responses came back null; `contributorIds` keeps an open element
type because every array observed was empty, and a guessed element type
would read as breakage rather than as drift.

79 fields remain, with no shape in common — `ari`, `operations`, the
`container` group, user fields like `locale`. Each needs deciding which
schema owns it, so they are a separate pass.
161 undocumented fields across 93 endpoints down to 7 across 5, with the
suite passing 493/493.

This is the long tail the first pass deliberately left: fields with no
shape in common, each needing a decision about which schema owns it.

`Container` turned out to be a second empty schema, like the links one
before it — declared with no properties at all while naming the parent
of every piece of content. Ten fields, including its own `_links`.

The rest are one-offs: `ari` and `base64EncodedAri`, `accountStatus` and
`locale` across the three separate user schemas that each lag
differently, `resolutionStatus` on comments, `operations` and
`properties` on the newer v2 entities.

Seven remain. Each sits either behind an inline response schema with no
name to target, or behind a collection whose item schema differs from
the single-entity one — both want a proper look rather than a guess, and
the audit will keep reporting them until they get one.
Brings develop up to 3.0.1: the version bump, the cleared changesets, and the
release workflow now publishing via changeset publish. develop matches master.
The remaining seven the schema audit reported: Version's comment/attachment, the like
collection's count, the hyphenated inline-comment property keys, the async
content-body's content, and noAccessEmails on the check-access response. Drift is now 0.
pnpm 11 publishes natively and reads provenance from .npmrc, not the
NPM_CONFIG_PROVENANCE env var the workflow set — so 3.0.2 shipped without an
attestation. Move the flag to .npmrc and drop the ineffective env var. Changeset
cuts 3.0.3 to restore provenance on the latest tag; contents are identical to 3.0.2.
changeset publish took pnpm's OIDC trusted-publishing path, which produces no
provenance attestation and ignores both .npmrc provenance=true and
NPM_CONFIG_PROVENANCE — 3.0.2 and 3.0.3 shipped unsigned. Only the explicit
--provenance flag makes pnpm sign, as 3.0.1 did.

release:publish is now scripts/publish.ts: it no-ops if the version is already on the
registry (keeping empty pushes clean) and otherwise runs pnpm publish --provenance.
Restores the custom tag step, since pnpm publish prints no New tag: line for the
action to act on.
# Conflicts:
#	.github/workflows/release.yml
@MrRefactoring
MrRefactoring merged commit eaad9e0 into master Jul 21, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant