@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/docs/releasing.md CHANGED
@@ -1,143 +1,78 @@
1
1
  # Releases
2
2
 
3
- ## Versions
4
-
5
- `beta` is the sole remote and default branch. Releases start at `0.1.0-beta.1`
6
- and use the npm `beta` tag. A beta tag is not promoted to `latest`.
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](../.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
- then rerun the original release job. It verifies the published integrity
44
- against the original tested archive before creating its Git tag and GitHub
45
- prerelease. It does not stage or publish the package again.
46
-
47
- Pushes, PRs and dispatches with `publish: false` cannot stage a package. Release
48
- jobs are serialized and not cancelled. Artifacts last seven days. A fresh
49
- workflow run is not a substitute for rerunning the original release job when
50
- recovering an already staged/published candidate.
51
-
52
- ## Required setup
53
-
54
- 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:
55
45
 
56
46
  | Field | Value |
57
47
  | --- | --- |
58
- | Provider | GitHub Actions |
59
- | Organization | `ciqol` |
48
+ | Organization or user | `ciqol` |
60
49
  | Repository | `resenv` |
61
- | Workflow filename | `ci.yml` |
62
- | Environment | `release` |
63
- | Permission | `npm stage publish` |
64
-
65
- No permanent npm token or direct-publish permission is needed. The pinned
66
- Node 24.19.0/npm 11.17.0 platform includes staged publishing. New trusted
67
- publisher configurations must be validated by a successful CI operation before
68
- the deadline shown in npm settings.
69
-
70
- The GitHub environment `release` accepts only the `beta` branch and has no
71
- required GitHub reviewers. CI submits staged packages; the maintainer approves
72
- publication in npm. After reading back the branch policy and verifying npm
73
- setup, set Actions variable `RELEASE_ENABLED=true`. Leave it unset until then
74
- to prevent a dispatch from creating an unrestricted environment automatically.
75
- Environment creation or protection changes require explicit authorization.
76
-
77
- ## Run the first beta
78
-
79
- Open [CI](https://github.com/ciqol/resenv/actions/workflows/ci.yml), choose
80
- **Run workflow**, select `beta`, and enable the staging input. When build and
81
- consumer checks pass, the release job stages the archive without another GitHub
82
- approval. Its summary and the `resenv-stage` artifact contain the stage
83
- identifier and tested integrity.
84
-
85
- Review the staged package in npm, then approve it with the stage identifier:
86
-
87
- ```sh
88
- npm stage view <stage-id> --json
89
- npm stage approve <stage-id>
90
- ```
91
-
92
- These are maintainer review/approval commands; the archive is built and staged
93
- by GitHub Actions. OIDC cannot perform the approval step. Wait for npm scanning
94
- and public availability, then rerun the original release job to record the tag.
95
- Verify the npm version, `beta` tag, archive integrity, provenance and GitHub
96
- prerelease. Never infer success from a staging receipt alone.
97
-
98
- For a hosted rehearsal, leave the staging input off. Local verification is:
99
-
100
- ```sh
101
- npm ci
102
- npm run audit
103
- npm run release:check
104
- ```
105
-
106
- None of these commands publishes. The planner can generate a non-publishing
107
- plan with `node scripts/release-plan.mjs /absolute/path/to/candidate-directory`.
108
-
109
- ## Recovery and old versions
110
-
111
- A failed stage operation creates no Git tag or GitHub release. Check npm before
112
- retrying an ambiguous outcome: a staged version reserves its version number.
113
- Do not attempt to stage it again while awaiting approval. Approve or reject the
114
- existing stage through npm. Rejection requires a reviewed replacement candidate.
115
-
116
- The original release job accepts an existing public version only if integrity
117
- matches its candidate. A conflicting archive, changed beta head or conflicting
118
- Git tag stops recovery. Keep the beta branch at the reviewed commit until the
119
- release is recorded. If its artifact expires, review recovery separately.
120
-
121
- The maintainer removed the accidental `1.0.0` publication. Retain the
122
- `0.0.0-stage` placeholder until `0.1.0-beta.1` is publicly available and verified.
123
- With explicit authorization, remove that exact placeholder version and check
124
- remaining versions and tags. Never unpublish the whole package. npm's unpublish
125
- policy still applies; deleted versions cannot be reused.
126
- See [npm's policy](https://docs.npmjs.com/policies/unpublish/).
127
-
128
- ## Security and platform limits
129
-
130
- The runtime package has no npm dependencies or advisory exceptions. The
131
- release-tool tree has bounded, executable advisory exceptions expiring November
132
- 9, 2026; it is not vulnerability-free. The privileged job does not install that
133
- tree. See [release security](release-security.md).
134
-
135
- Doppler is the only built-in cloud provider. Fresh native browser login has not
136
- been verified end to end, Linux credential storage has mock coverage, and
137
- Windows native login/storage is not implemented. Explicit tokens and existing
138
- CLI credentials remain supported. Commands require explicit opt-in. Dotenvx
139
- ciphertext is left unchanged. See [Security](../SECURITY.md).
140
-
141
- Sources: [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/),
142
- [staged publishing](https://docs.npmjs.com/cli/v11/commands/npm-stage/),
143
- [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/doppler/auth.cjs CHANGED
@@ -1,125 +1,19 @@
1
1
  'use strict';
2
2
 
3
- var promises = require('node:timers/promises');
4
- var node_module = require('node:module');
5
3
  var errors = require('../errors.cjs');
6
- var values = require('../values.cjs');
7
4
  var http = require('./http.cjs');
8
5
  var system = require('./system.cjs');
9
6
 
10
- const manifest = node_module.createRequire(require('node:url').pathToFileURL(__filename).href)('@ciqol/resenv/package.json');
11
- if (!values.isRecord(manifest) || typeof manifest.version !== 'string')
12
- throw new Error('Invalid package version');
13
- const { version } = manifest;
14
- function credential(env, system$1 = system.createSystem()) {
7
+ function credential(env, system$1) {
15
8
  return Promise.resolve().then(() => {
16
- // An explicitly selected identity is never replaced after an API rejection.
9
+ // An explicit identity is never replaced after validation or API rejection.
17
10
  if (env.DOPPLER_TOKEN !== undefined)
18
11
  return http.validateToken(env.DOPPLER_TOKEN);
19
- let saved;
20
- try {
21
- saved = system$1.read();
22
- }
23
- catch (err) {
24
- if (!values.hasErrorCode(err, 'DOPPLER_KEYRING_UNAVAILABLE'))
25
- throw err;
26
- }
27
- if (saved)
28
- return saved;
29
- const token = system$1.cliToken();
12
+ const token = (system$1 || system.createSystem()).cliToken();
30
13
  if (token)
31
14
  return token;
32
- throw new errors.ResenvError('DOPPLER_AUTH_REQUIRED', 'Run resenv login doppler, or supply DOPPLER_TOKEN. Startup never opens a login prompt.');
15
+ throw new errors.ResenvError('DOPPLER_AUTH_REQUIRED', 'Run doppler login from your application directory, or supply DOPPLER_TOKEN. Startup never opens a login prompt.');
33
16
  });
34
17
  }
35
- async function login({ cli = false, noBrowser = false } = {}, { request = http.createClient(), system: system$1 = system.createSystem(), output = text => process.stderr.write(`${text}\n`), interactive = Boolean(process.stdin.isTTY && process.stderr.isTTY), env = process.env, sleep = promises.setTimeout, now = Date.now } = {}) {
36
- if (!interactive || env.CI)
37
- throw new errors.ResenvError('DOPPLER_INTERACTIVE_REQUIRED', 'Login requires an interactive local terminal outside CI. Supply DOPPLER_TOKEN for unattended runs.');
38
- if (env.DOPPLER_TOKEN !== undefined)
39
- throw new errors.ResenvError('DOPPLER_TOKEN_OVERRIDE', 'Unset DOPPLER_TOKEN before logging in; it overrides saved credentials.');
40
- const fallback = ({ storeUnavailable = false } = {}) => {
41
- output('Using Doppler CLI login.');
42
- system$1.cliLogin();
43
- if (system$1.canStore && !storeUnavailable) {
44
- // Keep the identity chosen by this login ahead of an older resenv token.
45
- try {
46
- system$1.write(http.validateToken(system$1.cliToken()));
47
- }
48
- catch {
49
- throw new errors.ResenvError('DOPPLER_KEYRING_UNAVAILABLE', 'CLI login completed, but resenv could not update its saved credential. Unlock the credential store and retry.');
50
- }
51
- }
52
- output('Done: Doppler CLI login completed.');
53
- return 'cli';
54
- };
55
- if (cli || !system$1.canStore)
56
- return fallback();
57
- // Check keyring access before creating an authorization session.
58
- try {
59
- system$1.read();
60
- }
61
- catch (err) {
62
- if (!values.hasErrorCode(err, 'DOPPLER_KEYRING_UNAVAILABLE'))
63
- throw err;
64
- return fallback({ storeUnavailable: true });
65
- }
66
- let challenge;
67
- try {
68
- // Observed in Doppler's official MCP client, not a public OAuth contract.
69
- // Identify resenv honestly rather than impersonating Doppler's MCP client.
70
- const query = new URLSearchParams({ hostname: 'resenv', version: `v${version}`, os: process.platform, arch: process.arch });
71
- challenge = await request(`/v3/auth/cli/generate/2?${query.toString()}`);
72
- }
73
- catch (err) {
74
- if (values.hasErrorCode(err, 'DOPPLER_ENDPOINT_UNAVAILABLE'))
75
- return fallback();
76
- throw err;
77
- }
78
- let url;
79
- try {
80
- url = new URL(typeof challenge?.auth_url === 'string' ? challenge.auth_url : '');
81
- }
82
- catch (err) {
83
- if (!(err instanceof TypeError))
84
- throw err;
85
- }
86
- if (!challenge || !url || url.origin !== 'https://dashboard.doppler.com' || url.username || url.password || url.pathname !== '/workplace/auth/cli' ||
87
- typeof challenge.code !== 'string' || !/^[A-Za-z0-9_-]{8,256}$/.test(challenge.code) ||
88
- typeof challenge.polling_code !== 'string' || !/^[A-Za-z0-9_.-]{8,512}$/.test(challenge.polling_code)) {
89
- throw new errors.ResenvError('DOPPLER_INVALID_RESPONSE', 'Doppler returned an invalid browser authorization challenge.');
90
- }
91
- // Display the human authorization code only in the explicit login command.
92
- output(`Authorize resenv at ${url.href}`);
93
- output(`Authorization code: ${challenge.code}`);
94
- if (!noBrowser)
95
- system$1.openBrowser(url.href);
96
- const deadline = now() + 300000;
97
- while (now() < deadline) {
98
- const result = await request('/v3/auth/cli/authorize', { body: { code: challenge.polling_code }, pending: true });
99
- if (result) {
100
- const token = http.validateToken(result.token);
101
- try {
102
- system$1.write(token);
103
- }
104
- catch {
105
- // Do not leave a newly minted, unpersisted credential active if storage fails.
106
- try {
107
- await request('/v3/auth/revoke', { token, body: { token } });
108
- }
109
- catch (err) {
110
- if (!(err instanceof errors.ResenvError)) {
111
- throw new errors.ResenvError('DOPPLER_KEYRING_UNAVAILABLE', 'Could not save or revoke the login credential. Check Doppler CLI Tokens before retrying.');
112
- }
113
- }
114
- throw new errors.ResenvError('DOPPLER_KEYRING_UNAVAILABLE', 'Could not save the login credential. Revocation was attempted; check Doppler CLI Tokens, then try resenv login doppler --cli.');
115
- }
116
- output('Done: Doppler login saved in the OS credential store.');
117
- return 'native';
118
- }
119
- await sleep(2000);
120
- }
121
- throw new errors.ResenvError('DOPPLER_LOGIN_TIMEOUT', 'Doppler login timed out. Run resenv login doppler to try again.');
122
- }
123
18
 
124
19
  exports.credential = credential;
125
- exports.login = login;
package/doppler/http.cjs CHANGED
@@ -6,24 +6,19 @@ var values = require('../values.cjs');
6
6
  const API_ORIGIN = 'https://api.doppler.com';
7
7
  // No environment-controlled endpoint or redirects: credentials stay at Doppler.
8
8
  function createClient(fetchImpl = globalThis.fetch) {
9
- return async function request(path, { token, body, pending = false } = {}) {
9
+ return async function request(path, { token } = {}) {
10
10
  let response;
11
11
  try {
12
12
  response = await fetchImpl(new URL(path, API_ORIGIN), {
13
- method: body === undefined ? 'GET' : 'POST',
13
+ method: 'GET',
14
14
  headers: {
15
15
  'content-type': 'application/json',
16
16
  'user-agent': 'ciqol-resenv',
17
17
  ...(token ? { authorization: `Bearer ${token}` } : {})
18
18
  },
19
- body: body === undefined ? undefined : JSON.stringify(body),
20
19
  redirect: 'error',
21
20
  signal: AbortSignal.timeout(10000)
22
21
  });
23
- if (pending && response.status === 409) {
24
- await response.body?.cancel();
25
- return null;
26
- }
27
22
  if (!response.ok) {
28
23
  await response.body?.cancel();
29
24
  const code = response.status === 401 ? 'DOPPLER_AUTH_REQUIRED'
@@ -68,7 +63,7 @@ function createClient(fetchImpl = globalThis.fetch) {
68
63
  }
69
64
  function validateToken(token) {
70
65
  if (typeof token !== 'string' || !/^dp\.[a-z]+\.[A-Za-z0-9_.-]{10,512}$/.test(token)) {
71
- throw new errors.ResenvError('DOPPLER_INVALID_TOKEN', 'The Doppler credential is malformed. Run resenv login doppler or supply a valid DOPPLER_TOKEN.');
66
+ throw new errors.ResenvError('DOPPLER_INVALID_TOKEN', 'The Doppler credential is malformed. Check your Doppler CLI login or supply a valid DOPPLER_TOKEN.');
72
67
  }
73
68
  return token;
74
69
  }