@blamejs/blamejs-shop 0.4.3 → 0.4.5
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 +8 -7
- package/lib/admin.js +376 -0
- package/lib/asset-manifest.json +5 -5
- package/lib/storefront.js +296 -9
- package/lib/vendor/MANIFEST.json +23 -23
- package/lib/vendor/blamejs/.pinact.yaml +1 -1
- package/lib/vendor/blamejs/CHANGELOG.md +2 -0
- package/lib/vendor/blamejs/SECURITY.md +1 -1
- package/lib/vendor/blamejs/api-snapshot.json +15 -2
- package/lib/vendor/blamejs/index.js +5 -1
- package/lib/vendor/blamejs/lib/auth/jar.js +190 -28
- package/lib/vendor/blamejs/lib/auth/jwt-external.js +213 -0
- package/lib/vendor/blamejs/lib/auth/oauth.js +115 -101
- package/lib/vendor/blamejs/lib/http-client.js +3 -4
- package/lib/vendor/blamejs/lib/lro.js +3 -4
- package/lib/vendor/blamejs/lib/middleware/deny-response.js +2 -10
- package/lib/vendor/blamejs/lib/middleware/health.js +1 -4
- package/lib/vendor/blamejs/lib/middleware/trace-log-correlation.js +3 -6
- package/lib/vendor/blamejs/lib/validate-opts.js +34 -0
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.14.22.json +91 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jar.test.js +226 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +122 -14
- package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +104 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +127 -0
- package/package.json +1 -1
- package/lib/vendor/blamejs/memory/specs/node-26-map-getorinsert-migration.md +0 -165
package/lib/storefront.js
CHANGED
|
@@ -288,6 +288,7 @@ var LAYOUT =
|
|
|
288
288
|
"<body>\n" +
|
|
289
289
|
" <a class=\"skip-link\" href=\"#main\">{{skip_to_content}}</a>\n" +
|
|
290
290
|
"RAW_ANNOUNCEMENT_BAR" +
|
|
291
|
+
"RAW_PROMO_TOP_STRIP" +
|
|
291
292
|
"\n" +
|
|
292
293
|
" <div class=\"utility-bar\" role=\"complementary\">\n" +
|
|
293
294
|
" <div class=\"utility-bar__inner\">\n" +
|
|
@@ -329,6 +330,7 @@ var LAYOUT =
|
|
|
329
330
|
" </div>\n" +
|
|
330
331
|
" </section>\n" +
|
|
331
332
|
"\n" +
|
|
333
|
+
"RAW_PROMO_FOOTER" +
|
|
332
334
|
" <footer class=\"site-footer\">\n" +
|
|
333
335
|
" <div class=\"site-footer__inner\">\n" +
|
|
334
336
|
" <div class=\"site-footer__brand-col\">\n" +
|
|
@@ -576,6 +578,160 @@ function _buildAnnouncementBar(row) {
|
|
|
576
578
|
"</aside>";
|
|
577
579
|
}
|
|
578
580
|
|
|
581
|
+
// ---- promo banners -----------------------------------------------------
|
|
582
|
+
//
|
|
583
|
+
// Operator-authored marketing banners rendered at six fixed placements
|
|
584
|
+
// across the storefront — `top_strip` + `footer` are sitewide chrome (every
|
|
585
|
+
// page, spliced through the LAYOUT); `homepage_hero`, `pdp_side`,
|
|
586
|
+
// `cart_side`, `search_empty` are page-specific (spliced into the matching
|
|
587
|
+
// render fn). Each placement shows the single highest-priority banner active
|
|
588
|
+
// for the request's viewer at the request instant (priority DESC, then the
|
|
589
|
+
// cache's own order), audience-filtered (all / guest / logged_in; segment is
|
|
590
|
+
// resolved against the customerSegments handle the primitive carries, when
|
|
591
|
+
// one is wired).
|
|
592
|
+
//
|
|
593
|
+
// Resolution mirrors the announcement bar: a short-TTL in-memory cache of
|
|
594
|
+
// the active rows (refreshed out-of-band, fire-and-forget) feeds a
|
|
595
|
+
// SYNCHRONOUS per-request resolver, so the picked banners can ride the same
|
|
596
|
+
// locale ALS the page handler reads (an async middleware's `enterWith` would
|
|
597
|
+
// not reach the handler). No per-request DB read on the hot render path. The
|
|
598
|
+
// edge mirrors the markup byte-for-byte via `worker/render/_lib.js`'s
|
|
599
|
+
// `promoBanner` so an edge-cached page and a container page render the same
|
|
600
|
+
// banner for the same placement + audience.
|
|
601
|
+
//
|
|
602
|
+
// Impression / click counters fire container-side only (fire-and-forget,
|
|
603
|
+
// drop-silent) — the edge has no container handle, and an edge-cached page
|
|
604
|
+
// can't bump a per-view counter regardless. Counters never block or fail a
|
|
605
|
+
// render.
|
|
606
|
+
var _PROMO_PLACEMENTS = ["top_strip", "homepage_hero", "pdp_side", "cart_side", "search_empty", "footer"];
|
|
607
|
+
var _PROMO_TTL_MS = 30000;
|
|
608
|
+
var _promoCache = { rows: [], at: 0, inflight: false };
|
|
609
|
+
|
|
610
|
+
// Refresh the active-banner cache when it's older than the TTL. Async +
|
|
611
|
+
// fire-and-forget — a slow D1 read never stalls a render; the request
|
|
612
|
+
// resolves against whatever the cache last held (empty on a cold first
|
|
613
|
+
// request, populated within the TTL after).
|
|
614
|
+
function _refreshPromoCache(promoBanners) {
|
|
615
|
+
if (!promoBanners) return;
|
|
616
|
+
var now = Date.now();
|
|
617
|
+
if (_promoCache.inflight) return;
|
|
618
|
+
if (now - _promoCache.at < _PROMO_TTL_MS && _promoCache.at !== 0) return;
|
|
619
|
+
_promoCache.inflight = true;
|
|
620
|
+
Promise.resolve()
|
|
621
|
+
.then(function () { return promoBanners.listAll({ active_only: true }); })
|
|
622
|
+
.then(function (rows) { _promoCache.rows = Array.isArray(rows) ? rows : []; _promoCache.at = Date.now(); })
|
|
623
|
+
.catch(function () { /* drop-silent — keep serving the prior cache */ })
|
|
624
|
+
.then(function () { _promoCache.inflight = false; });
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Synchronous pick across the cached active rows: for each placement keep the
|
|
628
|
+
// highest-priority row whose audience the viewer matches. `listAll({active_only})`
|
|
629
|
+
// already sorts priority DESC (then created_at ASC, slug ASC), so the first
|
|
630
|
+
// audience match per placement is the winner. Segment audience is skipped at
|
|
631
|
+
// resolve time (the console doesn't offer it; a seeded segment row would need
|
|
632
|
+
// the isMember handle the cache resolver doesn't carry per request) — exactly
|
|
633
|
+
// like the announcement bar's segment skip. Returns a map keyed by placement
|
|
634
|
+
// (value = the row or null).
|
|
635
|
+
function _resolveActivePromoBanners(viewerKind) {
|
|
636
|
+
var out = {};
|
|
637
|
+
for (var k = 0; k < _PROMO_PLACEMENTS.length; k += 1) out[_PROMO_PLACEMENTS[k]] = null;
|
|
638
|
+
var rows = _promoCache.rows;
|
|
639
|
+
if (!rows || !rows.length) return out;
|
|
640
|
+
for (var i = 0; i < rows.length; i += 1) {
|
|
641
|
+
var row = rows[i];
|
|
642
|
+
var pl = row.placement;
|
|
643
|
+
// Skip unknown placements (out has no such key) and ones already filled —
|
|
644
|
+
// the cache is priority-sorted so the first audience match per placement
|
|
645
|
+
// is the winner.
|
|
646
|
+
if (!Object.prototype.hasOwnProperty.call(out, pl) || out[pl] !== null) continue;
|
|
647
|
+
if (row.audience === "logged_in" && viewerKind !== "logged_in") continue;
|
|
648
|
+
if (row.audience === "guest" && viewerKind !== "guest") continue;
|
|
649
|
+
if (row.audience === "segment") continue;
|
|
650
|
+
out[pl] = row;
|
|
651
|
+
}
|
|
652
|
+
return out;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// Render the banner markup for a hydrated row — BYTE-IDENTICAL to
|
|
656
|
+
// lib/promo-banners.js's `renderHtml` and to the edge twin
|
|
657
|
+
// `worker/render/_lib.js`'s `promoBanner`. Returns "" for a null row so an
|
|
658
|
+
// empty placement renders nothing. Every operator field is escaped; the
|
|
659
|
+
// cta_url / image_url were https/-rooted-validated at write time, and the
|
|
660
|
+
// href sink is re-checked here so a `javascript:`/`data:` scheme can never
|
|
661
|
+
// reach the rendered link even if a row arrived by another path.
|
|
662
|
+
function _buildPromoBanner(row) {
|
|
663
|
+
if (!row) return "";
|
|
664
|
+
var esc = function (s) { return b.template.escapeHtml(String(s == null ? "" : s)); };
|
|
665
|
+
var theme = esc(row.theme || "info");
|
|
666
|
+
var placement = esc(row.placement);
|
|
667
|
+
var slug = esc(row.slug);
|
|
668
|
+
var parts = [];
|
|
669
|
+
parts.push("<div class=\"promo-banner promo-banner--" + theme + " promo-banner--" + placement +
|
|
670
|
+
"\" data-banner-slug=\"" + slug + "\">");
|
|
671
|
+
if (row.image_url) {
|
|
672
|
+
var img = String(row.image_url);
|
|
673
|
+
if (/^https:\/\//i.test(img) || (img.charAt(0) === "/" && img.charAt(1) !== "/")) {
|
|
674
|
+
parts.push("<img class=\"promo-banner__image\" src=\"" + esc(img) + "\" alt=\"\" />");
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
parts.push("<div class=\"promo-banner__body\">");
|
|
678
|
+
parts.push("<h2 class=\"promo-banner__headline\">" + esc(row.headline) + "</h2>");
|
|
679
|
+
if (row.body) {
|
|
680
|
+
var raw = String(row.body).replace(/\r\n/g, "\n").split("\n");
|
|
681
|
+
while (raw.length && raw[raw.length - 1] === "") raw.pop();
|
|
682
|
+
for (var i = 0; i < raw.length; i += 1) {
|
|
683
|
+
parts.push("<p class=\"promo-banner__line\">" + esc(raw[i]) + "</p>");
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
// The CTA points at the container click-tracking route (`/promo/:slug/
|
|
687
|
+
// click`), which bumps recordClick then 303-redirects to the banner's own
|
|
688
|
+
// operator-validated cta_url. The href is derived from the slug alone (a
|
|
689
|
+
// narrow [A-Za-z0-9._-] charset), so it carries no operator free text and
|
|
690
|
+
// is byte-identical edge + container — the edge link simply navigates to
|
|
691
|
+
// the container route on click. Rendered only when the stored cta_url is a
|
|
692
|
+
// valid https/-rooted target (the route re-validates before redirecting).
|
|
693
|
+
var href = String(row.cta_url == null ? "" : row.cta_url);
|
|
694
|
+
if (/^https:\/\//i.test(href) || (href.charAt(0) === "/" && href.charAt(1) !== "/")) {
|
|
695
|
+
parts.push("<a class=\"promo-banner__cta\" href=\"/promo/" + slug + "/click\" data-banner-slug=\"" + slug + "\">" +
|
|
696
|
+
esc(row.cta_label) + "</a>");
|
|
697
|
+
}
|
|
698
|
+
parts.push("</div>");
|
|
699
|
+
parts.push("</div>");
|
|
700
|
+
return parts.join("");
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Fire-and-forget impression bump for a rendered banner. Drop-silent on the
|
|
704
|
+
// hot render path — the counter is supplementary; an absent handle / failed
|
|
705
|
+
// write never affects the response. The primitive's recordImpression is
|
|
706
|
+
// itself drop-silent, so this only guards the call shape + the promise tail.
|
|
707
|
+
function _firePromoImpression(handle, slug) {
|
|
708
|
+
if (!handle || typeof handle.recordImpression !== "function" || !slug) return;
|
|
709
|
+
try {
|
|
710
|
+
var r = handle.recordImpression(slug);
|
|
711
|
+
if (r && typeof r.then === "function") r.then(function () {}, function () {});
|
|
712
|
+
} catch (_e) { /* drop-silent — impression bump must not affect render */ }
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// Resolve the pre-rendered HTML for a placement from the request's ALS store
|
|
716
|
+
// (seeded by `promoBannerMiddleware`), or an explicit `opts.promo_banners`
|
|
717
|
+
// map a renderer / unit test threads. Returns "" when no banner is active.
|
|
718
|
+
// When the ALS path renders a banner, fires a best-effort impression for it
|
|
719
|
+
// (the explicit-opts path is the edge twin / unit test, which never counts).
|
|
720
|
+
function _promoBannerHtml(opts, placement) {
|
|
721
|
+
if (opts && opts.promo_banners && typeof opts.promo_banners === "object" &&
|
|
722
|
+
typeof opts.promo_banners[placement] === "string") {
|
|
723
|
+
return opts.promo_banners[placement];
|
|
724
|
+
}
|
|
725
|
+
var storeCtx = _localeAls.getStore();
|
|
726
|
+
var map = (storeCtx && storeCtx.promo_banners) || null;
|
|
727
|
+
if (map && map[placement]) {
|
|
728
|
+
var row = map[placement];
|
|
729
|
+
_firePromoImpression(storeCtx && storeCtx.promo_banners_handle, row.slug);
|
|
730
|
+
return _buildPromoBanner(row);
|
|
731
|
+
}
|
|
732
|
+
return "";
|
|
733
|
+
}
|
|
734
|
+
|
|
579
735
|
// Multi-currency display switcher — a GET form in the footer listing the
|
|
580
736
|
// operator's display currencies. Selecting one POSTs to /currency, which
|
|
581
737
|
// sets the sealed `shop_ccy` cookie and redirects back. The currently
|
|
@@ -793,6 +949,13 @@ function _wrap(opts) {
|
|
|
793
949
|
var announcementScript = (announcementRow && announcementRow.dismissible)
|
|
794
950
|
? _islandScript("announcement.js", { id: "announcement-island" })
|
|
795
951
|
: "";
|
|
952
|
+
// Sitewide promo banners (top_strip above the chrome, footer above the
|
|
953
|
+
// site footer) — pre-rendered HTML from the ALS-resolved map, or "" when
|
|
954
|
+
// no banner is active for the request's audience. Page-specific placements
|
|
955
|
+
// (homepage_hero / pdp_side / cart_side / search_empty) are spliced by the
|
|
956
|
+
// matching render fn, not the LAYOUT.
|
|
957
|
+
var promoTopStrip = _promoBannerHtml(opts, "top_strip");
|
|
958
|
+
var promoFooter = _promoBannerHtml(opts, "footer");
|
|
796
959
|
var chrome = localeCtx.chrome;
|
|
797
960
|
var cartCount = opts.cart_count == null ? 0 : opts.cart_count;
|
|
798
961
|
// The cart aria-label carries the count: when the resolved string is
|
|
@@ -882,6 +1045,11 @@ function _wrap(opts) {
|
|
|
882
1045
|
// Matches the edge renderers' `spliceRaw` so the dual-render stays
|
|
883
1046
|
// byte-consistent under a `$`-bearing announcement. See `_spliceRaw`.
|
|
884
1047
|
assembled = _spliceRaw(assembled, "RAW_ANNOUNCEMENT_BAR", announcementBarHtml);
|
|
1048
|
+
// Sitewide promo banners carry operator marketing copy (HTML-escaped, but a
|
|
1049
|
+
// `$` can survive), so splice via the replacer-function helper like the
|
|
1050
|
+
// announcement bar — byte-consistent with the edge `spliceRaw`.
|
|
1051
|
+
assembled = _spliceRaw(assembled, "RAW_PROMO_TOP_STRIP", promoTopStrip);
|
|
1052
|
+
assembled = _spliceRaw(assembled, "RAW_PROMO_FOOTER", promoFooter);
|
|
885
1053
|
// Primary nav — a raw splice (post strict-render) so the chrome strings
|
|
886
1054
|
// it consumes (nav_shop / nav_collections / nav_categories /
|
|
887
1055
|
// nav_framework / nav_account / nav_menu / nav_cart_aria) need no LAYOUT
|
|
@@ -1273,7 +1441,11 @@ function renderHome(opts) {
|
|
|
1273
1441
|
// resolves the absolute base from the shop name (a bare host or a full
|
|
1274
1442
|
// URL both normalise to `https://<host>`).
|
|
1275
1443
|
var homeJsonLd = _orgWebsiteJsonLd(shopName);
|
|
1276
|
-
|
|
1444
|
+
// Homepage-hero promo banner — operator marketing block above the hero.
|
|
1445
|
+
// Resolved from the request ALS (or threaded `opts.promo_banners`); "" when
|
|
1446
|
+
// none is active. Byte-identical to the edge `home.js` placement.
|
|
1447
|
+
var promoHero = _promoBannerHtml(opts, "homepage_hero");
|
|
1448
|
+
var body = promoHero + hero + catalog + homeJsonLd;
|
|
1277
1449
|
return _wrap(Object.assign({
|
|
1278
1450
|
title: title,
|
|
1279
1451
|
shop_name: shopName,
|
|
@@ -1283,6 +1455,7 @@ function renderHome(opts) {
|
|
|
1283
1455
|
og_url: opts.og_url,
|
|
1284
1456
|
og_description: "Shop the blamejs.shop catalog — an open-source, server-rendered storefront with post-quantum crypto and zero npm runtime dependencies.",
|
|
1285
1457
|
body: body,
|
|
1458
|
+
promo_banners: opts.promo_banners,
|
|
1286
1459
|
}, _currencyWrapOpts(opts)));
|
|
1287
1460
|
}
|
|
1288
1461
|
|
|
@@ -1735,13 +1908,19 @@ function renderSearch(opts) {
|
|
|
1735
1908
|
var chipsHtml = (qTrim.length > 0) ? _renderSearchChips(facets, filters, opts.q) : "";
|
|
1736
1909
|
|
|
1737
1910
|
var header = _render(SEARCH_HEADER, { title: title, summary: summary });
|
|
1911
|
+
// search_empty promo banner — operator marketing block shown alongside the
|
|
1912
|
+
// no-results state (the placement is named for "in place of no-results
|
|
1913
|
+
// copy"). Resolved from the request ALS (or threaded `opts.promo_banners`);
|
|
1914
|
+
// "" when none is active. Byte-identical to the edge `search.js` placement.
|
|
1915
|
+
var promoSearchEmpty = _promoBannerHtml(opts, "search_empty");
|
|
1738
1916
|
var resultsInner;
|
|
1739
1917
|
if (products.length === 0) {
|
|
1740
1918
|
var clearLink = hasFilters
|
|
1741
1919
|
? _render("<a href=\"{{href}}\" class=\"btn-ghost\">Clear filters</a>", { href: _searchUrl(opts.q, {}) })
|
|
1742
1920
|
: "";
|
|
1743
|
-
resultsInner =
|
|
1744
|
-
|
|
1921
|
+
resultsInner = promoSearchEmpty +
|
|
1922
|
+
_render(SEARCH_EMPTY, { heading: emptyHeading, copy: emptyCopy, clear_link: "RAW_CLEAR" })
|
|
1923
|
+
.replace("RAW_CLEAR", clearLink);
|
|
1745
1924
|
} else {
|
|
1746
1925
|
var assetPrefix = opts.asset_prefix || "/assets/";
|
|
1747
1926
|
var fmt = _priceFormatter(opts);
|
|
@@ -1790,6 +1969,7 @@ function renderSearch(opts) {
|
|
|
1790
1969
|
// but let crawlers follow the product links the page lists.
|
|
1791
1970
|
robots: "noindex,follow",
|
|
1792
1971
|
body: body,
|
|
1972
|
+
promo_banners: opts.promo_banners,
|
|
1793
1973
|
}, _currencyWrapOpts(opts)));
|
|
1794
1974
|
}
|
|
1795
1975
|
|
|
@@ -6386,6 +6566,11 @@ function renderProduct(opts) {
|
|
|
6386
6566
|
var qaPageJsonLd = _buildQaPageJsonLd(opts.qa_questions);
|
|
6387
6567
|
jsonLd = (jsonLd || "") + breadcrumbJsonLd + qaPageJsonLd;
|
|
6388
6568
|
|
|
6569
|
+
// pdp_side promo banner — operator marketing block alongside the product.
|
|
6570
|
+
// Resolved from the request ALS (or threaded `opts.promo_banners`); "" when
|
|
6571
|
+
// none is active. Byte-identical to the edge `product.js` placement.
|
|
6572
|
+
var promoPdpSide = _promoBannerHtml(opts, "pdp_side");
|
|
6573
|
+
|
|
6389
6574
|
return _wrap(Object.assign({
|
|
6390
6575
|
title: opts.product.title,
|
|
6391
6576
|
shop_name: shopName,
|
|
@@ -6397,7 +6582,8 @@ function renderProduct(opts) {
|
|
|
6397
6582
|
og_image: ogImage,
|
|
6398
6583
|
canonical_url: opts.canonical_url,
|
|
6399
6584
|
og_url: opts.og_url,
|
|
6400
|
-
body: body + jsonLd,
|
|
6585
|
+
body: promoPdpSide + body + jsonLd,
|
|
6586
|
+
promo_banners: opts.promo_banners,
|
|
6401
6587
|
}, _currencyWrapOpts(opts)));
|
|
6402
6588
|
}
|
|
6403
6589
|
|
|
@@ -7924,9 +8110,14 @@ function renderCart(opts) {
|
|
|
7924
8110
|
});
|
|
7925
8111
|
}
|
|
7926
8112
|
function _escAttr(s) { return b.template.escapeHtml(s); }
|
|
8113
|
+
// cart_side promo banner — operator marketing block adjacent to the cart
|
|
8114
|
+
// summary. Container-only (the cart page is session-bound, never edge-
|
|
8115
|
+
// cached), resolved from the request ALS (or threaded `opts.promo_banners`);
|
|
8116
|
+
// "" when none is active.
|
|
8117
|
+
var promoCartSide = _promoBannerHtml(opts, "cart_side");
|
|
7927
8118
|
var body;
|
|
7928
8119
|
if (rendered.length === 0) {
|
|
7929
|
-
body = CART_EMPTY_PAGE;
|
|
8120
|
+
body = promoCartSide + CART_EMPTY_PAGE;
|
|
7930
8121
|
} else {
|
|
7931
8122
|
var canSave = !!opts.can_save;
|
|
7932
8123
|
var rows = rendered.map(function (l) {
|
|
@@ -8010,7 +8201,7 @@ function renderCart(opts) {
|
|
|
8010
8201
|
// empty. Indented to match the aside's two-space block.
|
|
8011
8202
|
var cartEstimateHtml = _buildDeliveryEstimate(opts.delivery_estimate, b.template.escapeHtml);
|
|
8012
8203
|
cartEstimateHtml = cartEstimateHtml ? " " + cartEstimateHtml + "\n" : "";
|
|
8013
|
-
body = _render(CART_PAGE, {
|
|
8204
|
+
body = promoCartSide + _render(CART_PAGE, {
|
|
8014
8205
|
line_rows: "RAW_LINES",
|
|
8015
8206
|
}).replace("RAW_LINES", rows)
|
|
8016
8207
|
.replace("RAW_TOTALS_ROWS", totalsRows)
|
|
@@ -8041,6 +8232,7 @@ function renderCart(opts) {
|
|
|
8041
8232
|
// describing rather than relying on robots.txt alone.
|
|
8042
8233
|
robots: "noindex",
|
|
8043
8234
|
body: body,
|
|
8235
|
+
promo_banners: opts.promo_banners,
|
|
8044
8236
|
}, _currencyWrapOpts(opts)));
|
|
8045
8237
|
}
|
|
8046
8238
|
|
|
@@ -8937,6 +9129,17 @@ function _setLocaleCookie(res, locale) {
|
|
|
8937
9129
|
|
|
8938
9130
|
// ---- account-page renderers --------------------------------------------
|
|
8939
9131
|
|
|
9132
|
+
// One sign-in screen offering BOTH passwordless paths. The passkey form is
|
|
9133
|
+
// the primary action (a JS island posts the WebAuthn ceremony to
|
|
9134
|
+
// /account/passkey/login-*). The email magic-link is rendered inline as a
|
|
9135
|
+
// SERVER-RENDERED form that POSTs to /account/login/link — it works with
|
|
9136
|
+
// JavaScript disabled and is the always-available backup so a browser
|
|
9137
|
+
// without WebAuthn (or a failed ceremony) is never a dead end. The two
|
|
9138
|
+
// forms are independent <form> elements: the no-JS fallback never depends
|
|
9139
|
+
// on the island. The magic-link block only renders when the operator has
|
|
9140
|
+
// wired the customer-portal primitive AND a transactional mailer (the GET
|
|
9141
|
+
// route sets `magic_link_enabled`); absent it, the page degrades to the
|
|
9142
|
+
// passkey path with no broken affordance.
|
|
8940
9143
|
var ACCOUNT_LOGIN_PAGE =
|
|
8941
9144
|
"<section class=\"auth-page\">\n" +
|
|
8942
9145
|
" <div class=\"auth-card\">\n" +
|
|
@@ -8957,6 +9160,23 @@ var ACCOUNT_LOGIN_PAGE =
|
|
|
8957
9160
|
" RAW_LOGIN_SCRIPT\n" +
|
|
8958
9161
|
"</section>\n";
|
|
8959
9162
|
|
|
9163
|
+
// The inline email magic-link path on the unified login screen. A distinct
|
|
9164
|
+
// server-rendered <form> (its own email field) that POSTs to
|
|
9165
|
+
// /account/login/link with no JavaScript — the `_injectCsrfFields` wrap
|
|
9166
|
+
// chokepoint stamps the `_csrf` token automatically (the action is not an
|
|
9167
|
+
// EDGE_POST_PATHS prefix), so a no-JS browser submits an accepted token.
|
|
9168
|
+
// `data-passkey-fallback` lets passkey-login.js point a user here in one tap
|
|
9169
|
+
// when WebAuthn is unsupported or the ceremony fails — no dead end.
|
|
9170
|
+
var LOGIN_MAGIC_INLINE =
|
|
9171
|
+
"<div class=\"auth-oauth\" data-passkey-fallback>" +
|
|
9172
|
+
"<div class=\"auth-oauth__divider\"><span>or</span></div>" +
|
|
9173
|
+
"<p class=\"auth-card__lede\">No passkey on this device? We'll email you a single-use sign-in link.</p>" +
|
|
9174
|
+
"<form method=\"post\" action=\"/account/login/link\" class=\"form-stack auth-form auth-form--magic\">" +
|
|
9175
|
+
"<div class=\"form-row\"><label class=\"form-field\"><span class=\"form-field__label\">Email</span><input type=\"email\" name=\"email\" id=\"magic-email\" required autocomplete=\"email\"></label></div>" +
|
|
9176
|
+
"<div class=\"form-actions\"><button type=\"submit\" class=\"btn-secondary auth-form__submit\">Email me a sign-in link</button></div>" +
|
|
9177
|
+
"</form>" +
|
|
9178
|
+
"</div>";
|
|
9179
|
+
|
|
8960
9180
|
var LOGIN_ERROR_MESSAGES = {
|
|
8961
9181
|
oauth: "We couldn't complete that sign-in. Please try again.",
|
|
8962
9182
|
"email-conflict": "That email already has an account — sign in with your passkey instead.",
|
|
@@ -8981,9 +9201,9 @@ function renderAccountLogin(opts) {
|
|
|
8981
9201
|
var errHtml = (opts.error && LOGIN_ERROR_MESSAGES[opts.error])
|
|
8982
9202
|
? "<p class=\"auth-form__message auth-form__message--err\">" + b.template.escapeHtml(LOGIN_ERROR_MESSAGES[opts.error]) + "</p>"
|
|
8983
9203
|
: "";
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
9204
|
+
// Render the email-link path INLINE (a working no-JS form), not as a link
|
|
9205
|
+
// to a separate page, so both passwordless paths live on one screen.
|
|
9206
|
+
var magicHtml = opts.magic_link_enabled ? LOGIN_MAGIC_INLINE : "";
|
|
8987
9207
|
var body = ACCOUNT_LOGIN_PAGE
|
|
8988
9208
|
.replace("RAW_LOGIN_OAUTH", oauthHtml)
|
|
8989
9209
|
.replace("RAW_LOGIN_MAGIC", magicHtml)
|
|
@@ -10588,6 +10808,60 @@ function mount(router, deps) {
|
|
|
10588
10808
|
});
|
|
10589
10809
|
}
|
|
10590
10810
|
|
|
10811
|
+
// Promo-banner resolution — synchronous (so its `enterWith` reaches the
|
|
10812
|
+
// page handler) and audience-bucketed off the auth-cookie presence, exactly
|
|
10813
|
+
// like the announcement bar. Seeds the request ALS with the resolved
|
|
10814
|
+
// per-placement map (`promo_banners`) + the handle (`promo_banners_handle`)
|
|
10815
|
+
// so the render fns can splice each placement's markup and fire a best-
|
|
10816
|
+
// effort impression at the render sink. The active set rides a short-TTL
|
|
10817
|
+
// in-memory cache refreshed out-of-band here (fire-and-forget — never blocks
|
|
10818
|
+
// the render). Best-effort: any failure drops the banners, never the page.
|
|
10819
|
+
if (typeof router.use === "function" && deps.promoBanners) {
|
|
10820
|
+
router.use(function promoBannerMiddleware(req, _res, next) {
|
|
10821
|
+
try {
|
|
10822
|
+
_refreshPromoCache(deps.promoBanners);
|
|
10823
|
+
var viewerKind = _readPrefixedCookie(req, AUTH_COOKIE_NAME_SECURE, AUTH_COOKIE_NAME) ? "logged_in" : "guest";
|
|
10824
|
+
var map = _resolveActivePromoBanners(viewerKind);
|
|
10825
|
+
var cur = _localeAls.getStore() || {};
|
|
10826
|
+
_localeAls.enterWith(Object.assign({}, cur, { promo_banners: map, promo_banners_handle: deps.promoBanners }));
|
|
10827
|
+
} catch (_e) { /* drop-silent — no banners this request */ }
|
|
10828
|
+
next();
|
|
10829
|
+
});
|
|
10830
|
+
|
|
10831
|
+
// Click pass-through — the banner CTA links here so a click is counted
|
|
10832
|
+
// before the shopper reaches the destination. Bumps recordClick (best-
|
|
10833
|
+
// effort, drop-silent) then 303-redirects to the banner's own cta_url.
|
|
10834
|
+
// The destination is taken from the LIVE banner row (not a query param),
|
|
10835
|
+
// so the redirect target is the operator-validated https/-rooted URL the
|
|
10836
|
+
// primitive already vetted — a hostile/stale slug, or one with no live
|
|
10837
|
+
// banner, falls back to "/" and can never 500 or open-redirect.
|
|
10838
|
+
router.get("/promo/:slug/click", async function (req, res) {
|
|
10839
|
+
var slug = (req.params && typeof req.params.slug === "string") ? req.params.slug : "";
|
|
10840
|
+
var to = "/";
|
|
10841
|
+
if (/^[A-Za-z0-9][A-Za-z0-9._-]{0,79}$/.test(slug)) {
|
|
10842
|
+
try {
|
|
10843
|
+
var row = await deps.promoBanners.getBanner(slug);
|
|
10844
|
+
if (row && row.cta_url) {
|
|
10845
|
+
var href = String(row.cta_url);
|
|
10846
|
+
// Re-validate the destination at the redirect sink — https:// or a
|
|
10847
|
+
// /-rooted path (not protocol-relative `//`). The primitive vetted
|
|
10848
|
+
// this at write time; re-checking keeps a stored bad value from
|
|
10849
|
+
// ever becoming an open redirect.
|
|
10850
|
+
if (/^https:\/\//i.test(href) || (href.charAt(0) === "/" && href.charAt(1) !== "/")) {
|
|
10851
|
+
to = href;
|
|
10852
|
+
}
|
|
10853
|
+
}
|
|
10854
|
+
// recordClick is drop-silent on unknown slug; fire-and-forget.
|
|
10855
|
+
var r = deps.promoBanners.recordClick(slug);
|
|
10856
|
+
if (r && typeof r.then === "function") { try { await r; } catch (_e) { /* drop-silent */ } }
|
|
10857
|
+
} catch (_e) { /* unknown slug / read error → fall back to "/" */ }
|
|
10858
|
+
}
|
|
10859
|
+
res.status(303);
|
|
10860
|
+
res.setHeader && res.setHeader("location", to);
|
|
10861
|
+
return res.end ? res.end() : res.send("");
|
|
10862
|
+
});
|
|
10863
|
+
}
|
|
10864
|
+
|
|
10591
10865
|
// ---- customer survey (token-gated) ----------------------------------
|
|
10592
10866
|
// The invitation token IS the access — no login. GET renders the survey
|
|
10593
10867
|
// (or a state notice); POST records the response. Container-only (the
|
|
@@ -13442,6 +13716,19 @@ function mount(router, deps) {
|
|
|
13442
13716
|
}
|
|
13443
13717
|
|
|
13444
13718
|
router.get("/account/login", async function (req, res) {
|
|
13719
|
+
// An already-signed-in visitor has no business on the sign-in screen —
|
|
13720
|
+
// send them to their account instead of re-rendering a login form
|
|
13721
|
+
// (mirrors the /account guard's auth read + vault-not-configured catch).
|
|
13722
|
+
var signedIn;
|
|
13723
|
+
try { signedIn = _currentCustomer(req); }
|
|
13724
|
+
catch (e) {
|
|
13725
|
+
if (e && e.code === "vault/not-initialized") return _serviceUnavailable(res, "auth not configured");
|
|
13726
|
+
throw e;
|
|
13727
|
+
}
|
|
13728
|
+
if (signedIn) {
|
|
13729
|
+
res.status(303); res.setHeader && res.setHeader("location", "/account");
|
|
13730
|
+
return res.end ? res.end() : res.send("");
|
|
13731
|
+
}
|
|
13445
13732
|
var cartCount = await _cartCountForReq(req);
|
|
13446
13733
|
var url = req.url ? new URL(req.url, "http://localhost") : null;
|
|
13447
13734
|
// Login captcha is opt-in (CAPTCHA_GATE_LOGIN). The widget + the scoped
|
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.14.
|
|
7
|
-
"tag": "v0.14.
|
|
6
|
+
"version": "0.14.22",
|
|
7
|
+
"tag": "v0.14.22",
|
|
8
8
|
"license": "Apache-2.0",
|
|
9
9
|
"author": "blamejs contributors",
|
|
10
10
|
"source": "https://github.com/blamejs/blamejs",
|
|
@@ -791,7 +791,6 @@
|
|
|
791
791
|
"lib/worm.js": "lib/vendor/blamejs/lib/worm.js",
|
|
792
792
|
"lib/ws-client.js": "lib/vendor/blamejs/lib/ws-client.js",
|
|
793
793
|
"lib/xml-c14n.js": "lib/vendor/blamejs/lib/xml-c14n.js",
|
|
794
|
-
"memory/specs/node-26-map-getorinsert-migration.md": "lib/vendor/blamejs/memory/specs/node-26-map-getorinsert-migration.md",
|
|
795
794
|
"oss-fuzz/projects/blamejs/Dockerfile": "lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile",
|
|
796
795
|
"oss-fuzz/projects/blamejs/README.md": "lib/vendor/blamejs/oss-fuzz/projects/blamejs/README.md",
|
|
797
796
|
"oss-fuzz/projects/blamejs/build.sh": "lib/vendor/blamejs/oss-fuzz/projects/blamejs/build.sh",
|
|
@@ -817,6 +816,7 @@
|
|
|
817
816
|
"release-notes/v0.14.2.json": "lib/vendor/blamejs/release-notes/v0.14.2.json",
|
|
818
817
|
"release-notes/v0.14.20.json": "lib/vendor/blamejs/release-notes/v0.14.20.json",
|
|
819
818
|
"release-notes/v0.14.21.json": "lib/vendor/blamejs/release-notes/v0.14.21.json",
|
|
819
|
+
"release-notes/v0.14.22.json": "lib/vendor/blamejs/release-notes/v0.14.22.json",
|
|
820
820
|
"release-notes/v0.14.3.json": "lib/vendor/blamejs/release-notes/v0.14.3.json",
|
|
821
821
|
"release-notes/v0.14.4.json": "lib/vendor/blamejs/release-notes/v0.14.4.json",
|
|
822
822
|
"release-notes/v0.14.5.json": "lib/vendor/blamejs/release-notes/v0.14.5.json",
|
|
@@ -1383,9 +1383,9 @@
|
|
|
1383
1383
|
".gitleaks.toml": "sha256:e97869021bc744236bd882a2af070eebbbc95d211336c60bf179f6521d6ed96b",
|
|
1384
1384
|
".hadolint.yaml": "sha256:46a4fbc587c8e5998430788339cc3f2be8d1014a0466a0781eb2e51e31c6dd32",
|
|
1385
1385
|
".npmrc": "sha256:66f104e7d07c496d2d0409988225e8c0e4ceb8d247dbcac3be75b2128d20ce66",
|
|
1386
|
-
".pinact.yaml": "sha256:
|
|
1386
|
+
".pinact.yaml": "sha256:0213ffda55961dc49b64c0a5dfa3c0567419633b1499d57eaf7c8d842d7da6c7",
|
|
1387
1387
|
"ARCHITECTURE.md": "sha256:9b1c8d2b1b7a41838eb348b0a008e4b4369718fd72bfe2974b37155f7536d35b",
|
|
1388
|
-
"CHANGELOG.md": "sha256:
|
|
1388
|
+
"CHANGELOG.md": "sha256:c0b12053e79aa39d75018f3e5e33af6c543236b515175aa912c589bfb1d556c1",
|
|
1389
1389
|
"CODE_OF_CONDUCT.md": "sha256:148a281960fff7c2fe6554dab66da572c72245ddeb00b0d14811558397bff386",
|
|
1390
1390
|
"CONTRIBUTING.md": "sha256:bb4dbdbc8598da31dbce653a8ed322e08ff46560173f2eb67a4d684653948332",
|
|
1391
1391
|
"GOVERNANCE.md": "sha256:906df6afb1f552b27b9acb50f7f96c47b917a2f1021cd4e987dbf4ee0e0a821b",
|
|
@@ -1394,8 +1394,8 @@
|
|
|
1394
1394
|
"MIGRATING.md": "sha256:e6a7e89578e0d7759183e5dfdf67dfb4ecd94aefe0fde2921fd91985ad57ef59",
|
|
1395
1395
|
"NOTICE": "sha256:f487fa47a11aca0f89e2615cdd3c713e9842abf7a30d8d328eeeae1c864aa774",
|
|
1396
1396
|
"README.md": "sha256:d81e9f6978eb937af294d7d0c33f869abdebdc906e77d7aeadff399a7e5a8824",
|
|
1397
|
-
"SECURITY.md": "sha256:
|
|
1398
|
-
"api-snapshot.json": "sha256:
|
|
1397
|
+
"SECURITY.md": "sha256:ca67ec6b0638d0c64a69e7d260d2b4a101db84d240fe450dd54974c085a26ab1",
|
|
1398
|
+
"api-snapshot.json": "sha256:b914510a543b565493f7783c93725d47444cc457ce2388559cf1a36071034e19",
|
|
1399
1399
|
"assets/BlameJS_Logo.png": "sha256:3c65699753c771b48ef9ac7f45bb40815ec19a23afcdd0cd30ef4601bbbe293e",
|
|
1400
1400
|
"assets/BlameJS_Logo.svg": "sha256:dda44f3fb1343d5de9db6b1fcdb75fc649c57e7a99a8e8239fcf852e3841e1a8",
|
|
1401
1401
|
"bench/README.md": "sha256:74202f2507fd840bfc1ac6c681975d9273cf36cca6e0f72655f138337304033c",
|
|
@@ -1583,7 +1583,7 @@
|
|
|
1583
1583
|
"fuzz/safe-url_seed_corpus/05-ipv6.txt": "sha256:b210575d6e9f91b70d1616c89a38bf81e66e4356dcf204a3d40f1932961d01cc",
|
|
1584
1584
|
"fuzz/safe-url_seed_corpus/06-idn.txt": "sha256:9f163641afe7046491b09f95684e30aac38b3cbf243afb115c556ae4fc0339f0",
|
|
1585
1585
|
"fuzz/safe-vcard.fuzz.js": "sha256:20ef167055ea75b6138bc6dc9d8cbdcf108d92be2792571a0162b849671354bd",
|
|
1586
|
-
"index.js": "sha256:
|
|
1586
|
+
"index.js": "sha256:0715f7b351f0f769b4eb1994baa46f85541e1dc329b7cf0abd9b61c39c5cdcec",
|
|
1587
1587
|
"keys/release-pqc-pub.json": "sha256:38fb7f580ccc06c5682c5c3f12b43441d4fdd3e79cf57afb8b3dab3a73af290d",
|
|
1588
1588
|
"lib/_test/crypto-fixtures.js": "sha256:91470fc813e41eeed06dee1e8fbb92d179af77eb01109c1256f7330cb2fc0980",
|
|
1589
1589
|
"lib/a2a-tasks.js": "sha256:8308a8a00790035090ae2912030c288e0cf4eaa29134f4c73bb38ddef02a4e59",
|
|
@@ -1648,11 +1648,11 @@
|
|
|
1648
1648
|
"lib/auth/elevation-grant.js": "sha256:c152c403050b08106f687e46ee85b5d80f160f6e346b5c2d278381f039eca143",
|
|
1649
1649
|
"lib/auth/fal.js": "sha256:aabf6d8095dd41dcda8a2efdb48e00e95bffe70c78991c93fbef827816918692",
|
|
1650
1650
|
"lib/auth/fido-mds3.js": "sha256:5ddd58557a0331bb39e7606c15cb0f29fbc38fd85f51c99c93d16621db99261e",
|
|
1651
|
-
"lib/auth/jar.js": "sha256:
|
|
1652
|
-
"lib/auth/jwt-external.js": "sha256:
|
|
1651
|
+
"lib/auth/jar.js": "sha256:f333f25a87b8c60f5f19c51d68aefba8ae8ed304e0f54a957560475359e11f7f",
|
|
1652
|
+
"lib/auth/jwt-external.js": "sha256:4fcf0443decf374aed4d0a328ce769df2d321981afe5a9496c57e1ef90938db7",
|
|
1653
1653
|
"lib/auth/jwt.js": "sha256:032dec9c7a117ef728ded26ac681b846ff4b98112074aa890c499c97902cbec4",
|
|
1654
1654
|
"lib/auth/lockout.js": "sha256:44afb265e064401fc2bedfb46673f822fb24c1ffae05cdb116949ce0f841a813",
|
|
1655
|
-
"lib/auth/oauth.js": "sha256:
|
|
1655
|
+
"lib/auth/oauth.js": "sha256:4883d3d054933908c636e06c39147e0187a2805fdc0e045300b635aba6101454",
|
|
1656
1656
|
"lib/auth/oid4vci.js": "sha256:f8595472abd01beb635ce03fc79e305e288ae7802587ec8f75229d2efa2c8294",
|
|
1657
1657
|
"lib/auth/oid4vp.js": "sha256:ec2098480638e70d8b7b450242b5d158d52ac3d0f2aea59d6dfc345e8451a29f",
|
|
1658
1658
|
"lib/auth/openid-federation.js": "sha256:e39b72665c6ab95b233f94ed44dc4e30b9e9a5ae79d0e94fe3474f8e23dba9c5",
|
|
@@ -1834,7 +1834,7 @@
|
|
|
1834
1834
|
"lib/html-balance.js": "sha256:325db4349ac4c968704e295f2c8cbec330c2d64908c89e9192ab443572c14910",
|
|
1835
1835
|
"lib/http-client-cache.js": "sha256:5bc95d801cffbde654d5216963dec888ff12ff150c2e82129f0f6d1dbb88b6cf",
|
|
1836
1836
|
"lib/http-client-cookie-jar.js": "sha256:d0e859a9b548a3dc97e3418a1698b27336021f8f7d6c5327b2004dd710fa06dc",
|
|
1837
|
-
"lib/http-client.js": "sha256:
|
|
1837
|
+
"lib/http-client.js": "sha256:885e960349c30cca15b2092c37ea275b11f15226b2e0b7c74871020c11a9bda9",
|
|
1838
1838
|
"lib/http-message-signature.js": "sha256:9aae3f9231c607d4fdc7693aa8b473744af807bff07b7c50c3cf1bd0b07a3283",
|
|
1839
1839
|
"lib/http2-teardown.js": "sha256:61d291c34e321e18b64d60a4c0253e638550fff7dc32568b980d3aa13bb178e2",
|
|
1840
1840
|
"lib/i18n-messageformat.js": "sha256:9f7cc5761f9343e87a210b58706eed01fbfb66c563ad479e75a492b1365a25a1",
|
|
@@ -1868,7 +1868,7 @@
|
|
|
1868
1868
|
"lib/log-stream-webhook.js": "sha256:390d771da48b3b084d1438f05a348ca34390084d5972074f75742110718e4622",
|
|
1869
1869
|
"lib/log-stream.js": "sha256:9ffda79044835670fba447876b617b1d5cef0592abf08b52167e2ae7b6bcdba7",
|
|
1870
1870
|
"lib/log.js": "sha256:2c6215248d5db3d7b3b75495d00ffe1f5c72f3fccc1365aa7f5a550ff153d9a6",
|
|
1871
|
-
"lib/lro.js": "sha256:
|
|
1871
|
+
"lib/lro.js": "sha256:da9baf47f27c422c32d51495b2896c887ec3ac283875712efcd7528fd396868b",
|
|
1872
1872
|
"lib/mail-agent.js": "sha256:8d2c17ac5b1039689eed9ee236a806d89ca48ccc546d7f3ad330a4bb4e475e7c",
|
|
1873
1873
|
"lib/mail-arc-sign.js": "sha256:ab7a36916d78e60664d4509133cb834bf20c5dacb298404b209d4da991b4cfd5",
|
|
1874
1874
|
"lib/mail-arf.js": "sha256:13163945823f1cdc4bc3b5ae16b40bedeaea5f4a161f64340398523c9f54659c",
|
|
@@ -1929,14 +1929,14 @@
|
|
|
1929
1929
|
"lib/middleware/csrf-protect.js": "sha256:20f4f529481a31e5e8ca04019ad912b00c25c95eac21cc27ac54d7ba33921271",
|
|
1930
1930
|
"lib/middleware/daily-byte-quota.js": "sha256:b1d93d7629838a995ebffeca4f2399cad3d66361e0f67c80b81aa2eb64018fdd",
|
|
1931
1931
|
"lib/middleware/db-role-for.js": "sha256:b9879c17dbf7fa3d299f402043592a133176a74ac1bcb49b0b717253d4ad1d3a",
|
|
1932
|
-
"lib/middleware/deny-response.js": "sha256:
|
|
1932
|
+
"lib/middleware/deny-response.js": "sha256:381241477b78614fb4c39f0ee1a23875403f4c398fb5d0a021c521ae36fa06e6",
|
|
1933
1933
|
"lib/middleware/dpop.js": "sha256:09f8c1ef796d15da18aa8ba081115e24466e292892b4abec5416a788e77b6c14",
|
|
1934
1934
|
"lib/middleware/error-handler.js": "sha256:7c0baf2e6b37f1c9330775396bc46a87943a253ceba540379db4785d305c396c",
|
|
1935
1935
|
"lib/middleware/fetch-metadata.js": "sha256:0be11ee9eeeaf069a553732c8ee7172ea1f01311d93af66b9402f5976b16cd3f",
|
|
1936
1936
|
"lib/middleware/flag-context.js": "sha256:76fefb869244267f3b2bf24c4dd0b40fcba0988552b62d8b48208d116b85ee3f",
|
|
1937
1937
|
"lib/middleware/gpc.js": "sha256:6bfc817381582e060ecead9829f92d044dbc6902c86e383429827622044e9a8d",
|
|
1938
1938
|
"lib/middleware/headers.js": "sha256:d53abbe53b1981df5b934aad06dc4588729ce2024f014d2b4b0aa5ff0701cebd",
|
|
1939
|
-
"lib/middleware/health.js": "sha256:
|
|
1939
|
+
"lib/middleware/health.js": "sha256:d9e95a38cd18a1236b4787901f6145b258e9a63d98f98eb34e6200489673a4e3",
|
|
1940
1940
|
"lib/middleware/host-allowlist.js": "sha256:c5572e12b460c69dcc98664eb95a4c810f08c95e66ee8f24f860e08f70b8e3fa",
|
|
1941
1941
|
"lib/middleware/idempotency-key.js": "sha256:9ae08ef63e7f87e34a77e958d52615b57264ad9c9350c27352ba2dcbbd93eb49",
|
|
1942
1942
|
"lib/middleware/index.js": "sha256:01643697e716ab912fab7f214d5d51eb1d70ca4363ad67fba5b912be2ccc0c16",
|
|
@@ -1961,7 +1961,7 @@
|
|
|
1961
1961
|
"lib/middleware/span-http-server.js": "sha256:9fb94fa14c41b2969cce5bc9877ce49de3576d3991cfc7cc64ef2129fdec2cb6",
|
|
1962
1962
|
"lib/middleware/speculation-rules.js": "sha256:565c7a55c0625f300b6ea412709fbe787fe18715bad3d2a9340184eb44007302",
|
|
1963
1963
|
"lib/middleware/sse.js": "sha256:d0094cb33fced9bc748edd1f6d55fba6029ff3bff6da735d72ad5d10806f02f7",
|
|
1964
|
-
"lib/middleware/trace-log-correlation.js": "sha256:
|
|
1964
|
+
"lib/middleware/trace-log-correlation.js": "sha256:f6a36bfcb666cee5434867b1841092793491491bb9da7bc92626dd93cfa7b0d0",
|
|
1965
1965
|
"lib/middleware/trace-propagate.js": "sha256:876b91a195ae17d6c8916884c10b3fcc54d12ae97d13927e501b58f77e0c306d",
|
|
1966
1966
|
"lib/middleware/tus-upload.js": "sha256:f764417775b582778285a191136a5d980e8ca618ecb79403763430ca73353d2a",
|
|
1967
1967
|
"lib/middleware/web-app-manifest.js": "sha256:75c620a8f5354514f2fe8f030eceb0b2540561412c27907d259ee33063cd4bbd",
|
|
@@ -2103,7 +2103,7 @@
|
|
|
2103
2103
|
"lib/tsa.js": "sha256:88d0f79c4eb9d6c948c360d8d6aff4982f83dd9614e37a3047c4ff247b349ba8",
|
|
2104
2104
|
"lib/uri-template.js": "sha256:9b7252fce4a8245ee1ad51b3ce4dadd42d08080ddded961dafad2330a1a6cd8d",
|
|
2105
2105
|
"lib/uuid.js": "sha256:5b4c2b1880a66a52adb529afce679888a033f17dd284c190419f7e496803d182",
|
|
2106
|
-
"lib/validate-opts.js": "sha256:
|
|
2106
|
+
"lib/validate-opts.js": "sha256:cefcb9256f8676f6ce6fa3c796467643ae44692078bb00c4c5b49ec20652aba9",
|
|
2107
2107
|
"lib/vault-aad.js": "sha256:f2e5e1abecd6b5a748d1bf4c12be372f4e330ca701f03b7e12ab688a1ab98f67",
|
|
2108
2108
|
"lib/vault/index.js": "sha256:3a8928741a58e98f24ef7c09880b8ef77cda044c5acd56a1640f715427701286",
|
|
2109
2109
|
"lib/vault/passphrase-ops.js": "sha256:d7936e193f2ef3f52720d5c42e78eeb0a3f1baea985363c6151a8bdf271ffe9d",
|
|
@@ -2138,12 +2138,11 @@
|
|
|
2138
2138
|
"lib/worm.js": "sha256:bb2557c6de89780e4e845d46b4bf337c9e95aaa38267c7d50f1d91876dd527e3",
|
|
2139
2139
|
"lib/ws-client.js": "sha256:48982b3fb5fe12d977001d3566093f4257a247331a3e49adfa6b67fe93fb2425",
|
|
2140
2140
|
"lib/xml-c14n.js": "sha256:01a27d20df99ebd6eaefbff0aad933a2231049f65a54ae994236694d4146ce5d",
|
|
2141
|
-
"memory/specs/node-26-map-getorinsert-migration.md": "sha256:c7ec64dbfe06f280e7a0ac35e43f54e40a59efbb03ebc993383b2c2be901b34a",
|
|
2142
2141
|
"oss-fuzz/projects/blamejs/Dockerfile": "sha256:277c9e93cf2e8746b0a6d09a0678b35cbe700e9c2373bdc1b2177ed2167b7359",
|
|
2143
2142
|
"oss-fuzz/projects/blamejs/README.md": "sha256:ae13b7bb79ed8d69b1b3276e5562807a0349fb6e6b7d11cf1f683aad1eafdb4b",
|
|
2144
2143
|
"oss-fuzz/projects/blamejs/build.sh": "sha256:0ced1cf21782c97be7f8d74faf5e27a308b60b2f858836fb5ca3b8c4e939a8f7",
|
|
2145
2144
|
"oss-fuzz/projects/blamejs/project.yaml": "sha256:59f2cb83aa622325a175b77416fe155be15b70a9c798bd1a78bba05763b1b03d",
|
|
2146
|
-
"package.json": "sha256:
|
|
2145
|
+
"package.json": "sha256:6cb63950bdc9eea2d713ca7972a6f9670189c132fea11b3a0271891e0a667a64",
|
|
2147
2146
|
"release-notes/v0.0.x.json": "sha256:7a49819f30068ee119000cad7010194882bb8bfaa12acbdab4dfc066efb7982f",
|
|
2148
2147
|
"release-notes/v0.1.x.json": "sha256:6742a8c17f947c5cb76f69dead7eea86b942d80621d914b774ba5488e09937e5",
|
|
2149
2148
|
"release-notes/v0.10.x.json": "sha256:fe498045daf88337bd3d987e5964aa42c99a50e1685b6f09e51f698b8687726f",
|
|
@@ -2164,6 +2163,7 @@
|
|
|
2164
2163
|
"release-notes/v0.14.2.json": "sha256:0823f20cd837fb2ff80b93506bf5417cdfca2d938797d3bfb0d61c89a10dd8c8",
|
|
2165
2164
|
"release-notes/v0.14.20.json": "sha256:5c6d374883e9c2593c12acd9cc185f65ff76010560e92915c4bea56bd882f569",
|
|
2166
2165
|
"release-notes/v0.14.21.json": "sha256:02bae943c89c01d93516ce73a87bc915951f40e428652837f41d9011cdb1db48",
|
|
2166
|
+
"release-notes/v0.14.22.json": "sha256:4f8acf37b8093dc53f871ecf029acefae42daba4df60ba1d031493a3034a02cd",
|
|
2167
2167
|
"release-notes/v0.14.3.json": "sha256:231442b2ce6a0acc19c5e3cfdebd4725250fc5c27c0fd338d71664d8467abb95",
|
|
2168
2168
|
"release-notes/v0.14.4.json": "sha256:7d3b405f139accf69bc98929ab0417ef5c45a9c9b1390bf63b5efc527dcc1519",
|
|
2169
2169
|
"release-notes/v0.14.5.json": "sha256:0dadead3a48b40636222badaa2246fae2ffc73e261c57c48d4a9942e27e08dad",
|
|
@@ -2302,7 +2302,7 @@
|
|
|
2302
2302
|
"test/layer-0-primitives/audit-use-store.test.js": "sha256:201c462f2d6e3d7f2f4850e91e702e6729427ded41ab04d0a3aae1fb3e345450",
|
|
2303
2303
|
"test/layer-0-primitives/auth-bot-challenge-verifier.test.js": "sha256:082c610cce567f6fb76f030741ace572f770f600d7aa20a35d19b45f8b908ac2",
|
|
2304
2304
|
"test/layer-0-primitives/auth-bot-challenge.test.js": "sha256:957abf6bce2e615b45e54c705ded318890271e37dd728d943424eca42af71ab2",
|
|
2305
|
-
"test/layer-0-primitives/auth-jar.test.js": "sha256:
|
|
2305
|
+
"test/layer-0-primitives/auth-jar.test.js": "sha256:f539217f22205918d22b3a8d651c92a9d837df8279b10a89afae3a7863a10d0e",
|
|
2306
2306
|
"test/layer-0-primitives/auth-jwt-defenses.test.js": "sha256:f7bda4a1cec7e73f1840b76a41fbcfe2bf41933ec5a92dc2d79466dae1ae3f4e",
|
|
2307
2307
|
"test/layer-0-primitives/auth-lockout.test.js": "sha256:3d588d8c7e9715c3be8501f2391864388080a5d1163d094a3924114f52a772fb",
|
|
2308
2308
|
"test/layer-0-primitives/auth-password-audit.test.js": "sha256:9f7152a245d1ba88418402aa6a7e54f4c217f7707e2962998edb1e26d34e067d",
|
|
@@ -2356,7 +2356,7 @@
|
|
|
2356
2356
|
"test/layer-0-primitives/cluster-storage.test.js": "sha256:5627e621dff001e236b668e04336eb39c9fe08a4a7d45a640e6e7fccce37a022",
|
|
2357
2357
|
"test/layer-0-primitives/cluster-vault-rotation.test.js": "sha256:3514e9e71d6c39e805248f58ad2f41528d091e196c0f3766a032675677161b2d",
|
|
2358
2358
|
"test/layer-0-primitives/cms-codec.test.js": "sha256:7e46078ed82be5b69d22c48f22dba37ea5015371c2a8cf5f94fb1a792fb7bb78",
|
|
2359
|
-
"test/layer-0-primitives/codebase-patterns.test.js": "sha256:
|
|
2359
|
+
"test/layer-0-primitives/codebase-patterns.test.js": "sha256:4add8aee8fca78447375c6990dc560eb9045ba08fc774fa094db71e83282c156",
|
|
2360
2360
|
"test/layer-0-primitives/compliance-ai-act.test.js": "sha256:5ee4ad05d12233cb3c5457ef10a727833710bbc1ce1318838f9f9ef5d2cb8d4b",
|
|
2361
2361
|
"test/layer-0-primitives/compliance-cascade.test.js": "sha256:ee02cf14541a837a9d7977c6ea6bf7f9210bed293925d93c976e31f270aebec4",
|
|
2362
2362
|
"test/layer-0-primitives/compliance-eaa.test.js": "sha256:8afb3fa66f3f9452592995e77f5e0644d8c82de2321c551c6f5be6002b2c27a4",
|
|
@@ -2503,7 +2503,7 @@
|
|
|
2503
2503
|
"test/layer-0-primitives/json-schema.test.js": "sha256:bd1e2a09d1b6c916323acfb6a79c9a2dbf9b70a658ce84069530ce2e3c55f919",
|
|
2504
2504
|
"test/layer-0-primitives/jtd.test.js": "sha256:74385592a7845358bcae0f5bf9c13d2fab17f7eabdd4accd973b3acc6eb23035",
|
|
2505
2505
|
"test/layer-0-primitives/jwk.test.js": "sha256:ceb4cf2aae65f7a0881143fdf8d22fa0c026bc4003df18180f3671439dd02b21",
|
|
2506
|
-
"test/layer-0-primitives/jwt-external.test.js": "sha256:
|
|
2506
|
+
"test/layer-0-primitives/jwt-external.test.js": "sha256:f7896e520a04c98b848d5496c3709798267ed85cafdb0e9e91cadb46aa559f67",
|
|
2507
2507
|
"test/layer-0-primitives/keychain.test.js": "sha256:8d6fa2888cd9e6757101c4d211891c5a6bf3f1a88842871ff188edf2d07d80c1",
|
|
2508
2508
|
"test/layer-0-primitives/legal-hold.test.js": "sha256:1ba934827ddcd679a6adaca23bdffda2d4310d9fc4f8aa98c5096fead7ee2fb1",
|
|
2509
2509
|
"test/layer-0-primitives/link-header.test.js": "sha256:c684b000921c6e79d6b9a432e5f2629f36b23fa9a2fc458b9b8d34857304d0fe",
|
|
@@ -2574,7 +2574,7 @@
|
|
|
2574
2574
|
"test/layer-0-primitives/no-cache.test.js": "sha256:b80e5ae1ad53cbf552423c3b16653c6d011d773f2056fa156e4436fc4f014e9b",
|
|
2575
2575
|
"test/layer-0-primitives/notify.test.js": "sha256:8a7cf548e567cdcf0e6cc6d731c5e2e6fcc364e8838ef411999c324234da3917",
|
|
2576
2576
|
"test/layer-0-primitives/numeric-bounds.test.js": "sha256:539a476f1cf968088b7f680e8a87cd734a3625eea4e375d47b1957a8f145f45f",
|
|
2577
|
-
"test/layer-0-primitives/oauth-callback.test.js": "sha256:
|
|
2577
|
+
"test/layer-0-primitives/oauth-callback.test.js": "sha256:da785fbad16efd7b76b43285f0483c37f0fa70d5505e28c802cbac9c28d8f5f9",
|
|
2578
2578
|
"test/layer-0-primitives/observability-tracing.test.js": "sha256:0912c59a2b52ca139a61a06a5f0f57bcd952b0da503656efe6c0e0a3135765f4",
|
|
2579
2579
|
"test/layer-0-primitives/observability.test.js": "sha256:969600b4e53437d0efdb326cd7e4df06f807afd5c5d4f21100091f1c1e764258",
|
|
2580
2580
|
"test/layer-0-primitives/openapi.test.js": "sha256:2e552cbb27b70ac28688632364defc9d063b3b26ff45788012e656bce8ba31e3",
|