Skip to content

OIDC trusted publishing + signed Release pipeline (release.yml) - #2

Merged
takashi-matsuyama merged 4 commits into
mainfrom
feat/release-yml-oidc
May 27, 2026
Merged

takashi-matsuyama merged 4 commits into
mainfrom
feat/release-yml-oidc

Conversation

@takashi-matsuyama

Copy link
Copy Markdown
Member

Summary

Add a tag-driven release pipeline for @basou/{core,cli,sdk} that publishes to npm via OIDC trusted publishing (no NPM_TOKEN secret), attaches SLSA provenance v1 attestations, and ships a signed GitHub Release with cosign sign-blob bundles.

  • publish-npm matrix runs over @basou/core, @basou/cli, @basou/sdk. Each package is packed with pnpm pack (so workspace:* refs are rewritten to real semver) and pushed through the OIDC handshake by npm CLI v11.5+ (Node 24 via .nvmrc).
  • github-release packs the same tarballs, signs each one keyless with cosign sign-blob (Sigstore Fulcio + Rekor), and attaches the tarball + bundle to a release with auto-generated notes.
  • Every third-party action is SHA-pinned; Dependabot is wired up to keep the pins fresh.
  • workflow_dispatch only ever runs the dry-run branch — the publish step is gated on $GITHUB_EVENT_NAME = "push", and github-release is additionally gated on inputs.dry_run != true. A manual dispatch cannot produce a real publish.
  • The unscoped basou package is deliberately not in the matrix — the npm support ticket for that name is still open. The workflow grows a fourth matrix entry without other changes once the name resolves.

The consumer-facing engines.node minimum stays at >=20.10.0 per AGENTS.md Tier 1 — the Node 24 requirement is scoped to the CI runner only.

Test plan

  • quality.yml CI is green on this branch
  • After merge: trigger release.yml via workflow_dispatch (dry_run=true) and confirm the publish-npm matrix logs the OIDC handshake on all three packages and github-release is skipped
  • Configure trusted publishers for @basou/core, @basou/cli, @basou/sdk on npmjs.com (Organization basou-dev, Repository basou, Workflow release.yml) — must be done before the first real tag push
  • Cut v0.4.0 after Step 2 + Step 3 are both green

takashi-matsuyama and others added 4 commits May 27, 2026 15:09
npm CLI v10 (bundled with Node 20) does not implement OIDC trusted
publishing for `npm publish --provenance`. v11.5+ (bundled with Node
22+) is required, and Node 24 is recommended. Add `.nvmrc` so the
release workflow can pick Node 24 via `actions/setup-node` with
`node-version-file: '.nvmrc'`.

The runtime requirement is scoped to the CI runner only. The library
consumer minimum (root `engines.node`, `>=20.10.0` per AGENTS.md
Tier 1) is intentionally not raised - OIDC trusted publishing affects
publish-time tooling, not the published artifacts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add the metadata that npm's provenance attestation pipeline validates
strictly, and the publish-time flags that the OIDC trusted publisher
flow expects:

- `publishConfig.provenance: true` so each package opts in to SLSA
  provenance v1 attestation by default
- `homepage` + `bugs.url` for consistent npm registry display
- `prepublishOnly: "pnpm -w run build"` so the workspace builds before
  any local `pnpm pack` / `npm publish` invocation

`repository.url` + `repository.directory` were already correct on every
package, so the provenance validator's URL match is covered. The
consumer-facing `engines.node` minimum stays at `>=20.10.0` per
AGENTS.md Tier 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Keep SHA-pinned actions fresh and surface upstream npm dependency
updates on a weekly cadence. Initial SHA pinning is still manual (the
github-actions ecosystem does not perform tag-to-SHA conversion on
its own); Dependabot only updates pins that already exist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A tag push of `vX.Y.Z` runs three jobs:

1. verify - pnpm install + build + typecheck + lint + test, the same
   gate as quality.yml but anchored to the tagged tree.
2. publish-npm - fan out across `@basou/{core,cli,sdk}` and publish
   each through npm's OIDC trusted-publisher path, with SLSA
   provenance v1 attestation. No long-lived `NPM_TOKEN` secret is
   used; the runner obtains an OIDC token at job time.
3. github-release - pack each package with `pnpm pack`, sign every
   tarball with cosign sign-blob (keyless, Sigstore Fulcio + Rekor),
   and attach both the tarball and the cosign bundle to a GitHub
   Release with auto-generated notes.

`workflow_dispatch` is wired up for dry-runs only: the publish path
is gated on `$GITHUB_EVENT_NAME = "push"`, and github-release is
additionally gated on `inputs.dry_run != true`, so a manual dispatch
can never produce a real publish or release.

All third-party actions are SHA-pinned. Inline comments in the
workflow call out the precise reason for each defensive step
(notably: omitting `registry-url` on `actions/setup-node` and
rewriting ~/.npmrc to a single registry line so the OIDC handshake
takes over instead of falling back to an empty bearer token).

The `basou` unscoped package is not yet listed in the matrix; the
npm support ticket for that name is still pending. Once the name
resolves the matrix can grow a fourth entry without any other
changes to this workflow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@takashi-matsuyama
takashi-matsuyama merged commit c6cbee7 into main May 27, 2026
7 checks passed
@takashi-matsuyama takashi-matsuyama mentioned this pull request May 27, 2026
5 tasks
takashi-matsuyama added a commit that referenced this pull request May 27, 2026
Bump @basou/core, @basou/cli, @basou/sdk, and the (still unpublished)
unscoped basou to 0.4.0. This is the first release that goes through
the OIDC trusted-publisher pipeline introduced in PR #2:

  - npm publishes are signed with SLSA provenance v1 attestation
  - tarballs are republished as signed GitHub Release assets with
    cosign sign-blob bundles
  - no `NPM_TOKEN` secret is involved

No code changes ride along with this bump - 0.3.1 -> 0.4.0 marks the
supply-chain transition, not new functionality.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
takashi-matsuyama added a commit that referenced this pull request Jun 23, 2026
Add a `kind: "track"` to the decision_recorded event. A "track" is a
strategic, UNFINISHED direction (the next essential thing to build, and
why) that `basou orient` / `basou handoff` resurface in a dedicated
open-tracks section EVERY session until it is explicitly closed with
`basou decision void` (or superseded). A plain decision (no kind) is
unchanged.

Addresses Takuhon dogfeedback #2 (intent leak): a direction agreed in
conversation was captured-then-buried. The single "latest decision"
pointer was displaced by any newer decision, so the strategic track sank
into the flat decision list and never carried to the next session. Tracks
are a distinct, persistent forward-looking surface, separate from the
terminal note and from in-flight tasks. This is the read-side keystone;
write-side capture enforcement (a Stop hook) is a separate slice.

- schema: additive-optional `kind` enum on decision_recorded (mirrors
  note_added.kind; no schema_version bump; pre-existing events round-trip
  byte-identically). Regenerated JSON Schema artifacts.
- capture/record: `--track` flag and a `"kind":"track"` JSON field; an
  explicit "decision" is normalized to omission.
- orient + handoff: a new open-tracks section listing all non-voided
  tracks newest-first with their rationale; close hint; the no-direction
  fallback is suppressed when a track is open; a discoverability nudge
  points at --track when decisions exist but none give a forward direction
  (suppressed for a pristine workspace).
- decisions.md marks tracks [TRACK] + a kind line; report tags [track].
- close reuses the existing decision void / supersede (no new verb).
- +25 tests across schema, capture, orient, handoff, decisions, report,
  including the regression that an open track survives a later plain
  decision. Adversarial review (Codex + 2 perspectives) applied.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
takashi-matsuyama added a commit that referenced this pull request Jun 23, 2026
Add kind:track to decision_recorded - a strategic unfinished direction that orient/handoff resurface until closed via decision void. Read-side keystone for Takuhon dogfeedback #2 (intent leak). Additive-optional schema, +25 tests, adversarial review applied.
@takashi-matsuyama
takashi-matsuyama deleted the feat/release-yml-oidc branch October 8, 2026 05:22
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