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 +5 -0
- package/dist/.build-source-sha +3 -3
- package/dist/cli.js +32 -17
- package/package.json +7 -8
- package/scripts/build.js +8 -24
- package/scripts/lib/source-fingerprint.js +56 -0
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.
|
package/dist/.build-source-sha
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "GENERATED by scripts/build.js. sha256 over src
|
|
3
|
-
"sha256": "
|
|
4
|
-
"file_count":
|
|
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.
|
|
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:
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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: "
|
|
231524
|
-
tag: "v0.9.
|
|
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-
|
|
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.
|
|
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":
|
|
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.
|
|
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
|
|
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
|
|
77
|
-
+ '
|
|
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
|
|
63
|
+
file_count,
|
|
80
64
|
}, null, 2)}\n`);
|
|
81
|
-
process.stdout.write(`build: source fingerprint ${sha256.slice(0, 12)}… over ${
|
|
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 };
|