@blamejs/blamejs-shop 0.2.11 → 0.2.13
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 +4 -0
- package/lib/asset-manifest.json +3 -3
- package/lib/storefront.js +276 -24
- package/lib/translations.js +2 -2
- package/lib/vendor/MANIFEST.json +2 -2
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +71 -23
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +2 -0
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +2 -0
- package/lib/vendor/blamejs/.github/workflows/ci.yml +17 -0
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +18 -10
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +29 -16
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +22 -3
- package/lib/vendor/blamejs/.github/zizmor.yml +29 -0
- package/lib/vendor/blamejs/.pinact.yaml +24 -8
- package/lib/vendor/blamejs/CHANGELOG.md +4 -0
- package/lib/vendor/blamejs/api-snapshot.json +2 -2
- package/lib/vendor/blamejs/lib/archive-wrap.js +1 -1
- package/lib/vendor/blamejs/lib/auth/jwt.js +7 -4
- package/lib/vendor/blamejs/lib/auth/saml.js +2 -2
- package/lib/vendor/blamejs/lib/cose.js +1 -1
- package/lib/vendor/blamejs/lib/did.js +1 -1
- package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
- package/lib/vendor/blamejs/lib/guard-auth.js +5 -5
- package/lib/vendor/blamejs/lib/guard-cidr.js +4 -4
- package/lib/vendor/blamejs/lib/guard-csv.js +6 -6
- package/lib/vendor/blamejs/lib/guard-domain.js +4 -4
- package/lib/vendor/blamejs/lib/guard-email.js +6 -5
- package/lib/vendor/blamejs/lib/guard-filename.js +4 -4
- package/lib/vendor/blamejs/lib/guard-graphql.js +5 -5
- package/lib/vendor/blamejs/lib/guard-html.js +2 -2
- package/lib/vendor/blamejs/lib/guard-image.js +1 -1
- package/lib/vendor/blamejs/lib/guard-json.js +5 -5
- package/lib/vendor/blamejs/lib/guard-jsonpath.js +4 -4
- package/lib/vendor/blamejs/lib/guard-jwt.js +5 -5
- package/lib/vendor/blamejs/lib/guard-markdown.js +6 -6
- package/lib/vendor/blamejs/lib/guard-mime.js +6 -6
- package/lib/vendor/blamejs/lib/guard-oauth.js +5 -5
- package/lib/vendor/blamejs/lib/guard-pdf.js +1 -1
- package/lib/vendor/blamejs/lib/guard-regex.js +4 -4
- package/lib/vendor/blamejs/lib/guard-shell.js +4 -4
- package/lib/vendor/blamejs/lib/guard-svg.js +5 -5
- package/lib/vendor/blamejs/lib/guard-template.js +4 -4
- package/lib/vendor/blamejs/lib/guard-time.js +6 -6
- package/lib/vendor/blamejs/lib/guard-uuid.js +6 -6
- package/lib/vendor/blamejs/lib/guard-xml.js +4 -4
- package/lib/vendor/blamejs/lib/guard-yaml.js +5 -5
- package/lib/vendor/blamejs/lib/link-header.js +3 -2
- package/lib/vendor/blamejs/lib/mail-agent.js +4 -2
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +2 -2
- package/lib/vendor/blamejs/lib/tsa.js +2 -1
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.13.23.json +42 -0
- package/lib/vendor/blamejs/release-notes/v0.13.24.json +26 -0
- package/lib/vendor/blamejs/test/smoke.js +25 -0
- package/package.json +1 -1
|
@@ -50,6 +50,8 @@ jobs:
|
|
|
50
50
|
steps:
|
|
51
51
|
- name: Checkout
|
|
52
52
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
53
|
+
with:
|
|
54
|
+
persist-credentials: false
|
|
53
55
|
|
|
54
56
|
- name: Install pinact (release binary + sha256 verify)
|
|
55
57
|
# Install pinact directly from the upstream release binary
|
|
@@ -106,32 +108,43 @@ jobs:
|
|
|
106
108
|
name: zizmor — workflow security audit
|
|
107
109
|
runs-on: ubuntu-latest
|
|
108
110
|
timeout-minutes: 5
|
|
109
|
-
permissions:
|
|
110
|
-
contents: read
|
|
111
|
-
security-events: write # required for SARIF upload to Code Scanning
|
|
112
111
|
steps:
|
|
113
112
|
- name: Checkout
|
|
114
113
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
114
|
+
with:
|
|
115
|
+
persist-credentials: false
|
|
115
116
|
|
|
116
|
-
- name: Install
|
|
117
|
-
|
|
117
|
+
- name: Install zizmor (release binary + sha256 verify)
|
|
118
|
+
# Direct release-binary install instead of astral-sh/setup-uv + uvx.
|
|
119
|
+
# setup-uv (a third-party action) startup_failures the whole
|
|
120
|
+
# workflow on the current runner — the same class of failure as the
|
|
121
|
+
# raven-actions/actionlint composite that took down the actionlint
|
|
122
|
+
# job (no jobs, no logs). A run: step cannot startup_failure.
|
|
123
|
+
# zizmor publishes no checksums file, so the expected sha256 is
|
|
124
|
+
# pinned inline; a mismatch fails closed.
|
|
125
|
+
env:
|
|
126
|
+
ZIZMOR_VERSION: v1.18.0
|
|
127
|
+
ZIZMOR_SHA256: 8e7901319ab7b71c38d6d388a48e02ff65791e5971b2ee6577c9b5c3ab44c65f
|
|
128
|
+
run: |
|
|
129
|
+
set -euo pipefail
|
|
130
|
+
curl -fsSLo /tmp/zizmor.tar.gz "https://github.com/zizmorcore/zizmor/releases/download/${ZIZMOR_VERSION}/zizmor-x86_64-unknown-linux-gnu.tar.gz"
|
|
131
|
+
ACTUAL=$(sha256sum /tmp/zizmor.tar.gz | awk '{print $1}')
|
|
132
|
+
if [ "$ACTUAL" != "$ZIZMOR_SHA256" ]; then
|
|
133
|
+
echo "::error::zizmor tarball sha256 ${ACTUAL} does not match pinned ${ZIZMOR_SHA256}"
|
|
134
|
+
exit 1
|
|
135
|
+
fi
|
|
136
|
+
mkdir -p /tmp/zizmor-bin
|
|
137
|
+
tar -xzf /tmp/zizmor.tar.gz -C /tmp/zizmor-bin ./zizmor
|
|
138
|
+
sudo install -m 0755 /tmp/zizmor-bin/zizmor /usr/local/bin/zizmor
|
|
139
|
+
zizmor --version
|
|
118
140
|
|
|
119
141
|
- name: Run zizmor (fail on level=low across every rule class)
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
#
|
|
142
|
+
# Pure run-gate: zizmor exits non-zero on any finding, failing the
|
|
143
|
+
# job. Inline `# zizmor: ignore[<rule>] — <reason>` is the
|
|
144
|
+
# suppression mechanism for reviewed exceptions.
|
|
123
145
|
run: |
|
|
124
146
|
set -euo pipefail
|
|
125
|
-
|
|
126
|
-
uvx zizmor@1.18.0 --min-severity low . || true # human-readable output for the step log
|
|
127
|
-
if [ "${EXIT:-0}" != "0" ]; then exit "$EXIT"; fi
|
|
128
|
-
|
|
129
|
-
- name: Upload SARIF to Code Scanning
|
|
130
|
-
if: always()
|
|
131
|
-
uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
|
|
132
|
-
with:
|
|
133
|
-
sarif_file: zizmor.sarif
|
|
134
|
-
category: zizmor
|
|
147
|
+
zizmor --min-severity low --no-progress .github/workflows/
|
|
135
148
|
|
|
136
149
|
actionlint:
|
|
137
150
|
name: actionlint — YAML + expression + shellcheck on `run:` blocks
|
|
@@ -140,9 +153,44 @@ jobs:
|
|
|
140
153
|
steps:
|
|
141
154
|
- name: Checkout
|
|
142
155
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
143
|
-
|
|
144
|
-
- name: Run actionlint
|
|
145
|
-
uses: raven-actions/actionlint@205b530c5d9fa8f44ae9ed59f341a0db994aa6f8 # v2.1.2
|
|
146
156
|
with:
|
|
147
|
-
|
|
148
|
-
|
|
157
|
+
persist-credentials: false
|
|
158
|
+
|
|
159
|
+
- name: Install actionlint (release binary + sha256 verify)
|
|
160
|
+
# Direct release-binary install instead of the
|
|
161
|
+
# raven-actions/actionlint composite action. That composite (v2.1.2,
|
|
162
|
+
# the latest release) startup_failures on the current runner, taking
|
|
163
|
+
# the whole workflow down before any job runs — which is why this
|
|
164
|
+
# gate never ran from v0.11.21 onward. The binary path also drops the
|
|
165
|
+
# composite's transitive github-script / cache action surface, which
|
|
166
|
+
# fits the gate whose entire purpose is pinning discipline. Mirrors
|
|
167
|
+
# the pinact install step above.
|
|
168
|
+
env:
|
|
169
|
+
ACTIONLINT_VERSION: v1.7.12
|
|
170
|
+
run: |
|
|
171
|
+
set -euo pipefail
|
|
172
|
+
V="${ACTIONLINT_VERSION#v}"
|
|
173
|
+
curl -fsSLo /tmp/actionlint.tar.gz "https://github.com/rhysd/actionlint/releases/download/${ACTIONLINT_VERSION}/actionlint_${V}_linux_amd64.tar.gz"
|
|
174
|
+
curl -fsSLo /tmp/actionlint-checksums.txt "https://github.com/rhysd/actionlint/releases/download/${ACTIONLINT_VERSION}/actionlint_${V}_checksums.txt"
|
|
175
|
+
ACTUAL=$(sha256sum /tmp/actionlint.tar.gz | awk '{print $1}')
|
|
176
|
+
EXPECTED=$(grep "actionlint_${V}_linux_amd64.tar.gz\$" /tmp/actionlint-checksums.txt | awk '{print $1}')
|
|
177
|
+
if [ -z "$EXPECTED" ]; then
|
|
178
|
+
echo "::error::could not find actionlint_${V}_linux_amd64.tar.gz line in upstream checksums"
|
|
179
|
+
exit 1
|
|
180
|
+
fi
|
|
181
|
+
if [ "$ACTUAL" != "$EXPECTED" ]; then
|
|
182
|
+
echo "::error::actionlint tarball sha256 ${ACTUAL} does not match upstream-published ${EXPECTED}"
|
|
183
|
+
exit 1
|
|
184
|
+
fi
|
|
185
|
+
mkdir -p /tmp/actionlint-bin
|
|
186
|
+
tar -xzf /tmp/actionlint.tar.gz -C /tmp/actionlint-bin actionlint
|
|
187
|
+
sudo install -m 0755 /tmp/actionlint-bin/actionlint /usr/local/bin/actionlint
|
|
188
|
+
actionlint --version
|
|
189
|
+
|
|
190
|
+
- name: Run actionlint (+ shellcheck on every run block)
|
|
191
|
+
# shellcheck ships preinstalled on ubuntu-latest; actionlint invokes
|
|
192
|
+
# it automatically on each `run:` block. Non-zero exit on any finding
|
|
193
|
+
# keeps this a hard gate (the raven composite's fail_on_error: true).
|
|
194
|
+
run: |
|
|
195
|
+
set -euo pipefail
|
|
196
|
+
actionlint -color
|
|
@@ -52,6 +52,8 @@ jobs:
|
|
|
52
52
|
steps:
|
|
53
53
|
- name: Checkout
|
|
54
54
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
55
|
+
with:
|
|
56
|
+
persist-credentials: false
|
|
55
57
|
|
|
56
58
|
- name: Set up Node 24.14.1 LTS
|
|
57
59
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -106,6 +108,8 @@ jobs:
|
|
|
106
108
|
steps:
|
|
107
109
|
- name: Checkout
|
|
108
110
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
111
|
+
with:
|
|
112
|
+
persist-credentials: false
|
|
109
113
|
|
|
110
114
|
- name: Set up Node 24.14.1 LTS
|
|
111
115
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -126,6 +130,8 @@ jobs:
|
|
|
126
130
|
steps:
|
|
127
131
|
- name: Checkout
|
|
128
132
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
133
|
+
with:
|
|
134
|
+
persist-credentials: false
|
|
129
135
|
|
|
130
136
|
- name: Set up Node 24.14.1 LTS
|
|
131
137
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -149,6 +155,8 @@ jobs:
|
|
|
149
155
|
steps:
|
|
150
156
|
- name: Checkout
|
|
151
157
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
158
|
+
with:
|
|
159
|
+
persist-credentials: false
|
|
152
160
|
- name: Set up Node
|
|
153
161
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
154
162
|
with:
|
|
@@ -168,6 +176,7 @@ jobs:
|
|
|
168
176
|
- name: Checkout
|
|
169
177
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
170
178
|
with:
|
|
179
|
+
persist-credentials: false
|
|
171
180
|
# gitleaks scans full history on a non-shallow checkout, so an
|
|
172
181
|
# accidentally-committed secret in any prior commit on the
|
|
173
182
|
# branch is caught even if a later commit reverts it. The
|
|
@@ -225,6 +234,8 @@ jobs:
|
|
|
225
234
|
steps:
|
|
226
235
|
- name: Checkout
|
|
227
236
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
237
|
+
with:
|
|
238
|
+
persist-credentials: false
|
|
228
239
|
|
|
229
240
|
- name: Set up Node 24.14.1 LTS
|
|
230
241
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -254,6 +265,8 @@ jobs:
|
|
|
254
265
|
steps:
|
|
255
266
|
- name: Checkout
|
|
256
267
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
268
|
+
with:
|
|
269
|
+
persist-credentials: false
|
|
257
270
|
|
|
258
271
|
- name: Set up Node 24.14.1 LTS
|
|
259
272
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -294,6 +307,8 @@ jobs:
|
|
|
294
307
|
steps:
|
|
295
308
|
- name: Checkout
|
|
296
309
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
310
|
+
with:
|
|
311
|
+
persist-credentials: false
|
|
297
312
|
|
|
298
313
|
- name: Run Hadolint (strict, all severities)
|
|
299
314
|
# `--no-fail` is OFF; any error or warning fails the job.
|
|
@@ -336,6 +351,8 @@ jobs:
|
|
|
336
351
|
steps:
|
|
337
352
|
- name: Checkout
|
|
338
353
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
354
|
+
with:
|
|
355
|
+
persist-credentials: false
|
|
339
356
|
|
|
340
357
|
- name: Detect shell scripts
|
|
341
358
|
id: sh
|
|
@@ -94,6 +94,8 @@ jobs:
|
|
|
94
94
|
steps:
|
|
95
95
|
- name: Checkout
|
|
96
96
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
97
|
+
with:
|
|
98
|
+
persist-credentials: false
|
|
97
99
|
|
|
98
100
|
- name: Set up Node 24.14.1 LTS
|
|
99
101
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
@@ -102,11 +104,14 @@ jobs:
|
|
|
102
104
|
|
|
103
105
|
- name: Compute version + is_tag flag
|
|
104
106
|
id: version
|
|
107
|
+
env:
|
|
108
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
109
|
+
REF: ${{ github.ref }}
|
|
105
110
|
run: |
|
|
106
111
|
set -euo pipefail
|
|
107
112
|
PKG_VERSION=$(node -e "console.log(require('./package.json').version)")
|
|
108
113
|
echo "version=$PKG_VERSION" >> "$GITHUB_OUTPUT"
|
|
109
|
-
if [ "$
|
|
114
|
+
if [ "$EVENT_NAME" = "push" ] && [[ "$REF" == refs/tags/v* ]]; then
|
|
110
115
|
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
|
|
111
116
|
echo "is_tag=true" >> "$GITHUB_OUTPUT"
|
|
112
117
|
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
|
|
@@ -132,7 +137,7 @@ jobs:
|
|
|
132
137
|
|
|
133
138
|
- name: ShellCheck
|
|
134
139
|
if: steps.shells.outputs.found == 'true'
|
|
135
|
-
uses: ludeeus/action-shellcheck@
|
|
140
|
+
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0
|
|
136
141
|
with:
|
|
137
142
|
severity: error
|
|
138
143
|
|
|
@@ -229,7 +234,7 @@ jobs:
|
|
|
229
234
|
id: subjects
|
|
230
235
|
run: |
|
|
231
236
|
set -euo pipefail
|
|
232
|
-
TARBALL=$(basename "$(
|
|
237
|
+
TARBALL=$(basename "$(find dist -maxdepth 1 -name '*.tgz' | head -1)")
|
|
233
238
|
HASHES=$(
|
|
234
239
|
(cd dist && sha256sum "$TARBALL") && \
|
|
235
240
|
sha256sum sbom.cdx.json sbom.vendored.cdx.json
|
|
@@ -292,7 +297,9 @@ jobs:
|
|
|
292
297
|
# repo specifically so the SLSA tag-pin call is permitted. The
|
|
293
298
|
# `slsa-action-not-pinned` codebase-patterns detector allowlists
|
|
294
299
|
# this specific callsite (see test/layer-0-primitives/codebase-patterns.test.js).
|
|
295
|
-
|
|
300
|
+
# SLSA's reusable builder workflow refuses non-tag refs (cannot be
|
|
301
|
+
# SHA-pinned); upstream tag-protection + immutable releases mitigate.
|
|
302
|
+
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 # zizmor: ignore[unpinned-uses] allow:slsa-framework-action-not-sha-pinned — SLSA's internal builder-fetch refuses non-tag refs; mitigated by slsa-framework's upstream tag-protection + immutable-release rules
|
|
296
303
|
with:
|
|
297
304
|
base64-subjects: "${{ needs.validate.outputs.hashes }}"
|
|
298
305
|
upload-assets: false
|
|
@@ -410,6 +417,7 @@ jobs:
|
|
|
410
417
|
# and failed immediately on the first PQC release run.
|
|
411
418
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
412
419
|
with:
|
|
420
|
+
persist-credentials: false
|
|
413
421
|
path: src
|
|
414
422
|
|
|
415
423
|
- name: Release-digest sidecars (SHA-256 + SHA3-512)
|
|
@@ -424,7 +432,7 @@ jobs:
|
|
|
424
432
|
# Both written in `<sha> <filename>` sha-sum-compatible format.
|
|
425
433
|
run: |
|
|
426
434
|
set -euo pipefail
|
|
427
|
-
TARBALL=$(
|
|
435
|
+
TARBALL=$(find dist -maxdepth 1 -name '*.tgz' | head -1)
|
|
428
436
|
node src/scripts/sha3-digest.js "$TARBALL"
|
|
429
437
|
|
|
430
438
|
- name: PQC sidecar — ML-DSA-65 signature of the tarball
|
|
@@ -463,7 +471,7 @@ jobs:
|
|
|
463
471
|
echo "available=false" >> "$GITHUB_OUTPUT"
|
|
464
472
|
exit 0
|
|
465
473
|
fi
|
|
466
|
-
TARBALL=$(
|
|
474
|
+
TARBALL=$(find dist -maxdepth 1 -name '*.tgz' | head -1)
|
|
467
475
|
# The signer expects keys/release-pqc-pub.json at the
|
|
468
476
|
# framework root for the self-verify cross-check. Symlink
|
|
469
477
|
# the checked-out src/keys/ into the working directory so
|
|
@@ -514,11 +522,11 @@ jobs:
|
|
|
514
522
|
set -euo pipefail
|
|
515
523
|
if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
|
516
524
|
echo "::error::Release $TAG already exists. The workflow is authoritative for release creation as of v0.11.7."
|
|
517
|
-
echo "::error::Manual
|
|
518
|
-
echo "::error::Either delete the existing release
|
|
525
|
+
echo "::error::Manual 'gh release create' was removed from the release workflow in v0.11.7."
|
|
526
|
+
echo "::error::Either delete the existing release with 'gh release delete $TAG' and re-run this workflow, OR push a new tag."
|
|
519
527
|
exit 1
|
|
520
528
|
fi
|
|
521
|
-
TARBALL=$(
|
|
529
|
+
TARBALL=$(find dist -maxdepth 1 -name '*.tgz' | head -1)
|
|
522
530
|
# Title comes from the structured release-notes JSON's
|
|
523
531
|
# `headline` field — single source of truth. Format:
|
|
524
532
|
# `vX.Y.Z — <headline>`.
|
|
@@ -594,7 +602,7 @@ jobs:
|
|
|
594
602
|
# mis-classifies a relative path containing `/` as a git
|
|
595
603
|
# spec.
|
|
596
604
|
run: |
|
|
597
|
-
TARBALL=$(
|
|
605
|
+
TARBALL=$(find dist -maxdepth 1 -name '*.tgz' | head -1)
|
|
598
606
|
echo "Publishing: $TARBALL"
|
|
599
607
|
npm publish "./${TARBALL}" --provenance --access public
|
|
600
608
|
env:
|
|
@@ -57,6 +57,8 @@ jobs:
|
|
|
57
57
|
steps:
|
|
58
58
|
- name: Checkout
|
|
59
59
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
60
|
+
with:
|
|
61
|
+
persist-credentials: false
|
|
60
62
|
- name: Set up Node 24.14.1 LTS
|
|
61
63
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
62
64
|
with:
|
|
@@ -73,6 +75,8 @@ jobs:
|
|
|
73
75
|
steps:
|
|
74
76
|
- name: Checkout
|
|
75
77
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
78
|
+
with:
|
|
79
|
+
persist-credentials: false
|
|
76
80
|
- name: Run Hadolint (strict, all severities)
|
|
77
81
|
uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0
|
|
78
82
|
with:
|
|
@@ -88,6 +92,8 @@ jobs:
|
|
|
88
92
|
steps:
|
|
89
93
|
- name: Checkout
|
|
90
94
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
95
|
+
with:
|
|
96
|
+
persist-credentials: false
|
|
91
97
|
- name: Detect shell scripts
|
|
92
98
|
id: sh
|
|
93
99
|
run: |
|
|
@@ -97,7 +103,7 @@ jobs:
|
|
|
97
103
|
echo "found=$count" >> "$GITHUB_OUTPUT"
|
|
98
104
|
- name: Run ShellCheck
|
|
99
105
|
if: steps.sh.outputs.found != '0'
|
|
100
|
-
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 #
|
|
106
|
+
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0
|
|
101
107
|
with:
|
|
102
108
|
severity: style
|
|
103
109
|
format: tty
|
|
@@ -118,16 +124,18 @@ jobs:
|
|
|
118
124
|
steps:
|
|
119
125
|
- name: Checkout
|
|
120
126
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
127
|
+
with:
|
|
128
|
+
persist-credentials: false
|
|
121
129
|
|
|
122
130
|
- name: Set up QEMU (for ARM64 cross-build)
|
|
123
|
-
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4
|
|
131
|
+
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
|
124
132
|
|
|
125
133
|
- name: Set up Docker Buildx
|
|
126
|
-
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
|
|
134
|
+
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
|
127
135
|
|
|
128
136
|
- name: Log in to GHCR
|
|
129
137
|
if: ${{ !inputs.dry_run }}
|
|
130
|
-
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
|
|
138
|
+
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
|
131
139
|
with:
|
|
132
140
|
registry: ghcr.io
|
|
133
141
|
username: ${{ github.actor }}
|
|
@@ -162,7 +170,7 @@ jobs:
|
|
|
162
170
|
# Note: load: true forces single-arch (amd64). The multi-arch
|
|
163
171
|
# build happens on the post-scan push step below.
|
|
164
172
|
- name: Build (local-only, for Trivy)
|
|
165
|
-
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7
|
|
173
|
+
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
|
166
174
|
with:
|
|
167
175
|
context: .
|
|
168
176
|
file: examples/wiki/Dockerfile
|
|
@@ -210,7 +218,7 @@ jobs:
|
|
|
210
218
|
- name: Push (multi-arch, after Trivy gate)
|
|
211
219
|
id: push
|
|
212
220
|
if: ${{ !inputs.dry_run && steps.tags.outputs.is_tag == 'true' }}
|
|
213
|
-
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7
|
|
221
|
+
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
|
214
222
|
with:
|
|
215
223
|
context: .
|
|
216
224
|
file: examples/wiki/Dockerfile
|
|
@@ -236,7 +244,7 @@ jobs:
|
|
|
236
244
|
if: ${{ !inputs.dry_run && steps.tags.outputs.is_tag == 'true' && steps.push.outputs.digest }}
|
|
237
245
|
env:
|
|
238
246
|
DIGEST: ${{ steps.push.outputs.digest }}
|
|
239
|
-
run: cosign sign --yes "${
|
|
247
|
+
run: cosign sign --yes "${IMAGE}@${DIGEST}"
|
|
240
248
|
|
|
241
249
|
- name: Generate SHA3-512 digest
|
|
242
250
|
if: ${{ !inputs.dry_run && steps.tags.outputs.is_tag == 'true' && steps.push.outputs.digest }}
|
|
@@ -245,8 +253,8 @@ jobs:
|
|
|
245
253
|
DIGEST: ${{ steps.push.outputs.digest }}
|
|
246
254
|
run: |
|
|
247
255
|
set -euo pipefail
|
|
248
|
-
docker pull "${
|
|
249
|
-
HASH=$(docker save "${
|
|
256
|
+
docker pull "${IMAGE}@${DIGEST}"
|
|
257
|
+
HASH=$(docker save "${IMAGE}@${DIGEST}" | openssl dgst -sha3-512 | awk '{print $NF}')
|
|
250
258
|
echo "SHA3-512: $HASH"
|
|
251
259
|
echo "sha3=$HASH" >> "$GITHUB_OUTPUT"
|
|
252
260
|
{
|
|
@@ -275,8 +283,8 @@ jobs:
|
|
|
275
283
|
echo "|---|---|"
|
|
276
284
|
echo "| **Version** | ${VERSION} |"
|
|
277
285
|
echo "| **Platforms** | linux/amd64, linux/arm64 |"
|
|
278
|
-
echo "| **Registry** | ${
|
|
279
|
-
echo "| **Commit** | ${
|
|
286
|
+
echo "| **Registry** | ${IMAGE} |"
|
|
287
|
+
echo "| **Commit** | ${GITHUB_SHA} |"
|
|
280
288
|
echo "| **Dry run** | ${DRY_RUN} |"
|
|
281
289
|
echo "| **Tag push** | ${IS_TAG} |"
|
|
282
290
|
echo ""
|
|
@@ -297,6 +305,11 @@ jobs:
|
|
|
297
305
|
if: ${{ !inputs.dry_run && needs.publish.outputs.digest != '' }}
|
|
298
306
|
runs-on: ubuntu-latest
|
|
299
307
|
timeout-minutes: 10
|
|
308
|
+
env:
|
|
309
|
+
# Hoisted so run: blocks reference $DIGEST instead of inlining the
|
|
310
|
+
# ${{ needs.publish.outputs.digest }} expression (template-injection
|
|
311
|
+
# hardening — keeps GitHub-context values out of shell-parsed text).
|
|
312
|
+
DIGEST: ${{ needs.publish.outputs.digest }}
|
|
300
313
|
steps:
|
|
301
314
|
# Smoke-test runs on a fresh runner — it doesn't inherit the
|
|
302
315
|
# publish job's GHCR auth. Log in first so `docker pull` works
|
|
@@ -304,19 +317,19 @@ jobs:
|
|
|
304
317
|
# against a public package, so this is the right shape regardless
|
|
305
318
|
# of visibility.
|
|
306
319
|
- name: Log in to GHCR
|
|
307
|
-
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
|
|
320
|
+
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
|
308
321
|
with:
|
|
309
322
|
registry: ghcr.io
|
|
310
323
|
username: ${{ github.actor }}
|
|
311
324
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
312
325
|
|
|
313
326
|
- name: Pull published image
|
|
314
|
-
run: docker pull "${
|
|
327
|
+
run: docker pull "${IMAGE}@${DIGEST}"
|
|
315
328
|
|
|
316
329
|
- name: Verify OCI labels
|
|
317
330
|
run: |
|
|
318
331
|
set -euo pipefail
|
|
319
|
-
LABELS=$(docker inspect "${
|
|
332
|
+
LABELS=$(docker inspect "${IMAGE}@${DIGEST}" --format '{{json .Config.Labels}}')
|
|
320
333
|
echo "$LABELS" | python3 -m json.tool
|
|
321
334
|
echo "$LABELS" | python3 -c "
|
|
322
335
|
import sys, json
|
|
@@ -342,7 +355,7 @@ jobs:
|
|
|
342
355
|
--security-opt no-new-privileges:true \
|
|
343
356
|
--cap-drop ALL \
|
|
344
357
|
-p 3008:3008 \
|
|
345
|
-
"${
|
|
358
|
+
"${IMAGE}@${DIGEST}"
|
|
346
359
|
|
|
347
360
|
echo "Waiting for /healthz..."
|
|
348
361
|
for i in $(seq 1 30); do
|
|
@@ -396,7 +409,7 @@ jobs:
|
|
|
396
409
|
{
|
|
397
410
|
echo "### Post-publish smoke ❌"
|
|
398
411
|
echo ""
|
|
399
|
-
echo "Smoke test failed for ${
|
|
412
|
+
echo "Smoke test failed for ${IMAGE}@${DIGEST}."
|
|
400
413
|
echo "See the 'Capture container diagnostics on failure' step above for"
|
|
401
414
|
echo "docker ps / inspect / logs output."
|
|
402
415
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
@@ -39,6 +39,7 @@ jobs:
|
|
|
39
39
|
- name: Checkout (full history needed for first-parent walk)
|
|
40
40
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
41
41
|
with:
|
|
42
|
+
persist-credentials: false
|
|
42
43
|
fetch-depth: 0
|
|
43
44
|
fetch-tags: true
|
|
44
45
|
|
|
@@ -53,10 +54,15 @@ jobs:
|
|
|
53
54
|
- name: Resolve tag + verify chain
|
|
54
55
|
env:
|
|
55
56
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
57
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
58
|
+
# Hoisted: a workflow_dispatch input is operator-supplied text;
|
|
59
|
+
# inlining ${{ github.event.inputs.tag }} into the shell is the
|
|
60
|
+
# template-injection vector. Reference $INPUT_TAG instead.
|
|
61
|
+
INPUT_TAG: ${{ github.event.inputs.tag }}
|
|
56
62
|
run: |
|
|
57
63
|
set -euo pipefail
|
|
58
|
-
if [ "$
|
|
59
|
-
TAG="$
|
|
64
|
+
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
|
|
65
|
+
TAG="$INPUT_TAG"
|
|
60
66
|
else
|
|
61
67
|
TAG="${GITHUB_REF#refs/tags/}"
|
|
62
68
|
fi
|
|
@@ -77,7 +83,20 @@ jobs:
|
|
|
77
83
|
# pass that test. The strict first-parent invariant is
|
|
78
84
|
# what the project's squash-merge policy actually
|
|
79
85
|
# produces; check it directly.
|
|
80
|
-
|
|
86
|
+
#
|
|
87
|
+
# Capture rev-list output first, then grep against a
|
|
88
|
+
# here-string. The obvious-looking
|
|
89
|
+
# `git rev-list --first-parent origin/main | grep -qx "$SHA"`
|
|
90
|
+
# is a `set -o pipefail` + `grep -q` trap: when grep -q
|
|
91
|
+
# finds the match it exits early and closes its stdin,
|
|
92
|
+
# rev-list gets SIGPIPE and exits 141, and pipefail then
|
|
93
|
+
# propagates 141 as the pipeline's exit. The outer
|
|
94
|
+
# `if !` negates 141 → enters the false-fail branch
|
|
95
|
+
# every time on a long first-parent chain. (False-failed
|
|
96
|
+
# every release v0.13.18-.22.) The here-string consumes
|
|
97
|
+
# rev-list to completion first; no pipe, no SIGPIPE.
|
|
98
|
+
FIRST_PARENT=$(git rev-list --first-parent origin/main)
|
|
99
|
+
if ! grep -qFx "$SHA" <<<"$FIRST_PARENT"; then
|
|
81
100
|
echo "::error::tag $TAG points at $SHA which is NOT on main's first-parent history"
|
|
82
101
|
echo "::error::this means the tag was created from a side-branch commit that never merged via the project's squash-merge flow"
|
|
83
102
|
echo "::error::the publish workflow refuses to proceed; investigate before re-tagging"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# zizmor configuration (auto-discovered at .github/zizmor.yml).
|
|
2
|
+
#
|
|
3
|
+
# Suppressions live here rather than as inline `# zizmor: ignore[...]`
|
|
4
|
+
# comments because the affected lines are `uses:` references that
|
|
5
|
+
# already carry a pinact version comment (`# vX.Y.Z`). zizmor only
|
|
6
|
+
# honors an ignore pragma when `zizmor:` is the first token of the
|
|
7
|
+
# YAML comment; a `# vX.Y.Z # zizmor: ignore[...]` line reads as the
|
|
8
|
+
# comment text "vX.Y.Z # zizmor: ..." and the pragma is never seen.
|
|
9
|
+
# A config-file ignore is the only placement that does not collide
|
|
10
|
+
# with the SHA-pin version comment that pinact requires.
|
|
11
|
+
|
|
12
|
+
rules:
|
|
13
|
+
cache-poisoning:
|
|
14
|
+
# actions/setup-node carries an optional `cache:` input that, when
|
|
15
|
+
# set, restores a dependency cache. zizmor flags the *capability*
|
|
16
|
+
# whenever the workflow also has a release-class trigger
|
|
17
|
+
# (`push: tags: ["v*"]`), because a poisoned cache restored during a
|
|
18
|
+
# publishing run is high-impact. None of these workflows set a
|
|
19
|
+
# `cache:` input — no dependency cache is created or restored, so
|
|
20
|
+
# there is nothing to poison. The finding is capability-driven, not
|
|
21
|
+
# an observed cache.
|
|
22
|
+
#
|
|
23
|
+
# Invariant for future edits: if any step in one of these files adds
|
|
24
|
+
# a `cache:` input to a setup-* action, remove that file from this
|
|
25
|
+
# list and review the cache-poisoning exposure for real.
|
|
26
|
+
ignore:
|
|
27
|
+
- ci.yml
|
|
28
|
+
- npm-publish.yml
|
|
29
|
+
- release-container.yml
|
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
# pinact configuration — refuses any tag-shaped `uses:` reference EXCEPT
|
|
2
|
-
# the documented
|
|
2
|
+
# the documented exceptions below.
|
|
3
3
|
#
|
|
4
|
-
# The
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
4
|
+
# 1. The SLSA reusable workflow. SLSA's internal builder-fetch step
|
|
5
|
+
# refuses non-tag `BUILDER_REF` values ("Invalid ref: <40-hex>.
|
|
6
|
+
# Expected ref of the form refs/tags/vX.Y.Z"), so the call MUST be
|
|
7
|
+
# tag-pinned. Mitigated by slsa-framework's upstream tag-protection +
|
|
8
|
+
# immutable-release rules. Same suppression also appears as a per-line
|
|
9
|
+
# `# allow:slsa-framework-action-not-sha-pinned` marker in
|
|
10
|
+
# `.github/workflows/npm-publish.yml` for the codebase-patterns gate.
|
|
11
|
+
#
|
|
12
|
+
# 2. aquasecurity/trivy-action. The aquasecurity org enables a GitHub
|
|
13
|
+
# org-level IP allow-list that returns 403 to GitHub Actions runner
|
|
14
|
+
# IPs on the commits API, so `pinact run --verify`'s online tag
|
|
15
|
+
# re-resolution cannot complete from CI (it succeeds from
|
|
16
|
+
# unrestricted IPs). The action stays SHA-pinned in the workflow
|
|
17
|
+
# (auditable inline); this entry only exempts it from the online
|
|
18
|
+
# re-verification that the upstream org makes impossible from a
|
|
19
|
+
# runner.
|
|
11
20
|
#
|
|
12
21
|
# See npm-publish.yml comment block + memory/specs/release-v0.10.19-plan.md.
|
|
13
22
|
|
|
14
23
|
version: 3
|
|
15
24
|
|
|
16
25
|
ignore_actions:
|
|
26
|
+
# pinact v3 treats both `name` and `ref` as regular expressions, and
|
|
27
|
+
# both are required (a name-only entry fails config load with
|
|
28
|
+
# "initialize ignore_action: ref is required"). `ref: .*` matches the
|
|
29
|
+
# tag-pinned ref this single exception carries (currently v2.1.0).
|
|
17
30
|
- name: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml
|
|
31
|
+
ref: .*
|
|
32
|
+
- name: aquasecurity/trivy-action
|
|
33
|
+
ref: .*
|
|
@@ -8,6 +8,10 @@ upgrading across more than a few patches at a time.
|
|
|
8
8
|
|
|
9
9
|
## v0.13.x
|
|
10
10
|
|
|
11
|
+
- v0.13.24 (2026-05-28) — **`b.guard*` docs corrected: the compliance-posture opt key, the gate API, and validate return shapes.** Documentation corrections across the b.guard* family. The most consequential: the posture-selection option was documented as `compliance:` in many guards' @opts, but the working key is `compliancePosture:` — passing the documented `{ compliance: "hipaa" }` was silently ignored, so a compliance posture (e.g. HIPAA PII redaction) never activated. If you select a posture via the gate/validate/sanitize options, use `compliancePosture:`; `compliance:` had no effect. The guard docs now name the correct key uniformly. Also corrected: gate examples and prose that invoked the gate as a callable or via `.run` / `.inspect` (the gate is an object whose method is `.check(ctx)`), and validate() return shapes that listed `severities` / `summary` / `refusal` fields the function never returned (it returns `{ ok, issues }`). **Fixed:** *guard posture option is `compliancePosture:`, not `compliance:`* — Many `b.guard*` primitives documented the compliance-posture selector as `compliance: "hipaa"|"pci-dss"|"gdpr"|"soc2"` in their `@opts`, but the family resolver reads `compliancePosture:`. Passing `{ compliance: "hipaa" }` was accepted and silently ignored — the posture overlay (e.g. CSV `piiPolicy: "redact"` under HIPAA) never applied, leaving the default policy in force. The docs across the guard family now name `compliancePosture:` consistently (the key the resolver and `b.guardX.compliancePosture(name)` already used). Action: if you selected a posture with `compliance:`, switch to `compliancePosture:` — the posture was not taking effect before. · *guard gate is an object with `.check(ctx)`, not a callable* — Several guards' gate `@example`s and prose invoked the gate as a function (`g({...})`), via `.run(...)`, or via `.inspect(...)`, and a few described it as "an async function". `b.guardX.gate(opts)` returns an object whose async method is `.check(ctx)`; the examples and prose now use `.check`, so they run as written. · *guard validate() returns `{ ok, issues }`* — Several guards documented `validate()` as returning `{ ok, issues, severities }`, `{ ok, issues, summary }`, or `{ ok, issues, refusal? }`. The function returns `{ ok, issues }` (each issue carries its own `severity` / `kind`); the documented extra top-level fields were never present. The docs now state the actual shape.
|
|
12
|
+
|
|
13
|
+
- v0.13.23 (2026-05-28) — **Documentation corrected to match actual behavior across several primitives.** A set of JSDoc / doc-comment corrections where the documented contract had drifted from what the code does. No behavior changes — the implementations already behaved as now documented; only the docs were wrong. The most operator-relevant is the JWT signer doc: an expiring token signed without an explicit jti receives an auto-minted 128-bit jti (so the replay-defense path has the jti it needs), which the sign-opts doc previously denied. Also corrected: did.resolve's unsupported-method error now names did:jwk (always supported); b.cose.verify is marked stable to match its stable sign sibling and the CWT / EAT / SCITT / mdoc verifiers built on it; b.linkHeader.serialize's doc now states every parameter value is double-quoted; b.auth.saml verifyResponse's documented return shape now lists inResponseTo and issuer (both always returned); and the rate-limit custom-backend contract drops a gc member the middleware never invoked. **Fixed:** *JWT signer doc now describes the auto-minted jti on expiring tokens* — `b.auth.jwt.sign`'s opts doc claimed that omitting `jti` adds no jti. In fact, when a token carries an `exp` and no operator-supplied `jti`, the signer auto-mints a random 128-bit `jti` so a replay-protected token always carries the identifier `verify`'s replay store requires. The doc now describes this; pass an explicit `jti` for a deterministic value. Behavior is unchanged. · *`b.did.resolve` unsupported-method error now names did:jwk* — The thrown error for an unsupported DID method listed only `did:key` and `did:web`, omitting `did:jwk`, which `resolve` fully supports. The message now reads `(did:key, did:jwk, and did:web only)`. · *`b.cose.verify` marked stable* — `b.cose.verify` carried `@status experimental` while its `b.cose.sign` sibling is stable and the CWT / EAT / SCITT / mdoc verifiers that depend on it are stable and shipped. The verifier is the same maturity as the rest of the COSE_Sign1 round-trip; its status now reflects that. · *`b.linkHeader.serialize` doc matches its quoting behavior* — The doc said parameters are token-encoded when they fit RFC 7230 token grammar and double-quoted otherwise. The serializer always double-quotes every value (valid under RFC 8288, and required for space-separated multi-rel and media-type values). The doc now states that. · *`b.auth.saml` verifyResponse documented return shape lists all fields* — The prose and the example each omitted a different field that `verifyResponse` always returns. The documented shape now lists all of `nameId`, `nameIdFormat`, `sessionIndex`, `attributes`, `audience`, `inResponseTo`, and `issuer`. · *rate-limit custom-backend contract is `{ take, reset }`* — The custom-backend opts doc listed a `gc` member that the middleware never reads or invokes (the runtime contract is `take` / `reset` / `close`, and the error message already said `{ take, reset }`). The documented shape now matches; an operator-supplied `gc` was always silently ignored. · *`b.mail.agent.create` doc no longer lists consumer as a method* — The created agent's method list named `consumer`, which is not a method on the returned object — the queue consumer is the sibling export `b.mail.agent.consumer`. The doc now says so.
|
|
14
|
+
|
|
11
15
|
- v0.13.22 (2026-05-27) — **`b.archive.read.zip.fromTrustedStream` reads a ZIP from a Readable — no longer an experimental stub.** fromTrustedStream was an experimental stub whose inspect / entries / extract methods threw, forcing callers to buffer the stream themselves and use the random-access reader. It now works, with the same shape as the tar trusted-stream reader: pass b.archive.adapters.trustedStream(readable) and the bytes are collected into a size-capped buffer (1 GiB hard ceiling) and read through the same bomb-cap, path-traversal, and entry-type decode as the random-access reader — so bombPolicy, guardProfile, entryTypePolicy, and audit all apply, and inspect / entries / extract / extractEntries all return data. This is a bounded-memory reader (the archive is held in memory under the ceiling), not zero-buffer streaming; a future forward-inflate walker shared with the tar reader would lift the ceiling. **Added:** *`b.archive.read.zip.fromTrustedStream` now reads — `inspect` / `entries` / `extract` / `extractEntries`* — The ZIP trusted-stream reader is implemented (was an experimental stub that threw). Pass `b.archive.adapters.trustedStream(readable)` to read a ZIP straight from a Node Readable without buffering it yourself. The stream is collected into a size-capped buffer (1 GiB ceiling, matching `b.archive.read.tar`'s trusted-stream reader) and decoded through the same adversarial-safe path as the random-access reader, so `bombPolicy` / `guardProfile` / `entryTypePolicy` / `audit` are honored on decode. Adversarial archives remain fully bomb-capped; "trusted" refers only to the source-size bound. A non-trusted-stream adapter is refused with `archive-read/bad-adapter`.
|
|
12
16
|
|
|
13
17
|
- v0.13.21 (2026-05-27) — **`b.cose.exportKey` — serialize a public key as a COSE_Key, the inverse of `b.cose.importKey`.** b.cose could import a COSE_Key (RFC 9052 §7) into a node:crypto key for verification, but had no way to produce one — so a key used with b.cose.sign could not be shipped to a verifier in COSE form without hand-building the CBOR map. b.cose.exportKey(keyObject, opts?) closes the round-trip: it serializes an EC2 (P-256 / P-384 / P-521) or OKP (Ed25519) public key as the CBOR-encoded COSE_Key map, with optional alg and kid common parameters. A private key has its public half exported; unsupported curves / key types are refused rather than emitting a COSE_Key no verifier here would accept. The bytes round-trip through b.cose.importKey, and feed the mdoc MSO / COSE_Key header / SCITT / C2PA verification-key paths. **Added:** *`b.cose.exportKey(keyObject, { alg?, kid? })` — KeyObject → COSE_Key (RFC 9052 §7)* — Serialize a `node:crypto` public key as the CBOR-encoded COSE_Key map — the inverse of `b.cose.importKey`. Supports EC2 (P-256 / P-384 / P-521) and OKP (Ed25519), the same key types `b.cose.verify` accepts; `opts.alg` (e.g. `"ES256"`) and `opts.kid` populate the COSE_Key alg (label 3) and kid (label 2) common parameters. A private key exports its public half; unsupported curves / key types throw rather than producing a COSE_Key no verifier would accept. `b.cose.importKey(b.cbor.decode(exportKey(k)))` round-trips, so a key signed with `b.cose.sign` can be shipped to a verifier as bytes — the mdoc MSO / COSE_Key header / SCITT / C2PA verification-key paths.
|
|
@@ -370,7 +370,7 @@ function sniffEnvelope(bytes) {
|
|
|
370
370
|
* @signature b.archive.wrapWithPassphrase(bytes, opts)
|
|
371
371
|
* @since 0.12.11
|
|
372
372
|
* @status stable
|
|
373
|
-
* @related b.archive.unwrapWithPassphrase, b.archive.wrap
|
|
373
|
+
* @related b.archive.unwrapWithPassphrase, b.archive.wrap
|
|
374
374
|
*
|
|
375
375
|
* Wrap archive bytes in a passphrase-derived envelope. The envelope
|
|
376
376
|
* wire format is the framework's standard Argon2id (RFC 9106) +
|