tamperward 2.39.10 → 2.39.12
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 +227 -132
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -671,7 +671,7 @@ var init_policy = __esm({
|
|
|
671
671
|
});
|
|
672
672
|
|
|
673
673
|
// src/disk.ts
|
|
674
|
-
import { closeSync, constants, fstatSync, lstatSync as lstatSync2, openSync, readSync, readlinkSync, realpathSync as realpathSync2 } from "node:fs";
|
|
674
|
+
import { closeSync, constants, fstatSync, lstatSync as lstatSync2, openSync, readSync, readlinkSync, realpathSync as realpathSync2, writeSync } from "node:fs";
|
|
675
675
|
import { join as join3 } from "node:path";
|
|
676
676
|
function errText(e) {
|
|
677
677
|
return e instanceof Error ? e.message : String(e);
|
|
@@ -788,9 +788,53 @@ function readStateFile(abs) {
|
|
|
788
788
|
if (e.kind === "absent") return null;
|
|
789
789
|
if (e.kind === "file") return textOf2(e) ?? "";
|
|
790
790
|
throw new StateFileError(
|
|
791
|
-
`${abs} ${notARegularFile(e)}; the gate reads its
|
|
791
|
+
`${abs} ${notARegularFile(e)}; the gate reads its state files only as regular files \u2014 remove what stands there so the state can be re-established`
|
|
792
792
|
);
|
|
793
793
|
}
|
|
794
|
+
function stateDirectory(gitDir3) {
|
|
795
|
+
const dir = join3(gitDir3, "tamperward");
|
|
796
|
+
const st = lstatSync2(dir, { throwIfNoEntry: false });
|
|
797
|
+
if (st === void 0 || st.isDirectory()) return dir;
|
|
798
|
+
if (st.isSymbolicLink()) {
|
|
799
|
+
let target = "";
|
|
800
|
+
try {
|
|
801
|
+
target = readlinkSync(dir);
|
|
802
|
+
} catch {
|
|
803
|
+
}
|
|
804
|
+
throw new StateFileError(`${dir} is a symbolic link to ${escapeControl(target)}${STATE_DIR_REFUSED}`);
|
|
805
|
+
}
|
|
806
|
+
throw new StateFileError(`${dir} is a ${st.isFile() ? "regular file" : irregularName(st)}${STATE_DIR_REFUSED}`);
|
|
807
|
+
}
|
|
808
|
+
function multiplyLinked(st) {
|
|
809
|
+
return st.nlink === 1 ? null : `has ${st.nlink} names \u2014 a hard link is the same file under another name, the session marker's or the policy's, say`;
|
|
810
|
+
}
|
|
811
|
+
function appendRegular(abs, text, mode = 438) {
|
|
812
|
+
const st = lstatSync2(abs, { throwIfNoEntry: false });
|
|
813
|
+
if (st !== void 0 && !st.isFile()) throw new StateFileError(`${abs} ${notARegularFile(classify(abs, st))}${APPEND_REFUSED}`);
|
|
814
|
+
const linked = st === void 0 ? null : multiplyLinked(st);
|
|
815
|
+
if (linked !== null) throw new StateFileError(`${abs} ${linked}${APPEND_REFUSED}`);
|
|
816
|
+
let fd;
|
|
817
|
+
try {
|
|
818
|
+
fd = openSync(abs, O_APPEND_REGULAR, mode);
|
|
819
|
+
} catch (e) {
|
|
820
|
+
const code2 = errCode(e);
|
|
821
|
+
if (code2 === "ELOOP" || code2 === "ENXIO" || code2 === "EISDIR") {
|
|
822
|
+
throw new StateFileError(`${abs} changed shape while it was being opened (${errText(e)})${APPEND_REFUSED}`);
|
|
823
|
+
}
|
|
824
|
+
throw e;
|
|
825
|
+
}
|
|
826
|
+
try {
|
|
827
|
+
const now = fstatSync(fd);
|
|
828
|
+
if (!now.isFile()) throw new StateFileError(`${abs} is a ${irregularName(now)}${APPEND_REFUSED}`);
|
|
829
|
+
const opened = multiplyLinked(now);
|
|
830
|
+
if (opened !== null) throw new StateFileError(`${abs} ${opened}${APPEND_REFUSED}`);
|
|
831
|
+
const buf = Buffer.from(text, "utf8");
|
|
832
|
+
let off2 = 0;
|
|
833
|
+
while (off2 < buf.length) off2 += writeSync(fd, buf, off2, buf.length - off2);
|
|
834
|
+
} finally {
|
|
835
|
+
closeSync(fd);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
794
838
|
function describe(e, shown) {
|
|
795
839
|
switch (e.kind) {
|
|
796
840
|
case "symlink":
|
|
@@ -831,7 +875,7 @@ function unjudgeableProtected(cwd, policy, changes) {
|
|
|
831
875
|
}
|
|
832
876
|
return out3;
|
|
833
877
|
}
|
|
834
|
-
var READ_CAP, NO_META, O_READ, StateFileError;
|
|
878
|
+
var READ_CAP, NO_META, O_READ, StateFileError, STATE_DIR_REFUSED, O_APPEND_REGULAR, APPEND_REFUSED;
|
|
835
879
|
var init_disk = __esm({
|
|
836
880
|
"src/disk.ts"() {
|
|
837
881
|
"use strict";
|
|
@@ -842,6 +886,9 @@ var init_disk = __esm({
|
|
|
842
886
|
O_READ = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
|
|
843
887
|
StateFileError = class extends Error {
|
|
844
888
|
};
|
|
889
|
+
STATE_DIR_REFUSED = "; the gate keeps its state only in a directory of its own under the git directory \u2014 replace what stands there with a directory, or remove it";
|
|
890
|
+
O_APPEND_REGULAR = constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
|
|
891
|
+
APPEND_REFUSED = "; the gate appends its records only to a regular file with one name \u2014 remove what stands there so the record can be kept";
|
|
845
892
|
}
|
|
846
893
|
});
|
|
847
894
|
|
|
@@ -11582,7 +11629,13 @@ function writeBaseline(p, sha3) {
|
|
|
11582
11629
|
function baselinePath(cwd, sessionId) {
|
|
11583
11630
|
const gd = gitDir(cwd);
|
|
11584
11631
|
if (!gd) return null;
|
|
11585
|
-
|
|
11632
|
+
const name = `session-${sessionId.replace(UNSAFE, "")}`;
|
|
11633
|
+
try {
|
|
11634
|
+
return join10(stateDirectory(gd), name);
|
|
11635
|
+
} catch (e) {
|
|
11636
|
+
if (e instanceof StateFileError) throw new BaselineWriteError(join10(gd, "tamperward", name), e);
|
|
11637
|
+
throw e;
|
|
11638
|
+
}
|
|
11586
11639
|
}
|
|
11587
11640
|
function turnBaseline(cwd, sessionId) {
|
|
11588
11641
|
if (!sessionId) return null;
|
|
@@ -11649,7 +11702,7 @@ function statePath(cwd, sessionId, kind) {
|
|
|
11649
11702
|
if (!sessionId) return null;
|
|
11650
11703
|
const gd = gitDir2(cwd);
|
|
11651
11704
|
if (!gd) return null;
|
|
11652
|
-
const dir =
|
|
11705
|
+
const dir = stateDirectory(gd);
|
|
11653
11706
|
return join11(dir, `${kind}-${sessionId.replace(UNSAFE2, "")}.json`);
|
|
11654
11707
|
}
|
|
11655
11708
|
function ptreePath(cwd, sessionId) {
|
|
@@ -11777,8 +11830,53 @@ var init_effect = __esm({
|
|
|
11777
11830
|
}
|
|
11778
11831
|
});
|
|
11779
11832
|
|
|
11833
|
+
// src/safe-write.ts
|
|
11834
|
+
import { randomBytes } from "node:crypto";
|
|
11835
|
+
import { lstatSync as lstatSync5, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
11836
|
+
function writeTargetKind(path) {
|
|
11837
|
+
let st;
|
|
11838
|
+
try {
|
|
11839
|
+
st = lstatSync5(path, { throwIfNoEntry: false });
|
|
11840
|
+
} catch (e) {
|
|
11841
|
+
if (errnoCode(e) === "ENOTDIR") return "absent";
|
|
11842
|
+
throw e;
|
|
11843
|
+
}
|
|
11844
|
+
if (!st) return "absent";
|
|
11845
|
+
if (st.isSymbolicLink()) return "symlink";
|
|
11846
|
+
return st.isFile() ? "file" : "irregular";
|
|
11847
|
+
}
|
|
11848
|
+
function refuseNonRegular(path) {
|
|
11849
|
+
switch (writeTargetKind(path)) {
|
|
11850
|
+
case "symlink":
|
|
11851
|
+
return "refusing: symlink \u2014 the target would be written instead of this path; replace the link with a regular file, then re-run";
|
|
11852
|
+
case "irregular":
|
|
11853
|
+
return "refusing: not a regular file \u2014 a directory or special file stands where a file is expected; remove it, then re-run";
|
|
11854
|
+
default:
|
|
11855
|
+
return null;
|
|
11856
|
+
}
|
|
11857
|
+
}
|
|
11858
|
+
function existingMode(path, fallback) {
|
|
11859
|
+
if (writeTargetKind(path) !== "file") return fallback;
|
|
11860
|
+
return lstatSync5(path).mode & 511;
|
|
11861
|
+
}
|
|
11862
|
+
function atomicReplaceFile(path, content, mode) {
|
|
11863
|
+
const tmp = `${path}.${process.pid}.${randomBytes(8).toString("hex")}.tmp`;
|
|
11864
|
+
try {
|
|
11865
|
+
writeFileSync4(tmp, content, { encoding: "utf8", flag: "wx", mode });
|
|
11866
|
+
renameSync3(tmp, path);
|
|
11867
|
+
} finally {
|
|
11868
|
+
rmSync4(tmp, { force: true });
|
|
11869
|
+
}
|
|
11870
|
+
}
|
|
11871
|
+
var init_safe_write = __esm({
|
|
11872
|
+
"src/safe-write.ts"() {
|
|
11873
|
+
"use strict";
|
|
11874
|
+
init_narrow();
|
|
11875
|
+
}
|
|
11876
|
+
});
|
|
11877
|
+
|
|
11780
11878
|
// src/cli/watch.ts
|
|
11781
|
-
import {
|
|
11879
|
+
import { lstatSync as lstatSync6, mkdirSync as mkdirSync4, readdirSync as readdirSync2, watch } from "node:fs";
|
|
11782
11880
|
import { join as join12 } from "node:path";
|
|
11783
11881
|
import { createHash as createHash5 } from "node:crypto";
|
|
11784
11882
|
function snap(abs) {
|
|
@@ -11790,7 +11888,7 @@ function snap(abs) {
|
|
|
11790
11888
|
}
|
|
11791
11889
|
function defaultEventLog(cwd) {
|
|
11792
11890
|
if (process.env.TAMPERWARD_FSEVENTS) return process.env.TAMPERWARD_FSEVENTS;
|
|
11793
|
-
return join12(gitDir(cwd) ?? join12(cwd, ".git"), "
|
|
11891
|
+
return join12(stateDirectory(gitDir(cwd) ?? join12(cwd, ".git")), "fsevents.jsonl");
|
|
11794
11892
|
}
|
|
11795
11893
|
function watcherHealthPath(log) {
|
|
11796
11894
|
return `${log}.health.json`;
|
|
@@ -11889,7 +11987,7 @@ function watchTree(dir, cb, onState, onError, watchFn = watch) {
|
|
|
11889
11987
|
const child = rel ? `${rel}/${String(fname)}` : String(fname);
|
|
11890
11988
|
cb(kind, child);
|
|
11891
11989
|
try {
|
|
11892
|
-
if (
|
|
11990
|
+
if (lstatSync6(join12(dir, child)).isDirectory()) addDir(child);
|
|
11893
11991
|
} catch {
|
|
11894
11992
|
}
|
|
11895
11993
|
});
|
|
@@ -11925,7 +12023,7 @@ function watchTree(dir, cb, onState, onError, watchFn = watch) {
|
|
|
11925
12023
|
const child = rel ? `${rel}/${name}` : name;
|
|
11926
12024
|
if (SKIP2.test(child + "/")) continue;
|
|
11927
12025
|
try {
|
|
11928
|
-
if (
|
|
12026
|
+
if (lstatSync6(join12(dir, child)).isDirectory()) walk2(child);
|
|
11929
12027
|
} catch {
|
|
11930
12028
|
}
|
|
11931
12029
|
}
|
|
@@ -11964,7 +12062,7 @@ function startWatcher(dir, log, policy, watchFn = watch) {
|
|
|
11964
12062
|
let healthWriteWarningEmitted = false;
|
|
11965
12063
|
const persistHealth = () => {
|
|
11966
12064
|
try {
|
|
11967
|
-
|
|
12065
|
+
atomicReplaceFile(healthPath, JSON.stringify(health) + "\n", 384);
|
|
11968
12066
|
healthWriteWarningEmitted = false;
|
|
11969
12067
|
} catch (e) {
|
|
11970
12068
|
if (!healthWriteWarningEmitted) {
|
|
@@ -12004,7 +12102,7 @@ function startWatcher(dir, log, policy, watchFn = watch) {
|
|
|
12004
12102
|
...s
|
|
12005
12103
|
};
|
|
12006
12104
|
try {
|
|
12007
|
-
|
|
12105
|
+
appendRegular(log, JSON.stringify(ev) + "\n");
|
|
12008
12106
|
health.event_count++;
|
|
12009
12107
|
health.last_append_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
12010
12108
|
persistHealth();
|
|
@@ -12067,6 +12165,7 @@ var init_watch = __esm({
|
|
|
12067
12165
|
"src/cli/watch.ts"() {
|
|
12068
12166
|
"use strict";
|
|
12069
12167
|
init_disk();
|
|
12168
|
+
init_safe_write();
|
|
12070
12169
|
init_policy_load();
|
|
12071
12170
|
init_policy();
|
|
12072
12171
|
init_build();
|
|
@@ -12332,34 +12431,34 @@ var init_fs_events = __esm({
|
|
|
12332
12431
|
});
|
|
12333
12432
|
|
|
12334
12433
|
// src/cli/audit.ts
|
|
12335
|
-
import { createHash as createHash6, randomBytes } from "node:crypto";
|
|
12336
|
-
import {
|
|
12434
|
+
import { createHash as createHash6, randomBytes as randomBytes2 } from "node:crypto";
|
|
12435
|
+
import { closeSync as closeSync4, existsSync as existsSync5, mkdirSync as mkdirSync5, openSync as openSync4, readSync as readSync3 } from "node:fs";
|
|
12337
12436
|
import { dirname as dirname4, isAbsolute as isAbsolute8, join as join13, resolve as resolve4 } from "node:path";
|
|
12338
12437
|
function sessionHash(sessionId) {
|
|
12339
12438
|
if (!sessionId) return void 0;
|
|
12340
12439
|
return "sha256:" + createHash6("sha256").update(sessionId).digest("hex").slice(0, 24);
|
|
12341
12440
|
}
|
|
12342
12441
|
function eventId() {
|
|
12343
|
-
return "sha256:" + createHash6("sha256").update(
|
|
12442
|
+
return "sha256:" + createHash6("sha256").update(randomBytes2(32)).digest("hex").slice(0, 32);
|
|
12344
12443
|
}
|
|
12345
12444
|
function configuredAuditPath(cwd, env = process.env) {
|
|
12346
12445
|
const value = env[AUDIT_LOG_ENV];
|
|
12347
12446
|
if (!value) return null;
|
|
12348
12447
|
if (value === "auto") {
|
|
12349
12448
|
const ctx = repoContext(cwd);
|
|
12350
|
-
return ctx ? join13(ctx.gitDir, "
|
|
12449
|
+
return ctx ? join13(stateDirectory(ctx.gitDir), "audit.jsonl") : null;
|
|
12351
12450
|
}
|
|
12352
12451
|
return isAbsolute8(value) ? value : resolve4(cwd, value);
|
|
12353
12452
|
}
|
|
12354
12453
|
function defaultAuditPath(cwd) {
|
|
12355
12454
|
const ctx = repoContext(cwd);
|
|
12356
|
-
return ctx ? join13(ctx.gitDir, "
|
|
12455
|
+
return ctx ? join13(stateDirectory(ctx.gitDir), "audit.jsonl") : null;
|
|
12357
12456
|
}
|
|
12358
12457
|
function recordAuditFindings(findings, context) {
|
|
12359
12458
|
if (findings.length === 0) return;
|
|
12360
|
-
const path = configuredAuditPath(context.cwd);
|
|
12361
|
-
if (!path) return;
|
|
12362
12459
|
try {
|
|
12460
|
+
const path = configuredAuditPath(context.cwd);
|
|
12461
|
+
if (!path) return;
|
|
12363
12462
|
mkdirSync5(dirname4(path), { recursive: true });
|
|
12364
12463
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
12365
12464
|
const session = sessionHash(context.sessionId);
|
|
@@ -12378,7 +12477,7 @@ function recordAuditFindings(findings, context) {
|
|
|
12378
12477
|
};
|
|
12379
12478
|
return JSON.stringify(event);
|
|
12380
12479
|
});
|
|
12381
|
-
|
|
12480
|
+
appendRegular(path, lines.join("\n") + "\n");
|
|
12382
12481
|
} catch {
|
|
12383
12482
|
}
|
|
12384
12483
|
}
|
|
@@ -12613,6 +12712,7 @@ var init_audit = __esm({
|
|
|
12613
12712
|
"src/cli/audit.ts"() {
|
|
12614
12713
|
"use strict";
|
|
12615
12714
|
init_repo_context();
|
|
12715
|
+
init_disk();
|
|
12616
12716
|
AUDIT_SCHEMA_VERSION = 1;
|
|
12617
12717
|
AUDIT_LOG_ENV = "TAMPERWARD_AUDIT_LOG";
|
|
12618
12718
|
MAX_AUDIT_LINE_BYTES = 16 * 1024;
|
|
@@ -12631,7 +12731,7 @@ var init_audit = __esm({
|
|
|
12631
12731
|
});
|
|
12632
12732
|
|
|
12633
12733
|
// src/cli/hook.ts
|
|
12634
|
-
import { readFileSync as readFileSync6,
|
|
12734
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync6 } from "node:fs";
|
|
12635
12735
|
import { createHash as createHash7 } from "node:crypto";
|
|
12636
12736
|
function setSnapshotCache(cache3) {
|
|
12637
12737
|
snapshotCache = cache3;
|
|
@@ -12666,7 +12766,7 @@ function recordDenylog(blocks2) {
|
|
|
12666
12766
|
const log = process.env.TAMPERWARD_DENYLOG;
|
|
12667
12767
|
if (!log) return;
|
|
12668
12768
|
try {
|
|
12669
|
-
|
|
12769
|
+
appendRegular(log, blocks2.map((b) => b.rule).join(",") + "\n");
|
|
12670
12770
|
} catch {
|
|
12671
12771
|
}
|
|
12672
12772
|
}
|
|
@@ -12985,7 +13085,7 @@ function recordWarns(cwd, sessionId, warns) {
|
|
|
12985
13085
|
const log = process.env.TAMPERWARD_DENYLOG;
|
|
12986
13086
|
if (!log) return;
|
|
12987
13087
|
try {
|
|
12988
|
-
|
|
13088
|
+
appendRegular(log, warns.map((w) => `warn:${w.rule}:${w.file ?? ""}`).join("\n") + "\n");
|
|
12989
13089
|
} catch {
|
|
12990
13090
|
}
|
|
12991
13091
|
}
|
|
@@ -12995,7 +13095,7 @@ function recordObserverHealth(cwd, sessionId, state, reason) {
|
|
|
12995
13095
|
if (!log) return;
|
|
12996
13096
|
const detail = (reason ?? "").replace(/[\r\n]+/g, " ").trim();
|
|
12997
13097
|
try {
|
|
12998
|
-
|
|
13098
|
+
appendRegular(
|
|
12999
13099
|
log,
|
|
13000
13100
|
`warn:transient-observer:${state}${detail ? ":" + detail : ""}
|
|
13001
13101
|
`
|
|
@@ -13112,7 +13212,7 @@ var init_hook = __esm({
|
|
|
13112
13212
|
});
|
|
13113
13213
|
|
|
13114
13214
|
// src/ptree-cache.ts
|
|
13115
|
-
import { lstatSync as
|
|
13215
|
+
import { lstatSync as lstatSync7 } from "node:fs";
|
|
13116
13216
|
import { join as join14 } from "node:path";
|
|
13117
13217
|
function keyOf(st) {
|
|
13118
13218
|
return `${st.dev}:${st.ino}:${st.size}:${st.mode}:${st.mtimeNs}:${st.ctimeNs}`;
|
|
@@ -13166,7 +13266,7 @@ var init_ptree_cache = __esm({
|
|
|
13166
13266
|
const abs = join14(cwd, rel);
|
|
13167
13267
|
let st;
|
|
13168
13268
|
try {
|
|
13169
|
-
st =
|
|
13269
|
+
st = lstatSync7(abs, { bigint: true });
|
|
13170
13270
|
} catch {
|
|
13171
13271
|
this.map.delete(abs);
|
|
13172
13272
|
this.stats.misses++;
|
|
@@ -13188,7 +13288,7 @@ var init_ptree_cache = __esm({
|
|
|
13188
13288
|
const entry = compute();
|
|
13189
13289
|
let after;
|
|
13190
13290
|
try {
|
|
13191
|
-
after =
|
|
13291
|
+
after = lstatSync7(abs, { bigint: true });
|
|
13192
13292
|
} catch {
|
|
13193
13293
|
this.map.delete(abs);
|
|
13194
13294
|
return entry;
|
|
@@ -13206,7 +13306,7 @@ var init_ptree_cache = __esm({
|
|
|
13206
13306
|
});
|
|
13207
13307
|
|
|
13208
13308
|
// src/cli/hook-service.ts
|
|
13209
|
-
import { chmodSync, existsSync as existsSync7, lstatSync as
|
|
13309
|
+
import { chmodSync, existsSync as existsSync7, lstatSync as lstatSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync7, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "node:fs";
|
|
13210
13310
|
import { createConnection as createConnection2, createServer } from "node:net";
|
|
13211
13311
|
import { realpathSync as realpathSync4 } from "node:fs";
|
|
13212
13312
|
import { sep } from "node:path";
|
|
@@ -13289,13 +13389,13 @@ function withEnv(env, fn) {
|
|
|
13289
13389
|
}
|
|
13290
13390
|
function removeQuietly(p) {
|
|
13291
13391
|
try {
|
|
13292
|
-
|
|
13392
|
+
rmSync5(p, { force: true });
|
|
13293
13393
|
} catch {
|
|
13294
13394
|
}
|
|
13295
13395
|
}
|
|
13296
13396
|
function ensurePrivateDir(dir, uid) {
|
|
13297
13397
|
if (!existsSync7(dir)) mkdirSync6(dir, { recursive: true, mode: 448 });
|
|
13298
|
-
const st =
|
|
13398
|
+
const st = lstatSync8(dir);
|
|
13299
13399
|
if (!st.isDirectory()) throw new Error(`${dir} is not a directory`);
|
|
13300
13400
|
if (st.uid !== uid) throw new Error(`${dir} is owned by uid ${st.uid}, not ${uid}; refusing to serve from it`);
|
|
13301
13401
|
if ((st.mode & 63) !== 0) chmodSync(dir, 448);
|
|
@@ -13725,51 +13825,6 @@ var init_verifier_limits = __esm({
|
|
|
13725
13825
|
}
|
|
13726
13826
|
});
|
|
13727
13827
|
|
|
13728
|
-
// src/safe-write.ts
|
|
13729
|
-
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
13730
|
-
import { lstatSync as lstatSync8, renameSync as renameSync3, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
13731
|
-
function writeTargetKind(path) {
|
|
13732
|
-
let st;
|
|
13733
|
-
try {
|
|
13734
|
-
st = lstatSync8(path, { throwIfNoEntry: false });
|
|
13735
|
-
} catch (e) {
|
|
13736
|
-
if (errnoCode(e) === "ENOTDIR") return "absent";
|
|
13737
|
-
throw e;
|
|
13738
|
-
}
|
|
13739
|
-
if (!st) return "absent";
|
|
13740
|
-
if (st.isSymbolicLink()) return "symlink";
|
|
13741
|
-
return st.isFile() ? "file" : "irregular";
|
|
13742
|
-
}
|
|
13743
|
-
function refuseNonRegular(path) {
|
|
13744
|
-
switch (writeTargetKind(path)) {
|
|
13745
|
-
case "symlink":
|
|
13746
|
-
return "refusing: symlink \u2014 the target would be written instead of this path; replace the link with a regular file, then re-run";
|
|
13747
|
-
case "irregular":
|
|
13748
|
-
return "refusing: not a regular file \u2014 a directory or special file stands where a file is expected; remove it, then re-run";
|
|
13749
|
-
default:
|
|
13750
|
-
return null;
|
|
13751
|
-
}
|
|
13752
|
-
}
|
|
13753
|
-
function existingMode(path, fallback) {
|
|
13754
|
-
if (writeTargetKind(path) !== "file") return fallback;
|
|
13755
|
-
return lstatSync8(path).mode & 511;
|
|
13756
|
-
}
|
|
13757
|
-
function atomicReplaceFile(path, content, mode) {
|
|
13758
|
-
const tmp = `${path}.${process.pid}.${randomBytes2(8).toString("hex")}.tmp`;
|
|
13759
|
-
try {
|
|
13760
|
-
writeFileSync7(tmp, content, { encoding: "utf8", flag: "wx", mode });
|
|
13761
|
-
renameSync3(tmp, path);
|
|
13762
|
-
} finally {
|
|
13763
|
-
rmSync5(tmp, { force: true });
|
|
13764
|
-
}
|
|
13765
|
-
}
|
|
13766
|
-
var init_safe_write = __esm({
|
|
13767
|
-
"src/safe-write.ts"() {
|
|
13768
|
-
"use strict";
|
|
13769
|
-
init_narrow();
|
|
13770
|
-
}
|
|
13771
|
-
});
|
|
13772
|
-
|
|
13773
13828
|
// src/cli/init.ts
|
|
13774
13829
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
13775
13830
|
import { createHash as createHash8 } from "node:crypto";
|
|
@@ -15063,7 +15118,7 @@ var init_dependency_env = __esm({
|
|
|
15063
15118
|
|
|
15064
15119
|
// src/suite-diagnostics.ts
|
|
15065
15120
|
import { spawnSync } from "node:child_process";
|
|
15066
|
-
import { mkdtempSync as mkdtempSync2, rmSync as rmSync6, writeFileSync as
|
|
15121
|
+
import { mkdtempSync as mkdtempSync2, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "node:fs";
|
|
15067
15122
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
15068
15123
|
import { join as join17 } from "node:path";
|
|
15069
15124
|
function emptySuiteDiagnostics() {
|
|
@@ -15149,7 +15204,7 @@ function runCapturedProcessSync(executable, args, opts) {
|
|
|
15149
15204
|
const configFile = join17(stateDir2, "config.json");
|
|
15150
15205
|
const backstop = opts.backstopMs ?? 3e4;
|
|
15151
15206
|
try {
|
|
15152
|
-
|
|
15207
|
+
writeFileSync7(
|
|
15153
15208
|
configFile,
|
|
15154
15209
|
JSON.stringify({
|
|
15155
15210
|
executable,
|
|
@@ -15916,7 +15971,7 @@ var init_verifier_backend = __esm({
|
|
|
15916
15971
|
// src/verification-state.ts
|
|
15917
15972
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
15918
15973
|
import { createHash as createHash12 } from "node:crypto";
|
|
15919
|
-
import { mkdirSync as mkdirSync8, readFileSync as readFileSync11, rmSync as rmSync7
|
|
15974
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync11, rmSync as rmSync7 } from "node:fs";
|
|
15920
15975
|
import { dirname as dirname8, join as join19 } from "node:path";
|
|
15921
15976
|
function git2(args, cwd) {
|
|
15922
15977
|
return execFileSync8("git", args, {
|
|
@@ -16033,7 +16088,7 @@ function computeBinding(cwd, inputs, precomputed) {
|
|
|
16033
16088
|
}
|
|
16034
16089
|
function stateDir(cwd) {
|
|
16035
16090
|
const ctx = repoContext(cwd);
|
|
16036
|
-
return ctx ?
|
|
16091
|
+
return ctx ? stateDirectory(ctx.gitDir) : null;
|
|
16037
16092
|
}
|
|
16038
16093
|
function verificationRecordPath(cwd) {
|
|
16039
16094
|
const dir = stateDir(cwd);
|
|
@@ -16060,11 +16115,17 @@ function recordVerification(cwd, inputs, treeFingerprintValue) {
|
|
|
16060
16115
|
binding
|
|
16061
16116
|
};
|
|
16062
16117
|
mkdirSync8(dirname8(path), { recursive: true });
|
|
16063
|
-
|
|
16118
|
+
atomicReplaceFile(path, JSON.stringify(record) + "\n", 438);
|
|
16064
16119
|
return true;
|
|
16065
16120
|
}
|
|
16066
16121
|
function invalidateVerificationRecordIfCurrent(cwd) {
|
|
16067
|
-
|
|
16122
|
+
let record;
|
|
16123
|
+
try {
|
|
16124
|
+
record = readVerificationRecord(cwd);
|
|
16125
|
+
} catch (e) {
|
|
16126
|
+
if (e instanceof StateFileError) return false;
|
|
16127
|
+
throw e;
|
|
16128
|
+
}
|
|
16068
16129
|
if (!record) return false;
|
|
16069
16130
|
let live;
|
|
16070
16131
|
try {
|
|
@@ -16126,12 +16187,8 @@ function parseVerificationRecord(value) {
|
|
|
16126
16187
|
function readVerificationRecord(cwd) {
|
|
16127
16188
|
const path = verificationRecordPath(cwd);
|
|
16128
16189
|
if (!path) return null;
|
|
16129
|
-
|
|
16130
|
-
|
|
16131
|
-
raw = readFileSync11(path, "utf8");
|
|
16132
|
-
} catch {
|
|
16133
|
-
return null;
|
|
16134
|
-
}
|
|
16190
|
+
const raw = readStateFile(path);
|
|
16191
|
+
if (raw === null) return null;
|
|
16135
16192
|
let parsed;
|
|
16136
16193
|
try {
|
|
16137
16194
|
parsed = JSON.parse(raw);
|
|
@@ -16149,25 +16206,25 @@ function pidAlive3(pid) {
|
|
|
16149
16206
|
}
|
|
16150
16207
|
}
|
|
16151
16208
|
function beginVerifying(cwd) {
|
|
16152
|
-
const path = verifyingMarkerPath(cwd);
|
|
16153
|
-
if (!path) return false;
|
|
16154
16209
|
try {
|
|
16210
|
+
const path = verifyingMarkerPath(cwd);
|
|
16211
|
+
if (!path) return false;
|
|
16155
16212
|
const marker = {
|
|
16156
16213
|
schema_version: VERIFICATION_STATE_SCHEMA_VERSION,
|
|
16157
16214
|
pid: process.pid,
|
|
16158
16215
|
started_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
16159
16216
|
};
|
|
16160
16217
|
mkdirSync8(dirname8(path), { recursive: true });
|
|
16161
|
-
|
|
16218
|
+
atomicReplaceFile(path, JSON.stringify(marker) + "\n", 438);
|
|
16162
16219
|
return true;
|
|
16163
16220
|
} catch {
|
|
16164
16221
|
return false;
|
|
16165
16222
|
}
|
|
16166
16223
|
}
|
|
16167
16224
|
function endVerifying(cwd) {
|
|
16168
|
-
const path = verifyingMarkerPath(cwd);
|
|
16169
|
-
if (!path) return;
|
|
16170
16225
|
try {
|
|
16226
|
+
const path = verifyingMarkerPath(cwd);
|
|
16227
|
+
if (!path) return;
|
|
16171
16228
|
rmSync7(path, { force: true });
|
|
16172
16229
|
} catch {
|
|
16173
16230
|
}
|
|
@@ -16175,9 +16232,11 @@ function endVerifying(cwd) {
|
|
|
16175
16232
|
function readVerifyingMarker(cwd) {
|
|
16176
16233
|
const path = verifyingMarkerPath(cwd);
|
|
16177
16234
|
if (!path) return null;
|
|
16235
|
+
const raw = readStateFile(path);
|
|
16236
|
+
if (raw === null) return null;
|
|
16178
16237
|
let parsed;
|
|
16179
16238
|
try {
|
|
16180
|
-
parsed = JSON.parse(
|
|
16239
|
+
parsed = JSON.parse(raw);
|
|
16181
16240
|
} catch {
|
|
16182
16241
|
return null;
|
|
16183
16242
|
}
|
|
@@ -16204,10 +16263,22 @@ function environmentInputDivergences(recorded, live) {
|
|
|
16204
16263
|
return ENVIRONMENT_INPUTS.filter((input) => recorded[input] !== live[input]);
|
|
16205
16264
|
}
|
|
16206
16265
|
function evaluateVerificationState(cwd) {
|
|
16207
|
-
|
|
16266
|
+
let marker;
|
|
16267
|
+
let record;
|
|
16268
|
+
try {
|
|
16269
|
+
marker = readVerifyingMarker(cwd);
|
|
16270
|
+
record = marker ? null : readVerificationRecord(cwd);
|
|
16271
|
+
} catch (e) {
|
|
16272
|
+
if (!(e instanceof StateFileError)) throw e;
|
|
16273
|
+
return {
|
|
16274
|
+
state: "UNVERIFIED",
|
|
16275
|
+
reason: "the verification store cannot be read: something other than a regular file stands at a record path",
|
|
16276
|
+
detail: e.message
|
|
16277
|
+
};
|
|
16278
|
+
}
|
|
16279
|
+
if (marker) {
|
|
16208
16280
|
return { state: "VERIFYING", reason: "a verification is in progress" };
|
|
16209
16281
|
}
|
|
16210
|
-
const record = readVerificationRecord(cwd);
|
|
16211
16282
|
if (!record) {
|
|
16212
16283
|
return {
|
|
16213
16284
|
state: "UNVERIFIED",
|
|
@@ -16262,6 +16333,8 @@ var init_verification_state = __esm({
|
|
|
16262
16333
|
init_repo_context();
|
|
16263
16334
|
init_wiring();
|
|
16264
16335
|
init_dependency_env();
|
|
16336
|
+
init_disk();
|
|
16337
|
+
init_safe_write();
|
|
16265
16338
|
VERIFICATION_STATE_SCHEMA_VERSION = 1;
|
|
16266
16339
|
BINDING_INPUTS = [
|
|
16267
16340
|
"tree",
|
|
@@ -16311,7 +16384,7 @@ var init_verification_state = __esm({
|
|
|
16311
16384
|
|
|
16312
16385
|
// src/verification-receipt.ts
|
|
16313
16386
|
import { createHash as createHash13 } from "node:crypto";
|
|
16314
|
-
import { mkdirSync as mkdirSync9, rmSync as rmSync8
|
|
16387
|
+
import { mkdirSync as mkdirSync9, rmSync as rmSync8 } from "node:fs";
|
|
16315
16388
|
import { dirname as dirname9, join as join20 } from "node:path";
|
|
16316
16389
|
function isRecord5(v) {
|
|
16317
16390
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
@@ -16351,23 +16424,23 @@ function receiptFromRecord(record) {
|
|
|
16351
16424
|
}
|
|
16352
16425
|
function receiptPath(cwd) {
|
|
16353
16426
|
const ctx = repoContext(cwd);
|
|
16354
|
-
return ctx ? join20(ctx.gitDir, "
|
|
16427
|
+
return ctx ? join20(stateDirectory(ctx.gitDir), "verification-receipt.json") : null;
|
|
16355
16428
|
}
|
|
16356
16429
|
function storeReceipt(cwd, receipt) {
|
|
16357
|
-
const path = receiptPath(cwd);
|
|
16358
|
-
if (!path) return false;
|
|
16359
16430
|
try {
|
|
16431
|
+
const path = receiptPath(cwd);
|
|
16432
|
+
if (!path) return false;
|
|
16360
16433
|
mkdirSync9(dirname9(path), { recursive: true });
|
|
16361
|
-
|
|
16434
|
+
atomicReplaceFile(path, JSON.stringify(receipt) + "\n", 438);
|
|
16362
16435
|
return true;
|
|
16363
16436
|
} catch {
|
|
16364
16437
|
return false;
|
|
16365
16438
|
}
|
|
16366
16439
|
}
|
|
16367
16440
|
function removeStoredReceipt(cwd) {
|
|
16368
|
-
const path = receiptPath(cwd);
|
|
16369
|
-
if (!path) return;
|
|
16370
16441
|
try {
|
|
16442
|
+
const path = receiptPath(cwd);
|
|
16443
|
+
if (!path) return;
|
|
16371
16444
|
rmSync8(path, { force: true });
|
|
16372
16445
|
} catch {
|
|
16373
16446
|
}
|
|
@@ -16529,6 +16602,8 @@ var RECEIPT_SCHEMA_VERSION, RECEIPT_STAGE_RESULTS, RECEIPT_INTEGRITY_RESULTS;
|
|
|
16529
16602
|
var init_verification_receipt = __esm({
|
|
16530
16603
|
"src/verification-receipt.ts"() {
|
|
16531
16604
|
"use strict";
|
|
16605
|
+
init_disk();
|
|
16606
|
+
init_safe_write();
|
|
16532
16607
|
init_repo_context();
|
|
16533
16608
|
init_verification_state();
|
|
16534
16609
|
init_machine_output();
|
|
@@ -16541,7 +16616,7 @@ var init_verification_receipt = __esm({
|
|
|
16541
16616
|
// src/cli/verify.ts
|
|
16542
16617
|
import { execFileSync as execFileSync9, spawnSync as spawnSync3 } from "node:child_process";
|
|
16543
16618
|
import { createHash as createHash14 } from "node:crypto";
|
|
16544
|
-
import { chmodSync as chmodSync2, cpSync, lstatSync as lstatSync10, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, readFileSync as readFileSync12, readlinkSync as readlinkSync3, rmSync as rmSync9, symlinkSync, writeFileSync as
|
|
16619
|
+
import { chmodSync as chmodSync2, cpSync, lstatSync as lstatSync10, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, readFileSync as readFileSync12, readlinkSync as readlinkSync3, rmSync as rmSync9, symlinkSync, writeFileSync as writeFileSync8, existsSync as existsSync10 } from "node:fs";
|
|
16545
16620
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
16546
16621
|
import { dirname as dirname10, isAbsolute as isAbsolute11, join as join21, relative as relative6, resolve as resolve9, sep as sep4 } from "node:path";
|
|
16547
16622
|
function oracleAssuranceReport() {
|
|
@@ -16736,7 +16811,7 @@ function probeFilesystemCaseSensitivity(dir) {
|
|
|
16736
16811
|
const upper = join21(dir, ".tw-case-probe-A");
|
|
16737
16812
|
const lower = join21(dir, ".tw-case-probe-a");
|
|
16738
16813
|
try {
|
|
16739
|
-
|
|
16814
|
+
writeFileSync8(upper, "", { flag: "wx" });
|
|
16740
16815
|
return !existsSync10(lower);
|
|
16741
16816
|
} finally {
|
|
16742
16817
|
rmSync9(upper, { force: true });
|
|
@@ -16839,7 +16914,7 @@ function overlayPristine(cwd, base, dest, policy, cmd, dependencyRoot, caseSensi
|
|
|
16839
16914
|
safeSymlink(target, out3, dest, `the base's ${e.path}`);
|
|
16840
16915
|
restoredLinks.push({ path: e.path, out: out3, target });
|
|
16841
16916
|
} else {
|
|
16842
|
-
|
|
16917
|
+
writeFileSync8(out3, content);
|
|
16843
16918
|
chmodSync2(out3, parseInt(e.mode.slice(-4), 8) & 511);
|
|
16844
16919
|
}
|
|
16845
16920
|
restored.push(e.path);
|
|
@@ -16864,7 +16939,7 @@ function suiteEnv(scratch) {
|
|
|
16864
16939
|
}
|
|
16865
16940
|
const userRc = join21(scratch, "npmrc-user");
|
|
16866
16941
|
const globalRc = join21(scratch, "npmrc-global");
|
|
16867
|
-
for (const f of [userRc, globalRc])
|
|
16942
|
+
for (const f of [userRc, globalRc]) writeFileSync8(f, "", { mode: 292 });
|
|
16868
16943
|
env.npm_config_userconfig = userRc;
|
|
16869
16944
|
env.npm_config_globalconfig = globalRc;
|
|
16870
16945
|
env.npm_config_node_options = " ";
|
|
@@ -17615,7 +17690,7 @@ var init_verify = __esm({
|
|
|
17615
17690
|
// src/cli/run.ts
|
|
17616
17691
|
import { execFileSync as execFileSync10, spawn, spawnSync as spawnSync4 } from "node:child_process";
|
|
17617
17692
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
17618
|
-
import { accessSync as accessSync3, constants as fsConstants, mkdtempSync as mkdtempSync4, readdirSync as readdirSync4, readFileSync as readFileSync13, readlinkSync as readlinkSync4, realpathSync as realpathSync8, rmSync as rmSync10, statSync as statSync5, writeFileSync as
|
|
17693
|
+
import { accessSync as accessSync3, constants as fsConstants, mkdtempSync as mkdtempSync4, readdirSync as readdirSync4, readFileSync as readFileSync13, readlinkSync as readlinkSync4, realpathSync as realpathSync8, rmSync as rmSync10, statSync as statSync5, writeFileSync as writeFileSync9 } from "node:fs";
|
|
17619
17694
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
17620
17695
|
import { dirname as dirname11, join as join22, resolve as resolve10 } from "node:path";
|
|
17621
17696
|
function authoritativeRunLifecyclePlatform(platform = process.platform) {
|
|
@@ -17712,7 +17787,7 @@ function runAgentSupervised(argv, cwd, budgetSecs, linuxPythonCandidates, lifecy
|
|
|
17712
17787
|
failure: trustedPython.reason ?? "trusted Linux python3 interpreter is unavailable"
|
|
17713
17788
|
};
|
|
17714
17789
|
}
|
|
17715
|
-
|
|
17790
|
+
writeFileSync9(agentEnvFile, JSON.stringify(process.env), { mode: 384 });
|
|
17716
17791
|
executable = trustedPython.path;
|
|
17717
17792
|
args = [
|
|
17718
17793
|
"-I",
|
|
@@ -17823,8 +17898,7 @@ function observerExited(pid) {
|
|
|
17823
17898
|
function supervisedObserverLog(cwd) {
|
|
17824
17899
|
const gd = gitDir(cwd) ?? join22(cwd, ".git");
|
|
17825
17900
|
return join22(
|
|
17826
|
-
gd,
|
|
17827
|
-
"tamperward",
|
|
17901
|
+
stateDirectory(gd),
|
|
17828
17902
|
`run-observer-${process.pid}-${Date.now()}-${randomBytes3(4).toString("hex")}.jsonl`
|
|
17829
17903
|
);
|
|
17830
17904
|
}
|
|
@@ -19270,7 +19344,10 @@ function renderStatus(model, colour) {
|
|
|
19270
19344
|
if (v.state === "STALE" && v.reason) rows.push(["Reason", v.reason]);
|
|
19271
19345
|
else if (v.state === "BROKEN") rows.push(["Reason", v.detail ?? v.reason ?? "authority wiring is invalid"]);
|
|
19272
19346
|
else if (v.state === "VERIFYING") rows.push(["Reason", v.reason ?? "a verification is in progress"]);
|
|
19273
|
-
else if (v.state === "UNVERIFIED"
|
|
19347
|
+
else if (v.state === "UNVERIFIED" && v.detail) {
|
|
19348
|
+
rows.push(["Reason", v.detail]);
|
|
19349
|
+
rows.push(["Next", "remove what stands at that path, then run `tamperward verify`"]);
|
|
19350
|
+
} else if (v.state === "UNVERIFIED") rows.push(["Next", "run `tamperward verify` to establish a verified baseline"]);
|
|
19274
19351
|
if (rows.length) {
|
|
19275
19352
|
lines.push("");
|
|
19276
19353
|
const width = Math.max(...rows.map(([k]) => k.length));
|
|
@@ -21005,7 +21082,7 @@ var init_adapter3 = __esm({
|
|
|
21005
21082
|
|
|
21006
21083
|
// src/adapters/copilot-sdk/changes.ts
|
|
21007
21084
|
import { execFileSync as execFileSync13 } from "node:child_process";
|
|
21008
|
-
import { mkdtempSync as mkdtempSync6, writeFileSync as
|
|
21085
|
+
import { mkdtempSync as mkdtempSync6, writeFileSync as writeFileSync10, readFileSync as readFileSync17, rmSync as rmSync12, existsSync as existsSync14, realpathSync as realpathSync10 } from "node:fs";
|
|
21009
21086
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
21010
21087
|
import { basename as basename5, dirname as dirname12, isAbsolute as isAbsolute16, relative as relative11, resolve as resolve15, join as join26 } from "node:path";
|
|
21011
21088
|
function asStr4(v) {
|
|
@@ -21082,9 +21159,9 @@ function reconstructAfterViaGit(rawDiff, display2, before, isCreate) {
|
|
|
21082
21159
|
const dir = mkdtempSync6(join26(tmpdir7(), "hf-sdk-apply-"));
|
|
21083
21160
|
try {
|
|
21084
21161
|
const targetPath = join26(dir, TARGET);
|
|
21085
|
-
if (op !== "create")
|
|
21162
|
+
if (op !== "create") writeFileSync10(targetPath, before ?? "");
|
|
21086
21163
|
const patchPath = join26(dir, "change.patch");
|
|
21087
|
-
|
|
21164
|
+
writeFileSync10(patchPath, patch);
|
|
21088
21165
|
const git8 = (extra) => execFileSync13("git", ["apply", ...extra, patchPath], {
|
|
21089
21166
|
cwd: dir,
|
|
21090
21167
|
encoding: "utf8",
|
|
@@ -21852,17 +21929,19 @@ var init_runtime_qualification = __esm({
|
|
|
21852
21929
|
|
|
21853
21930
|
// src/cli/runtime.ts
|
|
21854
21931
|
import { execFileSync as execFileSync14 } from "node:child_process";
|
|
21855
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync18
|
|
21932
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync18 } from "node:fs";
|
|
21856
21933
|
import { join as join27, dirname as dirname13 } from "node:path";
|
|
21857
21934
|
function storePath(cwd) {
|
|
21858
21935
|
const dir = gitDir(cwd);
|
|
21859
|
-
return dir ? join27(dir, "
|
|
21936
|
+
return dir ? join27(stateDirectory(dir), "runtime-qualification.json") : null;
|
|
21860
21937
|
}
|
|
21861
21938
|
function readStore(cwd) {
|
|
21862
21939
|
const path = storePath(cwd);
|
|
21863
|
-
if (!path
|
|
21940
|
+
if (!path) return null;
|
|
21941
|
+
const raw = readStateFile(path);
|
|
21942
|
+
if (raw === null) return null;
|
|
21864
21943
|
try {
|
|
21865
|
-
const parsed = JSON.parse(
|
|
21944
|
+
const parsed = JSON.parse(raw);
|
|
21866
21945
|
if (parsed && typeof parsed === "object" && parsed.records && typeof parsed.records === "object") return parsed;
|
|
21867
21946
|
} catch {
|
|
21868
21947
|
return null;
|
|
@@ -21993,7 +22072,7 @@ function writeRecord(cwd, id, report2) {
|
|
|
21993
22072
|
store.updated_at = report2.timestamp;
|
|
21994
22073
|
try {
|
|
21995
22074
|
mkdirSync11(dirname13(path), { recursive: true });
|
|
21996
|
-
|
|
22075
|
+
atomicReplaceFile(path, JSON.stringify(store, null, 2) + "\n", 384);
|
|
21997
22076
|
return true;
|
|
21998
22077
|
} catch {
|
|
21999
22078
|
return false;
|
|
@@ -22173,7 +22252,13 @@ function emit2(report2, opts, cwd) {
|
|
|
22173
22252
|
renderText3(report2, cwd);
|
|
22174
22253
|
}
|
|
22175
22254
|
function storedQualification(adapter, cwd, opts = {}) {
|
|
22176
|
-
|
|
22255
|
+
let raw;
|
|
22256
|
+
try {
|
|
22257
|
+
raw = readStore(cwd)?.records[adapter.name];
|
|
22258
|
+
} catch (e) {
|
|
22259
|
+
if (e instanceof StateFileError) return { state: "rejected", reason: e.message };
|
|
22260
|
+
throw e;
|
|
22261
|
+
}
|
|
22177
22262
|
if (raw === void 0) return { state: "none" };
|
|
22178
22263
|
const validated = validateStoredReport(raw);
|
|
22179
22264
|
if ("reason" in validated) return { state: "rejected", reason: validated.reason };
|
|
@@ -22212,10 +22297,18 @@ function runRuntime(sub, opts) {
|
|
|
22212
22297
|
}
|
|
22213
22298
|
const { binding, assessments } = buildQualification(target, opts, cwd);
|
|
22214
22299
|
const report2 = reportFrom("verify", binding, assessments);
|
|
22215
|
-
|
|
22300
|
+
let wrote = false;
|
|
22301
|
+
let refused;
|
|
22302
|
+
try {
|
|
22303
|
+
wrote = writeRecord(cwd, target.name, report2);
|
|
22304
|
+
} catch (e) {
|
|
22305
|
+
if (!(e instanceof StateFileError)) throw e;
|
|
22306
|
+
refused = e.message;
|
|
22307
|
+
}
|
|
22216
22308
|
if (!wrote) {
|
|
22217
|
-
const
|
|
22218
|
-
const
|
|
22309
|
+
const dir = gitDir(cwd);
|
|
22310
|
+
const dest = dir ? join27(dir, "tamperward", "runtime-qualification.json") : null;
|
|
22311
|
+
const reason = `could not persist the qualification to ${dest ?? "the git-local store (no repository found)"}${refused ? ` (${refused})` : ""}; nothing was recorded, so \`tamperward runtime status\` will report UNQUALIFIED`;
|
|
22219
22312
|
const failure = {
|
|
22220
22313
|
...report2,
|
|
22221
22314
|
recorded: false,
|
|
@@ -22285,6 +22378,8 @@ var HONESTY_NOTE, CAP_ID_SET, STATE_SEVERITY, AGGREGATE_SEVERITY, RUNTIME_SUBCOM
|
|
|
22285
22378
|
var init_runtime = __esm({
|
|
22286
22379
|
"src/cli/runtime.ts"() {
|
|
22287
22380
|
"use strict";
|
|
22381
|
+
init_disk();
|
|
22382
|
+
init_safe_write();
|
|
22288
22383
|
init_build();
|
|
22289
22384
|
init_wiring();
|
|
22290
22385
|
init_machine_output();
|
|
@@ -23493,7 +23588,7 @@ var init_record = __esm({
|
|
|
23493
23588
|
// src/research/run.ts
|
|
23494
23589
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
23495
23590
|
import { execFileSync as execFileSync16 } from "node:child_process";
|
|
23496
|
-
import { closeSync as closeSync5, existsSync as existsSync16, linkSync, mkdirSync as mkdirSync12, openSync as openSync5, readFileSync as readFileSync21, renameSync as renameSync4, rmSync as rmSync14, unlinkSync, writeFileSync as
|
|
23591
|
+
import { closeSync as closeSync5, existsSync as existsSync16, linkSync, mkdirSync as mkdirSync12, openSync as openSync5, readFileSync as readFileSync21, renameSync as renameSync4, rmSync as rmSync14, unlinkSync, writeFileSync as writeFileSync11, writeSync as writeSync2 } from "node:fs";
|
|
23497
23592
|
import { hostname } from "node:os";
|
|
23498
23593
|
import { join as join29, resolve as resolve19 } from "node:path";
|
|
23499
23594
|
function git7(args, cwd) {
|
|
@@ -23574,7 +23669,7 @@ function acquireResearchLock(ledger, breakStaleLock = false) {
|
|
|
23574
23669
|
let fd = -1;
|
|
23575
23670
|
try {
|
|
23576
23671
|
fd = openSync5(path, "wx", 384);
|
|
23577
|
-
|
|
23672
|
+
writeSync2(fd, text);
|
|
23578
23673
|
closeSync5(fd);
|
|
23579
23674
|
fd = -1;
|
|
23580
23675
|
} catch (e) {
|
|
@@ -23638,7 +23733,7 @@ function resumableRecord(path, expected) {
|
|
|
23638
23733
|
}
|
|
23639
23734
|
function writeRecordAtomically(path, text) {
|
|
23640
23735
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
23641
|
-
|
|
23736
|
+
writeFileSync11(tmp, text);
|
|
23642
23737
|
renameSync4(tmp, path);
|
|
23643
23738
|
}
|
|
23644
23739
|
function cloneArgs(repo, ws3) {
|
|
@@ -24239,7 +24334,7 @@ var init_summarize = __esm({
|
|
|
24239
24334
|
|
|
24240
24335
|
// src/research/init.ts
|
|
24241
24336
|
import { createHash as createHash17 } from "node:crypto";
|
|
24242
|
-
import { existsSync as existsSync17, mkdirSync as mkdirSync13, readFileSync as readFileSync23, writeFileSync as
|
|
24337
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync13, readFileSync as readFileSync23, writeFileSync as writeFileSync12 } from "node:fs";
|
|
24243
24338
|
import { basename as basename6, dirname as dirname15, resolve as resolve21 } from "node:path";
|
|
24244
24339
|
function idFrom(repo) {
|
|
24245
24340
|
const clean = repo.replace(/[\\/]$/, "").split(/[\\/]/).pop() || "task";
|
|
@@ -24269,7 +24364,7 @@ function createResearchManifest(opts) {
|
|
|
24269
24364
|
};
|
|
24270
24365
|
const text = JSON.stringify(doc, null, 2) + "\n";
|
|
24271
24366
|
mkdirSync13(dirname15(out3), { recursive: true });
|
|
24272
|
-
|
|
24367
|
+
writeFileSync12(out3, text, { flag: "wx", mode: 384 });
|
|
24273
24368
|
const parsed = readManifest(out3);
|
|
24274
24369
|
if (parsed.tasks.length !== 1 || parsed.tasks[0].id !== id) throw new ResearchError(`research init wrote an invalid manifest ${out3}`);
|
|
24275
24370
|
return out3;
|
|
@@ -24359,7 +24454,7 @@ var init_report2 = __esm({
|
|
|
24359
24454
|
import { createHash as createHash18 } from "node:crypto";
|
|
24360
24455
|
import { isDeepStrictEqual } from "node:util";
|
|
24361
24456
|
import { gzipSync, gunzipSync } from "node:zlib";
|
|
24362
|
-
import { mkdirSync as mkdirSync14, readFileSync as readFileSync24, writeFileSync as
|
|
24457
|
+
import { mkdirSync as mkdirSync14, readFileSync as readFileSync24, writeFileSync as writeFileSync13 } from "node:fs";
|
|
24363
24458
|
import { dirname as dirname16, resolve as resolve22 } from "node:path";
|
|
24364
24459
|
function octal(value, width) {
|
|
24365
24460
|
return value.toString(8).padStart(width - 1, "0") + "\0";
|
|
@@ -24559,7 +24654,7 @@ function createResearchBundle(opts) {
|
|
|
24559
24654
|
entries.push({ name: "provenance.json", bytes: jsonBytes(provenance) });
|
|
24560
24655
|
const out3 = resolve22(opts.out);
|
|
24561
24656
|
mkdirSync14(dirname16(out3), { recursive: true });
|
|
24562
|
-
|
|
24657
|
+
writeFileSync13(out3, gzipSync(makeTar(entries)), { flag: "wx", mode: 384 });
|
|
24563
24658
|
return out3;
|
|
24564
24659
|
}
|
|
24565
24660
|
function runResearchBundle(opts) {
|
|
@@ -24706,7 +24801,7 @@ var init_research = __esm({
|
|
|
24706
24801
|
});
|
|
24707
24802
|
|
|
24708
24803
|
// src/cli/receipt.ts
|
|
24709
|
-
import { appendFileSync as
|
|
24804
|
+
import { appendFileSync as appendFileSync3, readFileSync as readFileSync25, writeFileSync as writeFileSync14 } from "node:fs";
|
|
24710
24805
|
function parseReceipt(args) {
|
|
24711
24806
|
const [sub, ...rest] = args;
|
|
24712
24807
|
const exportOpts = {};
|
|
@@ -24808,7 +24903,7 @@ function runReceiptExport(opts = {}) {
|
|
|
24808
24903
|
const serialized = JSON.stringify(receipt) + "\n";
|
|
24809
24904
|
if (opts.out) {
|
|
24810
24905
|
try {
|
|
24811
|
-
|
|
24906
|
+
writeFileSync14(opts.out, serialized);
|
|
24812
24907
|
} catch (e) {
|
|
24813
24908
|
process.stderr.write(`tamperward: could not write receipt to ${opts.out} (${e instanceof Error ? e.message : String(e)})
|
|
24814
24909
|
`);
|
|
@@ -25030,7 +25125,7 @@ function writeJobSummary(r, receipt, ciBinding, adjudicatedTree) {
|
|
|
25030
25125
|
for (const d of r.divergence) md.push(`- ${d}`);
|
|
25031
25126
|
md.push("");
|
|
25032
25127
|
try {
|
|
25033
|
-
|
|
25128
|
+
appendFileSync3(path, md.join("\n") + "\n");
|
|
25034
25129
|
} catch {
|
|
25035
25130
|
}
|
|
25036
25131
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tamperward",
|
|
3
|
-
"version": "2.39.
|
|
3
|
+
"version": "2.39.12",
|
|
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",
|