Private npm Supply Chain
Wavemap separates package authorization, credential storage, delivery, and publication. A credential is scoped to one actor and operation class; it is never promoted from a developer workstation into CI or from dependency reads into package publication.
Developers should begin with Private npm Access. This page owns the automation and operator lifecycle.
Trust Contexts
Section titled “Trust Contexts”| Context | Authority | Credential And Lifetime |
|---|---|---|
| Developer install | Developer’s npm identity can read declared packages. | Developer-owned granular token in the native OS store; normally 180 days. |
| Wavemap CI dependency install | Exact packages declared by Wavemap policy. | Wavemap-only NPM_PRIVATE_READ_TOKEN Actions secret; normally 180 days. |
| Local Docker build | Same read authority as the invoking developer. | Native token passed as BuildKit secret for one frontend build. |
| CI Docker build | Same read authority as Wavemap CI. | CI token passed as BuildKit secret for one frontend build. |
| Codon UI publication | Exact repository, workflow, branch, and environment. | GitHub OIDC identity for one workflow job; no persistent npm write token. |
| i18n-foundation publication | Exact repository, workflow, branch, and environment. | GitHub OIDC identity for one workflow job; no persistent npm write token. |
| Deployed application runtime | No npm registry authority. | No npm token. |
The public i18n package must resolve with empty authentication. A token is not added merely because that package shares the same consumer graph.
CI Read Contract
Section titled “CI Read Contract”Wavemap owns one repository Actions secret named NPM_PRIVATE_READ_TOKEN. Its backing npm token is read-only, selects the
exact private package set discovered by Wavemap policy, has no organization permissions, and cannot bypass 2FA.
Waveguide uses the same external secret name with a different token value so either consumer can be rotated or revoked
independently.
The repository’s composite pnpm setup action passes the secret to bin/npm-auth/preflight-ci.sh. Before installation,
that preflight:
- Validates that the secret has one supported granular-token shape.
- Builds a temporary authenticated npm configuration with owner-only permissions.
- Resolves every exact private package from the versioned policy.
- Resolves every public assertion with credentials removed.
- Runs the requested frozen install only after the package proofs pass.
Workflow source references only secrets.NPM_PRIVATE_READ_TOKEN; there is no NPM_TOKEN fallback. Fork, Dependabot, and
explicit cache-only lanes remain credential-free and cannot deploy.
Docker Boundary
Section titled “Docker Boundary”Only Wavemap’s frontend graph consumes @codon-ui/cli. Frontend dependency installation receives one BuildKit secret
named npm_private_read_token; backend development and deployment builds receive no npm credential. Dockerfiles consume
the secret from a mount only for the install instruction, create a temporary owner-only npm configuration, and remove
that file inside the same instruction.
Never carry the token through ARG, ENV, Compose environment, a copied npmrc, image metadata, an exported cache, or a
runtime container. The public commands:
pnpm wavemap -- npm-auth docker-proofpnpm wavemap -- npm-auth docker-proof --target frontend-deployforce no-cache builds without exported image output and scan withheld build output for the exact credential before releasing logs. The named-target form recovers one failed target without rebuilding accepted targets. A Docker change is accepted only when image configuration, history, layers, logs, and exported cache remain credential-free.
Trusted Package Publication
Section titled “Trusted Package Publication”Dependency-read credentials do not publish packages. The two source repositories own manual trusted-publication workflows:
| Package | Source And Workflow | Required npm Trusted-Publisher Identity | Access |
|---|---|---|---|
@codon-ui/cli | gabrielbourget/codon-ui / publish-cli.yml | Repository codon-ui, branch develop, environment npm-release | Restricted |
@gabrielbourget/i18n-foundation | gabrielbourget/i18n-foundation / publish-package.yml | Repository i18n-foundation, branch main, environment npm-release | Public |
The npm Repository field takes the bare GitHub repository name, not an npm package name. Both workflows require an exact
version and publish <version> confirmation, grant id-token: write only to the publication job, and use an
npm-release environment with no npm secret or variable. Package publishing access requires 2FA and disallows bypass
tokens; trusted publishers remain compatible with that stricter setting.
Do not add NPM_TOKEN, a write token, or an environment secret when OIDC fails. Diagnose package/repository identity,
workflow filename, branch, environment, version, and package contents locally. A failed paid or registry-mutating run
does not authorize a rerun.
CI Token Rotation
Section titled “CI Token Rotation”Start ordinary rotation 30 days before expiry and escalate at 7 days:
- Create a new read-only token dedicated to Wavemap, selecting the current policy’s complete private package set.
- Keep the old token active and update only the Wavemap repository’s
NPM_PRIVATE_READ_TOKENsecret. - With explicit authorization for that paid action, run one bounded CI proof that performs an empty-cache install and the relevant clean frontend Docker builds.
- Confirm source has no fallback and the accepted run used the replacement secret path.
- Revoke the old npm token.
- Re-run the least expensive post-revocation package proof needed to show that a cache did not hide stale authority.
Secret mutation, workflow dispatch, rerun, publication, and revocation are separate human gates. Never revoke the only proved credential before its replacement passes the same operation class.
Offboarding
Section titled “Offboarding”For a departing developer:
- Remove the npm identity from package-specific teams and the
codon-uiorganization. - Have the developer revoke their personal token; do not rotate other developers’ native credentials.
- Confirm the removed identity can no longer resolve the private package when a safe non-owner proof is available.
- Leave Waveguide and Wavemap CI tokens unchanged unless exposure, not membership, is the reason for offboarding.
For a departing publisher, remove the identity from cli-maintainers or the relevant GitHub environment reviewers. OIDC
publication remains bound to the exact repository workflow rather than a personal write token.
Incident Response
Section titled “Incident Response”| Suspected Boundary | Containment | Recovery Proof |
|---|---|---|
| Developer token exposed | Revoke that token, create a replacement, and run bootstrap --rotate. | Both consumer preflights and clean frozen installs pass; CI remains untouched. |
| Wavemap CI token exposed | Replace the Wavemap token and repository secret; do not rotate Waveguide automatically. | Exact-package CI preflight and required clean frontend Docker lane pass before old-token revocation. |
| Token appears in a Docker artifact | Stop distribution, revoke the responsible token, and inspect image config, history, layers, and caches. | Rebuild without cache through the BuildKit-secret path and repeat exact-value scans. |
| Trusted publication identity fails | Pause publication; inspect the exact npm publisher tuple and workflow source without adding a write token. | Local release checks pass, then one freshly authorized OIDC publication and registry readback pass. |
| npm membership is broader than policy | Remove the unintended team or member grant and review organization-member residual authority. | Intended identities retain reads; removed identities are denied; both CI readers remain healthy. |
Do not place token values, raw workflow logs, or account inventories in public docs or issues. Record sanitized evidence: repository, workflow/run identifier, package and version, operation class, result, and whether cache-independent proof was used.
The enforcing sources are infra/operations/config/private-npm-access-policy.json, infra/operations/src/private-npm,
bin/npm-auth, .github/actions/setup-pnpm, workflow contract tests, frontend Dockerfiles, and Bake definitions. Update
this page when the secret name, BuildKit secret ID, package policy, publisher tuple, or rotation ownership changes.