access/.github/workflows/package-drift.yml
claude[bot] f17de4044a
Add npm/PyPI package publishing access management (config + drift detection) (#169)
* Add npm/PyPI package publishing access management (config + drift detection)

Declare expected npm org membership, per-package maintainers and trusted
publishers, and PyPI project rosters in src/config/packageAccess.ts, with
npm/pypi identity fields on members in users.ts.

Deliberately outside the Pulumi resource graph: npm governance writes
require an interactive 2FA challenge since August 2026 (read endpoints
still work with a granular access token), and PyPI has no management API
at all. Drift against the live npm registry is detected read-only by
scripts/check-package-drift.ts (weekly via package-drift.yml, no-op when
the NPM_READ_TOKEN secret is absent), which emits a remediation plan of
npm CLI commands for a maintainer to run in one 2FA-approved session.
PyPI procedures are documented as a manual runbook in the README.

* Encode all slashes when escaping package names in registry URLs

Fixes the CodeQL finding: String.replace with a string pattern only
replaces the first occurrence. Use a shared helper with a global regex,
following the npm CLI convention (keep '@' literal, encode every '/').

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-19 12:12:46 +01:00

41 lines
1.2 KiB
YAML

name: Package Drift
# Read-only drift detection for npm package publishing access, comparing the
# live registry against src/config/packageAccess.ts. Mutations are applied by
# a human via the generated remediation plan (npm requires an interactive 2FA
# challenge for all governance writes); PyPI has no API and is not checked.
#
# Requires the NPM_READ_TOKEN secret: a read-only npm granular access token
# with organization read access to "modelcontextprotocol". When the secret is
# absent the check prints a skip notice and passes (same optional-credential
# pattern as the Discord integration).
on:
schedule:
- cron: '0 14 * * 1' # Mondays 14:00 UTC
workflow_dispatch:
permissions:
contents: read
jobs:
npm-drift:
name: npm package access drift
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Check npm package access drift
env:
NPM_TOKEN: ${{ secrets.NPM_READ_TOKEN }}
run: npm run check-package-drift