coderifts 8.6.2 → 8.6.3

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 CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 8.6.3 - 2026-09-12
6
+
7
+ js-yaml moves to 4.3.2 in the shipped dependency set. The generated strict workflow pins contract-gate v0.9.5, following the gate release. The package metadata points at the public site rather than the private app repository.
8
+
9
+
5
10
  ## 8.6.2 - 2026-09-10
6
11
 
7
12
  The generated strict workflow pins contract-gate v0.9.3 (f288c4b), following the gate release. The Atomic-V2 installer teaches ENFORCING_ATOMIC_V2 with the v2 factors required, not Strict.
@@ -1,5 +1,5 @@
1
1
  {
2
- "$comment": "GENERATED by scripts/build.js. sha256 over src/**.js + bin/**.js (path + bytes). test/build-freshness.test.js recomputes it; a mismatch means dist/cli.js is stale.",
3
- "sha256": "3eec93dc767975626ebdebc8fe9ab226e6ea24668e2721af17e41ebc5c214495",
4
- "file_count": 49
2
+ "$comment": "GENERATED by scripts/build.js. sha256 over src/** + bin/** (path + bytes), for every extension esbuild bundles — .js AND .json. scripts/lib/source-fingerprint.js is the single implementation; test/build-freshness.test.js recomputes it from there rather than from a copy. A mismatch means dist/cli.js is stale.",
3
+ "sha256": "161a9dee4c63f32c2a90dda17091ef50d667bcc084bdd25ae62b1cfe804eea68",
4
+ "file_count": 51
5
5
  }
package/dist/cli.js CHANGED
@@ -3028,7 +3028,7 @@ var require_package = __commonJS({
3028
3028
  "package.json"(exports2, module2) {
3029
3029
  module2.exports = {
3030
3030
  name: "coderifts",
3031
- version: "8.6.2",
3031
+ version: "8.6.3",
3032
3032
  description: "Detect breaking API changes from the command line. Works locally or with the CodeRifts cloud API.",
3033
3033
  author: "CodeRifts <hello@coderifts.com>",
3034
3034
  license: "MIT",
@@ -3056,13 +3056,12 @@ var require_package = __commonJS({
3056
3056
  "swagger",
3057
3057
  "devtools"
3058
3058
  ],
3059
- repository: {
3060
- type: "git",
3061
- url: "git+https://github.com/coderifts/app.git",
3062
- directory: "packages/cli"
3063
- },
3059
+ repository: "https://coderifts.com",
3064
3060
  homepage: "https://coderifts.com",
3065
- bugs: "https://github.com/coderifts/app/issues",
3061
+ bugs: {
3062
+ url: "https://coderifts.com",
3063
+ email: "support@coderifts.com"
3064
+ },
3066
3065
  engines: {
3067
3066
  node: ">=20.0.0"
3068
3067
  },
@@ -3080,7 +3079,7 @@ var require_package = __commonJS({
3080
3079
  "cli-table3": "^0.6.4",
3081
3080
  commander: "^12.0.0",
3082
3081
  inquirer: "^8.2.6",
3083
- "js-yaml": "^4.3.1",
3082
+ "js-yaml": "^4.3.2",
3084
3083
  "openapi-diff": "^0.24.1",
3085
3084
  ora: "^5.4.1"
3086
3085
  },
@@ -11701,16 +11700,21 @@ var require_loader = __commonJS({
11701
11700
  state.result += _result;
11702
11701
  }
11703
11702
  }
11703
+ function chargeMergeWork(state) {
11704
+ state.totalMergeKeys++;
11705
+ if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) {
11706
+ throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")");
11707
+ }
11708
+ }
11704
11709
  function mergeMappings(state, destination, source, overridableKeys) {
11705
11710
  if (!common.isObject(source)) {
11706
11711
  throwError(state, "cannot merge mappings; the provided source object is unacceptable");
11707
11712
  }
11713
+ chargeMergeWork(state);
11708
11714
  const sourceKeys = Object.keys(source);
11709
11715
  for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
11710
11716
  const key = sourceKeys[index];
11711
- if (state.maxTotalMergeKeys !== -1 && ++state.totalMergeKeys > state.maxTotalMergeKeys) {
11712
- throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")");
11713
- }
11717
+ chargeMergeWork(state);
11714
11718
  if (!_hasOwnProperty.call(destination, key)) {
11715
11719
  setProperty(destination, key, source[key]);
11716
11720
  overridableKeys[key] = true;
@@ -11738,6 +11742,9 @@ var require_loader = __commonJS({
11738
11742
  }
11739
11743
  if (keyTag === "tag:yaml.org,2002:merge") {
11740
11744
  if (Array.isArray(valueNode)) {
11745
+ if (valueNode.length > 100) {
11746
+ throwError(state, "abnormal merge sequence size");
11747
+ }
11741
11748
  for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) {
11742
11749
  mergeMappings(state, _result, valueNode[index], overridableKeys);
11743
11750
  }
@@ -163516,16 +163523,21 @@ var require_loader2 = __commonJS({
163516
163523
  state.result += _result;
163517
163524
  }
163518
163525
  }
163526
+ function chargeMergeWork(state) {
163527
+ state.totalMergeKeys++;
163528
+ if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) {
163529
+ throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")");
163530
+ }
163531
+ }
163519
163532
  function mergeMappings(state, destination, source, overridableKeys) {
163520
163533
  if (!common.isObject(source)) {
163521
163534
  throwError(state, "cannot merge mappings; the provided source object is unacceptable");
163522
163535
  }
163536
+ chargeMergeWork(state);
163523
163537
  const sourceKeys = Object.keys(source);
163524
163538
  for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
163525
163539
  const key = sourceKeys[index];
163526
- if (state.maxTotalMergeKeys !== -1 && ++state.totalMergeKeys > state.maxTotalMergeKeys) {
163527
- throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")");
163528
- }
163540
+ chargeMergeWork(state);
163529
163541
  if (!_hasOwnProperty.call(destination, key)) {
163530
163542
  setProperty(destination, key, source[key]);
163531
163543
  overridableKeys[key] = true;
@@ -163553,6 +163565,9 @@ var require_loader2 = __commonJS({
163553
163565
  }
163554
163566
  if (keyTag === "tag:yaml.org,2002:merge") {
163555
163567
  if (Array.isArray(valueNode)) {
163568
+ if (valueNode.length > 100) {
163569
+ throwError(state, "abnormal merge sequence size");
163570
+ }
163556
163571
  for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) {
163557
163572
  mergeMappings(state, _result, valueNode[index], overridableKeys);
163558
163573
  }
@@ -231520,10 +231535,10 @@ var require_gate_pin = __commonJS({
231520
231535
  "src/generated/gate-pin.json"(exports2, module2) {
231521
231536
  module2.exports = {
231522
231537
  repo: "coderifts/contract-gate",
231523
- sha: "f288c4bea752db6b405367c8e3b81e7885c54b20",
231524
- tag: "v0.9.3",
231538
+ sha: "15c19a6373ad69f5a8aaee992b69bc38baf98f14",
231539
+ tag: "v0.9.5",
231525
231540
  resolved_from: "https://github.com/coderifts/contract-gate refs/tags/v0",
231526
- resolved_at: "2026-09-10T06:43:53Z",
231541
+ resolved_at: "2026-09-12T19:02:41Z",
231527
231542
  note: "STRICT template pins this full commit SHA (GitHub: only a full SHA is immutable). v0 is a tag we move on every release, so it is NOT a pin. Re-run scripts/generate-gate-pin.js on each gate release; Dependabot bumps adopters."
231528
231543
  };
231529
231544
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coderifts",
3
- "version": "8.6.2",
3
+ "version": "8.6.3",
4
4
  "description": "Detect breaking API changes from the command line. Works locally or with the CodeRifts cloud API.",
5
5
  "author": "CodeRifts <hello@coderifts.com>",
6
6
  "license": "MIT",
@@ -28,13 +28,12 @@
28
28
  "swagger",
29
29
  "devtools"
30
30
  ],
31
- "repository": {
32
- "type": "git",
33
- "url": "git+https://github.com/coderifts/app.git",
34
- "directory": "packages/cli"
35
- },
31
+ "repository": "https://coderifts.com",
36
32
  "homepage": "https://coderifts.com",
37
- "bugs": "https://github.com/coderifts/app/issues",
33
+ "bugs": {
34
+ "url": "https://coderifts.com",
35
+ "email": "support@coderifts.com"
36
+ },
38
37
  "engines": {
39
38
  "node": ">=20.0.0"
40
39
  },
@@ -52,7 +51,7 @@
52
51
  "cli-table3": "^0.6.4",
53
52
  "commander": "^12.0.0",
54
53
  "inquirer": "^8.2.6",
55
- "js-yaml": "^4.3.1",
54
+ "js-yaml": "^4.3.2",
56
55
  "openapi-diff": "^0.24.1",
57
56
  "ora": "^5.4.1"
58
57
  },
package/scripts/build.js CHANGED
@@ -11,6 +11,7 @@ const path = require('path');
11
11
  const fs = require('fs');
12
12
  const crypto = require('crypto');
13
13
  const esbuild = require('esbuild');
14
+ const { sourceFingerprint } = require('./lib/source-fingerprint');
14
15
 
15
16
  const stub = path.join(__dirname, '..', 'src', 'logger-stub.js');
16
17
  const appLogger = path.resolve(__dirname, '..', '..', '..', 'src', 'logger.js');
@@ -52,33 +53,16 @@ esbuild.build({
52
53
  // CONTENT-ADDRESSED, not timestamps: mtimes move on checkout, rebase and copy without the bytes
53
54
  // changing, and a freshness check that cries wolf gets deleted.
54
55
  const root = path.join(__dirname, '..');
55
- const files = [];
56
- const walk = (dir) => {
57
- if (!fs.existsSync(dir)) return;
58
- for (const e of fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
59
- if (e.name === 'node_modules' || e.name.startsWith('.')) continue;
60
- const full = path.join(dir, e.name);
61
- if (e.isDirectory()) walk(full);
62
- else if (e.name.endsWith('.js')) files.push(full);
63
- }
64
- };
65
- walk(path.join(root, 'src'));
66
- walk(path.join(root, 'bin'));
67
- const h = crypto.createHash('sha256');
68
- for (const f of files.sort()) {
69
- h.update(path.relative(root, f));
70
- h.update('\0');
71
- h.update(fs.readFileSync(f));
72
- h.update('\0');
73
- }
74
- const sha256 = h.digest('hex');
56
+ const { sha256, file_count } = sourceFingerprint(root);
75
57
  fs.writeFileSync(path.join(root, 'dist', '.build-source-sha'), `${JSON.stringify({
76
- $comment: 'GENERATED by scripts/build.js. sha256 over src/**.js + bin/**.js (path + bytes). '
77
- + 'test/build-freshness.test.js recomputes it; a mismatch means dist/cli.js is stale.',
58
+ $comment: 'GENERATED by scripts/build.js. sha256 over src/** + bin/** (path + bytes), for '
59
+ + 'every extension esbuild bundles .js AND .json. scripts/lib/source-fingerprint.js is '
60
+ + 'the single implementation; test/build-freshness.test.js recomputes it from there rather '
61
+ + 'than from a copy. A mismatch means dist/cli.js is stale.',
78
62
  sha256,
79
- file_count: files.length,
63
+ file_count,
80
64
  }, null, 2)}\n`);
81
- process.stdout.write(`build: source fingerprint ${sha256.slice(0, 12)}… over ${files.length} files\n`);
65
+ process.stdout.write(`build: source fingerprint ${sha256.slice(0, 12)}… over ${file_count} files\n`);
82
66
  }).catch((err) => {
83
67
  console.error(err);
84
68
  process.exit(1);
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ /*
4
+ * The source fingerprint dist/cli.js is stamped with, and the one test/build-freshness.test.js
5
+ * recomputes. ONE implementation, required by both.
6
+ *
7
+ * WHY IT LIVES HERE. The walk used to exist twice — once in scripts/build.js and once inside the
8
+ * test, whose comment said the copy was "kept in step by the assertions below". No assertion
9
+ * compared them, so "kept in step" was a hope. MEASURED 2026-09-12: it had already failed in one
10
+ * direction and was about to fail in the other. A freshness gate whose recomputation is a COPY of
11
+ * the thing it checks can drift from it silently, which is the one failure a freshness gate must
12
+ * not have.
13
+ *
14
+ * .json COUNTS. esbuild inlines src/generated/gate-pin.json into dist/cli.js, so it is shipped
15
+ * runtime rather than configuration beside it. With a .js-only walk the pin moved from v0.9.3 to
16
+ * v0.9.4 while the marker stayed green and dist kept naming v0.9.3 — the marker's own comment
17
+ * promises that a mismatch means dist is stale, and for a bundled JSON it did not deliver.
18
+ */
19
+
20
+ const path = require('path');
21
+ const fs = require('fs');
22
+ const crypto = require('crypto');
23
+
24
+ /** Extensions that end up INSIDE the bundle. Anything here changes the shipped runtime. */
25
+ const BUNDLED_EXT = Object.freeze(['.js', '.json']);
26
+
27
+ /**
28
+ * sha256 over src/** + bin/** (path + bytes), content-addressed — never mtime: mtimes move on
29
+ * checkout, rebase and copy with no byte change, and a freshness check that cries wolf gets
30
+ * deleted.
31
+ * @param {string} root package root
32
+ */
33
+ function sourceFingerprint(root) {
34
+ const files = [];
35
+ const walk = (dir) => {
36
+ if (!fs.existsSync(dir)) return;
37
+ for (const e of fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
38
+ if (e.name === 'node_modules' || e.name.startsWith('.')) continue;
39
+ const full = path.join(dir, e.name);
40
+ if (e.isDirectory()) walk(full);
41
+ else if (BUNDLED_EXT.some((x) => e.name.endsWith(x))) files.push(full);
42
+ }
43
+ };
44
+ walk(path.join(root, 'src'));
45
+ walk(path.join(root, 'bin'));
46
+ const h = crypto.createHash('sha256');
47
+ for (const f of files.sort()) {
48
+ h.update(path.relative(root, f));
49
+ h.update('\0');
50
+ h.update(fs.readFileSync(f));
51
+ h.update('\0');
52
+ }
53
+ return { sha256: h.digest('hex'), file_count: files.length };
54
+ }
55
+
56
+ module.exports = { sourceFingerprint, BUNDLED_EXT };