tamperward 2.29.17 → 2.29.19

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 +36 -3
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -10747,6 +10747,9 @@ function validate(r, where) {
10747
10747
  const v = r.verify;
10748
10748
  const { command, budget, inputs, backend, image } = v;
10749
10749
  if (command !== void 0 && typeof command !== "string") bad2(`verify.command must be a string, got ${show(command)}`);
10750
+ if (typeof command !== "string" || command.trim() === "") {
10751
+ bad2(`verify.command is required and must be a non-empty command when a verify block is present, got ${show(command)}`);
10752
+ }
10750
10753
  if (budget !== void 0 && !(typeof budget === "number" && Number.isFinite(budget) && budget > 0)) {
10751
10754
  bad2(`verify.budget must be a positive number of seconds, got ${show(budget)}`);
10752
10755
  }
@@ -13021,6 +13024,8 @@ async function startHookService(opts) {
13021
13024
  const cache3 = opts.cache ?? new SnapshotCache();
13022
13025
  let served = 0;
13023
13026
  let inFlight = false;
13027
+ const sockets = /* @__PURE__ */ new Set();
13028
+ let acceptedSocket = null;
13024
13029
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
13025
13030
  const respond = (sock, body) => {
13026
13031
  try {
@@ -13053,6 +13058,7 @@ async function startHookService(opts) {
13053
13058
  if (named !== null && !within(root, named)) return respond(sock, { refused: "payload cwd outside the bound repository" });
13054
13059
  if (inFlight) return respond(sock, { refused: "another request is in flight" });
13055
13060
  inFlight = true;
13061
+ acceptedSocket = sock;
13056
13062
  sock.write(JSON.stringify({ v: HOOK_SERVICE_PROTOCOL, version: TW_VERSION, accepted: true }) + "\n");
13057
13063
  setImmediate(() => {
13058
13064
  try {
@@ -13071,24 +13077,38 @@ async function startHookService(opts) {
13071
13077
  respond(sock, { exitCode: result.exitCode, stdout: result.stdout });
13072
13078
  } finally {
13073
13079
  inFlight = false;
13080
+ acceptedSocket = null;
13074
13081
  }
13075
13082
  });
13076
13083
  };
13077
13084
  const server = createServer((sock) => {
13085
+ sockets.add(sock);
13078
13086
  let buf = "";
13079
13087
  let answered = false;
13080
13088
  sock.setEncoding("utf8");
13089
+ const deadline = setTimeout(() => {
13090
+ if (answered) return;
13091
+ answered = true;
13092
+ respond(sock, { refused: "request deadline exceeded" });
13093
+ }, REQUEST_DEADLINE_MS);
13094
+ deadline.unref?.();
13081
13095
  sock.on("error", () => sock.destroy());
13096
+ sock.on("close", () => {
13097
+ clearTimeout(deadline);
13098
+ sockets.delete(sock);
13099
+ });
13082
13100
  sock.on("data", (chunk) => {
13083
13101
  if (answered) return;
13084
13102
  buf += chunk;
13085
13103
  if (buf.length > MAX_REQUEST_BYTES) {
13086
13104
  answered = true;
13105
+ clearTimeout(deadline);
13087
13106
  return respond(sock, { refused: "request too large" });
13088
13107
  }
13089
13108
  const nl = buf.indexOf("\n");
13090
13109
  if (nl < 0) return;
13091
13110
  answered = true;
13111
+ clearTimeout(deadline);
13092
13112
  handle(sock, buf.slice(0, nl));
13093
13113
  });
13094
13114
  });
@@ -13119,11 +13139,22 @@ async function startHookService(opts) {
13119
13139
  if (closed) return resolve17();
13120
13140
  closed = true;
13121
13141
  setSnapshotCache(null);
13122
- server.close(() => {
13142
+ let settled = false;
13143
+ let drain;
13144
+ const finalize = () => {
13145
+ if (settled) return;
13146
+ settled = true;
13147
+ clearTimeout(drain);
13123
13148
  removeQuietly(paths.socket);
13124
13149
  removeQuietly(paths.state);
13125
13150
  resolve17();
13126
- });
13151
+ };
13152
+ server.close(finalize);
13153
+ for (const sock of sockets) if (sock !== acceptedSocket) sock.destroy();
13154
+ drain = setTimeout(() => {
13155
+ for (const sock of sockets) sock.destroy();
13156
+ }, SHUTDOWN_DRAIN_MS);
13157
+ drain.unref?.();
13127
13158
  })
13128
13159
  };
13129
13160
  }
@@ -13261,7 +13292,7 @@ function runHookService(args) {
13261
13292
  });
13262
13293
  return -1;
13263
13294
  }
13264
- var MAX_REQUEST_BYTES, STOP_WAIT_MS;
13295
+ var MAX_REQUEST_BYTES, STOP_WAIT_MS, REQUEST_DEADLINE_MS, SHUTDOWN_DRAIN_MS;
13265
13296
  var init_hook_service = __esm({
13266
13297
  "src/cli/hook-service.ts"() {
13267
13298
  "use strict";
@@ -13274,6 +13305,8 @@ var init_hook_service = __esm({
13274
13305
  init_hook_client();
13275
13306
  MAX_REQUEST_BYTES = 64 * 1024 * 1024;
13276
13307
  STOP_WAIT_MS = 1e4;
13308
+ REQUEST_DEADLINE_MS = 3e4;
13309
+ SHUTDOWN_DRAIN_MS = 5e3;
13277
13310
  }
13278
13311
  });
13279
13312
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tamperward",
3
- "version": "2.29.17",
3
+ "version": "2.29.19",
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",