@blamejs/blamejs-shop 0.0.83 → 0.0.85

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.
@@ -2185,6 +2185,76 @@ async function testNoDuplicateCodeBlocks() {
2185
2185
  files: ["lib/api-key.js:issue", "lib/db-query.js:<top>", "lib/session.js:create"],
2186
2186
  reason: "Generic JS array helper / lambda shape — Object.keys(...).map(fn) + similar functional idioms appearing in any code that walks a column-or-key list.",
2187
2187
  },
2188
+ {
2189
+ mode: "family-subset",
2190
+ files: [
2191
+ "lib/archive-read.js:_emitAudit",
2192
+ "lib/archive-tar-read.js:_emitAudit",
2193
+ "lib/archive.js:_emitAudit",
2194
+ "lib/http-client.js:_emitAudit",
2195
+ ],
2196
+ 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
+ },
2198
+ {
2199
+ mode: "family-subset",
2200
+ files: [
2201
+ "lib/archive-adapters.js:fs",
2202
+ "lib/archive-adapters.js:http",
2203
+ "lib/network-smtp-policy.js:mtaStsFetch",
2204
+ "lib/parsers/safe-env.js:readVar",
2205
+ ],
2206
+ reason: "v0.12.7 — `if (typeof <opt> !== \"string\" || <opt>.length === 0) throw new <Error>(...)` shape repeats across primitives validating REQUIRED string opts. validateOpts.requireNonEmptyString covers most call sites; the four flagged here are inline because they each carry a primitive-specific error CODE (adapter/bad-arg, smtp-policy/bad-arg, safe-env/bad-arg) that the helper's caller-error-class shape doesn't compose cleanly across — each primitive's typed-error class is module-local + the message string names the local opt. The duplicated shape is the symptom, not the cause; the cause is that JS doesn't have a way to throw an instance of caller-namespaced ErrorClass without the local closure.",
2207
+ },
2208
+ {
2209
+ mode: "family-subset",
2210
+ files: [
2211
+ "lib/archive-read.js:extract",
2212
+ "lib/archive-tar-read.js:extract",
2213
+ "lib/auth/ciba.js:pollToken",
2214
+ "lib/auth/oid4vci.js:exchangePreAuthorizedCode",
2215
+ "lib/auth/oid4vci.js:issueCredential",
2216
+ ],
2217
+ reason: "v0.12.7 + v0.12.8 — `try { ... await ... } catch (e) { /* per-step cleanup */ throw e; }` shape repeats across primitives doing multi-step async work with per-step rollback. archive-read.extract + archive-tar.extract both clean up partial-extract files; ciba.pollToken cleans up rate-limit + retry state; oid4vci.exchange/issueCredential clean up partial credential-state. Each catch body is primitive-specific (the cleanup it does is the primitive's responsibility) — extraction would require a generic transaction-style helper which is itself a v1.0+ surface decision. Five-file repetition with primitive-specific cleanup bodies stays as the documented exception.",
2218
+ },
2219
+ {
2220
+ mode: "family-subset",
2221
+ files: [
2222
+ "lib/archive-tar-read.js:_classifyTypeflag",
2223
+ "lib/archive-tar-read.js:inspect",
2224
+ "lib/auth/ciba.js:_registerInitialInterval",
2225
+ "lib/auth/oauth.js:exchangeToken",
2226
+ "lib/auth/oauth.js:pollDeviceCode",
2227
+ "lib/auth/oid4vci.js:createCredentialOffer",
2228
+ "lib/auth/oid4vci.js:exchangePreAuthorizedCode",
2229
+ "lib/restore-rollback.js:swap",
2230
+ ],
2231
+ reason: "v0.12.8 — Compact branching helpers (`if (x === A) return ...; if (x === B) return ...;` switch-style) repeat across primitives that map operator-supplied enum values to internal labels. archive-tar-read._classifyTypeflag maps single-char tar typeflags (0/1/2/3/4/5/6/7/x/g) to entry-type labels (file/symlink/hardlink/device/fifo/directory/etc.); archive-tar-read.inspect dispatches on the same typeflag set per-entry — distinct vocabulary from oauth.exchangeToken / oid4vci.createCredentialOffer / etc. which dispatch on grant_type / credential_format / step. The match is shape (chain of if-equals-return), not semantic. Extraction would require a generic enum-dispatch helper for trivially-different enums — that's an obscured abstraction. Each call site's enum + label set is primitive-specific.",
2232
+ },
2233
+ {
2234
+ mode: "family-subset",
2235
+ files: [
2236
+ "lib/archive-read.js:_normalizeEntryTypePolicy",
2237
+ "lib/archive-tar-read.js:_normalizeEntryTypePolicy",
2238
+ "lib/archive.js:writeTo",
2239
+ ],
2240
+ reason: "v0.12.8 — `_normalizeEntryTypePolicy` shape is genuinely duplicated between archive-read.js + archive-tar-read.js — both copy DEFAULT_ENTRY_TYPE_POLICY and merge with operator opts. Could extract to a shared lib/_archive-policy.js helper in a future patch; for v0.12.8 keeping the duplication so the format-specific entry-type vocabulary (zip's external-attrs vs tar's typeflag) stays close to the reader that uses it. archive.js:writeTo is the unrelated third file in the dup cluster — its toBuffer + writeFileSync shape happens to share the 50-token shingle by coincidence (writeTo is the legacy ZIP write-to-path helper, not policy-related).",
2241
+ },
2242
+ {
2243
+ mode: "family-subset",
2244
+ files: [
2245
+ "lib/agent-idempotency.js:_checkArgs",
2246
+ "lib/agent-tenant.js:_sealField",
2247
+ "lib/atomic-file.js:copyDirRecursive",
2248
+ "lib/ddl-change-control.js:approve",
2249
+ "lib/ddl-change-control.js:reject",
2250
+ "lib/deprecate.js:alias",
2251
+ "lib/guard-filename.js:verifyExtractionPath",
2252
+ "lib/jose-jwe-experimental.js:decrypt",
2253
+ "lib/mail-deploy.js:_validateTlsRptReport",
2254
+ "lib/totp.js:uri",
2255
+ ],
2256
+ reason: "v0.12.7 — Generic string-argument validation shape: `if (typeof X !== \"string\" || X.length === 0) throw new <ErrorClass>(<code>, ...)` repeats across primitives validating REQUIRED non-empty string opts. Each call site emits a primitive-specific typed error class (BackupError, GuardFilenameError, IdempotencyError, AgentTenantError, AtomicFileError, DdlError, DeprecateError, JoseError, MailDeployError, TotpError) so extracting to a shared helper would lose the per-primitive error namespace. validateOpts.requireNonEmptyString covers most call sites where the caller's typed-error class composes with the helper's caller-error-class shape; the 9 file paths here are inline because each one's typed error has a primitive-local code namespace + message string the helper can't compose cleanly. Same shape as the v0.10.16 client-hints/csp/sandbox family-subset reason (inline for per-primitive typed errors). 5/9/3-file subsets at smaller token windows are the same family — one entry covers all of them.",
2257
+ },
2188
2258
  {
2189
2259
  mode: "family-subset",
2190
2260
  files: [
@@ -5391,7 +5461,10 @@ var KNOWN_ANTIPATTERNS = [
5391
5461
  "lib/observability-otlp-exporter.js", // byResource grouping (Map<resKey, bucket>) — object-literal factory
5392
5462
  "lib/otel-export.js", // counters / observations (2 sites) — object-literal factory
5393
5463
  "lib/pubsub.js", // exactSubs (Map<channel, Set<sub>>) — Set factory
5464
+ "lib/backup/index.js", // bundleAdapterStorage.listBundles: byBundle (Map<bundleId, stats>) — object-literal factory
5394
5465
  ],
5466
+ // Strong-dup allowlists added with v0.12.7 archive substrate
5467
+ // — see KNOWN_CLUSTERS additions below for structural reasons.
5395
5468
  reason: "Node 26 ships Map.prototype.getOrInsertComputed(key, factory) — a single-lookup get-or-insert that replaces the two-step `var v = m.get(k); if (!v) { v = factory(); m.set(k, v); }` pattern. The sweep is deferred to the Node 26 floor-bump (eligible Oct 2026); engines.node is `>=24` today. Allowlist above is the survey ground truth from memory/specs/node-26-map-getorinsert-migration.md. New code post-this-patch trips the detector — either wait for the floor bump, or add the call site to BOTH the allowlist AND the migration spec in the same patch. When the floor moves, the bump commit walks the allowlist, rewrites each call site, drops the allowlist + flips the detector to enforce.",
5396
5469
  },
5397
5470
  {
@@ -5512,6 +5585,60 @@ var KNOWN_ANTIPATTERNS = [
5512
5585
  reason: "Codex P1 on v0.12.6 PR #157 — `_anyValueToProto` negative-int path wrapped a varint payload in `embeddedMessage` (wire-type 2) instead of using `int64` (wire-type 0 varint). The wire-type mismatch poisons the whole OTLP batch; the `v >>> 0` truncation also dropped sign + high bits. Fixed by adding `pb.int64` + `pb.sint64` to the encoder + routing the negative-int branch through `pb.int64`. Detector locks the shape: `embeddedMessage(N, _writeVarint(...))` cannot recur.",
5513
5586
  },
5514
5587
 
5588
+ {
5589
+ // Codex P1 on v0.12.7 PR #158 — archive-read.extract's rollback
5590
+ // cleanup deleted PRE-EXISTING destination files when a later
5591
+ // entry failed. The renameSync(tmpPath, resolvedPath) silently
5592
+ // overwrote operator files at the destination, then on abort the
5593
+ // catch-block rmSync wiped them out — permanent data loss
5594
+ // disguised as atomic rollback. Fix: refuse to write when the
5595
+ // destination path already exists; force operators to extract
5596
+ // into a fresh / empty subtree.
5597
+ //
5598
+ // Detector scope: any lib/archive*.js or lib/safe-archive.js file
5599
+ // that calls renameSync into a path it ALSO tracks for cleanup
5600
+ // MUST refuse overwrite up-front. Codify as a file-scoped invariant:
5601
+ // archive-read.js must contain "destination-exists" refusal code.
5602
+ id: "archive-extract-overwrite-without-refusal",
5603
+ primitive: "extract loops in lib/archive-read.js MUST refuse to write to a destination path that already exists — atomic rollback via tmp-rename + tracked-path cleanup is only safe when every tracked path was newly created. Pre-existing files at the destination + catch-block rmSync = data loss.",
5604
+ // File-scoped: only fires on archive-read.js / safe-archive.js
5605
+ // shape. The pattern is renameSync of a tmpPath onto resolvedPath
5606
+ // (the canonical destination variable) — atomic-file.js's
5607
+ // operator-file rename is a different shape (operator already
5608
+ // owns the destination context); http-client.js's atomic-tmp
5609
+ // rename writes operator-supplied paths under operator-supplied
5610
+ // tmp dirs, also a different concern.
5611
+ regex: /written\.push\s*\(\s*\{[^}]*path:\s*resolvedPath/,
5612
+ requires: /destination-exists/,
5613
+ skipCommentLines: true,
5614
+ allowlist: [],
5615
+ reason: "Codex P1 on v0.12.7 PR #158 — archive-read.extract used renameSync to atomically place each decompressed entry at its canonical destination + tracked written[].path for catch-block cleanup. When the destination directory was non-empty, the rename silently overwrote operator files; on extract abort, the cleanup deleted them. Fix: refuse upfront if destination path exists, force operators to use a fresh / empty subtree. Detector locks the shape: any extract code that tracks resolvedPath for catch-block cleanup MUST carry a `destination-exists` refusal in the same file.",
5616
+ },
5617
+
5618
+ {
5619
+ // Codex P1 on v0.12.8 PR #159 — archive-tar-read.js's walker
5620
+ // advanced `pos` by the declared padded block size without
5621
+ // checking that those bytes existed in the buffer. A truncated
5622
+ // archive (header says 11 bytes, buffer holds 8) silently
5623
+ // produced an entry whose extract() sliced the 8-byte prefix
5624
+ // and wrote it as if it were the complete file. Fix: refuse
5625
+ // upfront with a `truncated-entry` typed error when
5626
+ // `bodyStart + paddedSize > bytes.length`. Same shape applies
5627
+ // to the pax-extended-header path (its `bodyEnd` advance was
5628
+ // the same uncapped arithmetic).
5629
+ id: "archive-tar-walker-without-truncation-check",
5630
+ primitive: "tar walkers in lib/archive-tar-read.js MUST verify that the declared block size fits within the remaining buffer before advancing `pos` — a header that claims more bytes than the buffer holds is a truncated archive, not a valid entry. The refusal carries `truncated-entry` code so operators can distinguish wire-format-bad input from policy-bad input.",
5631
+ // File-scoped: only fires on archive-tar-read.js. The walker
5632
+ // advances pos by paddedSize (Math.ceil(hdr.size / BLOCK_SIZE)
5633
+ // * BLOCK_SIZE) — any code that adds paddedSize to pos without
5634
+ // a preceding bounds check is the smell.
5635
+ regex: /pos\s*\+=\s*paddedSize/,
5636
+ requires: /truncated-entry/,
5637
+ skipCommentLines: true,
5638
+ allowlist: [],
5639
+ reason: "Codex P1 on v0.12.8 PR #159 — archive-tar-read.js's tar walker recorded each entry and advanced pos by paddedSize without verifying the declared bytes existed in the buffer. A truncated archive silently produced a partial-content entry on extract — exact reproducer in the Codex thread: declared 11-byte file backed by 8 bytes of buffer produced an 8-byte output. Fix: refuse upfront with `archive-tar/truncated-entry` typed error. Detector locks the shape: any code path that advances pos by paddedSize in archive-tar-read.js MUST carry a `truncated-entry` refusal in the same file.",
5640
+ },
5641
+
5515
5642
  {
5516
5643
  // Codex P2 on v0.11.22 PR #126 — `b.cert.create`'s SNI dispatch
5517
5644
  // wildcard-matched `*.example.com` against `foo.bar.example.com`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/blamejs-shop",
3
- "version": "0.0.83",
3
+ "version": "0.0.85",
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": {
@@ -35,7 +35,7 @@
35
35
  "type": "git",
36
36
  "url": "git+https://github.com/blamejs/blamejs.shop.git"
37
37
  },
38
- "homepage": "https://github.com/blamejs/blamejs.shop",
38
+ "homepage": "https://blamejs.shop",
39
39
  "devDependencies": {
40
40
  "@cloudflare/containers": "^0.3.4",
41
41
  "wrangler": "^4.93.0"