coderifts 8.0.0 → 8.1.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coderifts",
3
- "version": "8.0.0",
3
+ "version": "8.1.0",
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",
@@ -36,17 +36,17 @@
36
36
  "homepage": "https://coderifts.com",
37
37
  "bugs": "https://github.com/coderifts/app/issues",
38
38
  "engines": {
39
- "node": ">=18.0.0"
39
+ "node": ">=20.0.0"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "node scripts/copy-corpus.js && node scripts/build.js",
43
- "prepublishOnly": "node scripts/assert-guard-major.js && node scripts/assert-changelog-version.js && bash ../../scripts/freeze-gate.sh && npm run build",
43
+ "prepublishOnly": "node scripts/assert-guard-major.js && node scripts/assert-changelog-version.js && bash ../../scripts/freeze-gate.sh && npm run build && bash ../../scripts/release-check.sh .",
44
44
  "assert-guard-major": "node scripts/assert-guard-major.js",
45
45
  "postinstall": "node scripts/postinstall.js",
46
46
  "test": "node --test test/*.test.js"
47
47
  },
48
48
  "dependencies": {
49
- "@coderifts/agent-guard": "^15.0.0",
49
+ "@coderifts/agent-guard": "^16.0.0",
50
50
  "chalk": "^4.1.2",
51
51
  "cli-table3": "^0.6.4",
52
52
  "commander": "^12.0.0",
@@ -60,7 +60,7 @@
60
60
  "json-schema-ref-parser": "npm:@apidevtools/json-schema-ref-parser@^11.7.3",
61
61
  "form-data": "^4.0.6",
62
62
  "axios": ">=1.18.0",
63
- "fast-uri": ">=3.1.5",
63
+ "fast-uri": ">=4.1.3",
64
64
  "brace-expansion": "5.0.9"
65
65
  },
66
66
  "devDependencies": {
@@ -73,13 +73,16 @@
73
73
  * asVerifiedDeployReceiptView, DEPLOY_RECEIPT_VIEW_SPEC and matchGlob — no DeployGateReason
74
74
  * exhaustive switch, no V2 config-conflict throw. The raise is installer-facing: the range
75
75
  * is what `npm i -g coderifts` resolves.)
76
+ * 8.1.0: floor raised to 16 (published guard 16.0.0 is on npm; 16 makes UNGUARDED_MUTATION
77
+ * fail-closed the default. The CLI range must match so `npm i -g coderifts` installs the guard
78
+ * whose default the docs describe, not the 15.x advisory-default it shipped alongside before.)
76
79
  */
77
80
 
78
81
  const fs = require('fs');
79
82
  const path = require('path');
80
83
 
81
84
  /** Minimum acceptable major for @coderifts/agent-guard in THIS package (the CLI). */
82
- const MIN_GUARD_MAJOR = 15;
85
+ const MIN_GUARD_MAJOR = 16;
83
86
  const DEP = '@coderifts/agent-guard';
84
87
 
85
88
  /**
@@ -109,7 +112,7 @@ const CHECKOUTS = [
109
112
  id: 'app-root',
110
113
  label: 'coderifts-app (root)',
111
114
  pkgPath: path.join(__dirname, '..', '..', '..', 'package.json'),
112
- floor: 3,
115
+ floor: 14,
113
116
  /**
114
117
  * DELIBERATE, MEASURED, AND LOWER THAN THE CLI'S — recorded so it is a decision, not a default.
115
118
  *
@@ -159,8 +162,10 @@ const CHECKOUTS = [
159
162
  * So the floor is pinned at 3 to stop it drifting LOWER unnoticed. Raise this number in that
160
163
  * round and record the reason on the line below, in the style of the CLI history above.
161
164
  */
162
- why: 'root pinned at 3 pending the gateDecision residual-PRECEDENCE reconciliation (see comment; '
163
- + 're-measured against 11.0.0 unchanged from 10.0.0).',
165
+ why: 'floor 14 = last measured merge-gate vintage (webhook-integration.js:344-345: '
166
+ + 'gateDecision call/return unchanged on 14; protection_inescapable is derived in-app '
167
+ + 'so a stale package cannot fail-open). Declared range is ^15 (installer). Floor is '
168
+ + 'not forced to 15: root code does not consume 15-only APIs on this path.',
164
169
  },
165
170
  ];
166
171
 
package/scripts/build.js CHANGED
@@ -8,6 +8,8 @@
8
8
  */
9
9
 
10
10
  const path = require('path');
11
+ const fs = require('fs');
12
+ const crypto = require('crypto');
11
13
  const esbuild = require('esbuild');
12
14
 
13
15
  const stub = path.join(__dirname, '..', 'src', 'logger-stub.js');
@@ -35,6 +37,48 @@ esbuild.build({
35
37
  });
36
38
  },
37
39
  }],
40
+ }).then(() => {
41
+ // ── 1353: build freshness ────────────────────────────────────────────────────────────────
42
+ //
43
+ // MEASURED 2026-09-04: dist/cli.js still printed the pre-1305 verdict a day after the source
44
+ // fix. `prepublishOnly` DOES run the build — the premise that it did not is wrong — so the
45
+ // PUBLISHED artifact was never at risk. The gap is LOCAL: dist/ is gitignored and the globally
46
+ // linked `coderifts` points straight at it, so a developer edits src, sees a green suite over
47
+ // src, and runs a stale binary. So does the reviewer.
48
+ //
49
+ // The build records a fingerprint of the sources it consumed; test/build-freshness.test.js
50
+ // recomputes it and fails when dist is behind — catching what a suite over src alone cannot.
51
+ //
52
+ // CONTENT-ADDRESSED, not timestamps: mtimes move on checkout, rebase and copy without the bytes
53
+ // changing, and a freshness check that cries wolf gets deleted.
54
+ 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');
75
+ 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.',
78
+ sha256,
79
+ file_count: files.length,
80
+ }, null, 2)}\n`);
81
+ process.stdout.write(`build: source fingerprint ${sha256.slice(0, 12)}… over ${files.length} files\n`);
38
82
  }).catch((err) => {
39
83
  console.error(err);
40
84
  process.exit(1);