coderifts 6.0.0 → 6.0.2
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 +27 -2
- package/dist/cli.js +233 -30
- package/package.json +2 -2
- package/scripts/assert-guard-major.js +21 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 6.0.
|
|
3
|
+
## 6.0.2
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **init --agents wrote 8 of 9 embedded files.** The skill file joined the single source on 2026-08-25 but was never added to EXTRA_RULES_ON_ALL, a second hand-maintained list. Every release since shipped an installer that under-writes, and agent-setup --check was correctly reporting DRIFT the whole time.
|
|
8
|
+
- **The strict workflow pins actions/checkout too.** It runs first and fetches the code every later step reads; the least pinned step in the strict chain was the most load-bearing.
|
|
9
|
+
|
|
10
|
+
## 6.0.1
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- **Guard floor raised to 13, declared range `^13.0.0`.** ADOPTER-FACING: the guard is a direct
|
|
14
|
+
dependency with no `peerDependencies` and no bundled copy, so this range *is* what a fresh install
|
|
15
|
+
resolves. `coderifts@5.0.1` declared `^12.0.0`, which resolves to 12.0.0 — the version in which
|
|
16
|
+
`wrapWriteWithFsCas` measured its expected CAS token INSIDE `executeFactory`, after preflight and
|
|
17
|
+
after the T2 recheck, and conditioned the write on that self-fetched value. Measured on 12.0.0: a
|
|
18
|
+
writer landing in that window had its state adopted as the legitimate starting point and the CAS
|
|
19
|
+
still returned `committed` with `enforced: true`, clobbering it. 13.0.0 threads the
|
|
20
|
+
authorization-time token, and adds three filesystem defences that were measured absent rather than
|
|
21
|
+
assumed — `..` refused before resolution, a symlinked final component refused (`stat`/`readFile`
|
|
22
|
+
measured the link's TARGET while `rename` replaced the LINK, so check and write named different
|
|
23
|
+
objects), the token read through a single file descriptor, and `dev`+`ino` recorded in the write
|
|
24
|
+
evidence.
|
|
25
|
+
|
|
26
|
+
**Cost measured as zero**, the same way the 11-, 12- and 13-raises were: the CLI imports only
|
|
27
|
+
`deployGate`, `asVerifiedDeployReceiptView`, `DEPLOY_RECEIPT_VIEW_SPEC` and `matchGlob`, whose
|
|
28
|
+
implementing modules are byte-identical 12.0.0 → 13.0.0, and all four return identical values
|
|
29
|
+
under both. Suite staged against 13.0.0 returned an identical 539/518/21 with a byte-identical
|
|
30
|
+
28-item failure set. Nothing in the CLI calls the CAS or FS adapters.
|
|
6
31
|
|
|
7
32
|
## 5.0.1
|
|
8
33
|
|
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: "6.0.
|
|
3031
|
+
version: "6.0.2",
|
|
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",
|
|
@@ -3073,7 +3073,7 @@ var require_package = __commonJS({
|
|
|
3073
3073
|
test: "node --test test/*.test.js"
|
|
3074
3074
|
},
|
|
3075
3075
|
dependencies: {
|
|
3076
|
-
"@coderifts/agent-guard": "^
|
|
3076
|
+
"@coderifts/agent-guard": "^13.0.0",
|
|
3077
3077
|
chalk: "^4.1.2",
|
|
3078
3078
|
"cli-table3": "^0.6.4",
|
|
3079
3079
|
commander: "^12.0.0",
|
|
@@ -67189,6 +67189,9 @@ var require_conditional_write = __commonJS({
|
|
|
67189
67189
|
write_style,
|
|
67190
67190
|
mutating
|
|
67191
67191
|
};
|
|
67192
|
+
if (ctx.guarantee === "SAME_TRANSACTION" || ctx.guarantee === "CONDITIONAL_EXTERNAL" || ctx.guarantee === "NON_ATOMIC") {
|
|
67193
|
+
basis.guarantee = ctx.guarantee;
|
|
67194
|
+
}
|
|
67192
67195
|
if (conditional_write === true) {
|
|
67193
67196
|
if (typeof ctx.conditioned_on_token === "string") {
|
|
67194
67197
|
basis.conditioned_on_token = ctx.conditioned_on_token;
|
|
@@ -67324,8 +67327,11 @@ var require_fs = __commonJS({
|
|
|
67324
67327
|
};
|
|
67325
67328
|
})();
|
|
67326
67329
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
67327
|
-
exports2.tokensEqual = exports2.FS_ABSENT_TOKEN = exports2.FS_VERSION_TOKEN_PREFIX = void 0;
|
|
67330
|
+
exports2.tokensEqual = exports2.UnsafeCasPathError = exports2.FS_ABSENT_TOKEN = exports2.FS_VERSION_TOKEN_PREFIX = void 0;
|
|
67328
67331
|
exports2.fsTokenContentHash = fsTokenContentHash;
|
|
67332
|
+
exports2.assertSafeCasPath = assertSafeCasPath;
|
|
67333
|
+
exports2.fsObjectIdentity = fsObjectIdentity;
|
|
67334
|
+
exports2.identitiesEqual = identitiesEqual;
|
|
67329
67335
|
exports2.createFsVersionToken = createFsVersionToken;
|
|
67330
67336
|
exports2.readVersionedFile = readVersionedFile;
|
|
67331
67337
|
exports2.writeFileIfUnchanged = writeFileIfUnchanged;
|
|
@@ -67354,23 +67360,90 @@ var require_fs = __commonJS({
|
|
|
67354
67360
|
const hash = rest.slice(colon + 1);
|
|
67355
67361
|
return /^[a-f0-9]{64}$/.test(hash) ? hash : null;
|
|
67356
67362
|
}
|
|
67363
|
+
var UnsafeCasPathError = class extends Error {
|
|
67364
|
+
reason;
|
|
67365
|
+
casPath;
|
|
67366
|
+
constructor(reason, casPath) {
|
|
67367
|
+
super(`unsafe CAS path (${reason}): ${casPath}`);
|
|
67368
|
+
this.name = "UnsafeCasPathError";
|
|
67369
|
+
this.reason = reason;
|
|
67370
|
+
this.casPath = casPath;
|
|
67371
|
+
}
|
|
67372
|
+
};
|
|
67373
|
+
exports2.UnsafeCasPathError = UnsafeCasPathError;
|
|
67374
|
+
async function assertSafeCasPath(filePath) {
|
|
67375
|
+
const segments = filePath.split(/[\\/]+/);
|
|
67376
|
+
if (segments.includes(".."))
|
|
67377
|
+
throw new UnsafeCasPathError("path_traversal", filePath);
|
|
67378
|
+
const resolved = path.resolve(filePath);
|
|
67379
|
+
const dir = path.dirname(resolved);
|
|
67380
|
+
let canonicalDir = dir;
|
|
67381
|
+
try {
|
|
67382
|
+
canonicalDir = await node_fs_1.promises.realpath(dir);
|
|
67383
|
+
} catch (err) {
|
|
67384
|
+
const code = err && typeof err === "object" && "code" in err ? String(err.code) : "";
|
|
67385
|
+
if (code !== "ENOENT")
|
|
67386
|
+
throw err;
|
|
67387
|
+
}
|
|
67388
|
+
const target = path.join(canonicalDir, path.basename(resolved));
|
|
67389
|
+
try {
|
|
67390
|
+
const lst = await node_fs_1.promises.lstat(target);
|
|
67391
|
+
if (lst.isSymbolicLink())
|
|
67392
|
+
throw new UnsafeCasPathError("symlink_target", filePath);
|
|
67393
|
+
} catch (err) {
|
|
67394
|
+
if (err instanceof UnsafeCasPathError)
|
|
67395
|
+
throw err;
|
|
67396
|
+
const code = err && typeof err === "object" && "code" in err ? String(err.code) : "";
|
|
67397
|
+
if (code !== "ENOENT")
|
|
67398
|
+
throw err;
|
|
67399
|
+
}
|
|
67400
|
+
return target;
|
|
67401
|
+
}
|
|
67402
|
+
async function fsObjectIdentity(filePath) {
|
|
67403
|
+
let fh;
|
|
67404
|
+
try {
|
|
67405
|
+
fh = await node_fs_1.promises.open(filePath, "r");
|
|
67406
|
+
const st = await fh.stat();
|
|
67407
|
+
return { dev: st.dev, ino: st.ino };
|
|
67408
|
+
} catch (err) {
|
|
67409
|
+
const code = err && typeof err === "object" && "code" in err ? String(err.code) : "";
|
|
67410
|
+
if (code === "ENOENT")
|
|
67411
|
+
return null;
|
|
67412
|
+
throw err;
|
|
67413
|
+
} finally {
|
|
67414
|
+
if (fh)
|
|
67415
|
+
await fh.close().catch(() => {
|
|
67416
|
+
});
|
|
67417
|
+
}
|
|
67418
|
+
}
|
|
67419
|
+
function identitiesEqual(a, b) {
|
|
67420
|
+
if (!a || !b)
|
|
67421
|
+
return false;
|
|
67422
|
+
return a.dev === b.dev && a.ino === b.ino;
|
|
67423
|
+
}
|
|
67357
67424
|
async function createFsVersionToken(filePath) {
|
|
67358
|
-
let
|
|
67425
|
+
let fh;
|
|
67359
67426
|
try {
|
|
67360
|
-
|
|
67427
|
+
fh = await node_fs_1.promises.open(filePath, "r");
|
|
67361
67428
|
} catch (err) {
|
|
67362
67429
|
const code = err && typeof err === "object" && "code" in err ? String(err.code) : "";
|
|
67363
67430
|
if (code === "ENOENT")
|
|
67364
67431
|
return exports2.FS_ABSENT_TOKEN;
|
|
67365
67432
|
throw err;
|
|
67366
67433
|
}
|
|
67367
|
-
|
|
67368
|
-
|
|
67434
|
+
try {
|
|
67435
|
+
const st = await fh.stat();
|
|
67436
|
+
if (!st.isFile()) {
|
|
67437
|
+
throw new Error(`createFsVersionToken: not a regular file: ${filePath}`);
|
|
67438
|
+
}
|
|
67439
|
+
const buf = await fh.readFile();
|
|
67440
|
+
const hash = sha256hex(buf);
|
|
67441
|
+
const mtimeMs = Math.trunc(st.mtimeMs);
|
|
67442
|
+
return `${exports2.FS_VERSION_TOKEN_PREFIX}${mtimeMs}:${hash}`;
|
|
67443
|
+
} finally {
|
|
67444
|
+
await fh.close().catch(() => {
|
|
67445
|
+
});
|
|
67369
67446
|
}
|
|
67370
|
-
const buf = await node_fs_1.promises.readFile(filePath);
|
|
67371
|
-
const hash = sha256hex(buf);
|
|
67372
|
-
const mtimeMs = Math.trunc(st.mtimeMs);
|
|
67373
|
-
return `${exports2.FS_VERSION_TOKEN_PREFIX}${mtimeMs}:${hash}`;
|
|
67374
67447
|
}
|
|
67375
67448
|
async function readVersionedFile(filePath) {
|
|
67376
67449
|
const version_token = await createFsVersionToken(filePath);
|
|
@@ -67381,9 +67454,23 @@ var require_fs = __commonJS({
|
|
|
67381
67454
|
return { content, version_token };
|
|
67382
67455
|
}
|
|
67383
67456
|
async function writeFileIfUnchanged(args) {
|
|
67384
|
-
const target =
|
|
67457
|
+
const target = await assertSafeCasPath(args.path);
|
|
67385
67458
|
const body = typeof args.content === "string" ? Buffer.from(args.content, "utf8") : args.content;
|
|
67386
67459
|
const writtenHash = sha256hex(body);
|
|
67460
|
+
const checkedIdentity = await fsObjectIdentity(target);
|
|
67461
|
+
const hasT1Identity = Object.prototype.hasOwnProperty.call(args, "expected_identity");
|
|
67462
|
+
if (hasT1Identity) {
|
|
67463
|
+
const t1 = args.expected_identity ?? null;
|
|
67464
|
+
const held = t1 === null ? checkedIdentity === null : identitiesEqual(t1, checkedIdentity);
|
|
67465
|
+
if (!held) {
|
|
67466
|
+
return {
|
|
67467
|
+
status: "refused",
|
|
67468
|
+
reason: "stale_version_token",
|
|
67469
|
+
expected_token: args.expected_token,
|
|
67470
|
+
current_token: await createFsVersionToken(target).catch(() => null)
|
|
67471
|
+
};
|
|
67472
|
+
}
|
|
67473
|
+
}
|
|
67387
67474
|
return (0, conditional_write_js_1.executeIfUnchanged)({
|
|
67388
67475
|
expected_token: args.expected_token,
|
|
67389
67476
|
current_token: () => createFsVersionToken(target),
|
|
@@ -67402,6 +67489,15 @@ var require_fs = __commonJS({
|
|
|
67402
67489
|
const tmp = path.join(dir, `.coderifts-cas-${path.basename(target)}-${process.pid}-${(0, node_crypto_1.randomBytes)(6).toString("hex")}.tmp`);
|
|
67403
67490
|
try {
|
|
67404
67491
|
await node_fs_1.promises.writeFile(tmp, body);
|
|
67492
|
+
const stillIdentity = await fsObjectIdentity(target);
|
|
67493
|
+
const identityHeld = checkedIdentity === null ? stillIdentity === null : identitiesEqual(checkedIdentity, stillIdentity);
|
|
67494
|
+
if (!identityHeld) {
|
|
67495
|
+
try {
|
|
67496
|
+
await node_fs_1.promises.unlink(tmp);
|
|
67497
|
+
} catch {
|
|
67498
|
+
}
|
|
67499
|
+
throw new conditional_write_js_1.StaleVersionTokenAbort(await createFsVersionToken(target).catch(() => null));
|
|
67500
|
+
}
|
|
67405
67501
|
const still = await createFsVersionToken(target);
|
|
67406
67502
|
if (!(0, conditional_write_js_1.tokensEqual)(args.expected_token, still)) {
|
|
67407
67503
|
try {
|
|
@@ -67420,7 +67516,13 @@ var require_fs = __commonJS({
|
|
|
67420
67516
|
}
|
|
67421
67517
|
throw err;
|
|
67422
67518
|
}
|
|
67423
|
-
return {
|
|
67519
|
+
return {
|
|
67520
|
+
path: target,
|
|
67521
|
+
bytes: body.length,
|
|
67522
|
+
written_content_hash: writtenHash,
|
|
67523
|
+
checked_identity: checkedIdentity,
|
|
67524
|
+
committed_identity: await fsObjectIdentity(target)
|
|
67525
|
+
};
|
|
67424
67526
|
}
|
|
67425
67527
|
});
|
|
67426
67528
|
}
|
|
@@ -69409,6 +69511,10 @@ var require_cas_attestation = __commonJS({
|
|
|
69409
69511
|
const s = x;
|
|
69410
69512
|
return s.reason === "stale_during_commit" && typeof s.expected_token === "string";
|
|
69411
69513
|
}
|
|
69514
|
+
if (o.status === "indeterminate") {
|
|
69515
|
+
const i = x;
|
|
69516
|
+
return (i.reason === "response_lost" || i.reason === "ambiguous_provider_reply" || i.reason === "observation_failed") && typeof i.expected_token === "string";
|
|
69517
|
+
}
|
|
69412
69518
|
return false;
|
|
69413
69519
|
}
|
|
69414
69520
|
function freezeExecutionResultHash(h) {
|
|
@@ -69431,6 +69537,15 @@ var require_cas_attestation = __commonJS({
|
|
|
69431
69537
|
current_token: outcome.current_token == null ? null : outcome.current_token
|
|
69432
69538
|
});
|
|
69433
69539
|
}
|
|
69540
|
+
if (outcome.status === "indeterminate") {
|
|
69541
|
+
return Object.freeze({
|
|
69542
|
+
status: "indeterminate",
|
|
69543
|
+
write_ran: "unknown",
|
|
69544
|
+
reason: outcome.reason,
|
|
69545
|
+
expected_token: outcome.expected_token,
|
|
69546
|
+
observed_token: outcome.observed_token == null ? null : outcome.observed_token
|
|
69547
|
+
});
|
|
69548
|
+
}
|
|
69434
69549
|
return Object.freeze({
|
|
69435
69550
|
status: "committed_stale_detected",
|
|
69436
69551
|
write_ran: true,
|
|
@@ -69451,6 +69566,7 @@ var require_cas_attestation = __commonJS({
|
|
|
69451
69566
|
const write_ran = cas.write_ran === true;
|
|
69452
69567
|
const stale_during_commit = cas.status === "committed_stale_detected";
|
|
69453
69568
|
const refused = cas.status === "refused";
|
|
69569
|
+
const indeterminate = cas.status === "indeterminate";
|
|
69454
69570
|
const cas_evidence = evaluateCasEvidence(outcome, opts);
|
|
69455
69571
|
let authorized_and_committed = receipt_verified && cas.status === "committed";
|
|
69456
69572
|
if (opts.profile === "ENFORCING_STRICT") {
|
|
@@ -69471,7 +69587,8 @@ var require_cas_attestation = __commonJS({
|
|
|
69471
69587
|
authorized_and_committed,
|
|
69472
69588
|
write_ran,
|
|
69473
69589
|
stale_during_commit,
|
|
69474
|
-
refused
|
|
69590
|
+
refused,
|
|
69591
|
+
indeterminate
|
|
69475
69592
|
}),
|
|
69476
69593
|
cas_evidence,
|
|
69477
69594
|
limits: LIMITS
|
|
@@ -72729,6 +72846,8 @@ var require_fs_default_wire = __commonJS({
|
|
|
72729
72846
|
exports2.inferFsPathFromArgs = inferFsPathFromArgs;
|
|
72730
72847
|
exports2.inferFullFileWriteContent = inferFullFileWriteContent;
|
|
72731
72848
|
exports2.wrapWriteWithFsCas = wrapWriteWithFsCas;
|
|
72849
|
+
exports2.measureFsAuthorization = measureFsAuthorization;
|
|
72850
|
+
exports2.measureFsAuthorizationToken = measureFsAuthorizationToken;
|
|
72732
72851
|
var cas_attestation_js_1 = require_cas_attestation();
|
|
72733
72852
|
var fs_js_1 = require_fs();
|
|
72734
72853
|
function inferFsPathFromArgs(args) {
|
|
@@ -72755,20 +72874,16 @@ var require_fs_default_wire = __commonJS({
|
|
|
72755
72874
|
}
|
|
72756
72875
|
return null;
|
|
72757
72876
|
}
|
|
72758
|
-
async function wrapWriteWithFsCas(args, write) {
|
|
72877
|
+
async function wrapWriteWithFsCas(args, write, opts) {
|
|
72759
72878
|
const filePath = inferFsPathFromArgs(args);
|
|
72760
72879
|
const content = inferFullFileWriteContent(args);
|
|
72761
|
-
|
|
72762
|
-
|
|
72763
|
-
try {
|
|
72764
|
-
expected = await (0, fs_js_1.createFsVersionToken)(filePath);
|
|
72765
|
-
} catch {
|
|
72766
|
-
return write();
|
|
72767
|
-
}
|
|
72880
|
+
const expected = opts && typeof opts.expected_token === "string" ? opts.expected_token : null;
|
|
72881
|
+
if (filePath && content != null && expected !== null) {
|
|
72768
72882
|
return (0, fs_js_1.writeFileIfUnchanged)({
|
|
72769
72883
|
path: filePath,
|
|
72770
72884
|
expected_token: expected,
|
|
72771
|
-
content
|
|
72885
|
+
content,
|
|
72886
|
+
...opts && "expected_identity" in opts ? { expected_identity: opts.expected_identity ?? null } : {}
|
|
72772
72887
|
});
|
|
72773
72888
|
}
|
|
72774
72889
|
const raw = await write();
|
|
@@ -72776,6 +72891,24 @@ var require_fs_default_wire = __commonJS({
|
|
|
72776
72891
|
return raw;
|
|
72777
72892
|
return raw;
|
|
72778
72893
|
}
|
|
72894
|
+
async function measureFsAuthorization(args) {
|
|
72895
|
+
const filePath = inferFsPathFromArgs(args);
|
|
72896
|
+
const content = inferFullFileWriteContent(args);
|
|
72897
|
+
if (!filePath || content == null)
|
|
72898
|
+
return null;
|
|
72899
|
+
try {
|
|
72900
|
+
const target = await (0, fs_js_1.assertSafeCasPath)(filePath);
|
|
72901
|
+
const expected_identity = await (0, fs_js_1.fsObjectIdentity)(target);
|
|
72902
|
+
const expected_token = await (0, fs_js_1.createFsVersionToken)(target);
|
|
72903
|
+
return { expected_token, expected_identity };
|
|
72904
|
+
} catch {
|
|
72905
|
+
return null;
|
|
72906
|
+
}
|
|
72907
|
+
}
|
|
72908
|
+
async function measureFsAuthorizationToken(args) {
|
|
72909
|
+
const m = await measureFsAuthorization(args);
|
|
72910
|
+
return m ? m.expected_token : null;
|
|
72911
|
+
}
|
|
72779
72912
|
}
|
|
72780
72913
|
});
|
|
72781
72914
|
|
|
@@ -72960,6 +73093,11 @@ var require_tool_registry = __commonJS({
|
|
|
72960
73093
|
lastDerivation = d.derivation;
|
|
72961
73094
|
return d.call;
|
|
72962
73095
|
};
|
|
73096
|
+
const rebindAndRemeasure = async () => {
|
|
73097
|
+
const c = await rebind();
|
|
73098
|
+
casAuth = await (0, fs_default_wire_js_1.measureFsAuthorization)(args);
|
|
73099
|
+
return c;
|
|
73100
|
+
};
|
|
72963
73101
|
const call = await rebind();
|
|
72964
73102
|
const refreshContext = async (c) => (0, freshness_js_1.collectFreshnessCallContext)({
|
|
72965
73103
|
call: {
|
|
@@ -72970,16 +73108,17 @@ var require_tool_registry = __commonJS({
|
|
|
72970
73108
|
resolvePriorContent: guardCfg.resolvePriorContent
|
|
72971
73109
|
});
|
|
72972
73110
|
const fctx = await refreshContext(call);
|
|
73111
|
+
let casAuth = await (0, fs_default_wire_js_1.measureFsAuthorization)(args);
|
|
72973
73112
|
const factory = async (_envelope, redacted, execution) => {
|
|
72974
73113
|
const rawArgs = redacted ? redacted.arguments : args;
|
|
72975
|
-
return (0, fs_default_wire_js_1.wrapWriteWithFsCas)(rawArgs, () => execution ? rawExecute(rawArgs, execution) : rawExecute(rawArgs));
|
|
73114
|
+
return (0, fs_default_wire_js_1.wrapWriteWithFsCas)(rawArgs, () => execution ? rawExecute(rawArgs, execution) : rawExecute(rawArgs), casAuth ? { expected_token: casAuth.expected_token, expected_identity: casAuth.expected_identity } : {});
|
|
72976
73115
|
};
|
|
72977
73116
|
const outcome = (0, auto_recheck_js_1.normalizeAutoRecheck)(guardCfg.autoRecheck) ? await (0, auto_recheck_js_1.runAutoRecheckLoop)({
|
|
72978
73117
|
call,
|
|
72979
73118
|
factory,
|
|
72980
73119
|
config: guardCfg,
|
|
72981
73120
|
callContext: fctx,
|
|
72982
|
-
rebind,
|
|
73121
|
+
rebind: rebindAndRemeasure,
|
|
72983
73122
|
refreshContext
|
|
72984
73123
|
}) : await (0, guard_js_1.guardToolCall)(call, factory, guardCfg, fctx);
|
|
72985
73124
|
return (0, auto_derive_js_1.attachDerivation)(outcome, lastDerivation);
|
|
@@ -75298,9 +75437,10 @@ var require_cjs4 = __commonJS({
|
|
|
75298
75437
|
"use strict";
|
|
75299
75438
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
75300
75439
|
exports2.monitorAttestSigningInput = exports2.kidFromMonitoringAttestation = exports2.tryIssueMonitoringAttestation = exports2.DEFAULT_MONITORING_SINK_TIMEOUT_MS = exports2.ackBytes = exports2.verifyAckHmac = exports2.monitoringDeliveryFailClosed = exports2.formatMonitoringDeliveryLine = exports2.deliverMonitoring = exports2.hashObservedContent = exports2.observeCommit = exports2.deriveKeySignal = exports2.pathClass = exports2.classifyCommand = exports2.projectState = exports2.emptySessionState = exports2.computeTainted = exports2.evaluate = exports2.updateSession = exports2.SESSION_TAINT_VERSION = exports2.SessionTaintTracker = exports2.readDecision = exports2.EXECUTION_TIME_FP_REASONS = exports2.EXECUTION_STATE_UNMEASURABLE_NOTE = exports2.isUnmeasurableExecutionStateReason = exports2.computeCanonicalBundleFingerprint = exports2.authorizedFingerprintFromEnvelope = exports2.checkExecutionTimeFingerprint = exports2.computeBundleFingerprint = exports2.computeArtifactDigest = exports2.evaluateEnvelope = exports2.RECEIPT_PREV_NULL = exports2.decodeReceiptBodyPrev = exports2.previousReceiptCommitment = exports2.verifyReceiptChainLinkage = exports2.canonicalJson = exports2.computeBodyHash = exports2.bindReceiptToEnvelope = exports2.DETECTOR_VERSION = exports2.builtinDetector = exports2.resetPolicyWarnForTests = exports2.warnPolicyAbsentOnce = exports2.observePolicyPresence = exports2.detectPolicyPresence = exports2.policyPresenceOf = exports2.withPolicy = exports2.POLICY_ABSENT_WARN = exports2.POLICY_MARKER = exports2.CODERIFTS_POLICY = exports2.guardToolCall = void 0;
|
|
75301
|
-
exports2.
|
|
75302
|
-
exports2.
|
|
75303
|
-
exports2.
|
|
75440
|
+
exports2.createDbVersionToken = exports2.API_ABSENT_TOKEN = exports2.API_VERSION_TOKEN_PREFIX = exports2.apiTokenRaw = exports2.writeApiIfUnchanged = exports2.createApiVersionToken = exports2.identitiesEqual = exports2.fsObjectIdentity = exports2.UnsafeCasPathError = exports2.assertSafeCasPath = exports2.FS_ABSENT_TOKEN = exports2.FS_VERSION_TOKEN_PREFIX = exports2.fsTokenContentHash = exports2.createFsPriorContentResolver = exports2.writeFileIfUnchanged = exports2.readVersionedFile = exports2.createFsVersionToken = exports2.StaleVersionTokenAbort = exports2.executeIfUnchanged = exports2.RESIDUAL_UNCONDITIONAL_WRITE = exports2.conditionalWriteResidual = exports2.tokensEqual = exports2.buildConditionalWriteBasis = exports2.buildFreshnessBasis = exports2.collectFreshnessCallContext = exports2.artifactIdsForResolve = exports2.isMutatingCall = exports2.isWriteStyleCall = exports2.freshnessAllowsEnforce = exports2.computePathSetTreeHash = exports2.contentByteIdentical = exports2.assessWriteStylePrior = exports2.assessFreshness = exports2.deriveProofBanner = exports2.attachProofToAgentResponse = exports2.renderFinalAnswerProof = exports2.EXECUTION_PROOF_SPEC = exports2.assertEnforcedReceiptInvariant = exports2.hashExecutionResult = exports2.buildExecutionProof = exports2.COVERAGE_ATTEST_ENVELOPE_TAG = exports2.COVERAGE_ATTEST_SIGNING_PREFIX = exports2.COVERAGE_ATTEST_VERSION = exports2.coverageAttestSigningInput = exports2.kidFromCoverageAttestation = exports2.tryIssueCoverageAttestation = exports2.MONITOR_ATTEST_ENVELOPE_TAG = exports2.MONITOR_ATTEST_SIGNING_PREFIX = exports2.MONITOR_ATTEST_VERSION = exports2.receiptDigestOfToken = void 0;
|
|
75441
|
+
exports2.guardedFractionAmongRoutes = exports2.foldTableSettledCalls = exports2.withCodeRifts = exports2.AUTO_DERIVE_READ_TIMEOUT_MS = exports2.AUTO_DERIVE_SOURCE = exports2.defaultFsReader = exports2.normalizeAutoDerive = exports2.runAutoDerive = exports2.AUTO_RECHECK_MAX_CAP = exports2.clampMaxAttempts = exports2.normalizeAutoRecheck = exports2.runAutoRecheckLoop = exports2.coverageReport = exports2.DEPLOY_REPAIRABLE_REASONS = exports2.bindDeploy = exports2.verifyDeployReceiptToken = exports2.DEPLOY_RECEIPT_VIEW_SPEC = exports2.isVerifiedDeployReceiptView = exports2.asVerifiedDeployReceiptView = exports2.deployGate = exports2.gateDecision = exports2.RegistryConstructionError = exports2.guardToolRegistry = exports2.globToRegExp = exports2.matchGlob = exports2.blobMapKey = exports2.classifyByName = exports2.resolveArtifacts = exports2.REMEDIATION_LOOP_ATTESTATION_SPEC = exports2.isCasAttestation = exports2.readPriorBlockRemediation = exports2.readRemediationTransaction = exports2.buildRemediationLoopAttestation = exports2.COMMIT_EVIDENCE_MISSING = exports2.CAS_ATTESTATION_SPEC = exports2.strictCommitObservation = exports2.extractExecutorAttestationToken = exports2.evaluateCasEvidence = exports2.isExecuteIfUnchangedOutcome = exports2.isGuardExecutionProof = exports2.buildCasAttestation = exports2.REGISTRY_ABSENT_TOKEN = exports2.REGISTRY_VERSION_TOKEN_PREFIX = exports2.registryTokenRaw = exports2.writeRegistryIfUnchanged = exports2.createRegistryVersionToken = exports2.DB_ABSENT_TOKEN = exports2.DB_VERSION_TOKEN_PREFIX = exports2.dbTokenRaw = exports2.writeDbIfUnchanged = void 0;
|
|
75442
|
+
exports2.TOOLSET_ATTEST_ENVELOPE_TAG = exports2.TOOLSET_ATTEST_SIGNING_PREFIX = exports2.TOOLSET_ATTEST_VERSION = exports2.surfaceEnvelopeFields = exports2.isGuardOutcome = exports2.executeLangGraphToolCall = exports2.executeGeminiToolCall = exports2.executeAnthropicToolCall = exports2.executeOpenAIToolCall = exports2.executeProtectedTool = exports2.defaultSerializeGeminiToolResult = exports2.bindGeminiGuardOutcome = exports2.protectedToolToFunctionDeclaration = exports2.toGeminiTools = exports2.geminiToolAdapter = exports2.withCodeRiftsGemini = exports2.measureFsAuthorizationToken = exports2.measureFsAuthorization = exports2.wrapWriteWithFsCas = exports2.inferFullFileWriteContent = exports2.inferFsPathFromArgs = exports2.FRESHNESS_RESOLVER_FIX = exports2.freshnessRefusalTeaching = exports2.formatGateRefusalBody = exports2.defaultSerializeLangGraphToolResult = exports2.bindLangGraphGuardOutcome = exports2.LangGraphToolsNotStructuredError = exports2.isLangGraphReactAgentTool = exports2.bindLangGraphTools = exports2.protectedToolToLangGraph = exports2.toLangGraphTools = exports2.langGraphToolAdapter = exports2.withCodeRiftsLangGraph = exports2.defaultSerializeAnthropicToolResult = exports2.bindAnthropicGuardOutcome = exports2.protectedToolToAnthropic = exports2.toAnthropicTools = exports2.anthropicToolAdapter = exports2.withCodeRiftsAnthropic = exports2.defaultSerializeOpenAIToolResult = exports2.bindOpenAIGuardOutcome = exports2.protectedToolToOpenAI = exports2.toOpenAITools = exports2.openAIToolAdapter = exports2.withCodeRiftsOpenAI = exports2.formatCoverageObservedLine = exports2.freezeCoverageObserved = exports2.createCoverageObserver = exports2.readExecutionGrantToken = exports2.isExecutionGrantEnabled = void 0;
|
|
75443
|
+
exports2.kidFromToolsetAttestation = exports2.tryIssueToolsetAttestation = exports2.toolsetAttestSigningInput = exports2.declarationEntriesFromTools = exports2.computeToolsetDigest = exports2.TOOLSET_ATTEST_STATEMENT = void 0;
|
|
75304
75444
|
var guard_js_1 = require_guard();
|
|
75305
75445
|
Object.defineProperty(exports2, "guardToolCall", { enumerable: true, get: function() {
|
|
75306
75446
|
return guard_js_1.guardToolCall;
|
|
@@ -75589,6 +75729,18 @@ var require_cjs4 = __commonJS({
|
|
|
75589
75729
|
Object.defineProperty(exports2, "FS_ABSENT_TOKEN", { enumerable: true, get: function() {
|
|
75590
75730
|
return fs_js_1.FS_ABSENT_TOKEN;
|
|
75591
75731
|
} });
|
|
75732
|
+
Object.defineProperty(exports2, "assertSafeCasPath", { enumerable: true, get: function() {
|
|
75733
|
+
return fs_js_1.assertSafeCasPath;
|
|
75734
|
+
} });
|
|
75735
|
+
Object.defineProperty(exports2, "UnsafeCasPathError", { enumerable: true, get: function() {
|
|
75736
|
+
return fs_js_1.UnsafeCasPathError;
|
|
75737
|
+
} });
|
|
75738
|
+
Object.defineProperty(exports2, "fsObjectIdentity", { enumerable: true, get: function() {
|
|
75739
|
+
return fs_js_1.fsObjectIdentity;
|
|
75740
|
+
} });
|
|
75741
|
+
Object.defineProperty(exports2, "identitiesEqual", { enumerable: true, get: function() {
|
|
75742
|
+
return fs_js_1.identitiesEqual;
|
|
75743
|
+
} });
|
|
75592
75744
|
var api_js_1 = require_api3();
|
|
75593
75745
|
Object.defineProperty(exports2, "createApiVersionToken", { enumerable: true, get: function() {
|
|
75594
75746
|
return api_js_1.createApiVersionToken;
|
|
@@ -75876,6 +76028,12 @@ var require_cjs4 = __commonJS({
|
|
|
75876
76028
|
Object.defineProperty(exports2, "wrapWriteWithFsCas", { enumerable: true, get: function() {
|
|
75877
76029
|
return fs_default_wire_js_1.wrapWriteWithFsCas;
|
|
75878
76030
|
} });
|
|
76031
|
+
Object.defineProperty(exports2, "measureFsAuthorization", { enumerable: true, get: function() {
|
|
76032
|
+
return fs_default_wire_js_1.measureFsAuthorization;
|
|
76033
|
+
} });
|
|
76034
|
+
Object.defineProperty(exports2, "measureFsAuthorizationToken", { enumerable: true, get: function() {
|
|
76035
|
+
return fs_default_wire_js_1.measureFsAuthorizationToken;
|
|
76036
|
+
} });
|
|
75879
76037
|
var gemini_js_1 = require_gemini();
|
|
75880
76038
|
Object.defineProperty(exports2, "withCodeRiftsGemini", { enumerable: true, get: function() {
|
|
75881
76039
|
return gemini_js_1.withCodeRiftsGemini;
|
|
@@ -227325,6 +227483,25 @@ var require_gate_pin = __commonJS({
|
|
|
227325
227483
|
}
|
|
227326
227484
|
});
|
|
227327
227485
|
|
|
227486
|
+
// src/generated/action-pins.json
|
|
227487
|
+
var require_action_pins = __commonJS({
|
|
227488
|
+
"src/generated/action-pins.json"(exports2, module2) {
|
|
227489
|
+
module2.exports = {
|
|
227490
|
+
actions: [
|
|
227491
|
+
{
|
|
227492
|
+
action: "actions/checkout",
|
|
227493
|
+
sha: "11d5960a326750d5838078e36cf38b85af677262",
|
|
227494
|
+
tag: "v4",
|
|
227495
|
+
exact_tag: "v4.4.0",
|
|
227496
|
+
resolved_from: "https://github.com/actions/checkout refs/tags/v4",
|
|
227497
|
+
resolved_at: "2026-08-27T13:27:52Z"
|
|
227498
|
+
}
|
|
227499
|
+
],
|
|
227500
|
+
note: "STRICT template pins these third-party actions to full commit SHAs (only a full SHA is immutable). The DEFAULT template deliberately stays on moving tags. A SHA pin does not receive upstream security fixes until someone bumps it \u2014 Dependabot raises that PR, and a pin nobody bumps is worse than a tag because it rots silently. Re-run scripts/generate-action-pins.js."
|
|
227501
|
+
};
|
|
227502
|
+
}
|
|
227503
|
+
});
|
|
227504
|
+
|
|
227328
227505
|
// src/contract-gate-workflow.js
|
|
227329
227506
|
var require_contract_gate_workflow = __commonJS({
|
|
227330
227507
|
"src/contract-gate-workflow.js"(exports2, module2) {
|
|
@@ -227334,6 +227511,17 @@ var require_contract_gate_workflow = __commonJS({
|
|
|
227334
227511
|
var WORKFLOW_REL = ".github/workflows/coderifts.yml";
|
|
227335
227512
|
var GATE_ACTION = "coderifts/contract-gate@v0";
|
|
227336
227513
|
var GATE_PIN = require_gate_pin();
|
|
227514
|
+
var ACTION_PINS = require_action_pins();
|
|
227515
|
+
function pinnedActionRef(action) {
|
|
227516
|
+
const entry = (ACTION_PINS.actions || []).find((a) => a && a.action === action);
|
|
227517
|
+
if (!entry || !/^[0-9a-f]{40}$/.test(String(entry.sha || ""))) {
|
|
227518
|
+
throw new Error(
|
|
227519
|
+
`contract-gate-workflow: no usable SHA pin for ${action} in src/generated/action-pins.json \u2014 run scripts/generate-action-pins.js. Refusing to emit an unpinned STRICT workflow.`
|
|
227520
|
+
);
|
|
227521
|
+
}
|
|
227522
|
+
return `${action}@${entry.sha} # ${entry.exact_tag || entry.tag}`;
|
|
227523
|
+
}
|
|
227524
|
+
var CHECKOUT_STRICT = pinnedActionRef("actions/checkout");
|
|
227337
227525
|
if (typeof GATE_PIN.sha !== "string" || !/^[0-9a-f]{40}$/.test(GATE_PIN.sha)) {
|
|
227338
227526
|
throw new Error(
|
|
227339
227527
|
"contract-gate-workflow: generated/gate-pin.json carries no valid 40-hex sha \u2014 re-run scripts/generate-gate-pin.js. Refusing to emit an unpinned STRICT workflow."
|
|
@@ -227368,6 +227556,10 @@ jobs:
|
|
|
227368
227556
|
contract-gate:
|
|
227369
227557
|
runs-on: ubuntu-latest
|
|
227370
227558
|
steps:
|
|
227559
|
+
# actions/checkout stays on the MOVING TAG @v4 here, deliberately \u2014 the same trade this
|
|
227560
|
+
# template makes for the gate itself. You get upstream fixes without editing this file, and
|
|
227561
|
+
# you accept that the bytes can change under you. \`coderifts init --agents --strict\` pins a
|
|
227562
|
+
# full commit SHA for both. Do not "fix" this to a SHA and do not "fix" strict back to a tag.
|
|
227371
227563
|
- uses: actions/checkout@v4
|
|
227372
227564
|
with:
|
|
227373
227565
|
# REQUIRED: the gate derives the change set from git diff base...head.
|
|
@@ -227424,7 +227616,14 @@ jobs:
|
|
|
227424
227616
|
contract-gate:
|
|
227425
227617
|
runs-on: ubuntu-latest
|
|
227426
227618
|
steps:
|
|
227427
|
-
|
|
227619
|
+
# PINNED, like the gate below it. \`@v4\` is a tag GitHub moves on every release of the
|
|
227620
|
+
# action, so it is not a pin \u2014 and checkout runs FIRST, fetching the code every later step
|
|
227621
|
+
# reads. A strict chain whose first step can change under it is not strict.
|
|
227622
|
+
# MAINTENANCE, stated because a pin has a cost: a SHA-pinned action receives no upstream
|
|
227623
|
+
# fixes, security included, until someone bumps it. Dependabot understands this form and
|
|
227624
|
+
# raises that PR. WITHOUT Dependabot the obligation is yours, and a pin nobody bumps is worse
|
|
227625
|
+
# than a tag, because a tag rots visibly and a pin rots silently.
|
|
227626
|
+
- uses: ${CHECKOUT_STRICT}
|
|
227428
227627
|
with:
|
|
227429
227628
|
# REQUIRED: the gate derives the change set from git diff base...head.
|
|
227430
227629
|
fetch-depth: 0
|
|
@@ -227508,6 +227707,9 @@ jobs:
|
|
|
227508
227707
|
GATE_ACTION,
|
|
227509
227708
|
GATE_ACTION_STRICT,
|
|
227510
227709
|
GATE_PIN,
|
|
227710
|
+
ACTION_PINS,
|
|
227711
|
+
CHECKOUT_STRICT,
|
|
227712
|
+
pinnedActionRef,
|
|
227511
227713
|
ENFORCEMENT_DOC,
|
|
227512
227714
|
writeContractGateWorkflow,
|
|
227513
227715
|
workflowPresent
|
|
@@ -227564,7 +227766,8 @@ var require_init_agents = __commonJS({
|
|
|
227564
227766
|
var EXTRA_RULES_ON_ALL = Object.freeze([
|
|
227565
227767
|
".github/copilot-instructions.md",
|
|
227566
227768
|
"coderifts-langgraph-policy.js",
|
|
227567
|
-
"openai-agent-instructions.md"
|
|
227769
|
+
"openai-agent-instructions.md",
|
|
227770
|
+
"skills/api-governance/SKILL.md"
|
|
227568
227771
|
]);
|
|
227569
227772
|
var NEXT_MANUAL_STEP_LINES = Object.freeze([
|
|
227570
227773
|
" Next manual step",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coderifts",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2",
|
|
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",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"test": "node --test test/*.test.js"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@coderifts/agent-guard": "^
|
|
48
|
+
"@coderifts/agent-guard": "^13.0.0",
|
|
49
49
|
"chalk": "^4.1.2",
|
|
50
50
|
"cli-table3": "^0.6.4",
|
|
51
51
|
"commander": "^12.0.0",
|
|
@@ -45,13 +45,33 @@
|
|
|
45
45
|
* raise, and no product code. The floor rises anyway, because a semantics floor is about
|
|
46
46
|
* what the CLI may RUN against: a guard that silently skips the atomicity demand on an ordinary
|
|
47
47
|
* edit is exactly the class of difference this gate exists to refuse.)
|
|
48
|
+
* 6.0.0: floor raised to 13 (the CAS now conditions on the AUTHORIZATION-TIME token. Through 12.0.0
|
|
49
|
+
* wrapWriteWithFsCas measured its expected token INSIDE executeFactory — after preflight and after
|
|
50
|
+
* the T2 recheck — and conditioned the write on that self-fetched value, which asks whether the
|
|
51
|
+
* state changed since a read a microsecond earlier. Measured on 12.0.0: a writer landing in that
|
|
52
|
+
* window had its state adopted as the legitimate starting point and the CAS still returned
|
|
53
|
+
* committed with enforced:true, clobbering it. 13.0.0 threads the T1 token, and adds three FS
|
|
54
|
+
* defences that were measured ABSENT rather than assumed: `..` refused before resolution, a
|
|
55
|
+
* symlinked final component refused (stat/readFile measured the TARGET while rename replaced the
|
|
56
|
+
* LINK — check and write named different objects), the token read through one file descriptor,
|
|
57
|
+
* and dev+ino recorded in the evidence. COST MEASURED AS ZERO, and measured more carefully than
|
|
58
|
+
* the last two raises: the CLI imports only deployGate, asVerifiedDeployReceiptView,
|
|
59
|
+
* DEPLOY_RECEIPT_VIEW_SPEC and matchGlob, whose implementing modules (deploy-gate.js,
|
|
60
|
+
* resolver-glob.js, deploy-receipt-token.js, merge-gate.js) are BYTE-IDENTICAL 12.0.0 -> 13.0.0.
|
|
61
|
+
* Note the honest qualifier the earlier raises did not state: requiring the barrel index.js LOADS
|
|
62
|
+
* every changed module, so the changed code is in the process — it is simply not on the code path
|
|
63
|
+
* of any symbol the CLI calls, and the four symbols return identical values under both versions.
|
|
64
|
+
* Suite staged against 13.0.0 returned an identical 539/518/21 with a byte-identical 28-item
|
|
65
|
+
* failure set. The floor rises anyway, because a semantics floor is about what the CLI may RUN
|
|
66
|
+
* against: a CAS that reports committed after adopting another writer's state is exactly the
|
|
67
|
+
* class this gate exists to refuse.)
|
|
48
68
|
*/
|
|
49
69
|
|
|
50
70
|
const fs = require('fs');
|
|
51
71
|
const path = require('path');
|
|
52
72
|
|
|
53
73
|
/** Minimum acceptable major for @coderifts/agent-guard in THIS package (the CLI). */
|
|
54
|
-
const MIN_GUARD_MAJOR =
|
|
74
|
+
const MIN_GUARD_MAJOR = 13;
|
|
55
75
|
const DEP = '@coderifts/agent-guard';
|
|
56
76
|
|
|
57
77
|
/**
|