@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 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/beta/AGENTS.md) before editing or releasing.
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
- Releases start at `0.1.0-beta.1` on the sole branch `beta`, using npm tags
10
- `beta` and `latest` for the same tested version. Semantic-release's official
11
- commit-analysis and release-notes plugins select releasable changes and generate
12
- notes; actual beta tags supply the next
13
- prerelease counter. The root and ordinary local builds remain private prototypes.
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; fork PRs retain the local gate and reports but cannot upload. CLI lookup
86
- checks use injected helpers and temporary dummy executables; they never access
87
- a developer credential store or authenticated provider session.
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
- `beta` channel and avoid unpublished or local-archive installation guidance.
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-beta.1.tgz
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. This is an experimental beta, published on npm's
24
- `beta` channel.
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 the beta in your application project:
30
+ Install in your application project:
29
31
 
30
32
  ```sh
31
- npm install --save-exact @ciqol/resenv@beta
33
+ npm install --save-exact @ciqol/resenv
32
34
  ```
33
35
 
34
- This records the selected beta version in your project's manifest and lockfile.
35
- The `latest` tag points to the same beta; omitting `@beta` installs it too.
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`. The CI build accepts a validated
94
- release plan and sets its computed version, removing `private` before the final
95
- archive is packed and tested. The development root stays private. Only the
96
- manual release workflow stages that tested archive for npm approval; see
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 `build` job uses normal npm lifecycle behavior, checks dependency advisories and
118
- signatures, runs typed lint, implementation/spec checks and Vitest source coverage,
119
- builds once and uploads the packed
120
- archive. The `test` matrix downloads that artifact, verifies the installed
121
- package, extracts the same build
122
- for the process tests, and never recompiles it. The matrix checks Node 20
123
- and 22 on Linux plus the `.nvmrc` version on Linux and macOS.
124
-
125
- Build and test jobs have read-only repository permissions and receive no application or
126
- registry secrets. Missing artifacts and digest mismatches fail the run. The
127
- archive is retained for seven days for maintainer review. A separate release
128
- job requires manual dispatch on `beta`, the protected `release` environment and
129
- all candidate checks. Hosted results must be observed before treating the workflow definition
130
- as a passing CI run.
131
-
132
- Official `actions/*` and `github/*` actions use exact release tags under the
133
- repository's GitHub publisher trust policy. Other remote actions require full
134
- commit SHAs. Installs use normal npm lifecycle behavior, and dependency updates
135
- require an install-hook review. Build commands run explicitly.
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.
@@ -1,61 +1,68 @@
1
1
  # Dependencies
2
2
 
3
- resenv has no runtime npm dependencies. Build, test and release tools are
4
- development-only and excluded from the consumer archive. Exact versions live
5
- in the [source manifest](https://github.com/ciqol/resenv/blob/beta/package.json);
6
- the lockfile pins their resolved artifacts.
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` | Compile TypeScript, preserve the module graph and generate declarations | MIT |
13
- | `typescript` | Strict implementation, spec and consumer type checks | Apache-2.0 |
14
- | `tslib` | Helpers used by the TypeScript build plugin | 0BSD |
15
- | `@types/node` | Node platform types for the pinned development runtime | MIT |
16
- | `eslint`, `typescript-eslint` | Lint source and tooling, including rules that use type information | MIT |
17
- | `vitest`, `@vitest/coverage-v8` | Colocated unit tests and source coverage | MIT |
18
- | `@semantic-release/commit-analyzer`, `@semantic-release/release-notes-generator` | Official Conventional Commit classification and release notes | MIT |
19
-
20
- The [Doppler CLI](doppler.md) is a separately installed authentication helper,
21
- owned and updated by the user. resenv does not download or vendor it. Supplying
22
- `DOPPLER_TOKEN` avoids the CLI dependency.
23
-
24
- ## Installation policy
25
-
26
- Use the Node version in `.nvmrc`, `npm ci` and normal npm lifecycle behavior.
27
- Do not disable scripts globally. Review published install hooks and implicit
28
- native builds when dependencies change. Rollup uses platform-specific optional
29
- binaries; keep the Linux/macOS clean-install checks. The lockfile marks optional
30
- `fsevents` as having an install script, although its reviewed artifact has no
31
- install hook or `binding.gyp`; npm may warn about that metadata.
32
-
33
- The committed `.npmrc` sets `omit=peer`. The two release plugins export the
34
- standalone functions the planner uses, but declare the full `semantic-release`
35
- engine as a peer for their usual integration. Omitting that unused peer also
36
- keeps its npm/GitHub publisher dependency graph off disk. Audit and planning
37
- guards require those modules to be unresolvable from the project and both
38
- plugins. See [release security](release-security.md).
39
-
40
- npm still resolves omitted peers into the lockfile. `npm ls` reports the
41
- deliberately missing engine peers; an audit with `--include=peer` can report
42
- vulnerabilities in those uninstalled entries. Do not conceal the peer warning
43
- with `--force`, `--legacy-peer-deps` or an alias package. Restoring the engine
44
- requires a dependency/security review and a deliberate guard change.
45
-
46
- ## Updating dependencies
47
-
48
- Maintainers own dependency admission and updates. Keep direct versions exact
49
- and review the manifest and lockfile diff, upstream source and release notes,
50
- distributed licenses, provenance, advisories and install hooks. Keep Vitest and
51
- its coverage provider compatible. Changes to release plugins also require
52
- reviewing their standalone exports and executable guards.
53
-
54
- Run `npm ci`, `npm run audit`, `npm audit signatures` and `npm run verify`.
55
- Review hosted matrix checks before release. Record review evidence and check
56
- results in the PR and CI; update this guide only when a lasting choice or
57
- installation requirement changes. Do not append dated intake or test logs.
58
-
59
- Official `actions/*` and `github/*` actions use exact release tags under the
60
- repository's GitHub publisher trust policy. Other remote actions require full
61
- commit SHAs. Review action source, permissions and license when updating them.
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/beta/AGENTS.md) for repository policy and
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); `beta` is the default and sole
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) | Candidate checks, npm staging/approval and recovery |
21
- | [Release security](release-security.md) | Isolation guards, advisory policy and platform review deadline |
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
- | `scripts/release-plan.mjs` | Official release plugins and beta counter |
35
- | `scripts/publish.mjs` | Tested-archive staging and verified release recording |
36
- | `.github/workflows/ci.yml` | Build once, archive matrix tests and manual release |
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.
@@ -1,70 +1,64 @@
1
1
  # Release-tool security
2
2
 
3
- Maintainer: `titan-ron`. Runtime dependencies have no advisory exceptions.
4
- The executable development policy is [security-exceptions.json](security-exceptions.json).
5
- Its review expires **November 9, 2026 at 00:00 UTC**. This is a project review
6
- deadline, also enforced by the publisher for platform npm; removing unused
7
- development tools does not extend it.
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
- ## Release planning
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
- The planner calls the official commit-analysis and release-notes plugins
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
- The committed peer-omission policy keeps the engine, `@semantic-release/npm`,
17
- `@semantic-release/github` and their npm module off disk. Before auditing or
18
- planning, `scripts/release-guards.mjs` requires that none resolve from the
19
- project or either selected plugin. Its planner hook also rejects bare and
20
- resolved imports of those tools. An audit explicitly including omitted peers
21
- can still report their locked entries; see [installation policy](dependencies.md).
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 guard pins both plugins, micromatch and braces. It replaces every callable
24
- braces export with a throwing guard before loading the plugins. The selected
25
- micromatch matching calls use picomatch; vulnerable brace expansion must never
26
- execute. Version drift fails until the guards are reviewed.
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
- `npm run audit` checks runtime dependencies without exceptions, then the
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
- ## Publishing platform
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
- The privileged publisher installs no release-tool dependencies and accepts only
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
- The platform is pinned to Node.js 24.19.0 and its npm 11.17.0. Platform npm has
43
- separately reviewed bundled-component risks; omitting development peers does
44
- not fix those components. `scripts/publish.mjs` rejects platform version drift
45
- and an expired review, including on a failed-job retry.
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
- The staging command accepts a fixed tarball and HTTPS npm registry, with no
48
- package lifecycle scripts in the generated manifest. It runs with a fresh home,
49
- configuration and cache, strips proxy/token/arbitrary npm configuration, and
50
- uses the protected workflow's OIDC identity. It accepts no login, shell,
51
- selector or arbitrary URL input. Registry and signing services remain trusted
52
- inputs. These controls bound exposure; they do not patch the platform CLI.
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
- The publisher validates the staging receipt's package name, version and
55
- integrity. npm approval publishes the stage. A retry verifies the public
56
- archive's integrity and both npm tags before recording the Git tag/release.
57
- No tag is created for a pending stage.
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
- ## Reviewing changes
60
-
61
- Review the actual published artifacts, including bundled copies; patching a
62
- standalone package does not establish that npm's bundled copy is fixed.
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
- ## Versions
4
-
5
- `beta` is the sole release and default branch. Releases start at `0.1.0-beta.1`
6
- and use npm tags `beta` and `latest`, both pointing to the same tested beta.
7
-
8
- The planner uses semantic-release's official commit-analysis and release-notes
9
- plugins. Conventional Commits decide whether changes need a release. Each
10
- releasable update increments the counter from the latest reachable
11
- `v0.1.0-beta.N` tag; docs-only changes do not release. Breaking changes during
12
- this experimental line also increment the beta counter. Selecting a stable
13
- line or another base version is a separate release-policy change.
14
-
15
- The full semantic-release engine requires a normal release branch and defaults
16
- to a first version of 1.0.0. Using its official plugins directly preserves the
17
- requested sole-beta-branch setup without inventing a stable branch or a release
18
- that never happened. The base line is declared in `release.config.mjs`.
19
-
20
- The development manifest and ordinary local builds stay private. Only a valid
21
- release plan sets the distribution version and removes `private` before packing.
22
- Never edit a generated manifest or overwrite a previously shared archive.
23
-
24
- ## CI pipeline
25
-
26
- The [CI workflow](https://github.com/ciqol/resenv/blob/beta/.github/workflows/ci.yml) builds one archive:
27
-
28
- 1. **Build:** normal npm installation, runtime/development audits, registry
29
- signatures, lint, strict types and colocated Vitest specs. The read-only
30
- planner generates the beta version and notes from Git history. Rollup builds
31
- it once; npm packs it and records SHA-256 and SHA-512 integrity.
32
- 2. **Consumers:** Linux Node 20, 22 and the pinned Node 24, plus macOS Node 24,
33
- install and test the same archive. Checks cover ESM, CJS, types, preloads,
34
- CLI, literal secret output and failure boundaries. Nothing is rebuilt.
35
- 3. **Release:** a manual dispatch from `beta` with `publish: true`, after every
36
- check passes. The protected job verifies hashes, workflow identity and the
37
- current branch head. It installs no project dependencies and runs no package
38
- code. `npm stage publish` submits the exact archive through OIDC with
39
- provenance and the explicit `beta` tag. The job validates and saves npm's
40
- staging receipt; no Git tag or GitHub release is created yet.
41
- 4. **Approval and recording:** the maintainer reviews and approves the staged
42
- package in npm using interactive 2FA. Wait for npm to make it available,
43
- update `latest` to the approved version, then rerun the original release job.
44
- It verifies the published integrity against the original tested archive and
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
- | Provider | GitHub Actions |
60
- | Organization | `ciqol` |
48
+ | Organization or user | `ciqol` |
61
49
  | Repository | `resenv` |
62
- | Workflow filename | `ci.yml` |
63
- | Environment | `release` |
64
- | Permission | `npm stage publish` |
65
-
66
- No permanent npm token or direct-publish permission is needed. The pinned
67
- Node 24.19.0/npm 11.17.0 platform includes staged publishing. New trusted
68
- publisher configurations must be validated by a successful CI operation before
69
- the deadline shown in npm settings.
70
-
71
- The GitHub environment `release` accepts only the `beta` branch and has no
72
- required GitHub reviewers. CI submits staged packages; the maintainer approves
73
- publication in npm. After reading back the branch policy and verifying npm
74
- setup, set Actions variable `RELEASE_ENABLED=true`. Leave it unset until then
75
- to prevent a dispatch from creating an unrestricted environment automatically.
76
- Environment creation or protection changes require explicit authorization.
77
-
78
- ## Run a beta release
79
-
80
- Open [CI](https://github.com/ciqol/resenv/actions/workflows/ci.yml), choose
81
- **Run workflow**, select `beta`, and enable the staging input. When build and
82
- consumer checks pass, the release job stages the archive without another GitHub
83
- approval. Its summary and the `resenv-stage` artifact contain the stage
84
- identifier and tested integrity.
85
-
86
- Review the staged package in npm, then approve it with the stage identifier:
87
-
88
- ```sh
89
- npm stage view <stage-id> --json
90
- npm stage approve <stage-id>
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": "Release planning only; runtime audit has no exceptions.",
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-beta.2",
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": "beta",
8
+ "tag": "latest",
9
9
  "registry": "https://registry.npmjs.org/"
10
10
  },
11
11
  "repository": {