@blamejs/blamejs-shop 0.2.12 → 0.2.14
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/README.md +1 -1
- package/lib/admin.js +616 -21
- package/lib/asset-manifest.json +5 -5
- package/lib/catalog.js +19 -0
- package/lib/storefront.js +1 -1
- package/lib/vendor/MANIFEST.json +3 -3
- 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 +20 -0
- package/lib/vendor/blamejs/api-snapshot.json +6 -2
- package/lib/vendor/blamejs/lib/agent-idempotency.js +50 -10
- package/lib/vendor/blamejs/lib/agent-orchestrator.js +58 -5
- package/lib/vendor/blamejs/lib/agent-saga.js +8 -4
- package/lib/vendor/blamejs/lib/agent-tenant.js +56 -4
- package/lib/vendor/blamejs/lib/agent-trace.js +4 -3
- package/lib/vendor/blamejs/lib/ai-adverse-decision.js +1 -1
- package/lib/vendor/blamejs/lib/archive-wrap.js +1 -1
- package/lib/vendor/blamejs/lib/audit-daily-review.js +3 -3
- package/lib/vendor/blamejs/lib/audit.js +11 -8
- 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/calendar.js +14 -10
- package/lib/vendor/blamejs/lib/circuit-breaker.js +6 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +2 -2
- package/lib/vendor/blamejs/lib/compliance.js +7 -9
- package/lib/vendor/blamejs/lib/cookies.js +2 -2
- package/lib/vendor/blamejs/lib/cose.js +1 -1
- package/lib/vendor/blamejs/lib/crypto-field.js +8 -3
- package/lib/vendor/blamejs/lib/data-act.js +4 -3
- package/lib/vendor/blamejs/lib/did.js +1 -1
- package/lib/vendor/blamejs/lib/file-upload.js +18 -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/mail-bimi.js +3 -2
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +7 -11
- package/lib/vendor/blamejs/lib/mail-crypto-smime.js +6 -5
- package/lib/vendor/blamejs/lib/mail-crypto.js +5 -5
- package/lib/vendor/blamejs/lib/mail-store.js +3 -2
- package/lib/vendor/blamejs/lib/mcp.js +2 -3
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +10 -6
- package/lib/vendor/blamejs/lib/middleware/ai-act-disclosure.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +3 -3
- package/lib/vendor/blamejs/lib/middleware/compose-pipeline.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/csp-nonce.js +2 -2
- package/lib/vendor/blamejs/lib/middleware/flag-context.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +2 -2
- package/lib/vendor/blamejs/lib/middleware/require-auth.js +2 -1
- package/lib/vendor/blamejs/lib/queue-redis.js +9 -0
- package/lib/vendor/blamejs/lib/queue.js +17 -1
- package/lib/vendor/blamejs/lib/retry.js +26 -0
- package/lib/vendor/blamejs/lib/router.js +4 -1
- package/lib/vendor/blamejs/lib/safe-decompress.js +3 -2
- package/lib/vendor/blamejs/lib/safe-icap.js +3 -2
- package/lib/vendor/blamejs/lib/safe-mime.js +1 -1
- package/lib/vendor/blamejs/lib/safe-smtp.js +1 -1
- package/lib/vendor/blamejs/lib/sec-cyber.js +1 -1
- package/lib/vendor/blamejs/lib/storage.js +20 -16
- package/lib/vendor/blamejs/lib/tsa.js +2 -1
- package/lib/vendor/blamejs/lib/vault/index.js +1 -0
- package/lib/vendor/blamejs/lib/vault-aad.js +2 -2
- 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/release-notes/v0.13.25.json +39 -0
- package/lib/vendor/blamejs/release-notes/v0.13.26.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.13.27.json +34 -0
- package/lib/vendor/blamejs/release-notes/v0.13.28.json +30 -0
- package/lib/vendor/blamejs/release-notes/v0.13.29.json +30 -0
- package/lib/vendor/blamejs/release-notes/v0.13.30.json +30 -0
- package/lib/vendor/blamejs/release-notes/v0.13.31.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.13.32.json +34 -0
- package/lib/vendor/blamejs/test/20-db.js +30 -0
- package/lib/vendor/blamejs/test/integration/queue-redis.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +37 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-orchestrator.test.js +37 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-tenant.test.js +26 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-daily-review.test.js +9 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retry.test.js +25 -0
- package/lib/vendor/blamejs/test/smoke.js +25 -0
- package/package.json +1 -1
package/lib/asset-manifest.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.2.
|
|
2
|
+
"version": "0.2.14",
|
|
3
3
|
"assets": {
|
|
4
4
|
"css/admin.css": {
|
|
5
|
-
"integrity": "sha384-
|
|
6
|
-
"fingerprinted": "css/admin.
|
|
5
|
+
"integrity": "sha384-1SIn6oAf1DjECbRfKENZasdKHJiywGdXR58wn0hsFGcdVHzUmvfgMkEz5ANIAZJ3",
|
|
6
|
+
"fingerprinted": "css/admin.72c808274ebcefd9.css"
|
|
7
7
|
},
|
|
8
8
|
"css/main.css": {
|
|
9
|
-
"integrity": "sha384-
|
|
10
|
-
"fingerprinted": "css/main.
|
|
9
|
+
"integrity": "sha384-E56XcvNC5nbTWyHJJcepF6sVA1KjRNo/MWFL5F5w2PDN10JNaHdzIAP9a46m2Md8",
|
|
10
|
+
"fingerprinted": "css/main.a76d36ac566703d6.css"
|
|
11
11
|
},
|
|
12
12
|
"js/announcement.js": {
|
|
13
13
|
"integrity": "sha384-z4zcEMn+tScoVnYRE4nEf8N/oyvpxdpaxTNrT4QO/jURChid4+qjAvWkzatCaAPq",
|
package/lib/catalog.js
CHANGED
|
@@ -591,6 +591,19 @@ function _pricesModule(query) {
|
|
|
591
591
|
);
|
|
592
592
|
return r.rows;
|
|
593
593
|
},
|
|
594
|
+
|
|
595
|
+
// The distinct currencies this variant has ever been priced in, so a
|
|
596
|
+
// caller (the admin price manager) can render current + history per
|
|
597
|
+
// currency without first knowing which currencies exist. Ordered for a
|
|
598
|
+
// stable display.
|
|
599
|
+
currencies: async function (variantId) {
|
|
600
|
+
_id(variantId, "variant_id");
|
|
601
|
+
var r = await query(
|
|
602
|
+
"SELECT DISTINCT currency FROM prices WHERE variant_id = ?1 ORDER BY currency ASC",
|
|
603
|
+
[variantId],
|
|
604
|
+
);
|
|
605
|
+
return r.rows.map(function (row) { return row.currency; });
|
|
606
|
+
},
|
|
594
607
|
};
|
|
595
608
|
}
|
|
596
609
|
|
|
@@ -753,6 +766,12 @@ function _mediaModule(query) {
|
|
|
753
766
|
return { id: id, product_id: pid, variant_id: vid, r2_key: input.r2_key, content_type: input.content_type, width: width, height: height, position: position, alt_text: altText, created_at: ts };
|
|
754
767
|
},
|
|
755
768
|
|
|
769
|
+
get: async function (id) {
|
|
770
|
+
_id(id, "media id");
|
|
771
|
+
var r = await query("SELECT * FROM media WHERE id = ?1", [id]);
|
|
772
|
+
return r.rows[0] || null;
|
|
773
|
+
},
|
|
774
|
+
|
|
756
775
|
listForProduct: async function (productId) {
|
|
757
776
|
_id(productId, "product_id");
|
|
758
777
|
var r = await query("SELECT * FROM media WHERE product_id = ?1 ORDER BY position ASC, created_at ASC", [productId]);
|
package/lib/storefront.js
CHANGED
|
@@ -696,7 +696,7 @@ var PRODUCT_CARD_IMAGE =
|
|
|
696
696
|
var PRODUCT_CARD =
|
|
697
697
|
"<a class=\"product-card\" href=\"/products/{{slug}}\">\n" +
|
|
698
698
|
" <figure class=\"product-card__media product-card__media--placeholder\">\n" +
|
|
699
|
-
" <svg class=\"media-ph__svg\" viewBox=\"0 0 160 120\" aria-hidden=\"true\"><rect width=\"160\" height=\"120\" fill=\"none\"/><g stroke=\"currentColor\" stroke-opacity=\"0.
|
|
699
|
+
" <svg class=\"media-ph__svg\" viewBox=\"0 0 160 120\" aria-hidden=\"true\"><rect width=\"160\" height=\"120\" fill=\"none\"/><g stroke=\"currentColor\" stroke-opacity=\"0.18\" stroke-width=\"1\"><path d=\"M0 30 H160 M0 60 H160 M0 90 H160 M40 0 V120 M80 0 V120 M120 0 V120\"/></g><g fill=\"none\" stroke=\"#AD38DB\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M80 38 L104 50 L104 76 L80 88 L56 76 L56 50 Z\"/><path d=\"M56 50 L80 62 L104 50 M80 62 V88\" stroke=\"#C75BE8\"/><path d=\"M70 47 L74 50 L70 53\" stroke=\"currentColor\" stroke-width=\"2\"/><path d=\"M77 54 H86\" stroke=\"currentColor\" stroke-width=\"2\"/></g><text x=\"80\" y=\"106\" text-anchor=\"middle\" font-family=\"ui-monospace,Menlo,Consolas,monospace\" font-size=\"9\" letter-spacing=\"1.5\" fill=\"#9b9ba7\">no image yet</text></svg>\n" +
|
|
700
700
|
" </figure>\n" +
|
|
701
701
|
" <div class=\"product-card__meta\">\n" +
|
|
702
702
|
" <h3 class=\"product-card__title\">{{title}}</h3>\n" +
|
package/lib/vendor/MANIFEST.json
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"_about": "blamejs.shop vendors a single framework — blamejs — which itself bundles every server-side crypto/identity dependency. The transitive packages blamejs ships are surfaced in its own MANIFEST.json at lib/vendor/blamejs/lib/vendor/MANIFEST.json — Trivy / Grype rely on that nested data for CVE attribution.",
|
|
4
4
|
"packages": {
|
|
5
5
|
"blamejs": {
|
|
6
|
-
"version": "0.13.
|
|
7
|
-
"tag": "v0.13.
|
|
6
|
+
"version": "0.13.32",
|
|
7
|
+
"tag": "v0.13.32",
|
|
8
8
|
"license": "Apache-2.0",
|
|
9
9
|
"author": "blamejs contributors",
|
|
10
10
|
"source": "https://github.com/blamejs/blamejs",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"server": "lib/vendor/blamejs/"
|
|
14
14
|
},
|
|
15
15
|
"bundler": "shallow git clone of release tag from github.com/blamejs/blamejs",
|
|
16
|
-
"bundledAt": "2026-05-
|
|
16
|
+
"bundledAt": "2026-05-29"
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -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
|