@blamejs/blamejs-shop 0.0.66 → 0.0.72

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/lib/assembly-instructions.js +777 -0
  3. package/lib/auto-replenish.js +933 -0
  4. package/lib/click-and-collect.js +711 -0
  5. package/lib/clickstream.js +713 -0
  6. package/lib/customer-activity.js +862 -0
  7. package/lib/customer-notes.js +712 -0
  8. package/lib/customer-risk-profile.js +593 -0
  9. package/lib/customer-surveys.js +1012 -0
  10. package/lib/damage-photos.js +473 -0
  11. package/lib/dropship-forwarding.js +645 -0
  12. package/lib/email-templates.js +817 -0
  13. package/lib/index.js +36 -0
  14. package/lib/inventory-allocations.js +559 -0
  15. package/lib/inventory-writeoffs.js +636 -0
  16. package/lib/knowledge-base.js +1104 -0
  17. package/lib/locale-router.js +1077 -0
  18. package/lib/loyalty-earn-rules.js +786 -0
  19. package/lib/operator-roles.js +768 -0
  20. package/lib/order-escalation.js +951 -0
  21. package/lib/order-ratings.js +495 -0
  22. package/lib/order-tags.js +944 -0
  23. package/lib/packing-slips.js +810 -0
  24. package/lib/pixel-events.js +995 -0
  25. package/lib/print-queue.js +681 -0
  26. package/lib/product-qa.js +749 -0
  27. package/lib/promo-bundles.js +835 -0
  28. package/lib/push-notifications.js +937 -0
  29. package/lib/refund-automation.js +853 -0
  30. package/lib/reorder-reminders.js +798 -0
  31. package/lib/robots-config.js +753 -0
  32. package/lib/seller-signup.js +1052 -0
  33. package/lib/sitemap-generator.js +717 -0
  34. package/lib/split-shipments.js +7 -1
  35. package/lib/subscription-gifts.js +710 -0
  36. package/lib/tax-cert-renewals.js +632 -0
  37. package/lib/tier-benefits.js +776 -0
  38. package/lib/vendor/MANIFEST.json +2 -2
  39. package/lib/vendor/blamejs/CHANGELOG.md +2 -0
  40. package/lib/vendor/blamejs/api-snapshot.json +2 -2
  41. package/lib/vendor/blamejs/lib/metrics.js +68 -4
  42. package/lib/vendor/blamejs/package.json +1 -1
  43. package/lib/vendor/blamejs/release-notes/v0.12.5.json +40 -0
  44. package/lib/wishlist-alerts.js +842 -0
  45. package/lib/wishlist-sharing.js +718 -0
  46. package/package.json +1 -1
@@ -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.12.4",
7
- "tag": "v0.12.4",
6
+ "version": "0.12.5",
7
+ "tag": "v0.12.5",
8
8
  "license": "Apache-2.0",
9
9
  "author": "blamejs contributors",
10
10
  "source": "https://github.com/blamejs/blamejs",
@@ -8,6 +8,8 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.12.x
10
10
 
11
+ - v0.12.5 (2026-05-22) — **`b.metrics` content-negotiates OpenMetrics 1.0 + auto-attaches trace exemplars on request histograms.** The `/metrics` scrape endpoint now serves `application/openmetrics-text; version=1.0.0; charset=utf-8` when the scraper requests it via the `Accept` header (Prometheus 2.x strict mode, OpenObservability tooling). Legacy scrapers still get `text/plain; version=0.0.4` — no operator with the default Prometheus client sees a content-type change. Separately, the framework's request-duration histogram middleware now auto-attaches the active sampled trace's `trace_id` + `span_id` as the OpenMetrics §6.2 exemplar on every bucket sample, so Grafana / Tempo / Jaeger scrapers can pivot from a slow-bucket histogram to the exact trace that produced the sample. The wiring is composition-only — `b.middleware.tracePropagate` populates `req.trace.{traceId,parentId,sampled}`, the metrics middleware reads it, no operator opt-in needed. **Added:** *`Accept` content-negotiation on `b.metrics.expositionHandler()`* — When the scraper's `Accept` header includes `application/openmetrics-text`, the handler renders the OpenMetrics 1.0 wire format (`# UNIT` lines, `_total` suffix on counters, `# EOF` terminator, exemplar shape) and serves `application/openmetrics-text; version=1.0.0; charset=utf-8`. Otherwise serves Prometheus 0.0.4 `text/plain` as before. Operators relying on the legacy Prometheus content-type see no change. · *Auto-attached trace exemplars on request-duration histograms* — When `b.middleware.spanHttpServer` populates `req.span.{traceId, spanId, sampled}` on the inbound request and the span is sampled, the framework's built-in `requestDuration` histogram middleware attaches `{ labels: { trace_id, span_id }, value: <duration>, timestamp: <unix-sec> }` as the OpenMetrics §6.2 exemplar on the corresponding bucket. The exemplar's `span_id` is the server-handling span, not the upstream `traceparent`'s parent-id, so the metric-to-trace pivot in Grafana / Tempo / Jaeger lands on the work the metric measured. Operators wiring `tracePropagate` without `spanHttpServer` fall back to `req.trace.spanId` when populated; the framework never invents a span_id from the upstream parent. **Fixed:** *Accept-header weighted negotiation (Codex P1)* — The first pass treated any `Accept` header containing `application/openmetrics-text` as an unconditional OpenMetrics request — clients sending `Accept: text/plain;q=1.0, application/openmetrics-text;q=0.5` got OpenMetrics back instead of their preferred Prometheus 0.0.4. Fix: parse Accept via `b.requestHelpers.parseQualityList` and compare q-values for `application/openmetrics-text` vs `text/plain` (wildcards `*/*`, `application/*`, `text/*` honored). Defaults to Prometheus when both q-values are equal or zero (backward compatibility with the legacy default content-type). · *Exemplar span_id sources the active server span, not the upstream parent (Codex P2)* — The first pass used `req.trace.parentId` for the exemplar's `span_id` label — but `parentId` is the upstream caller's span (or empty for root requests), not the server-handling span. Fix: prefer `req.span.spanId` (set by `b.middleware.spanHttpServer`), falling back to `req.trace.spanId` for operators wiring `tracePropagate` without `spanHttpServer`. Never synthesises a span_id from `parentId`. **References:** [OpenMetrics 1.0 §1.2 (content negotiation)](https://prometheus.io/docs/specs/om/open_metrics_spec/) · [OpenMetrics 1.0 §6.2 (exemplars)](https://prometheus.io/docs/specs/om/open_metrics_spec/) · [W3C Trace Context (traceparent header)](https://www.w3.org/TR/trace-context/)
12
+
11
13
  - v0.12.4 (2026-05-22) — **`SECURITY.md` Watch list — remove stale "framework doesn't ship CMS / S/MIME" entry.** The Watch list bullet claiming `framework does not ship a CMS / S/MIME / PKCS#7 surface today` has been wrong since v0.10.13 — `b.cms.encodeSignedData` / `decode` / `encodeEnvelopedData` / `parseSignedData` shipped then, and `b.mail.crypto.smime.sign` / `verify` / `verifyAll` / `checkCert` shipped under the mail-stack. The Watch list is for CVE classes the framework deliberately doesn't ship a primitive for; CMS no longer fits that shape. Entry removed. **Fixed:** *Watch list no longer claims CMS / S/MIME are unshipped* — `b.cms` exposes RFC 5652 ContentInfo / SignedData / EnvelopedData encode + decode with PQC signer support (ML-DSA-65 per RFC 9909 §5, ML-DSA-87 per RFC 9909 §6, SLH-DSA-SHAKE-256f per RFC 9881). `b.mail.crypto.smime` builds on it for RFC 8551 S/MIME signed + enveloped mail with `checkCert` for X.509 chain validation. The SECURITY.md Watch list entry that pointed operators to external CMS libraries is gone; operators on regulated mail interop reach for the in-framework primitives instead.
12
14
 
13
15
  - v0.12.3 (2026-05-22) — **README "What ships in the box" backfill — mail-stack listeners + JSCalendar + new postures.** The README's "Communication" + "Compliance regimes" bullets lagged behind the v0.11.24-v0.12.1 ship cadence. Backfilled: `b.mail.send.deliver` (turnkey outbound delivery chain), the four mail-server listeners (mx / submission / imap / jmap), the JMAP EmailSubmission/set reference handler, mail-crypto (CMS + PGP+WKD), the mail-stack agent, `b.calendar` (RFC 8984 JSCalendar substrate with full BY*+BYSETPOS+multi-rule expansion), and the 16 newly-promoted postures from v0.12.1 (`42-cfr-part-2` / `hti-1` / `uscdi-v4` / `irs-1075` / `nist-800-172-r3` / `tlp-2.0` / `soci-au` / `ffiec-cat-2` / `cri-profile-v2.0` / `m-22-09` / `m-22-18` / `nist-800-53-r5-privacy` / `nist-ai-600-1-genai` / `nist-csf-2.0` / `sb-53` / `nyc-ll144-2024`). **Changed:** *Communication section names every mail-stack listener + delivery chain + crypto primitive* — New entries: `b.mail.send.deliver` (MX → MTA-STS → DANE → REQUIRETLS → SMTP → DSN chain), four `b.mail.server.*` listeners, JMAP EmailSubmission reference handler, `b.mail.crypto.cms` + `b.mail.crypto.pgp`, `b.mail.agent` + `b.mailStore`, and `b.calendar` (JSCalendar / iCalendar bridge for JMAP Calendars interop). · *Compliance regimes section lists the 16 v0.12.1 backfilled postures* — New rows organise the additions under three sub-bullets: AI governance adds `nyc-ll144-2024` / `sb-53` / `nist-ai-rmf-1.0` / `nist-ai-600-1-genai` alongside the existing AI-act / NYC-LL144 / Colorado / Illinois entries; a new "Federal / sectoral" row covers `42-cfr-part-2` / `hti-1` / `uscdi-v4` / `irs-1075` / `nist-csf-2.0` / `nist-800-53-r5-privacy` / `nist-800-172-r3` / `m-22-09` / `m-22-18` / `ffiec-cat-2` / `cri-profile-v2.0`; a new "Critical infrastructure / info-sharing" row covers `soci-au` / `tlp-2.0`.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 1,
3
- "frameworkVersion": "0.12.4",
4
- "createdAt": "2026-05-22T23:12:46.997Z",
3
+ "frameworkVersion": "0.12.5",
4
+ "createdAt": "2026-05-23T01:16:54.749Z",
5
5
  "exports": {
6
6
  "a2a": {
7
7
  "type": "object",
@@ -45,7 +45,8 @@ var safeJson = require("./safe-json");
45
45
  var { defineClass } = require("./framework-error");
46
46
  var { boot } = require("./log");
47
47
  var numericBounds = require("./numeric-bounds");
48
- var { resolveRoute, captureResponseStatus, HTTP_STATUS } = require("./request-helpers");
48
+ var requestHelpers = require("./request-helpers");
49
+ var { resolveRoute, captureResponseStatus, HTTP_STATUS } = requestHelpers;
49
50
  var validateOpts = require("./validate-opts");
50
51
 
51
52
  var MetricsError = defineClass("MetricsError", { alwaysPermanent: true });
@@ -635,9 +636,42 @@ function create(opts) {
635
636
 
636
637
  function expositionHandler() {
637
638
  return function metricsHandler(req, res) {
638
- var body = exposition();
639
+ // OpenMetrics §1.2 content-negotiation. Operators with
640
+ // OpenMetrics-strict scrapers (Prometheus 2.x with strict mode,
641
+ // OpenObservability tooling) send
642
+ // `Accept: application/openmetrics-text; version=1.0.0`. The
643
+ // handler returns the OpenMetrics-1.0 wire format when that
644
+ // media type has the highest q-value among supported types;
645
+ // defaults to Prometheus 0.0.4 otherwise. Codex P1 v0.12.5 —
646
+ // honor RFC 9110 §12.5.1 weighted negotiation: a client that
647
+ // sends `Accept: text/plain;q=1.0, application/openmetrics-
648
+ // text;q=0.5` (or `;q=0`) gets text/plain back, even though
649
+ // both media types are supported.
650
+ var acceptHeader = req && req.headers ? String(req.headers.accept || "") : "";
651
+ var entries = requestHelpers.parseQualityList(acceptHeader);
652
+ var openMetricsQ = 0;
653
+ var prometheusQ = 0;
654
+ var sawAccept = entries.length > 0;
655
+ for (var i = 0; i < entries.length; i += 1) {
656
+ var v = entries[i].value;
657
+ var q = entries[i].q;
658
+ if (v === "application/openmetrics-text" || v === "*/*" || v === "application/*") {
659
+ if (q > openMetricsQ) openMetricsQ = q;
660
+ }
661
+ if (v === "text/plain" || v === "*/*" || v === "text/*") {
662
+ if (q > prometheusQ) prometheusQ = q;
663
+ }
664
+ }
665
+ // Default Prometheus when client sent no Accept header or both
666
+ // q-values are zero. Tie-break favours Prometheus for
667
+ // backward-compatibility with legacy scrapers.
668
+ var wantOpenMetrics = sawAccept && openMetricsQ > prometheusQ && openMetricsQ > 0;
669
+ var body = exposition(wantOpenMetrics ? { format: "openmetrics" } : undefined);
670
+ var contentType = wantOpenMetrics
671
+ ? "application/openmetrics-text; version=1.0.0; charset=utf-8"
672
+ : "text/plain; version=0.0.4; charset=utf-8";
639
673
  res.writeHead(HTTP_STATUS.OK, {
640
- "Content-Type": "text/plain; version=0.0.4; charset=utf-8",
674
+ "Content-Type": contentType,
641
675
  "Content-Length": Buffer.byteLength(body),
642
676
  "Cache-Control": "no-store",
643
677
  });
@@ -679,7 +713,37 @@ function create(opts) {
679
713
  // the rest of the framework's diagnostics.
680
714
  try { requestsTotal.inc(labels); }
681
715
  catch (e) { log.warn("metrics/request-counter-failed: " + e.message); }
682
- try { requestDuration.observe(durLabels, elapsedSec); }
716
+ // OpenMetrics §6.2 when a sampled trace context is active
717
+ // on the request, attach the trace + active SERVER-span id
718
+ // as the histogram bucket's exemplar so downstream scrapers
719
+ // (Prometheus 2.x, Grafana exemplar-renderer) can pivot
720
+ // from a slow-request bucket to the trace that produced it.
721
+ //
722
+ // Codex P2 v0.12.5 — the span_id MUST be the server-handling
723
+ // span (created by b.middleware.spanHttpServer + stamped on
724
+ // req.span), not the upstream `traceparent`'s parent-id.
725
+ // The parent-id points at the CALLER's span (or nothing for
726
+ // root requests); using it would mis-pivot the exemplar.
727
+ var exemplar = null;
728
+ if (req.span && req.span.traceId && req.span.spanId && req.span.sampled !== false) {
729
+ exemplar = {
730
+ labels: { trace_id: req.span.traceId, span_id: req.span.spanId },
731
+ value: elapsedSec,
732
+ timestamp: Date.now() / 1000, // allow:raw-time-literal — OpenMetrics §6.2 unix epoch seconds with subsecond fraction
733
+ };
734
+ } else if (req.trace && req.trace.sampled && req.trace.traceId && req.trace.spanId) {
735
+ // Operators wiring traceparent directly without
736
+ // spanHttpServer surface the inbound span as
737
+ // req.trace.spanId. Fall back to it; refuse to invent a
738
+ // span_id from parentId since that points at the upstream
739
+ // caller, not the work the metric measures.
740
+ exemplar = {
741
+ labels: { trace_id: req.trace.traceId, span_id: req.trace.spanId },
742
+ value: elapsedSec,
743
+ timestamp: Date.now() / 1000, // allow:raw-time-literal — OpenMetrics §6.2 unix epoch seconds with subsecond fraction
744
+ };
745
+ }
746
+ try { requestDuration.observe(durLabels, elapsedSec, exemplar); }
683
747
  catch (e) { log.warn("metrics/request-duration-failed: " + e.message); }
684
748
  });
685
749
  return next();
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.12.4",
3
+ "version": "0.12.5",
4
4
  "description": "The Node framework that owns its stack.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.12.5",
4
+ "date": "2026-05-22",
5
+ "headline": "`b.metrics` content-negotiates OpenMetrics 1.0 + auto-attaches trace exemplars on request histograms",
6
+ "summary": "The `/metrics` scrape endpoint now serves `application/openmetrics-text; version=1.0.0; charset=utf-8` when the scraper requests it via the `Accept` header (Prometheus 2.x strict mode, OpenObservability tooling). Legacy scrapers still get `text/plain; version=0.0.4` — no operator with the default Prometheus client sees a content-type change. Separately, the framework's request-duration histogram middleware now auto-attaches the active sampled trace's `trace_id` + `span_id` as the OpenMetrics §6.2 exemplar on every bucket sample, so Grafana / Tempo / Jaeger scrapers can pivot from a slow-bucket histogram to the exact trace that produced the sample. The wiring is composition-only — `b.middleware.tracePropagate` populates `req.trace.{traceId,parentId,sampled}`, the metrics middleware reads it, no operator opt-in needed.",
7
+ "sections": [
8
+ {
9
+ "heading": "Added",
10
+ "items": [
11
+ {
12
+ "title": "`Accept` content-negotiation on `b.metrics.expositionHandler()`",
13
+ "body": "When the scraper's `Accept` header includes `application/openmetrics-text`, the handler renders the OpenMetrics 1.0 wire format (`# UNIT` lines, `_total` suffix on counters, `# EOF` terminator, exemplar shape) and serves `application/openmetrics-text; version=1.0.0; charset=utf-8`. Otherwise serves Prometheus 0.0.4 `text/plain` as before. Operators relying on the legacy Prometheus content-type see no change."
14
+ },
15
+ {
16
+ "title": "Auto-attached trace exemplars on request-duration histograms",
17
+ "body": "When `b.middleware.spanHttpServer` populates `req.span.{traceId, spanId, sampled}` on the inbound request and the span is sampled, the framework's built-in `requestDuration` histogram middleware attaches `{ labels: { trace_id, span_id }, value: <duration>, timestamp: <unix-sec> }` as the OpenMetrics §6.2 exemplar on the corresponding bucket. The exemplar's `span_id` is the server-handling span, not the upstream `traceparent`'s parent-id, so the metric-to-trace pivot in Grafana / Tempo / Jaeger lands on the work the metric measured. Operators wiring `tracePropagate` without `spanHttpServer` fall back to `req.trace.spanId` when populated; the framework never invents a span_id from the upstream parent."
18
+ }
19
+ ]
20
+ },
21
+ {
22
+ "heading": "Fixed",
23
+ "items": [
24
+ {
25
+ "title": "Accept-header weighted negotiation (Codex P1)",
26
+ "body": "The first pass treated any `Accept` header containing `application/openmetrics-text` as an unconditional OpenMetrics request — clients sending `Accept: text/plain;q=1.0, application/openmetrics-text;q=0.5` got OpenMetrics back instead of their preferred Prometheus 0.0.4. Fix: parse Accept via `b.requestHelpers.parseQualityList` and compare q-values for `application/openmetrics-text` vs `text/plain` (wildcards `*/*`, `application/*`, `text/*` honored). Defaults to Prometheus when both q-values are equal or zero (backward compatibility with the legacy default content-type)."
27
+ },
28
+ {
29
+ "title": "Exemplar span_id sources the active server span, not the upstream parent (Codex P2)",
30
+ "body": "The first pass used `req.trace.parentId` for the exemplar's `span_id` label — but `parentId` is the upstream caller's span (or empty for root requests), not the server-handling span. Fix: prefer `req.span.spanId` (set by `b.middleware.spanHttpServer`), falling back to `req.trace.spanId` for operators wiring `tracePropagate` without `spanHttpServer`. Never synthesises a span_id from `parentId`."
31
+ }
32
+ ]
33
+ }
34
+ ],
35
+ "references": [
36
+ { "label": "OpenMetrics 1.0 §1.2 (content negotiation)", "url": "https://prometheus.io/docs/specs/om/open_metrics_spec/" },
37
+ { "label": "OpenMetrics 1.0 §6.2 (exemplars)", "url": "https://prometheus.io/docs/specs/om/open_metrics_spec/" },
38
+ { "label": "W3C Trace Context (traceparent header)", "url": "https://www.w3.org/TR/trace-context/" }
39
+ ]
40
+ }