Skip to content

ci: Bun cooldown for installs, no gateway in publish, OIDC - #597

Merged
guyofeck merged 4 commits into
mainfrom
ci/embargo-interim-npm-min-release-age
Aug 11, 2026
Merged

ci: Bun cooldown for installs, no gateway in publish, OIDC#597
guyofeck merged 4 commits into
mainfrom
ci/embargo-interim-npm-min-release-age

Conversation

@guyofeck

@guyofeck guyofeck commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Implements the interim policy @dimar set out in this thread, so Actions can be re-enabled for base44/cli.

Requirement How it's met
1. Lock-files, build never overrides one bun install --frozen-lockfile, already in all 9 install steps — unchanged
2. Package manager with a minimal-age directive minimumReleaseAge = 1209600 (14 days) in new bunfig.toml
3. Embargo in non-publish tasks only Gateway removed from both publish workflows; /etc/hosts unpin hack deleted

No package manager migration needed — Bun supports this natively: bun install --minimum-release-age=. @dimar, your list said "pnpm/yarn/(latest)npm"; Bun belongs on it.

Dropping the gateway from publish is safe because those jobs resolve nothing — --frozen-lockfile installs bun.lock verbatim. check_wix_proxy_steps.py keeps the proxy mandatory everywhere else: the two publish workflows are exempted by exact filename in a PUBLISH_WORKFLOWS list, and every exemption is printed on success, so the list cannot quietly grow.

Also: publishes authenticate via trusted publishing (OIDC), so NPM_TOKEN is gone; and bunx json-bump becomes npm version / npm pkg set, since bunx fetched an undeclared package at run time and doesn't enforce the cooldown (#30748).

Why the gateway can't just carry the publish

npm publish sends PUT /<package>, which matches neither the embargo's ^~ /-/ passthrough block nor ~ \.tgz$, so it lands in location / (proxy_metadata, a read path with caching). The gateway also sets no client_max_body_size, so nginx's 1 MB default rejects a packument carrying the base64 tarball. Worth fixing on the embargo side — once it is, these two workflows should go back to being gatewayed like everything else.

Bun's own gaps, for the record: bunx ignores --minimum-release-age (#30748), bun update --latest skips the cooldown for transitive deps (#25305), and there's no bypass when an update fixes a known vulnerability (#26065) — minimumReleaseAgeExcludes is the escape hatch there.

Status

  • check_wix_proxy_steps.py: 12/12 non-publish jobs across 11 workflows, 2 publish workflows exempt; 11/11 unit tests
  • Nothing here has run — Actions is disabled org-wide
  • Trusted publishers on npmjs.com — needs npm org admin, one entry per workflow filename

Questions for @dimar

  1. Does Bun's minimumReleaseAge satisfy requirement 2? Set to 14 days here — say if you want a different window.
  2. Nothing verifies a committed lockfile change respected the cooldown (CI never resolves). Want a check for that, and for --frozen-lockfile itself?

🤖 Generated with Claude Code

Implements the interim policy Dima Ryskin set out for OSS repos, so GitHub
Actions can be re-enabled for base44/cli at the org level:

  1. enforce lock-files on all node builds, so the build never overrides one
  2. enforce a package manager that supports a minimal-age directive
  3. use embargo in non-publish workflow tasks

Bun satisfies point 2 natively, so no package manager migration is needed:

    bun install --minimum-release-age=<val>
        Only install packages published at least N seconds ago (security feature)

bunfig.toml sets `minimumReleaseAge = 604800` (7 days; Bun takes SECONDS, unlike
npm's min-release-age, which takes days). Point 1 was already satisfied by
`bun install --frozen-lockfile`, which is what every workflow runs.

That choice matters operationally, not just aesthetically: Wix-managed machines
block registry.npmjs.org at the network-extension layer, so no developer here can
regenerate an npm lockfile without routing through the embargo gateway or an
internal mirror. A Bun-native cooldown keeps bun.lock as the single source of
truth and needs no lockfile regeneration at all.

Point 3 — the publish workflows no longer run the embargo gateway:

- Drops the `sudo sed -i /etc/hosts` unpin hack from both. There is no pin to
  strip now, so the window where the gateway was bypassed is gone entirely.
- Safe because those jobs resolve nothing: `--frozen-lockfile` installs bun.lock
  verbatim, so dropping the gateway does not widen what they can pull.
- check_wix_proxy_steps.py enforces the split bidirectionally: non-publish jobs
  must run the proxy, publish jobs must not. Exemptions are keyed on exact
  filename and printed on success, so the list cannot quietly grow.

Also closes the remaining unprotected registry fetches in the publish path:

- Authenticate via npm trusted publishing (OIDC). Drops NODE_AUTH_TOKEN /
  secrets.NPM_TOKEN from preview-publish; manual-publish never had a credential
  wired at all, so it could not have published regardless.
- Replace `bunx json-bump` with `npm version` and `npm pkg set`. json-bump is
  declared in no manifest, so bunx fetched it at run time — outside bun.lock and
  outside the cooldown, since bunx accepts --minimum-release-age without
  enforcing it (oven-sh/bun#30748).
- Remove `npm install -g npm@latest` from both publish workflows.
- Least-privilege per-job permissions replace the workflow-level blocks; drops
  manual-publish's unused packages: write and pull-requests: read.

Known Bun gaps, documented in bunfig.toml and docs/AGENTS.md rather than left to
be discovered: bunx does not enforce the flag (#30748), `bun update --latest`
skips transitive deps (#25305), and there is no bypass for vulnerability fixes
(#26065) short of minimumReleaseAgeExcludes.

Verified: check_wix_proxy_steps.py reports 12 of 12 non-publish jobs across 11
workflows with both publish jobs confirmed to abstain; 12 of 12 unit tests pass
(4 new, covering both directions of the rule).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@guyofeck
guyofeck force-pushed the ci/embargo-interim-npm-min-release-age branch from d582f83 to 42cb58b Compare August 11, 2026 12:00
@guyofeck guyofeck changed the title ci: npm + min-release-age for installs, no gateway in publish ci: Bun cooldown for installs, no gateway in publish, OIDC Aug 11, 2026
@guyofeck
guyofeck marked this pull request as ready for review August 11, 2026 12:06
@guyofeck
guyofeck requested a review from Paveltarno August 11, 2026 12:18
Comment on lines +146 to +157
def publish_job_problem(job: dict) -> str | None:
"""Describe why this publish job wrongly runs the proxy, or None if it abstains."""
if "uses" in job:
return None
steps = job.get("steps") or []
if any(_uses(step) == PROXY_ACTION for step in steps):
return (
"runs the Wix gateway proxy, but publish workflows must not: the gateway "
"cannot carry `npm publish`, so these workflows rely on the committed "
"lockfile plus min-release-age in .npmrc instead"
)
return None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure this is really needed, maybe its enough to simply not check the publishing actions set explicitly in the list?

Comment thread bunfig.toml Outdated
Comment on lines +2 to +23
# Supply-chain cooldown — Wix secplatform interim policy for OSS repos.
#
# Bun resolves only package versions published at least this long ago, so a
# compromised release cannot enter bun.lock inside the window. This is what lets
# the publish workflows run without the embargo gateway, which cannot carry
# `npm publish` today (see .github/workflows/manual-publish.yml).
#
# Units are SECONDS, unlike npm's `min-release-age`, which takes days.
# 604800 = 7 days.
#
# Applies at resolution time: `bun install` without a lockfile entry, `bun add`,
# `bun update`. `bun install --frozen-lockfile`, which is all CI runs, installs
# bun.lock verbatim and never resolves, so it is unaffected by design.
#
# Known gaps, accepted knowingly rather than discovered later:
# - `bunx` accepts --minimum-release-age but does not enforce it
# (oven-sh/bun#30748). Do not fetch tooling with bunx in a release path;
# the publish workflows use `npm version` / `npm pkg set` instead.
# - `bun update --latest` skips the cooldown for transitive deps
# (oven-sh/bun#25305).
# - No bypass when an update fixes a known vulnerability
# (oven-sh/bun#26065) — use minimumReleaseAgeExcludes for that case.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's delete this slop

Comment on lines +25 to +39
# Workflows that must NOT route npm through the embargo gateway.
#
# secplatform's interim policy for OSS repos (Dima Ryskin): use embargo for
# non-publish tasks, and protect publish tasks with an enforced lockfile
# (`bun install --frozen-lockfile`) plus a package manager that honors a
# minimal-age directive (`minimumReleaseAge` in bunfig.toml) instead. Those jobs
# resolve nothing, so dropping the gateway does not widen what they can pull.
# The gateway cannot carry a publish today — `npm publish` sends
# `PUT /<package>`, which misses its `^~ /-/` passthrough block, and it sets no
# client_max_body_size so nginx's 1 MB default rejects a packument carrying the
# base64 tarball.
#
# Keyed on exact filename, and every exemption is printed on success, so this
# cannot quietly grow. Revisit once the embargo publish bug is fixed: these
# workflows should go back to being gatewayed like everything else.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets remove slop, enough to write that adding files here should not be taken easily and can pose a security concern

claude added 2 commits August 11, 2026 13:58
- check_wix_proxy_steps.py: skip workflows listed in PUBLISH_WORKFLOWS
  instead of also asserting they don't run the proxy, per review. Cut the
  rationale block down to the security note about adding entries.
- bunfig.toml, publish workflows, AGENTS.md: cut the long comment blocks
  to the facts that change what a reader does.
Paveltarno
Paveltarno previously approved these changes Aug 11, 2026

@Paveltarno Paveltarno left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

לגטמ

@guyofeck
guyofeck merged commit 596104f into main Aug 11, 2026
@guyofeck
guyofeck deleted the ci/embargo-interim-npm-min-release-age branch August 11, 2026 14:13
guyofeck added a commit to base44/javascript-sdk that referenced this pull request Aug 12, 2026
)

* ci: enforce wix gateway proxy in all workflows

Routes every npm-registry fetch in this repo's CI through the Wix npm
embargo gateway, ported from base44-dev/vite-plugin#105. All jobs run on
ubuntu-latest; the action is byte-identical to the vite-plugin/apper copy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: npm cooldown for installs, no gateway in publish, OIDC

Ports base44/cli#597 (596104f) to this repo. The Wix gateway cannot carry
`npm publish` — it rejects `PUT /<package>` — so the two publish workflows
were the one place the embargo rollout had to cheat, deleting the /etc/hosts
pin mid-job right before publishing.

Per secplatform's interim policy for OSS repos, publish workflows are exempt
from the gateway and protected by the lockfile plus a release cooldown instead:

- .npmrc gets `min-release-age=14`, matching the gateway's 14-day window, so a
  freshly published version cannot enter package-lock.json.
- Both publish workflows drop the gateway action and the `sed -i /etc/hosts`
  unpin hack. check_wix_proxy_steps.py records the exemption explicitly in
  PUBLISH_WORKFLOWS, so every other workflow — present and future — still
  fails CI without the proxy.
- preview-publish.yml installs with `npm ci` instead of `npm install`: with no
  gateway in front of the job, a resolving install was the only step that could
  still pull a fresh release. Both publish jobs now resolve nothing.
- Both bump to Node 24 and drop `npm install -g npm@11`, which fetched a
  floating npm release outside the cooldown. Node 24's bundled npm (>= 11.17)
  already covers trusted publishing (>= 11.5.1) and min-release-age (>= 11.10.0).
- Publish steps keep authenticating via npm trusted publishing (OIDC), and
  `permissions` moves to the job with a note on why each scope is there.
  `packages: write` goes away — nothing here publishes to GHCR.

Verified: `check_wix_proxy_steps.py` passes at 8 of 8 jobs across 8
non-exempt workflows, and its 11 tests pass, including three new ones
covering the exemption.

---------

Co-authored-by: dorr <dorr@base44.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

3 participants