@blamejs/blamejs-shop 0.1.36 → 0.1.38

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 (31) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +1 -0
  3. package/lib/admin.js +205 -42
  4. package/lib/asset-manifest.json +5 -5
  5. package/lib/storefront.js +706 -74
  6. package/lib/translations.js +203 -0
  7. package/lib/vendor/MANIFEST.json +2 -2
  8. package/lib/vendor/blamejs/CHANGELOG.md +6 -0
  9. package/lib/vendor/blamejs/README.md +2 -1
  10. package/lib/vendor/blamejs/api-snapshot.json +6 -2
  11. package/lib/vendor/blamejs/index.js +1 -0
  12. package/lib/vendor/blamejs/lib/ai-disclosure.js +2 -3
  13. package/lib/vendor/blamejs/lib/ai-frontier-protocol.js +196 -0
  14. package/lib/vendor/blamejs/lib/archive-gz.js +5 -3
  15. package/lib/vendor/blamejs/lib/archive-read.js +84 -35
  16. package/lib/vendor/blamejs/lib/archive-tar-read.js +86 -31
  17. package/lib/vendor/blamejs/lib/archive-tar.js +2 -3
  18. package/lib/vendor/blamejs/lib/backup/index.js +2 -3
  19. package/lib/vendor/blamejs/lib/cose.js +4 -3
  20. package/lib/vendor/blamejs/lib/mail-server-jmap.js +9 -9
  21. package/lib/vendor/blamejs/lib/mail-server-submission.js +3 -2
  22. package/lib/vendor/blamejs/lib/mdoc.js +14 -14
  23. package/lib/vendor/blamejs/lib/network-dnssec.js +10 -8
  24. package/lib/vendor/blamejs/package.json +1 -1
  25. package/lib/vendor/blamejs/release-notes/v0.13.6.json +18 -0
  26. package/lib/vendor/blamejs/release-notes/v0.13.7.json +27 -0
  27. package/lib/vendor/blamejs/release-notes/v0.13.8.json +27 -0
  28. package/lib/vendor/blamejs/test/layer-0-primitives/ai-frontier-protocol.test.js +83 -0
  29. package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +50 -0
  30. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +89 -0
  31. package/package.json +1 -1
@@ -223,8 +223,58 @@ async function testBundleAdapterStorageRoundTrip() {
223
223
  }
224
224
  }
225
225
 
226
+ // In-memory extraction (serverless / read-only FS): reader.extractEntries()
227
+ // yields decompressed bytes without ever writing to disk, and those bytes are
228
+ // byte-identical to what disk extract() produces.
229
+ async function testExtractEntriesInMemory() {
230
+ var z = b.archive.zip();
231
+ z.addFile("readme.txt", "Hello, in-memory!\n");
232
+ z.addFile("data/nums.csv", "n,sq\n2,4\n");
233
+ z.addFile("docs/deep.bin", Buffer.from([0, 1, 2, 3, 255]));
234
+ var bytes = z.toBuffer();
235
+
236
+ // Spy: no fs write may happen during the in-memory path.
237
+ var wrote = false;
238
+ var origWrite = fs.writeFileSync;
239
+ fs.writeFileSync = function () { wrote = true; return origWrite.apply(fs, arguments); };
240
+ var collected = {};
241
+ try {
242
+ var reader = b.archive.read.zip(b.archive.adapters.buffer(bytes));
243
+ for await (var e of reader.extractEntries()) { collected[e.name] = e.bytes; }
244
+ } finally {
245
+ fs.writeFileSync = origWrite;
246
+ }
247
+ check("zip extractEntries: no disk write", wrote === false);
248
+ check("zip extractEntries: 3 file entries (dir skipped)", Object.keys(collected).length === 3);
249
+ check("zip extractEntries: text bytes match", collected["readme.txt"].toString("utf8") === "Hello, in-memory!\n");
250
+ check("zip extractEntries: binary bytes match", collected["docs/deep.bin"].equals(Buffer.from([0, 1, 2, 3, 255])));
251
+
252
+ // Byte-equality with disk extract().
253
+ var dest = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-archive-mem-"));
254
+ try {
255
+ await b.safeArchive.extract({ source: bytes, destination: dest, guardProfile: "balanced" });
256
+ var diskBin = fs.readFileSync(path.join(dest, "docs/deep.bin"));
257
+ check("zip extractEntries bytes == disk extract bytes", collected["docs/deep.bin"].equals(diskBin));
258
+ } finally {
259
+ fs.rmSync(dest, { recursive: true, force: true });
260
+ }
261
+
262
+ // tar in-memory.
263
+ var t = b.archive.tar();
264
+ t.addFile("x.txt", "world\n");
265
+ t.addFile("sub/y.dat", Buffer.from([9, 8, 7]));
266
+ var tbytes = t.toBuffer();
267
+ var tcollected = {};
268
+ var tr = b.archive.read.tar(b.archive.adapters.buffer(tbytes));
269
+ for await (var te of tr.extractEntries()) { tcollected[te.name] = te.bytes; }
270
+ check("tar extractEntries: 2 entries", Object.keys(tcollected).length === 2);
271
+ check("tar extractEntries: text matches", tcollected["x.txt"].toString("utf8") === "world\n");
272
+ check("tar extractEntries: binary matches", tcollected["sub/y.dat"].equals(Buffer.from([9, 8, 7])));
273
+ }
274
+
226
275
  async function run() {
227
276
  await testRoundTripExtract();
277
+ await testExtractEntriesInMemory();
228
278
  testSafeArchiveErrorClass();
229
279
  await testSafeArchiveInspect();
230
280
  await testZipBombPolicy();
@@ -510,6 +510,80 @@ function testNoUnresolvedMarkers() {
510
510
  matches);
511
511
  }
512
512
 
513
+ // ---- Pattern: overdue defers (promised landing version already shipped) ----
514
+ //
515
+ // A comment/string that promises a feature "lands in vX" / "deferred to vX" /
516
+ // "not supported in vX" is fine while vX is in the future. Once the package
517
+ // version reaches vX, that promise is OVERDUE: either the feature shipped (and
518
+ // the comment is stale and should be corrected) or it never shipped (a real
519
+ // gap to close or an explicit defer-with-condition to record here). This gate
520
+ // surfaces the iabTcf-class "advertised-but-missing / stale-landing" shape on
521
+ // every release rather than letting promised-landing comments rot silently.
522
+ //
523
+ // STALE_DEFER_ALLOWLIST entries are acknowledged overdue mentions: each is
524
+ // either a deliberate defer-with-condition (no operator demand + escape hatch)
525
+ // or an item on the gap backlog being worked down. The key is the file; the
526
+ // value is a list of distinctive content substrings to permit. Remove an entry
527
+ // when the comment is corrected or the gap is closed — that is the backlog.
528
+ var STALE_DEFER_ALLOWLIST = {
529
+ // Deliberate defer-with-condition: needs an envelope-semantics decision
530
+ // (per-tenant KEM keypair vs symmetric); explicit escape hatch is passing
531
+ // { publicKey, ecPublicKey } directly. Tracked for design, not overdue work.
532
+ "lib/archive-wrap.js": [
533
+ // quote-free phrases (source has escaped \" so avoid quote chars here)
534
+ "deferred to v0.12.11",
535
+ "lands in v0.12.11",
536
+ ],
537
+ // Deliberate: Sieve extension refused per RFC 5228 §3.2 — script-declared
538
+ // capability gating, defer-with-condition (operator demand).
539
+ "lib/safe-sieve.js": ["not implemented in v0.9.55 — script refused"],
540
+ // Conditional on a future vendoring decision (no bundled EXIF/IPTC reader);
541
+ // operator-feeds-metadata escape hatch. Defer-with-condition.
542
+ "lib/ai-content-detect.js": ["IPTC PhotoMetadata reader lands in v0.10.9"],
543
+ // GAP BACKLOG (being worked down — these are real overdue items):
544
+ // archive-read ZIP64 read + fromTrustedStream (promised v0.12.8) — building.
545
+ "lib/archive-read.js": [
546
+ "not supported in v0.12.7. Will land",
547
+ "switch to tar — lands v0.12.8",
548
+ "carries ZIP64 sentinel sizes (not supported in v0.12.7)",
549
+ "deferred to v0.12.8 alongside the tar reader",
550
+ "fromTrustedStream.inspect() is deferred to v0.12.8",
551
+ "fromTrustedStream.entries() is deferred to v0.12.8",
552
+ "fromTrustedStream.extract() is deferred to v0.12.8",
553
+ ],
554
+ "lib/safe-archive.js": [
555
+ "tar lands v0.12.8, gz v0.12.9",
556
+ "fromTrustedStream` is deferred to v0.12.8",
557
+ ],
558
+ // STALE comments (feature shipped; phrased as future) — correcting to past
559
+ // tense as the backlog is worked; allowlisted until then.
560
+ "lib/break-glass.js": ["passkey lands in v0.5.2"],
561
+ };
562
+
563
+ function testNoStaleDefers() {
564
+ var path = require("node:path");
565
+ var pkgVersion = require(path.resolve(__dirname, "..", "..", "package.json")).version.split(".").map(Number);
566
+ function cmp(a, b) { for (var i = 0; i < 3; i += 1) { if ((a[i] || 0) !== (b[i] || 0)) return (a[i] || 0) - (b[i] || 0); } return 0; }
567
+ // Promised-landing phrasings only ("X lands in vN" / "deferred to vN" / "not
568
+ // supported in vN"). NOT "deferred FROM vN" (that is an origin, not a deadline).
569
+ var PROMISE = /(?:deferred to|lands(?: in)?|will land(?: in)?|not supported in)\s+v?(\d+\.\d+\.\d+)/i;
570
+ var matches = _scan(PROMISE, { skipComments: false });
571
+ var overdue = [];
572
+ matches.forEach(function (m) {
573
+ var mm = m.content.match(PROMISE);
574
+ if (!mm) return;
575
+ // Only a STRICTLY-FUTURE promise is exempt. A promise for the current
576
+ // version is due in the release being cut now — if the feature isn't here,
577
+ // the comment is overdue and must be fixed in this release, not a later one.
578
+ if (cmp(mm[1].split(".").map(Number), pkgVersion) > 0) return;
579
+ var allow = STALE_DEFER_ALLOWLIST[m.file] || [];
580
+ if (allow.some(function (sub) { return m.content.indexOf(sub) !== -1; })) return;
581
+ overdue.push({ file: m.file, line: m.line, content: "overdue defer (promised v" + mm[1] + ", now v" + pkgVersion.join(".") + "): " + m.content.slice(0, 100) });
582
+ });
583
+ _report("no overdue defers in lib/ (promised-landing version already shipped — close the gap, fix the stale comment, or record it in STALE_DEFER_ALLOWLIST)",
584
+ overdue);
585
+ }
586
+
513
587
  // ---- Pattern: literal NUL bytes (0x00) in source files ----
514
588
  //
515
589
  // The Edit / Write tooling decodes JSON `\u0000` escape sequences into
@@ -2195,6 +2269,20 @@ async function testNoDuplicateCodeBlocks() {
2195
2269
  ],
2196
2270
  reason: "v0.12.7 + v0.12.8 — Per-module `_emitAudit(opts, action, outcome, metadata)` shape repeats across primitives that drop-silently emit to opts.audit.safeEmit if present. Each module's audit events carry a primitive-specific `action:` namespace (archive.read.*, archive.zip.*, archive.read.tar.*, http-client.*) + per-primitive metadata fields; consolidating would lose the namespace + force every consumer to import the same audit helper. Four-file repetition is the expected shape per `feedback_audit_safeEmit_per_module_emitAudit_shape`. archive-tar.js (write) does NOT carry _emitAudit — the read side lives in sibling archive-tar-read.js so the @primitive validator can pair both `b.archive.tar` (write) and `b.archive.read.tar` (read) cleanly.",
2197
2271
  },
2272
+ {
2273
+ mode: "family-subset",
2274
+ files: [
2275
+ "lib/archive-read.js:_assertGuardMetadata",
2276
+ "lib/archive-tar-read.js:_assertGuardMetadata",
2277
+ "lib/auth/ciba.js:_registerInitialInterval",
2278
+ "lib/auth/oauth.js:exchangeToken",
2279
+ "lib/auth/oauth.js:pollDeviceCode",
2280
+ "lib/auth/oid4vci.js:createCredentialOffer",
2281
+ "lib/auth/oid4vci.js:exchangePreAuthorizedCode",
2282
+ "lib/restore-rollback.js:swap",
2283
+ ],
2284
+ reason: "v0.13.8 — the shared shingle is the framework's emit-audit-then-throw-typed-error idiom (validate/poll/guard → emit a namespaced audit row → throw a primitive-specific FrameworkError), not behaviour. archive-read/archive-tar-read `_assertGuardMetadata` run the b.guardArchive metadata cascade and throw ArchiveReadError/TarError (factored so disk `extract` + in-memory `extractEntries` share one refusal path); ciba/oauth/oid4vci are OAuth/OIDC device-code + credential-offer polling/exchange; restore-rollback.swap is the backup restore swap. Each body is domain-divergent (different inputs, error classes, audit namespaces); consolidating would couple unrelated subsystems to one helper.",
2285
+ },
2198
2286
  {
2199
2287
  mode: "family-subset",
2200
2288
  files: [
@@ -10012,6 +10100,7 @@ async function run() {
10012
10100
  testHttp2TeardownPaired();
10013
10101
  testNoStrayConsoleCalls();
10014
10102
  testNoUnresolvedMarkers();
10103
+ testNoStaleDefers();
10015
10104
  testNoLiteralNulBytesInSource();
10016
10105
  testParserPrimitivesHaveFuzzHarness();
10017
10106
  testSafeGuardWiredInIndex();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/blamejs-shop",
3
- "version": "0.1.36",
3
+ "version": "0.1.38",
4
4
  "description": "Open-source framework built on blamejs. Vendored stack, zero npm runtime deps, PQC-first crypto, security-on by default.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {