Add npm/PyPI package publishing access management (config + drift detection) - #169
Draft
claude[bot] wants to merge 2 commits into
Draft
Add npm/PyPI package publishing access management (config + drift detection)#169claude[bot] wants to merge 2 commits into
claude[bot] wants to merge 2 commits into
Conversation
…ection) 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.
Pulumi PreviewClick to expand preview output |
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 '/').
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Den Delimarsky · Slack thread
Before / After
Before: who can publish
@modelcontextprotocol/*npm packages and the MCP PyPI projects is managed ad hoc in the registry web UIs — invisible to this repo, unreviewed, and unaudited. After: expected registry access is declared here next to the GitHub/Google/Discord config, a weekly CI job surfaces drift between the declared state and the live npm registry, and changes are applied by a maintainer from a generated command plan. PyPI state is declared for audit with a manual runbook.How
src/config/utils.ts—Membergains optionalnpm/pypiidentity fields (documented likediscord), populated insrc/config/users.tsonly where the mapping was verified (see below).src/config/packageAccess.ts— npm org name, expected org membership (derived from members'npmfields plus an explicitUNMAPPED_NPM_USERSlist), per-package maintainers + trusted publisher (repo/workflow taken from npm provenance attestations) forsdk,inspector, andserver-everything, and a default policy for the org's other ~50 packages (base maintainer set, publish via trusted publishing). PyPI: declared rosters formcp,mcp-server-git,mcp-server-fetch,mcp-server-time. Import-safe for the validation scripts — pure data + helpers, no network.scripts/check-package-drift.ts(npm run check-package-drift) — read-only npm drift check usingNPM_TOKEN: org roster, org package enumeration, per-package maintainers, trusted-publisher config (GET /-/package/{pkg}/trust, degrading to a warning when the token can't read it). Prints a drift report and a remediation plan of exactnpm org/npm ownercommands to paste into one 2FA-approved session. Exits 1 on drift; prints a skip notice and exits 0 without a token..github/workflows/package-drift.yml— weekly +workflow_dispatch; no-ops gracefully when theNPM_READ_TOKENsecret is absent (same optional-credential pattern as Discord).deploy.yml/preview.ymluntouched.scripts/validate-config.ts/test-config.ts— validate the new config (usernames referenced by packages must exist on a member or the unmapped list, no duplicate npm/pypi usernames, no stale unmapped entries, org-scoped package names, org-owned trusted-publisher repos).Why no Pulumi resources: since August 2026 every npm governance mutation (org/team membership, maintainer add/remove, trusted publishing, token management) requires an interactive 2FA challenge — tokens with "bypass 2FA" get
403, and write-capable tokens are capped at 90-day lifetime anyway. Only reads are headless-automatable, hence config + read-only drift detection + human-applied plan. PyPI has no management API at all (web-UI only, maintainer invites accepted by email), so PyPI automation is deliberately out of scope.Verified identity mappings (populated in
users.ts):jspahrsummerspcarletonpaul@modelcontextprotocol.iomatches member's GWS prefixthedspdavid@modelcontextprotocol.iomatches member's emailfweinbergerfweinberger@anthropic.commatches nameochafik-antochafik@anthropic.commatches GitHub username + namecliffhallcliff@futurescale.commatches member's emaildspmcpproject accountjspahrsummersmcpproject accountKludexmcpproject accountmaxisbeymcpproject accountNot mapped (left out rather than guessed):
ashwin-ant(registry emailashwin@anthropic.com) — current maintainer on all three key packages but no matching entry inusers.ts; declared inUNMAPPED_NPM_USERSso the drift check doesn't propose removing them.mcp-server-git/mcp-server-fetch/mcp-server-time— PyPI exposes rosters only in the web UI and the pages sit behind a client challenge; declared empty with a note asking a project owner to fill them in from the Manage → Collaborators page.Open questions
ashwin-anton npm one of our members (and under which GitHub account)? Who holds roles on themcp-server-*PyPI projects?npm team+ per-team package grants) instead of flat per-package maintainer lists? Left out for now to keep the declared model matching what the registry actually shows.NPM_READ_TOKENActions secret; note it also becomes visible to same-repo PR preview runs if ever added to those workflows (it isn't in this PR). Token creation itself requires interactive 2FA, so rotation is a manual calendar item.modelcontextprotocolis registered by an unrelated party, so Python packages stay undermcp*names unless a PEP 541 transfer is ever pursued.