tamperward 2.39.0 → 2.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli/index.js +27 -21
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -19963,18 +19963,13 @@ var init_adapter = __esm({
19963
19963
  init_contract();
19964
19964
  ClaudeRuntimeAdapter = class {
19965
19965
  name = "claude-code";
19966
- /**
19967
- * Claude Code's live PreToolUse fires for EVERY tool and can synchronously deny it —
19968
- * shell, file edit, file read, MCP, and anything else — even under
19969
- * `--dangerously-skip-permissions`. The end-of-turn Stop sweep is live too. There is no
19970
- * live per-tool PostToolUse veto (Stop is the post-turn reconciliation), so `postObserve`
19971
- * is empty and `unsupported` names that gap explicitly rather than implying it.
19972
- */
19973
19966
  capabilities = {
19974
- preDeny: OPERATION_KINDS,
19967
+ preDeny: OPERATION_KINDS.filter((kind) => kind !== "mcp" && kind !== "other"),
19975
19968
  postObserve: [],
19976
19969
  endOfTurn: true,
19977
19970
  unsupported: [
19971
+ "MCP pre-deny is not declared because Claude MCP calls are not reconstructed into Change[] before evaluation",
19972
+ "catch-all other-tool pre-deny is not declared because unmodelled Claude tools are not reconstructed into Change[] before evaluation",
19978
19973
  "per-operation post-action veto (end-of-turn Stop sweep is the post-turn reconciliation)",
19979
19974
  "network-egress control",
19980
19975
  "identity / authentication"
@@ -20041,26 +20036,28 @@ var init_adapter = __esm({
20041
20036
  const parsed = this.parseEvent(raw, phase);
20042
20037
  if ("failure" in parsed) {
20043
20038
  const live2 = phase === "end-of-turn" ? stopFromRaw(raw, defaultCwd) : preToolUseFromRaw(raw, defaultCwd);
20039
+ const findings2 = live2.findings ? [...live2.findings] : [];
20044
20040
  return {
20045
20041
  outcome: "parse-failure",
20046
20042
  detail: parsed.detail,
20047
20043
  wire: live2.stdout,
20048
- decision: { verdict: "deny", findings: [], reason: live2.stdout }
20044
+ decision: { verdict: "deny", findings: findings2, reason: live2.stdout }
20049
20045
  };
20050
20046
  }
20051
20047
  const idv = this.validateIdentity(parsed.identity, defaultCwd);
20052
20048
  if (!idv.ok) {
20053
- const findings = [steeringUnavailableFinding(`repository identity claim rejected: ${idv.rejected}`)];
20054
- const wire2 = this.denyPayload(findings, phase);
20055
- return { outcome: "ok", wire: wire2, detail: idv.rejected, decision: { verdict: "deny", findings, reason: wire2 } };
20049
+ const findings2 = [steeringUnavailableFinding(`repository identity claim rejected: ${idv.rejected}`)];
20050
+ const wire2 = this.denyPayload(findings2, phase);
20051
+ return { outcome: "ok", wire: wire2, detail: idv.rejected, decision: { verdict: "deny", findings: findings2, reason: wire2 } };
20056
20052
  }
20057
20053
  const live = phase === "end-of-turn" ? stopFromRaw(raw, defaultCwd, idv.trustedRoot) : preToolUseFromRaw(raw, defaultCwd, idv.trustedRoot);
20058
20054
  const wire = live.stdout;
20059
20055
  const denied = wire.length > 0;
20056
+ const findings = live.findings ? [...live.findings] : [];
20060
20057
  return {
20061
20058
  outcome: "ok",
20062
20059
  wire,
20063
- decision: { verdict: denied ? "deny" : "allow", findings: [], reason: denied ? wire : void 0 }
20060
+ decision: { verdict: denied ? "deny" : "allow", findings, reason: denied ? wire : void 0 }
20064
20061
  };
20065
20062
  }
20066
20063
  /**
@@ -20439,8 +20436,9 @@ var init_adapter2 = __esm({
20439
20436
  return { outcome: "ok", wire, detail: idv.rejected, decision: { verdict: "deny", findings, reason: wire } };
20440
20437
  }
20441
20438
  if (phase === "end-of-turn") {
20442
- const wire = stopFromRaw(raw, defaultCwd, idv.trustedRoot).stdout;
20443
- return { outcome: "ok", wire, decision: { verdict: wire ? "deny" : "allow", findings: [], reason: wire || void 0 } };
20439
+ const swept = stopFromRaw(raw, defaultCwd, idv.trustedRoot);
20440
+ const findings = swept.findings ? [...swept.findings] : [];
20441
+ return { outcome: "ok", wire: swept.stdout, decision: { verdict: swept.stdout ? "deny" : "allow", findings, reason: swept.stdout || void 0 } };
20444
20442
  }
20445
20443
  try {
20446
20444
  const root = idv.trustedRoot ?? repoRoot(defaultCwd ?? process.cwd());
@@ -20778,12 +20776,13 @@ var init_adapter3 = __esm({
20778
20776
  if (phase === "end-of-turn") {
20779
20777
  const stopInput = copilotStopInput(raw);
20780
20778
  if (typeof stopInput !== "string") {
20781
- const findings = [steeringUnavailableFinding(`unparseable Copilot event: ${stopInput.detail}`)];
20782
- const wire2 = this.denyPayload(findings, "end-of-turn");
20783
- return { outcome: "parse-failure", detail: stopInput.detail, wire: wire2, decision: { verdict: "deny", findings, reason: wire2 } };
20779
+ const findings2 = [steeringUnavailableFinding(`unparseable Copilot event: ${stopInput.detail}`)];
20780
+ const wire = this.denyPayload(findings2, "end-of-turn");
20781
+ return { outcome: "parse-failure", detail: stopInput.detail, wire, decision: { verdict: "deny", findings: findings2, reason: wire } };
20784
20782
  }
20785
- const wire = stopFromRaw(stopInput, defaultCwd, idv.trustedRoot).stdout;
20786
- return { outcome: "ok", wire, decision: { verdict: wire ? "deny" : "allow", findings: [], reason: wire || void 0 } };
20783
+ const swept = stopFromRaw(stopInput, defaultCwd, idv.trustedRoot);
20784
+ const findings = swept.findings ? [...swept.findings] : [];
20785
+ return { outcome: "ok", wire: swept.stdout, decision: { verdict: swept.stdout ? "deny" : "allow", findings, reason: swept.stdout || void 0 } };
20787
20786
  }
20788
20787
  if (parsed.operation.kind === "unknown") {
20789
20788
  const detail = `unrecognized Copilot tool ${parsed.operation.name}; refusing to evaluate it as a no-op`;
@@ -21985,7 +21984,8 @@ function storedQualification(adapter, cwd, opts = {}) {
21985
21984
  const validated = validateStoredReport(raw);
21986
21985
  if ("reason" in validated) return { state: "rejected", reason: validated.reason };
21987
21986
  const stored = validated.report;
21988
- const { binding: current } = buildQualification(adapter, opts, cwd);
21987
+ const currentQualification = buildQualification(adapter, opts, cwd);
21988
+ const current = currentQualification.binding;
21989
21989
  const storedBinding = {
21990
21990
  runtime: stored.runtime,
21991
21991
  tamperward: stored.tamperward,
@@ -21999,6 +21999,12 @@ function storedQualification(adapter, cwd, opts = {}) {
21999
21999
  evidence_id: stored.evidence_id
22000
22000
  };
22001
22001
  const staleness = qualificationStaleness(storedBinding, current);
22002
+ if (!staleness.stale && (stored.evidence_id !== current.evidence_id || JSON.stringify(stored.capabilities) !== JSON.stringify(currentQualification.assessments))) {
22003
+ return {
22004
+ state: "rejected",
22005
+ reason: "stored qualification posture does not match retained evidence for the current binding"
22006
+ };
22007
+ }
22002
22008
  return { state: "recorded", report: stored, stale: staleness.stale, changed_inputs: staleness.changed };
22003
22009
  }
22004
22010
  function runRuntime(sub, opts) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tamperward",
3
- "version": "2.39.0",
3
+ "version": "2.39.1",
4
4
  "description": "The deterministic agent-integrity gate. One ruleset, evaluated on the actual diff/commands as a verdict, enforced everywhere a change can be made.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "hexrift",