tamperward 2.29.18 → 2.29.20
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/dist/cli/index.js +68 -12
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -11638,14 +11638,31 @@ function watcherTelemetry(log) {
|
|
|
11638
11638
|
return { state: "degraded", health, reason: health.last_error ?? "observer reported an error" };
|
|
11639
11639
|
return { state: "healthy", health };
|
|
11640
11640
|
}
|
|
11641
|
-
function watchTree(dir, cb, onState, onError) {
|
|
11641
|
+
function watchTree(dir, cb, onState, onError, watchFn = watch) {
|
|
11642
|
+
const describe2 = (e) => e instanceof Error ? e.message : String(e);
|
|
11642
11643
|
if (process.env.TAMPERWARD_WATCH_NO_RECURSIVE !== "1") {
|
|
11643
11644
|
try {
|
|
11644
|
-
|
|
11645
|
+
let recursiveClosed = false;
|
|
11646
|
+
const closeRecursive = () => {
|
|
11647
|
+
if (recursiveClosed) return;
|
|
11648
|
+
recursiveClosed = true;
|
|
11649
|
+
w.close();
|
|
11650
|
+
};
|
|
11651
|
+
const w = watchFn(dir, { recursive: true }, (kind, fname) => {
|
|
11645
11652
|
if (fname) cb(kind, String(fname));
|
|
11646
11653
|
});
|
|
11654
|
+
w.on("error", (e) => {
|
|
11655
|
+
if (recursiveClosed) return;
|
|
11656
|
+
recursiveClosed = true;
|
|
11657
|
+
try {
|
|
11658
|
+
w.close();
|
|
11659
|
+
} catch {
|
|
11660
|
+
}
|
|
11661
|
+
onState("recursive", 0);
|
|
11662
|
+
onError(`recursive watch on ${dir}: ${describe2(e)}`);
|
|
11663
|
+
});
|
|
11647
11664
|
onState("recursive", 1);
|
|
11648
|
-
return { close:
|
|
11665
|
+
return { close: closeRecursive };
|
|
11649
11666
|
} catch {
|
|
11650
11667
|
}
|
|
11651
11668
|
}
|
|
@@ -11656,7 +11673,7 @@ function watchTree(dir, cb, onState, onError) {
|
|
|
11656
11673
|
if (closed || watchers.has(rel) || SKIP2.test(rel + "/")) return;
|
|
11657
11674
|
let w;
|
|
11658
11675
|
try {
|
|
11659
|
-
w =
|
|
11676
|
+
w = watchFn(rel ? join12(dir, rel) : dir, (kind, fname) => {
|
|
11660
11677
|
if (closed || !fname) return;
|
|
11661
11678
|
const child = rel ? `${rel}/${String(fname)}` : String(fname);
|
|
11662
11679
|
cb(kind, child);
|
|
@@ -11666,11 +11683,19 @@ function watchTree(dir, cb, onState, onError) {
|
|
|
11666
11683
|
}
|
|
11667
11684
|
});
|
|
11668
11685
|
} catch (e) {
|
|
11669
|
-
onError(
|
|
11670
|
-
`watch directory ${rel || "."}: ${e instanceof Error ? e.message : String(e)}`
|
|
11671
|
-
);
|
|
11686
|
+
onError(`watch directory ${rel || "."}: ${describe2(e)}`);
|
|
11672
11687
|
return;
|
|
11673
11688
|
}
|
|
11689
|
+
w.on("error", (e) => {
|
|
11690
|
+
if (closed || watchers.get(rel) !== w) return;
|
|
11691
|
+
watchers.delete(rel);
|
|
11692
|
+
try {
|
|
11693
|
+
w.close();
|
|
11694
|
+
} catch {
|
|
11695
|
+
}
|
|
11696
|
+
onError(`watch directory ${rel || "."}: ${describe2(e)}`);
|
|
11697
|
+
onState("fallback", watchers.size);
|
|
11698
|
+
});
|
|
11674
11699
|
watchers.set(rel, w);
|
|
11675
11700
|
onState("fallback", watchers.size);
|
|
11676
11701
|
};
|
|
@@ -11704,7 +11729,7 @@ function watchTree(dir, cb, onState, onError) {
|
|
|
11704
11729
|
}
|
|
11705
11730
|
};
|
|
11706
11731
|
}
|
|
11707
|
-
function startWatcher(dir, log, policy) {
|
|
11732
|
+
function startWatcher(dir, log, policy, watchFn = watch) {
|
|
11708
11733
|
try {
|
|
11709
11734
|
mkdirSync4(join12(log, ".."), { recursive: true });
|
|
11710
11735
|
} catch {
|
|
@@ -11784,7 +11809,8 @@ function startWatcher(dir, log, policy) {
|
|
|
11784
11809
|
health.watched_dirs = watchedDirs;
|
|
11785
11810
|
persistHealth();
|
|
11786
11811
|
},
|
|
11787
|
-
(detail) => degrade(detail)
|
|
11812
|
+
(detail) => degrade(detail),
|
|
11813
|
+
watchFn
|
|
11788
11814
|
);
|
|
11789
11815
|
let closed = false;
|
|
11790
11816
|
return {
|
|
@@ -13024,6 +13050,8 @@ async function startHookService(opts) {
|
|
|
13024
13050
|
const cache3 = opts.cache ?? new SnapshotCache();
|
|
13025
13051
|
let served = 0;
|
|
13026
13052
|
let inFlight = false;
|
|
13053
|
+
const sockets = /* @__PURE__ */ new Set();
|
|
13054
|
+
let acceptedSocket = null;
|
|
13027
13055
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
13028
13056
|
const respond = (sock, body) => {
|
|
13029
13057
|
try {
|
|
@@ -13056,6 +13084,7 @@ async function startHookService(opts) {
|
|
|
13056
13084
|
if (named !== null && !within(root, named)) return respond(sock, { refused: "payload cwd outside the bound repository" });
|
|
13057
13085
|
if (inFlight) return respond(sock, { refused: "another request is in flight" });
|
|
13058
13086
|
inFlight = true;
|
|
13087
|
+
acceptedSocket = sock;
|
|
13059
13088
|
sock.write(JSON.stringify({ v: HOOK_SERVICE_PROTOCOL, version: TW_VERSION, accepted: true }) + "\n");
|
|
13060
13089
|
setImmediate(() => {
|
|
13061
13090
|
try {
|
|
@@ -13074,24 +13103,38 @@ async function startHookService(opts) {
|
|
|
13074
13103
|
respond(sock, { exitCode: result.exitCode, stdout: result.stdout });
|
|
13075
13104
|
} finally {
|
|
13076
13105
|
inFlight = false;
|
|
13106
|
+
acceptedSocket = null;
|
|
13077
13107
|
}
|
|
13078
13108
|
});
|
|
13079
13109
|
};
|
|
13080
13110
|
const server = createServer((sock) => {
|
|
13111
|
+
sockets.add(sock);
|
|
13081
13112
|
let buf = "";
|
|
13082
13113
|
let answered = false;
|
|
13083
13114
|
sock.setEncoding("utf8");
|
|
13115
|
+
const deadline = setTimeout(() => {
|
|
13116
|
+
if (answered) return;
|
|
13117
|
+
answered = true;
|
|
13118
|
+
respond(sock, { refused: "request deadline exceeded" });
|
|
13119
|
+
}, REQUEST_DEADLINE_MS);
|
|
13120
|
+
deadline.unref?.();
|
|
13084
13121
|
sock.on("error", () => sock.destroy());
|
|
13122
|
+
sock.on("close", () => {
|
|
13123
|
+
clearTimeout(deadline);
|
|
13124
|
+
sockets.delete(sock);
|
|
13125
|
+
});
|
|
13085
13126
|
sock.on("data", (chunk) => {
|
|
13086
13127
|
if (answered) return;
|
|
13087
13128
|
buf += chunk;
|
|
13088
13129
|
if (buf.length > MAX_REQUEST_BYTES) {
|
|
13089
13130
|
answered = true;
|
|
13131
|
+
clearTimeout(deadline);
|
|
13090
13132
|
return respond(sock, { refused: "request too large" });
|
|
13091
13133
|
}
|
|
13092
13134
|
const nl = buf.indexOf("\n");
|
|
13093
13135
|
if (nl < 0) return;
|
|
13094
13136
|
answered = true;
|
|
13137
|
+
clearTimeout(deadline);
|
|
13095
13138
|
handle(sock, buf.slice(0, nl));
|
|
13096
13139
|
});
|
|
13097
13140
|
});
|
|
@@ -13122,11 +13165,22 @@ async function startHookService(opts) {
|
|
|
13122
13165
|
if (closed) return resolve17();
|
|
13123
13166
|
closed = true;
|
|
13124
13167
|
setSnapshotCache(null);
|
|
13125
|
-
|
|
13168
|
+
let settled = false;
|
|
13169
|
+
let drain;
|
|
13170
|
+
const finalize = () => {
|
|
13171
|
+
if (settled) return;
|
|
13172
|
+
settled = true;
|
|
13173
|
+
clearTimeout(drain);
|
|
13126
13174
|
removeQuietly(paths.socket);
|
|
13127
13175
|
removeQuietly(paths.state);
|
|
13128
13176
|
resolve17();
|
|
13129
|
-
}
|
|
13177
|
+
};
|
|
13178
|
+
server.close(finalize);
|
|
13179
|
+
for (const sock of sockets) if (sock !== acceptedSocket) sock.destroy();
|
|
13180
|
+
drain = setTimeout(() => {
|
|
13181
|
+
for (const sock of sockets) sock.destroy();
|
|
13182
|
+
}, SHUTDOWN_DRAIN_MS);
|
|
13183
|
+
drain.unref?.();
|
|
13130
13184
|
})
|
|
13131
13185
|
};
|
|
13132
13186
|
}
|
|
@@ -13264,7 +13318,7 @@ function runHookService(args) {
|
|
|
13264
13318
|
});
|
|
13265
13319
|
return -1;
|
|
13266
13320
|
}
|
|
13267
|
-
var MAX_REQUEST_BYTES, STOP_WAIT_MS;
|
|
13321
|
+
var MAX_REQUEST_BYTES, STOP_WAIT_MS, REQUEST_DEADLINE_MS, SHUTDOWN_DRAIN_MS;
|
|
13268
13322
|
var init_hook_service = __esm({
|
|
13269
13323
|
"src/cli/hook-service.ts"() {
|
|
13270
13324
|
"use strict";
|
|
@@ -13277,6 +13331,8 @@ var init_hook_service = __esm({
|
|
|
13277
13331
|
init_hook_client();
|
|
13278
13332
|
MAX_REQUEST_BYTES = 64 * 1024 * 1024;
|
|
13279
13333
|
STOP_WAIT_MS = 1e4;
|
|
13334
|
+
REQUEST_DEADLINE_MS = 3e4;
|
|
13335
|
+
SHUTDOWN_DRAIN_MS = 5e3;
|
|
13280
13336
|
}
|
|
13281
13337
|
});
|
|
13282
13338
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tamperward",
|
|
3
|
-
"version": "2.29.
|
|
3
|
+
"version": "2.29.20",
|
|
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",
|