@blamejs/pki 0.6.33 → 0.6.34

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/CHANGELOG.md CHANGED
@@ -4,6 +4,14 @@ All notable changes to `@blamejs/pki` are documented here. The format
4
4
  follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this
5
5
  project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## v0.6.34 — 2026-09-04
8
+
9
+ An injected transport that does not return a promise is reported as a typed option error naming the option, in every client that accepts one.
10
+
11
+ ### Changed
12
+
13
+ - pki.est, pki.acme, pki.cmp, and pki.scep reject with est/bad-input, acme/bad-input, cmp/bad-input, or scep/bad-input when opts.transport returns something that is not a promise of the response, instead of failing with a raw TypeError or a misleading response verdict. A transport returning any thenable is still accepted, and the documented signature now states the promise contract.
14
+
7
15
  ## v0.6.33 — 2026-09-04
8
16
 
9
17
  pki.transport reports the RFC 9266 tls-exporter channel binding of a TLS 1.3 connection, so every connection the toolkit opens now carries the binding its protocol version defines.
package/lib/acme.js CHANGED
@@ -1763,7 +1763,7 @@ function _parseLinkNext(headers, base) { var m = _parseLinkRelation(headers, bas
1763
1763
  *
1764
1764
  * @opts
1765
1765
  * - `accountKey` / `accountJwk` / `alg` -- REQUIRED: the account private key, its public JWK, and the JWS alg.
1766
- * - `transport` -- injectable transport(request) -> {status, headers, body}; default pki.transport.https.
1766
+ * - `transport` -- injectable `transport(request) -> Promise<{status, headers, body}>`; default pki.transport.https. It must return a promise of the response; anything else is `acme/bad-input`.
1767
1767
  * - `tls` -- { anchors, useSystemStore, cert, key, minVersion, servername, checkServerIdentity } for the default transport.
1768
1768
  * - `timeout` / `maxResponseBytes` / `maxRedirects` -- transport budgets; `maxNonceRetries` -- badNonce retry cap (default 1).
1769
1769
  * - `proxy` -- reach the ACME server through a forward HTTP proxy (`{ url, auth?, tls? }`; see pki.transport).
@@ -1911,7 +1911,9 @@ function client(directoryUrl, opts) {
1911
1911
  function _send(method, url, headers, body) { return _sendFollowing(method, url, headers, body, 0); }
1912
1912
  function _sendFollowing(method, url, headers, body, redirects) {
1913
1913
  var reqHeaders = Object.assign({ "user-agent": CLIENT_USER_AGENT }, headers || {});
1914
- return transport({ method: method, url: url, headers: reqHeaders, body: body, tls: _tlsFor(url), proxy: budgets.proxy, timeout: budgets.timeout, maxResponseBytes: budgets.maxResponseBytes }).then(function (res) {
1914
+ return guard.async.deferred(function () {
1915
+ return guard.async.awaited(transport({ method: method, url: url, headers: reqHeaders, body: body, tls: _tlsFor(url), proxy: budgets.proxy, timeout: budgets.timeout, maxResponseBytes: budgets.maxResponseBytes }), E, "acme/bad-input", "opts.transport");
1916
+ }).then(function (res) {
1915
1917
  res = res || {};
1916
1918
  var h = {};
1917
1919
  Object.keys(res.headers || {}).forEach(function (k) { h[k.toLowerCase()] = res.headers[k]; });
package/lib/cmp-build.js CHANGED
@@ -809,7 +809,7 @@ function _transfer(url, message, opts) {
809
809
  });
810
810
  headers["content-type"] = PKIXCMP;
811
811
  var tls = _tlsForTransfer(opts);
812
- return Promise.resolve(transport({ method: "POST", url: parsedUrl.href, headers: headers, body: der, tls: tls, proxy: proxy, timeout: timeout, maxResponseBytes: maxResponseBytes })).then(function (res) {
812
+ return guard.async.awaited(transport({ method: "POST", url: parsedUrl.href, headers: headers, body: der, tls: tls, proxy: proxy, timeout: timeout, maxResponseBytes: maxResponseBytes }), _err, "cmp/bad-input", "opts.transport").then(function (res) {
813
813
  res = res || {};
814
814
  var h = {};
815
815
  Object.keys(res.headers || {}).forEach(function (k) { h[k.toLowerCase()] = res.headers[k]; });
@@ -285,7 +285,7 @@ function _certConfHash(certDer) {
285
285
  * - `expectedSender` -- optional CA signer certificate (DER Buffer / PEM string / already-parsed `pki.schema.x509.parse` object); when set, every signed response's authenticated header sender MUST bind to it under the RFC 5280 sec. 7 subject-or-subjectAltName rule cmp.verify uses, so a re-encoded-but-equivalent DN and an empty-subject CA named only by a directoryName SAN both match. Given as bytes/PEM it also resolves a first response that omits its own extraCerts (a CA that assumes the client already holds its certificate). Absent, the session pins the first signed response's signer certificate and requires every later leg's sender to bind to it, rejecting a switch to a different trusted signer while permitting same-identity certificate/key rotation.
286
286
  * - `implicitConfirm` -- request implicit confirmation (skip the certConf leg when the CA grants it).
287
287
  * - `acceptCert` -- an async policy `(certDer, { status, grantedWithMods }) => boolean` consulted before the certConf; return true to accept, anything else to veto (a `grantedWithMods` certificate the CA changed). A veto sends a rejecting certConf and yields `outcome: "rejected"` with the certificate still surfaced. Incompatible with `implicitConfirm` (no reject leg exists), so the combination throws at construction.
288
- * - `transport` -- injectable transport(request) -> {status, headers, body}; default pki.transport.https.
288
+ * - `transport` -- injectable `transport(request) -> Promise<{status, headers, body}>`; default pki.transport.https. It must return a promise of the response; anything else is `cmp/bad-input`.
289
289
  * - `tls` / `headers` / `timeout` / `maxResponseBytes` -- transport config + budgets.
290
290
  * - `proxy` -- reach the CA through a forward HTTP proxy (`{ url, auth?, tls? }`; see pki.transport).
291
291
  * - `maxPolls` / `maxTotalWait` / `sleep` -- poll-loop budgets + an injectable sleeper; `time` -- verify-time clock.
package/lib/est.js CHANGED
@@ -882,7 +882,7 @@ function _drive(method, url, body, headers, opts, transport, budgets) {
882
882
  }
883
883
  function step() {
884
884
  var hopBody = (typeof body === "function" && budgets.onAttempt) ? budgets.onAttempt() : body;
885
- return transport({ method: method, url: url.href, headers: _headersFor(url), body: hopBody, tls: _tlsFor(url), proxy: budgets.proxy, timeout: budgets.timeout, maxResponseBytes: budgets.maxResponseBytes }).then(function (res) {
885
+ return guard.async.awaited(transport({ method: method, url: url.href, headers: _headersFor(url), body: hopBody, tls: _tlsFor(url), proxy: budgets.proxy, timeout: budgets.timeout, maxResponseBytes: budgets.maxResponseBytes }), E, "est/bad-input", "opts.transport").then(function (res) {
886
886
  res = res || {};
887
887
  var blen = _bodyLen(res);
888
888
  if (blen > budgets.maxResponseBytes) throw E("est/response-too-large", "the response body (" + blen + " bytes) exceeds the " + budgets.maxResponseBytes + "-byte cap (RFC 7030 sec. 6)");
@@ -1486,7 +1486,7 @@ function _enroll(op, baseUrl, csrInput, opts, proxySnap) {
1486
1486
  * anchor on the next call.
1487
1487
  *
1488
1488
  * @opts
1489
- * - `transport`: an injected transport(request) -> {status, headers, body, tls}; default pki.transport.https.
1489
+ * - `transport`: an injected `transport(request) -> Promise<{status, headers, body, tls}>`; default pki.transport.https. It must return a promise of the response; anything else is `est/bad-input`.
1490
1490
  * - `tls` -- { anchors, useSystemStore, cert, key, minVersion, servername, checkServerIdentity }.
1491
1491
  * - `label` -- an OPTIONAL CA label path segment; `timeout` / `maxResponseBytes` / `maxRedirects` -- budgets.
1492
1492
  * - `proxy` -- reach the CA through a forward HTTP proxy (`{ url, auth?, tls? }`; see pki.transport).
@@ -5,6 +5,7 @@
5
5
  var _intrinsic = require("./guard-intrinsic");
6
6
  var _resolve = _intrinsic.uncurry(_intrinsic.promiseResolve);
7
7
  var _reject = _intrinsic.uncurry(_intrinsic.promiseReject);
8
+ var _apply = _intrinsic.apply;
8
9
  var _Promise = Promise;
9
10
  // @internal
10
11
  // @enforced-by behavioral -- the rule has no rename-proof code shape (it is the ABSENCE of a wrapper
@@ -13,4 +14,19 @@ function deferred(body) {
13
14
  catch (e) { return _reject(_Promise, e); }
14
15
  }
15
16
 
16
- module.exports = _intrinsic.freeze({ deferred: deferred });
17
+ // @internal
18
+ // @enforced-by behavioral -- a RED vector in each client suite refuses a transport yielding no thenable
19
+ function awaited(value, E, code, label) {
20
+ var thenFn;
21
+ try { thenFn = value == null ? null : value.then; }
22
+ catch (_te) { thenFn = null; }
23
+ if (typeof thenFn !== "function") {
24
+ throw E(code, label + " must return a promise of the response; got " +
25
+ (value === null ? "null" : typeof value));
26
+ }
27
+ return _resolve(_Promise, {
28
+ then: function (resolve, reject) { _apply(thenFn, value, [resolve, reject]); },
29
+ });
30
+ }
31
+
32
+ module.exports = _intrinsic.freeze({ deferred: deferred, awaited: awaited });
package/lib/scep.js CHANGED
@@ -700,7 +700,7 @@ function _drive(method, url, body, headers, opts, transport, budgets) {
700
700
  var req = { method: curMethod, url: current.href, headers: headers, tls: _hopTls(current), timeout: budgets.timeout, maxResponseBytes: budgets.maxResponseBytes };
701
701
  if (proxySnap != null) req.proxy = proxySnap;
702
702
  if (curBody != null) req.body = curBody;
703
- return transport(req).then(function (res) {
703
+ return guard.async.awaited(transport(req), _err, "scep/bad-input", "opts.transport").then(function (res) {
704
704
  res = res || {};
705
705
  var blen = _responseLen(res.body);
706
706
  if (blen > budgets.maxResponseBytes) throw _err("scep/response-too-large", "the response body (" + blen + " bytes) exceeds the " + budgets.maxResponseBytes + "-byte cap");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/pki",
3
- "version": "0.6.33",
3
+ "version": "0.6.34",
4
4
  "description": "Pure-JavaScript PKI toolkit that owns its stack — X.509, ASN.1/DER, CMS, PQC-first.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",
package/sbom.cdx.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.5",
5
- "serialNumber": "urn:uuid:aa5ec092-0f56-46b7-bfb3-469fc4202b37",
5
+ "serialNumber": "urn:uuid:c595f123-cf34-46db-924e-ffa5c0c5018e",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-09-04T18:56:11.300Z",
8
+ "timestamp": "2026-09-04T22:46:35.510Z",
9
9
  "lifecycles": [
10
10
  {
11
11
  "phase": "build"
@@ -19,14 +19,14 @@
19
19
  }
20
20
  ],
21
21
  "component": {
22
- "bom-ref": "@blamejs/pki@0.6.33",
22
+ "bom-ref": "@blamejs/pki@0.6.34",
23
23
  "type": "application",
24
24
  "name": "pki",
25
- "version": "0.6.33",
25
+ "version": "0.6.34",
26
26
  "scope": "required",
27
27
  "author": "blamejs contributors",
28
28
  "description": "Pure-JavaScript PKI toolkit that owns its stack — X.509, ASN.1/DER, CMS, PQC-first.",
29
- "purl": "pkg:npm/%40blamejs/pki@0.6.33",
29
+ "purl": "pkg:npm/%40blamejs/pki@0.6.34",
30
30
  "properties": [],
31
31
  "externalReferences": [
32
32
  {
@@ -54,7 +54,7 @@
54
54
  "components": [],
55
55
  "dependencies": [
56
56
  {
57
- "ref": "@blamejs/pki@0.6.33",
57
+ "ref": "@blamejs/pki@0.6.34",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]