@devrouter/cli 0.1.1 → 0.1.2
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/devrouter-lifecycle-worker.js +207 -67
- package/dist/devrouter.js +404 -141
- package/package.json +2 -1
- package/upgrade-prompts/0.1.2.md +57 -0
package/dist/devrouter.js
CHANGED
|
@@ -4275,7 +4275,7 @@ function loadRepoConfig(repoPath, read2 = (file) => import_node_fs7.default.read
|
|
|
4275
4275
|
const config = parseConfig(parsed ?? {}, configPath);
|
|
4276
4276
|
const requiredVersion = config.devrouter?.version;
|
|
4277
4277
|
if (requiredVersion && !hasWarnedVersionMismatch) {
|
|
4278
|
-
const cliVersion = true ? "0.1.
|
|
4278
|
+
const cliVersion = true ? "0.1.2" : "0.0.0-dev";
|
|
4279
4279
|
if (cliVersion !== "0.0.0-dev" && compareSemver(requiredVersion, cliVersion) > 0) {
|
|
4280
4280
|
hasWarnedVersionMismatch = true;
|
|
4281
4281
|
process.stderr.write(
|
|
@@ -5263,10 +5263,11 @@ function serializeSnapshot(snapshot) {
|
|
|
5263
5263
|
throw new Error("Capacity reservation snapshot exceeds byte limit.");
|
|
5264
5264
|
return contents;
|
|
5265
5265
|
}
|
|
5266
|
-
var import_node_fs9, import_node_path11, MAX_BYTES2, CapacityHistoryError, CapacitySnapshotChangedError, CapacityStore;
|
|
5266
|
+
var import_node_crypto6, import_node_fs9, import_node_path11, MAX_BYTES2, CapacityHistoryError, CapacitySnapshotChangedError, CapacityStore;
|
|
5267
5267
|
var init_capacity_store = __esm({
|
|
5268
5268
|
"src/core/capacity-store.ts"() {
|
|
5269
5269
|
"use strict";
|
|
5270
|
+
import_node_crypto6 = require("crypto");
|
|
5270
5271
|
import_node_fs9 = __toESM(require("fs"));
|
|
5271
5272
|
import_node_path11 = __toESM(require("path"));
|
|
5272
5273
|
init_atomic_file();
|
|
@@ -5274,11 +5275,13 @@ var init_capacity_store = __esm({
|
|
|
5274
5275
|
init_file_lock();
|
|
5275
5276
|
MAX_BYTES2 = 1048576;
|
|
5276
5277
|
CapacityHistoryError = class extends Error {
|
|
5277
|
-
constructor(code) {
|
|
5278
|
+
constructor(code, cause = null, location = null) {
|
|
5278
5279
|
super(
|
|
5279
5280
|
code === "capacity-ledger-lost" ? "Capacity ledger history is lost; restore verified capacity-reservations.json." : "Capacity history cannot be proven; inspect the private lifecycle journals."
|
|
5280
5281
|
);
|
|
5281
5282
|
this.code = code;
|
|
5283
|
+
this.cause = cause;
|
|
5284
|
+
this.location = location;
|
|
5282
5285
|
this.name = "CapacityHistoryError";
|
|
5283
5286
|
}
|
|
5284
5287
|
};
|
|
@@ -5351,9 +5354,10 @@ var init_capacity_store = __esm({
|
|
|
5351
5354
|
const buffer = Buffer.alloc(MAX_BYTES2 + 1);
|
|
5352
5355
|
const count = import_node_fs9.default.readSync(descriptor, buffer, 0, buffer.length, 0);
|
|
5353
5356
|
if (count > MAX_BYTES2) throw new Error("Capacity reservation snapshot exceeds byte limit.");
|
|
5354
|
-
const
|
|
5357
|
+
const bytes2 = buffer.subarray(0, count);
|
|
5358
|
+
const value = JSON.parse(bytes2.toString("utf8"));
|
|
5355
5359
|
validate(value);
|
|
5356
|
-
this.ledgerGeneration =
|
|
5360
|
+
this.ledgerGeneration = this.generationIdentity(stat, bytes2);
|
|
5357
5361
|
if (value.revision < minimumRevision) return { kind: "stale", revision: value.revision };
|
|
5358
5362
|
this.observedLedger = true;
|
|
5359
5363
|
return { kind: "intact", revision: value.revision, snapshot: value };
|
|
@@ -5406,20 +5410,30 @@ var init_capacity_store = __esm({
|
|
|
5406
5410
|
return snapshot;
|
|
5407
5411
|
}
|
|
5408
5412
|
commit(snapshot) {
|
|
5409
|
-
|
|
5413
|
+
const contents = serializeSnapshot(snapshot);
|
|
5414
|
+
this.write(this.file, contents);
|
|
5410
5415
|
this.observedLedger = true;
|
|
5411
|
-
this.rememberGeneration();
|
|
5416
|
+
this.rememberGeneration(contents);
|
|
5412
5417
|
this.establish();
|
|
5413
5418
|
}
|
|
5414
5419
|
/** Remember the published snapshot identity for the next generation fence. */
|
|
5415
|
-
rememberGeneration() {
|
|
5420
|
+
rememberGeneration(contents) {
|
|
5416
5421
|
try {
|
|
5417
5422
|
const stat = import_node_fs9.default.statSync(this.file);
|
|
5418
|
-
this.ledgerGeneration = stat.isFile() ?
|
|
5423
|
+
this.ledgerGeneration = stat.isFile() ? this.generationIdentity(stat, contents) : void 0;
|
|
5419
5424
|
} catch {
|
|
5420
5425
|
this.ledgerGeneration = void 0;
|
|
5421
5426
|
}
|
|
5422
5427
|
}
|
|
5428
|
+
/**
|
|
5429
|
+
* File identity plus content digest. Deleting and recreating the snapshot can
|
|
5430
|
+
* reuse its inode number, so the inode alone cannot fence a replacement that
|
|
5431
|
+
* reuses a revision number.
|
|
5432
|
+
*/
|
|
5433
|
+
generationIdentity(stat, contents) {
|
|
5434
|
+
const digest3 = (0, import_node_crypto6.createHash)("sha256").update(contents).digest("hex");
|
|
5435
|
+
return `${stat.dev}:${stat.ino}:${digest3}`;
|
|
5436
|
+
}
|
|
5423
5437
|
/**
|
|
5424
5438
|
* Durable evidence that recorded history is gone, for a stop whose physical
|
|
5425
5439
|
* cessation is already proven. The caller holds that proof; this writes no
|
|
@@ -5898,11 +5912,11 @@ function retain(session, previous) {
|
|
|
5898
5912
|
environment: { ...environment }
|
|
5899
5913
|
};
|
|
5900
5914
|
}
|
|
5901
|
-
var
|
|
5915
|
+
var import_node_crypto7, import_node_fs10, import_node_path12, CONTROLLER_SNAPSHOT_BYTES, EVENT_KINDS, LEGACY_EVENT_KINDS, PROJECTION_STATUSES, ControllerStore;
|
|
5902
5916
|
var init_controller_store = __esm({
|
|
5903
5917
|
"src/core/controller-store.ts"() {
|
|
5904
5918
|
"use strict";
|
|
5905
|
-
|
|
5919
|
+
import_node_crypto7 = require("crypto");
|
|
5906
5920
|
import_node_fs10 = __toESM(require("fs"));
|
|
5907
5921
|
import_node_path12 = __toESM(require("path"));
|
|
5908
5922
|
init_atomic_file();
|
|
@@ -5993,7 +6007,7 @@ var init_controller_store = __esm({
|
|
|
5993
6007
|
provenance(identity2) {
|
|
5994
6008
|
if (identity2.version !== 2) throw new Error("Controller binding provenance is unavailable.");
|
|
5995
6009
|
return {
|
|
5996
|
-
digest: (0,
|
|
6010
|
+
digest: (0, import_node_crypto7.createHash)("sha256").update(JSON.stringify(["devrouter-controller-binding-v1", identity2.store, identity2.key])).digest("hex"),
|
|
5997
6011
|
enrolledEpoch: identity2.enrolledEpoch
|
|
5998
6012
|
};
|
|
5999
6013
|
}
|
|
@@ -6017,7 +6031,7 @@ var init_controller_store = __esm({
|
|
|
6017
6031
|
if (!current || current.store !== captured.store || current.epoch !== captured.epoch || JSON.stringify(current.fingerprint) !== JSON.stringify(captured.fingerprint) || identity2?.version !== 2)
|
|
6018
6032
|
throw new Error("Controller binding incarnation changed.");
|
|
6019
6033
|
this.checkProvenance(current, identity2);
|
|
6020
|
-
return (0,
|
|
6034
|
+
return (0, import_node_crypto7.createHmac)("sha256", Buffer.from(identity2.key, "hex")).update(JSON.stringify({ owner, config })).digest("hex");
|
|
6021
6035
|
};
|
|
6022
6036
|
}
|
|
6023
6037
|
read() {
|
|
@@ -6070,7 +6084,7 @@ var init_controller_store = __esm({
|
|
|
6070
6084
|
const identity2 = existing?.version === 2 ? existing : {
|
|
6071
6085
|
version: 2,
|
|
6072
6086
|
store,
|
|
6073
|
-
key: (0,
|
|
6087
|
+
key: (0, import_node_crypto7.randomBytes)(32).toString("hex"),
|
|
6074
6088
|
enrolledEpoch: epoch
|
|
6075
6089
|
};
|
|
6076
6090
|
if (existing?.version !== 2)
|
|
@@ -6116,7 +6130,7 @@ var init_controller_store = __esm({
|
|
|
6116
6130
|
if (!previous) {
|
|
6117
6131
|
previous = {
|
|
6118
6132
|
version: 2,
|
|
6119
|
-
store: (0,
|
|
6133
|
+
store: (0, import_node_crypto7.randomUUID)(),
|
|
6120
6134
|
epoch: 0,
|
|
6121
6135
|
revision: 0,
|
|
6122
6136
|
parkingRevision: 0,
|
|
@@ -6259,7 +6273,7 @@ var init_reliability_contract = __esm({
|
|
|
6259
6273
|
|
|
6260
6274
|
// src/core/reliability-operation-store.ts
|
|
6261
6275
|
function installedCliVersion() {
|
|
6262
|
-
return true ? "0.1.
|
|
6276
|
+
return true ? "0.1.2" : "0.0.0-dev";
|
|
6263
6277
|
}
|
|
6264
6278
|
function compareCliVersions(left, right) {
|
|
6265
6279
|
const parts = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
@@ -6275,7 +6289,7 @@ function identityKey(identity2) {
|
|
|
6275
6289
|
if (!import_node_path13.default.isAbsolute(identity2.repoPath) || import_node_path13.default.resolve(identity2.repoPath) !== identity2.repoPath || identity2.repoPath.includes("\0") || identity2.workspace !== null && !isReliabilityId(identity2.workspace) || !["devpod", "devsy"].includes(identity2.provider)) {
|
|
6276
6290
|
throw new Error("Invalid reliability workspace identity.");
|
|
6277
6291
|
}
|
|
6278
|
-
return (0,
|
|
6292
|
+
return (0, import_node_crypto8.createHash)("sha256").update(identity2.repoPath).digest("hex");
|
|
6279
6293
|
}
|
|
6280
6294
|
function reliabilityOperationPath(identity2) {
|
|
6281
6295
|
return import_node_path13.default.join(DEVROUTER_HOME, "reliability", `${identityKey(identity2)}.json`);
|
|
@@ -6574,12 +6588,20 @@ function validate2(record5, identity2) {
|
|
|
6574
6588
|
}
|
|
6575
6589
|
}
|
|
6576
6590
|
}
|
|
6591
|
+
function journalEntryLocation(name) {
|
|
6592
|
+
const printable = name.replace(/[^A-Za-z0-9._-]/g, "?");
|
|
6593
|
+
return printable.length > MAX_REPORTED_ENTRY_NAME ? `${printable.slice(0, MAX_REPORTED_ENTRY_NAME - 3)}...` : printable;
|
|
6594
|
+
}
|
|
6577
6595
|
function createLifecycleCapacityStore(directory = import_node_path13.default.join(DEVROUTER_HOME, "controller")) {
|
|
6578
6596
|
return new CapacityStore(directory, void 0, () => {
|
|
6579
6597
|
try {
|
|
6580
6598
|
return listUnsettledCapacityBindings().floor;
|
|
6581
|
-
} catch {
|
|
6582
|
-
throw new CapacityHistoryError("capacity-history-unprovable")
|
|
6599
|
+
} catch (error) {
|
|
6600
|
+
throw error instanceof ReliabilityJournalError ? new CapacityHistoryError("capacity-history-unprovable", error.cause, error.location) : new CapacityHistoryError(
|
|
6601
|
+
"capacity-history-unprovable",
|
|
6602
|
+
"journal-enumeration-failed",
|
|
6603
|
+
null
|
|
6604
|
+
);
|
|
6583
6605
|
}
|
|
6584
6606
|
});
|
|
6585
6607
|
}
|
|
@@ -6638,11 +6660,12 @@ function readBoundedPrivateJson(file, label2) {
|
|
|
6638
6660
|
try {
|
|
6639
6661
|
const stat = import_node_fs11.default.fstatSync(descriptor);
|
|
6640
6662
|
if (!stat.isFile() || stat.uid !== process.getuid?.() || stat.size > MAX_RECORD_BYTES || (stat.mode & 63) !== 0) {
|
|
6641
|
-
throw new
|
|
6663
|
+
throw new JournalFileGuardError(`${label2} is not a bounded private file.`);
|
|
6642
6664
|
}
|
|
6643
6665
|
const bytes2 = Buffer.alloc(MAX_RECORD_BYTES + 1);
|
|
6644
6666
|
const count = import_node_fs11.default.readSync(descriptor, bytes2, 0, bytes2.length, 0);
|
|
6645
|
-
if (count > MAX_RECORD_BYTES)
|
|
6667
|
+
if (count > MAX_RECORD_BYTES)
|
|
6668
|
+
throw new JournalFileGuardError(`${label2} exceeds its byte limit.`);
|
|
6646
6669
|
return JSON.parse(bytes2.subarray(0, count).toString("utf8"));
|
|
6647
6670
|
} finally {
|
|
6648
6671
|
import_node_fs11.default.closeSync(descriptor);
|
|
@@ -6650,7 +6673,11 @@ function readBoundedPrivateJson(file, label2) {
|
|
|
6650
6673
|
}
|
|
6651
6674
|
function assertReliabilityEnumerationTime(startedAtMs) {
|
|
6652
6675
|
if (performance.now() - startedAtMs > MAX_RELIABILITY_ENUMERATION_MS)
|
|
6653
|
-
throw new
|
|
6676
|
+
throw new ReliabilityJournalError(
|
|
6677
|
+
"journal-enumeration-timeout",
|
|
6678
|
+
null,
|
|
6679
|
+
"Reliability journal enumeration exceeded its time limit."
|
|
6680
|
+
);
|
|
6654
6681
|
}
|
|
6655
6682
|
function reliabilityDirectory() {
|
|
6656
6683
|
return import_node_path13.default.join(DEVROUTER_HOME, "reliability");
|
|
@@ -6671,22 +6698,56 @@ function listReliabilityOperations() {
|
|
|
6671
6698
|
stat = import_node_fs11.default.lstatSync(directory);
|
|
6672
6699
|
} catch (error) {
|
|
6673
6700
|
if (error.code === "ENOENT") return [];
|
|
6674
|
-
throw
|
|
6701
|
+
throw new ReliabilityJournalError(
|
|
6702
|
+
"journal-directory-unreadable",
|
|
6703
|
+
null,
|
|
6704
|
+
"Reliability journal directory could not be read."
|
|
6705
|
+
);
|
|
6675
6706
|
}
|
|
6676
6707
|
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
6677
|
-
throw new
|
|
6708
|
+
throw new ReliabilityJournalError(
|
|
6709
|
+
"journal-directory-unsafe",
|
|
6710
|
+
null,
|
|
6711
|
+
"Reliability journal directory is unsafe."
|
|
6712
|
+
);
|
|
6678
6713
|
if (stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
|
|
6679
|
-
throw new
|
|
6714
|
+
throw new ReliabilityJournalError(
|
|
6715
|
+
"journal-directory-unsafe",
|
|
6716
|
+
null,
|
|
6717
|
+
"Reliability journal directory is not private."
|
|
6718
|
+
);
|
|
6680
6719
|
const entries = [];
|
|
6681
|
-
|
|
6720
|
+
let handle;
|
|
6721
|
+
try {
|
|
6722
|
+
handle = import_node_fs11.default.opendirSync(directory);
|
|
6723
|
+
} catch {
|
|
6724
|
+
throw new ReliabilityJournalError(
|
|
6725
|
+
"journal-directory-unreadable",
|
|
6726
|
+
null,
|
|
6727
|
+
"Reliability journal directory could not be read."
|
|
6728
|
+
);
|
|
6729
|
+
}
|
|
6682
6730
|
try {
|
|
6683
6731
|
for (; ; ) {
|
|
6684
6732
|
assertReliabilityEnumerationTime(startedAtMs);
|
|
6685
|
-
|
|
6733
|
+
let entry;
|
|
6734
|
+
try {
|
|
6735
|
+
entry = handle.readSync();
|
|
6736
|
+
} catch {
|
|
6737
|
+
throw new ReliabilityJournalError(
|
|
6738
|
+
"journal-directory-unreadable",
|
|
6739
|
+
null,
|
|
6740
|
+
"Reliability journal directory could not be read."
|
|
6741
|
+
);
|
|
6742
|
+
}
|
|
6686
6743
|
if (!entry) break;
|
|
6687
6744
|
entries.push(entry);
|
|
6688
6745
|
if (entries.length > MAX_RELIABILITY_DIRECTORY_ENTRIES)
|
|
6689
|
-
throw new
|
|
6746
|
+
throw new ReliabilityJournalError(
|
|
6747
|
+
"journal-enumeration-limit",
|
|
6748
|
+
null,
|
|
6749
|
+
"Reliability journal directory exceeds its entry limit."
|
|
6750
|
+
);
|
|
6690
6751
|
}
|
|
6691
6752
|
} finally {
|
|
6692
6753
|
handle.closeSync();
|
|
@@ -6695,27 +6756,82 @@ function listReliabilityOperations() {
|
|
|
6695
6756
|
for (const entry of entries) {
|
|
6696
6757
|
assertReliabilityEnumerationTime(startedAtMs);
|
|
6697
6758
|
if (entry.isSymbolicLink())
|
|
6698
|
-
throw new
|
|
6759
|
+
throw new ReliabilityJournalError(
|
|
6760
|
+
"journal-entry-unsupported",
|
|
6761
|
+
journalEntryLocation(entry.name),
|
|
6762
|
+
"Reliability journal directory contains a symlink."
|
|
6763
|
+
);
|
|
6699
6764
|
if (!entry.isFile())
|
|
6700
|
-
throw new
|
|
6765
|
+
throw new ReliabilityJournalError(
|
|
6766
|
+
"journal-entry-unsupported",
|
|
6767
|
+
journalEntryLocation(entry.name),
|
|
6768
|
+
"Reliability journal directory contains an unsupported entry."
|
|
6769
|
+
);
|
|
6701
6770
|
if (RELIABILITY_LOCK_NAME_RE.test(entry.name) || RELIABILITY_ATOMIC_TEMP_NAME_RE.test(entry.name))
|
|
6702
6771
|
continue;
|
|
6703
6772
|
const match = RELIABILITY_JOURNAL_NAME_RE.exec(entry.name);
|
|
6704
|
-
if (!match)
|
|
6773
|
+
if (!match)
|
|
6774
|
+
throw new ReliabilityJournalError(
|
|
6775
|
+
"journal-entry-unsupported",
|
|
6776
|
+
journalEntryLocation(entry.name),
|
|
6777
|
+
"Reliability journal directory contains an unsupported entry."
|
|
6778
|
+
);
|
|
6705
6779
|
journals.push({ name: entry.name, key: match[1] });
|
|
6706
6780
|
}
|
|
6707
6781
|
if (journals.length > MAX_RELIABILITY_JOURNALS)
|
|
6708
|
-
throw new
|
|
6782
|
+
throw new ReliabilityJournalError(
|
|
6783
|
+
"journal-enumeration-limit",
|
|
6784
|
+
null,
|
|
6785
|
+
"Reliability journal directory exceeds its journal limit."
|
|
6786
|
+
);
|
|
6709
6787
|
journals.sort((left, right) => left.name.localeCompare(right.name));
|
|
6710
6788
|
const records = [];
|
|
6711
6789
|
for (const journal of journals) {
|
|
6712
6790
|
assertReliabilityEnumerationTime(startedAtMs);
|
|
6713
6791
|
const file = import_node_path13.default.join(directory, journal.name);
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6792
|
+
let raw;
|
|
6793
|
+
try {
|
|
6794
|
+
raw = readBoundedPrivateJson(file, "Reliability journal");
|
|
6795
|
+
} catch (error) {
|
|
6796
|
+
const fsCode = error?.code;
|
|
6797
|
+
const cause = error instanceof JournalFileGuardError ? "journal-entry-unsafe" : error instanceof SyntaxError || !fsCode ? "journal-invalid" : "journal-unreadable";
|
|
6798
|
+
throw new ReliabilityJournalError(
|
|
6799
|
+
cause,
|
|
6800
|
+
journalEntryLocation(journal.name),
|
|
6801
|
+
error instanceof JournalFileGuardError ? error.message : cause === "journal-invalid" ? "Reliability journal entry is invalid." : "Reliability journal entry could not be read."
|
|
6802
|
+
);
|
|
6803
|
+
}
|
|
6804
|
+
if (raw === void 0)
|
|
6805
|
+
throw new ReliabilityJournalError(
|
|
6806
|
+
"journal-unstable",
|
|
6807
|
+
journalEntryLocation(journal.name),
|
|
6808
|
+
"Reliability journal disappeared during enumeration."
|
|
6809
|
+
);
|
|
6810
|
+
let identity2;
|
|
6811
|
+
let record5;
|
|
6812
|
+
try {
|
|
6813
|
+
identity2 = journalIdentity(raw);
|
|
6814
|
+
if (identityKey(identity2) !== journal.key)
|
|
6815
|
+
throw new ReliabilityJournalError(
|
|
6816
|
+
"journal-identity-mismatch",
|
|
6817
|
+
journalEntryLocation(journal.name),
|
|
6818
|
+
"Reliability journal filename does not match its identity."
|
|
6819
|
+
);
|
|
6820
|
+
record5 = readReliabilityOperation(identity2);
|
|
6821
|
+
} catch (error) {
|
|
6822
|
+
if (error instanceof ReliabilityJournalError) throw error;
|
|
6823
|
+
throw new ReliabilityJournalError(
|
|
6824
|
+
"journal-invalid",
|
|
6825
|
+
journalEntryLocation(journal.name),
|
|
6826
|
+
"Reliability journal entry is invalid."
|
|
6827
|
+
);
|
|
6828
|
+
}
|
|
6829
|
+
if (!record5)
|
|
6830
|
+
throw new ReliabilityJournalError(
|
|
6831
|
+
"journal-unstable",
|
|
6832
|
+
journalEntryLocation(journal.name),
|
|
6833
|
+
"Reliability journal disappeared during enumeration."
|
|
6834
|
+
);
|
|
6719
6835
|
records.push(record5);
|
|
6720
6836
|
assertReliabilityEnumerationTime(startedAtMs);
|
|
6721
6837
|
}
|
|
@@ -6872,11 +6988,11 @@ function setReliabilityHumanPin(identity2, expectedJournalRevision, expectedProt
|
|
|
6872
6988
|
};
|
|
6873
6989
|
});
|
|
6874
6990
|
}
|
|
6875
|
-
var
|
|
6991
|
+
var import_node_crypto8, import_node_fs11, import_node_path13, import_node_util3, MAX_RECORD_BYTES, MAX_RELIABILITY_JOURNALS, MAX_RELIABILITY_DIRECTORY_ENTRIES, MAX_RELIABILITY_ENUMERATION_MS, RELIABILITY_JOURNAL_NAME_RE, RELIABILITY_LOCK_NAME_RE, RELIABILITY_ATOMIC_TEMP_NAME_RE, ReliabilityJournalError, MAX_REPORTED_ENTRY_NAME, JournalFileGuardError;
|
|
6876
6992
|
var init_reliability_operation_store = __esm({
|
|
6877
6993
|
"src/core/reliability-operation-store.ts"() {
|
|
6878
6994
|
"use strict";
|
|
6879
|
-
|
|
6995
|
+
import_node_crypto8 = require("crypto");
|
|
6880
6996
|
import_node_fs11 = __toESM(require("fs"));
|
|
6881
6997
|
import_node_path13 = __toESM(require("path"));
|
|
6882
6998
|
import_node_util3 = require("util");
|
|
@@ -6893,6 +7009,21 @@ var init_reliability_operation_store = __esm({
|
|
|
6893
7009
|
RELIABILITY_JOURNAL_NAME_RE = /^([0-9a-f]{64})\.json$/;
|
|
6894
7010
|
RELIABILITY_LOCK_NAME_RE = /^[0-9a-f]{64}\.json\.lock(?:\.[0-9]+\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.candidate(?:\.stale)?|\.queue\.[0-9]+\.[0-9]+\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}(?:\.candidate)?)?$/;
|
|
6895
7011
|
RELIABILITY_ATOMIC_TEMP_NAME_RE = /^\.[0-9a-f]{64}\.json\.[0-9]+\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.tmp$/;
|
|
7012
|
+
ReliabilityJournalError = class extends Error {
|
|
7013
|
+
constructor(cause, location, message) {
|
|
7014
|
+
super(message);
|
|
7015
|
+
this.cause = cause;
|
|
7016
|
+
this.location = location;
|
|
7017
|
+
this.name = "ReliabilityJournalError";
|
|
7018
|
+
}
|
|
7019
|
+
};
|
|
7020
|
+
MAX_REPORTED_ENTRY_NAME = 160;
|
|
7021
|
+
JournalFileGuardError = class extends Error {
|
|
7022
|
+
constructor(message) {
|
|
7023
|
+
super(message);
|
|
7024
|
+
this.name = "JournalFileGuardError";
|
|
7025
|
+
}
|
|
7026
|
+
};
|
|
6896
7027
|
}
|
|
6897
7028
|
});
|
|
6898
7029
|
|
|
@@ -7258,7 +7389,7 @@ var init_managed_stop_baseline = __esm({
|
|
|
7258
7389
|
|
|
7259
7390
|
// src/core/managed-runtime-state.ts
|
|
7260
7391
|
function stateKey(repoPath, workspace) {
|
|
7261
|
-
return (0,
|
|
7392
|
+
return (0, import_node_crypto9.createHash)("sha256").update(`${repoPath}\0${workspace ?? ""}`, "utf-8").digest("hex");
|
|
7262
7393
|
}
|
|
7263
7394
|
function managedRuntimeStatePath(repoPath, workspace) {
|
|
7264
7395
|
return import_node_path17.default.join(DEVROUTER_HOME, "managed-runtime", `${stateKey(repoPath, workspace)}.json`);
|
|
@@ -7337,11 +7468,11 @@ function readManagedRuntimeState(repoPath, workspace, read2 = (file) => import_n
|
|
|
7337
7468
|
}
|
|
7338
7469
|
return validateState(parsed, repoPath, workspace);
|
|
7339
7470
|
}
|
|
7340
|
-
var
|
|
7471
|
+
var import_node_crypto9, import_node_fs13, import_node_path17;
|
|
7341
7472
|
var init_managed_runtime_state = __esm({
|
|
7342
7473
|
"src/core/managed-runtime-state.ts"() {
|
|
7343
7474
|
"use strict";
|
|
7344
|
-
|
|
7475
|
+
import_node_crypto9 = require("crypto");
|
|
7345
7476
|
import_node_fs13 = __toESM(require("fs"));
|
|
7346
7477
|
import_node_path17 = __toESM(require("path"));
|
|
7347
7478
|
init_atomic_file();
|
|
@@ -8416,7 +8547,7 @@ async function observeControllerBinding(directory, input2) {
|
|
|
8416
8547
|
};
|
|
8417
8548
|
}
|
|
8418
8549
|
async function controllerRequest(directory, input2, emit, timeoutMs) {
|
|
8419
|
-
const request2 = parseControllerRequest({ ...input2, version: 1, id: (0,
|
|
8550
|
+
const request2 = parseControllerRequest({ ...input2, version: 1, id: (0, import_node_crypto10.randomUUID)() });
|
|
8420
8551
|
const socketPath = import_node_path20.default.join(directory, "control.sock");
|
|
8421
8552
|
const stat = import_node_fs14.default.lstatSync(socketPath);
|
|
8422
8553
|
if (!stat.isSocket() || stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
|
|
@@ -8426,7 +8557,7 @@ async function controllerRequest(directory, input2, emit, timeoutMs) {
|
|
|
8426
8557
|
let buffer = Buffer.alloc(0);
|
|
8427
8558
|
let handshake = false;
|
|
8428
8559
|
let completed = false;
|
|
8429
|
-
const handshakeId = (0,
|
|
8560
|
+
const handshakeId = (0, import_node_crypto10.randomUUID)();
|
|
8430
8561
|
const timeout = request2.method === "watch" || request2.method === "operation-watch" ? Math.min(request2.timeout + 5, 2147483) * 1e3 : 5e3;
|
|
8431
8562
|
const timer = setTimeout(
|
|
8432
8563
|
() => {
|
|
@@ -8492,11 +8623,11 @@ async function controllerRequest(directory, input2, emit, timeoutMs) {
|
|
|
8492
8623
|
});
|
|
8493
8624
|
});
|
|
8494
8625
|
}
|
|
8495
|
-
var
|
|
8626
|
+
var import_node_crypto10, import_node_fs14, import_node_net, import_node_path20, CONTROLLER_OPERATION_WATCH_SECONDS, CONTROLLER_OPERATION_DEFAULT_WAIT_SECONDS, CONTROLLER_OPERATION_MAX_WAIT_SECONDS, CONTROLLER_ID_RE2, ControllerResponseDeadlineError, ControllerOperationSubmissionError;
|
|
8496
8627
|
var init_controller_client = __esm({
|
|
8497
8628
|
"src/core/controller-client.ts"() {
|
|
8498
8629
|
"use strict";
|
|
8499
|
-
|
|
8630
|
+
import_node_crypto10 = require("crypto");
|
|
8500
8631
|
import_node_fs14 = __toESM(require("fs"));
|
|
8501
8632
|
import_node_net = __toESM(require("net"));
|
|
8502
8633
|
import_node_path20 = __toESM(require("path"));
|
|
@@ -8632,11 +8763,11 @@ var init_reliability_output = __esm({
|
|
|
8632
8763
|
|
|
8633
8764
|
// src/core/controller-monitor.ts
|
|
8634
8765
|
function controllerCapability(selector) {
|
|
8635
|
-
return selector === "runtime" ? "runtime" : `app-${(0,
|
|
8766
|
+
return selector === "runtime" ? "runtime" : `app-${(0, import_node_crypto11.createHash)("sha256").update(selector).digest("hex")}`;
|
|
8636
8767
|
}
|
|
8637
8768
|
function sessionConsumerId(input2) {
|
|
8638
8769
|
const { store, epoch, session, generation } = input2;
|
|
8639
|
-
return `session-${(0,
|
|
8770
|
+
return `session-${(0, import_node_crypto11.createHash)("sha256").update(JSON.stringify([store, epoch, session, generation])).digest("hex")}`;
|
|
8640
8771
|
}
|
|
8641
8772
|
function environmentIdentity(environment) {
|
|
8642
8773
|
return {
|
|
@@ -8657,11 +8788,11 @@ function parkingConsumers(consumers) {
|
|
|
8657
8788
|
consentRevision
|
|
8658
8789
|
})).sort((a, b) => a.id.localeCompare(b.id));
|
|
8659
8790
|
}
|
|
8660
|
-
var
|
|
8791
|
+
var import_node_crypto11, import_node_util7, ControllerObservationBindingChanged, UNFINISHED_PARK_SCAN_MS, ControllerMonitor;
|
|
8661
8792
|
var init_controller_monitor = __esm({
|
|
8662
8793
|
"src/core/controller-monitor.ts"() {
|
|
8663
8794
|
"use strict";
|
|
8664
|
-
|
|
8795
|
+
import_node_crypto11 = require("crypto");
|
|
8665
8796
|
import_node_util7 = require("util");
|
|
8666
8797
|
init_reliability_operation_store();
|
|
8667
8798
|
init_reliability_output();
|
|
@@ -8935,7 +9066,7 @@ var init_controller_monitor = __esm({
|
|
|
8935
9066
|
const projections = /* @__PURE__ */ new Map();
|
|
8936
9067
|
for (const consumer of consumers) {
|
|
8937
9068
|
const transient = structuredClone(journal.state);
|
|
8938
|
-
const consumerId = `observer-${(0,
|
|
9069
|
+
const consumerId = `observer-${(0, import_node_crypto11.createHash)("sha256").update(consumer.id).digest("hex")}`;
|
|
8939
9070
|
transient.consumers = [
|
|
8940
9071
|
{
|
|
8941
9072
|
id: consumerId,
|
|
@@ -9353,7 +9484,7 @@ function writeManifestRecord(cacheRoot, manifest) {
|
|
|
9353
9484
|
import_node_fs16.default.mkdirSync(directory, { recursive: true, mode: 448 });
|
|
9354
9485
|
const temporary = import_node_path22.default.join(
|
|
9355
9486
|
directory,
|
|
9356
|
-
`.${DEVSY_AGENT_MANIFEST_FILE}.${process.pid}.${(0,
|
|
9487
|
+
`.${DEVSY_AGENT_MANIFEST_FILE}.${process.pid}.${(0, import_node_crypto12.randomUUID)()}.tmp`
|
|
9357
9488
|
);
|
|
9358
9489
|
const record5 = {
|
|
9359
9490
|
version: 1,
|
|
@@ -9451,7 +9582,7 @@ function managedBinaryPath(cacheRoot, devsyVersion, asset) {
|
|
|
9451
9582
|
return import_node_path22.default.join(cacheRoot, `v${devsyVersion}`, asset.name);
|
|
9452
9583
|
}
|
|
9453
9584
|
function hashOpenFile(file) {
|
|
9454
|
-
const digest3 = (0,
|
|
9585
|
+
const digest3 = (0, import_node_crypto12.createHash)("sha256");
|
|
9455
9586
|
const buffer = Buffer.allocUnsafe(1024 * 1024);
|
|
9456
9587
|
let position = 0;
|
|
9457
9588
|
for (; ; ) {
|
|
@@ -9647,7 +9778,7 @@ async function downloadAndPublish(asset, binaryPath, fetcher, githubCliDownloade
|
|
|
9647
9778
|
import_node_fs16.default.mkdirSync(directory, { recursive: true, mode: 448 });
|
|
9648
9779
|
const temporaryPath = import_node_path22.default.join(
|
|
9649
9780
|
directory,
|
|
9650
|
-
`.${import_node_path22.default.basename(binaryPath)}.${process.pid}.${(0,
|
|
9781
|
+
`.${import_node_path22.default.basename(binaryPath)}.${process.pid}.${(0, import_node_crypto12.randomUUID)()}.tmp`
|
|
9651
9782
|
);
|
|
9652
9783
|
let handle;
|
|
9653
9784
|
try {
|
|
@@ -9659,7 +9790,7 @@ async function downloadAndPublish(asset, binaryPath, fetcher, githubCliDownloade
|
|
|
9659
9790
|
directFailure = error;
|
|
9660
9791
|
}
|
|
9661
9792
|
handle = await import_node_fs16.default.promises.open(temporaryPath, "wx", 384);
|
|
9662
|
-
const digest3 = (0,
|
|
9793
|
+
const digest3 = (0, import_node_crypto12.createHash)("sha256");
|
|
9663
9794
|
let size = 0;
|
|
9664
9795
|
const writeChunk = async (chunk) => {
|
|
9665
9796
|
size += chunk.byteLength;
|
|
@@ -9795,12 +9926,12 @@ async function prepareDevsyAgent(options = {}) {
|
|
|
9795
9926
|
return { ...preparedFromInspection(published), changed: true, transport };
|
|
9796
9927
|
});
|
|
9797
9928
|
}
|
|
9798
|
-
var import_node_child_process7,
|
|
9929
|
+
var import_node_child_process7, import_node_crypto12, import_node_fs16, import_node_path22, PINNED_DEVSY_AGENT_VERSION, SUPPORTED_DEVSY_MIN_VERSION, SUPPORTED_DEVSY_MAX_VERSION, SUPPORTED_DEVSY_RANGE, DEVSY_AGENT_SETUP_COMMAND, DEVSY_RELEASE_TAG_PREFIX, DEVSY_RELEASE_METADATA_BASE_URL, DEVSY_AGENT_ASSETS, DevsyAgentReadinessError, DEVSY_AGENT_CACHE_LOCK, DEVSY_AGENT_LOCK_WAIT_MS, DEVSY_AGENT_MANIFEST_FILE, DEVSY_AGENT_ASSET_NAMES, GITHUB_CLI_STDERR_TAIL_BYTES;
|
|
9799
9930
|
var init_devsy_agent = __esm({
|
|
9800
9931
|
"src/core/devsy-agent.ts"() {
|
|
9801
9932
|
"use strict";
|
|
9802
9933
|
import_node_child_process7 = require("child_process");
|
|
9803
|
-
|
|
9934
|
+
import_node_crypto12 = require("crypto");
|
|
9804
9935
|
import_node_fs16 = __toESM(require("fs"));
|
|
9805
9936
|
import_node_path22 = __toESM(require("path"));
|
|
9806
9937
|
init_file_lock();
|
|
@@ -10037,7 +10168,7 @@ function isWildcard(values) {
|
|
|
10037
10168
|
return values?.length === 1 && values[0] === "*";
|
|
10038
10169
|
}
|
|
10039
10170
|
function sha256(contents) {
|
|
10040
|
-
return (0,
|
|
10171
|
+
return (0, import_node_crypto13.createHash)("sha256").update(contents, "utf-8").digest("hex");
|
|
10041
10172
|
}
|
|
10042
10173
|
function safeComposeProject(value) {
|
|
10043
10174
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(value)) {
|
|
@@ -10260,12 +10391,12 @@ function stopExactManagedService(containerId, service, options) {
|
|
|
10260
10391
|
throw new Error(`Could not stop exact managed service '${service}' (${containerId}).`);
|
|
10261
10392
|
}
|
|
10262
10393
|
}
|
|
10263
|
-
var import_node_child_process8,
|
|
10394
|
+
var import_node_child_process8, import_node_crypto13, import_node_fs18, import_node_path25, import_yaml3, MANAGED_DEVCONTAINER_PATH, MANAGED_DEVCONTAINER_MARKER, COMPOSE_HASH_TIMEOUT_MS;
|
|
10264
10395
|
var init_devcontainer_profile = __esm({
|
|
10265
10396
|
"src/core/devcontainer-profile.ts"() {
|
|
10266
10397
|
"use strict";
|
|
10267
10398
|
import_node_child_process8 = require("child_process");
|
|
10268
|
-
|
|
10399
|
+
import_node_crypto13 = require("crypto");
|
|
10269
10400
|
import_node_fs18 = __toESM(require("fs"));
|
|
10270
10401
|
import_node_path25 = __toESM(require("path"));
|
|
10271
10402
|
import_yaml3 = __toESM(require("yaml"));
|
|
@@ -11751,7 +11882,7 @@ function parseDnsHostsFromSubjectAltName(subjectAltName) {
|
|
|
11751
11882
|
return normalizeUniqueHosts(names);
|
|
11752
11883
|
}
|
|
11753
11884
|
function parseCertificateDnsHosts(pem) {
|
|
11754
|
-
const certificate = new
|
|
11885
|
+
const certificate = new import_node_crypto14.X509Certificate(pem);
|
|
11755
11886
|
const subjectAltName = certificate.subjectAltName ?? "";
|
|
11756
11887
|
if (subjectAltName.length === 0) {
|
|
11757
11888
|
return [];
|
|
@@ -11951,12 +12082,12 @@ Run: ${tlsSetupCommand(options.repoPath)}`
|
|
|
11951
12082
|
);
|
|
11952
12083
|
}
|
|
11953
12084
|
}
|
|
11954
|
-
var import_node_child_process14,
|
|
12085
|
+
var import_node_child_process14, import_node_crypto14, import_node_fs23, import_node_path31, DEFAULT_TLS_CERT_HOSTS, TLS_CERTIFICATE_LOCK_FILE, TLS_CERTIFICATE_LOCK_WAIT_MS, TLS_CERTIFICATE_WRITE_ATTEMPTS;
|
|
11955
12086
|
var init_tls = __esm({
|
|
11956
12087
|
"src/core/tls.ts"() {
|
|
11957
12088
|
"use strict";
|
|
11958
12089
|
import_node_child_process14 = require("child_process");
|
|
11959
|
-
|
|
12090
|
+
import_node_crypto14 = require("crypto");
|
|
11960
12091
|
import_node_fs23 = __toESM(require("fs"));
|
|
11961
12092
|
import_node_path31 = __toESM(require("path"));
|
|
11962
12093
|
init_docker();
|
|
@@ -13515,7 +13646,7 @@ function validateRoot(root) {
|
|
|
13515
13646
|
return resolved;
|
|
13516
13647
|
}
|
|
13517
13648
|
function hashKey(value) {
|
|
13518
|
-
return (0,
|
|
13649
|
+
return (0, import_node_crypto15.createHash)("sha256").update(value).digest("hex");
|
|
13519
13650
|
}
|
|
13520
13651
|
function cloneFence(fence) {
|
|
13521
13652
|
return { ...fence };
|
|
@@ -13538,11 +13669,11 @@ function isErrno2(error, code) {
|
|
|
13538
13669
|
function claimError(code, message) {
|
|
13539
13670
|
return new NetworkClaimError(code, message);
|
|
13540
13671
|
}
|
|
13541
|
-
var
|
|
13672
|
+
var import_node_crypto15, import_node_fs27, import_node_path35, NETWORK_CLAIMS_VERSION, NETWORK_CLAIMS_ROOT, NETWORK_CLAIMS_MAX_RECORDS, NETWORK_CLAIMS_MAX_FILE_BYTES, NetworkClaimError, CLAIM_CORE_KEYS, CLAIM_KEYS, FENCE_KEYS, DOCUMENT_KEYS, MAX_CLAIM_TEXT, MAX_ENDPOINT_TEXT;
|
|
13542
13673
|
var init_network_claims = __esm({
|
|
13543
13674
|
"src/core/network-claims.ts"() {
|
|
13544
13675
|
"use strict";
|
|
13545
|
-
|
|
13676
|
+
import_node_crypto15 = require("crypto");
|
|
13546
13677
|
import_node_fs27 = __toESM(require("fs"));
|
|
13547
13678
|
import_node_path35 = __toESM(require("path"));
|
|
13548
13679
|
init_atomic_file();
|
|
@@ -13595,7 +13726,7 @@ var init_network_claims = __esm({
|
|
|
13595
13726
|
function networkOwnerKey(repoPath) {
|
|
13596
13727
|
if (!import_node_path36.default.isAbsolute(repoPath) || import_node_path36.default.resolve(repoPath) !== repoPath)
|
|
13597
13728
|
throw new Error("Invalid network owner path.");
|
|
13598
|
-
return (0,
|
|
13729
|
+
return (0, import_node_crypto16.createHash)("sha256").update(repoPath).digest("hex");
|
|
13599
13730
|
}
|
|
13600
13731
|
function findOwnedNetworkClaim(repoPath, root = NETWORK_CLAIMS_ROOT) {
|
|
13601
13732
|
let names;
|
|
@@ -13635,7 +13766,7 @@ function findOwnedNetworkClaim(repoPath, root = NETWORK_CLAIMS_ROOT) {
|
|
|
13635
13766
|
} finally {
|
|
13636
13767
|
import_node_fs28.default.closeSync(descriptor);
|
|
13637
13768
|
}
|
|
13638
|
-
if (typeof value.daemonId !== "string" || `${(0,
|
|
13769
|
+
if (typeof value.daemonId !== "string" || `${(0, import_node_crypto16.createHash)("sha256").update(value.daemonId).digest("hex")}.json` !== file)
|
|
13639
13770
|
throw new Error("Retained network daemon identity is invalid.");
|
|
13640
13771
|
const claim2 = readNetworkClaim({
|
|
13641
13772
|
daemonId: value.daemonId,
|
|
@@ -13649,11 +13780,11 @@ function findOwnedNetworkClaim(repoPath, root = NETWORK_CLAIMS_ROOT) {
|
|
|
13649
13780
|
}
|
|
13650
13781
|
return found;
|
|
13651
13782
|
}
|
|
13652
|
-
var
|
|
13783
|
+
var import_node_crypto16, import_node_fs28, import_node_path36;
|
|
13653
13784
|
var init_network_claim_lookup = __esm({
|
|
13654
13785
|
"src/core/network-claim-lookup.ts"() {
|
|
13655
13786
|
"use strict";
|
|
13656
|
-
|
|
13787
|
+
import_node_crypto16 = require("crypto");
|
|
13657
13788
|
import_node_fs28 = __toESM(require("fs"));
|
|
13658
13789
|
import_node_path36 = __toESM(require("path"));
|
|
13659
13790
|
init_network_claims();
|
|
@@ -13680,7 +13811,7 @@ function qualifyNetworkProviderDefinition(value, provider) {
|
|
|
13680
13811
|
if (definition.name !== "docker" || ![true, "true"].includes(agent.local) || agent.driver !== void 0 && agent.driver !== "docker" && agent.driver !== "" || docker.path !== "${DOCKER_PATH}" || docker.builder !== "${DOCKER_BUILDER}" || ![false, "false"].includes(docker.install) || (provider === "devsy" ? docker.elevation !== "${DOCKER_ELEVATION}" : docker.elevation !== void 0 && docker.elevation !== "") || env.DOCKER_HOST !== "${DOCKER_HOST}" || Object.keys(env).some((key) => key !== "DOCKER_HOST") || host.global !== true || dockerPath.default !== "docker" || actualCommand.length !== 1 || typeof actualCommand[0] !== "string" || actualCommand[0].trim() !== command || Object.keys(exec).some((key) => key !== "command") || agent.path !== void 0 && agent.path !== "" || agent.downloadURL !== void 0 && agent.downloadURL !== "") {
|
|
13681
13812
|
throw new Error("Docker provider definition is not qualified for network allocation.");
|
|
13682
13813
|
}
|
|
13683
|
-
return (0,
|
|
13814
|
+
return (0, import_node_crypto17.createHash)("sha256").update(JSON.stringify({ name: definition.name, agent, options, exec })).digest("hex");
|
|
13684
13815
|
}
|
|
13685
13816
|
function read(provider, args) {
|
|
13686
13817
|
const result = (0, import_node_child_process16.spawnSync)(provider, args, {
|
|
@@ -13772,12 +13903,12 @@ function inspectNetworkProviderBinding(input2) {
|
|
|
13772
13903
|
);
|
|
13773
13904
|
}
|
|
13774
13905
|
}
|
|
13775
|
-
var import_node_child_process16,
|
|
13906
|
+
var import_node_child_process16, import_node_crypto17;
|
|
13776
13907
|
var init_network_provider_inspect = __esm({
|
|
13777
13908
|
"src/core/network-provider-inspect.ts"() {
|
|
13778
13909
|
"use strict";
|
|
13779
13910
|
import_node_child_process16 = require("child_process");
|
|
13780
|
-
|
|
13911
|
+
import_node_crypto17 = require("crypto");
|
|
13781
13912
|
init_devpod_environment();
|
|
13782
13913
|
init_devsy_agent();
|
|
13783
13914
|
}
|
|
@@ -15095,14 +15226,14 @@ async function runLifecycleWorker(request2, supervision, beforeAdmission) {
|
|
|
15095
15226
|
}
|
|
15096
15227
|
}
|
|
15097
15228
|
function newLifecycleIds() {
|
|
15098
|
-
return { requestId: (0,
|
|
15229
|
+
return { requestId: (0, import_node_crypto18.randomUUID)(), operationId: (0, import_node_crypto18.randomUUID)(), workerId: (0, import_node_crypto18.randomUUID)() };
|
|
15099
15230
|
}
|
|
15100
|
-
var import_node_child_process18,
|
|
15231
|
+
var import_node_child_process18, import_node_crypto18, import_node_fs30, import_node_path38, OUTPUT_BUFFER_LIMIT, DEFAULT_OUTPUT_PAGE_BYTES, LifecycleOutput, LifecycleWorkerAdmissionBusyError;
|
|
15101
15232
|
var init_reliability_worker = __esm({
|
|
15102
15233
|
"src/core/reliability-worker.ts"() {
|
|
15103
15234
|
"use strict";
|
|
15104
15235
|
import_node_child_process18 = require("child_process");
|
|
15105
|
-
|
|
15236
|
+
import_node_crypto18 = require("crypto");
|
|
15106
15237
|
import_node_fs30 = __toESM(require("fs"));
|
|
15107
15238
|
import_node_path38 = __toESM(require("path"));
|
|
15108
15239
|
init_file_lock();
|
|
@@ -15790,7 +15921,7 @@ function readRegularFile(filePath) {
|
|
|
15790
15921
|
return readRegularFileBytes(filePath)?.toString("utf-8");
|
|
15791
15922
|
}
|
|
15792
15923
|
function adapterFingerprint(adapter) {
|
|
15793
|
-
return (0,
|
|
15924
|
+
return (0, import_node_crypto19.createHash)("sha256").update(adapter).digest("hex");
|
|
15794
15925
|
}
|
|
15795
15926
|
function resolveManagedPostStartPlan(repoPath) {
|
|
15796
15927
|
const adapterPath = import_node_path41.default.join(repoPath, MANAGED_ADAPTER_PATH);
|
|
@@ -15880,12 +16011,12 @@ function runManagedProcessAction(options) {
|
|
|
15880
16011
|
}
|
|
15881
16012
|
return "drifted";
|
|
15882
16013
|
}
|
|
15883
|
-
var import_node_child_process23,
|
|
16014
|
+
var import_node_child_process23, import_node_crypto19, import_node_fs33, import_node_path41, MANAGED_MARKER, MANAGED_ADAPTER_PATH, RUNTIME_HELPER_PATH;
|
|
15884
16015
|
var init_managed_post_start = __esm({
|
|
15885
16016
|
"src/core/managed-post-start.ts"() {
|
|
15886
16017
|
"use strict";
|
|
15887
16018
|
import_node_child_process23 = require("child_process");
|
|
15888
|
-
|
|
16019
|
+
import_node_crypto19 = require("crypto");
|
|
15889
16020
|
import_node_fs33 = __toESM(require("fs"));
|
|
15890
16021
|
import_node_path41 = __toESM(require("path"));
|
|
15891
16022
|
init_devcontainer_config();
|
|
@@ -15897,25 +16028,34 @@ var init_managed_post_start = __esm({
|
|
|
15897
16028
|
});
|
|
15898
16029
|
|
|
15899
16030
|
// src/core/managed-runtime-status.ts
|
|
16031
|
+
function recoveryPath(repoPath) {
|
|
16032
|
+
if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(repoPath)) return repoPath;
|
|
16033
|
+
return `'${repoPath.replaceAll("'", "'\\''")}'`;
|
|
16034
|
+
}
|
|
15900
16035
|
function reliabilityRecovery(reason, repoPath) {
|
|
16036
|
+
const checkout = recoveryPath(repoPath);
|
|
15901
16037
|
switch (reason) {
|
|
15902
16038
|
case "stop-incomplete":
|
|
15903
16039
|
case "operation-unknown":
|
|
15904
|
-
return [`Run: devrouter stop ${
|
|
16040
|
+
return [`Run: devrouter stop ${checkout}`, `Run: devrouter ensure ${checkout} --repair`];
|
|
15905
16041
|
case "start-refused":
|
|
15906
16042
|
return [
|
|
15907
|
-
`Run: devrouter doctor ${
|
|
15908
|
-
`Stop the holding workspace or change this repository's own published binding, then run: devrouter ensure ${
|
|
16043
|
+
`Run: devrouter doctor --repo ${checkout} to read the refused fixed host-port claim and its holder`,
|
|
16044
|
+
`Stop the holding workspace or change this repository's own published binding, then run: devrouter ensure ${checkout}`
|
|
15909
16045
|
];
|
|
15910
16046
|
case "unadmittable":
|
|
15911
16047
|
return [
|
|
15912
|
-
`Run: devrouter stop ${
|
|
15913
|
-
`Lower the requested capacity in .devrouter.yml, then run: devrouter ensure ${
|
|
16048
|
+
`Run: devrouter stop ${checkout}`,
|
|
16049
|
+
`Lower the requested capacity in .devrouter.yml, then run: devrouter ensure ${checkout}`
|
|
15914
16050
|
];
|
|
15915
16051
|
case "capacity-parked":
|
|
15916
|
-
return [
|
|
16052
|
+
return [
|
|
16053
|
+
"Parked for host capacity: the enrolled foreground controller resumes this checkout after its pressure dwell and live-consumer checks pass.",
|
|
16054
|
+
`Inspect the parked intent with: devrouter status --repo ${checkout} --json`,
|
|
16055
|
+
`'devrouter ensure' refuses while the journal stays parked; release the intent instead with: devrouter stop ${checkout}`
|
|
16056
|
+
];
|
|
15917
16057
|
case "capacity-waiting":
|
|
15918
|
-
return [`Run: devrouter ensure ${
|
|
16058
|
+
return [`Run: devrouter ensure ${checkout} (still queued until capacity frees up)`];
|
|
15919
16059
|
default:
|
|
15920
16060
|
return [];
|
|
15921
16061
|
}
|
|
@@ -17019,11 +17159,13 @@ function networkCapacityCheck(report) {
|
|
|
17019
17159
|
(pool) => pool.candidates.some((candidate) => candidate.overlappingNetworkIds.length === 0)
|
|
17020
17160
|
);
|
|
17021
17161
|
const managedDetails = managed ? ` Managed policy: ${managed.policy.status}; /${managed.policy.requestedPrefixLength} capacity: ${managed.configuredPolicyCapacity.status}; claims: ${managed.claims.reserved} reserved, ${managed.claims.attached} attached, ${managed.claims.uncertain} uncertain.` : "";
|
|
17162
|
+
const blockers = report.allocation.blockers.slice(0, 4).map((blocker) => blocker.slice(0, 120));
|
|
17163
|
+
const blockerDetails = blockers.length > 0 ? ` Missing evidence: ${blockers.join("; ")}.` : "";
|
|
17022
17164
|
return {
|
|
17023
17165
|
id: "global.network-capacity",
|
|
17024
17166
|
level: legacyAvailable ? "ok" : "warn",
|
|
17025
17167
|
summary: exhausted ? "Docker default address pools are exhausted for new networks." : legacyAvailable ? "Docker default pools have unoccupied capacity; managed allocation is not configured." : "Network allocation readiness requires complete route and capacity evidence.",
|
|
17026
|
-
details: `${report.pools.length} pool(s); ${retained} network(s) have no active endpoints but retain container references. Allocation readiness: ${report.allocation.status}.${managedDetails}`,
|
|
17168
|
+
details: `${report.pools.length} pool(s); ${retained} network(s) have no active endpoints but retain container references. Allocation readiness: ${report.allocation.status}.${blockerDetails}${managedDetails}`,
|
|
17027
17169
|
suggestion: exhausted ? "Existing network reuse can continue. Review operator-approved route-safe pools or exact ownership-aware recovery. Stop and worktree removal do not release subnets; do not prune automatically." : "Review complete Docker, LAN, VPN and guest route evidence before allocating a new subnet. Unknown evidence does not authorize cleanup."
|
|
17028
17170
|
};
|
|
17029
17171
|
}
|
|
@@ -17041,21 +17183,21 @@ var init_network_diagnostics = __esm({
|
|
|
17041
17183
|
});
|
|
17042
17184
|
|
|
17043
17185
|
// src/core/network-compose.ts
|
|
17044
|
-
var
|
|
17186
|
+
var import_node_crypto20;
|
|
17045
17187
|
var init_network_compose = __esm({
|
|
17046
17188
|
"src/core/network-compose.ts"() {
|
|
17047
17189
|
"use strict";
|
|
17048
|
-
|
|
17190
|
+
import_node_crypto20 = require("crypto");
|
|
17049
17191
|
}
|
|
17050
17192
|
});
|
|
17051
17193
|
|
|
17052
17194
|
// src/core/network-compose-files.ts
|
|
17053
|
-
var import_node_child_process26,
|
|
17195
|
+
var import_node_child_process26, import_node_crypto21, import_node_fs35, import_node_path43, import_yaml4, MAX_BYTES3;
|
|
17054
17196
|
var init_network_compose_files = __esm({
|
|
17055
17197
|
"src/core/network-compose-files.ts"() {
|
|
17056
17198
|
"use strict";
|
|
17057
17199
|
import_node_child_process26 = require("child_process");
|
|
17058
|
-
|
|
17200
|
+
import_node_crypto21 = require("crypto");
|
|
17059
17201
|
import_node_fs35 = __toESM(require("fs"));
|
|
17060
17202
|
import_node_path43 = __toESM(require("path"));
|
|
17061
17203
|
import_yaml4 = __toESM(require("yaml"));
|
|
@@ -17087,11 +17229,11 @@ var init_network_lifecycle = __esm({
|
|
|
17087
17229
|
});
|
|
17088
17230
|
|
|
17089
17231
|
// src/core/network-managed.ts
|
|
17090
|
-
var
|
|
17232
|
+
var import_node_crypto22;
|
|
17091
17233
|
var init_network_managed = __esm({
|
|
17092
17234
|
"src/core/network-managed.ts"() {
|
|
17093
17235
|
"use strict";
|
|
17094
|
-
|
|
17236
|
+
import_node_crypto22 = require("crypto");
|
|
17095
17237
|
init_devpod_environment();
|
|
17096
17238
|
init_network_capacity();
|
|
17097
17239
|
init_network_claim_lookup();
|
|
@@ -17847,7 +17989,7 @@ async function superviseThroughController(input2) {
|
|
|
17847
17989
|
try {
|
|
17848
17990
|
const bind = () => observeControllerBinding(directory, {
|
|
17849
17991
|
path: input2.repoPath,
|
|
17850
|
-
session: (0,
|
|
17992
|
+
session: (0, import_node_crypto23.randomUUID)(),
|
|
17851
17993
|
profile: input2.profile ?? "full",
|
|
17852
17994
|
// The protocol requires at least one readiness selector, and every
|
|
17853
17995
|
// supervised operation depends on runtime readiness; "runtime" is the
|
|
@@ -17998,11 +18140,11 @@ function bindLifecycleCapacity(request2, binding, directory = import_node_path45
|
|
|
17998
18140
|
stepRecord(record5, { ...request2.fence, type: "admission", result: "admitted" });
|
|
17999
18141
|
});
|
|
18000
18142
|
}
|
|
18001
|
-
var
|
|
18143
|
+
var import_node_crypto23, import_node_path45, import_node_util11, activeWorker, lockHeld, BUSY_LIFECYCLE_WAIT_MS, BUSY_LIFECYCLE_POLL_MS, CAPACITY_CLIENT_WAIT_MS, BUSY_LIFECYCLE_PROGRESS_MS;
|
|
18002
18144
|
var init_reliability_lifecycle = __esm({
|
|
18003
18145
|
"src/core/reliability-lifecycle.ts"() {
|
|
18004
18146
|
"use strict";
|
|
18005
|
-
|
|
18147
|
+
import_node_crypto23 = require("crypto");
|
|
18006
18148
|
import_node_path45 = __toESM(require("path"));
|
|
18007
18149
|
import_node_util11 = require("util");
|
|
18008
18150
|
init_capacity_accounting();
|
|
@@ -18638,7 +18780,7 @@ function createCapacityController(options) {
|
|
|
18638
18780
|
controller,
|
|
18639
18781
|
policyRevision: policy.revision
|
|
18640
18782
|
});
|
|
18641
|
-
const payloadKey = (0,
|
|
18783
|
+
const payloadKey = (0, import_node_crypto24.randomBytes)(32);
|
|
18642
18784
|
const acceptedPayloads = /* @__PURE__ */ new Map();
|
|
18643
18785
|
const settlePreparations = () => {
|
|
18644
18786
|
if (lifetime.signal.aborted) return;
|
|
@@ -18802,7 +18944,7 @@ function createCapacityController(options) {
|
|
|
18802
18944
|
{
|
|
18803
18945
|
...charge,
|
|
18804
18946
|
operationId: prepared.operationId,
|
|
18805
|
-
reservationId: (0,
|
|
18947
|
+
reservationId: (0, import_node_crypto24.randomUUID)(),
|
|
18806
18948
|
policyRevision: target.current.revision
|
|
18807
18949
|
},
|
|
18808
18950
|
{
|
|
@@ -18905,7 +19047,7 @@ function createCapacityController(options) {
|
|
|
18905
19047
|
throw error;
|
|
18906
19048
|
}
|
|
18907
19049
|
}
|
|
18908
|
-
const signature = (0,
|
|
19050
|
+
const signature = (0, import_node_crypto24.createHmac)("sha256", payloadKey).update(
|
|
18909
19051
|
JSON.stringify({
|
|
18910
19052
|
repoPath: identity2.repoPath,
|
|
18911
19053
|
profile: environment.profile,
|
|
@@ -18925,7 +19067,7 @@ function createCapacityController(options) {
|
|
|
18925
19067
|
{
|
|
18926
19068
|
...charge,
|
|
18927
19069
|
operationId: prepared.operationId,
|
|
18928
|
-
reservationId: (0,
|
|
19070
|
+
reservationId: (0, import_node_crypto24.randomUUID)(),
|
|
18929
19071
|
policyRevision: current.revision
|
|
18930
19072
|
},
|
|
18931
19073
|
{ estimates: resolved.estimates, enrollment: resolved.enrollment, pool }
|
|
@@ -19060,7 +19202,7 @@ function createCapacityController(options) {
|
|
|
19060
19202
|
// the budget module then falls back to the conservative wall duration.
|
|
19061
19203
|
activeElapsedMs: null,
|
|
19062
19204
|
profile: environment.profile,
|
|
19063
|
-
incidentId: `incident-${(0,
|
|
19205
|
+
incidentId: `incident-${(0, import_node_crypto24.randomUUID)()}`
|
|
19064
19206
|
});
|
|
19065
19207
|
} catch {
|
|
19066
19208
|
return;
|
|
@@ -19078,7 +19220,7 @@ function createCapacityController(options) {
|
|
|
19078
19220
|
{
|
|
19079
19221
|
...charge,
|
|
19080
19222
|
operationId: prepared.operationId,
|
|
19081
|
-
reservationId: (0,
|
|
19223
|
+
reservationId: (0, import_node_crypto24.randomUUID)(),
|
|
19082
19224
|
policyRevision: current.revision
|
|
19083
19225
|
},
|
|
19084
19226
|
{ estimates: resolved.estimates, enrollment: resolved.enrollment, pool }
|
|
@@ -19098,11 +19240,11 @@ function createCapacityController(options) {
|
|
|
19098
19240
|
}
|
|
19099
19241
|
};
|
|
19100
19242
|
}
|
|
19101
|
-
var
|
|
19243
|
+
var import_node_crypto24, import_node_path46, import_node_util13;
|
|
19102
19244
|
var init_capacity_controller = __esm({
|
|
19103
19245
|
"src/core/capacity-controller.ts"() {
|
|
19104
19246
|
"use strict";
|
|
19105
|
-
|
|
19247
|
+
import_node_crypto24 = require("crypto");
|
|
19106
19248
|
import_node_path46 = __toESM(require("path"));
|
|
19107
19249
|
import_node_util13 = require("util");
|
|
19108
19250
|
init_capacity_accounting();
|
|
@@ -19199,7 +19341,7 @@ printf '%s %s %s\n' "$pid" "$birth" "$fingerprint"
|
|
|
19199
19341
|
|
|
19200
19342
|
// src/core/controller-observation.ts
|
|
19201
19343
|
function digest2(value) {
|
|
19202
|
-
return (0,
|
|
19344
|
+
return (0, import_node_crypto25.createHash)("sha256").update(JSON.stringify(value)).digest("hex");
|
|
19203
19345
|
}
|
|
19204
19346
|
function readRoutes() {
|
|
19205
19347
|
return readHostRouteStateReadOnly((file) => readControllerEvidence(file, 1048576));
|
|
@@ -19283,7 +19425,7 @@ function createControllerObservationCollector(resolve, fingerprint) {
|
|
|
19283
19425
|
() => persisted.contents[3]
|
|
19284
19426
|
);
|
|
19285
19427
|
const source = parseDevcontainerConfig(persisted.contents[4], sourcePath);
|
|
19286
|
-
if (!state || state.devpodId !== environment.providerId || state.profile !== environment.profile || typeof source.service !== "string" || !source.service || (0,
|
|
19428
|
+
if (!state || state.devpodId !== environment.providerId || state.profile !== environment.profile || typeof source.service !== "string" || !source.service || (0, import_node_crypto25.createHash)("sha256").update(persisted.contents[4]).digest("hex") !== state.sourceConfigSha256 || (0, import_node_crypto25.createHash)("sha256").update(persisted.contents[5]).digest("hex") !== state.effectiveConfigSha256)
|
|
19287
19429
|
throw new ControllerObservationBindingChanged("Observation retained configuration changed.");
|
|
19288
19430
|
const identity2 = {
|
|
19289
19431
|
repoPath: environment.repoPath,
|
|
@@ -19458,11 +19600,11 @@ function createControllerObservationCollector(resolve, fingerprint) {
|
|
|
19458
19600
|
};
|
|
19459
19601
|
};
|
|
19460
19602
|
}
|
|
19461
|
-
var
|
|
19603
|
+
var import_node_crypto25, import_node_path47, OBSERVATION_INSPECT_TEMPLATE;
|
|
19462
19604
|
var init_controller_observation = __esm({
|
|
19463
19605
|
"src/core/controller-observation.ts"() {
|
|
19464
19606
|
"use strict";
|
|
19465
|
-
|
|
19607
|
+
import_node_crypto25 = require("crypto");
|
|
19466
19608
|
import_node_path47 = __toESM(require("path"));
|
|
19467
19609
|
init_controller_binding();
|
|
19468
19610
|
init_controller_monitor();
|
|
@@ -19487,11 +19629,11 @@ var init_controller_observation = __esm({
|
|
|
19487
19629
|
});
|
|
19488
19630
|
|
|
19489
19631
|
// src/core/controller-sessions.ts
|
|
19490
|
-
var
|
|
19632
|
+
var import_node_crypto26, import_node_util14, ControllerSessions;
|
|
19491
19633
|
var init_controller_sessions = __esm({
|
|
19492
19634
|
"src/core/controller-sessions.ts"() {
|
|
19493
19635
|
"use strict";
|
|
19494
|
-
|
|
19636
|
+
import_node_crypto26 = require("crypto");
|
|
19495
19637
|
import_node_util14 = require("util");
|
|
19496
19638
|
ControllerSessions = class {
|
|
19497
19639
|
constructor(store) {
|
|
@@ -19663,7 +19805,7 @@ var init_controller_sessions = __esm({
|
|
|
19663
19805
|
const session = {
|
|
19664
19806
|
id: id5,
|
|
19665
19807
|
environmentId: environment.id,
|
|
19666
|
-
generation: (0,
|
|
19808
|
+
generation: (0, import_node_crypto26.randomUUID)(),
|
|
19667
19809
|
requirements: required,
|
|
19668
19810
|
renewedAtMs: wall,
|
|
19669
19811
|
parkingConsent: "protected",
|
|
@@ -19690,7 +19832,7 @@ var init_controller_sessions = __esm({
|
|
|
19690
19832
|
const session = {
|
|
19691
19833
|
id: previous.session,
|
|
19692
19834
|
environmentId: environment.id,
|
|
19693
|
-
generation: (0,
|
|
19835
|
+
generation: (0, import_node_crypto26.randomUUID)(),
|
|
19694
19836
|
requirements: required,
|
|
19695
19837
|
renewedAtMs: wall,
|
|
19696
19838
|
parkingConsent: "protected",
|
|
@@ -21134,26 +21276,30 @@ checkout's environment is mid-transition. Wire \`devrouter harness gate\` as a
|
|
|
21134
21276
|
{
|
|
21135
21277
|
"hooks": {
|
|
21136
21278
|
"PreToolUse": [
|
|
21137
|
-
{ "matcher": "
|
|
21279
|
+
{ "matcher": ".*", "hooks": [
|
|
21138
21280
|
{ "type": "command", "command": "devrouter harness gate", "timeout": 90 }
|
|
21139
21281
|
] }
|
|
21140
21282
|
]
|
|
21141
21283
|
}
|
|
21142
21284
|
}
|
|
21143
21285
|
|
|
21144
|
-
The Codex CLI reads the same hook from \`$CODEX_HOME/hooks.json
|
|
21145
|
-
tool is named \`exec_command\`:
|
|
21286
|
+
The Codex CLI reads the same hook from \`$CODEX_HOME/hooks.json\`:
|
|
21146
21287
|
|
|
21147
21288
|
{
|
|
21148
21289
|
"hooks": {
|
|
21149
21290
|
"PreToolUse": [
|
|
21150
|
-
{ "matcher": "
|
|
21291
|
+
{ "matcher": ".*", "hooks": [
|
|
21151
21292
|
{ "type": "command", "command": "devrouter harness gate", "timeout": 180 }
|
|
21152
21293
|
] }
|
|
21153
21294
|
]
|
|
21154
21295
|
}
|
|
21155
21296
|
}
|
|
21156
21297
|
|
|
21298
|
+
\`.*\` matches every tool, including the shell, file-editing and MCP tools a model
|
|
21299
|
+
can point at the environment. The gate answers a settled checkout immediately, so
|
|
21300
|
+
the price is one short-lived process per gated call; narrow the matcher when that
|
|
21301
|
+
price matters more than covering every tool.
|
|
21302
|
+
|
|
21157
21303
|
The gate identifies the requesting harness from its payload and answers in that
|
|
21158
21304
|
harness's accepted shape: a refusal is a \`deny\` in both, while an allowed call is
|
|
21159
21305
|
\`permissionDecision: allow\` for Claude Code and Codex receives a bare completion
|
|
@@ -23205,7 +23351,7 @@ function probeInstalledCliVersion(executable) {
|
|
|
23205
23351
|
}
|
|
23206
23352
|
function buildCliPathCheck(options = {}) {
|
|
23207
23353
|
const id5 = "global.cli-path";
|
|
23208
|
-
const runningVersion = options.runningVersion ?? (true ? "0.1.
|
|
23354
|
+
const runningVersion = options.runningVersion ?? (true ? "0.1.2" : "0.0.0-dev");
|
|
23209
23355
|
if (runningVersion === "0.0.0-dev") {
|
|
23210
23356
|
return {
|
|
23211
23357
|
id: id5,
|
|
@@ -23871,6 +24017,17 @@ function collectNextSteps(checks, statusNextSteps) {
|
|
|
23871
24017
|
}
|
|
23872
24018
|
return Array.from(steps.values());
|
|
23873
24019
|
}
|
|
24020
|
+
function capacityHistoryDetails(error) {
|
|
24021
|
+
if (!(error instanceof CapacityHistoryError)) return "capacity-history-unprovable";
|
|
24022
|
+
const parts = [error.code];
|
|
24023
|
+
if (error.cause) parts.push(error.cause);
|
|
24024
|
+
if (error.location) parts.push(`at ${error.location}`);
|
|
24025
|
+
return parts.join("; ");
|
|
24026
|
+
}
|
|
24027
|
+
function capacityHistorySuggestion(error) {
|
|
24028
|
+
const cause = error instanceof CapacityHistoryError ? error.cause : null;
|
|
24029
|
+
return (cause ? CAPACITY_RECOVERY_BY_CAUSE[cause] : void 0) ?? "Preserve ledger and lifecycle records; restore verified history before retrying admission.";
|
|
24030
|
+
}
|
|
23874
24031
|
async function buildDoctorReport(options = {}) {
|
|
23875
24032
|
const checks = [];
|
|
23876
24033
|
const fileLayout = getRouterFileLayout();
|
|
@@ -23916,8 +24073,8 @@ async function buildDoctorReport(options = {}) {
|
|
|
23916
24073
|
id: "global.capacity-ledger",
|
|
23917
24074
|
level: "error",
|
|
23918
24075
|
summary: "Capacity ledger history is unavailable for safe admission.",
|
|
23919
|
-
details: error
|
|
23920
|
-
suggestion: absent ? "Preserve ledger and lifecycle records; with every enrolled environment stopped, run: devrouter capacity reconcile --yes" :
|
|
24076
|
+
details: capacityHistoryDetails(error),
|
|
24077
|
+
suggestion: absent ? "Preserve ledger and lifecycle records; with every enrolled environment stopped, run: devrouter capacity reconcile --yes" : capacityHistorySuggestion(error)
|
|
23921
24078
|
});
|
|
23922
24079
|
}
|
|
23923
24080
|
let statusNextSteps = [];
|
|
@@ -24053,7 +24210,7 @@ async function buildDoctorReport(options = {}) {
|
|
|
24053
24210
|
suggestion: `Remedy ${expansionNotice.remedy.code}: set a named default profile other than '${expansionNotice.profile}'${remedyCandidates}.`
|
|
24054
24211
|
});
|
|
24055
24212
|
}
|
|
24056
|
-
const cliVersion = true ? "0.1.
|
|
24213
|
+
const cliVersion = true ? "0.1.2" : "0.0.0-dev";
|
|
24057
24214
|
const configVersion = config.devrouter?.version;
|
|
24058
24215
|
const installedKnown = cliVersion !== "0.0.0-dev";
|
|
24059
24216
|
const versionComparison = installedKnown && configVersion ? compareSemver(configVersion, cliVersion) : void 0;
|
|
@@ -24279,7 +24436,7 @@ async function buildDoctorReport(options = {}) {
|
|
|
24279
24436
|
nextSteps
|
|
24280
24437
|
};
|
|
24281
24438
|
}
|
|
24282
|
-
var import_node_fs44, import_node_path56, import_yaml6, POSTGRES_DEFAULTS;
|
|
24439
|
+
var import_node_fs44, import_node_path56, import_yaml6, POSTGRES_DEFAULTS, CAPACITY_RECOVERY_BY_CAUSE;
|
|
24283
24440
|
var init_doctor = __esm({
|
|
24284
24441
|
"src/core/doctor.ts"() {
|
|
24285
24442
|
"use strict";
|
|
@@ -24308,6 +24465,14 @@ var init_doctor = __esm({
|
|
|
24308
24465
|
POSTGRES_PASSWORD: "prisma",
|
|
24309
24466
|
POSTGRES_DB: "prisma"
|
|
24310
24467
|
};
|
|
24468
|
+
CAPACITY_RECOVERY_BY_CAUSE = {
|
|
24469
|
+
"journal-entry-unsupported": "Move the named unrecognised entry out of the private reliability journal directory, preserving its contents; it blocks every capacity read while it stays there.",
|
|
24470
|
+
"journal-directory-unsafe": "Restore private ownership and mode 0700 on the reliability journal directory, then retry.",
|
|
24471
|
+
"journal-directory-unreadable": "Restore read access to the reliability journal directory, then retry.",
|
|
24472
|
+
"journal-invalid": "Preserve the named journal entry and restore verified history before retrying admission.",
|
|
24473
|
+
"journal-unreadable": "Preserve the named journal entry and restore verified history before retrying admission.",
|
|
24474
|
+
"journal-entry-unsafe": "Restore private ownership, mode 0600 and a bounded size on the named journal entry, then retry."
|
|
24475
|
+
};
|
|
24311
24476
|
}
|
|
24312
24477
|
});
|
|
24313
24478
|
|
|
@@ -24916,7 +25081,7 @@ var init_status2 = __esm({
|
|
|
24916
25081
|
|
|
24917
25082
|
// src/core/harness-continuation.ts
|
|
24918
25083
|
function harnessContinuationPath(repoRoot) {
|
|
24919
|
-
const key = (0,
|
|
25084
|
+
const key = (0, import_node_crypto27.createHash)("sha256").update(comparableWorkspacePath(repoRoot)).digest("hex");
|
|
24920
25085
|
return import_node_path57.default.join(DEVROUTER_HOME, "harness", `${key}.json`);
|
|
24921
25086
|
}
|
|
24922
25087
|
function counter4(value) {
|
|
@@ -25014,11 +25179,11 @@ function settleHarnessContinuation(repoRoot, toolUseId, settlement) {
|
|
|
25014
25179
|
} catch {
|
|
25015
25180
|
}
|
|
25016
25181
|
}
|
|
25017
|
-
var
|
|
25182
|
+
var import_node_crypto27, import_node_fs45, import_node_path57, HARNESS_CONTINUATION_MAX_ENTRIES, HARNESS_CONTINUATION_TTL_MS, HARNESS_CONTINUATION_LOCK_WAIT_MS, MAX_LEDGER_BYTES, MAX_TOOL_USE_ID_LENGTH, MAX_PHASE_LENGTH;
|
|
25018
25183
|
var init_harness_continuation = __esm({
|
|
25019
25184
|
"src/core/harness-continuation.ts"() {
|
|
25020
25185
|
"use strict";
|
|
25021
|
-
|
|
25186
|
+
import_node_crypto27 = require("crypto");
|
|
25022
25187
|
import_node_fs45 = __toESM(require("fs"));
|
|
25023
25188
|
import_node_path57 = __toESM(require("path"));
|
|
25024
25189
|
init_atomic_file();
|
|
@@ -25085,17 +25250,20 @@ async function waitForHarnessGate(options) {
|
|
|
25085
25250
|
options.onObservation?.(observation, now() - started);
|
|
25086
25251
|
if (!isTransitionalHarnessPhase(observation.phase)) {
|
|
25087
25252
|
const waitedMs2 = now() - started;
|
|
25253
|
+
let reason = deferred ? "settled-after-wait" : "settled";
|
|
25254
|
+
if (observation.phase === "unknown") reason = "evidence-unavailable";
|
|
25088
25255
|
return {
|
|
25089
25256
|
version: 1,
|
|
25090
25257
|
decision: deferred ? "deferred-allow" : "allow",
|
|
25091
|
-
reason
|
|
25258
|
+
reason,
|
|
25092
25259
|
waitedMs: waitedMs2,
|
|
25093
25260
|
observations,
|
|
25094
25261
|
observedPhase: observation.phase
|
|
25095
25262
|
};
|
|
25096
25263
|
}
|
|
25097
25264
|
const waitedMs = now() - started;
|
|
25098
|
-
|
|
25265
|
+
const remainingMs = budget - waitedMs;
|
|
25266
|
+
if (remainingMs <= 0) {
|
|
25099
25267
|
return {
|
|
25100
25268
|
version: 1,
|
|
25101
25269
|
decision: "refuse",
|
|
@@ -25120,7 +25288,7 @@ async function waitForHarnessGate(options) {
|
|
|
25120
25288
|
}
|
|
25121
25289
|
}
|
|
25122
25290
|
deferred = true;
|
|
25123
|
-
await sleep3(Math.min(interval,
|
|
25291
|
+
await sleep3(Math.min(interval, remainingMs));
|
|
25124
25292
|
}
|
|
25125
25293
|
}
|
|
25126
25294
|
function parseHarnessGateBudget(value) {
|
|
@@ -25162,6 +25330,91 @@ __export(harness_exports, {
|
|
|
25162
25330
|
detectHarnessHook: () => detectHarnessHook,
|
|
25163
25331
|
runHarnessCommand: () => runHarnessCommand
|
|
25164
25332
|
});
|
|
25333
|
+
function commandSegments(command) {
|
|
25334
|
+
const segments = [];
|
|
25335
|
+
let current = "";
|
|
25336
|
+
let quote;
|
|
25337
|
+
for (const char of command) {
|
|
25338
|
+
if (quote) {
|
|
25339
|
+
current += char;
|
|
25340
|
+
if (char === quote) quote = void 0;
|
|
25341
|
+
continue;
|
|
25342
|
+
}
|
|
25343
|
+
if (char === "'" || char === '"') {
|
|
25344
|
+
quote = char;
|
|
25345
|
+
current += char;
|
|
25346
|
+
continue;
|
|
25347
|
+
}
|
|
25348
|
+
if (char === ";" || char === "\n" || char === "&" || char === "|" || char === "(" || char === ")") {
|
|
25349
|
+
segments.push(current);
|
|
25350
|
+
current = "";
|
|
25351
|
+
continue;
|
|
25352
|
+
}
|
|
25353
|
+
current += char;
|
|
25354
|
+
}
|
|
25355
|
+
segments.push(current);
|
|
25356
|
+
return segments;
|
|
25357
|
+
}
|
|
25358
|
+
function segmentWords(segment, limit) {
|
|
25359
|
+
const words = [];
|
|
25360
|
+
let current = "";
|
|
25361
|
+
let quote;
|
|
25362
|
+
const flush = () => {
|
|
25363
|
+
if (current) words.push(current);
|
|
25364
|
+
current = "";
|
|
25365
|
+
};
|
|
25366
|
+
for (const char of segment) {
|
|
25367
|
+
if (quote) {
|
|
25368
|
+
if (char === quote) {
|
|
25369
|
+
quote = void 0;
|
|
25370
|
+
continue;
|
|
25371
|
+
}
|
|
25372
|
+
current += char;
|
|
25373
|
+
continue;
|
|
25374
|
+
}
|
|
25375
|
+
if (char === "'" || char === '"') {
|
|
25376
|
+
quote = char;
|
|
25377
|
+
continue;
|
|
25378
|
+
}
|
|
25379
|
+
if (char === " " || char === " ") {
|
|
25380
|
+
flush();
|
|
25381
|
+
if (words.length >= limit) return words;
|
|
25382
|
+
continue;
|
|
25383
|
+
}
|
|
25384
|
+
current += char;
|
|
25385
|
+
}
|
|
25386
|
+
flush();
|
|
25387
|
+
return words;
|
|
25388
|
+
}
|
|
25389
|
+
function executableName(word) {
|
|
25390
|
+
return word.slice(word.lastIndexOf("/") + 1);
|
|
25391
|
+
}
|
|
25392
|
+
function commandWord(segment) {
|
|
25393
|
+
const words = segmentWords(segment, COMMAND_WORD_LIMIT);
|
|
25394
|
+
let index = 0;
|
|
25395
|
+
for (; ; ) {
|
|
25396
|
+
const word = words[index];
|
|
25397
|
+
if (word === void 0) return void 0;
|
|
25398
|
+
if (word === "env" || /^[A-Za-z_][A-Za-z0-9_]*=/u.test(word)) {
|
|
25399
|
+
index += 1;
|
|
25400
|
+
continue;
|
|
25401
|
+
}
|
|
25402
|
+
break;
|
|
25403
|
+
}
|
|
25404
|
+
const launcher = words[index];
|
|
25405
|
+
if (launcher !== void 0 && LAUNCHER_WORDS.has(executableName(launcher))) {
|
|
25406
|
+
index += 1;
|
|
25407
|
+
const subcommand = words[index];
|
|
25408
|
+
if (subcommand !== void 0 && LAUNCHER_SUBCOMMANDS.has(subcommand)) index += 1;
|
|
25409
|
+
}
|
|
25410
|
+
return words[index];
|
|
25411
|
+
}
|
|
25412
|
+
function isDevrouterLifecycleCommand(command) {
|
|
25413
|
+
return commandSegments(command).some((segment) => {
|
|
25414
|
+
const word = commandWord(segment);
|
|
25415
|
+
return word !== void 0 && DEVROUTER_EXECUTABLES.has(executableName(word));
|
|
25416
|
+
});
|
|
25417
|
+
}
|
|
25165
25418
|
function detectHarnessHook(payload) {
|
|
25166
25419
|
const turnId = payload.turn_id;
|
|
25167
25420
|
return typeof turnId === "string" && turnId.length > 0 ? "codex" : "claude";
|
|
@@ -25208,11 +25461,19 @@ function permitReason(decision) {
|
|
|
25208
25461
|
}
|
|
25209
25462
|
return `devrouter: this tool call's wait was cancelled${age}; the harness may have run it. Verify whether it ran before issuing a new call.`;
|
|
25210
25463
|
}
|
|
25211
|
-
switch (decision.
|
|
25212
|
-
case "
|
|
25464
|
+
switch (decision.reason) {
|
|
25465
|
+
case "budget-exhausted":
|
|
25213
25466
|
return `devrouter: the managed environment is still ${decision.observedPhase} after waiting ${seconds}s. Do not retry automatically; run 'devrouter status .' and continue once it settles.`;
|
|
25214
|
-
case "
|
|
25467
|
+
case "settled-after-wait":
|
|
25215
25468
|
return `devrouter: environment settled after ${seconds}s; the tool may run now.`;
|
|
25469
|
+
case "devrouter-command":
|
|
25470
|
+
return "devrouter: lifecycle command; the gate left it to the lifecycle engine and did not observe the environment.";
|
|
25471
|
+
case "unmanaged-checkout":
|
|
25472
|
+
return "devrouter: no managed checkout was found for this call; the gate did not observe environment state.";
|
|
25473
|
+
case "hook-payload-invalid":
|
|
25474
|
+
return "devrouter: the hook payload was unreadable; the gate did not observe environment state.";
|
|
25475
|
+
case "evidence-unavailable":
|
|
25476
|
+
return "devrouter: lifecycle evidence was unavailable; the gate observed no settled phase and the tool proceeds.";
|
|
25216
25477
|
default:
|
|
25217
25478
|
return "devrouter: environment settled.";
|
|
25218
25479
|
}
|
|
@@ -25280,10 +25541,9 @@ async function runHarnessCommand(method, options, repoPath, dependencies = {}) {
|
|
|
25280
25541
|
return;
|
|
25281
25542
|
}
|
|
25282
25543
|
kind = detectHarnessHook(payload);
|
|
25283
|
-
const toolName = typeof payload.tool_name === "string" ? payload.tool_name : "";
|
|
25284
25544
|
const toolInput = isRecord7(payload.tool_input) ? payload.tool_input : {};
|
|
25285
|
-
const command = typeof toolInput.command === "string" ? toolInput.command : "";
|
|
25286
|
-
if (
|
|
25545
|
+
const command = typeof toolInput.command === "string" ? toolInput.command : typeof toolInput.cmd === "string" ? toolInput.cmd : "";
|
|
25546
|
+
if (isDevrouterLifecycleCommand(command)) {
|
|
25287
25547
|
const decision2 = gateDecision("allow", "devrouter-command");
|
|
25288
25548
|
process.stdout.write(
|
|
25289
25549
|
json ? `${JSON.stringify(decision2)}
|
|
@@ -25305,7 +25565,7 @@ async function runHarnessCommand(method, options, repoPath, dependencies = {}) {
|
|
|
25305
25565
|
}
|
|
25306
25566
|
const budgetMs = parseHarnessGateBudget(options.waitBudgetMs);
|
|
25307
25567
|
const toolUseId = typeof payload.tool_use_id === "string" && payload.tool_use_id.length > 0 && payload.tool_use_id.length <= MAX_TOOL_USE_ID_LENGTH2 ? payload.tool_use_id : void 0;
|
|
25308
|
-
const payloadSha256 = (0,
|
|
25568
|
+
const payloadSha256 = (0, import_node_crypto28.createHash)("sha256").update(JSON.stringify(toolInput)).digest("hex");
|
|
25309
25569
|
const claim2 = dependencies.claim ?? ((root, input2) => {
|
|
25310
25570
|
const outcome = claimHarnessContinuation(root, input2);
|
|
25311
25571
|
if (outcome.kind === "claimed") {
|
|
@@ -25413,17 +25673,20 @@ async function runHarnessCommand(method, options, repoPath, dependencies = {}) {
|
|
|
25413
25673
|
`
|
|
25414
25674
|
);
|
|
25415
25675
|
}
|
|
25416
|
-
var
|
|
25676
|
+
var import_node_crypto28, MAX_HOOK_PAYLOAD_BYTES, STDIN_TIMEOUT_MS, MAX_TOOL_USE_ID_LENGTH2, DEVROUTER_EXECUTABLES, LAUNCHER_WORDS, LAUNCHER_SUBCOMMANDS, COMMAND_WORD_LIMIT;
|
|
25417
25677
|
var init_harness = __esm({
|
|
25418
25678
|
"src/commands/harness.ts"() {
|
|
25419
25679
|
"use strict";
|
|
25420
|
-
|
|
25680
|
+
import_node_crypto28 = require("crypto");
|
|
25421
25681
|
init_harness_continuation();
|
|
25422
25682
|
init_harness_gate();
|
|
25423
25683
|
MAX_HOOK_PAYLOAD_BYTES = 256 * 1024;
|
|
25424
25684
|
STDIN_TIMEOUT_MS = 5e3;
|
|
25425
25685
|
MAX_TOOL_USE_ID_LENGTH2 = 256;
|
|
25426
|
-
|
|
25686
|
+
DEVROUTER_EXECUTABLES = /* @__PURE__ */ new Set(["devrouter", "devrouter-process"]);
|
|
25687
|
+
LAUNCHER_WORDS = /* @__PURE__ */ new Set(["npx", "pnpm", "npm", "yarn"]);
|
|
25688
|
+
LAUNCHER_SUBCOMMANDS = /* @__PURE__ */ new Set(["exec", "dlx"]);
|
|
25689
|
+
COMMAND_WORD_LIMIT = 8;
|
|
25427
25690
|
}
|
|
25428
25691
|
});
|
|
25429
25692
|
|
|
@@ -27538,7 +27801,7 @@ function sanitizeRouterId(value) {
|
|
|
27538
27801
|
return value.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
27539
27802
|
}
|
|
27540
27803
|
function repoHash(repoPath) {
|
|
27541
|
-
return (0,
|
|
27804
|
+
return (0, import_node_crypto29.createHash)("sha1").update(import_node_path64.default.resolve(repoPath)).digest("hex").slice(0, 12);
|
|
27542
27805
|
}
|
|
27543
27806
|
function asDockerApp(app) {
|
|
27544
27807
|
return app.runtime === "docker";
|
|
@@ -27741,12 +28004,12 @@ function queryMappedPort(repoPath, composeFiles2, overlayPath, service, internal
|
|
|
27741
28004
|
const port = Number(match[1]);
|
|
27742
28005
|
return Number.isInteger(port) && port > 0 ? port : void 0;
|
|
27743
28006
|
}
|
|
27744
|
-
var import_node_child_process33,
|
|
28007
|
+
var import_node_child_process33, import_node_crypto29, import_node_fs51, import_node_path64, import_yaml9;
|
|
27745
28008
|
var init_docker_run = __esm({
|
|
27746
28009
|
"src/core/docker-run.ts"() {
|
|
27747
28010
|
"use strict";
|
|
27748
28011
|
import_node_child_process33 = require("child_process");
|
|
27749
|
-
|
|
28012
|
+
import_node_crypto29 = require("crypto");
|
|
27750
28013
|
import_node_fs51 = __toESM(require("fs"));
|
|
27751
28014
|
import_node_path64 = __toESM(require("path"));
|
|
27752
28015
|
import_yaml9 = __toESM(require("yaml"));
|
|
@@ -30033,7 +30296,7 @@ var init_version = __esm({
|
|
|
30033
30296
|
|
|
30034
30297
|
// src/cli.ts
|
|
30035
30298
|
var import_commander = require("commander");
|
|
30036
|
-
var CLI_VERSION = true ? "0.1.
|
|
30299
|
+
var CLI_VERSION = true ? "0.1.2" : "0.0.0-dev";
|
|
30037
30300
|
var VERSION_FLAGS = /* @__PURE__ */ new Set(["-V", "--version"]);
|
|
30038
30301
|
function withErrorHandling(action2) {
|
|
30039
30302
|
return async (...args) => {
|