coderifts 6.0.0 → 6.0.1

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
@@ -1,8 +1,26 @@
1
1
  # Changelog
2
2
 
3
- ## 6.0.0
3
+ ## 6.0.1
4
4
 
5
- _Nothing yet._
5
+ ### Changed
6
+ - **Guard floor raised to 13, declared range `^13.0.0`.** ADOPTER-FACING: the guard is a direct
7
+ dependency with no `peerDependencies` and no bundled copy, so this range *is* what a fresh install
8
+ resolves. `coderifts@5.0.1` declared `^12.0.0`, which resolves to 12.0.0 — the version in which
9
+ `wrapWriteWithFsCas` measured its expected CAS token INSIDE `executeFactory`, after preflight and
10
+ after the T2 recheck, and conditioned the write on that self-fetched value. Measured on 12.0.0: a
11
+ writer landing in that window had its state adopted as the legitimate starting point and the CAS
12
+ still returned `committed` with `enforced: true`, clobbering it. 13.0.0 threads the
13
+ authorization-time token, and adds three filesystem defences that were measured absent rather than
14
+ assumed — `..` refused before resolution, a symlinked final component refused (`stat`/`readFile`
15
+ measured the link's TARGET while `rename` replaced the LINK, so check and write named different
16
+ objects), the token read through a single file descriptor, and `dev`+`ino` recorded in the write
17
+ evidence.
18
+
19
+ **Cost measured as zero**, the same way the 11-, 12- and 13-raises were: the CLI imports only
20
+ `deployGate`, `asVerifiedDeployReceiptView`, `DEPLOY_RECEIPT_VIEW_SPEC` and `matchGlob`, whose
21
+ implementing modules are byte-identical 12.0.0 → 13.0.0, and all four return identical values
22
+ under both. Suite staged against 13.0.0 returned an identical 539/518/21 with a byte-identical
23
+ 28-item failure set. Nothing in the CLI calls the CAS or FS adapters.
6
24
 
7
25
  ## 5.0.1
8
26
 
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.0",
3031
+ version: "6.0.1",
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": "^12.0.0",
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 st;
67425
+ let fh;
67359
67426
  try {
67360
- st = await node_fs_1.promises.stat(filePath);
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
- if (!st.isFile()) {
67368
- throw new Error(`createFsVersionToken: not a regular file: ${filePath}`);
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 = path.resolve(args.path);
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 { path: target, bytes: body.length, written_content_hash: writtenHash };
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
- if (filePath && content != null) {
72762
- let expected;
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.DB_ABSENT_TOKEN = exports2.DB_VERSION_TOKEN_PREFIX = exports2.dbTokenRaw = exports2.writeDbIfUnchanged = exports2.createDbVersionToken = exports2.API_ABSENT_TOKEN = exports2.API_VERSION_TOKEN_PREFIX = exports2.apiTokenRaw = exports2.writeApiIfUnchanged = exports2.createApiVersionToken = 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;
75302
- exports2.freezeCoverageObserved = exports2.createCoverageObserver = exports2.readExecutionGrantToken = exports2.isExecutionGrantEnabled = 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 = void 0;
75303
- exports2.kidFromToolsetAttestation = exports2.tryIssueToolsetAttestation = exports2.toolsetAttestSigningInput = exports2.declarationEntriesFromTools = exports2.computeToolsetDigest = exports2.TOOLSET_ATTEST_STATEMENT = 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.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 = void 0;
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coderifts",
3
- "version": "6.0.0",
3
+ "version": "6.0.1",
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": "^12.0.0",
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 = 12;
74
+ const MIN_GUARD_MAJOR = 13;
55
75
  const DEP = '@coderifts/agent-guard';
56
76
 
57
77
  /**