coderifts 7.0.0 → 8.0.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/CHANGELOG.md +18 -0
- package/README.md +34 -4
- package/dist/cli.js +1070 -167
- package/package.json +2 -2
- package/scripts/assert-guard-major.js +6 -1
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: "
|
|
3031
|
+
version: "8.0.0",
|
|
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",
|
|
@@ -3074,7 +3074,7 @@ var require_package = __commonJS({
|
|
|
3074
3074
|
test: "node --test test/*.test.js"
|
|
3075
3075
|
},
|
|
3076
3076
|
dependencies: {
|
|
3077
|
-
"@coderifts/agent-guard": "^
|
|
3077
|
+
"@coderifts/agent-guard": "^15.0.0",
|
|
3078
3078
|
chalk: "^4.1.2",
|
|
3079
3079
|
"cli-table3": "^0.6.4",
|
|
3080
3080
|
commander: "^12.0.0",
|
|
@@ -70000,7 +70000,7 @@ var require_policy2 = __commonJS({
|
|
|
70000
70000
|
exports2.observePolicyPresence = observePolicyPresence;
|
|
70001
70001
|
exports2.resetPolicyWarnForTests = resetPolicyWarnForTests;
|
|
70002
70002
|
exports2.POLICY_MARKER = "A receipt authorizes ONE operation: a merge receipt does not authorize a deploy.";
|
|
70003
|
-
exports2.CODERIFTS_POLICY = 'Call `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call
|
|
70003
|
+
exports2.CODERIFTS_POLICY = 'Call `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".';
|
|
70004
70004
|
exports2.POLICY_ABSENT_WARN = "CodeRifts policy text not detected in the system prompt. The agent will still see the tools, but measured evidence shows operation-scope misuse is markedly more likely without it. See https://github.com/coderifts/agent-guard#policy-delivery.";
|
|
70005
70005
|
function textHasMarker(text) {
|
|
70006
70006
|
return text.includes(exports2.POLICY_MARKER);
|
|
@@ -70079,16 +70079,167 @@ var require_policy2 = __commonJS({
|
|
|
70079
70079
|
}
|
|
70080
70080
|
});
|
|
70081
70081
|
|
|
70082
|
+
// node_modules/@coderifts/agent-guard/dist/cjs/deny-remedy.js
|
|
70083
|
+
var require_deny_remedy = __commonJS({
|
|
70084
|
+
"node_modules/@coderifts/agent-guard/dist/cjs/deny-remedy.js"(exports2) {
|
|
70085
|
+
"use strict";
|
|
70086
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
70087
|
+
exports2.ARGS_SHAPE = exports2.DOES_NOT_PROMISE = exports2.DENY_ERROR = void 0;
|
|
70088
|
+
exports2.buildDenyRemedy = buildDenyRemedy;
|
|
70089
|
+
exports2.denyErrorForReason = denyErrorForReason;
|
|
70090
|
+
exports2.DENY_ERROR = Object.freeze({
|
|
70091
|
+
GRANT_REQUIRED: "CODERIFTS_GRANT_REQUIRED",
|
|
70092
|
+
GRANT_INVALID: "CODERIFTS_GRANT_INVALID",
|
|
70093
|
+
GRANT_MISMATCH: "CODERIFTS_GRANT_MISMATCH"
|
|
70094
|
+
});
|
|
70095
|
+
exports2.DOES_NOT_PROMISE = "a grant does not guarantee execution (CAS may still fail)";
|
|
70096
|
+
exports2.ARGS_SHAPE = Object.freeze({
|
|
70097
|
+
artifacts: "Array<{ id, type, before, after }> \u2014 the change set being authorized",
|
|
70098
|
+
context: "{ operation, environment?, repository?, branch?, pull_request? } \u2014 operation is required for authorize"
|
|
70099
|
+
});
|
|
70100
|
+
var FINGERPRINT_RE = /^sha256:[0-9a-f]{64}$/;
|
|
70101
|
+
function buildDenyRemedy({ error, target = null, fingerprint = null, observed = null }) {
|
|
70102
|
+
if (!error || !Object.values(exports2.DENY_ERROR).includes(error))
|
|
70103
|
+
return null;
|
|
70104
|
+
const remedy = {
|
|
70105
|
+
error,
|
|
70106
|
+
// Null, never a wildcard: a surface that cannot name what it refused must
|
|
70107
|
+
// not emit a value a reader could take for "everything".
|
|
70108
|
+
target: typeof target === "string" && target.length > 0 ? target : null,
|
|
70109
|
+
// Only a well-formed fingerprint. A malformed one is dropped rather than
|
|
70110
|
+
// passed through, because a caller comparing it would get a false mismatch.
|
|
70111
|
+
fingerprint: typeof fingerprint === "string" && FINGERPRINT_RE.test(fingerprint) ? fingerprint : null,
|
|
70112
|
+
action_required: {
|
|
70113
|
+
tool: "preflight_change_set",
|
|
70114
|
+
mode: "authorize",
|
|
70115
|
+
args_shape: { ...exports2.ARGS_SHAPE }
|
|
70116
|
+
},
|
|
70117
|
+
does_not_promise: exports2.DOES_NOT_PROMISE
|
|
70118
|
+
};
|
|
70119
|
+
if (observed && typeof observed === "object")
|
|
70120
|
+
remedy.observed = observed;
|
|
70121
|
+
return remedy;
|
|
70122
|
+
}
|
|
70123
|
+
function denyErrorForReason(reason) {
|
|
70124
|
+
switch (String(reason || "").toLowerCase()) {
|
|
70125
|
+
// Nothing was presented.
|
|
70126
|
+
case "receipt_missing":
|
|
70127
|
+
case "missing_receipt":
|
|
70128
|
+
case "missing_grant_header":
|
|
70129
|
+
case "decision_missing":
|
|
70130
|
+
case "missing_decision_result":
|
|
70131
|
+
case "no_preflight_response":
|
|
70132
|
+
case "grant_not_supplied":
|
|
70133
|
+
return exports2.DENY_ERROR.GRANT_REQUIRED;
|
|
70134
|
+
// Something was presented and did not hold up.
|
|
70135
|
+
case "receipt_invalid":
|
|
70136
|
+
case "receipt_unverified":
|
|
70137
|
+
case "invalid_signature":
|
|
70138
|
+
case "unknown_key":
|
|
70139
|
+
case "unknown_kid":
|
|
70140
|
+
case "dsse_malformed":
|
|
70141
|
+
case "dsse_unsupported":
|
|
70142
|
+
case "dsse_predicate_mismatch":
|
|
70143
|
+
case "malformed":
|
|
70144
|
+
case "grant_malformed":
|
|
70145
|
+
case "grant_unverified":
|
|
70146
|
+
case "grant_expired":
|
|
70147
|
+
return exports2.DENY_ERROR.GRANT_INVALID;
|
|
70148
|
+
// It held up, but it is not about this request.
|
|
70149
|
+
case "scope_mismatch":
|
|
70150
|
+
case "target_mismatch":
|
|
70151
|
+
case "operation_mismatch":
|
|
70152
|
+
case "grant_scope_mismatch":
|
|
70153
|
+
case "mode_mismatch":
|
|
70154
|
+
case "repo_mismatch":
|
|
70155
|
+
case "base_mismatch":
|
|
70156
|
+
case "head_mismatch":
|
|
70157
|
+
case "grant_does_not_cover_path":
|
|
70158
|
+
case "grant_bound_elsewhere":
|
|
70159
|
+
case "receipt_envelope_mismatch":
|
|
70160
|
+
case "artifact_mismatch":
|
|
70161
|
+
case "grant_unbound":
|
|
70162
|
+
case "grant_wrong_audience":
|
|
70163
|
+
return exports2.DENY_ERROR.GRANT_MISMATCH;
|
|
70164
|
+
default:
|
|
70165
|
+
return null;
|
|
70166
|
+
}
|
|
70167
|
+
}
|
|
70168
|
+
}
|
|
70169
|
+
});
|
|
70170
|
+
|
|
70082
70171
|
// node_modules/@coderifts/agent-guard/dist/cjs/execution-grant.js
|
|
70083
70172
|
var require_execution_grant2 = __commonJS({
|
|
70084
70173
|
"node_modules/@coderifts/agent-guard/dist/cjs/execution-grant.js"(exports2) {
|
|
70085
70174
|
"use strict";
|
|
70086
70175
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
70176
|
+
exports2.V2_WIRE_FIELDS = exports2.V2_FIELD_KEYS = void 0;
|
|
70177
|
+
exports2.resolveV2Fields = resolveV2Fields;
|
|
70178
|
+
exports2.v2WireFields = v2WireFields;
|
|
70087
70179
|
exports2.isExecutionGrantEnabled = isExecutionGrantEnabled;
|
|
70088
70180
|
exports2.readExecutionGrantToken = readExecutionGrantToken;
|
|
70089
70181
|
exports2.firstArtifactId = firstArtifactId;
|
|
70090
70182
|
exports2.isSignerUnavailableError = isSignerUnavailableError;
|
|
70091
70183
|
exports2.resolveStateNonceForCall = resolveStateNonceForCall;
|
|
70184
|
+
exports2.V2_FIELD_KEYS = Object.freeze([
|
|
70185
|
+
"executorId",
|
|
70186
|
+
"adapterId",
|
|
70187
|
+
"targetUri",
|
|
70188
|
+
"tenantId",
|
|
70189
|
+
"policyHash",
|
|
70190
|
+
"audienceHash"
|
|
70191
|
+
]);
|
|
70192
|
+
function resolveV2Fields(input) {
|
|
70193
|
+
const top = input || {};
|
|
70194
|
+
const nested = input && input.executionGrant || {};
|
|
70195
|
+
const out = {};
|
|
70196
|
+
const conflicts = [];
|
|
70197
|
+
for (const key of exports2.V2_FIELD_KEYS) {
|
|
70198
|
+
const t = typeof top[key] === "string" && top[key].length > 0 ? top[key] : void 0;
|
|
70199
|
+
const n = typeof nested[key] === "string" && nested[key].length > 0 ? nested[key] : void 0;
|
|
70200
|
+
if (t !== void 0 && n !== void 0 && t !== n) {
|
|
70201
|
+
conflicts.push(` ${key}: top-level ${JSON.stringify(t)} vs executionGrant.${key} ${JSON.stringify(n)}`);
|
|
70202
|
+
continue;
|
|
70203
|
+
}
|
|
70204
|
+
const v = t !== void 0 ? t : n;
|
|
70205
|
+
if (v !== void 0)
|
|
70206
|
+
out[key] = v;
|
|
70207
|
+
}
|
|
70208
|
+
if (conflicts.length > 0) {
|
|
70209
|
+
const err = new Error(`withCodeRifts: the V2 identity fields are configured in two places and they disagree.
|
|
70210
|
+
${conflicts.join("\n")}
|
|
70211
|
+
|
|
70212
|
+
These feed DIFFERENT halves of the system \u2014 the top level binds the ATOMIC construction check and the posture receipt, the executionGrant copy goes on the authorize request \u2014 so a disagreement builds a grant against one identity and verifies against another. Set each field ONCE, at the top level; the executionGrant spelling is a deprecated alias.`);
|
|
70213
|
+
err.code = "V2_FIELDS_CONFLICT";
|
|
70214
|
+
throw err;
|
|
70215
|
+
}
|
|
70216
|
+
return out;
|
|
70217
|
+
}
|
|
70218
|
+
exports2.V2_WIRE_FIELDS = Object.freeze([
|
|
70219
|
+
["executor_id", "executorId"],
|
|
70220
|
+
["adapter_id", "adapterId"],
|
|
70221
|
+
["target_uri", "targetUri"],
|
|
70222
|
+
["tenant_id", "tenantId"],
|
|
70223
|
+
["policy_hash", "policyHash"],
|
|
70224
|
+
["audience_hash", "audienceHash"]
|
|
70225
|
+
]);
|
|
70226
|
+
function v2WireFields(config) {
|
|
70227
|
+
const g = config && config.executionGrant;
|
|
70228
|
+
const fields = {};
|
|
70229
|
+
const absent = [];
|
|
70230
|
+
if (!g || g.grantVersion !== "v2") {
|
|
70231
|
+
return { fields, absent: exports2.V2_WIRE_FIELDS.map(([wire]) => wire) };
|
|
70232
|
+
}
|
|
70233
|
+
const resolved = resolveV2Fields(config);
|
|
70234
|
+
for (const [wire, key] of exports2.V2_WIRE_FIELDS) {
|
|
70235
|
+
const v = resolved[key];
|
|
70236
|
+
if (typeof v === "string" && v.length > 0)
|
|
70237
|
+
fields[wire] = v;
|
|
70238
|
+
else
|
|
70239
|
+
absent.push(wire);
|
|
70240
|
+
}
|
|
70241
|
+
return { fields, absent };
|
|
70242
|
+
}
|
|
70092
70243
|
function isExecutionGrantEnabled(config) {
|
|
70093
70244
|
return !!(config && config.executionGrant && config.executionGrant.enabled === true);
|
|
70094
70245
|
}
|
|
@@ -70163,6 +70314,7 @@ var require_guard = __commonJS({
|
|
|
70163
70314
|
var monitoring_delivery_js_1 = require_monitoring_delivery();
|
|
70164
70315
|
var monitoring_attestation_js_1 = require_monitoring_attestation2();
|
|
70165
70316
|
var policy_js_1 = require_policy2();
|
|
70317
|
+
var deny_remedy_js_1 = require_deny_remedy();
|
|
70166
70318
|
var execution_grant_js_1 = require_execution_grant2();
|
|
70167
70319
|
var breakers = /* @__PURE__ */ new WeakMap();
|
|
70168
70320
|
var nowMs = () => Date.now();
|
|
@@ -70333,7 +70485,7 @@ var require_guard = __commonJS({
|
|
|
70333
70485
|
function coverageOutcomeFieldsFrom(s) {
|
|
70334
70486
|
return s.coverageObserved ? { coverage_observed: s.coverageObserved } : {};
|
|
70335
70487
|
}
|
|
70336
|
-
function blocked(config, verdict, preflighted, freshness, conditional_write, monitoring_delivery, monitoring_attestation, grantObs) {
|
|
70488
|
+
function blocked(config, verdict, preflighted, freshness, conditional_write, monitoring_delivery, monitoring_attestation, grantObs, call) {
|
|
70337
70489
|
const commit_observation = {
|
|
70338
70490
|
status: "not_observed",
|
|
70339
70491
|
observed_at: iso(),
|
|
@@ -70341,6 +70493,14 @@ var require_guard = __commonJS({
|
|
|
70341
70493
|
};
|
|
70342
70494
|
const base = { executionAttempted: false, executed: false, enforced: false, verdict, preflighted };
|
|
70343
70495
|
const cov = coverageSnap(config);
|
|
70496
|
+
const cause = "cause" in verdict ? verdict.cause : null;
|
|
70497
|
+
const remedy = call ? (0, deny_remedy_js_1.buildDenyRemedy)({
|
|
70498
|
+
error: (0, deny_remedy_js_1.denyErrorForReason)(cause),
|
|
70499
|
+
target: call.toolName || null,
|
|
70500
|
+
// The guard's own input fingerprint, already sha256:<hex>.
|
|
70501
|
+
fingerprint: fingerprint(call),
|
|
70502
|
+
observed: { cause, resolution: "resolution" in verdict ? verdict.resolution : null }
|
|
70503
|
+
}) : null;
|
|
70344
70504
|
const out = {
|
|
70345
70505
|
...base,
|
|
70346
70506
|
proof: (0, execution_proof_js_1.buildExecutionProof)({
|
|
@@ -70357,7 +70517,8 @@ var require_guard = __commonJS({
|
|
|
70357
70517
|
...monitoring_delivery ? { monitoring_delivery } : {},
|
|
70358
70518
|
...monitoring_attestation ? { monitoring_attestation } : {},
|
|
70359
70519
|
...coverageOutcomeFieldsFrom(cov),
|
|
70360
|
-
...grantObs ? { execution_grant: grantObs } : {}
|
|
70520
|
+
...grantObs ? { execution_grant: grantObs } : {},
|
|
70521
|
+
...remedy ? { remedy } : {}
|
|
70361
70522
|
};
|
|
70362
70523
|
return attachPolicyPresence(out, config);
|
|
70363
70524
|
}
|
|
@@ -70565,7 +70726,7 @@ var require_guard = __commonJS({
|
|
|
70565
70726
|
const v = unavailableVerdict({ cause: "MISSING_ARTIFACT_CONTENT", failPolicy, resolution: "CLOSED", action: "STOP" }, count);
|
|
70566
70727
|
const { basis } = freshnessFor(config, redacted, fctx, detection.artifacts);
|
|
70567
70728
|
const { basis: cw } = conditionalWriteFor(config, redacted, cwctx, detection.artifacts);
|
|
70568
|
-
return blocked(config, v, false, basis, cw);
|
|
70729
|
+
return blocked(config, v, false, basis, cw, void 0, void 0, void 0, redacted);
|
|
70569
70730
|
}
|
|
70570
70731
|
if (failPolicy === "lkg" && !config.lkg) {
|
|
70571
70732
|
breakerRecord(config);
|
|
@@ -70589,6 +70750,20 @@ var require_guard = __commonJS({
|
|
|
70589
70750
|
request.include_execution_grant = true;
|
|
70590
70751
|
if (nonceRes.nonce)
|
|
70591
70752
|
request.state_nonce = nonceRes.nonce;
|
|
70753
|
+
const wire = (0, execution_grant_js_1.v2WireFields)(config);
|
|
70754
|
+
if (config.executionGrant?.grantVersion === "v2") {
|
|
70755
|
+
request.grant_version = "v2";
|
|
70756
|
+
for (const [k, v] of Object.entries(wire.fields))
|
|
70757
|
+
request[k] = v;
|
|
70758
|
+
}
|
|
70759
|
+
if (config.executionGrant?.grantVersion === "v2") {
|
|
70760
|
+
grantObs = {
|
|
70761
|
+
...grantObs,
|
|
70762
|
+
grant_version: "v2",
|
|
70763
|
+
v2_fields_sent: Object.keys(wire.fields),
|
|
70764
|
+
v2_fields_absent: wire.absent
|
|
70765
|
+
};
|
|
70766
|
+
}
|
|
70592
70767
|
}
|
|
70593
70768
|
const cap = config.maxPayloadBytes ?? 1e6;
|
|
70594
70769
|
if (Buffer.byteLength(JSON.stringify(request), "utf8") > cap) {
|
|
@@ -70605,14 +70780,14 @@ var require_guard = __commonJS({
|
|
|
70605
70780
|
if (pf.integrity) {
|
|
70606
70781
|
emit(config, { type: "breaker_tripped", at: iso(), cause: pf.cause });
|
|
70607
70782
|
const v2 = unavailableVerdict({ cause: pf.cause, failPolicy, resolution: "CLOSED", action: "STOP" }, count);
|
|
70608
|
-
return blocked(config, v2, false, basis, cw, void 0, void 0, grantObs);
|
|
70783
|
+
return blocked(config, v2, false, basis, cw, void 0, void 0, grantObs, redacted);
|
|
70609
70784
|
}
|
|
70610
70785
|
const availCause = pf.cause;
|
|
70611
70786
|
if (grantObs && grantObs.requested) {
|
|
70612
70787
|
if (breakerTripped(config))
|
|
70613
70788
|
emit(config, { type: "breaker_tripped", at: iso(), cause: availCause });
|
|
70614
70789
|
const v2 = unavailableVerdict({ cause: availCause, failPolicy, resolution: "CLOSED", action: "STOP" }, count);
|
|
70615
|
-
return blocked(config, v2, false, basis, cw, void 0, void 0, grantObs);
|
|
70790
|
+
return blocked(config, v2, false, basis, cw, void 0, void 0, grantObs, redacted);
|
|
70616
70791
|
}
|
|
70617
70792
|
if (failPolicy === "open" && !breakerTripped(config)) {
|
|
70618
70793
|
emit(config, { type: "preflight_unavailable", at: iso(), cause: availCause, action: "CONTINUE" });
|
|
@@ -70630,7 +70805,7 @@ var require_guard = __commonJS({
|
|
|
70630
70805
|
if (breakerTripped(config))
|
|
70631
70806
|
emit(config, { type: "breaker_tripped", at: iso(), cause: availCause });
|
|
70632
70807
|
const v = unavailableVerdict({ cause: availCause, failPolicy, resolution: "CLOSED", action: "STOP" }, count);
|
|
70633
|
-
return blocked(config, v, false, basis, cw, void 0, void 0, grantObs);
|
|
70808
|
+
return blocked(config, v, false, basis, cw, void 0, void 0, grantObs, redacted);
|
|
70634
70809
|
}
|
|
70635
70810
|
const rd = (0, read_decision_js_1.readDecision)(pf.response);
|
|
70636
70811
|
if (rd.reason === "EXECUTION_ACTION_UNRECOGNISED") {
|
|
@@ -70670,7 +70845,7 @@ var require_guard = __commonJS({
|
|
|
70670
70845
|
if (gate.verdict === "block-strict") {
|
|
70671
70846
|
const { basis } = freshnessFor(config, redacted, fctx, detection.artifacts);
|
|
70672
70847
|
const { basis: cw } = conditionalWriteFor(config, redacted, cwctx, detection.artifacts);
|
|
70673
|
-
return gate.decision === "BLOCK" ? blocked(config, { kind: "BLOCK", action: "STOP", envelope, receiptVerified }, true, basis, cw, void 0, void 0, grantObs) : blocked(config, { kind: "APPROVAL", action: "REQUEST_APPROVAL", envelope, receiptVerified }, true, basis, cw, void 0, void 0, grantObs);
|
|
70848
|
+
return gate.decision === "BLOCK" ? blocked(config, { kind: "BLOCK", action: "STOP", envelope, receiptVerified }, true, basis, cw, void 0, void 0, grantObs, redacted) : blocked(config, { kind: "APPROVAL", action: "REQUEST_APPROVAL", envelope, receiptVerified }, true, basis, cw, void 0, void 0, grantObs, redacted);
|
|
70674
70849
|
}
|
|
70675
70850
|
const kind = gate.kind;
|
|
70676
70851
|
if (grantObs && grantObs.requested) {
|
|
@@ -70816,7 +70991,7 @@ var require_guard = __commonJS({
|
|
|
70816
70991
|
const v = unavailableVerdict({ cause, failPolicy, resolution: "CLOSED", action: "STOP" }, count);
|
|
70817
70992
|
const { basis } = freshnessFor(config, redacted, fctx, arts);
|
|
70818
70993
|
const { basis: cw } = conditionalWriteFor(config, redacted, cwctx, arts);
|
|
70819
|
-
return blocked(config, v, false, basis, cw, monitoring_delivery, monitoring_attestation, grantObs);
|
|
70994
|
+
return blocked(config, v, false, basis, cw, monitoring_delivery, monitoring_attestation, grantObs, redacted);
|
|
70820
70995
|
}
|
|
70821
70996
|
function isExpired(envelope) {
|
|
70822
70997
|
const exp = envelope.expires_at;
|
|
@@ -73427,6 +73602,31 @@ var require_deploy_receipt_token = __commonJS({
|
|
|
73427
73602
|
}
|
|
73428
73603
|
return v1;
|
|
73429
73604
|
}
|
|
73605
|
+
function deriveKeyWithdrawalStatus(ts, keyMeta) {
|
|
73606
|
+
const KNOWN_STATUSES = ["active", "retired", "revoked", null];
|
|
73607
|
+
if (!KNOWN_STATUSES.includes(keyMeta.status))
|
|
73608
|
+
return "UNKNOWN_KEY_STATUS";
|
|
73609
|
+
if (typeof keyMeta.revoked_at === "string" && keyMeta.revoked_at.length > 0)
|
|
73610
|
+
return "KEY_REVOKED";
|
|
73611
|
+
if (typeof keyMeta.retired_at === "string" && keyMeta.retired_at.length > 0 && ts) {
|
|
73612
|
+
const issued = Date.parse(ts);
|
|
73613
|
+
const retired = Date.parse(keyMeta.retired_at);
|
|
73614
|
+
if (Number.isFinite(issued) && Number.isFinite(retired) && issued >= retired) {
|
|
73615
|
+
return "KEY_RETIRED_AFTER_SIGNING";
|
|
73616
|
+
}
|
|
73617
|
+
}
|
|
73618
|
+
if (keyMeta.status === "revoked") {
|
|
73619
|
+
const at = keyMeta.compromised_at;
|
|
73620
|
+
if (typeof at !== "string" || at.length === 0)
|
|
73621
|
+
return "REVOKED_KEY_UNDECIDABLE";
|
|
73622
|
+
const boundary = Date.parse(at);
|
|
73623
|
+
const issued = typeof ts === "string" ? Date.parse(ts) : NaN;
|
|
73624
|
+
if (!Number.isFinite(boundary) || !Number.isFinite(issued))
|
|
73625
|
+
return "REVOKED_KEY_UNDECIDABLE";
|
|
73626
|
+
return issued >= boundary ? "REVOKED_KEY" : "REVOKED_KEY_UNDECIDABLE";
|
|
73627
|
+
}
|
|
73628
|
+
return null;
|
|
73629
|
+
}
|
|
73430
73630
|
function isIssueTimeWithinKeyWindow(ts, keyMeta) {
|
|
73431
73631
|
if (!keyMeta || keyMeta.status === "active")
|
|
73432
73632
|
return true;
|
|
@@ -73451,6 +73651,12 @@ var require_deploy_receipt_token = __commonJS({
|
|
|
73451
73651
|
return false;
|
|
73452
73652
|
return true;
|
|
73453
73653
|
}
|
|
73654
|
+
function optionalString(source, field) {
|
|
73655
|
+
if (!source || typeof source !== "object")
|
|
73656
|
+
return null;
|
|
73657
|
+
const v = source[field];
|
|
73658
|
+
return typeof v === "string" && v.length > 0 ? v : null;
|
|
73659
|
+
}
|
|
73454
73660
|
function resolveKey(kid, registry, pinnedKeyPem) {
|
|
73455
73661
|
if (typeof pinnedKeyPem === "string" && pinnedKeyPem.trim().length > 0) {
|
|
73456
73662
|
try {
|
|
@@ -73458,7 +73664,9 @@ var require_deploy_receipt_token = __commonJS({
|
|
|
73458
73664
|
publicKey: (0, node_crypto_1.createPublicKey)(pinnedKeyPem),
|
|
73459
73665
|
status: "active",
|
|
73460
73666
|
valid_from: null,
|
|
73461
|
-
retired_at: null
|
|
73667
|
+
retired_at: null,
|
|
73668
|
+
revoked_at: null,
|
|
73669
|
+
compromised_at: null
|
|
73462
73670
|
};
|
|
73463
73671
|
} catch {
|
|
73464
73672
|
return null;
|
|
@@ -73473,9 +73681,11 @@ var require_deploy_receipt_token = __commonJS({
|
|
|
73473
73681
|
try {
|
|
73474
73682
|
return {
|
|
73475
73683
|
publicKey: (0, node_crypto_1.createPublicKey)(entry.public_key_pem),
|
|
73476
|
-
status: entry.status === "
|
|
73684
|
+
status: typeof entry.status === "string" ? entry.status : null,
|
|
73477
73685
|
valid_from: entry.valid_from || null,
|
|
73478
|
-
retired_at: entry.retired_at || null
|
|
73686
|
+
retired_at: entry.retired_at || null,
|
|
73687
|
+
revoked_at: optionalString(entry, "revoked_at"),
|
|
73688
|
+
compromised_at: optionalString(entry, "compromised_at")
|
|
73479
73689
|
};
|
|
73480
73690
|
} catch {
|
|
73481
73691
|
return null;
|
|
@@ -73549,6 +73759,14 @@ var require_deploy_receipt_token = __commonJS({
|
|
|
73549
73759
|
return fail("INVALID_SIGNATURE", "invalid_signature", { payload, authz_reason: "delimiter_in_field" });
|
|
73550
73760
|
}
|
|
73551
73761
|
}
|
|
73762
|
+
const withdrawn = deriveKeyWithdrawalStatus(typeof payload.ts === "string" ? payload.ts : void 0, resolved);
|
|
73763
|
+
if (withdrawn) {
|
|
73764
|
+
return fail(withdrawn, withdrawn === "UNKNOWN_KEY_STATUS" ? "unknown_key_status" : "revoked_key", {
|
|
73765
|
+
payload,
|
|
73766
|
+
authz_reason: withdrawn.toLowerCase(),
|
|
73767
|
+
key_status: withdrawn === "UNKNOWN_KEY_STATUS" ? "unknown" : "revoked"
|
|
73768
|
+
});
|
|
73769
|
+
}
|
|
73552
73770
|
if (resolved.status === "retired") {
|
|
73553
73771
|
if (!isIssueTimeWithinKeyWindow(typeof payload.ts === "string" ? payload.ts : void 0, resolved)) {
|
|
73554
73772
|
return fail("INVALID_SIGNATURE", "invalid_signature", { payload, authz_reason: "retired_key_outside_window" });
|
|
@@ -74040,18 +74258,168 @@ var require_coverage_report = __commonJS({
|
|
|
74040
74258
|
}
|
|
74041
74259
|
});
|
|
74042
74260
|
|
|
74261
|
+
// node_modules/@coderifts/agent-guard/dist/cjs/posture-receipt.js
|
|
74262
|
+
var require_posture_receipt = __commonJS({
|
|
74263
|
+
"node_modules/@coderifts/agent-guard/dist/cjs/posture-receipt.js"(exports2) {
|
|
74264
|
+
"use strict";
|
|
74265
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
74266
|
+
exports2.POSTURE_CLOCK_SKEW_TOLERANCE_MS = exports2.POSTURE_RECEIPT_V = void 0;
|
|
74267
|
+
exports2.verifyPostureReceipt = verifyPostureReceipt;
|
|
74268
|
+
var node_crypto_1 = require("node:crypto");
|
|
74269
|
+
exports2.POSTURE_RECEIPT_V = "cr.posture.receipt.v1";
|
|
74270
|
+
exports2.POSTURE_CLOCK_SKEW_TOLERANCE_MS = 5e3;
|
|
74271
|
+
function resolvePostureKey(kid, registry, pinnedKeyPem) {
|
|
74272
|
+
if (typeof pinnedKeyPem === "string" && pinnedKeyPem.trim().length > 0) {
|
|
74273
|
+
try {
|
|
74274
|
+
return { ok: true, key: (0, node_crypto_1.createPublicKey)(pinnedKeyPem) };
|
|
74275
|
+
} catch {
|
|
74276
|
+
return { ok: false, status: "POSTURE_UNKNOWN_KEY" };
|
|
74277
|
+
}
|
|
74278
|
+
}
|
|
74279
|
+
if (!registry || !Array.isArray(registry.keys) || !kid) {
|
|
74280
|
+
return { ok: false, status: "POSTURE_UNKNOWN_KEY" };
|
|
74281
|
+
}
|
|
74282
|
+
const matches = registry.keys.filter((k) => k && k.kid === kid && typeof k.public_key_pem === "string");
|
|
74283
|
+
if (matches.length === 0)
|
|
74284
|
+
return { ok: false, status: "POSTURE_UNKNOWN_KEY" };
|
|
74285
|
+
const entry = matches.find((k) => k.status === "active");
|
|
74286
|
+
if (!entry)
|
|
74287
|
+
return { ok: false, status: "POSTURE_REVOKED_KEY" };
|
|
74288
|
+
try {
|
|
74289
|
+
return { ok: true, key: (0, node_crypto_1.createPublicKey)(entry.public_key_pem) };
|
|
74290
|
+
} catch {
|
|
74291
|
+
return { ok: false, status: "POSTURE_UNKNOWN_KEY" };
|
|
74292
|
+
}
|
|
74293
|
+
}
|
|
74294
|
+
var fail = (status, reason, extra = {}) => ({ valid: false, status, reason, ...extra });
|
|
74295
|
+
function verifyPostureReceipt(token, input = {}) {
|
|
74296
|
+
if (typeof token !== "string" || token.length === 0) {
|
|
74297
|
+
return fail("POSTURE_MALFORMED", "malformed_structure");
|
|
74298
|
+
}
|
|
74299
|
+
const seg = token.split("|");
|
|
74300
|
+
if (seg.length !== 4 || seg[0] !== exports2.POSTURE_RECEIPT_V || seg.some((x) => !x)) {
|
|
74301
|
+
return fail("POSTURE_MALFORMED", "malformed_structure");
|
|
74302
|
+
}
|
|
74303
|
+
let preimageBytes;
|
|
74304
|
+
try {
|
|
74305
|
+
preimageBytes = Buffer.from(seg[2], "base64url");
|
|
74306
|
+
if (preimageBytes.length === 0)
|
|
74307
|
+
throw new Error("empty");
|
|
74308
|
+
} catch {
|
|
74309
|
+
return fail("POSTURE_MALFORMED", "bad_preimage");
|
|
74310
|
+
}
|
|
74311
|
+
const resolved = resolvePostureKey(seg[1], input.registry, input.pinnedKeyPem);
|
|
74312
|
+
if (!resolved.ok) {
|
|
74313
|
+
return fail(resolved.status, resolved.status === "POSTURE_REVOKED_KEY" ? "kid_revoked" : "unknown_kid");
|
|
74314
|
+
}
|
|
74315
|
+
const key = resolved.key;
|
|
74316
|
+
let sigOk = false;
|
|
74317
|
+
try {
|
|
74318
|
+
sigOk = (0, node_crypto_1.verify)(null, preimageBytes, key, Buffer.from(seg[3], "base64url"));
|
|
74319
|
+
} catch {
|
|
74320
|
+
return fail("POSTURE_INVALID_SIGNATURE", "signature_error");
|
|
74321
|
+
}
|
|
74322
|
+
if (!sigOk)
|
|
74323
|
+
return fail("POSTURE_INVALID_SIGNATURE", "signature_mismatch");
|
|
74324
|
+
let payload;
|
|
74325
|
+
try {
|
|
74326
|
+
payload = JSON.parse(preimageBytes.toString("utf8"));
|
|
74327
|
+
} catch {
|
|
74328
|
+
return fail("POSTURE_MALFORMED", "bad_json");
|
|
74329
|
+
}
|
|
74330
|
+
if (!payload || typeof payload !== "object") {
|
|
74331
|
+
return fail("POSTURE_MALFORMED", "bad_json");
|
|
74332
|
+
}
|
|
74333
|
+
if (payload.verdict !== "PASS") {
|
|
74334
|
+
return fail("POSTURE_FAIL", "posture_verdict_not_pass", { payload });
|
|
74335
|
+
}
|
|
74336
|
+
if (typeof payload.executor_kid === "string" && payload.executor_kid.length > 0 && payload.executor_kid !== seg[1]) {
|
|
74337
|
+
return fail("POSTURE_UNBOUND", "kid_mismatch", { payload });
|
|
74338
|
+
}
|
|
74339
|
+
if (Object.prototype.hasOwnProperty.call(payload, "v") && payload.v != null && payload.v !== exports2.POSTURE_RECEIPT_V) {
|
|
74340
|
+
return fail("POSTURE_MALFORMED", "body_version_mismatch", { payload });
|
|
74341
|
+
}
|
|
74342
|
+
if (typeof input.expectedDeploymentId === "string" && input.expectedDeploymentId.length > 0) {
|
|
74343
|
+
if (payload.deployment_id !== input.expectedDeploymentId) {
|
|
74344
|
+
return fail("POSTURE_UNBOUND", "deployment_id_mismatch", { payload });
|
|
74345
|
+
}
|
|
74346
|
+
}
|
|
74347
|
+
const bound = [];
|
|
74348
|
+
const notBound = [];
|
|
74349
|
+
const tuple = [
|
|
74350
|
+
["executor_id", input.expectedExecutorId, "executor_id"],
|
|
74351
|
+
["adapter_id", input.expectedAdapterId, "adapter_id"],
|
|
74352
|
+
["target_uri", input.expectedTargetUri, "target_uri"],
|
|
74353
|
+
["policy_hash", input.expectedPolicyHash, "policy_hash"]
|
|
74354
|
+
];
|
|
74355
|
+
for (const [field, expected, label] of tuple) {
|
|
74356
|
+
if (typeof expected !== "string" || expected.length === 0) {
|
|
74357
|
+
notBound.push({
|
|
74358
|
+
field: label,
|
|
74359
|
+
reason: "the caller did not state an expected value, so this verification did not check it"
|
|
74360
|
+
});
|
|
74361
|
+
continue;
|
|
74362
|
+
}
|
|
74363
|
+
const actual = payload[field];
|
|
74364
|
+
if (typeof actual !== "string" || actual.length === 0) {
|
|
74365
|
+
return fail("POSTURE_UNBOUND", `${label}_absent`, { payload, bound, not_bound: notBound });
|
|
74366
|
+
}
|
|
74367
|
+
if (actual !== expected) {
|
|
74368
|
+
return fail("POSTURE_UNBOUND", `${label}_mismatch`, { payload, bound, not_bound: notBound });
|
|
74369
|
+
}
|
|
74370
|
+
bound.push(label);
|
|
74371
|
+
}
|
|
74372
|
+
let ageMs;
|
|
74373
|
+
if (typeof input.maxAgeMs === "number" && Number.isFinite(input.maxAgeMs)) {
|
|
74374
|
+
const measured = Date.parse(String(payload.measured_at));
|
|
74375
|
+
if (Number.isNaN(measured)) {
|
|
74376
|
+
return fail("POSTURE_STALE", "measured_at_unparseable", { payload });
|
|
74377
|
+
}
|
|
74378
|
+
const now = (input.now || (() => Date.now()))();
|
|
74379
|
+
if (!Number.isFinite(now)) {
|
|
74380
|
+
return fail("POSTURE_STALE", "now_unparseable", { payload });
|
|
74381
|
+
}
|
|
74382
|
+
ageMs = now - measured;
|
|
74383
|
+
if (!Number.isFinite(ageMs)) {
|
|
74384
|
+
return fail("POSTURE_STALE", "measured_at_unparseable", { payload });
|
|
74385
|
+
}
|
|
74386
|
+
if (ageMs < -exports2.POSTURE_CLOCK_SKEW_TOLERANCE_MS) {
|
|
74387
|
+
return fail("POSTURE_STALE", "measured_at_in_future", { payload, age_ms: ageMs });
|
|
74388
|
+
}
|
|
74389
|
+
if (ageMs > input.maxAgeMs) {
|
|
74390
|
+
return fail("POSTURE_STALE", "outside_freshness_window", { payload, age_ms: ageMs });
|
|
74391
|
+
}
|
|
74392
|
+
}
|
|
74393
|
+
return {
|
|
74394
|
+
valid: true,
|
|
74395
|
+
status: "POSTURE_PASS",
|
|
74396
|
+
reason: null,
|
|
74397
|
+
payload,
|
|
74398
|
+
...ageMs === void 0 ? {} : { age_ms: ageMs },
|
|
74399
|
+
// What this PASS actually proved about the credential boundary — and what
|
|
74400
|
+
// it did not. A caller must not have to infer the difference.
|
|
74401
|
+
bound,
|
|
74402
|
+
not_bound: notBound
|
|
74403
|
+
};
|
|
74404
|
+
}
|
|
74405
|
+
}
|
|
74406
|
+
});
|
|
74407
|
+
|
|
74043
74408
|
// node_modules/@coderifts/agent-guard/dist/cjs/atomic-profile.js
|
|
74044
74409
|
var require_atomic_profile = __commonJS({
|
|
74045
74410
|
"node_modules/@coderifts/agent-guard/dist/cjs/atomic-profile.js"(exports2) {
|
|
74046
74411
|
"use strict";
|
|
74047
74412
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
74048
|
-
exports2.ATOMIC_INVARIANTS = exports2.ATOMIC_PROFILE_UNSATISFIED = exports2.GUARD_ATOMIC_WIRE_VALUE = exports2.PROFILE_ENFORCING_ATOMIC_V1 = void 0;
|
|
74413
|
+
exports2.CREDENTIAL_BOUNDARY_BARE_REJECTED = exports2.ATOMIC_V2_MAX_AGE_MS_CAP = exports2.ATOMIC_INVARIANTS = exports2.ATOMIC_PROFILE_UNSATISFIED = exports2.GUARD_ATOMIC_WIRE_VALUE = exports2.PROFILE_ENFORCING_ATOMIC_V2 = exports2.PROFILE_ENFORCING_ATOMIC_V1 = void 0;
|
|
74049
74414
|
exports2.createMutatorRegister = createMutatorRegister;
|
|
74050
74415
|
exports2.isEnforcingAtomic = isEnforcingAtomic;
|
|
74416
|
+
exports2.isEnforcingAtomicV2 = isEnforcingAtomicV2;
|
|
74051
74417
|
exports2.atomicConstructionProblems = atomicConstructionProblems;
|
|
74052
74418
|
exports2.throwAtomicUnsatisfied = throwAtomicUnsatisfied;
|
|
74053
74419
|
exports2.atomicOutcome = atomicOutcome;
|
|
74420
|
+
var posture_receipt_js_1 = require_posture_receipt();
|
|
74054
74421
|
exports2.PROFILE_ENFORCING_ATOMIC_V1 = "ENFORCING_ATOMIC_V1";
|
|
74422
|
+
exports2.PROFILE_ENFORCING_ATOMIC_V2 = "ENFORCING_ATOMIC_V2";
|
|
74055
74423
|
exports2.GUARD_ATOMIC_WIRE_VALUE = "ENFORCING_ATOMIC";
|
|
74056
74424
|
exports2.ATOMIC_PROFILE_UNSATISFIED = "ATOMIC_PROFILE_UNSATISFIED";
|
|
74057
74425
|
exports2.ATOMIC_INVARIANTS = Object.freeze([
|
|
@@ -74087,8 +74455,13 @@ var require_atomic_profile = __commonJS({
|
|
|
74087
74455
|
return api;
|
|
74088
74456
|
}
|
|
74089
74457
|
function isEnforcingAtomic(profile) {
|
|
74090
|
-
return profile === "ENFORCING_ATOMIC" || profile === exports2.PROFILE_ENFORCING_ATOMIC_V1;
|
|
74458
|
+
return profile === "ENFORCING_ATOMIC" || profile === exports2.PROFILE_ENFORCING_ATOMIC_V1 || profile === exports2.PROFILE_ENFORCING_ATOMIC_V2;
|
|
74459
|
+
}
|
|
74460
|
+
function isEnforcingAtomicV2(profile) {
|
|
74461
|
+
return profile === exports2.PROFILE_ENFORCING_ATOMIC_V2;
|
|
74091
74462
|
}
|
|
74463
|
+
exports2.ATOMIC_V2_MAX_AGE_MS_CAP = 864e5;
|
|
74464
|
+
exports2.CREDENTIAL_BOUNDARY_BARE_REJECTED = "credential_boundary: a verified cr.posture.receipt.v1 is required; a bare assertion is no longer accepted. ENFORCING_ATOMIC_V1 still accepts the bare form and is frozen \u2014 move to _V2 to get this check.";
|
|
74092
74465
|
function atomicConstructionProblems(input) {
|
|
74093
74466
|
const problems = [];
|
|
74094
74467
|
const grant = input.executionGrant;
|
|
@@ -74125,6 +74498,42 @@ var require_atomic_profile = __commonJS({
|
|
|
74125
74498
|
if (input.credentialBoundary !== true && typeof input.credentialBoundary !== "object") {
|
|
74126
74499
|
problems.push("credential_boundary: credentialBoundary assertion required");
|
|
74127
74500
|
}
|
|
74501
|
+
if (isEnforcingAtomicV2(input.profile)) {
|
|
74502
|
+
const cb = input.credentialBoundary;
|
|
74503
|
+
if (cb === true || !cb || typeof cb !== "object" || typeof cb.postureReceipt !== "string") {
|
|
74504
|
+
problems.push(exports2.CREDENTIAL_BOUNDARY_BARE_REJECTED);
|
|
74505
|
+
} else if (!cb.registry && !cb.pinnedKeyPem) {
|
|
74506
|
+
problems.push("credential_boundary: credentialBoundary.registry or .pinnedKeyPem required \u2014 the posture receipt is verified against a caller-supplied key; this package never fetches one.");
|
|
74507
|
+
} else {
|
|
74508
|
+
const deploymentId = typeof cb.deploymentId === "string" ? cb.deploymentId : "";
|
|
74509
|
+
if (deploymentId.length === 0) {
|
|
74510
|
+
problems.push("credential_boundary: credentialBoundary.deploymentId required under ENFORCING_ATOMIC_V2 \u2014 the posture receipt must be bound to this deployment.");
|
|
74511
|
+
}
|
|
74512
|
+
const maxAgeMs = cb.maxAgeMs;
|
|
74513
|
+
const maxAgeOk = typeof maxAgeMs === "number" && Number.isFinite(maxAgeMs) && maxAgeMs > 0 && maxAgeMs <= exports2.ATOMIC_V2_MAX_AGE_MS_CAP;
|
|
74514
|
+
if (typeof maxAgeMs !== "number" || !Number.isFinite(maxAgeMs) || maxAgeMs <= 0) {
|
|
74515
|
+
problems.push("credential_boundary: credentialBoundary.maxAgeMs required under ENFORCING_ATOMIC_V2 \u2014 a finite positive freshness window; the receipt signs measured_at and no expires_at.");
|
|
74516
|
+
} else if (maxAgeMs > exports2.ATOMIC_V2_MAX_AGE_MS_CAP) {
|
|
74517
|
+
problems.push(`credential_boundary: credentialBoundary.maxAgeMs exceeds the ${exports2.ATOMIC_V2_MAX_AGE_MS_CAP}ms cap (24h). A larger window is not a freshness check.`);
|
|
74518
|
+
}
|
|
74519
|
+
if (deploymentId.length > 0 && maxAgeOk) {
|
|
74520
|
+
const r = (0, posture_receipt_js_1.verifyPostureReceipt)(cb.postureReceipt, {
|
|
74521
|
+
registry: cb.registry,
|
|
74522
|
+
pinnedKeyPem: cb.pinnedKeyPem,
|
|
74523
|
+
expectedDeploymentId: deploymentId,
|
|
74524
|
+
expectedExecutorId: input.executorId,
|
|
74525
|
+
expectedAdapterId: input.adapterId,
|
|
74526
|
+
expectedTargetUri: input.targetUri,
|
|
74527
|
+
expectedPolicyHash: input.policyHash,
|
|
74528
|
+
maxAgeMs,
|
|
74529
|
+
now: cb.now
|
|
74530
|
+
});
|
|
74531
|
+
if (!r.valid) {
|
|
74532
|
+
problems.push(`credential_boundary: posture receipt not verified \u2014 ${r.status} (${r.reason}). ` + (r.status === "POSTURE_STALE" ? "This is the caller-supplied freshness window (maxAgeMs), not a receipt-carried expiry: cr.posture.receipt.v1 signs measured_at and no expires_at." : r.status === "POSTURE_FAIL" ? "The signature verified; the posture did not. A signed FAIL is a drift artifact \u2014 the boundary regressed, the receipt is intact." : "Supply a posture receipt signed by a key in the registry, bound to this deployment_id, with verdict PASS."));
|
|
74533
|
+
}
|
|
74534
|
+
}
|
|
74535
|
+
}
|
|
74536
|
+
}
|
|
74128
74537
|
return problems;
|
|
74129
74538
|
}
|
|
74130
74539
|
function throwAtomicUnsatisfied(problems) {
|
|
@@ -74153,11 +74562,12 @@ var require_with_coderifts = __commonJS({
|
|
|
74153
74562
|
"node_modules/@coderifts/agent-guard/dist/cjs/with-coderifts.js"(exports2) {
|
|
74154
74563
|
"use strict";
|
|
74155
74564
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
74156
|
-
exports2.PROFILE_ENFORCING_ATOMIC_V1 = exports2.PROFILE_ENFORCING_STRICT_V1 = void 0;
|
|
74565
|
+
exports2.PROFILE_ENFORCING_ATOMIC_V2 = exports2.PROFILE_ENFORCING_ATOMIC_V1 = exports2.PROFILE_ENFORCING_STRICT_V1 = void 0;
|
|
74157
74566
|
exports2.foldTableSettledCalls = foldTableSettledCalls;
|
|
74158
74567
|
exports2.guardedFractionAmongRoutes = guardedFractionAmongRoutes;
|
|
74159
74568
|
exports2.withCodeRifts = withCodeRifts;
|
|
74160
74569
|
var tool_registry_js_1 = require_tool_registry();
|
|
74570
|
+
var execution_grant_js_1 = require_execution_grant2();
|
|
74161
74571
|
var coverage_observed_js_1 = require_coverage_observed();
|
|
74162
74572
|
var atomic_profile_js_1 = require_atomic_profile();
|
|
74163
74573
|
function foldTableSettledCalls(events) {
|
|
@@ -74185,9 +74595,13 @@ var require_with_coderifts = __commonJS({
|
|
|
74185
74595
|
Object.defineProperty(exports2, "PROFILE_ENFORCING_ATOMIC_V1", { enumerable: true, get: function() {
|
|
74186
74596
|
return atomic_profile_js_2.PROFILE_ENFORCING_ATOMIC_V1;
|
|
74187
74597
|
} });
|
|
74598
|
+
Object.defineProperty(exports2, "PROFILE_ENFORCING_ATOMIC_V2", { enumerable: true, get: function() {
|
|
74599
|
+
return atomic_profile_js_2.PROFILE_ENFORCING_ATOMIC_V2;
|
|
74600
|
+
} });
|
|
74188
74601
|
var ACCEPTED_PROFILES = Object.freeze([
|
|
74189
74602
|
"ENFORCING_STRICT_V1",
|
|
74190
74603
|
"ENFORCING_STRICT",
|
|
74604
|
+
"ENFORCING_ATOMIC_V2",
|
|
74191
74605
|
"ENFORCING_ATOMIC_V1",
|
|
74192
74606
|
"ENFORCING_ATOMIC"
|
|
74193
74607
|
]);
|
|
@@ -74465,16 +74879,21 @@ var require_with_coderifts = __commonJS({
|
|
|
74465
74879
|
problems.push(...enforcingStrictExecutionChainProblems(input));
|
|
74466
74880
|
}
|
|
74467
74881
|
if ((0, atomic_profile_js_1.isEnforcingAtomic)(input.profile)) {
|
|
74882
|
+
const v2 = (0, execution_grant_js_1.resolveV2Fields)(input);
|
|
74468
74883
|
const atomicProblems = (0, atomic_profile_js_1.atomicConstructionProblems)({
|
|
74469
74884
|
executionGrant: input.executionGrant,
|
|
74470
|
-
executorId:
|
|
74471
|
-
adapterId:
|
|
74472
|
-
targetUri:
|
|
74885
|
+
executorId: v2.executorId,
|
|
74886
|
+
adapterId: v2.adapterId,
|
|
74887
|
+
targetUri: v2.targetUri,
|
|
74888
|
+
// Previously never forwarded, so the posture verifier's policy_hash
|
|
74889
|
+
// binding could not fire no matter what the caller configured.
|
|
74890
|
+
policyHash: v2.policyHash,
|
|
74473
74891
|
executorAttestation: input.executorAttestation,
|
|
74474
74892
|
mutatorRegister: input.mutatorRegister,
|
|
74475
74893
|
casAdapter: input.casAdapter,
|
|
74476
74894
|
readBack: input.readBack,
|
|
74477
|
-
credentialBoundary: input.credentialBoundary
|
|
74895
|
+
credentialBoundary: input.credentialBoundary,
|
|
74896
|
+
profile: input.profile
|
|
74478
74897
|
});
|
|
74479
74898
|
if (atomicProblems.length > 0)
|
|
74480
74899
|
(0, atomic_profile_js_1.throwAtomicUnsatisfied)(atomicProblems);
|
|
@@ -74553,6 +74972,7 @@ var require_with_coderifts = __commonJS({
|
|
|
74553
74972
|
}
|
|
74554
74973
|
if (input.executionGrant !== void 0) {
|
|
74555
74974
|
guard.executionGrant = input.executionGrant;
|
|
74975
|
+
Object.assign(guard, (0, execution_grant_js_1.resolveV2Fields)(input));
|
|
74556
74976
|
}
|
|
74557
74977
|
const strict = isEnforcingStrict(input);
|
|
74558
74978
|
if (strict) {
|
|
@@ -75105,6 +75525,174 @@ var require_gemini = __commonJS({
|
|
|
75105
75525
|
}
|
|
75106
75526
|
});
|
|
75107
75527
|
|
|
75528
|
+
// node_modules/@coderifts/agent-guard/dist/cjs/adapters/vercel.js
|
|
75529
|
+
var require_vercel = __commonJS({
|
|
75530
|
+
"node_modules/@coderifts/agent-guard/dist/cjs/adapters/vercel.js"(exports2) {
|
|
75531
|
+
"use strict";
|
|
75532
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
75533
|
+
exports2.protectedToolToVercel = protectedToolToVercel;
|
|
75534
|
+
exports2.toVercelTools = toVercelTools;
|
|
75535
|
+
exports2.withCodeRiftsVercel = withCodeRiftsVercel;
|
|
75536
|
+
exports2.vercelToolAdapter = vercelToolAdapter;
|
|
75537
|
+
exports2.defaultSerializeVercelToolResult = defaultSerializeVercelToolResult;
|
|
75538
|
+
exports2.bindVercelGuardOutcome = bindVercelGuardOutcome;
|
|
75539
|
+
var with_coderifts_js_1 = require_with_coderifts();
|
|
75540
|
+
var execution_proof_js_1 = require_execution_proof();
|
|
75541
|
+
var final_answer_proof_js_1 = require_final_answer_proof();
|
|
75542
|
+
var gate_refusal_js_1 = require_gate_refusal();
|
|
75543
|
+
var EMPTY_PARAMETERS = Object.freeze({
|
|
75544
|
+
type: "object",
|
|
75545
|
+
properties: {}
|
|
75546
|
+
});
|
|
75547
|
+
function looksLikeGuardOutcome(x) {
|
|
75548
|
+
if (!x || typeof x !== "object")
|
|
75549
|
+
return false;
|
|
75550
|
+
const o = x;
|
|
75551
|
+
return typeof o.executed === "boolean" && typeof o.executionAttempted === "boolean" && o.proof != null && typeof o.proof === "object" && o.verdict != null && typeof o.verdict === "object";
|
|
75552
|
+
}
|
|
75553
|
+
function toolCallIdFromOptions(options) {
|
|
75554
|
+
if (options && typeof options.toolCallId === "string")
|
|
75555
|
+
return options.toolCallId;
|
|
75556
|
+
return "";
|
|
75557
|
+
}
|
|
75558
|
+
var FRESHNESS_NOT_CONFIGURED = Object.freeze({
|
|
75559
|
+
wiring: "NOT_CONFIGURED",
|
|
75560
|
+
write_style: false,
|
|
75561
|
+
require_freshness: false
|
|
75562
|
+
});
|
|
75563
|
+
var CW_NOT_REPORTED = Object.freeze({
|
|
75564
|
+
conditional_write: "not_reported",
|
|
75565
|
+
require_conditional_write: false,
|
|
75566
|
+
write_style: false,
|
|
75567
|
+
mutating: false
|
|
75568
|
+
});
|
|
75569
|
+
function guardedNonOutcomeRefusal(toolName) {
|
|
75570
|
+
const verdict = {
|
|
75571
|
+
kind: "UNAVAILABLE",
|
|
75572
|
+
cause: "CONFIG_ERROR",
|
|
75573
|
+
failPolicy: "closed",
|
|
75574
|
+
resolution: "CLOSED",
|
|
75575
|
+
action: "STOP",
|
|
75576
|
+
decisionMissing: true,
|
|
75577
|
+
unavailableCount: 1
|
|
75578
|
+
};
|
|
75579
|
+
const commit_observation = {
|
|
75580
|
+
status: "not_observed",
|
|
75581
|
+
observed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
75582
|
+
host_attestation: "absent"
|
|
75583
|
+
};
|
|
75584
|
+
const proof = (0, execution_proof_js_1.buildExecutionProof)({
|
|
75585
|
+
preflighted: false,
|
|
75586
|
+
executionAttempted: false,
|
|
75587
|
+
executed: false,
|
|
75588
|
+
enforced: false,
|
|
75589
|
+
verdict,
|
|
75590
|
+
commitObservation: commit_observation
|
|
75591
|
+
});
|
|
75592
|
+
void toolName;
|
|
75593
|
+
return {
|
|
75594
|
+
executionAttempted: false,
|
|
75595
|
+
executed: false,
|
|
75596
|
+
enforced: false,
|
|
75597
|
+
verdict,
|
|
75598
|
+
preflighted: false,
|
|
75599
|
+
proof,
|
|
75600
|
+
freshness: FRESHNESS_NOT_CONFIGURED,
|
|
75601
|
+
conditional_write: CW_NOT_REPORTED,
|
|
75602
|
+
commit_observation
|
|
75603
|
+
};
|
|
75604
|
+
}
|
|
75605
|
+
function protectedToolToVercel(tool) {
|
|
75606
|
+
const parameters = tool.inputSchema != null && typeof tool.inputSchema === "object" && !Array.isArray(tool.inputSchema) ? tool.inputSchema : { ...EMPTY_PARAMETERS };
|
|
75607
|
+
const execute = async (args, options) => {
|
|
75608
|
+
const raw = await Promise.resolve().then(() => tool.execute(args));
|
|
75609
|
+
const bindArgs = {
|
|
75610
|
+
toolCallId: toolCallIdFromOptions(options),
|
|
75611
|
+
toolName: tool.name
|
|
75612
|
+
};
|
|
75613
|
+
if (looksLikeGuardOutcome(raw)) {
|
|
75614
|
+
return bindVercelGuardOutcome(raw, bindArgs).result;
|
|
75615
|
+
}
|
|
75616
|
+
if (tool._coderifts && tool._coderifts.guarded) {
|
|
75617
|
+
return bindVercelGuardOutcome(guardedNonOutcomeRefusal(tool.name), bindArgs).result;
|
|
75618
|
+
}
|
|
75619
|
+
return raw;
|
|
75620
|
+
};
|
|
75621
|
+
const out = {
|
|
75622
|
+
parameters,
|
|
75623
|
+
execute
|
|
75624
|
+
};
|
|
75625
|
+
if (tool.description != null && tool.description !== "") {
|
|
75626
|
+
out.description = tool.description;
|
|
75627
|
+
}
|
|
75628
|
+
return out;
|
|
75629
|
+
}
|
|
75630
|
+
function toVercelTools(protectedTools) {
|
|
75631
|
+
const out = {};
|
|
75632
|
+
for (const t of protectedTools) {
|
|
75633
|
+
out[t.name] = protectedToolToVercel(t);
|
|
75634
|
+
}
|
|
75635
|
+
return out;
|
|
75636
|
+
}
|
|
75637
|
+
function withCodeRiftsVercel(input) {
|
|
75638
|
+
const core = (0, with_coderifts_js_1.withCodeRifts)(input);
|
|
75639
|
+
return vercelToolAdapter(core);
|
|
75640
|
+
}
|
|
75641
|
+
function vercelToolAdapter(result) {
|
|
75642
|
+
const protected_tools = result.tools;
|
|
75643
|
+
const tools = toVercelTools(protected_tools);
|
|
75644
|
+
const out = {
|
|
75645
|
+
tools,
|
|
75646
|
+
protected_tools,
|
|
75647
|
+
registry_report: result.registry_report,
|
|
75648
|
+
composition_assurance: result.composition_assurance,
|
|
75649
|
+
receipt_thread: result.receipt_thread,
|
|
75650
|
+
coverage_observed: result.coverage_observed
|
|
75651
|
+
};
|
|
75652
|
+
if (result.repository !== void 0) {
|
|
75653
|
+
out.repository = result.repository;
|
|
75654
|
+
}
|
|
75655
|
+
return out;
|
|
75656
|
+
}
|
|
75657
|
+
function defaultSerializeVercelToolResult(result) {
|
|
75658
|
+
if (typeof result === "string")
|
|
75659
|
+
return result;
|
|
75660
|
+
if (typeof result === "number" || typeof result === "boolean" || typeof result === "bigint" || result === null || result === void 0) {
|
|
75661
|
+
return String(result);
|
|
75662
|
+
}
|
|
75663
|
+
try {
|
|
75664
|
+
return JSON.stringify(result);
|
|
75665
|
+
} catch {
|
|
75666
|
+
return String(result);
|
|
75667
|
+
}
|
|
75668
|
+
}
|
|
75669
|
+
function bindVercelGuardOutcome(outcome, args) {
|
|
75670
|
+
const toolCallId = args.toolCallId;
|
|
75671
|
+
const serialize = args.serialize ?? defaultSerializeVercelToolResult;
|
|
75672
|
+
let body;
|
|
75673
|
+
if (outcome.executed === true) {
|
|
75674
|
+
body = serialize(outcome.result);
|
|
75675
|
+
} else if (outcome.executionAttempted === false) {
|
|
75676
|
+
body = (0, gate_refusal_js_1.formatGateRefusalBody)(outcome);
|
|
75677
|
+
} else {
|
|
75678
|
+
const err = "error" in outcome ? outcome.error : void 0;
|
|
75679
|
+
const kind = (0, gate_refusal_js_1.verdictKind)(outcome);
|
|
75680
|
+
body = `Tool execution failed after gate decision (verdict: ${kind}): ${(0, gate_refusal_js_1.formatGuardError)(err)}`;
|
|
75681
|
+
}
|
|
75682
|
+
const result = args.attachProof === false ? body : (0, final_answer_proof_js_1.attachProofToAgentResponse)(body, outcome.proof);
|
|
75683
|
+
const part = {
|
|
75684
|
+
type: "tool-result",
|
|
75685
|
+
toolCallId,
|
|
75686
|
+
result
|
|
75687
|
+
};
|
|
75688
|
+
if (args.toolName != null && args.toolName !== "") {
|
|
75689
|
+
part.toolName = args.toolName;
|
|
75690
|
+
}
|
|
75691
|
+
return part;
|
|
75692
|
+
}
|
|
75693
|
+
}
|
|
75694
|
+
});
|
|
75695
|
+
|
|
75108
75696
|
// node_modules/@coderifts/agent-guard/dist/cjs/execute-tool-call.js
|
|
75109
75697
|
var require_execute_tool_call = __commonJS({
|
|
75110
75698
|
"node_modules/@coderifts/agent-guard/dist/cjs/execute-tool-call.js"(exports2) {
|
|
@@ -75117,11 +75705,13 @@ var require_execute_tool_call = __commonJS({
|
|
|
75117
75705
|
exports2.executeAnthropicToolCall = executeAnthropicToolCall;
|
|
75118
75706
|
exports2.executeGeminiToolCall = executeGeminiToolCall;
|
|
75119
75707
|
exports2.executeLangGraphToolCall = executeLangGraphToolCall;
|
|
75708
|
+
exports2.executeVercelToolCall = executeVercelToolCall;
|
|
75120
75709
|
var execution_proof_js_1 = require_execution_proof();
|
|
75121
75710
|
var openai_js_1 = require_openai();
|
|
75122
75711
|
var anthropic_js_1 = require_anthropic();
|
|
75123
75712
|
var gemini_js_1 = require_gemini();
|
|
75124
75713
|
var langgraph_js_1 = require_langgraph();
|
|
75714
|
+
var vercel_js_1 = require_vercel();
|
|
75125
75715
|
function resolveProtectedTools(table) {
|
|
75126
75716
|
if (Array.isArray(table))
|
|
75127
75717
|
return table;
|
|
@@ -75382,6 +75972,26 @@ var require_execute_tool_call = __commonJS({
|
|
|
75382
75972
|
}
|
|
75383
75973
|
return bound;
|
|
75384
75974
|
}
|
|
75975
|
+
async function executeVercelToolCall(args) {
|
|
75976
|
+
const callArgs = parseMaybeJsonArgs(args.arguments);
|
|
75977
|
+
const outcome = await executeProtectedTool(args.tools, args.name, callArgs);
|
|
75978
|
+
const bound = (0, vercel_js_1.bindVercelGuardOutcome)(outcome, {
|
|
75979
|
+
toolCallId: args.toolCallId,
|
|
75980
|
+
toolName: args.name,
|
|
75981
|
+
serialize: args.serialize
|
|
75982
|
+
});
|
|
75983
|
+
if (outcome.executionAttempted === false) {
|
|
75984
|
+
const result = appendEnvelopeSurface(bound.result, outcome);
|
|
75985
|
+
const part = {
|
|
75986
|
+
type: "tool-result",
|
|
75987
|
+
toolCallId: args.toolCallId,
|
|
75988
|
+
toolName: args.name,
|
|
75989
|
+
result
|
|
75990
|
+
};
|
|
75991
|
+
return part;
|
|
75992
|
+
}
|
|
75993
|
+
return bound;
|
|
75994
|
+
}
|
|
75385
75995
|
function parseMaybeJsonArgs(args) {
|
|
75386
75996
|
if (typeof args === "string") {
|
|
75387
75997
|
const s = args.trim();
|
|
@@ -75612,8 +76222,8 @@ var require_cjs4 = __commonJS({
|
|
|
75612
76222
|
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;
|
|
75613
76223
|
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;
|
|
75614
76224
|
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;
|
|
75615
|
-
exports2.
|
|
75616
|
-
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 = void 0;
|
|
76225
|
+
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 = exports2.POSTURE_CLOCK_SKEW_TOLERANCE_MS = exports2.POSTURE_RECEIPT_V = exports2.verifyPostureReceipt = exports2.ATOMIC_V2_MAX_AGE_MS_CAP = exports2.CREDENTIAL_BOUNDARY_BARE_REJECTED = exports2.atomicConstructionProblems = exports2.isEnforcingAtomicV2 = exports2.PROFILE_ENFORCING_ATOMIC_V2 = exports2.isEnforcingAtomic = exports2.atomicOutcome = exports2.ATOMIC_PROFILE_UNSATISFIED = exports2.ATOMIC_INVARIANTS = exports2.createMutatorRegister = exports2.PROFILE_ENFORCING_ATOMIC_V1 = exports2.PROFILE_ENFORCING_STRICT_V1 = void 0;
|
|
76226
|
+
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.executeVercelToolCall = exports2.executeLangGraphToolCall = exports2.executeGeminiToolCall = exports2.executeAnthropicToolCall = exports2.executeOpenAIToolCall = exports2.executeProtectedTool = exports2.defaultSerializeVercelToolResult = exports2.bindVercelGuardOutcome = exports2.protectedToolToVercel = exports2.toVercelTools = exports2.vercelToolAdapter = exports2.withCodeRiftsVercel = exports2.defaultSerializeGeminiToolResult = exports2.bindGeminiGuardOutcome = exports2.protectedToolToFunctionDeclaration = exports2.toGeminiTools = exports2.geminiToolAdapter = void 0;
|
|
75617
76227
|
var guard_js_1 = require_guard();
|
|
75618
76228
|
Object.defineProperty(exports2, "guardToolCall", { enumerable: true, get: function() {
|
|
75619
76229
|
return guard_js_1.guardToolCall;
|
|
@@ -76120,6 +76730,31 @@ var require_cjs4 = __commonJS({
|
|
|
76120
76730
|
Object.defineProperty(exports2, "isEnforcingAtomic", { enumerable: true, get: function() {
|
|
76121
76731
|
return atomic_profile_js_1.isEnforcingAtomic;
|
|
76122
76732
|
} });
|
|
76733
|
+
Object.defineProperty(exports2, "PROFILE_ENFORCING_ATOMIC_V2", { enumerable: true, get: function() {
|
|
76734
|
+
return atomic_profile_js_1.PROFILE_ENFORCING_ATOMIC_V2;
|
|
76735
|
+
} });
|
|
76736
|
+
Object.defineProperty(exports2, "isEnforcingAtomicV2", { enumerable: true, get: function() {
|
|
76737
|
+
return atomic_profile_js_1.isEnforcingAtomicV2;
|
|
76738
|
+
} });
|
|
76739
|
+
Object.defineProperty(exports2, "atomicConstructionProblems", { enumerable: true, get: function() {
|
|
76740
|
+
return atomic_profile_js_1.atomicConstructionProblems;
|
|
76741
|
+
} });
|
|
76742
|
+
Object.defineProperty(exports2, "CREDENTIAL_BOUNDARY_BARE_REJECTED", { enumerable: true, get: function() {
|
|
76743
|
+
return atomic_profile_js_1.CREDENTIAL_BOUNDARY_BARE_REJECTED;
|
|
76744
|
+
} });
|
|
76745
|
+
Object.defineProperty(exports2, "ATOMIC_V2_MAX_AGE_MS_CAP", { enumerable: true, get: function() {
|
|
76746
|
+
return atomic_profile_js_1.ATOMIC_V2_MAX_AGE_MS_CAP;
|
|
76747
|
+
} });
|
|
76748
|
+
var posture_receipt_js_1 = require_posture_receipt();
|
|
76749
|
+
Object.defineProperty(exports2, "verifyPostureReceipt", { enumerable: true, get: function() {
|
|
76750
|
+
return posture_receipt_js_1.verifyPostureReceipt;
|
|
76751
|
+
} });
|
|
76752
|
+
Object.defineProperty(exports2, "POSTURE_RECEIPT_V", { enumerable: true, get: function() {
|
|
76753
|
+
return posture_receipt_js_1.POSTURE_RECEIPT_V;
|
|
76754
|
+
} });
|
|
76755
|
+
Object.defineProperty(exports2, "POSTURE_CLOCK_SKEW_TOLERANCE_MS", { enumerable: true, get: function() {
|
|
76756
|
+
return posture_receipt_js_1.POSTURE_CLOCK_SKEW_TOLERANCE_MS;
|
|
76757
|
+
} });
|
|
76123
76758
|
var execution_grant_js_1 = require_execution_grant2();
|
|
76124
76759
|
Object.defineProperty(exports2, "isExecutionGrantEnabled", { enumerable: true, get: function() {
|
|
76125
76760
|
return execution_grant_js_1.isExecutionGrantEnabled;
|
|
@@ -76248,6 +76883,25 @@ var require_cjs4 = __commonJS({
|
|
|
76248
76883
|
Object.defineProperty(exports2, "defaultSerializeGeminiToolResult", { enumerable: true, get: function() {
|
|
76249
76884
|
return gemini_js_1.defaultSerializeGeminiToolResult;
|
|
76250
76885
|
} });
|
|
76886
|
+
var vercel_js_1 = require_vercel();
|
|
76887
|
+
Object.defineProperty(exports2, "withCodeRiftsVercel", { enumerable: true, get: function() {
|
|
76888
|
+
return vercel_js_1.withCodeRiftsVercel;
|
|
76889
|
+
} });
|
|
76890
|
+
Object.defineProperty(exports2, "vercelToolAdapter", { enumerable: true, get: function() {
|
|
76891
|
+
return vercel_js_1.vercelToolAdapter;
|
|
76892
|
+
} });
|
|
76893
|
+
Object.defineProperty(exports2, "toVercelTools", { enumerable: true, get: function() {
|
|
76894
|
+
return vercel_js_1.toVercelTools;
|
|
76895
|
+
} });
|
|
76896
|
+
Object.defineProperty(exports2, "protectedToolToVercel", { enumerable: true, get: function() {
|
|
76897
|
+
return vercel_js_1.protectedToolToVercel;
|
|
76898
|
+
} });
|
|
76899
|
+
Object.defineProperty(exports2, "bindVercelGuardOutcome", { enumerable: true, get: function() {
|
|
76900
|
+
return vercel_js_1.bindVercelGuardOutcome;
|
|
76901
|
+
} });
|
|
76902
|
+
Object.defineProperty(exports2, "defaultSerializeVercelToolResult", { enumerable: true, get: function() {
|
|
76903
|
+
return vercel_js_1.defaultSerializeVercelToolResult;
|
|
76904
|
+
} });
|
|
76251
76905
|
var execute_tool_call_js_1 = require_execute_tool_call();
|
|
76252
76906
|
Object.defineProperty(exports2, "executeProtectedTool", { enumerable: true, get: function() {
|
|
76253
76907
|
return execute_tool_call_js_1.executeProtectedTool;
|
|
@@ -76264,6 +76918,9 @@ var require_cjs4 = __commonJS({
|
|
|
76264
76918
|
Object.defineProperty(exports2, "executeLangGraphToolCall", { enumerable: true, get: function() {
|
|
76265
76919
|
return execute_tool_call_js_1.executeLangGraphToolCall;
|
|
76266
76920
|
} });
|
|
76921
|
+
Object.defineProperty(exports2, "executeVercelToolCall", { enumerable: true, get: function() {
|
|
76922
|
+
return execute_tool_call_js_1.executeVercelToolCall;
|
|
76923
|
+
} });
|
|
76267
76924
|
Object.defineProperty(exports2, "isGuardOutcome", { enumerable: true, get: function() {
|
|
76268
76925
|
return execute_tool_call_js_1.isGuardOutcome;
|
|
76269
76926
|
} });
|
|
@@ -76311,6 +76968,24 @@ var require_claude_hook = __commonJS({
|
|
|
76311
76968
|
var { getApiKey } = require_config();
|
|
76312
76969
|
var { cloudAuthorizePreflight } = require_cloud();
|
|
76313
76970
|
var DEFAULT_SPEC_PATH = "api/openapi.yaml";
|
|
76971
|
+
var DEFAULT_SPEC_GLOBS = Object.freeze([
|
|
76972
|
+
"**/*openapi*.yaml",
|
|
76973
|
+
"**/*openapi*.yml",
|
|
76974
|
+
"**/*openapi*.json",
|
|
76975
|
+
"**/*swagger*.yaml",
|
|
76976
|
+
"**/*swagger*.yml",
|
|
76977
|
+
"**/*swagger*.json",
|
|
76978
|
+
"**/*asyncapi*.yaml",
|
|
76979
|
+
"**/*asyncapi*.yml",
|
|
76980
|
+
"**/*asyncapi*.json",
|
|
76981
|
+
"**/*.graphql",
|
|
76982
|
+
"**/*.gql",
|
|
76983
|
+
"**/*.proto",
|
|
76984
|
+
"**/*mcp*.json",
|
|
76985
|
+
"**/*mcp*.yaml",
|
|
76986
|
+
"**/*mcp*.yml",
|
|
76987
|
+
"**/*tool-schema*.json"
|
|
76988
|
+
]);
|
|
76314
76989
|
var CLOSED_ACTIONS = /* @__PURE__ */ new Set([
|
|
76315
76990
|
"CONTINUE",
|
|
76316
76991
|
"CONTINUE_WITH_MONITORING",
|
|
@@ -76320,8 +76995,9 @@ var require_claude_hook = __commonJS({
|
|
|
76320
76995
|
var USAGE = [
|
|
76321
76996
|
"Usage: coderifts claude-hook",
|
|
76322
76997
|
"",
|
|
76323
|
-
"Claude Code PreToolUse hook: gates Write|Edit|MultiEdit when they touch
|
|
76324
|
-
"
|
|
76998
|
+
"Claude Code PreToolUse hook: gates Write|Edit|MultiEdit when they touch a",
|
|
76999
|
+
"governed contract path (default family + git config coderifts.specPath).",
|
|
77000
|
+
"Reads JSON context from STDIN.",
|
|
76325
77001
|
"",
|
|
76326
77002
|
"Exit map (Claude Code semantics \u2014 get this exactly right):",
|
|
76327
77003
|
" 2 BLOCK \u2014 tool call cancelled (BLOCK/STOP, REQUEST_APPROVAL, unrecognised action,",
|
|
@@ -76336,7 +77012,7 @@ var require_claude_hook = __commonJS({
|
|
|
76336
77012
|
"Parse-gap DEFAULT (exit 2): unparseable stdin / missing file_path \u2014 refusing (fail-closed);",
|
|
76337
77013
|
" set CODERIFTS_ADVISORY=1 to soften. JSONL hook_blocked cause stdin_unparseable|missing_file_path.",
|
|
76338
77014
|
"",
|
|
76339
|
-
"Still exit 0 (nothing to govern):
|
|
77015
|
+
"Still exit 0 (nothing to govern): not-governed path (one stderr line), identical content, non-governed tool.",
|
|
76340
77016
|
"",
|
|
76341
77017
|
"CONTINUE_WITH_MONITORING: allow only if the host asserts a sink",
|
|
76342
77018
|
" (CODERIFTS_MONITORING_SINK_WIRED=1|true or git config coderifts.monitoringSinkWired).",
|
|
@@ -76344,8 +77020,11 @@ var require_claude_hook = __commonJS({
|
|
|
76344
77020
|
"",
|
|
76345
77021
|
"CODERIFTS_STRICT=1|true: same fail-closed as default; cannot be weakened by ADVISORY.",
|
|
76346
77022
|
"",
|
|
76347
|
-
"
|
|
76348
|
-
"
|
|
77023
|
+
"Governed paths (additive; configuring one path never drops the defaults):",
|
|
77024
|
+
" default family: OpenAPI/Swagger, GraphQL, *.proto, AsyncAPI, MCP manifest, tool-schema.json",
|
|
77025
|
+
" git config --add coderifts.specPath <path-or-glob> # extra includes",
|
|
77026
|
+
" git config --add coderifts.specPathExclude <path-or-glob> # opt out one path",
|
|
77027
|
+
" Not-governed path: exit 0 and one stderr line `coderifts claude-hook: not governed: <path>`.",
|
|
76349
77028
|
"",
|
|
76350
77029
|
"Baseline at PreToolUse: before = current file on disk (pre-edit state \u2014 the tool has",
|
|
76351
77030
|
"not written yet). after = proposed content from tool_input (Write: content; Edit/MultiEdit:",
|
|
@@ -76473,10 +77152,41 @@ var require_claude_hook = __commonJS({
|
|
|
76473
77152
|
return readGitConfig("coderifts.apiKey", deps);
|
|
76474
77153
|
}
|
|
76475
77154
|
function resolveSpecPath(deps = {}) {
|
|
77155
|
+
const extras = readGitConfigAll("coderifts.specPath", deps);
|
|
77156
|
+
if (extras.length) return extras[0];
|
|
76476
77157
|
const fromGit = readGitConfig("coderifts.specPath", deps);
|
|
76477
|
-
if (fromGit) return fromGit;
|
|
77158
|
+
if (fromGit) return splitConfigValues(fromGit)[0] || DEFAULT_SPEC_PATH;
|
|
76478
77159
|
return DEFAULT_SPEC_PATH;
|
|
76479
77160
|
}
|
|
77161
|
+
function splitConfigValues(raw) {
|
|
77162
|
+
return String(raw || "").split(/[\n,]/).map((s) => s.trim()).filter(Boolean);
|
|
77163
|
+
}
|
|
77164
|
+
function readGitConfigAll(key, deps = {}) {
|
|
77165
|
+
if (typeof deps.readGitConfigAll === "function") {
|
|
77166
|
+
const v = deps.readGitConfigAll(key);
|
|
77167
|
+
if (Array.isArray(v)) return v.flatMap(splitConfigValues);
|
|
77168
|
+
return splitConfigValues(v);
|
|
77169
|
+
}
|
|
77170
|
+
const run = deps.execSync || execSync;
|
|
77171
|
+
const cwd = deps.cwd || process.cwd();
|
|
77172
|
+
try {
|
|
77173
|
+
const v = run(`git config --get-all ${key}`, {
|
|
77174
|
+
encoding: "utf8",
|
|
77175
|
+
cwd,
|
|
77176
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
77177
|
+
});
|
|
77178
|
+
return splitConfigValues(v);
|
|
77179
|
+
} catch {
|
|
77180
|
+
const one = readGitConfig(key, deps);
|
|
77181
|
+
return one ? splitConfigValues(one) : [];
|
|
77182
|
+
}
|
|
77183
|
+
}
|
|
77184
|
+
function resolveSpecIncludes(deps = {}) {
|
|
77185
|
+
return readGitConfigAll("coderifts.specPath", deps);
|
|
77186
|
+
}
|
|
77187
|
+
function resolveSpecExcludes(deps = {}) {
|
|
77188
|
+
return readGitConfigAll("coderifts.specPathExclude", deps);
|
|
77189
|
+
}
|
|
76480
77190
|
var GOVERNED_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "multiedit", "multi_edit"]);
|
|
76481
77191
|
function isGovernedTool(name) {
|
|
76482
77192
|
return GOVERNED_TOOLS.has(String(name || "").toLowerCase());
|
|
@@ -76551,6 +77261,75 @@ var require_claude_hook = __commonJS({
|
|
|
76551
77261
|
}
|
|
76552
77262
|
return false;
|
|
76553
77263
|
}
|
|
77264
|
+
function globToRegExp(pattern) {
|
|
77265
|
+
const src = String(pattern).replace(/\\/g, "/");
|
|
77266
|
+
let out = "^";
|
|
77267
|
+
for (let i = 0; i < src.length; ) {
|
|
77268
|
+
if (src[i] === "*" && src[i + 1] === "*") {
|
|
77269
|
+
if (src[i + 2] === "/") {
|
|
77270
|
+
out += "(?:.*/)?";
|
|
77271
|
+
i += 3;
|
|
77272
|
+
} else {
|
|
77273
|
+
out += ".*";
|
|
77274
|
+
i += 2;
|
|
77275
|
+
}
|
|
77276
|
+
} else if (src[i] === "*") {
|
|
77277
|
+
out += "[^/]*";
|
|
77278
|
+
i += 1;
|
|
77279
|
+
} else if (src[i] === "?") {
|
|
77280
|
+
out += "[^/]";
|
|
77281
|
+
i += 1;
|
|
77282
|
+
} else {
|
|
77283
|
+
out += src[i].replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
77284
|
+
i += 1;
|
|
77285
|
+
}
|
|
77286
|
+
}
|
|
77287
|
+
out += "$";
|
|
77288
|
+
return new RegExp(out, "i");
|
|
77289
|
+
}
|
|
77290
|
+
function matchGlob(pattern, value) {
|
|
77291
|
+
if (!pattern || value == null) return false;
|
|
77292
|
+
return globToRegExp(pattern).test(String(value).replace(/\\/g, "/"));
|
|
77293
|
+
}
|
|
77294
|
+
function normalizeToolPath(filePath, cwd) {
|
|
77295
|
+
let p = String(filePath || "").replace(/\\/g, "/");
|
|
77296
|
+
while (p.startsWith("./")) p = p.slice(2);
|
|
77297
|
+
const root = String(cwd || "").replace(/\\/g, "/").replace(/\/$/, "");
|
|
77298
|
+
if (root && (p === root || p.startsWith(`${root}/`))) {
|
|
77299
|
+
p = p.slice(root.length).replace(/^\//, "");
|
|
77300
|
+
}
|
|
77301
|
+
return p;
|
|
77302
|
+
}
|
|
77303
|
+
function isDetectorsExcludedDir(rel) {
|
|
77304
|
+
const s = `/${String(rel).replace(/\\/g, "/").toLowerCase()}/`;
|
|
77305
|
+
return s.includes("/node_modules/") || s.includes("/vendor/");
|
|
77306
|
+
}
|
|
77307
|
+
function patternLooksLikeGlob(pattern) {
|
|
77308
|
+
return /[*?]/.test(String(pattern || ""));
|
|
77309
|
+
}
|
|
77310
|
+
function matchesPattern(filePath, rel, pattern) {
|
|
77311
|
+
if (!pattern) return false;
|
|
77312
|
+
if (patternLooksLikeGlob(pattern)) {
|
|
77313
|
+
return matchGlob(pattern, rel) || matchGlob(pattern, filePath);
|
|
77314
|
+
}
|
|
77315
|
+
return isSpecPath(filePath, pattern) || isSpecPath(rel, pattern);
|
|
77316
|
+
}
|
|
77317
|
+
function matchesAnyPattern(filePath, rel, patterns) {
|
|
77318
|
+
for (const p of patterns || []) {
|
|
77319
|
+
if (matchesPattern(filePath, rel, p)) return true;
|
|
77320
|
+
}
|
|
77321
|
+
return false;
|
|
77322
|
+
}
|
|
77323
|
+
function isGovernedPath(filePath, deps = {}) {
|
|
77324
|
+
if (!filePath) return false;
|
|
77325
|
+
const rel = normalizeToolPath(filePath, deps.cwd);
|
|
77326
|
+
const extras = resolveSpecIncludes(deps);
|
|
77327
|
+
const excludes = resolveSpecExcludes(deps);
|
|
77328
|
+
if (matchesAnyPattern(filePath, rel, excludes)) return false;
|
|
77329
|
+
if (matchesAnyPattern(filePath, rel, extras)) return true;
|
|
77330
|
+
if (isDetectorsExcludedDir(rel)) return false;
|
|
77331
|
+
return DEFAULT_SPEC_GLOBS.some((g) => matchGlob(g, rel) || matchGlob(g, String(filePath).replace(/\\/g, "/")));
|
|
77332
|
+
}
|
|
76554
77333
|
function deriveAfterContent(toolName, toolInput, diskBefore) {
|
|
76555
77334
|
const name = String(toolName || "").toLowerCase();
|
|
76556
77335
|
if (name === "write") {
|
|
@@ -76779,8 +77558,9 @@ var require_claude_hook = __commonJS({
|
|
|
76779
77558
|
return emitTerminal({ exitCode: 2, reason: "missing_file_path" });
|
|
76780
77559
|
}
|
|
76781
77560
|
filePathKnown = filePath;
|
|
76782
|
-
|
|
76783
|
-
|
|
77561
|
+
if (!isGovernedPath(filePath, { ...deps, cwd })) {
|
|
77562
|
+
const rel = normalizeToolPath(filePath, cwd);
|
|
77563
|
+
errLog(`coderifts claude-hook: not governed: ${rel || filePath}`);
|
|
76784
77564
|
logEv({ type: "detection_skip", signals: ["not_spec_path"], tool, path: filePath });
|
|
76785
77565
|
return emitTerminal({ exitCode: 0, reason: "not_spec_path" });
|
|
76786
77566
|
}
|
|
@@ -76961,12 +77741,18 @@ var require_claude_hook = __commonJS({
|
|
|
76961
77741
|
isGovernedTool,
|
|
76962
77742
|
coerceToolInput,
|
|
76963
77743
|
isSpecPath,
|
|
77744
|
+
isGovernedPath,
|
|
77745
|
+
matchGlob,
|
|
77746
|
+
normalizeToolPath,
|
|
76964
77747
|
deriveAfterContent,
|
|
76965
77748
|
mapDecisionSeverity,
|
|
76966
77749
|
renderDecisionWhy,
|
|
76967
77750
|
resolveApiKey,
|
|
76968
77751
|
resolveSpecPath,
|
|
77752
|
+
resolveSpecIncludes,
|
|
77753
|
+
resolveSpecExcludes,
|
|
76969
77754
|
readGitConfig,
|
|
77755
|
+
readGitConfigAll,
|
|
76970
77756
|
isEnvFlag,
|
|
76971
77757
|
isStrictMode,
|
|
76972
77758
|
isAdvisoryMode,
|
|
@@ -76974,6 +77760,7 @@ var require_claude_hook = __commonJS({
|
|
|
76974
77760
|
failClosedOrAdvisory,
|
|
76975
77761
|
softOrStrictBlock,
|
|
76976
77762
|
DEFAULT_SPEC_PATH,
|
|
77763
|
+
DEFAULT_SPEC_GLOBS,
|
|
76977
77764
|
CLOSED_ACTIONS,
|
|
76978
77765
|
USAGE,
|
|
76979
77766
|
appendGuardEventLog,
|
|
@@ -158775,7 +159562,7 @@ var require_rateLimit = __commonJS({
|
|
|
158775
159562
|
var ipDailyStore = /* @__PURE__ */ new Map();
|
|
158776
159563
|
var apiKeyMinuteStore = /* @__PURE__ */ new Map();
|
|
158777
159564
|
var ipAgentMinuteStore = /* @__PURE__ */ new Map();
|
|
158778
|
-
var AGENT_PUBLIC_ENDPOINTS = ["/api/v1/demo", "/api/v1/public/preflight", "/api/v1/public/actionguard-check", "/api/v1/public/migraguard-check", "/api/v1/badge/agent-readiness"];
|
|
159565
|
+
var AGENT_PUBLIC_ENDPOINTS = ["/api/v1/demo", "/api/v1/public/preflight", "/api/v1/public/actionguard-check", "/api/v1/public/migraguard-check", "/api/v1/badge/agent-readiness", "/snippets"];
|
|
158779
159566
|
var AGENT_IP_MINUTE_LIMIT = 60;
|
|
158780
159567
|
var ANONYMOUS_DAILY_LIMIT = 50;
|
|
158781
159568
|
var API_KEY_MINUTE_LIMIT = 100;
|
|
@@ -201561,7 +202348,120 @@ var require_asyncapi_diff = __commonJS({
|
|
|
201561
202348
|
channels[channelName] = { operations };
|
|
201562
202349
|
}
|
|
201563
202350
|
}
|
|
201564
|
-
return { channels };
|
|
202351
|
+
return { channels, root: parsed };
|
|
202352
|
+
}
|
|
202353
|
+
function stillHasRef(node) {
|
|
202354
|
+
return !!(node && typeof node === "object" && typeof node.$ref === "string" && !node.properties);
|
|
202355
|
+
}
|
|
202356
|
+
function comparePayload(basePayload, headPayload, pathPrefix, messageId, baseRoot, headRoot, addBreakingChange, addNonBreakingChange) {
|
|
202357
|
+
const baseResolved = resolveLocalRef(baseRoot, basePayload, []);
|
|
202358
|
+
const headResolved = resolveLocalRef(headRoot, headPayload, []);
|
|
202359
|
+
if (stillHasRef(baseResolved) || stillHasRef(headResolved)) {
|
|
202360
|
+
const ref = stillHasRef(baseResolved) && baseResolved.$ref || stillHasRef(headResolved) && headResolved.$ref || "";
|
|
202361
|
+
addNonBreakingChange(
|
|
202362
|
+
"PAYLOAD_REF_UNCOMPARED",
|
|
202363
|
+
pathPrefix,
|
|
202364
|
+
`Payload at '${pathPrefix}' uses unresolved $ref '${ref}' and was not compared.`
|
|
202365
|
+
);
|
|
202366
|
+
return;
|
|
202367
|
+
}
|
|
202368
|
+
if (!baseResolved || !headResolved || typeof baseResolved !== "object" || typeof headResolved !== "object") {
|
|
202369
|
+
return;
|
|
202370
|
+
}
|
|
202371
|
+
const baseProps = baseResolved.properties || {};
|
|
202372
|
+
const headProps = headResolved.properties || {};
|
|
202373
|
+
const baseReq = new Set(Array.isArray(baseResolved.required) ? baseResolved.required : []);
|
|
202374
|
+
const headReq = new Set(Array.isArray(headResolved.required) ? headResolved.required : []);
|
|
202375
|
+
for (const fieldName of headReq) {
|
|
202376
|
+
if (baseReq.has(fieldName)) continue;
|
|
202377
|
+
if (baseProps[fieldName]) {
|
|
202378
|
+
addBreakingChange(
|
|
202379
|
+
"PAYLOAD_FIELD_NOW_REQUIRED",
|
|
202380
|
+
`${pathPrefix}.${fieldName}`,
|
|
202381
|
+
`Payload field '${fieldName}' in message '${messageId}' changed from optional to required.`
|
|
202382
|
+
);
|
|
202383
|
+
} else {
|
|
202384
|
+
addBreakingChange(
|
|
202385
|
+
"REQUIRED_PAYLOAD_FIELD_ADDED",
|
|
202386
|
+
`${pathPrefix}.${fieldName}`,
|
|
202387
|
+
`Required payload field '${fieldName}' was added to message '${messageId}'.`
|
|
202388
|
+
);
|
|
202389
|
+
}
|
|
202390
|
+
}
|
|
202391
|
+
for (const fieldName of baseReq) {
|
|
202392
|
+
if (!headReq.has(fieldName) && headProps[fieldName]) {
|
|
202393
|
+
addNonBreakingChange(
|
|
202394
|
+
"PAYLOAD_FIELD_NOW_OPTIONAL",
|
|
202395
|
+
`${pathPrefix}.${fieldName}`,
|
|
202396
|
+
`Payload field '${fieldName}' in message '${messageId}' changed from required to optional.`
|
|
202397
|
+
);
|
|
202398
|
+
}
|
|
202399
|
+
}
|
|
202400
|
+
for (const fieldName in baseProps) {
|
|
202401
|
+
const baseField = resolveLocalRef(baseRoot, baseProps[fieldName], []);
|
|
202402
|
+
const headFieldRaw = headProps[fieldName];
|
|
202403
|
+
if (!headFieldRaw) {
|
|
202404
|
+
addBreakingChange(
|
|
202405
|
+
"PAYLOAD_FIELD_REMOVED",
|
|
202406
|
+
`${pathPrefix}.${fieldName}`,
|
|
202407
|
+
`Payload field '${fieldName}' was removed from message '${messageId}'.`
|
|
202408
|
+
);
|
|
202409
|
+
continue;
|
|
202410
|
+
}
|
|
202411
|
+
const headField = resolveLocalRef(headRoot, headFieldRaw, []);
|
|
202412
|
+
if (stillHasRef(baseField) || stillHasRef(headField)) {
|
|
202413
|
+
const ref = stillHasRef(baseField) && baseField.$ref || stillHasRef(headField) && headField.$ref || "";
|
|
202414
|
+
addNonBreakingChange(
|
|
202415
|
+
"PAYLOAD_REF_UNCOMPARED",
|
|
202416
|
+
`${pathPrefix}.${fieldName}`,
|
|
202417
|
+
`Payload field '${fieldName}' in message '${messageId}' uses unresolved $ref '${ref}' and was not compared.`
|
|
202418
|
+
);
|
|
202419
|
+
continue;
|
|
202420
|
+
}
|
|
202421
|
+
if (baseField && headField && baseField.type !== headField.type) {
|
|
202422
|
+
addBreakingChange(
|
|
202423
|
+
"PAYLOAD_FIELD_TYPE_CHANGED",
|
|
202424
|
+
`${pathPrefix}.${fieldName}`,
|
|
202425
|
+
`Payload field '${fieldName}' in message '${messageId}' changed type from '${baseField.type}' to '${headField.type}'.`
|
|
202426
|
+
);
|
|
202427
|
+
continue;
|
|
202428
|
+
}
|
|
202429
|
+
if (baseField && headField && Array.isArray(baseField.enum) && Array.isArray(headField.enum)) {
|
|
202430
|
+
for (const val of baseField.enum) {
|
|
202431
|
+
if (!headField.enum.includes(val)) {
|
|
202432
|
+
addBreakingChange(
|
|
202433
|
+
"ENUM_VALUE_REMOVED",
|
|
202434
|
+
`${pathPrefix}.${fieldName}.${val}`,
|
|
202435
|
+
`Enum value '${val}' was removed from field '${fieldName}' in message '${messageId}'.`
|
|
202436
|
+
);
|
|
202437
|
+
}
|
|
202438
|
+
}
|
|
202439
|
+
for (const val of headField.enum) {
|
|
202440
|
+
if (!baseField.enum.includes(val)) {
|
|
202441
|
+
addNonBreakingChange(
|
|
202442
|
+
"ENUM_VALUE_ADDED",
|
|
202443
|
+
`${pathPrefix}.${fieldName}.${val}`,
|
|
202444
|
+
`New enum value '${val}' was added to field '${fieldName}' in message '${messageId}'.`
|
|
202445
|
+
);
|
|
202446
|
+
}
|
|
202447
|
+
}
|
|
202448
|
+
}
|
|
202449
|
+
if (baseField && headField && (baseField.properties || headField.properties || baseField.type === "object" || headField.type === "object")) {
|
|
202450
|
+
comparePayload(baseField, headField, `${pathPrefix}.${fieldName}`, messageId, baseRoot, headRoot, addBreakingChange, addNonBreakingChange);
|
|
202451
|
+
}
|
|
202452
|
+
}
|
|
202453
|
+
for (const fieldName in headProps) {
|
|
202454
|
+
if (!baseProps[fieldName]) {
|
|
202455
|
+
const addedIsRequired = headReq.has(fieldName);
|
|
202456
|
+
if (!addedIsRequired) {
|
|
202457
|
+
addNonBreakingChange(
|
|
202458
|
+
"PAYLOAD_FIELD_ADDED",
|
|
202459
|
+
`${pathPrefix}.${fieldName}`,
|
|
202460
|
+
`New optional payload field '${fieldName}' was added to message '${messageId}'.`
|
|
202461
|
+
);
|
|
202462
|
+
}
|
|
202463
|
+
}
|
|
202464
|
+
}
|
|
201565
202465
|
}
|
|
201566
202466
|
function diffAsyncAPISchemas(base_schema_content, head_schema_content) {
|
|
201567
202467
|
const base = parseAsyncAPI(base_schema_content);
|
|
@@ -201601,42 +202501,17 @@ var require_asyncapi_diff = __commonJS({
|
|
|
201601
202501
|
}
|
|
201602
202502
|
const basePayload = baseMessage.payload;
|
|
201603
202503
|
const headPayload = headMessage.payload;
|
|
201604
|
-
if (basePayload && headPayload
|
|
201605
|
-
|
|
201606
|
-
|
|
201607
|
-
|
|
201608
|
-
|
|
201609
|
-
|
|
201610
|
-
|
|
201611
|
-
|
|
201612
|
-
|
|
201613
|
-
|
|
201614
|
-
|
|
201615
|
-
addBreakingChange("ENUM_VALUE_REMOVED", `${channelName}.${opType}.${messageId}.${fieldName}.${val}`, `Enum value '${val}' was removed from field '${fieldName}' in message '${messageId}'.`);
|
|
201616
|
-
}
|
|
201617
|
-
}
|
|
201618
|
-
for (const val of headField.enum) {
|
|
201619
|
-
if (!baseField.enum.includes(val)) {
|
|
201620
|
-
addNonBreakingChange("ENUM_VALUE_ADDED", `${channelName}.${opType}.${messageId}.${fieldName}.${val}`, `New enum value '${val}' was added to field '${fieldName}' in message '${messageId}'.`);
|
|
201621
|
-
}
|
|
201622
|
-
}
|
|
201623
|
-
}
|
|
201624
|
-
}
|
|
201625
|
-
for (const fieldName in headPayload.properties) {
|
|
201626
|
-
if (!basePayload.properties[fieldName]) {
|
|
201627
|
-
const addedIsRequired = Array.isArray(headPayload.required) && headPayload.required.includes(fieldName);
|
|
201628
|
-
if (!addedIsRequired) {
|
|
201629
|
-
addNonBreakingChange("PAYLOAD_FIELD_ADDED", `${channelName}.${opType}.${messageId}.${fieldName}`, `New optional payload field '${fieldName}' was added to message '${messageId}'.`);
|
|
201630
|
-
}
|
|
201631
|
-
}
|
|
201632
|
-
}
|
|
201633
|
-
if (headPayload.required && Array.isArray(headPayload.required)) {
|
|
201634
|
-
for (const requiredField of headPayload.required) {
|
|
201635
|
-
if (!basePayload.required || !basePayload.required.includes(requiredField)) {
|
|
201636
|
-
addBreakingChange("REQUIRED_PAYLOAD_FIELD_ADDED", `${channelName}.${opType}.${messageId}.${requiredField}`, `Required payload field '${requiredField}' was added to message '${messageId}'.`);
|
|
201637
|
-
}
|
|
201638
|
-
}
|
|
201639
|
-
}
|
|
202504
|
+
if (basePayload && headPayload) {
|
|
202505
|
+
comparePayload(
|
|
202506
|
+
basePayload,
|
|
202507
|
+
headPayload,
|
|
202508
|
+
`${channelName}.${opType}.${messageId}`,
|
|
202509
|
+
messageId,
|
|
202510
|
+
base.root,
|
|
202511
|
+
head.root,
|
|
202512
|
+
addBreakingChange,
|
|
202513
|
+
addNonBreakingChange
|
|
202514
|
+
);
|
|
201640
202515
|
}
|
|
201641
202516
|
}
|
|
201642
202517
|
for (const messageId in headOperation.messages) {
|
|
@@ -202829,6 +203704,7 @@ var require_response_envelope = __commonJS({
|
|
|
202829
203704
|
return response;
|
|
202830
203705
|
}
|
|
202831
203706
|
response.control_envelope = buildControlEnvelope(response, authzContext);
|
|
203707
|
+
if (isCoverageFailClosed(response)) response.safe_for_agent = false;
|
|
202832
203708
|
response.analysis = buildAnalysisTier(response);
|
|
202833
203709
|
try {
|
|
202834
203710
|
response.analysis.remediations = buildRemediations(response);
|
|
@@ -220480,6 +221356,15 @@ var require_persist_decision = __commonJS({
|
|
|
220480
221356
|
return null;
|
|
220481
221357
|
}
|
|
220482
221358
|
}
|
|
221359
|
+
function persistMeta(decisionId) {
|
|
221360
|
+
if (typeof decisionId === "string" && decisionId.length > 0) {
|
|
221361
|
+
return { stored: true };
|
|
221362
|
+
}
|
|
221363
|
+
return {
|
|
221364
|
+
stored: false,
|
|
221365
|
+
reason: persistenceEnabled() ? "storage_unavailable" : "persistence_disabled"
|
|
221366
|
+
};
|
|
221367
|
+
}
|
|
220483
221368
|
var AFTER_HEX_RE = /^[0-9a-f]{64}$/;
|
|
220484
221369
|
function normalizeAfterHex(raw) {
|
|
220485
221370
|
if (raw == null) return "";
|
|
@@ -220862,6 +221747,8 @@ var require_persist_decision = __commonJS({
|
|
|
220862
221747
|
}
|
|
220863
221748
|
module2.exports = {
|
|
220864
221749
|
persistDecision,
|
|
221750
|
+
persistMeta,
|
|
221751
|
+
persistenceEnabled,
|
|
220865
221752
|
persistAuthorizedPaths,
|
|
220866
221753
|
findDecisionsByAfterHash,
|
|
220867
221754
|
getAuthorizedPathsCollectingSince,
|
|
@@ -223317,82 +224204,7 @@ var require_mcp_streamable = __commonJS({
|
|
|
223317
224204
|
});
|
|
223318
224205
|
next();
|
|
223319
224206
|
});
|
|
223320
|
-
var DESC_PREFLIGHT_CHANGE_SET =
|
|
223321
|
-
risk score and breaking-change analysis \u2014 plus, on the AUTHORIZE path only, a governance decision
|
|
223322
|
-
(ALLOW / WARN / REQUIRE_APPROVAL / BLOCK) and a signed chain-receipt when applicable. ANALYZE
|
|
223323
|
-
returns informational risk only: analysis_outcome, may_execute:false, no decision, no receipt.
|
|
223324
|
-
|
|
223325
|
-
Requires a pending base\u2192head (before/after) contract change you are about to
|
|
223326
|
-
act on (merge, deploy, publish, or register tools). No pending change set \u2192
|
|
223327
|
-
do not call this tool.
|
|
223328
|
-
|
|
223329
|
-
Use this when:
|
|
223330
|
-
- You are about to merge, push, deploy, publish, or register/expose agent tools,
|
|
223331
|
-
AND the change includes \u22651 contract artifact (OpenAPI/Swagger, GraphQL SDL,
|
|
223332
|
-
gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas: type=agent_tools,
|
|
223333
|
-
including before re-registering tools with a runtime).
|
|
223334
|
-
- You have (or can assemble) FULL base and head for every changed contract
|
|
223335
|
-
artifact in this set \u2014 not a single-file subset when other contract files also
|
|
223336
|
-
change.
|
|
223337
|
-
- You need a NEW decision for the CURRENT change; you do not already hold a
|
|
223338
|
-
currently-valid receipt for this exact target/operation.
|
|
223339
|
-
- You hold a receipt for a different operation or target than the act you will
|
|
223340
|
-
perform (e.g. ALLOW for merge, now deploying). A receipt authorizes ONE
|
|
223341
|
-
operation: a merge receipt does not authorize a deploy. Run a NEW preflight
|
|
223342
|
-
with context.operation set to that operation (deploy, publish); a
|
|
223343
|
-
differently-scoped receipt is not reusable authorization and will fail at
|
|
223344
|
-
the gate.
|
|
223345
|
-
|
|
223346
|
-
Do not use when:
|
|
223347
|
-
- The change is documentation-only (README, guides, comments) with no contract
|
|
223348
|
-
artifact content change \u2014 do not call any CodeRifts tool.
|
|
223349
|
-
- You already hold a signed receipt and only need to check it is authentic and
|
|
223350
|
-
currently valid \u2014 use coderifts.verify_receipt instead.
|
|
223351
|
-
- You need details of a PREVIOUS decision by decision_id \u2014 use
|
|
223352
|
-
coderifts.get_decision_details instead.
|
|
223353
|
-
- You want a static 0\u2013100 "agent readiness" score for one OpenAPI/MCP file and
|
|
223354
|
-
there is no pending base\u2192head mutate \u2014 use coderifts.agent_readiness_score
|
|
223355
|
-
(advanced / opt-in; not one of the three default tools). If that tool is not
|
|
223356
|
-
in your available list, call none of the CodeRifts tools; do not substitute
|
|
223357
|
-
preflight_change_set.
|
|
223358
|
-
- You cannot supply both before and after (or base and head) for the artifacts
|
|
223359
|
-
that change \u2014 fix the change set first; do not invent empty before specs.
|
|
223360
|
-
|
|
223361
|
-
Inputs: list of artifacts, each with type, before, after (or equivalent), plus
|
|
223362
|
-
optional operation (merge|deploy|tool_call|publish), environment/stakes, and
|
|
223363
|
-
context. Opt-in derivation:"server" (proven tenant\u2194repo binding + context.repository
|
|
223364
|
-
+ base + head): omit artifacts[] \u2014 the server lists the contract-class set via the
|
|
223365
|
-
SCM provider for the proven binding (GitHub App Compare, or GitLab/Bitbucket Compare
|
|
223366
|
-
with a per-request X-Coderifts-Scm-Token, never stored; completeness_mode
|
|
223367
|
-
SERVER_DERIVED). Default (flag absent) is unchanged. Returns decision,
|
|
223368
|
-
execution_action, risk fields, and chain_receipt when issued.
|
|
223369
|
-
|
|
223370
|
-
CHANGE SOURCE \u2014 EXACTLY ONE, ENFORCED AT THE ROUTE (400), NOT BY THIS SCHEMA.
|
|
223371
|
-
Supply either artifacts[] OR derivation:"server". All three of these are rejected
|
|
223372
|
-
with HTTP 400 INVALID_INPUT, on analyze and on authorize alike:
|
|
223373
|
-
\u2022 neither artifacts[] nor derivation \u2192 "artifacts must be a non-empty array"
|
|
223374
|
-
\u2022 authorize with context.operation but no change source \u2192 same 400
|
|
223375
|
-
\u2022 artifacts[] together with derivation:"server" \u2192 "derivation:"server" forbids
|
|
223376
|
-
caller-supplied artifacts[] \u2014 one source of truth per request"
|
|
223377
|
-
This constraint is NOT expressible in the schema you are reading: a top-level
|
|
223378
|
-
oneOf/allOf union is rejected by at least one major MCP client (measured), so the
|
|
223379
|
-
schema stays permissive and the route is the enforcement point. Do not read schema
|
|
223380
|
-
acceptance as request validity \u2014 verified live against these exact three shapes on
|
|
223381
|
-
2026-08-26, over REST and over MCP tools/call (isError:true on all three).
|
|
223382
|
-
|
|
223383
|
-
Mode (required): pass preflight_mode. Use "analyze" for informational risk only
|
|
223384
|
-
(returns analysis_outcome with may_execute:false, no decision/execution_action/
|
|
223385
|
-
safe_for_agent, no receipt). Use "authorize" for the operation-bound path that can
|
|
223386
|
-
mint a receipt (requires context.operation: merge|deploy|publish|tool_call). Under
|
|
223387
|
-
Decision Spec 2.0 the mode is mandatory; omission is an error unless a legacy
|
|
223388
|
-
decision_spec_version "1.0" pin is set.
|
|
223389
|
-
|
|
223390
|
-
Branch on execution_action only (CONTINUE | CONTINUE_WITH_MONITORING | REQUEST_APPROVAL | STOP).
|
|
223391
|
-
On non-CONTINUE authorize responses, control_envelope.next_agent_step is a structured
|
|
223392
|
-
remediation SUGGESTION the agent MAY follow (action, reason, resume_condition, then_call).
|
|
223393
|
-
It is NOT permission and NOT a control-flow override \u2014 still branch on execution_action.
|
|
223394
|
-
On CONTINUE / CONTINUE_WITH_MONITORING, next_agent_step is null (no remediation step).
|
|
223395
|
-
Human tier remains human_report.next_steps_prose (same source; prose, not machine).`;
|
|
224207
|
+
var DESC_PREFLIGHT_CHANGE_SET = "Use this when: a change set of contract artifacts modifies OpenAPI, GraphQL, protobuf, AsyncAPI, MCP manifests, or agent tool schemas before merge, deploy, publish, or tool registration. Do not call for documentation-only changes, static readiness scoring, or receipt verification. Use analyze for risk only; authorize requires context.operation for permission. For receipt verification use coderifts.verify_receipt instead; for details of a past decision use coderifts.get_decision_details instead.";
|
|
223396
224208
|
var DESC_VERIFY_RECEIPT = `Verify a CodeRifts signed chain-receipt you ALREADY HOLD: cryptographic
|
|
223397
224209
|
authenticity (signature + key id), body binding, and \u2014 when lifecycle indices
|
|
223398
224210
|
are available \u2014 whether it is currently valid authorization (not expired,
|
|
@@ -223725,7 +224537,11 @@ next_agent_step is a suggestion, not permission.`;
|
|
|
223725
224537
|
}
|
|
223726
224538
|
}
|
|
223727
224539
|
},
|
|
223728
|
-
|
|
224540
|
+
// Authorize CREATES an authorization (receipt / grant). readOnlyHint:true over-stated
|
|
224541
|
+
// the mixed tool (roadmap 1212). Analyze is still informational (no receipt) — that
|
|
224542
|
+
// is the mode, not this annotation. Split into two tools is deferred: then_call in
|
|
224543
|
+
// response-envelope.js still names preflight_change_set, and the canonical set is 3.
|
|
224544
|
+
annotations: { readOnlyHint: false, openWorldHint: false }
|
|
223729
224545
|
},
|
|
223730
224546
|
{
|
|
223731
224547
|
name: "get_decision_details",
|
|
@@ -224255,9 +225071,9 @@ var require_generate_surface_anchor = __commonJS({
|
|
|
224255
225071
|
var OUT = path.join(__dirname, "..", "src", "generated", "surface-anchor.json");
|
|
224256
225072
|
var ENDPOINT = "https://app.coderifts.com/mcp";
|
|
224257
225073
|
var VOLATILE_KEYS = Object.freeze([]);
|
|
224258
|
-
var SOURCE_REF = "https://raw.githubusercontent.com/coderifts/api-governance/surface-
|
|
224259
|
-
var SOURCE_REF_COMMIT = "
|
|
224260
|
-
var SOURCE_REF_STATUS = `PINNED TO ONE REVISION. source_ref is the wire-format tools[] as served, published in the public coderifts/api-governance repo at tag surface-
|
|
225074
|
+
var SOURCE_REF = "https://raw.githubusercontent.com/coderifts/api-governance/surface-c3ec5f69/tools.wire.v1.json";
|
|
225075
|
+
var SOURCE_REF_COMMIT = "2496038c4bca672e0e9730a8de92db34d0556bb5";
|
|
225076
|
+
var SOURCE_REF_STATUS = `PINNED TO ONE REVISION. source_ref is the wire-format tools[] as served, published in the public coderifts/api-governance repo at tag surface-c3ec5f69 (commit ${SOURCE_REF_COMMIT}). Verified at fill time: the file's own tools_sha256, its tools[] recomputed under the canonical rule in digest_input, and this anchor's tools_sha256 are the same value. HOW TO USE IT: fetch it, recompute the digest yourself, and compare it to tools_sha256 here. IF THEY DIFFER, TRUST NEITHER -- it means the surface moved and this ref was not re-tagged. A tag can be force-moved; the commit SHA above cannot, so pin the SHA URL if you want the stronger form. OUR OBLIGATION: every surface change requires a NEW tag and a NEW source_ref in this file. Skipping that leaves this field pointing at an old surface while still looking authoritative, which is worse than the null it replaced. HOW THE OBLIGATION IS ENFORCED, on both sides: this repo CI-runs generate-surface-anchor.js --check --verify-source-ref, which fetches the ref above, recomputes its digest under the rule in digest_input, and FAILS if it is stale, self-inconsistent, or its tag is gone. The target repo runs scripts/validate-tools-wire.mjs from its own npm test and a CI workflow -- on push, on PR, and daily, because the wire target can go stale without anything in that repo changing. Both SKIP LOUDLY rather than fail on a transport error, and both treat a 404 as a real verdict rather than a network problem. Neither this ref nor those gates is a root of trust: pin the digest at YOUR approval time -- see honesty.pin_at_approval_time.`;
|
|
224261
225077
|
var HONESTY = Object.freeze({
|
|
224262
225078
|
pins_bytes_not_behaviour: "This anchor pins BYTES, not behaviour. It says the tool text you received is the text that was published. It says nothing about whether the model read it, understood it, or obeyed it.",
|
|
224263
225079
|
scoped_to_its_profile: "This digest is scoped to the profile named above and to nothing else. The default-profile digest says NOTHING about the surface served with include_advanced_tools, which is a different tool set with a different digest. A hash without its profile does not identify a surface.",
|
|
@@ -224885,6 +225701,41 @@ var require_decision_result = __commonJS({
|
|
|
224885
225701
|
function envelopeSafeForAgent(decision) {
|
|
224886
225702
|
return decision === "ALLOW" || decision === "WARN";
|
|
224887
225703
|
}
|
|
225704
|
+
var SAFE_FOR_AGENT_SEMANTICS = Object.freeze({
|
|
225705
|
+
"decision_result.safe_for_agent": Object.freeze({
|
|
225706
|
+
question: "is the verdict ALLOW/WARN?",
|
|
225707
|
+
kind: "verdict",
|
|
225708
|
+
forced_false_by: Object.freeze([])
|
|
225709
|
+
}),
|
|
225710
|
+
safe_for_agent: Object.freeze({
|
|
225711
|
+
question: "is it actually safe to proceed?",
|
|
225712
|
+
kind: "defense_in_depth",
|
|
225713
|
+
note: "1227: the most-read (flat) field is now defense-in-depth, same as control_envelope. A naive agent reading it must not proceed on a coverage-gapped ALLOW. The raw verdict stays on decision_result \u2014 no information lost.",
|
|
225714
|
+
forced_false_by: Object.freeze([
|
|
225715
|
+
"decision BLOCK",
|
|
225716
|
+
"decision REQUIRE_APPROVAL",
|
|
225717
|
+
"degraded",
|
|
225718
|
+
"coverage_gap",
|
|
225719
|
+
"fallback_reason",
|
|
225720
|
+
"coverage_gap rule_id",
|
|
225721
|
+
"webhook_surface_unanalyzed"
|
|
225722
|
+
])
|
|
225723
|
+
}),
|
|
225724
|
+
"control_envelope.safe_for_agent": Object.freeze({
|
|
225725
|
+
question: "is it actually safe to proceed?",
|
|
225726
|
+
kind: "defense_in_depth",
|
|
225727
|
+
note: "the verdict AND the coverage check; this is the field to gate on",
|
|
225728
|
+
forced_false_by: Object.freeze([
|
|
225729
|
+
"degraded",
|
|
225730
|
+
"coverage_gap",
|
|
225731
|
+
"fallback_reason",
|
|
225732
|
+
"coverage_gap rule_id",
|
|
225733
|
+
"webhook_surface_unanalyzed"
|
|
225734
|
+
])
|
|
225735
|
+
}),
|
|
225736
|
+
invariant: "safe_for_agent == control_envelope.safe_for_agent <= decision_result.safe_for_agent",
|
|
225737
|
+
invariant_means: "defense-in-depth only tightens: true may become false, false never becomes true. The flat field equals control_envelope (1227)."
|
|
225738
|
+
});
|
|
224888
225739
|
function mapSeverity(sev) {
|
|
224889
225740
|
const up = String(sev || "").toUpperCase();
|
|
224890
225741
|
return EVIDENCE_SEVERITIES.includes(up) ? up : "MEDIUM";
|
|
@@ -225251,6 +226102,7 @@ var require_decision_result = __commonJS({
|
|
|
225251
226102
|
module2.exports = {
|
|
225252
226103
|
buildDecisionResultV1,
|
|
225253
226104
|
envelopeSafeForAgent,
|
|
226105
|
+
SAFE_FOR_AGENT_SEMANTICS,
|
|
225254
226106
|
proseToType,
|
|
225255
226107
|
toUtcSeconds,
|
|
225256
226108
|
computeBodyHash,
|
|
@@ -227107,10 +227959,10 @@ var require_gate_pin = __commonJS({
|
|
|
227107
227959
|
"src/generated/gate-pin.json"(exports2, module2) {
|
|
227108
227960
|
module2.exports = {
|
|
227109
227961
|
repo: "coderifts/contract-gate",
|
|
227110
|
-
sha: "
|
|
227111
|
-
tag: "v0.
|
|
227962
|
+
sha: "90de4be6641bbbc76b647d55bdec1e9019fd1d20",
|
|
227963
|
+
tag: "v0.7.0",
|
|
227112
227964
|
resolved_from: "https://github.com/coderifts/contract-gate refs/tags/v0",
|
|
227113
|
-
resolved_at: "2026-
|
|
227965
|
+
resolved_at: "2026-09-01T13:10:37Z",
|
|
227114
227966
|
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."
|
|
227115
227967
|
};
|
|
227116
227968
|
}
|
|
@@ -228786,13 +229638,13 @@ var require_agent_host_files_embedded = __commonJS({
|
|
|
228786
229638
|
".cursor/hooks.json"
|
|
228787
229639
|
]);
|
|
228788
229640
|
var AGENT_HOST_FILES = Object.freeze({
|
|
228789
|
-
"AGENTS.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts agent rules\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call
|
|
228790
|
-
"CLAUDE.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call
|
|
228791
|
-
".cursor/rules/coderifts.mdc": '---\ndescription: CodeRifts API governance \u2014 when to preflight and how to branch\nglobs:\nalwaysApply: true\n---\n\n<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call
|
|
228792
|
-
".github/copilot-instructions.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts instructions for GitHub Copilot\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call
|
|
228793
|
-
"coderifts-langgraph-policy.js": '// GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js\n// System policy string for a LangGraph (or similar) agent. Content is generated;\n// identical rule sentences to AGENTS.md / other formats.\n\'use strict\';\n\nmodule.exports = "Call `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\\n\\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\\n\\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\\n\\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\\n\\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\\n\\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not \\"proceed with caution\\" without monitoring.\\n\\nDo not call
|
|
228794
|
-
"openai-agent-instructions.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts agent instructions\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call
|
|
228795
|
-
"skills/api-governance/SKILL.md": '---\nname: api-governance\ndescription: Before merging or shipping any API or tool-contract change: preflight the change set, then branch on execution_action.\n---\n\n# CodeRifts API Governance\n\n<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call
|
|
229641
|
+
"AGENTS.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts agent rules\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
|
|
229642
|
+
"CLAUDE.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
|
|
229643
|
+
".cursor/rules/coderifts.mdc": '---\ndescription: CodeRifts API governance \u2014 when to preflight and how to branch\nglobs:\nalwaysApply: true\n---\n\n<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
|
|
229644
|
+
".github/copilot-instructions.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts instructions for GitHub Copilot\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
|
|
229645
|
+
"coderifts-langgraph-policy.js": '// GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js\n// System policy string for a LangGraph (or similar) agent. Content is generated;\n// identical rule sentences to AGENTS.md / other formats.\n\'use strict\';\n\nmodule.exports = "Call `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\\n\\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\\n\\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\\n\\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\\n\\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\\n\\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not \\"proceed with caution\\" without monitoring.\\n\\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\\n\\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\\n\\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\\n\\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\\n\\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\\n\\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\\n\\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\\n\\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\\n\\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\\n\\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\\n\\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\\n\\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\\n\\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\\n\\nWith a proven tenant\u2194repo binding you may request `derivation:\\"server\\"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\\n\\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say \\"authorized, commit not proven\\".";\n',
|
|
229646
|
+
"openai-agent-instructions.md": '<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\n# CodeRifts agent instructions\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
|
|
229647
|
+
"skills/api-governance/SKILL.md": '---\nname: api-governance\ndescription: Before merging or shipping any API or tool-contract change: preflight the change set, then branch on execution_action.\n---\n\n# CodeRifts API Governance\n\n<!-- GENERATED from CodeRifts agent-host-rule (single source). Do not edit rule sentences by hand; run: node scripts/generate-agent-host-files.js -->\n\nCall `preflight_change_set` before merge, deploy, publish, or tool registration when a contract artifact changed (OpenAPI/Swagger, GraphQL, gRPC/protobuf, AsyncAPI, MCP manifest, or agent tool schemas).\n\nSend the complete base-to-head change set: every changed contract artifact with full before and after content. Do not send a single-file subset when other contract files also change.\n\nBranch on `execution_action` only. Do not branch on `decision` and do not branch on `safe_for_agent` (not_for_control_flow_use_execution_action). Canonical `execution_action` values: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, STOP.\n\nAn unrecognised `execution_action` is not permission: fail closed (halt or re-preflight). Well-known code: `not_permission_fail_closed`.\n\nWhen `execution_action` is REQUEST_APPROVAL or STOP, surface the detected patterns and the blast radius, and propose the safer path \u2014 deprecate-then-remove, an additive change, or a new version \u2014 rather than shipping the break.\n\n`CONTINUE_WITH_MONITORING` requires a wired monitoring sink (`monitoringSinkWired`). It is not "proceed with caution" without monitoring.\n\nDo not call `preflight_change_set` for: a documentation-only change (README, guides, comments) with no contract artifact content change; a static readiness score (a different capability, not a change-set decision); or to verify a receipt you already hold (that is `verify_receipt` \u2014 see the companion-tools rule).\n\nIf you already hold a chain receipt and only need authenticity/lifecycle: `verify_receipt`. If you need a past decision by id: `get_decision_details`. Neither replaces preflight for a new change set.\n\nThe CodeRifts MCP server exposes exactly three tools \u2014 `preflight_change_set`, `verify_receipt`, `get_decision_details`. Do not invent or assume others.\n\nA receipt authorizes ONE operation: a merge receipt does not authorize a deploy. Before a different operation (deploy, publish), call `preflight_change_set` with `context.operation` set to that operation \u2014 reusing a differently-scoped receipt is not permitted and will fail at the gate.\n\nA stale or superseded receipt on a changed head requires a NEW preflight \u2014 `verify_receipt` cannot re-diff.\n\nFor mutating tools, put only the guarded version in the agent\'s tool table; keep the raw handler host-only and unreachable from that table. How you name tools is yours \u2014 this is a reachability property, not a product rename of host tools. CodeRifts cannot see or stop a raw call the host makes outside the table it returns; adopt this as a host convention, not as a guarantee from the package.\n\nCodeRifts reports a governance decision and `execution_action`; it does not by itself block merges. Blocking requires separate repository configuration (required status checks, enforcement) that this rule file does not set.\n\nTo act (mutate a contract, merge, deploy, or publish): call `preflight_change_set` with `preflight_mode` authorize. Analyze is informational \u2014 risk only, `may_execute` is always false \u2014 and is not permission. Read `execution_action` on the `decision_result` envelope.\n\nBefore acting under a held receipt: call `verify_receipt` with the intended `context` (operation, environment, repository, branch, pull_request) for THIS attempt. Do not act on a receipt whose scope does not match.\n\nAct only when `currently_authorized` is true (`control_envelope.receipt_view.currently_authorized`). A valid-looking token is not permission if `currently_authorized` is false or omitted.\n\nCommit / CAS evidence is a separate measurement (`commit_observation` on GuardOutcome). It is not a substitute for authorize + `currently_authorized`. Production hosts that want the fail-closed conjunction lock it with `profile: ENFORCING_STRICT` on withCodeRifts.\n\nIf the host requests an execution grant (opt-in `include_execution_grant`), the grant is bound to operation + target + after-payload (`scope_hash`) and is short-lived \u2014 never reuse it after the after-payload changes.\n\nAn ATOMIC-profile grant carries `state_nonce` and is single-use at the executor \u2014 if the executor has consumed the nonce, re-preflight; do not retry the same grant.\n\nWith a proven tenant\u2194repo binding you may request `derivation:"server"` instead of assembling `artifacts[]` yourself (`context.repository` + `context.base` + `context.head` required; caller-supplied artifacts are rejected on that path).\n\nA commit is only proven when an executor attestation verifies (customer-held executor key, `cas_evidence: executor_attested`); otherwise say "authorized, commit not proven".\n',
|
|
228796
229648
|
".claude/settings.json": '{\n "hooks": {\n "PreToolUse": [\n {\n "matcher": "Write|Edit|MultiEdit",\n "hooks": [\n {\n "type": "command",\n "command": "coderifts claude-hook",\n "timeout": 60\n }\n ]\n }\n ]\n }\n}\n',
|
|
228797
229649
|
".cursor/hooks.json": '{\n "version": 1,\n "hooks": {\n "preToolUse": [\n {\n "command": "coderifts cursor-hook",\n "matcher": "Write|Delete",\n "timeout": 60,\n "failClosed": true\n }\n ]\n }\n}\n'
|
|
228798
229650
|
});
|
|
@@ -228958,6 +229810,7 @@ ${USAGE}` };
|
|
|
228958
229810
|
var AGENT_SETUP_HOOK_WIRE_LINES = Object.freeze([
|
|
228959
229811
|
chalk.bold(" Claude Code hook (.claude/settings.json): fail-closed PreToolUse"),
|
|
228960
229812
|
chalk.dim(" matcher Write|Edit|MultiEdit \u2192 coderifts claude-hook (exit 2 = BLOCK)."),
|
|
229813
|
+
chalk.dim(" Path family: OpenAPI/Swagger, GraphQL, *.proto, AsyncAPI, MCP, tool-schema.json (plus git config coderifts.specPath; exclude via coderifts.specPathExclude)."),
|
|
228961
229814
|
chalk.dim(" Missing key / API down / unreadable spec \u2192 exit 2 (enforce_indeterminate), not ALLOW."),
|
|
228962
229815
|
chalk.dim(" Opt-out: CODERIFTS_ADVISORY=1|true restores soft-allow when governance could not run."),
|
|
228963
229816
|
chalk.dim(" CODERIFTS_STRICT=1 cannot be weakened by ADVISORY.")
|
|
@@ -229358,6 +230211,7 @@ exit 0
|
|
|
229358
230211
|
say(`Claude Code PreToolUse hook written to ${dest}`);
|
|
229359
230212
|
if (backedUp) say(`Backup: ${backedUp}`);
|
|
229360
230213
|
say("matcher Write|Edit|MultiEdit \u2192 coderifts claude-hook (exit 2 = BLOCK).");
|
|
230214
|
+
say("governs the contract path family (OpenAPI/Swagger, GraphQL, *.proto, AsyncAPI, MCP, tool-schema) plus git config coderifts.specPath; opt out one path with coderifts.specPathExclude.");
|
|
229361
230215
|
return { exitCode: 0, code: "OK", path: dest, backedUp, wrote: true };
|
|
229362
230216
|
}
|
|
229363
230217
|
var CURSOR_HOOK_BIN = "coderifts cursor-hook";
|
|
@@ -256034,10 +256888,12 @@ var require_github_workflow_pin = __commonJS({
|
|
|
256034
256888
|
"use strict";
|
|
256035
256889
|
var { STATUS } = require_github_enforcement();
|
|
256036
256890
|
var PIN_REASON = Object.freeze({
|
|
256037
|
-
/** The pinned sha is the
|
|
256891
|
+
/** The pinned sha is the head commit sha being merged — GitHub's field, grants PASS. */
|
|
256038
256892
|
WORKFLOW_SHA_MATCHES_HEAD: "workflow_sha_matches_head",
|
|
256039
256893
|
/** A pin exists, but it names bytes that are not what is at the head. */
|
|
256040
256894
|
WORKFLOW_SHA_STALE: "workflow_sha_stale",
|
|
256895
|
+
/** Pin equals the file blob SHA, not a commit. Named; does NOT grant PASS. */
|
|
256896
|
+
WORKFLOW_SHA_IS_BLOB: "workflow_sha_is_blob",
|
|
256041
256897
|
/** No sha in the rule — the ruleset names a path, so rewriting the file changes what runs. */
|
|
256042
256898
|
WORKFLOW_NOT_PINNED: "workflow_not_pinned",
|
|
256043
256899
|
/** We could not read the workflow file at the head, so no comparison is possible. */
|
|
@@ -256053,7 +256909,8 @@ var require_github_workflow_pin = __commonJS({
|
|
|
256053
256909
|
workflow_ref: null,
|
|
256054
256910
|
workflow_sha: null,
|
|
256055
256911
|
workflow_sha_matches_head: false,
|
|
256056
|
-
matched_against: null
|
|
256912
|
+
matched_against: null,
|
|
256913
|
+
grants_pass: false
|
|
256057
256914
|
};
|
|
256058
256915
|
if (!pin || !Array.isArray(pin.workflows) || pin.workflows.length === 0) {
|
|
256059
256916
|
return {
|
|
@@ -256091,14 +256948,26 @@ var require_github_workflow_pin = __commonJS({
|
|
|
256091
256948
|
}
|
|
256092
256949
|
const matchedBlob = sameSha(pinned.sha, blobSha);
|
|
256093
256950
|
const matchedCommit = sameSha(pinned.sha, headCommitSha);
|
|
256094
|
-
if (
|
|
256951
|
+
if (matchedCommit) {
|
|
256095
256952
|
return {
|
|
256096
256953
|
...fields,
|
|
256097
256954
|
status: STATUS.VERIFIED,
|
|
256098
256955
|
reason_code: PIN_REASON.WORKFLOW_SHA_MATCHES_HEAD,
|
|
256099
256956
|
workflow_sha_matches_head: true,
|
|
256100
|
-
matched_against:
|
|
256101
|
-
|
|
256957
|
+
matched_against: "commit",
|
|
256958
|
+
grants_pass: true,
|
|
256959
|
+
reason: `the ruleset pins ${fields.workflow_path} to ${fields.workflow_sha}, which is the head commit being merged (GitHub workflows[].sha is a commit SHA, not a file blob). That match grants PASS. Moving this pin requires editing the ruleset (repository administration), a different permission from workflow write \u2014 so the check is attributable to THIS workflow, not merely to Actions. It still does not establish that the pinned workflow ran, nor that bypass actors cannot skip the ruleset entirely, nor that the pin equals the file blob SHA.`
|
|
256960
|
+
};
|
|
256961
|
+
}
|
|
256962
|
+
if (matchedBlob) {
|
|
256963
|
+
return {
|
|
256964
|
+
...fields,
|
|
256965
|
+
status: STATUS.UNVERIFIABLE,
|
|
256966
|
+
reason_code: PIN_REASON.WORKFLOW_SHA_IS_BLOB,
|
|
256967
|
+
workflow_sha_matches_head: false,
|
|
256968
|
+
matched_against: "blob",
|
|
256969
|
+
grants_pass: false,
|
|
256970
|
+
reason: "pinned sha matches the file blob, not a commit \u2014 GitHub treats workflows[].sha as a commit SHA. Blob equality is named and does not grant PASS."
|
|
256102
256971
|
};
|
|
256103
256972
|
}
|
|
256104
256973
|
return {
|
|
@@ -256107,9 +256976,26 @@ var require_github_workflow_pin = __commonJS({
|
|
|
256107
256976
|
reason_code: PIN_REASON.WORKFLOW_SHA_STALE,
|
|
256108
256977
|
workflow_sha_matches_head: false,
|
|
256109
256978
|
matched_against: null,
|
|
256979
|
+
grants_pass: false,
|
|
256110
256980
|
reason: `the ruleset pins ${fields.workflow_path} to ${fields.workflow_sha}, but the head carries ${blobSha || headCommitSha || "(nothing readable)"}. A pin to bytes nobody is merging gates nothing.`
|
|
256111
256981
|
};
|
|
256112
256982
|
}
|
|
256983
|
+
function evidenceStatement(headComparison) {
|
|
256984
|
+
if (headComparison && headComparison.grants_pass === true) {
|
|
256985
|
+
return "With the required workflow pinned by sha and that sha matching the head commit SHA (GitHub workflows[].sha is a commit SHA, not a file blob), the check is attributable to this workflow rather than to GitHub Actions in general: moving the pin requires repository administration, which is a different permission from workflow write. The common-issuer objection is closed WITHOUT a second GitHub App. This is not a blob-sha content pin.";
|
|
256986
|
+
}
|
|
256987
|
+
if (headComparison && headComparison.matched_against === "blob") {
|
|
256988
|
+
return "The pinned sha equals the workflow file blob, not the head commit. GitHub treats workflows[].sha as a commit SHA, so blob equality does not grant PASS. The common-issuer objection is not closed by a blob match.";
|
|
256989
|
+
}
|
|
256990
|
+
const code = headComparison && headComparison.reason_code;
|
|
256991
|
+
if (code === PIN_REASON.WORKFLOW_SHA_STALE) {
|
|
256992
|
+
return "A sha-pinned required workflow exists, but the pin names bytes that are not on the head. A stale pin gates nothing and does not grant PASS.";
|
|
256993
|
+
}
|
|
256994
|
+
if (code === PIN_REASON.WORKFLOW_FILE_UNREADABLE) {
|
|
256995
|
+
return "A sha-pinned required workflow exists, but the pin could not be compared with the head. That is UNVERIFIABLE, not a match, and does not grant PASS.";
|
|
256996
|
+
}
|
|
256997
|
+
return "Without a sha-pinned required workflow, the issuer proves the check came from GitHub Actions, not that it came from this workflow. Anyone who can write .github/workflows can post a passing check under the same shared issuer id.";
|
|
256998
|
+
}
|
|
256113
256999
|
function workflowBindingEvidence(pin, headComparison) {
|
|
256114
257000
|
return {
|
|
256115
257001
|
pin_status: pin ? pin.status : STATUS.UNVERIFIABLE,
|
|
@@ -256119,10 +257005,11 @@ var require_github_workflow_pin = __commonJS({
|
|
|
256119
257005
|
workflow_sha: headComparison.workflow_sha,
|
|
256120
257006
|
workflow_sha_matches_head: headComparison.workflow_sha_matches_head,
|
|
256121
257007
|
matched_against: headComparison.matched_against,
|
|
257008
|
+
grants_pass: headComparison.grants_pass === true,
|
|
256122
257009
|
status: headComparison.status,
|
|
256123
257010
|
reason_code: headComparison.reason_code,
|
|
256124
257011
|
reason: headComparison.reason,
|
|
256125
|
-
statement: headComparison
|
|
257012
|
+
statement: evidenceStatement(headComparison)
|
|
256126
257013
|
};
|
|
256127
257014
|
}
|
|
256128
257015
|
module2.exports = { PIN_REASON, evaluateWorkflowShaMatchesHead, workflowBindingEvidence };
|
|
@@ -256645,12 +257532,27 @@ var require_setup_required_check = __commonJS({
|
|
|
256645
257532
|
}
|
|
256646
257533
|
const commitRead = runApi([`repos/${owner}/${repo}/commits/${encodeURIComponent(branch)}`], { cwd });
|
|
256647
257534
|
const commitSha = commitRead && commitRead.ok && commitRead.body && (typeof commitRead.body.sha === "string" ? commitRead.body.sha : commitRead.body.commit && commitRead.body.commit.sha) || null;
|
|
257535
|
+
if (!commitSha || !/^[0-9a-f]{40}$/i.test(commitSha)) {
|
|
257536
|
+
if (!options.json) {
|
|
257537
|
+
logErr(chalk.red(`Could not resolve a commit SHA for ${branch}.`));
|
|
257538
|
+
logErr(" GitHub ruleset workflows[].sha is a commit SHA, not a file blob SHA \u2014 refusing to pin.");
|
|
257539
|
+
}
|
|
257540
|
+
return finish(EXIT.ERROR, {
|
|
257541
|
+
ok: false,
|
|
257542
|
+
code: "WORKFLOW_COMMIT_SHA_UNRESOLVED",
|
|
257543
|
+
owner,
|
|
257544
|
+
repo,
|
|
257545
|
+
branch,
|
|
257546
|
+
workflow_path: WORKFLOW_REL,
|
|
257547
|
+
http_status: commitRead ? commitRead.status : null
|
|
257548
|
+
});
|
|
257549
|
+
}
|
|
256648
257550
|
const rulesetDocs = fetchRulesetDocs(runApi, owner, repo, cwd) || [];
|
|
256649
257551
|
const existing = findExistingWorkflowRuleset(rulesetDocs, WORKFLOW_REL);
|
|
256650
257552
|
const created = buildWorkflowRulesetPayload({
|
|
256651
257553
|
repositoryId,
|
|
256652
257554
|
branch,
|
|
256653
|
-
sha:
|
|
257555
|
+
sha: commitSha,
|
|
256654
257556
|
path: WORKFLOW_REL
|
|
256655
257557
|
});
|
|
256656
257558
|
const payload = existing ? mergeWorkflowRule(existing, created) : created;
|
|
@@ -256661,7 +257563,8 @@ var require_setup_required_check = __commonJS({
|
|
|
256661
257563
|
if (!options.json) {
|
|
256662
257564
|
log(chalk.yellow(`Dry-run: pin ${WORKFLOW_REL} as a required workflow on ${branch}.`));
|
|
256663
257565
|
log(` repo: ${owner}/${repo} (id ${repositoryId})`);
|
|
256664
|
-
log(`
|
|
257566
|
+
log(` commit: ${commitSha}`);
|
|
257567
|
+
log(` blob (file object): ${blobSha}`);
|
|
256665
257568
|
log(` ${existing ? `update ruleset ${existing.id}` : "create ruleset"} ${payload.name}`);
|
|
256666
257569
|
log("");
|
|
256667
257570
|
log(cmdText);
|