@ciqol/resenv 0.1.0-beta.2 → 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 +16 -14
- package/README.md +8 -6
- package/docs/build.md +27 -23
- package/docs/dependencies.md +63 -56
- package/docs/maintainer-handoff.md +8 -7
- package/docs/release-security.md +51 -57
- package/docs/releasing.md +72 -148
- package/docs/security-exceptions.json +2 -135
- package/package.json +2 -2
package/CONTRIBUTING.md
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
# Contributing
|
|
2
2
|
|
|
3
3
|
Starting a new session? Read the [maintainer handoff](docs/maintainer-handoff.md)
|
|
4
|
-
and [repository instructions](https://github.com/ciqol/resenv/blob/
|
|
4
|
+
and [repository instructions](https://github.com/ciqol/resenv/blob/main/AGENTS.md) before editing or releasing.
|
|
5
5
|
|
|
6
6
|
The [README](README.md) covers using resenv in an application. This guide covers
|
|
7
7
|
changing resenv itself and verifying those changes.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
CI generates the publishable manifest before packing and testing it, then stages
|
|
15
|
-
the exact archive through npm OIDC for maintainer approval. See
|
|
16
|
-
[releasing](docs/releasing.md) and the bounded [release-tool review](docs/release-security.md).
|
|
9
|
+
Merge to protected `main` approves release. CI uses standard semantic-release
|
|
10
|
+
and the official npm/GitHub plugins to publish regular `0.x.x` versions to
|
|
11
|
+
`latest`. The root and local builds stay private; only the protected release
|
|
12
|
+
job makes the tested build publishable. See [releasing](docs/releasing.md)
|
|
13
|
+
and [release security](docs/release-security.md).
|
|
17
14
|
The source uses the [MIT license](LICENSE), copyright ciqol contributors.
|
|
18
15
|
|
|
19
16
|
## Local development
|
|
@@ -82,9 +79,14 @@ functions and lines. Worker and preload entry files stay in the denominator;
|
|
|
82
79
|
the CLI is checked separately by process and packed-package tests. CI retains
|
|
83
80
|
LCOV and Cobertura reports for seven days in the `resenv-coverage` artifact.
|
|
84
81
|
The official `actions/upload-code-coverage` action uploads Cobertura in a separate
|
|
85
|
-
job
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
job for same-repository PRs and `main` runs; other runs retain the local gate and
|
|
83
|
+
report artifacts. The main `ci` job groups audits, lint, types, coverage, build
|
|
84
|
+
and packed-package/process checks on the pinned Node version. CLI lookup checks
|
|
85
|
+
use injected helpers and temporary
|
|
86
|
+
dummy executables; they never access a developer credential store or
|
|
87
|
+
authenticated provider session.
|
|
88
|
+
The `smoke` matrix checks that same archive on Linux Node 20 and 22 and macOS
|
|
89
|
+
with the pinned Node version; it does not build or rerun source unit specs.
|
|
88
90
|
|
|
89
91
|
Use normal npm lifecycle behavior locally and in CI. Review install hooks,
|
|
90
92
|
including implicit native builds, when changing dependencies; record any
|
|
@@ -105,7 +107,7 @@ Pass an existing archive to test the same build CI uses:
|
|
|
105
107
|
also pass its `release.json` as the second argument. The supplied package's
|
|
106
108
|
name, version, executable mode and manifest are checked before runtime probes.
|
|
107
109
|
The README inside the archive must match the checkout, install from npm's
|
|
108
|
-
`
|
|
110
|
+
`latest` channel and avoid unpublished or local-archive installation guidance.
|
|
109
111
|
`npm run verify` runs lint, typecheck, build and tests; `npm run release:check`
|
|
110
112
|
also previews the package contents. Neither publishes or creates a tag.
|
|
111
113
|
|
|
@@ -128,7 +130,7 @@ npm run pack:local
|
|
|
128
130
|
Install the resulting archive from the application's directory:
|
|
129
131
|
|
|
130
132
|
```sh
|
|
131
|
-
npm install --save-exact /absolute/path/to/ciqol-resenv-0.1.0
|
|
133
|
+
npm install --save-exact /absolute/path/to/ciqol-resenv-0.1.0.tgz
|
|
132
134
|
```
|
|
133
135
|
|
|
134
136
|
This changes the application's manifest and lockfile. The archive must exist
|
package/README.md
CHANGED
|
@@ -20,19 +20,21 @@ Resolution happens once at startup. It does not watch the provider for changes;
|
|
|
20
20
|
restart the application to fetch updated values. No filename is passed to
|
|
21
21
|
resenv, and dotenv files are never rewritten.
|
|
22
22
|
|
|
23
|
-
Requires Node.js 20 or later.
|
|
24
|
-
|
|
23
|
+
Requires Node.js 20 or later. The package is experimental and remains in initial
|
|
24
|
+
development; its API may change between 0.x releases.
|
|
25
|
+
|
|
26
|
+
Background: [A new Git worktree shouldn't mean another copy of your secrets](https://dev.to/titanron/a-new-git-worktree-shouldnt-mean-another-copy-of-your-secrets-424).
|
|
25
27
|
|
|
26
28
|
## Install
|
|
27
29
|
|
|
28
|
-
Install
|
|
30
|
+
Install in your application project:
|
|
29
31
|
|
|
30
32
|
```sh
|
|
31
|
-
npm install --save-exact @ciqol/resenv
|
|
33
|
+
npm install --save-exact @ciqol/resenv
|
|
32
34
|
```
|
|
33
35
|
|
|
34
|
-
This records the selected
|
|
35
|
-
|
|
36
|
+
This records the version selected by npm's `latest` tag in your project's
|
|
37
|
+
manifest and lockfile.
|
|
36
38
|
|
|
37
39
|
The CLI examples below use `npx --no-install` to run the copy installed in your
|
|
38
40
|
project. In an npm script, use `resenv` directly.
|
package/docs/build.md
CHANGED
|
@@ -90,10 +90,10 @@ overrides and a package-wide `type` field. Explicit `.mjs` and `.cjs` extensions
|
|
|
90
90
|
select the output format. README, the MIT `LICENSE`, contributor/security guides
|
|
91
91
|
and docs are copied into the distribution and included in the archive.
|
|
92
92
|
|
|
93
|
-
Ordinary local builds retain `private: true`.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
Ordinary local and CI builds retain `private: true`. Only the protected release
|
|
94
|
+
job makes the tested build publishable and lets the npm plugin set its version.
|
|
95
|
+
The development root stays private. Release consumer checks validate the final
|
|
96
|
+
versioned package before direct publication; see
|
|
97
97
|
[releasing](releasing.md).
|
|
98
98
|
|
|
99
99
|
`npm run pack:local` packs the generated directory. `npm run test:package`
|
|
@@ -114,22 +114,26 @@ consumer artifact is rebuilt in place by these tests.
|
|
|
114
114
|
|
|
115
115
|
## CI
|
|
116
116
|
|
|
117
|
-
The `
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
job
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
117
|
+
The `ci` job checks advisories and registry signatures, lint, types and source
|
|
118
|
+
coverage, then builds and packs once. It tests the private archive and processes
|
|
119
|
+
on the pinned Node version. The `smoke` matrix tests that archive on Linux Node
|
|
120
|
+
20/22 and macOS with pinned Node 24; it never recompiles source. Coverage runs
|
|
121
|
+
once, with a separate job uploading the report on same-repository PRs and main.
|
|
122
|
+
Required archives and coverage reports are retained for seven days.
|
|
123
|
+
|
|
124
|
+
After a merge to protected `main`, `release` downloads the tested build and runs
|
|
125
|
+
semantic-release with the official npm/GitHub plugins. The npm plugin prepares
|
|
126
|
+
version metadata and a tarball; the local verification hook checks the final
|
|
127
|
+
package's consumer contract before publication. Source is never rebuilt in the
|
|
128
|
+
release job. The official npm plugin publishes the prepared directory with no
|
|
129
|
+
package lifecycle scripts. See [releasing](releasing.md) for the one-time 0.1.0
|
|
130
|
+
bootstrap and failure handling.
|
|
131
|
+
|
|
132
|
+
PRs and manual dispatches cannot publish. Release permissions are limited to
|
|
133
|
+
GitHub contents write and OIDC. Package and registry secrets are absent from
|
|
134
|
+
validation jobs. Every checkout disables persisted credentials, and the release
|
|
135
|
+
token is scoped to the release step. Official GitHub actions use exact release
|
|
136
|
+
tags; other remote actions require commit SHAs.
|
|
137
|
+
|
|
138
|
+
The protected branch requires `ci`, `coverage`, all three `smoke` contexts and
|
|
139
|
+
`Analyze (javascript-typescript)`. Keep these names stable when editing CI.
|
package/docs/dependencies.md
CHANGED
|
@@ -1,61 +1,68 @@
|
|
|
1
1
|
# Dependencies
|
|
2
2
|
|
|
3
|
-
resenv has no runtime npm dependencies.
|
|
4
|
-
|
|
5
|
-
in
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
## Tool choices
|
|
3
|
+
resenv has no runtime npm dependencies. All tools are development-only and
|
|
4
|
+
excluded from the consumer package. Exact direct versions and archive integrity
|
|
5
|
+
live in package.json and package-lock.json. Use the pinned Node version and
|
|
6
|
+
normal `npm ci`; review install hooks instead of disabling them globally.
|
|
9
7
|
|
|
10
8
|
| Packages | Purpose | License |
|
|
11
9
|
| --- | --- | --- |
|
|
12
|
-
| `rollup`, `@rollup/plugin-typescript` |
|
|
13
|
-
| `typescript` | Strict implementation
|
|
14
|
-
| `tslib` |
|
|
15
|
-
| `@types/node` |
|
|
16
|
-
| `eslint`, `typescript-eslint` |
|
|
17
|
-
| `vitest`, `@vitest/coverage-v8` |
|
|
18
|
-
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
10
|
+
| `rollup`, `@rollup/plugin-typescript` | CommonJS, ESM facades and declarations | MIT |
|
|
11
|
+
| `typescript` | Strict implementation and consumer checks | Apache-2.0 |
|
|
12
|
+
| `tslib` | Build-time compiler helpers | 0BSD |
|
|
13
|
+
| `@types/node` | Pinned runtime types | MIT |
|
|
14
|
+
| `eslint`, `typescript-eslint` | Source and tooling lint | MIT |
|
|
15
|
+
| `vitest`, `@vitest/coverage-v8` | Unit tests and coverage | MIT |
|
|
16
|
+
| `semantic-release` | Standard version, tag and release orchestration | MIT |
|
|
17
|
+
| `@semantic-release/commit-analyzer`, `@semantic-release/release-notes-generator` | Commit classification and release notes | MIT |
|
|
18
|
+
| `@semantic-release/npm`, `@semantic-release/github` | Official npm/GitHub publishing | MIT |
|
|
19
|
+
| `npm-undici-patch`, `npm-ip-address-patch` | Exact upstream fixes for npm's bundled development dependencies | MIT |
|
|
20
|
+
|
|
21
|
+
## Release tooling
|
|
22
|
+
|
|
23
|
+
The user selected standard semantic-release on main instead of maintaining a
|
|
24
|
+
custom staging/finalization lifecycle. The official engine and plugins provide
|
|
25
|
+
the release conventions and integrations that would otherwise need custom code.
|
|
26
|
+
They are pinned to 25.0.9 (engine), 13.2.0 (npm), and 12.0.10 (GitHub), alongside
|
|
27
|
+
the existing analysis/notes plugins. npm is pinned transitively to 11.21.1 so its
|
|
28
|
+
bundled implementation remains reviewable.
|
|
29
|
+
|
|
30
|
+
The temporary development aliases resolve to upstream `undici@6.29.1` and
|
|
31
|
+
`ip-address@10.7.5`. Both have no runtime dependencies or registry install hooks
|
|
32
|
+
and support the pinned Node runtime. The root postinstall hook copies their
|
|
33
|
+
locked registry contents into npm's bundle; see the checks and removal procedure
|
|
34
|
+
in [release security](release-security.md#temporary-npm-bundle-repair). Upstream
|
|
35
|
+
sources are [Undici](https://github.com/nodejs/undici/releases/tag/v6.29.1) and
|
|
36
|
+
[ip-address](https://github.com/beaugunderson/ip-address/releases/tag/v10.7.5).
|
|
37
|
+
|
|
38
|
+
Canonical sources are [semantic-release](https://github.com/semantic-release/semantic-release),
|
|
39
|
+
[npm plugin](https://github.com/semantic-release/npm) and
|
|
40
|
+
[GitHub plugin](https://github.com/semantic-release/github). Distributed artifacts
|
|
41
|
+
declare MIT, have no install hooks, and expose npm provenance attestations.
|
|
42
|
+
The packages share four listed maintainers and each receives over 12 million
|
|
43
|
+
monthly npm downloads; published updates support the pinned Node runtime.
|
|
44
|
+
Registry signatures and attestations must be verified on changes. Public npm
|
|
45
|
+
metadata does not establish individual maintainer MFA or complete account
|
|
46
|
+
ownership history; provenance and the existing official namespace are the
|
|
47
|
+
available trust evidence.
|
|
48
|
+
|
|
49
|
+
The engine/plugin tree invokes Git and npm, reads/writes repository/package
|
|
50
|
+
files and contacts GitHub/npm. It runs with release authority only after the
|
|
51
|
+
protected merge. The complete installed tree remains subject to the blocking
|
|
52
|
+
audit; adoption does not authorize accepting an advisory. Bundled npm components
|
|
53
|
+
must be reviewed on disk, not just through root overrides. See
|
|
54
|
+
[release security](release-security.md).
|
|
55
|
+
|
|
56
|
+
Maintainer `titan-ron` owns updates, advisory review and removal. Replacing this
|
|
57
|
+
toolchain means changing release.config.mjs and the trusted release job; it does
|
|
58
|
+
not alter the library runtime. Use the previous explicit workflow only through
|
|
59
|
+
a reviewed change if upstream becomes unsuitable. Keep review evidence in PRs.
|
|
60
|
+
|
|
61
|
+
The Doppler CLI is separately installed and managed by the user. Rollup uses
|
|
62
|
+
platform-specific optional binaries; preserve clean Linux/macOS install checks.
|
|
63
|
+
The optional fsevents lock metadata can advertise an install script even when
|
|
64
|
+
its reviewed archive contains neither an install hook nor binding.gyp.
|
|
65
|
+
|
|
66
|
+
Run `npm ci`, `npm run audit`, `npm audit signatures`, and `npm run verify`.
|
|
67
|
+
Official GitHub actions use exact release tags under the repository publisher
|
|
68
|
+
policy; other remote actions require full SHAs.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Maintainer guide
|
|
2
2
|
|
|
3
|
-
Start with [AGENTS.md](https://github.com/ciqol/resenv/blob/
|
|
3
|
+
Start with [AGENTS.md](https://github.com/ciqol/resenv/blob/main/AGENTS.md) for repository policy and
|
|
4
4
|
[CONTRIBUTING.md](../CONTRIBUTING.md) for setup and verification. Work in an
|
|
5
5
|
isolated task worktree on a `titan/*` branch. Authenticate as `titan-ron` for
|
|
6
|
-
[ciqol/resenv](https://github.com/ciqol/resenv); `
|
|
6
|
+
[ciqol/resenv](https://github.com/ciqol/resenv); `main` is the default and sole
|
|
7
7
|
release branch.
|
|
8
8
|
|
|
9
9
|
Inspect current Git status, branches, push remote and recent commits before
|
|
@@ -17,8 +17,8 @@ credentials between sessions.
|
|
|
17
17
|
| [Doppler](doppler.md) | CLI authentication, lookup, migration and platform limits |
|
|
18
18
|
| [Build](build.md) | Module formats, declarations, archive and CI contract |
|
|
19
19
|
| [Dependencies](dependencies.md) | Tool rationale, installation and update policy |
|
|
20
|
-
| [Releasing](releasing.md) |
|
|
21
|
-
| [Release security](release-security.md) |
|
|
20
|
+
| [Releasing](releasing.md) | PR approval, main releases and recovery |
|
|
21
|
+
| [Release security](release-security.md) | Dependency audit and release-tool review deadline |
|
|
22
22
|
| [Security](../SECURITY.md) | Trust boundaries and private vulnerability reporting |
|
|
23
23
|
|
|
24
24
|
## Code map
|
|
@@ -31,9 +31,10 @@ credentials between sessions.
|
|
|
31
31
|
| `src/commands.ts` | Explicit shell substitution and process limits |
|
|
32
32
|
| `bin/resenv.ts` | Child-process CLI |
|
|
33
33
|
| `rollup.config.mjs`, `scripts/build.mjs` | CJS implementation, ESM facades, types and manifest |
|
|
34
|
-
| `
|
|
35
|
-
| `scripts/
|
|
36
|
-
|
|
|
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 |
|
|
37
38
|
|
|
38
39
|
Keep docs focused on current contracts, decisions and procedures. Put per-run
|
|
39
40
|
test results, benchmarks, audit snapshots and session history in PRs or CI.
|
package/docs/release-security.md
CHANGED
|
@@ -1,70 +1,64 @@
|
|
|
1
1
|
# Release-tool security
|
|
2
2
|
|
|
3
|
-
Maintainer: `titan-ron`.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
8
|
|
|
9
|
-
|
|
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.
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
directly. It reads Git history and published beta tags without GitHub write,
|
|
13
|
-
npm or OIDC credentials. The full `semantic-release` engine and its publishing
|
|
14
|
-
plugins are unnecessary for this beta-only workflow.
|
|
15
|
+
## Publishing authority
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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.
|
|
22
23
|
|
|
23
|
-
The
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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.
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
installed development tree. Moderate/high/critical findings must match an exact
|
|
30
|
-
advisory URL, development-only lockfile path, version and unexpired policy
|
|
31
|
-
entry. New advisories, changed paths, runtime occurrences and expired
|
|
32
|
-
exceptions fail. The retained exception entries do not authorize reinstalling
|
|
33
|
-
the excluded tools. Prefer an upstream fix or removing unused dependencies;
|
|
34
|
-
never broaden the policy to make a check pass.
|
|
31
|
+
## Dependency review
|
|
35
32
|
|
|
36
|
-
|
|
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.
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
the archive described by the verified candidate plan. It checks source identity
|
|
40
|
-
and hashes before invoking npm. Publication follows the [release runbook](releasing.md).
|
|
39
|
+
### Temporary npm bundle repair
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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.
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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.
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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.
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
Recheck platform npm before the deadline and remove obsolete exception entries
|
|
64
|
-
when upstream fixes or dependency removal make them unnecessary. Do not extend
|
|
65
|
-
the deadline or bypass executable controls to unblock publication.
|
|
66
|
-
|
|
67
|
-
Run `npm run audit`, `npm audit signatures` and `npm run verify`. Release tooling
|
|
68
|
-
specs cover absence/version guards, policy scope and expiry, adversarial commit
|
|
69
|
-
analysis, real Git release history and publisher isolation. Keep review evidence
|
|
70
|
-
in the PR and CI, and maintain this document as the current policy.
|
|
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.
|
package/docs/releasing.md
CHANGED
|
@@ -1,154 +1,78 @@
|
|
|
1
1
|
# Releases
|
|
2
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
|
-
|
|
28
|
-
1.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
requires npm tags `beta` and `latest` to point to that version before creating
|
|
46
|
-
its Git tag and GitHub prerelease. It does not stage or publish the package again.
|
|
47
|
-
|
|
48
|
-
Pushes, PRs and dispatches with `publish: false` cannot stage a package. Release
|
|
49
|
-
jobs are serialized and not cancelled. Artifacts last seven days. A fresh
|
|
50
|
-
workflow run is not a substitute for rerunning the original release job when
|
|
51
|
-
recovering an already staged/published candidate.
|
|
52
|
-
|
|
53
|
-
## Required setup
|
|
54
|
-
|
|
55
|
-
The existing npm trusted publisher must match:
|
|
3
|
+
**Merge the PR to `main`; CI publishes the release.** There is no separate
|
|
4
|
+
approval button, npm staging queue or Finalize job. Manual workflow dispatch
|
|
5
|
+
runs checks only. The default branch requires a PR, current passing checks,
|
|
6
|
+
resolved review threads and squash merging, with no bypass actors. The sole
|
|
7
|
+
maintainer approves by merging; no second reviewer is required.
|
|
8
|
+
|
|
9
|
+
## Normal flow
|
|
10
|
+
|
|
11
|
+
CI audits dependencies, checks signatures, lint, types and coverage, builds
|
|
12
|
+
once, and tests the packed build across Linux Node 20/22/24 and macOS Node 24.
|
|
13
|
+
After a merge, the protected release job downloads that build and invokes
|
|
14
|
+
standard semantic-release. The official npm plugin prepares the release
|
|
15
|
+
version and archive; consumer checks run again on the final package. The
|
|
16
|
+
official npm and GitHub plugins publish to npm `latest` and create the GitHub
|
|
17
|
+
release. No source is rebuilt during release.
|
|
18
|
+
|
|
19
|
+
Conventional Commits determine releases: fixes and performance changes bump
|
|
20
|
+
patch, features bump minor, and breaking changes bump minor while the package
|
|
21
|
+
remains below 1.0. Docs and maintenance commits alone do not trigger a release.
|
|
22
|
+
Squash PR titles must follow that convention. `0.x.x` denotes initial
|
|
23
|
+
development, not a SemVer prerelease; published versions have no beta suffix.
|
|
24
|
+
A guard blocks 1.0 until that transition is reviewed explicitly.
|
|
25
|
+
|
|
26
|
+
## Initial 0.1.0 release
|
|
27
|
+
|
|
28
|
+
semantic-release starts at 1.0.0 when no regular release tag exists. To preserve
|
|
29
|
+
0.x numbering without a fake tag, the first enabled main release publishes the
|
|
30
|
+
tested `0.1.0` archive through npm OIDC and records its real tag and GitHub
|
|
31
|
+
release. Thereafter the normal engine uses that baseline. Existing beta tags
|
|
32
|
+
and npm versions remain historical; the `beta` channel is not updated.
|
|
33
|
+
|
|
34
|
+
## Setup
|
|
35
|
+
|
|
36
|
+
- Default/release branch: `main`, protected by PRs and the actual CI/CodeQL checks.
|
|
37
|
+
- npm trusted publisher: `ciqol/resenv`, `ci.yml`, environment `release`, with
|
|
38
|
+
**direct publish** permission. Stage-only permission cannot run this flow.
|
|
39
|
+
- GitHub environment `release`: allow only `main`, with no required reviewers.
|
|
40
|
+
- `RELEASE_ENABLED=true` only after protection, the npm publisher and dependency
|
|
41
|
+
audit are verified. The maintainer manages the npm setting.
|
|
42
|
+
|
|
43
|
+
On npmjs.com, open **@ciqol/resenv → Settings → Trusted publishing** and
|
|
44
|
+
configure its GitHub Actions publisher with these exact values:
|
|
56
45
|
|
|
57
46
|
| Field | Value |
|
|
58
47
|
| --- | --- |
|
|
59
|
-
|
|
|
60
|
-
| Organization | `ciqol` |
|
|
48
|
+
| Organization or user | `ciqol` |
|
|
61
49
|
| Repository | `resenv` |
|
|
62
|
-
| Workflow filename | `ci.yml` |
|
|
63
|
-
| Environment | `release` |
|
|
64
|
-
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
to
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
##
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
These are maintainer review/approval commands; the archive is built and staged
|
|
94
|
-
by GitHub Actions. OIDC cannot perform the approval step. Wait for npm scanning
|
|
95
|
-
and public availability, then update the default install tag in the maintainer
|
|
96
|
-
session:
|
|
97
|
-
|
|
98
|
-
```sh
|
|
99
|
-
npm dist-tag add @ciqol/resenv@<approved-version> latest
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
Rerun the original release job to record the release. Verify the npm version,
|
|
103
|
-
`beta` and `latest` tags, archive integrity, provenance and GitHub
|
|
104
|
-
prerelease. Never infer success from a staging receipt alone.
|
|
105
|
-
|
|
106
|
-
For a hosted rehearsal, leave the staging input off. Local verification is:
|
|
107
|
-
|
|
108
|
-
```sh
|
|
109
|
-
npm ci
|
|
110
|
-
npm run audit
|
|
111
|
-
npm run release:check
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
None of these commands publishes. The planner can generate a non-publishing
|
|
115
|
-
plan with `node scripts/release-plan.mjs /absolute/path/to/candidate-directory`.
|
|
116
|
-
|
|
117
|
-
## Recovery and old versions
|
|
118
|
-
|
|
119
|
-
A failed stage operation creates no Git tag or GitHub release. Check npm before
|
|
120
|
-
retrying an ambiguous outcome: a staged version reserves its version number.
|
|
121
|
-
Do not attempt to stage it again while awaiting approval. Approve or reject the
|
|
122
|
-
existing stage through npm. Rejection requires a reviewed replacement candidate.
|
|
123
|
-
|
|
124
|
-
The original release job accepts an existing public version only if integrity
|
|
125
|
-
matches its candidate. A conflicting archive, changed beta head or conflicting
|
|
126
|
-
Git tag stops recovery. Keep the beta branch at the reviewed commit until the
|
|
127
|
-
release is recorded. If its artifact expires, review recovery separately.
|
|
128
|
-
|
|
129
|
-
Retain the `0.0.0-stage` placeholder until a functional beta is publicly
|
|
130
|
-
available and verified.
|
|
131
|
-
With explicit authorization, remove that exact placeholder version and check
|
|
132
|
-
remaining versions and tags. Never unpublish the whole package. npm's unpublish
|
|
133
|
-
policy still applies; deleted versions cannot be reused.
|
|
134
|
-
See [npm's policy](https://docs.npmjs.com/policies/unpublish/).
|
|
135
|
-
|
|
136
|
-
## Security and platform limits
|
|
137
|
-
|
|
138
|
-
The runtime package has no npm dependencies or advisory exceptions. Installed
|
|
139
|
-
runtime and development audits must pass with the unused engine/publisher peer graph
|
|
140
|
-
omitted. Audit and planning enforce that absence; the lockfile still records
|
|
141
|
-
the uninstalled peers. The existing November 9, 2026 review deadline remains
|
|
142
|
-
for the policy and separately reviewed platform npm. The privileged job does
|
|
143
|
-
not install release-tool modules. See [release security](release-security.md).
|
|
144
|
-
|
|
145
|
-
Doppler is the only built-in cloud provider. Authentication is owned by the
|
|
146
|
-
Doppler CLI; resenv reads its existing directory-scoped token or accepts
|
|
147
|
-
`DOPPLER_TOKEN` for unattended use. It does not manage native credential storage
|
|
148
|
-
or browser login. Standard Windows CLI discovery has injected coverage but no
|
|
149
|
-
native Windows end-to-end verification. Commands require explicit opt-in.
|
|
150
|
-
Dotenvx ciphertext is left unchanged. See [Security](../SECURITY.md).
|
|
151
|
-
|
|
152
|
-
Sources: [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/),
|
|
153
|
-
[staged publishing](https://docs.npmjs.com/cli/v11/commands/npm-stage/),
|
|
154
|
-
[semantic-release branching](https://semantic-release.org/foundation/workflow-configuration/).
|
|
50
|
+
| Workflow filename | `ci.yml` (filename only) |
|
|
51
|
+
| Environment name | `release` |
|
|
52
|
+
| Allow npm publish | Enabled |
|
|
53
|
+
| Allow npm dist-tag | Not needed for this single-branch release flow |
|
|
54
|
+
|
|
55
|
+
Save the configuration and complete npm's confirmation if prompted. Staging is
|
|
56
|
+
always allowed; enabling direct publishing is the required change. The branch
|
|
57
|
+
restriction lives in GitHub's `release` environment, which already allows only
|
|
58
|
+
`main`. Keep account 2FA and the existing token restrictions; no npm token is
|
|
59
|
+
needed. See [npm's trusted-publishing guide](https://docs.npmjs.com/trusted-publishers/).
|
|
60
|
+
|
|
61
|
+
Never publish from a developer machine, configure a permanent npm publishing
|
|
62
|
+
token, or request local npm login. Local `npm run release:check` is read-only
|
|
63
|
+
with respect to publication. Only the trusted main push can pass the release
|
|
64
|
+
guard. A merge does not waive a failing audit or the security review expiry.
|
|
65
|
+
|
|
66
|
+
## Failures
|
|
67
|
+
|
|
68
|
+
Inspect the failed run, npm version and GitHub tag before retrying. The standard
|
|
69
|
+
engine creates its tag before calling publishers; a failed publication may
|
|
70
|
+
therefore leave a tag or partial release. Rerunning is not a general repair for
|
|
71
|
+
that state. Recover the intended version using its original source and archive
|
|
72
|
+
after maintainer review; do not retag different code or silently replace a
|
|
73
|
+
published version. The initial bootstrap creates its tag after npm succeeds;
|
|
74
|
+
if GitHub recording fails, recover that published baseline before another run.
|
|
75
|
+
|
|
76
|
+
No workflow automatically deletes tags, releases or npm versions. Existing
|
|
77
|
+
beta versions without matching GitHub releases need separate recovery from
|
|
78
|
+
their original evidence. See [release security](release-security.md).
|
|
@@ -1,139 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"expires": "2026-11-09T00:00:00.000Z",
|
|
3
3
|
"owner": "titan-ron",
|
|
4
|
-
"scope": "
|
|
5
|
-
"exceptions": [
|
|
6
|
-
{
|
|
7
|
-
"advisory": "https://github.com/advisories/GHSA-q2hr-2g5m-vwhr",
|
|
8
|
-
"package": "brace-expansion",
|
|
9
|
-
"versions": [
|
|
10
|
-
"5.0.9"
|
|
11
|
-
],
|
|
12
|
-
"nodes": [
|
|
13
|
-
"node_modules/npm/node_modules/brace-expansion"
|
|
14
|
-
],
|
|
15
|
-
"reason": "Bundled inside npm for the unselected @semantic-release/npm plugin. The planner blocks loading that plugin, the GitHub plugin and bundled npm; the publisher does not install release dependencies."
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"advisory": "https://github.com/advisories/GHSA-qhr7-859c-m2p7",
|
|
19
|
-
"package": "brace-expansion",
|
|
20
|
-
"versions": [
|
|
21
|
-
"5.0.9"
|
|
22
|
-
],
|
|
23
|
-
"nodes": [
|
|
24
|
-
"node_modules/npm/node_modules/brace-expansion"
|
|
25
|
-
],
|
|
26
|
-
"reason": "Bundled inside npm for the unselected @semantic-release/npm plugin. The planner blocks loading that plugin, the GitHub plugin and bundled npm; the publisher does not install release dependencies."
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"advisory": "https://github.com/advisories/GHSA-6j4f-fj2g-mc7p",
|
|
30
|
-
"package": "brace-expansion",
|
|
31
|
-
"versions": [
|
|
32
|
-
"5.0.9"
|
|
33
|
-
],
|
|
34
|
-
"nodes": [
|
|
35
|
-
"node_modules/npm/node_modules/brace-expansion"
|
|
36
|
-
],
|
|
37
|
-
"reason": "Bundled inside npm for the unselected @semantic-release/npm plugin. The planner blocks loading that plugin, the GitHub plugin and bundled npm; the publisher does not install release dependencies."
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
"advisory": "https://github.com/advisories/GHSA-vfj7-8cjw-p6xm",
|
|
41
|
-
"package": "braces",
|
|
42
|
-
"versions": [
|
|
43
|
-
"3.0.3"
|
|
44
|
-
],
|
|
45
|
-
"nodes": [
|
|
46
|
-
"node_modules/braces"
|
|
47
|
-
],
|
|
48
|
-
"reason": "The planner blocks every braces callable and only uses micromatch matching, which delegates to picomatch."
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
"advisory": "https://github.com/advisories/GHSA-ch52-4w7c-c8xp",
|
|
52
|
-
"package": "http-cache-semantics",
|
|
53
|
-
"versions": [
|
|
54
|
-
"4.2.0"
|
|
55
|
-
],
|
|
56
|
-
"nodes": [
|
|
57
|
-
"node_modules/npm/node_modules/http-cache-semantics"
|
|
58
|
-
],
|
|
59
|
-
"reason": "Bundled inside npm for the unselected @semantic-release/npm plugin. The planner blocks loading that plugin, the GitHub plugin and bundled npm; the publisher does not install release dependencies."
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
"advisory": "https://github.com/advisories/GHSA-rpw4-54j3-4h4q",
|
|
63
|
-
"package": "ip-address",
|
|
64
|
-
"versions": [
|
|
65
|
-
"10.5.0"
|
|
66
|
-
],
|
|
67
|
-
"nodes": [
|
|
68
|
-
"node_modules/npm/node_modules/ip-address"
|
|
69
|
-
],
|
|
70
|
-
"reason": "Bundled inside npm for the unselected @semantic-release/npm plugin. The planner blocks loading that plugin, the GitHub plugin and bundled npm; the publisher does not install release dependencies."
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"advisory": "https://github.com/advisories/GHSA-2vr4-cq9g-pvrc",
|
|
74
|
-
"package": "ip-address",
|
|
75
|
-
"versions": [
|
|
76
|
-
"10.5.0"
|
|
77
|
-
],
|
|
78
|
-
"nodes": [
|
|
79
|
-
"node_modules/npm/node_modules/ip-address"
|
|
80
|
-
],
|
|
81
|
-
"reason": "Bundled inside npm for the unselected @semantic-release/npm plugin. The planner blocks loading that plugin, the GitHub plugin and bundled npm; the publisher does not install release dependencies."
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
"advisory": "https://github.com/advisories/GHSA-j6r3-76f7-8jcv",
|
|
85
|
-
"package": "ip-address",
|
|
86
|
-
"versions": [
|
|
87
|
-
"10.5.0"
|
|
88
|
-
],
|
|
89
|
-
"nodes": [
|
|
90
|
-
"node_modules/npm/node_modules/ip-address"
|
|
91
|
-
],
|
|
92
|
-
"reason": "Bundled inside npm for the unselected @semantic-release/npm plugin. The planner blocks loading that plugin, the GitHub plugin and bundled npm; the publisher does not install release dependencies."
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
"advisory": "https://github.com/advisories/GHSA-h3mg-xc3c-68pw",
|
|
96
|
-
"package": "ip-address",
|
|
97
|
-
"versions": [
|
|
98
|
-
"10.5.0"
|
|
99
|
-
],
|
|
100
|
-
"nodes": [
|
|
101
|
-
"node_modules/npm/node_modules/ip-address"
|
|
102
|
-
],
|
|
103
|
-
"reason": "Bundled inside npm for the unselected @semantic-release/npm plugin. The planner blocks loading that plugin, the GitHub plugin and bundled npm; the publisher does not install release dependencies."
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
"advisory": "https://github.com/advisories/GHSA-rj75-hqrm-r3gf",
|
|
107
|
-
"package": "postcss-selector-parser",
|
|
108
|
-
"versions": [
|
|
109
|
-
"7.1.4"
|
|
110
|
-
],
|
|
111
|
-
"nodes": [
|
|
112
|
-
"node_modules/npm/node_modules/postcss-selector-parser"
|
|
113
|
-
],
|
|
114
|
-
"reason": "Bundled inside npm for the unselected @semantic-release/npm plugin. The planner blocks loading that plugin, the GitHub plugin and bundled npm; the publisher does not install release dependencies."
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
"advisory": "https://github.com/advisories/GHSA-3wwx-pv8p-q78v",
|
|
118
|
-
"package": "undici",
|
|
119
|
-
"versions": [
|
|
120
|
-
"6.28.0"
|
|
121
|
-
],
|
|
122
|
-
"nodes": [
|
|
123
|
-
"node_modules/npm/node_modules/undici"
|
|
124
|
-
],
|
|
125
|
-
"reason": "Bundled inside npm for the unselected @semantic-release/npm plugin. The planner blocks loading that plugin, the GitHub plugin and bundled npm; the publisher does not install release dependencies."
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
"advisory": "https://github.com/advisories/GHSA-rfgv-xxqx-mfg5",
|
|
129
|
-
"package": "undici",
|
|
130
|
-
"versions": [
|
|
131
|
-
"6.28.0"
|
|
132
|
-
],
|
|
133
|
-
"nodes": [
|
|
134
|
-
"node_modules/npm/node_modules/undici"
|
|
135
|
-
],
|
|
136
|
-
"reason": "Bundled inside npm for the unselected @semantic-release/npm plugin. The planner blocks loading that plugin, the GitHub plugin and bundled npm; the publisher does not install release dependencies."
|
|
137
|
-
}
|
|
138
|
-
]
|
|
4
|
+
"scope": "No advisory exceptions; the complete installed tree must pass npm audit at moderate severity.",
|
|
5
|
+
"exceptions": []
|
|
139
6
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ciqol/resenv",
|
|
3
|
-
"version": "0.1.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Replace environment references with their resolved values at application startup",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public",
|
|
8
|
-
"tag": "
|
|
8
|
+
"tag": "latest",
|
|
9
9
|
"registry": "https://registry.npmjs.org/"
|
|
10
10
|
},
|
|
11
11
|
"repository": {
|