@blamejs/blamejs-shop 0.4.126 → 0.4.127
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 +2 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/customer-segments.js +19 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,8 @@ upgrading across more than a few patches at a time.
|
|
|
8
8
|
|
|
9
9
|
## v0.4.x
|
|
10
10
|
|
|
11
|
+
- v0.4.127 (2026-06-27) — **Customer-segment-restricted automatic discounts now work instead of breaking the discount quote for signed-in shoppers.** An automatic-discount rule limited to a customer segment (for example a members-only offer) never functioned: the discount engine was constructed without the customer-segments handle it needs to test membership, so the moment any segment-restricted rule existed, computing the cart and checkout discount threw an error for every signed-in shopper — breaking the discount quote for authenticated customers — while the discount applied to no one. Guests were unaffected because a segment rule is skipped for a shopper with no account. The engine is now wired with the segments handle, so a segment-restricted rule correctly applies to shoppers who are in the segment, is skipped for shoppers who are not, and is skipped for guests; rules that are not segment-restricted are entirely unaffected. **Fixed:** *Customer-segment-restricted automatic discounts apply correctly and no longer break the quote* — The automatic-discount engine is now created with the customer-segments handle. Previously the storefront and checkout wired the engine without it, so evaluating a rule carrying a customer-segment restriction threw the moment a signed-in shopper reached the cart or checkout — the discount engine requires the handle to answer "is this customer in the segment?" and had none. The result was that a segment-restricted offer applied to nobody and broke the discount calculation for every authenticated shopper whenever such a rule was active. With the handle wired, a segment-restricted rule applies to shoppers in the segment, is cleanly skipped for shoppers outside it and for guests, and rules without a segment restriction behave exactly as before.
|
|
12
|
+
|
|
11
13
|
- v0.4.126 (2026-06-27) — **Storefront error responses no longer echo internal error detail, and order/account pages render images from the configured asset prefix.** Two storefront correctness fixes. First, around fifteen storefront routes (cart line edit/remove, product compare, saved-for-later, account actions and more) returned the raw error message to the client on an unexpected server error — a string that can carry an internal database column, a vault/crypto detail, or other implementation internals. Those routes now distinguish a client-shape validation error (a 400 that still shows its operator-authored message) from an unexpected server error (a 500 that logs the real error server-side, correlated by the request id, and returns only a generic message plus that id) — the same redaction the WebAuthn ceremony routes already used. Second, the order-detail and account-dashboard pages were rendering product thumbnails from the default "/assets/" path instead of the operator's configured asset prefix, so on a deployment that serves assets from a CDN or object-store prefix those two pages showed broken images; both pages now pass the configured prefix like every other page. **Fixed:** *Storefront routes no longer echo the internal error message on a 500* — About fifteen storefront routes — cart line update/remove, product-compare add/clear, saved-for-later move/remove, and several account actions — handled a caught error with `status(TypeError ? 400 : 500)` and then returned the raw error message for both cases, so an unexpected (non-validation) server error sent its internal message string to the client. These routes now return that message only for a client-shape validation error (a 400); any other error is a 500 that records the real error server-side against the request id and returns a generic "Something went wrong" message plus that id for support correlation. This matches the redaction the WebAuthn register/login routes already applied. · *Order-detail and account pages render images from the configured asset prefix* — The order-detail (`/orders/:id`) and account-dashboard (`/account`) renderers were not passed the configured asset prefix, so they fell back to the default `/assets/` path for product thumbnails while every other page used the operator's prefix. On a deployment that serves static assets from a CDN or object-store prefix, those two pages showed broken images. Both now pass the configured prefix, so their images load from the same place as the rest of the storefront.
|
|
12
14
|
|
|
13
15
|
- v0.4.125 (2026-06-27) — **Vendored framework refreshed to 0.15.34 — RSA OpenPGP signatures with a high zero byte now verify reliably.** Updates the vendored blamejs framework to 0.15.34. The upstream release fixes the framework's OpenPGP verification: an RSA signature whose value began with one or more zero bytes — about 1 in 256 of all signatures, for any key — was rejected as invalid even though it was correct, because the OpenPGP wire format strips those leading zero bytes and the verifier handed the shortened signature straight to RSA verification (which requires the signature to be exactly the key's modulus length). The signature is now left-padded back to the modulus width before verification, so every valid RSA signature verifies reliably, including signatures produced by other OpenPGP implementations. The release also carries internal test-suite tooling with no runtime effect. **Changed:** *Vendored framework refreshed to 0.15.34 (reliable RSA OpenPGP signature verification)* — Refreshes the vendored blamejs framework to 0.15.34. The upstream fix left-pads an RSA OpenPGP signature back to the key's modulus byte length before verifying it, so a valid signature whose value carried one or more leading zero bytes (~1 in 256, for any key) is no longer intermittently rejected — matching the padding the Ed25519 verification path already applied. Any code path that verifies OpenPGP RSA signatures through the framework now accepts every correct signature. The rest of the release is internal test-suite tooling with no runtime, public-API, or wire-format change.
|
package/lib/asset-manifest.json
CHANGED
package/lib/customer-segments.js
CHANGED
|
@@ -825,6 +825,25 @@ function create(opts) {
|
|
|
825
825
|
return out;
|
|
826
826
|
},
|
|
827
827
|
|
|
828
|
+
// Membership predicate: is this customer in the named (non-archived)
|
|
829
|
+
// segment? A single existence check over the same membership join
|
|
830
|
+
// `segmentsForCustomer` reads — so a caller gating one rule on one segment
|
|
831
|
+
// doesn't load the customer's whole segment list. This is the handle shape
|
|
832
|
+
// the autoDiscount engine's `customer_segment_in` gate composes
|
|
833
|
+
// (`isMember(customer_id, segment_slug) -> Promise<bool>`); a slug that
|
|
834
|
+
// names no segment (or an archived one) is simply not a member.
|
|
835
|
+
isMember: async function (customerId, segmentSlug) {
|
|
836
|
+
_uuid(customerId, "customer_id");
|
|
837
|
+
var slug = _slug(segmentSlug);
|
|
838
|
+
var r = await query(
|
|
839
|
+
"SELECT 1 FROM customer_segment_membership csm " +
|
|
840
|
+
"JOIN customer_segments cs ON cs.id = csm.segment_id " +
|
|
841
|
+
"WHERE csm.customer_id = ?1 AND cs.slug = ?2 AND cs.archived_at IS NULL LIMIT 1",
|
|
842
|
+
[customerId, slug],
|
|
843
|
+
);
|
|
844
|
+
return r.rows.length > 0;
|
|
845
|
+
},
|
|
846
|
+
|
|
828
847
|
listSegments: async function (listOpts) {
|
|
829
848
|
listOpts = listOpts || {};
|
|
830
849
|
var includeArchived = !!listOpts.include_archived;
|
package/package.json
CHANGED