SuperAPI AI Directory

lov-npm-publisher

Security & auditing

View repository

Updated 10-16 00:01

About this skill

lov-npm-publisher

Migrate npm packages from "logging in every time or maintaining a long-lived token" to an auditable automated publishing chain. Two peer authentication methods are supported:

  • oidc — GitHub Actions trusted publishing, CI without long-lived tokens (recommended for continuous releases of GitHub repositories);
  • bypass — local granular NPM_TOKEN, directly npm publish(suitable for quick local publishing and packages without CI).

Output must distinguish first-time bootstrap, authentication configuration, publish execution, and registry read-back; workflow generation must not be equated with having actually published.

Triggers

Activate when

  • The user says "automatically publish an npm package", "publish a new npm package but don't make me log in every time", "switch npm releases to GitHub Actions".
  • The user says "use NPM_TOKEN to publish this package locally", "publish this npm package locally without login".
  • User says “publish npm without login”, “automate npm releases”, or “set up tokenless npm publishing”.
  • The user needs to determine in bulk whether packages are being published for the first time, choose between OIDC and NPM_TOKEN, or verify whether a release is actually live.

Do not activate when

  • What is being published is an Agent Skill rather than an npm package; use lov-skill-publisher。
  • for generic GitHub Release, Tauri signing, or multi-platform CI/CD only; use lov-release-via-cicd。
  • The user only asks about npm authentication principles without requesting configuration or publishing; explain directly without modifying the repository.

User Profile (cross-session)

Read skill.yaml on every invocation. Resolve the current request, project context, Skill records, shared preferences, and the shared user/brand Profile in that order. Keep repository names, workflow choices, and credentials out of the portable source unless the user explicitly asks to persist a non-secret default.

Persist only direct durable statements through scripts/profile_store.py and report the canonical Profile path. Never persist npm tokens, OTP values, cookies, OIDC assertions, or secret-like environment values. See references/user-profile.md for the full contract.

Skill Group Composition

Read references/skill-composition.md before invoking an adjacent Skill. Sibling Skills are optional artifact-level handoffs, not hidden runtime dependencies.

Workflow (MANDATORY)

Follow these steps in order.

Step 0: Resolve runtime and current npm rules

  1. Resolve this source as SKILL_DIR and the target package directory from the request or current working directory.
  2. Read references/npm-publishing-contract.md and recheck the linked npm documentation when authentication behavior, supported runners, or deprecation dates could have changed.
  3. Read references/skill-composition.md before choosing an optional handoff.
  4. Verify package.json, git, npm, and scripts/publish.py exist. Do not request or print credentials during this read-only phase.

Step 1: Audit without changing external state

Run the planner first:

python3 "$SKILL_DIR/scripts/publish.py" PACKAGE_DIR --dry-run --json

The audit must establish:

  • package name, version, visibility, private flag, registry, and repository URL;
  • GitHub owner/repository and the exact workflow filename;
  • whether the package exists on the npm registry and whether this exact version already exists;
  • whether an existing workflow contains id-token: write, npm publish, and no long-lived publish secret;
  • whether the state is bootstrap_required, package_exists, or registry_unknown.

Do not turn a timeout, authorization error, or registry outage into “package does not exist”. Stop before publication when registry state is unknown.

Step 2: Select the authentication path

The planner emits auth.mode as oidc or bypass. With --auth-mode auto (the default), it resolves to oidc when a GitHub repository resolves and bypass otherwise; pass --auth-mode oidc|bypass to override inference. Both modes are first-class and equal; prefer oidc for GitHub-repository continuous releases and bypass for local, CI-less, or new-package publication.

oidc — GitHub trusted publishing

Trusted publishing cannot be registered for a name that does not yet exist. For bootstrap_required, explain that one interactive identity proof is unavoidable, then perform it only when the request authorizes publication:

npm login
npm publish --access public

Re-read the exact package and version from the npm registry. A successful command without registry visibility is not completion.

For package_exists, configure or verify the exact repository/workflow binding. With a current npm CLI, the plan emits a command shaped like:

npm trust github PACKAGE --repo OWNER/REPO --file publish.yml --allow-publish

This management action requires interactive identity proof. If it was already configured, verify the existing binding rather than replacing it blindly.

bypass — local granular NPM_TOKEN

A granular (Bypass-2FA) npm_ token publishes directly, including new packages. Detect the token without reading its value; auth.token reports whether NPM_TOKEN or a ~/.npmrc _authToken is present. When it is missing, warn and request a granular token before publishing. auth.publish_command carries the exact command; never echo the token value.

Step 3: Generate the workflow or the publish command

After resolving blocking audit errors, materialize the mode-specific artifact:

python3 "$SKILL_DIR/scripts/publish.py" PACKAGE_DIR --write --json

For oidc, the writer emits the tokenless workflow. It is conservative:

  • it preserves an equivalent OIDC workflow;
  • it refuses to replace an unrelated or token-based workflow unless --force is explicitly justified;
  • it never writes NPM_TOKEN, an npm access token, or an OTP;
  • it grants only contents: read and id-token: write;
  • it uses a hosted runner and lockfile-aware install command;
  • it runs build and test scripts when present before npm publish.

Review the diff. The package's repository.url must match the GitHub repository used by the trusted publisher; fix the package metadata before publishing when it does not match.

For bypass, the writer sets write_state to not-applicable — no workflow is generated. Use the auth.publish_command from the plan as the release command.

Step 4: Run the release gate

Before triggering the workflow:

  1. Confirm the requested version is not already present. npm versions are immutable; never retry by overwriting the same version.
  2. Run the package's existing test and build gates.
  3. Inspect the payload with npm pack --dry-run --json; reject secrets, unintended source files, private paths, or missing build output.
  4. Confirm the release commit is clean and contains the workflow and package version intended for the tag.
  5. Do not expose credentials in command output or logs.

Step 5: Trigger and verify the release

Only when the user asked to publish, act by mode:

  • oidc — create/push the intended version tag or run the configured manual workflow, then follow the GitHub Actions run to a terminal state.
  • bypass — run auth.publish_command from the plan against the granular NPM_TOKEN.

Then verify independently:

npm view PACKAGE@VERSION version --registry https://registry.npmjs.org

For public repositories, also check the npm provenance record when supported. Report the exact version, workflow run (or local publish), registry result, and provenance state. queued, in_progress, a generated YAML file, or an accepted npm publish request is not equivalent to a live package version. A root endpoint 404 right after publish can be CDN lag; re-read the specific version endpoint before concluding failure.

Step 6: Report the state precisely

Use these states:

  • audited — repository and registry state classified;
  • bootstrap-required — package name does not yet exist;
  • workflow-written — tokenless OIDC workflow exists locally;
  • trusted-publisher-configured — npm binding was verified;
  • publish-command-ready — bypass mode resolved a publish command and token;
  • publish-triggered — CI accepted the release request;
  • published — publish (CI or local) finished successfully;
  • verified-live — exact package and version were read back from npm;
  • blocked — name the missing identity proof, registry evidence, or failed gate.

Validation

Exercise both registry branches and both auth modes without external writes:

python3 scripts/publish.py CASE_DIR --registry-state missing --dry-run --json
python3 scripts/publish.py CASE_DIR --registry-state exists --dry-run --json
python3 scripts/publish.py CASE_DIR --auth-mode oidc --dry-run --json
python3 scripts/publish.py CASE_DIR --auth-mode bypass --dry-run --json
python3 scripts/validate_skill.py .

An activation check should route "help me automatically publish this new npm package, no login from now on" and "use NPM_TOKEN to publish this package locally" here. "List this Agent Skill on LovStudio" must stay with lov-skill-publisher.

Dependencies

  • Python 3.9+ standard library for the planner/writer.
  • Git and a valid GitHub repository for automatic repository inference.
  • Node/npm versions currently supported by npm Trusted Publishing.
  • PyYAML only for local Skill source validation.
  • npm/GitHub authentication is required only for the authorized external setup and publish steps; no credential is stored by this Skill.

Generic feedback loop

When the user raises revision feedback during a Skill-driven task, before continuing with the current artifact you must perform:

  1. First determine whether the feedback is task-specific(this time only) or reusable(reusable across tasks).
  2. task-specific Only modify the current task; do not change the Skill.
  3. reusable First determine the scope: for domain rules, first update the corresponding canonical Skill; for rules applicable to all Skills, first update the shared specification.
  4. After completing rule updates, versioning, lint, and distribution verification, then apply the changes to the current task.
  5. reusable The change invalidates previous "confirm", "continue", and "go ahead" responses; after completing the current artifact modification and read-back, you must stop and wait for the user's next instruction, without automatically proceeding to publishing, committing, or other external writes.