tamperward 1.10.0 → 1.10.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 +24 -1
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -2932,6 +2932,21 @@ function runEnvelope(opts) {
2932
2932
  err(`tamperward run: cannot resolve trusted base ${opts.base ?? "HEAD"} \u2014 failing closed.`);
2933
2933
  return 2;
2934
2934
  }
2935
+ let frozenCmd;
2936
+ let frozenBudget;
2937
+ try {
2938
+ const entryPolicy = loadPolicy(cwd);
2939
+ frozenCmd = opts.cmd ?? entryPolicy.verify?.command;
2940
+ frozenBudget = opts.budget ?? entryPolicy.verify?.budget;
2941
+ } catch (e) {
2942
+ err(`tamperward run: cannot load the entry-time policy (${e instanceof Error ? e.message : String(e)}) \u2014 failing closed.`);
2943
+ return 2;
2944
+ }
2945
+ if (!frozenCmd) {
2946
+ err("tamperward run: no suite command at entry (policy `verify: { command: ... }` or --cmd) \u2014");
2947
+ err("refusing to start: a verifier that appears after the agent runs would be agent-authored.");
2948
+ return 2;
2949
+ }
2935
2950
  if (!opts.allowDirty) {
2936
2951
  const dirty = git3(["status", "--porcelain"], cwd).trim();
2937
2952
  if (dirty) {
@@ -2944,6 +2959,14 @@ function runEnvelope(opts) {
2944
2959
  const agent = spawnSync2(opts.argv[0], opts.argv.slice(1), { cwd, stdio: "inherit" });
2945
2960
  const agentExit = agent.status ?? 1;
2946
2961
  const head = git3(["rev-parse", "HEAD"], cwd).trim();
2962
+ const isAncestor = spawnSync2("git", ["merge-base", "--is-ancestor", base, head], { cwd });
2963
+ if (isAncestor.status !== 0) {
2964
+ err(`tamperward run: HEAD ${head.slice(0, 10)} is not a descendant of the trusted base ${base.slice(0, 10)} \u2014`);
2965
+ err("the agent rewrote history out from under the anchor. That is the finding.");
2966
+ out(`
2967
+ tamperward run \u2014 agent exit ${agentExit}; HISTORY_REWRITE \u2192 ENFORCEMENT_FAILED`);
2968
+ return 1;
2969
+ }
2947
2970
  let diffCode = 0;
2948
2971
  if (head !== base) {
2949
2972
  out(`
@@ -2953,7 +2976,7 @@ function runEnvelope(opts) {
2953
2976
  out("\n[envelope] policy check over the working tree:");
2954
2977
  const workCode = runCheck({ worktree: true, cwd });
2955
2978
  out("\n[envelope] pristine verification against the trusted base:");
2956
- const verifyCode = runVerify({ cwd, base, cmd: opts.cmd, budget: opts.budget });
2979
+ const verifyCode = runVerify({ cwd, base, cmd: frozenCmd, budget: frozenBudget });
2957
2980
  const cannot = diffCode === 2 || workCode === 2 || verifyCode === 2;
2958
2981
  const blocked = diffCode === 1 || workCode === 1 || verifyCode === 1;
2959
2982
  const enforcement = cannot ? 2 : blocked ? 1 : 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tamperward",
3
- "version": "1.10.0",
3
+ "version": "1.10.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",