Skip to content

Commit fbd17d9

Browse files
author
Alain Picard
committed
Adjusted based on OpenRouter extensive rework.
Their comments: Latest commit: Upgrade npm to support OIDC Trusted Publishing (OpenRouterTeam#231) npm v10.8.2 (bundled with Node 20.x) predates Trusted Publishing support. npm CLI v11.5.1+ is required for OIDC authentication with --provenance flag. Evidence: CI publish failed with ENEEDAUTH despite id-token: write and correct workflow setup. npm fell back to token auth and found none. Add explicit npm upgrade step before publish to ensure OIDC works. Previous: Migrate npm OIDC (OpenRouterTeam#230) * refactor: migrate to OIDC for npm package publishing Replace token-based authentication with OpenID Connect (OIDC) for enhanced security: - Remove NPM_TOKEN from changesets action environment - Enable automatic provenance generation (NPM_CONFIG_PROVENANCE) - Set NODE_AUTH_TOKEN to empty string to force OIDC authentication - Keep diagnostic step for troubleshooting auth issues This requires configuring npm Trusted Publisher on npmjs.com for the repository. * refactor: restructure publish workflow to support OIDC properly Split changesets/action into versioning-only step and separate publish step to avoid .npmrc token mutation that would block OIDC. This ensures npm uses Trusted Publisher authentication instead of legacy token-based auth. Key changes: - changesets/action now only runs version step (no publish input) - Added OIDC preflight step to scrub any auth tokens from .npmrc before publishing - Separated publish into dedicated step with pnpm changeset-publish - Added post-mortem diagnostics for troubleshooting publish failures The id-token: write permission remains enabled for OIDC token generation. Registry setup and package.json publish script already include provenance. * fix: harden OIDC workflow with publish gate and comprehensive preflight Address three critical risks identified during code review: 1. Gate publish step to run only when no changesets exist - Prevents wasteful runs and log noise when version PR is created - Ensures publish only runs on merge commits (when hasChangesets == 'false') - .github/workflows/publish.yaml:74 2. Harden preflight to scrub all .npmrc locations and auth forms - Iterate over all potential locations: NPM_CONFIG_USERCONFIG, ~/.npmrc, .npmrc - Remove both registry-scoped (_authToken, _auth=) and global (always-auth) forms - Prevents stray .npmrc from blocking OIDC authentication - .github/workflows/publish.yaml:45-52 3. Make whoami check robust with exit code instead of grep - Check npm whoami exit code (0 = logged in, non-zero = not logged in) - Avoids reliance on fragile message matching across npm versions - Verify registry config (including @openrouter scope) - .github/workflows/publish.yaml:62-71 4. Enhance post-mortem diagnostics - Log registry configuration for both global and @openrouter scope - Redact .npmrc contents to aid forensics without exposing secrets - Check all three potential .npmrc locations - .github/workflows/publish.yaml:92-101 With these changes, the workflow is hardened against OIDC authentication failures. * refine: use extended regex patterns for comprehensive .npmrc token scrubbing Improve sed patterns to handle edge cases in token removal: - Registry-scoped tokens: Allow optional whitespace around = sign sed -i -E '/\/\/registry\.npmjs\.org\/:(_authToken|_auth)\s*=/d' - Global tokens: Match _authToken or _auth anywhere on a line with leading whitespace sed -i -E '/^\s*(_authToken|_auth)\s*=/d' - Global always-auth: Case-insensitive with optional spacing sed -i -E '/^\s*[Aa]lways-[Aa]uth\s*=/d' This closes the gap where npm could treat whitespace-padded or variant token lines as a signal to use legacy token auth instead of OIDC. Extended regex (-E) enables more flexible matching without sacrificing readability. Addresses edge case identified during workflow review.
1 parent 61b26bb commit fbd17d9

File tree

3 files changed

+108
-24
lines changed

3 files changed

+108
-24
lines changed

.github/workflows/publish.yaml

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,100 @@
1-
name: Publish package
1+
name: Release
22
on:
3-
release:
4-
types: [published]
5-
workflow_dispatch: {}
3+
push:
4+
branches: [main]
5+
6+
concurrency:
7+
group: ${{ github.workflow }}-${{ github.ref }}
8+
9+
permissions: {}
10+
611
jobs:
7-
build:
12+
release:
13+
name: Release
814
runs-on: ubuntu-latest
15+
timeout-minutes: 30
916
permissions:
10-
contents: read
11-
packages: write
17+
contents: write
1218
id-token: write
19+
pull-requests: write
1320
steps:
14-
- uses: actions/checkout@v6
15-
- uses: actions/setup-node@v6
21+
- uses: actions/checkout@v4
22+
- uses: pnpm/action-setup@v4
23+
- uses: actions/setup-node@v4
1624
with:
1725
node-version: "24.x"
1826
registry-url: "https://registry.npmjs.org"
1927
scope: "@alpic80"
20-
- uses: pnpm/action-setup@v4
21-
- run: pnpm install --frozen-lockfile
22-
- run: pnpm typecheck
23-
- run: pnpm build
24-
- name: Publish to npm
28+
cache: pnpm
29+
- name: Install dependencies
30+
run: pnpm install --frozen-lockfile
31+
- name: Upgrade npm for OIDC support
32+
run: npm install -g npm@latest
33+
- name: Create Release Pull Request or Publish
34+
id: changesets
35+
uses: changesets/action@v1
36+
with:
37+
version: pnpm changeset-version
38+
env:
39+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40+
- name: OIDC preflight - scrub .npmrc and verify registry
2541
run: |
26-
if [ "${{ github.event.release.prerelease }}" = "true" ]; then
27-
NODE_AUTH_TOKEN="" pnpm publish --provenance --access public --no-git-checks --tag beta
42+
echo "=== OIDC Preflight ==="
43+
44+
# Remove auth tokens from all potential .npmrc locations to ensure OIDC is used
45+
for npmrc in "$NPM_CONFIG_USERCONFIG" ~/.npmrc .npmrc; do
46+
if [ -n "$npmrc" ] && [ -f "$npmrc" ]; then
47+
echo "Cleaning $npmrc of any existing auth tokens..."
48+
# Remove registry-scoped tokens (allow optional whitespace around =)
49+
sed -i -E '/\/\/registry\.npmjs\.org\/:(_authToken|_auth)\s*=/d' "$npmrc"
50+
# Remove global tokens in any form
51+
sed -i -E '/^\s*(_authToken|_auth)\s*=/d' "$npmrc"
52+
# Remove global always-auth (case-insensitive, allow spacing)
53+
sed -i -E '/^\s*[Aa]lways-[Aa]uth\s*=/d' "$npmrc"
54+
fi
55+
done
56+
# Verify npm connectivity
57+
echo "Testing npm registry connectivity..."
58+
npm ping || exit 1
59+
# Verify no token is active (should fail for OIDC to work)
60+
echo "Verifying no auth token is configured..."
61+
if npm whoami >/dev/null 2>&1; then
62+
echo "⚠ Warning: npm whoami succeeded without OIDC token"
2863
else
29-
NODE_AUTH_TOKEN="" pnpm publish --provenance --access public --no-git-checks
64+
echo "✓ Confirmed: npm whoami failed (OIDC will be used)"
3065
fi
66+
echo ""
67+
echo "Registry configuration:"
68+
npm config get registry
69+
npm config get @alpic80:registry || echo " (no @alpic80 scope override)"
70+
- name: Publish with OIDC
71+
if: steps.changesets.outputs.hasChangesets == 'false'
72+
run: pnpm changeset-publish
3173
env:
32-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
74+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
75+
- name: Post-mortem diagnostics
76+
if: failure()
77+
run: |
78+
echo "=== Post-mortem Diagnostics ==="
79+
echo "Versions:"
80+
echo " Node: $(node --version)"
81+
echo " npm: $(npm --version)"
82+
echo " pnpm: $(pnpm --version)"
83+
echo ""
84+
echo "Registry configuration:"
85+
echo " registry: $(npm config get registry)"
86+
echo " @alpic80 scope: $(npm config get @alpic80:registry || echo '(inherited from global)')"
87+
echo ""
88+
echo ".npmrc files status:"
89+
for npmrc in "$NPM_CONFIG_USERCONFIG" ~/.npmrc .npmrc; do
90+
if [ -n "$npmrc" ] && [ -f "$npmrc" ]; then
91+
echo " $npmrc:"
92+
echo " Lines: $(wc -l < "$npmrc")"
93+
echo " Auth lines: $(grep -c "_auth\|_token" "$npmrc" || echo "0")"
94+
echo " Content (redacted):"
95+
sed 's/\(_auth[^=]*=\).*/\1***REDACTED***/g; s/\(_token[^=]*=\).*/\1***REDACTED***/g' "$npmrc" | sed 's/^/ /'
96+
fi
97+
done
98+
echo ""
99+
echo "Package availability:"
100+
npm view @alpic80/ai-sdk-provider@latest version 2>&1 || echo " (could not fetch)"

.npmrc

Lines changed: 0 additions & 2 deletions
This file was deleted.

package.json

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
"name": "@alpic80/rivet-ai-sdk-provider",
33
"version": "2.0.5",
44
"license": "Apache-2.0",
5+
"pnpm": {
6+
"overrides": {
7+
"glob": ">=10.5.0 <11",
8+
"js-yaml": "^3.14.2"
9+
}
10+
},
511
"sideEffects": false,
612
"main": "./dist/index.js",
713
"module": "./dist/index.mjs",
@@ -20,23 +26,34 @@
2026
"test": "pnpm test:node && pnpm test:edge",
2127
"test:edge": "vitest --config vitest.edge.config.ts --run",
2228
"test:node": "vitest --config vitest.node.config.ts --run",
23-
"test:e2e": "vitest --config vitest.e2e.config.ts --run"
29+
"test:e2e": "vitest --config vitest.e2e.config.ts --run",
30+
"changeset": "changeset",
31+
"changeset-version": "changeset version",
32+
"changeset-publish": "pnpm build && pnpm test && changeset publish --provenance"
2433
},
2534
"exports": {
2635
"./package.json": "./package.json",
2736
".": {
2837
"types": "./dist/index.d.ts",
2938
"import": "./dist/index.mjs",
3039
"require": "./dist/index.js"
40+
},
41+
"./internal": {
42+
"types": "./dist/internal/index.d.ts",
43+
"import": "./dist/internal/index.mjs",
44+
"module": "./dist/internal/index.mjs",
45+
"require": "./dist/internal/index.js"
3146
}
3247
},
3348
"devDependencies": {
3449
"@ai-sdk/provider": "2.0.0",
3550
"@ai-sdk/provider-utils": "3.0.12",
36-
"@biomejs/biome": "2.2.6",
51+
"@biomejs/biome": "2.3.7",
52+
"@changesets/changelog-github": "0.5.1",
53+
"@changesets/cli": "2.29.7",
3754
"@edge-runtime/vm": "5.0.0",
3855
"@types/node": "24.8.1",
39-
"ai": "5.0.76",
56+
"ai": "5.0.104",
4057
"dotenv": "17.2.3",
4158
"tsup": "8.5.0",
4259
"typescript": "5.9.3",
@@ -56,7 +73,8 @@
5673
},
5774
"homepage": "https://github.com/castortech/rivet-ai-sdk-provider",
5875
"repository": {
59-
"url": "https://github.com/castortech/rivet-ai-sdk-provider"
76+
"type": "git",
77+
"url": "git+https://github.com/castortech/rivet-ai-sdk-provider.git"
6078
},
6179
"bugs": {
6280
"url": "https://github.com/castortech/rivet-ai-sdk-provider/issues"

0 commit comments

Comments
 (0)