Skip to content

ci(sdk): make latest track the newest version, and add move-tag mode - #37

Merged
bytesbrains merged 1 commit into
mainfrom
ci/sdk-latest-tracks-newest
Jul 28, 2026
Merged

ci(sdk): make latest track the newest version, and add move-tag mode#37
bytesbrains merged 1 commit into
mainfrom
ci/sdk-latest-tracks-newest

Conversation

@nandal

@nandal nandal commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Problem

latest points at 0.1.0-dev.2 — a tarball with no deployment carrier at all — so a bare npm install @bytesbrains/maktub-sdk still hands people pre-#32 code even though 0.1.0-dev.4 is published.

The workflow caused this. Its guard refused to publish a pre-release to latest, on the usual npm convention that latest means "newest stable". Every version in this project is a 0.1.0-dev.x, so that guard permanently pinned latest to an old build.

Change summary

Policy: latest tracks the newest published version, always.

  • dist_tag now defaults to latest, and the pre-release guard is removed. The step remains as an informational note explaining why, so nobody restores the guard as a "fix". This is a deliberate departure from npm convention — being technically correct about the tag was worse for consumers than the thing the convention protects.
  • New mode: move-tag repoints a dist-tag at a version already on the registry, building and publishing nothing. A published version can't be re-published, so npm publish can never correct a tag after the fact — and 0.1.0-dev.4 is already out, making this the only CI route to fix latest now.
  • move-tag validates the inverse of the publish guard: the target version must already exist. Tagging a nonexistent version would break npm install outright.

Tests

YAML validated; step conditions confirmed to route correctly — the five publish-only steps and the three move-tag steps are mutually exclusive on inputs.mode, and move-tag skips npm ci since it builds nothing.

move-tag is unproven and I want to be explicit about it. npm's Trusted Publishing is built around npm publish; whether the OIDC exchange also authorises npm dist-tag isn't settled by the docs. Two outcomes:

  • It works → latest is fixable from CI from now on.
  • It fails with ENEEDAUTH → the exchange doesn't cover it, moving a tag stays a local npm dist-tag add by a maintainer with 2FA, and this mode should be deleted rather than left as a trap.

The npmjs entry may also need a dist-tag action ticked under "Allowed actions". Both caveats are recorded in the workflow itself, not just here.

Given the bring-up history, I'd rather ship this labelled honestly than assert it works.

Risk

Low. Publish-mode behaviour is unchanged apart from the default tag and the dropped guard. move-tag can only ever point a tag at a version that already exists, which is reversible by pointing it somewhere else. Nothing is built or published in that mode.

The real consequence to be aware of: after the tag moves, npm install starts serving a pre-release. That is the intent.

Backwards-compat

Existing pins are unaffected — versions are immutable and @dev still resolves to 0.1.0-dev.4. Anyone on a floating install picks up dev.4 instead of dev.2, which is the fix.

Privacy copy

No user-facing privacy copy.

🤖 Generated with Claude Code

Policy decision: `latest` should always point at the newest published version so
a bare `npm install` gets current code.

Publishes now default to dist_tag=latest, and the guard that REFUSED to publish
a pre-release to `latest` is removed. That guard encoded the usual npm convention
that `latest` means "newest stable". Every version here is a 0.1.0-dev.x, so the
convention left `npm install` resolving to 0.1.0-dev.2 — a tarball carrying no
deployment carrier at all. Being correct about the tag was worse for consumers
than the thing the convention protects. The step stays as an informational note
so nobody restores the guard as a "fix".

Adds `mode: move-tag`, which repoints a dist-tag at a version already on the
registry and builds/publishes nothing. Needed because a published version cannot
be re-published, so `npm publish` can never correct a tag afterwards — and
0.1.0-dev.4 is already out, so this is the only CI route to fix `latest` now.
It validates the inverse of the publish guard: the target version MUST exist,
since tagging a nonexistent version would break `npm install` outright.

move-tag is UNPROVEN. npm's Trusted Publishing is built around `npm publish`, and
whether the OIDC exchange also authorises `npm dist-tag` is not settled by the
docs. If it fails with ENEEDAUTH the exchange does not cover it, moving a tag
stays a local `npm dist-tag add` by a maintainer with 2FA, and this mode should
be deleted rather than left as a trap. The npmjs entry may also need a dist-tag
action ticked under "Allowed actions". Flagged in the workflow itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@wrokin

wrokin Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

🤖 wrokin code review

No high-signal issues. The diff is a well-structured addition of a move-tag mode with appropriate guards and dry-run handling. The documented uncertainty about npm dist-tag and OIDC is not a code bug, and the policy change (defaulting to latest, removing the pre-release guard) is intentional and explained. No correctness, security, or SOLID/DRY violations introduced.

Model: deepseek/deepseek-v4-pro · your key, your model (BYOK)

@bytesbrains
bytesbrains merged commit 1b35e2b into main Jul 28, 2026
10 checks passed
@bytesbrains
bytesbrains deleted the ci/sdk-latest-tracks-newest branch July 28, 2026 21:13
@wrokin

wrokin Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

🤖 wrokin security audit

.github/workflows/sdk-publish.yml:204 — Command injection via unsanitized inputs.move_tag_version

The new move-tag mode passes the user-controlled workflow input move_tag_version directly into a shell script as the environment variable TARGET (line 204) and then uses it inside a quoted command:

if ! npm view "${name}@${TARGET}" version >/dev/null 2>&1; then

Because the variable is embedded inside a double‑quoted string but not sanitized, a specially crafted input (e.g., "; rm -rf /; echo ") will break out of the quotes and execute arbitrary shell commands. The same unsanitized value is later used in the Move dist-tag step via the output steps.retag.outputs.version.

Remediation: Validate the version string against a strict semantic versioning regex (e.g., ^[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9.]+)?(\+[A-Za-z0-9.]+)?$) before any shell expansion. Fail the step immediately if the input does not match. Apply this validation before the npm view command and, ideally, re-export the sanitized value.

Model: deepseek/deepseek-v4-pro · your key, your model (BYOK)

@wrokin

wrokin Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

🛡️ wrokin security hunter

No vulnerabilities were proven in this pull request — the hunter found nothing it could exploit and prove by execution.

Advisory only — this check never blocks your PR.

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.

2 participants