@ciqol/resenv 0.1.0-beta.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +41 -19
- package/README.md +36 -20
- package/SECURITY.md +20 -20
- package/bin/resenv.cjs +21 -23
- package/docs/build.md +29 -26
- package/docs/dependencies.md +65 -502
- package/docs/doppler.md +69 -60
- package/docs/maintainer-handoff.md +30 -102
- package/docs/release-security.md +64 -134
- package/docs/releasing.md +72 -137
- package/docs/security-exceptions.json +2 -135
- package/doppler/auth.cjs +4 -110
- package/doppler/http.cjs +3 -8
- package/doppler/system.cjs +26 -75
- package/package.json +2 -2
- package/types/src/doppler/auth.d.ts +2 -17
- package/types/src/doppler/http.d.ts +1 -3
- package/types/src/doppler/system.d.ts +3 -8
- package/docs/maturity.md +0 -61
- package/docs/public-readiness.md +0 -138
- package/docs/security-performance-review.md +0 -150
- package/docs/validation.md +0 -700
package/docs/doppler.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Doppler references and
|
|
1
|
+
# Doppler references and CLI authentication
|
|
2
2
|
|
|
3
3
|
Doppler is resenv's only built-in cloud provider. After Nx or another loader
|
|
4
4
|
populates the environment, resenv fetches referenced values through HTTPS and
|
|
@@ -13,40 +13,57 @@ a provider option. `resolve-doppler` and
|
|
|
13
13
|
|
|
14
14
|
## Local setup
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
After [installing resenv](../README.md#install) in your application project,
|
|
17
|
+
install the [official Doppler CLI](https://docs.doppler.com/docs/cli) and run
|
|
18
|
+
this from the application's directory:
|
|
17
19
|
|
|
18
20
|
```sh
|
|
19
|
-
|
|
20
|
-
node dist/bin/resenv.cjs login doppler
|
|
21
|
+
doppler login
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
The
|
|
39
|
-
`
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
24
|
+
Doppler owns browser authorization, token persistence, login scopes and logout.
|
|
25
|
+
Use `doppler logout` to manage the CLI login. resenv never opens a browser,
|
|
26
|
+
prompts for login, issues or revokes tokens, or reads or writes the OS
|
|
27
|
+
credential store directly. There is no separate resenv login.
|
|
28
|
+
|
|
29
|
+
Existing Doppler users can reuse their login. resenv asks the CLI for the token
|
|
30
|
+
selected by its current working directory, so Doppler's directory-scoped
|
|
31
|
+
workplace identities continue to apply. See
|
|
32
|
+
[Doppler's scope guide](https://docs.doppler.com/docs/multiple-workplaces).
|
|
33
|
+
`doppler setup` is not required for resenv references: their project and config
|
|
34
|
+
are already explicit in each `doppler://` value. Nx or the caller remains
|
|
35
|
+
responsible for dotenv file loading.
|
|
36
|
+
|
|
37
|
+
### Platforms and installation locations
|
|
38
|
+
|
|
39
|
+
The CLI handles its own credential storage on macOS, Linux and Windows. resenv
|
|
40
|
+
does not require `secret-tool`, a separate keyring package or native Node addons.
|
|
41
|
+
It discovers the CLI in these standard locations:
|
|
42
|
+
|
|
43
|
+
| Platform | Locations, in lookup order |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| macOS / Linux | `/opt/homebrew/bin/doppler`, `/usr/local/bin/doppler`, `/usr/bin/doppler`, `~/.local/bin/doppler`, `~/bin/doppler` |
|
|
46
|
+
| Windows | `~/AppData/Local/Microsoft/WinGet/Links/doppler.exe`, `~/scoop/apps/doppler/current/doppler.exe` |
|
|
47
|
+
|
|
48
|
+
Here `~` is the OS user's home directory. Windows paths cover default per-user
|
|
49
|
+
WinGet and Scoop installations. Custom and system-wide Windows installations
|
|
50
|
+
outside these locations need an explicit `DOPPLER_TOKEN`. WSL uses the Linux
|
|
51
|
+
installation and login within WSL. The runtime deliberately ignores the
|
|
52
|
+
application's `PATH` so a repository-local executable cannot replace the
|
|
53
|
+
credential helper.
|
|
54
|
+
|
|
55
|
+
Windows discovery is covered with injected process tests; a native Windows
|
|
56
|
+
end-to-end run is not yet verified. Automated checks never use a developer's
|
|
57
|
+
Doppler login or OS credential store.
|
|
58
|
+
|
|
59
|
+
### Migration from resenv-managed login
|
|
60
|
+
|
|
61
|
+
`resenv login` and `resenv logout` have been removed. Run `doppler login` to
|
|
62
|
+
establish the CLI identity, then start the application normally. Earlier resenv
|
|
63
|
+
credentials stored under service `ciqol.envref.doppler`, account `default`, are
|
|
64
|
+
ignored and are not migrated or deleted automatically. If you used that flow,
|
|
65
|
+
remove the obsolete entry through your OS credential manager and revoke the
|
|
66
|
+
obsolete token in Doppler when it is no longer needed.
|
|
50
67
|
|
|
51
68
|
## Declare a reference
|
|
52
69
|
|
|
@@ -73,38 +90,31 @@ For an Nx command target, use `resenv run -- node app.mjs` inside the
|
|
|
73
90
|
target. Preloading the outer Nx process would run before Nx loads target files.
|
|
74
91
|
resenv does not choose, read or rewrite dotenv files.
|
|
75
92
|
|
|
76
|
-
##
|
|
93
|
+
## Runtime credential lookup
|
|
77
94
|
|
|
78
95
|
Resolution checks these sources in order:
|
|
79
96
|
|
|
80
97
|
1. An explicitly supplied `DOPPLER_TOKEN`.
|
|
81
|
-
2. The
|
|
82
|
-
3. The current directory's existing Doppler CLI login, retrieved with the
|
|
98
|
+
2. The current directory's existing Doppler CLI login, retrieved with the
|
|
83
99
|
documented `doppler configure get token --plain` operation.
|
|
84
100
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
101
|
+
resenv captures the token internally and fetches secrets through HTTPS; it does
|
|
102
|
+
not parse the CLI's private config format. The command uses a fixed executable,
|
|
103
|
+
separate arguments, `--no-check-version` and `--no-read-env`, with a restricted
|
|
104
|
+
environment. It inherits the application's working directory to preserve login
|
|
105
|
+
scopes. Lookup has a fifteen-second timeout and a 16 KiB output limit. Captured
|
|
106
|
+
output and helper errors are never forwarded to application logs.
|
|
91
107
|
|
|
92
|
-
|
|
93
|
-
|
|
108
|
+
If the CLI is missing, install it in a supported location and run `doppler login`,
|
|
109
|
+
or supply `DOPPLER_TOKEN`. A failed or empty CLI lookup reports that login is
|
|
110
|
+
required. An explicitly supplied invalid token, malformed CLI token, access
|
|
111
|
+
denial or network failure stops the operation without switching identities or
|
|
112
|
+
starting login.
|
|
94
113
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
An explicit invalid token, access denial, login rejection, timeout or network
|
|
100
|
-
error stops the operation. These failures do not silently switch identities.
|
|
101
|
-
Unset `DOPPLER_TOKEN` before interactive login because it overrides saved logins.
|
|
102
|
-
In CI, supply a suitably scoped token through the runner's credential facility.
|
|
103
|
-
|
|
104
|
-
`resenv logout doppler` removes only resenv's local credential. It does not
|
|
105
|
-
revoke the remote token, unset an environment variable or log the Doppler CLI
|
|
106
|
-
out. Those other credential sources can still authenticate. Revoke unwanted
|
|
107
|
-
tokens from Doppler's CLI Tokens page.
|
|
114
|
+
In CI, containers and other unattended environments, supply a suitably scoped
|
|
115
|
+
`DOPPLER_TOKEN` through the runner's secret facility. No CLI installation or
|
|
116
|
+
local credential store is needed in that mode. Changing the CLI login affects
|
|
117
|
+
the next application startup; resenv does not keep a persistent token cache.
|
|
108
118
|
|
|
109
119
|
## Resolution and security boundaries
|
|
110
120
|
|
|
@@ -126,10 +136,9 @@ tokens from Doppler's CLI Tokens page.
|
|
|
126
136
|
- Preloads use a child Node process to wait for asynchronous HTTPS while
|
|
127
137
|
retaining `--require` compatibility. It receives only references and an
|
|
128
138
|
explicit credential through stdin, with results returned through a private
|
|
129
|
-
pipe. No Doppler CLI is required when
|
|
139
|
+
pipe. No Doppler CLI is required when `DOPPLER_TOKEN` is supplied.
|
|
130
140
|
- Diagnostics show variable names and error codes, never tokens, provider
|
|
131
|
-
response bodies or resolved values.
|
|
132
|
-
its temporary human authorization code.
|
|
141
|
+
response bodies, CLI output or resolved values.
|
|
133
142
|
|
|
134
143
|
This removes shell evaluation from Doppler lookups. It does not isolate
|
|
135
144
|
untrusted repository code or agents that can access the same user's credential
|
|
@@ -139,8 +148,8 @@ to a specific config.
|
|
|
139
148
|
|
|
140
149
|
## Sources
|
|
141
150
|
|
|
142
|
-
- [Doppler
|
|
143
|
-
- [
|
|
151
|
+
- [Doppler CLI installation and authentication](https://docs.doppler.com/docs/cli)
|
|
152
|
+
- [Directory-scoped workplace logins](https://docs.doppler.com/docs/multiple-workplaces)
|
|
144
153
|
- [Retrieve a secret](https://docs.doppler.com/reference/secrets-get)
|
|
145
154
|
- [API authentication](https://docs.doppler.com/reference/api)
|
|
146
155
|
- [Retrieve the CLI token](https://docs.doppler.com/docs/cli#fetch-cli-token-from-your-local-environment)
|
|
@@ -1,112 +1,40 @@
|
|
|
1
|
-
# Maintainer
|
|
1
|
+
# Maintainer guide
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Start with [AGENTS.md](https://github.com/ciqol/resenv/blob/main/AGENTS.md) for repository policy and
|
|
4
|
+
[CONTRIBUTING.md](../CONTRIBUTING.md) for setup and verification. Work in an
|
|
5
|
+
isolated task worktree on a `titan/*` branch. Authenticate as `titan-ron` for
|
|
6
|
+
[ciqol/resenv](https://github.com/ciqol/resenv); `main` is the default and sole
|
|
7
|
+
release branch.
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
the push remote and recent commits before changing anything.
|
|
9
|
+
Inspect current Git status, branches, push remote and recent commits before
|
|
10
|
+
editing. Read live GitHub checks, releases and npm metadata before release
|
|
11
|
+
work; old chat messages or check results are not authoritative. Never copy
|
|
12
|
+
credentials between sessions.
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- Package: `@ciqol/resenv`; CLI: `resenv`.
|
|
21
|
-
- Node preloads: `--require @ciqol/resenv/resolve` and
|
|
22
|
-
`--import @ciqol/resenv/resolve`.
|
|
23
|
-
- Public API: `resolve(env = process.env, { replace: false })`. Always return a
|
|
24
|
-
copy; update the input only with `replace: true`.
|
|
25
|
-
- Let Nx or the caller load dotenv files. Resolve values already in the
|
|
26
|
-
environment, once before application imports.
|
|
27
|
-
- Doppler is the only cloud provider. Infer it from
|
|
28
|
-
`doppler://project/config/SECRET_NAME`; that syntax belongs to resenv.
|
|
29
|
-
- Commands require explicit opt-in. Fetched values remain literal, and a
|
|
30
|
-
failed pass leaves the caller's environment unchanged.
|
|
31
|
-
- Debug selector: `NODE_DEBUG=ciqol:resenv`. Never log secret values, tokens,
|
|
32
|
-
command text or provider response bodies.
|
|
33
|
-
- Runtime npm dependencies: none. Dotenvx decryption has been removed;
|
|
34
|
-
`encrypted:` values remain literal.
|
|
14
|
+
| Guide | Maintained information |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| [README](../README.md) | Application installation, API and CLI usage |
|
|
17
|
+
| [Doppler](doppler.md) | CLI authentication, lookup, migration and platform limits |
|
|
18
|
+
| [Build](build.md) | Module formats, declarations, archive and CI contract |
|
|
19
|
+
| [Dependencies](dependencies.md) | Tool rationale, installation and update policy |
|
|
20
|
+
| [Releasing](releasing.md) | PR approval, main releases and recovery |
|
|
21
|
+
| [Release security](release-security.md) | Dependency audit and release-tool review deadline |
|
|
22
|
+
| [Security](../SECURITY.md) | Trust boundaries and private vulnerability reporting |
|
|
35
23
|
|
|
36
24
|
## Code map
|
|
37
25
|
|
|
38
26
|
| Path | Responsibility |
|
|
39
27
|
| --- | --- |
|
|
40
|
-
| `src/index.ts` | Resolution API and atomic replacement |
|
|
28
|
+
| `src/index.ts` | Resolution API and atomic environment replacement |
|
|
41
29
|
| `src/preload.ts`, `src/resolve*.ts` | Startup integration and shared preload state |
|
|
42
|
-
| `src/doppler/` |
|
|
30
|
+
| `src/doppler/` | References, HTTPS, concurrency and CLI credential lookup |
|
|
43
31
|
| `src/commands.ts` | Explicit shell substitution and process limits |
|
|
44
|
-
| `bin/resenv.ts` |
|
|
45
|
-
| `rollup.config.mjs`, `scripts/build.mjs` | CJS implementation,
|
|
46
|
-
| `
|
|
47
|
-
| `scripts/
|
|
48
|
-
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
```sh
|
|
55
|
-
nvm use
|
|
56
|
-
npm ci
|
|
57
|
-
npm run audit
|
|
58
|
-
npm run verify
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Unit specs live beside source modules and run with Vitest. Process tests live
|
|
62
|
-
in `test/`. Clean-consumer checks exercise CJS, ESM, declarations, CLI and
|
|
63
|
-
preloads against the packed archive. Tests use dummy values and mocked effects;
|
|
64
|
-
do not use a developer's Doppler account or OS credential store as a fixture.
|
|
65
|
-
See CONTRIBUTING for Nx integration checks and benchmarking.
|
|
66
|
-
|
|
67
|
-
## Recover release state before pushing
|
|
68
|
-
|
|
69
|
-
Read current state rather than treating a dated handoff as authoritative:
|
|
70
|
-
|
|
71
|
-
```sh
|
|
72
|
-
gh run list --repo ciqol/resenv --workflow ci.yml --limit 5
|
|
73
|
-
gh release list --repo ciqol/resenv
|
|
74
|
-
npm view @ciqol/resenv versions dist-tags --json
|
|
75
|
-
npm stage list @ciqol/resenv --json
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
The first intended version is `0.1.0-beta.1` on npm's `beta` tag. The planner
|
|
79
|
-
uses semantic-release's official commit-analysis and notes plugins directly;
|
|
80
|
-
it does not run the full semantic-release engine. Real published release tags
|
|
81
|
-
supply later beta counters. Do not fabricate tags to advance a version.
|
|
82
|
-
|
|
83
|
-
Publishing is staged: a trusted manual CI dispatch submits the exact archive
|
|
84
|
-
that passed all consumer checks. The `release` environment accepts only `beta`
|
|
85
|
-
and has no GitHub reviewer gate. npm approval with 2FA makes a stage public.
|
|
86
|
-
After public availability and integrity verification, rerun the original
|
|
87
|
-
release job to record its Git tag and GitHub prerelease. Keep `beta` at that
|
|
88
|
-
candidate's commit until this step finishes, unless the maintainer explicitly
|
|
89
|
-
chooses to reject and replace the pending stage. Do not rerun the whole
|
|
90
|
-
workflow to recover an existing stage.
|
|
91
|
-
|
|
92
|
-
A staged version reserves its version number. To replace an unapproved
|
|
93
|
-
candidate, the maintainer must reject the old stage with npm 2FA before CI
|
|
94
|
-
stages the replacement. Check stage status before retrying an ambiguous result.
|
|
95
|
-
Never publish from a developer machine, add a publishing token, promote a beta
|
|
96
|
-
to `latest`, or delete the whole npm package. The `0.0.0-stage` placeholder must
|
|
97
|
-
remain until a functional beta is public; removing the last published version
|
|
98
|
-
would remove the package and impose npm's publishing cooldown.
|
|
99
|
-
|
|
100
|
-
## Known limits and follow-ups
|
|
101
|
-
|
|
102
|
-
- Native Doppler browser login has unit/mock coverage but has not been verified
|
|
103
|
-
end to end with a fresh account. Linux credential storage has mock coverage;
|
|
104
|
-
Windows native login/storage is not implemented. Explicit tokens and existing
|
|
105
|
-
CLI credentials are supported. See [Doppler details](doppler.md).
|
|
106
|
-
- The development release-tool tree has reviewed advisories. Exceptions expire
|
|
107
|
-
November 9, 2026, and executable guards fail on expiry or drift. Review
|
|
108
|
-
[release security](release-security.md); never broaden or bypass the policy.
|
|
109
|
-
- This beta has not had an independent security audit. Passing tests or the
|
|
110
|
-
static maturity checklist does not establish production readiness.
|
|
111
|
-
- Consumer repositories are separate. Keep local links out of their committed
|
|
112
|
-
package manifests, lockfiles and CI.
|
|
32
|
+
| `bin/resenv.ts` | Child-process CLI |
|
|
33
|
+
| `rollup.config.mjs`, `scripts/build.mjs` | CJS implementation, ESM facades, types and manifest |
|
|
34
|
+
| `release.config.mjs` | Standard semantic-release plugins and main/0.x policy |
|
|
35
|
+
| `scripts/release.mjs` | One-time 0.1.0 bootstrap, then the standard release command |
|
|
36
|
+
| `scripts/verify-release.mjs` | Trusted event, review expiry, 0.x and final package checks |
|
|
37
|
+
| `.github/workflows/ci.yml` | Checks, one compiled build and publication on main merges |
|
|
38
|
+
|
|
39
|
+
Keep docs focused on current contracts, decisions and procedures. Put per-run
|
|
40
|
+
test results, benchmarks, audit snapshots and session history in PRs or CI.
|
package/docs/release-security.md
CHANGED
|
@@ -1,134 +1,64 @@
|
|
|
1
|
-
# Release-tool security
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
The
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
`
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Standalone patched releases do not establish that the bundled copy is fixed.
|
|
66
|
-
Review and remove these exceptions when the upstream distributions are fixed.
|
|
67
|
-
|
|
68
|
-
## Dependency admission
|
|
69
|
-
|
|
70
|
-
- **Need:** automate Conventional Commit analysis and release notes, as selected
|
|
71
|
-
by the user. Platform APIs do not implement that versioning contract.
|
|
72
|
-
- **Fit:** retain the selected engine rather than switch to release-please or
|
|
73
|
-
maintain a custom analyzer. Native publication glue preserves the tested
|
|
74
|
-
archive instead of letting a package-directory plugin repack it.
|
|
75
|
-
- **Health:** registry review recorded monthly downloads of 12,515,497 for the
|
|
76
|
-
engine, 12,542,138 for the analyzer and 12,802,125 for the notes generator,
|
|
77
|
-
with three listed maintainers each. Selected release dates are August 5, 2026;
|
|
78
|
-
January 3, 2025; and May 8, 2026. The older analyzer remains the component
|
|
79
|
-
required by the current engine. Maintenance evidence is not a security guarantee.
|
|
80
|
-
- **Trust:** the canonical semantic-release repositories match the distributed
|
|
81
|
-
modules. The isolated installation verified 447 registry signatures and 121
|
|
82
|
-
provenance attestations; the final merged installation verified 606 signatures
|
|
83
|
-
and 186 attestations. Registry metadata does not expose individual MFA or
|
|
84
|
-
independently prove historical ownership continuity; those limits remain.
|
|
85
|
-
- **License:** the three direct artifacts contain MIT license text. The isolated
|
|
86
|
-
tree's licenses are MIT, ISC, BSD-2-Clause, BSD-3-Clause, Apache-2.0, BlueOak-1.0.0,
|
|
87
|
-
Python-2.0, Artistic-2.0, CC-BY-3.0, CC0-1.0 and permissive alternative sets.
|
|
88
|
-
qrcode-terminal's absent SPDX metadata is resolved by its Apache-2.0 LICENSE.
|
|
89
|
-
Some artifacts express the license in package metadata rather than a separate
|
|
90
|
-
license file. No reciprocal source-disclosure license was identified. These
|
|
91
|
-
development modules are excluded from the consumer package.
|
|
92
|
-
- **Capabilities:** filesystem, subprocess and Git access are required for local
|
|
93
|
-
history analysis. The selected plugin path does not publish, contact npm or
|
|
94
|
-
post GitHub comments. The isolated tree contains no install lifecycle hooks.
|
|
95
|
-
- **Control:** exact direct versions and the lockfile pin the tree; CODEOWNERS
|
|
96
|
-
and Dependabot retain ownership and update visibility. The guards and expiring
|
|
97
|
-
audit policy fail on drift. Removal means deleting the three development
|
|
98
|
-
dependencies and disabling release planning/publication; local build and
|
|
99
|
-
consumer verification remain available.
|
|
100
|
-
|
|
101
|
-
The audit result must remain visible. Do not describe the release-tool tree as
|
|
102
|
-
vulnerability-free, use an audit-wide ignore, or pass it to a privileged job.
|
|
103
|
-
|
|
104
|
-
## Publishing platform
|
|
105
|
-
|
|
106
|
-
The publisher uses the npm CLI shipped with the pinned Node.js 24.19.0 runtime
|
|
107
|
-
(npm 11.17.0). That platform CLI also bundles older components affected by
|
|
108
|
-
advisories. npm 12.2.0 was inspected and still distributes affected versions;
|
|
109
|
-
upgrading to it would not remove this risk. The development-only policy does
|
|
110
|
-
not imply that the platform CLI is vulnerability-free.
|
|
111
|
-
|
|
112
|
-
The staging path uses npm 11.17.0's existing `stage publish` subcommand and
|
|
113
|
-
accepts only the validated archive, with no lifecycle
|
|
114
|
-
scripts in its manifest. It uses a fresh home, configuration and cache, fixes
|
|
115
|
-
the registry to HTTPS npmjs.org, and strips proxy, token and arbitrary npm
|
|
116
|
-
configuration from the child environment. No package-query, login, shell,
|
|
117
|
-
selector or arbitrary URL input is accepted. OIDC is supplied by GitHub for the
|
|
118
|
-
specific repository, workflow and protected environment. Registry and signing
|
|
119
|
-
services remain trusted inputs. This bounds exposure; it is not an upstream
|
|
120
|
-
fix. The publisher checks the policy expiry again when it runs, including on a
|
|
121
|
-
failed-job retry, and rejects platform version drift. Review the platform CLI
|
|
122
|
-
again before November 9 alongside this policy.
|
|
123
|
-
|
|
124
|
-
## October 12 staging review
|
|
125
|
-
|
|
126
|
-
The pinned npm platform includes `lib/commands/stage/publish.js`, which extends
|
|
127
|
-
its reviewed publish command and sets `stage: true`. The same fixed tarball,
|
|
128
|
-
registry, OIDC identity and provenance options apply. Approval/rejection remain
|
|
129
|
-
interactive npm operations, outside CI. The publisher validates npm's JSON
|
|
130
|
-
receipt against the candidate's name, version and SHA-512 integrity and records
|
|
131
|
-
only its stage identifier and hashes. It creates no tag while the archive is
|
|
132
|
-
staged or pending registry availability. After approval, rerun the same release
|
|
133
|
-
job: its existing-version path verifies integrity and records the release.
|
|
134
|
-
No dependency version, advisory exception or expiry was broadened.
|
|
1
|
+
# Release-tool security
|
|
2
|
+
|
|
3
|
+
Maintainer: `titan-ron`. The complete installed tree must pass
|
|
4
|
+
`npm audit --audit-level=moderate`; there are no advisory exceptions. The
|
|
5
|
+
[review deadline](security-exceptions.json) remains **November 9, 2026 at
|
|
6
|
+
00:00 UTC** and is enforced before publication. Do not extend it or suppress
|
|
7
|
+
findings to unblock a release.
|
|
8
|
+
|
|
9
|
+
Standard semantic-release and the official npm/GitHub plugins replace the
|
|
10
|
+
standalone planner and staging controller. Their dependencies are now installed
|
|
11
|
+
and audited normally. The old peer-omission and module-blocking policy no longer
|
|
12
|
+
applies to tools explicitly selected for this pipeline. No release tool ships
|
|
13
|
+
to package consumers.
|
|
14
|
+
|
|
15
|
+
## Publishing authority
|
|
16
|
+
|
|
17
|
+
PR merge is approval. Branch rules require the real CI/CodeQL checks and prevent
|
|
18
|
+
direct pushes, force pushes, deletion and bypass. PRs and manual dispatches
|
|
19
|
+
cannot publish. Only main pushes may enter the `release` environment, with
|
|
20
|
+
contents write and OIDC permissions. There are no npm tokens or additional
|
|
21
|
+
reviewers. The release token is exposed only to the release step, and checkout
|
|
22
|
+
does not persist credentials.
|
|
23
|
+
|
|
24
|
+
The job consumes compiled output tested by CI. The npm plugin changes release
|
|
25
|
+
metadata and packs it; the verification hook tests the final package. Publishing
|
|
26
|
+
uses the prepared directory, whose manifest has no package lifecycle scripts.
|
|
27
|
+
The source is not rebuilt. The bootstrap publishes its checked tarball directly.
|
|
28
|
+
GitHub issue/PR comments and labels are disabled in the GitHub plugin so it
|
|
29
|
+
needs no issue or pull-request write permission.
|
|
30
|
+
|
|
31
|
+
## Dependency review
|
|
32
|
+
|
|
33
|
+
Review actual installed artifacts, including npm's bundled dependencies.
|
|
34
|
+
Overrides are not evidence that bundled files changed: inspect their manifests
|
|
35
|
+
on disk. A failing dependency audit blocks merge and release; it is not a
|
|
36
|
+
non-blocking report. Do not broaden exceptions or silently substitute an
|
|
37
|
+
unreviewed npm version.
|
|
38
|
+
|
|
39
|
+
### Temporary npm bundle repair
|
|
40
|
+
|
|
41
|
+
npm 11.21.1 bundles vulnerable `undici` and `ip-address` files that npm overrides
|
|
42
|
+
do not replace. Until an upstream npm release includes the fixes, the reviewed
|
|
43
|
+
root `postinstall` hook replaces those two directories with the exact registry
|
|
44
|
+
packages `undici@6.29.1` and `ip-address@10.7.5`, installed under development-only
|
|
45
|
+
aliases. Their integrity hashes are pinned in the lockfile, which also records
|
|
46
|
+
the repaired bundle versions. This is an actual file replacement, not an audit
|
|
47
|
+
exception or a metadata-only override.
|
|
48
|
+
|
|
49
|
+
`npm run audit` first compares every installed bundle file with the corresponding
|
|
50
|
+
locked upstream package. Missing, extra or modified files fail the check. The
|
|
51
|
+
repair accepts only the reviewed npm and dependency versions and rejects patch
|
|
52
|
+
packages with runtime dependencies. It does not fetch code or use credentials.
|
|
53
|
+
Registry signatures verify the upstream packages; they do not attest the locally
|
|
54
|
+
repaired npm bundle as an npm-maintained distribution.
|
|
55
|
+
|
|
56
|
+
Remove the hook, repair script/tests, aliases and repaired lock entries together
|
|
57
|
+
when upgrading to an npm release containing both fixes. Regenerate the lockfile
|
|
58
|
+
and validate a clean install, on-disk versions, audit, signatures and package
|
|
59
|
+
checks before removing the repair. The existing review deadline still applies.
|
|
60
|
+
|
|
61
|
+
Use pinned versions and the lockfile. Validate normal installs, registry
|
|
62
|
+
signatures/attestations, the full audit and the package tests. See
|
|
63
|
+
[dependencies](dependencies.md) for tool choices. Record dated findings and
|
|
64
|
+
per-run evidence in the PR, not in this document.
|