@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.
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
 
25
25
  // src/core/devpod-exec.ts
26
26
  var import_node_child_process29 = require("child_process");
27
- var import_node_crypto22 = require("crypto");
27
+ var import_node_crypto23 = require("crypto");
28
28
 
29
29
  // src/core/devpod-environment.ts
30
30
  var import_node_child_process3 = require("child_process");
@@ -4327,12 +4327,13 @@ function reliabilityFence(state) {
4327
4327
  }
4328
4328
 
4329
4329
  // src/core/reliability-operation-store.ts
4330
- var import_node_crypto8 = require("crypto");
4330
+ var import_node_crypto9 = require("crypto");
4331
4331
  var import_node_fs17 = __toESM(require("fs"));
4332
4332
  var import_node_path21 = __toESM(require("path"));
4333
4333
  var import_node_util4 = require("util");
4334
4334
 
4335
4335
  // src/core/capacity-store.ts
4336
+ var import_node_crypto7 = require("crypto");
4336
4337
  var import_node_fs15 = __toESM(require("fs"));
4337
4338
  var import_node_path19 = __toESM(require("path"));
4338
4339
 
@@ -4393,11 +4394,13 @@ function evaluateCapacity(budgets, samples, charges, requested, nowMs, maxSample
4393
4394
  // src/core/capacity-store.ts
4394
4395
  var MAX_BYTES = 1048576;
4395
4396
  var CapacityHistoryError = class extends Error {
4396
- constructor(code) {
4397
+ constructor(code, cause = null, location = null) {
4397
4398
  super(
4398
4399
  code === "capacity-ledger-lost" ? "Capacity ledger history is lost; restore verified capacity-reservations.json." : "Capacity history cannot be proven; inspect the private lifecycle journals."
4399
4400
  );
4400
4401
  this.code = code;
4402
+ this.cause = cause;
4403
+ this.location = location;
4401
4404
  this.name = "CapacityHistoryError";
4402
4405
  }
4403
4406
  };
@@ -4554,9 +4557,10 @@ var CapacityStore = class {
4554
4557
  const buffer = Buffer.alloc(MAX_BYTES + 1);
4555
4558
  const count = import_node_fs15.default.readSync(descriptor, buffer, 0, buffer.length, 0);
4556
4559
  if (count > MAX_BYTES) throw new Error("Capacity reservation snapshot exceeds byte limit.");
4557
- const value = JSON.parse(buffer.subarray(0, count).toString("utf8"));
4560
+ const bytes2 = buffer.subarray(0, count);
4561
+ const value = JSON.parse(bytes2.toString("utf8"));
4558
4562
  validate(value);
4559
- this.ledgerGeneration = `${stat.dev}:${stat.ino}`;
4563
+ this.ledgerGeneration = this.generationIdentity(stat, bytes2);
4560
4564
  if (value.revision < minimumRevision) return { kind: "stale", revision: value.revision };
4561
4565
  this.observedLedger = true;
4562
4566
  return { kind: "intact", revision: value.revision, snapshot: value };
@@ -4609,20 +4613,30 @@ var CapacityStore = class {
4609
4613
  return snapshot;
4610
4614
  }
4611
4615
  commit(snapshot) {
4612
- this.write(this.file, serializeSnapshot(snapshot));
4616
+ const contents = serializeSnapshot(snapshot);
4617
+ this.write(this.file, contents);
4613
4618
  this.observedLedger = true;
4614
- this.rememberGeneration();
4619
+ this.rememberGeneration(contents);
4615
4620
  this.establish();
4616
4621
  }
4617
4622
  /** Remember the published snapshot identity for the next generation fence. */
4618
- rememberGeneration() {
4623
+ rememberGeneration(contents) {
4619
4624
  try {
4620
4625
  const stat = import_node_fs15.default.statSync(this.file);
4621
- this.ledgerGeneration = stat.isFile() ? `${stat.dev}:${stat.ino}` : void 0;
4626
+ this.ledgerGeneration = stat.isFile() ? this.generationIdentity(stat, contents) : void 0;
4622
4627
  } catch {
4623
4628
  this.ledgerGeneration = void 0;
4624
4629
  }
4625
4630
  }
4631
+ /**
4632
+ * File identity plus content digest. Deleting and recreating the snapshot can
4633
+ * reuse its inode number, so the inode alone cannot fence a replacement that
4634
+ * reuses a revision number.
4635
+ */
4636
+ generationIdentity(stat, contents) {
4637
+ const digest = (0, import_node_crypto7.createHash)("sha256").update(contents).digest("hex");
4638
+ return `${stat.dev}:${stat.ino}:${digest}`;
4639
+ }
4626
4640
  /**
4627
4641
  * Durable evidence that recorded history is gone, for a stop whose physical
4628
4642
  * cessation is already proven. The caller holds that proof; this writes no
@@ -4871,7 +4885,7 @@ var CapacityStore = class {
4871
4885
  };
4872
4886
 
4873
4887
  // src/core/controller-store.ts
4874
- var import_node_crypto7 = require("crypto");
4888
+ var import_node_crypto8 = require("crypto");
4875
4889
  var import_node_fs16 = __toESM(require("fs"));
4876
4890
  var import_node_path20 = __toESM(require("path"));
4877
4891
  var CONTROLLER_SNAPSHOT_BYTES = 1048576;
@@ -5173,7 +5187,7 @@ var ControllerStore = class {
5173
5187
  provenance(identity2) {
5174
5188
  if (identity2.version !== 2) throw new Error("Controller binding provenance is unavailable.");
5175
5189
  return {
5176
- digest: (0, import_node_crypto7.createHash)("sha256").update(JSON.stringify(["devrouter-controller-binding-v1", identity2.store, identity2.key])).digest("hex"),
5190
+ digest: (0, import_node_crypto8.createHash)("sha256").update(JSON.stringify(["devrouter-controller-binding-v1", identity2.store, identity2.key])).digest("hex"),
5177
5191
  enrolledEpoch: identity2.enrolledEpoch
5178
5192
  };
5179
5193
  }
@@ -5197,7 +5211,7 @@ var ControllerStore = class {
5197
5211
  if (!current || current.store !== captured.store || current.epoch !== captured.epoch || JSON.stringify(current.fingerprint) !== JSON.stringify(captured.fingerprint) || identity2?.version !== 2)
5198
5212
  throw new Error("Controller binding incarnation changed.");
5199
5213
  this.checkProvenance(current, identity2);
5200
- return (0, import_node_crypto7.createHmac)("sha256", Buffer.from(identity2.key, "hex")).update(JSON.stringify({ owner, config })).digest("hex");
5214
+ return (0, import_node_crypto8.createHmac)("sha256", Buffer.from(identity2.key, "hex")).update(JSON.stringify({ owner, config })).digest("hex");
5201
5215
  };
5202
5216
  }
5203
5217
  read() {
@@ -5250,7 +5264,7 @@ var ControllerStore = class {
5250
5264
  const identity2 = existing?.version === 2 ? existing : {
5251
5265
  version: 2,
5252
5266
  store,
5253
- key: (0, import_node_crypto7.randomBytes)(32).toString("hex"),
5267
+ key: (0, import_node_crypto8.randomBytes)(32).toString("hex"),
5254
5268
  enrolledEpoch: epoch
5255
5269
  };
5256
5270
  if (existing?.version !== 2)
@@ -5296,7 +5310,7 @@ var ControllerStore = class {
5296
5310
  if (!previous) {
5297
5311
  previous = {
5298
5312
  version: 2,
5299
- store: (0, import_node_crypto7.randomUUID)(),
5313
+ store: (0, import_node_crypto8.randomUUID)(),
5300
5314
  epoch: 0,
5301
5315
  revision: 0,
5302
5316
  parkingRevision: 0,
@@ -5347,7 +5361,7 @@ function retain(session, previous) {
5347
5361
 
5348
5362
  // src/core/reliability-operation-store.ts
5349
5363
  function installedCliVersion() {
5350
- return true ? "0.1.1" : "0.0.0-dev";
5364
+ return true ? "0.1.2" : "0.0.0-dev";
5351
5365
  }
5352
5366
  function compareCliVersions(left, right) {
5353
5367
  const parts = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
@@ -5370,7 +5384,7 @@ function identityKey(identity2) {
5370
5384
  if (!import_node_path21.default.isAbsolute(identity2.repoPath) || import_node_path21.default.resolve(identity2.repoPath) !== identity2.repoPath || identity2.repoPath.includes("\0") || identity2.workspace !== null && !isReliabilityId(identity2.workspace) || !["devpod", "devsy"].includes(identity2.provider)) {
5371
5385
  throw new Error("Invalid reliability workspace identity.");
5372
5386
  }
5373
- return (0, import_node_crypto8.createHash)("sha256").update(identity2.repoPath).digest("hex");
5387
+ return (0, import_node_crypto9.createHash)("sha256").update(identity2.repoPath).digest("hex");
5374
5388
  }
5375
5389
  function reliabilityOperationPath(identity2) {
5376
5390
  return import_node_path21.default.join(DEVROUTER_HOME, "reliability", `${identityKey(identity2)}.json`);
@@ -5669,12 +5683,35 @@ function validate2(record5, identity2) {
5669
5683
  }
5670
5684
  }
5671
5685
  }
5686
+ var ReliabilityJournalError = class extends Error {
5687
+ constructor(cause, location, message) {
5688
+ super(message);
5689
+ this.cause = cause;
5690
+ this.location = location;
5691
+ this.name = "ReliabilityJournalError";
5692
+ }
5693
+ };
5694
+ var MAX_REPORTED_ENTRY_NAME = 160;
5695
+ var JournalFileGuardError = class extends Error {
5696
+ constructor(message) {
5697
+ super(message);
5698
+ this.name = "JournalFileGuardError";
5699
+ }
5700
+ };
5701
+ function journalEntryLocation(name) {
5702
+ const printable = name.replace(/[^A-Za-z0-9._-]/g, "?");
5703
+ return printable.length > MAX_REPORTED_ENTRY_NAME ? `${printable.slice(0, MAX_REPORTED_ENTRY_NAME - 3)}...` : printable;
5704
+ }
5672
5705
  function createLifecycleCapacityStore(directory = import_node_path21.default.join(DEVROUTER_HOME, "controller")) {
5673
5706
  return new CapacityStore(directory, void 0, () => {
5674
5707
  try {
5675
5708
  return listUnsettledCapacityBindings().floor;
5676
- } catch {
5677
- throw new CapacityHistoryError("capacity-history-unprovable");
5709
+ } catch (error) {
5710
+ throw error instanceof ReliabilityJournalError ? new CapacityHistoryError("capacity-history-unprovable", error.cause, error.location) : new CapacityHistoryError(
5711
+ "capacity-history-unprovable",
5712
+ "journal-enumeration-failed",
5713
+ null
5714
+ );
5678
5715
  }
5679
5716
  });
5680
5717
  }
@@ -5733,11 +5770,12 @@ function readBoundedPrivateJson(file, label) {
5733
5770
  try {
5734
5771
  const stat = import_node_fs17.default.fstatSync(descriptor);
5735
5772
  if (!stat.isFile() || stat.uid !== process.getuid?.() || stat.size > MAX_RECORD_BYTES || (stat.mode & 63) !== 0) {
5736
- throw new Error(`${label} is not a bounded private file.`);
5773
+ throw new JournalFileGuardError(`${label} is not a bounded private file.`);
5737
5774
  }
5738
5775
  const bytes2 = Buffer.alloc(MAX_RECORD_BYTES + 1);
5739
5776
  const count = import_node_fs17.default.readSync(descriptor, bytes2, 0, bytes2.length, 0);
5740
- if (count > MAX_RECORD_BYTES) throw new Error(`${label} exceeds its byte limit.`);
5777
+ if (count > MAX_RECORD_BYTES)
5778
+ throw new JournalFileGuardError(`${label} exceeds its byte limit.`);
5741
5779
  return JSON.parse(bytes2.subarray(0, count).toString("utf8"));
5742
5780
  } finally {
5743
5781
  import_node_fs17.default.closeSync(descriptor);
@@ -5745,7 +5783,11 @@ function readBoundedPrivateJson(file, label) {
5745
5783
  }
5746
5784
  function assertReliabilityEnumerationTime(startedAtMs) {
5747
5785
  if (performance.now() - startedAtMs > MAX_RELIABILITY_ENUMERATION_MS)
5748
- throw new Error("Reliability journal enumeration exceeded its time limit.");
5786
+ throw new ReliabilityJournalError(
5787
+ "journal-enumeration-timeout",
5788
+ null,
5789
+ "Reliability journal enumeration exceeded its time limit."
5790
+ );
5749
5791
  }
5750
5792
  function reliabilityDirectory() {
5751
5793
  return import_node_path21.default.join(DEVROUTER_HOME, "reliability");
@@ -5766,22 +5808,56 @@ function listReliabilityOperations() {
5766
5808
  stat = import_node_fs17.default.lstatSync(directory);
5767
5809
  } catch (error) {
5768
5810
  if (error.code === "ENOENT") return [];
5769
- throw error;
5811
+ throw new ReliabilityJournalError(
5812
+ "journal-directory-unreadable",
5813
+ null,
5814
+ "Reliability journal directory could not be read."
5815
+ );
5770
5816
  }
5771
5817
  if (!stat.isDirectory() || stat.isSymbolicLink())
5772
- throw new Error("Reliability journal directory is unsafe.");
5818
+ throw new ReliabilityJournalError(
5819
+ "journal-directory-unsafe",
5820
+ null,
5821
+ "Reliability journal directory is unsafe."
5822
+ );
5773
5823
  if (stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
5774
- throw new Error("Reliability journal directory is not private.");
5824
+ throw new ReliabilityJournalError(
5825
+ "journal-directory-unsafe",
5826
+ null,
5827
+ "Reliability journal directory is not private."
5828
+ );
5775
5829
  const entries = [];
5776
- const handle = import_node_fs17.default.opendirSync(directory);
5830
+ let handle;
5831
+ try {
5832
+ handle = import_node_fs17.default.opendirSync(directory);
5833
+ } catch {
5834
+ throw new ReliabilityJournalError(
5835
+ "journal-directory-unreadable",
5836
+ null,
5837
+ "Reliability journal directory could not be read."
5838
+ );
5839
+ }
5777
5840
  try {
5778
5841
  for (; ; ) {
5779
5842
  assertReliabilityEnumerationTime(startedAtMs);
5780
- const entry = handle.readSync();
5843
+ let entry;
5844
+ try {
5845
+ entry = handle.readSync();
5846
+ } catch {
5847
+ throw new ReliabilityJournalError(
5848
+ "journal-directory-unreadable",
5849
+ null,
5850
+ "Reliability journal directory could not be read."
5851
+ );
5852
+ }
5781
5853
  if (!entry) break;
5782
5854
  entries.push(entry);
5783
5855
  if (entries.length > MAX_RELIABILITY_DIRECTORY_ENTRIES)
5784
- throw new Error("Reliability journal directory exceeds its entry limit.");
5856
+ throw new ReliabilityJournalError(
5857
+ "journal-enumeration-limit",
5858
+ null,
5859
+ "Reliability journal directory exceeds its entry limit."
5860
+ );
5785
5861
  }
5786
5862
  } finally {
5787
5863
  handle.closeSync();
@@ -5790,27 +5866,82 @@ function listReliabilityOperations() {
5790
5866
  for (const entry of entries) {
5791
5867
  assertReliabilityEnumerationTime(startedAtMs);
5792
5868
  if (entry.isSymbolicLink())
5793
- throw new Error("Reliability journal directory contains a symlink.");
5869
+ throw new ReliabilityJournalError(
5870
+ "journal-entry-unsupported",
5871
+ journalEntryLocation(entry.name),
5872
+ "Reliability journal directory contains a symlink."
5873
+ );
5794
5874
  if (!entry.isFile())
5795
- throw new Error("Reliability journal directory contains an unsupported entry.");
5875
+ throw new ReliabilityJournalError(
5876
+ "journal-entry-unsupported",
5877
+ journalEntryLocation(entry.name),
5878
+ "Reliability journal directory contains an unsupported entry."
5879
+ );
5796
5880
  if (RELIABILITY_LOCK_NAME_RE.test(entry.name) || RELIABILITY_ATOMIC_TEMP_NAME_RE.test(entry.name))
5797
5881
  continue;
5798
5882
  const match = RELIABILITY_JOURNAL_NAME_RE.exec(entry.name);
5799
- if (!match) throw new Error("Reliability journal directory contains an unsupported entry.");
5883
+ if (!match)
5884
+ throw new ReliabilityJournalError(
5885
+ "journal-entry-unsupported",
5886
+ journalEntryLocation(entry.name),
5887
+ "Reliability journal directory contains an unsupported entry."
5888
+ );
5800
5889
  journals.push({ name: entry.name, key: match[1] });
5801
5890
  }
5802
5891
  if (journals.length > MAX_RELIABILITY_JOURNALS)
5803
- throw new Error("Reliability journal directory exceeds its journal limit.");
5892
+ throw new ReliabilityJournalError(
5893
+ "journal-enumeration-limit",
5894
+ null,
5895
+ "Reliability journal directory exceeds its journal limit."
5896
+ );
5804
5897
  journals.sort((left, right) => left.name.localeCompare(right.name));
5805
5898
  const records = [];
5806
5899
  for (const journal of journals) {
5807
5900
  assertReliabilityEnumerationTime(startedAtMs);
5808
5901
  const file = import_node_path21.default.join(directory, journal.name);
5809
- const identity2 = journalIdentity(readBoundedPrivateJson(file, "Reliability journal"));
5810
- if (identityKey(identity2) !== journal.key)
5811
- throw new Error("Reliability journal filename does not match its identity.");
5812
- const record5 = readReliabilityOperation(identity2);
5813
- if (!record5) throw new Error("Reliability journal disappeared during enumeration.");
5902
+ let raw;
5903
+ try {
5904
+ raw = readBoundedPrivateJson(file, "Reliability journal");
5905
+ } catch (error) {
5906
+ const fsCode = error?.code;
5907
+ const cause = error instanceof JournalFileGuardError ? "journal-entry-unsafe" : error instanceof SyntaxError || !fsCode ? "journal-invalid" : "journal-unreadable";
5908
+ throw new ReliabilityJournalError(
5909
+ cause,
5910
+ journalEntryLocation(journal.name),
5911
+ error instanceof JournalFileGuardError ? error.message : cause === "journal-invalid" ? "Reliability journal entry is invalid." : "Reliability journal entry could not be read."
5912
+ );
5913
+ }
5914
+ if (raw === void 0)
5915
+ throw new ReliabilityJournalError(
5916
+ "journal-unstable",
5917
+ journalEntryLocation(journal.name),
5918
+ "Reliability journal disappeared during enumeration."
5919
+ );
5920
+ let identity2;
5921
+ let record5;
5922
+ try {
5923
+ identity2 = journalIdentity(raw);
5924
+ if (identityKey(identity2) !== journal.key)
5925
+ throw new ReliabilityJournalError(
5926
+ "journal-identity-mismatch",
5927
+ journalEntryLocation(journal.name),
5928
+ "Reliability journal filename does not match its identity."
5929
+ );
5930
+ record5 = readReliabilityOperation(identity2);
5931
+ } catch (error) {
5932
+ if (error instanceof ReliabilityJournalError) throw error;
5933
+ throw new ReliabilityJournalError(
5934
+ "journal-invalid",
5935
+ journalEntryLocation(journal.name),
5936
+ "Reliability journal entry is invalid."
5937
+ );
5938
+ }
5939
+ if (!record5)
5940
+ throw new ReliabilityJournalError(
5941
+ "journal-unstable",
5942
+ journalEntryLocation(journal.name),
5943
+ "Reliability journal disappeared during enumeration."
5944
+ );
5814
5945
  records.push(record5);
5815
5946
  assertReliabilityEnumerationTime(startedAtMs);
5816
5947
  }
@@ -5886,7 +6017,7 @@ function clearStartupWitness(identity2, fence) {
5886
6017
  }
5887
6018
 
5888
6019
  // src/core/repo-config.ts
5889
- var import_node_crypto9 = require("crypto");
6020
+ var import_node_crypto10 = require("crypto");
5890
6021
  var import_node_fs18 = __toESM(require("fs"));
5891
6022
  var import_node_path22 = __toESM(require("path"));
5892
6023
  var import_yaml3 = __toESM(require("yaml"));
@@ -7163,7 +7294,7 @@ function loadRepoConfig(repoPath, read2 = (file) => import_node_fs18.default.rea
7163
7294
  const config = parseConfig(parsed ?? {}, configPath);
7164
7295
  const requiredVersion = config.devrouter?.version;
7165
7296
  if (requiredVersion && !hasWarnedVersionMismatch) {
7166
- const cliVersion = true ? "0.1.1" : "0.0.0-dev";
7297
+ const cliVersion = true ? "0.1.2" : "0.0.0-dev";
7167
7298
  if (cliVersion !== "0.0.0-dev" && compareSemver2(requiredVersion, cliVersion) > 0) {
7168
7299
  hasWarnedVersionMismatch = true;
7169
7300
  process.stderr.write(
@@ -7342,7 +7473,7 @@ async function ensureNetwork(name) {
7342
7473
 
7343
7474
  // src/core/tls.ts
7344
7475
  var import_node_child_process13 = require("child_process");
7345
- var import_node_crypto10 = require("crypto");
7476
+ var import_node_crypto11 = require("crypto");
7346
7477
  var import_node_fs19 = __toESM(require("fs"));
7347
7478
  var import_node_path23 = __toESM(require("path"));
7348
7479
  var DEFAULT_TLS_CERT_HOSTS = ["localhost", "*.localhost"];
@@ -7412,7 +7543,7 @@ function parseDnsHostsFromSubjectAltName(subjectAltName) {
7412
7543
  return normalizeUniqueHosts(names);
7413
7544
  }
7414
7545
  function parseCertificateDnsHosts(pem) {
7415
- const certificate = new import_node_crypto10.X509Certificate(pem);
7546
+ const certificate = new import_node_crypto11.X509Certificate(pem);
7416
7547
  const subjectAltName = certificate.subjectAltName ?? "";
7417
7548
  if (subjectAltName.length === 0) {
7418
7549
  return [];
@@ -8478,12 +8609,12 @@ function networkProviderEnvironment(binding, source) {
8478
8609
  }
8479
8610
 
8480
8611
  // src/core/network-claim-lookup.ts
8481
- var import_node_crypto12 = require("crypto");
8612
+ var import_node_crypto13 = require("crypto");
8482
8613
  var import_node_fs24 = __toESM(require("fs"));
8483
8614
  var import_node_path28 = __toESM(require("path"));
8484
8615
 
8485
8616
  // src/core/network-claims.ts
8486
- var import_node_crypto11 = require("crypto");
8617
+ var import_node_crypto12 = require("crypto");
8487
8618
  var import_node_fs23 = __toESM(require("fs"));
8488
8619
  var import_node_path27 = __toESM(require("path"));
8489
8620
 
@@ -9673,7 +9804,7 @@ function assertDirectory(directory) {
9673
9804
  }
9674
9805
  }
9675
9806
  function hashKey(value) {
9676
- return (0, import_node_crypto11.createHash)("sha256").update(value).digest("hex");
9807
+ return (0, import_node_crypto12.createHash)("sha256").update(value).digest("hex");
9677
9808
  }
9678
9809
  function cloneFence(fence) {
9679
9810
  return { ...fence };
@@ -9701,7 +9832,7 @@ function claimError(code, message) {
9701
9832
  function networkOwnerKey(repoPath) {
9702
9833
  if (!import_node_path28.default.isAbsolute(repoPath) || import_node_path28.default.resolve(repoPath) !== repoPath)
9703
9834
  throw new Error("Invalid network owner path.");
9704
- return (0, import_node_crypto12.createHash)("sha256").update(repoPath).digest("hex");
9835
+ return (0, import_node_crypto13.createHash)("sha256").update(repoPath).digest("hex");
9705
9836
  }
9706
9837
  function findOwnedNetworkClaim(repoPath, root = NETWORK_CLAIMS_ROOT) {
9707
9838
  let names;
@@ -9741,7 +9872,7 @@ function findOwnedNetworkClaim(repoPath, root = NETWORK_CLAIMS_ROOT) {
9741
9872
  } finally {
9742
9873
  import_node_fs24.default.closeSync(descriptor);
9743
9874
  }
9744
- if (typeof value.daemonId !== "string" || `${(0, import_node_crypto12.createHash)("sha256").update(value.daemonId).digest("hex")}.json` !== file)
9875
+ if (typeof value.daemonId !== "string" || `${(0, import_node_crypto13.createHash)("sha256").update(value.daemonId).digest("hex")}.json` !== file)
9745
9876
  throw new Error("Retained network daemon identity is invalid.");
9746
9877
  const claim2 = readNetworkClaim({
9747
9878
  daemonId: value.daemonId,
@@ -9758,7 +9889,7 @@ function findOwnedNetworkClaim(repoPath, root = NETWORK_CLAIMS_ROOT) {
9758
9889
 
9759
9890
  // src/core/network-provider-inspect.ts
9760
9891
  var import_node_child_process15 = require("child_process");
9761
- var import_node_crypto13 = require("crypto");
9892
+ var import_node_crypto14 = require("crypto");
9762
9893
  function object2(value) {
9763
9894
  if (!value || typeof value !== "object" || Array.isArray(value))
9764
9895
  throw new Error("Invalid provider evidence.");
@@ -9778,7 +9909,7 @@ function qualifyNetworkProviderDefinition(value, provider) {
9778
9909
  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 !== "") {
9779
9910
  throw new Error("Docker provider definition is not qualified for network allocation.");
9780
9911
  }
9781
- return (0, import_node_crypto13.createHash)("sha256").update(JSON.stringify({ name: definition.name, agent, options, exec })).digest("hex");
9912
+ return (0, import_node_crypto14.createHash)("sha256").update(JSON.stringify({ name: definition.name, agent, options, exec })).digest("hex");
9782
9913
  }
9783
9914
  function read(provider, args) {
9784
9915
  const result = (0, import_node_child_process15.spawnSync)(provider, args, {
@@ -10161,7 +10292,7 @@ var ExecutionOutcomeError = class extends Error {
10161
10292
  };
10162
10293
 
10163
10294
  // src/core/reliability-lifecycle.ts
10164
- var import_node_crypto21 = require("crypto");
10295
+ var import_node_crypto22 = require("crypto");
10165
10296
  var import_node_path40 = __toESM(require("path"));
10166
10297
  var import_node_util7 = require("util");
10167
10298
 
@@ -10170,7 +10301,7 @@ var import_node_fs26 = __toESM(require("fs"));
10170
10301
  var import_node_path30 = __toESM(require("path"));
10171
10302
 
10172
10303
  // src/core/controller-client.ts
10173
- var import_node_crypto14 = require("crypto");
10304
+ var import_node_crypto15 = require("crypto");
10174
10305
  var import_node_fs27 = __toESM(require("fs"));
10175
10306
  var import_node_net2 = __toESM(require("net"));
10176
10307
  var import_node_path32 = __toESM(require("path"));
@@ -10185,7 +10316,7 @@ var CONTROLLER_PROFILE_RE = new RegExp(
10185
10316
  );
10186
10317
 
10187
10318
  // src/core/controller-monitor.ts
10188
- var import_node_crypto15 = require("crypto");
10319
+ var import_node_crypto16 = require("crypto");
10189
10320
  var import_node_util6 = require("util");
10190
10321
 
10191
10322
  // src/core/reliability-output.ts
@@ -10974,7 +11105,7 @@ function stepReliability(state, event, nowMs) {
10974
11105
 
10975
11106
  // src/core/reliability-worker.ts
10976
11107
  var import_node_child_process17 = require("child_process");
10977
- var import_node_crypto16 = require("crypto");
11108
+ var import_node_crypto17 = require("crypto");
10978
11109
  var import_node_fs28 = __toESM(require("fs"));
10979
11110
  var import_node_path33 = __toESM(require("path"));
10980
11111
 
@@ -11742,7 +11873,7 @@ async function runManagedHostPreparation(repoPath, config) {
11742
11873
 
11743
11874
  // src/core/managed-post-start.ts
11744
11875
  var import_node_child_process22 = require("child_process");
11745
- var import_node_crypto17 = require("crypto");
11876
+ var import_node_crypto18 = require("crypto");
11746
11877
  var import_node_fs31 = __toESM(require("fs"));
11747
11878
  var import_node_path36 = __toESM(require("path"));
11748
11879
  var MANAGED_MARKER = "devrouter:managed devcontainer";
@@ -11799,7 +11930,7 @@ function readRegularFile(filePath) {
11799
11930
  return readRegularFileBytes(filePath)?.toString("utf-8");
11800
11931
  }
11801
11932
  function adapterFingerprint(adapter) {
11802
- return (0, import_node_crypto17.createHash)("sha256").update(adapter).digest("hex");
11933
+ return (0, import_node_crypto18.createHash)("sha256").update(adapter).digest("hex");
11803
11934
  }
11804
11935
  function resolveProcessHelperPath() {
11805
11936
  const candidates = [
@@ -11952,25 +12083,34 @@ function runManagedProcessAction(options) {
11952
12083
  }
11953
12084
 
11954
12085
  // src/core/managed-runtime-status.ts
12086
+ function recoveryPath(repoPath) {
12087
+ if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(repoPath)) return repoPath;
12088
+ return `'${repoPath.replaceAll("'", "'\\''")}'`;
12089
+ }
11955
12090
  function reliabilityRecovery(reason2, repoPath) {
12091
+ const checkout = recoveryPath(repoPath);
11956
12092
  switch (reason2) {
11957
12093
  case "stop-incomplete":
11958
12094
  case "operation-unknown":
11959
- return [`Run: devrouter stop ${repoPath}`, `Run: devrouter ensure ${repoPath} --repair`];
12095
+ return [`Run: devrouter stop ${checkout}`, `Run: devrouter ensure ${checkout} --repair`];
11960
12096
  case "start-refused":
11961
12097
  return [
11962
- `Run: devrouter doctor ${repoPath} to read the refused fixed host-port claim and its holder`,
11963
- `Stop the holding workspace or change this repository's own published binding, then run: devrouter ensure ${repoPath}`
12098
+ `Run: devrouter doctor --repo ${checkout} to read the refused fixed host-port claim and its holder`,
12099
+ `Stop the holding workspace or change this repository's own published binding, then run: devrouter ensure ${checkout}`
11964
12100
  ];
11965
12101
  case "unadmittable":
11966
12102
  return [
11967
- `Run: devrouter stop ${repoPath}`,
11968
- `Lower the requested capacity in .devrouter.yml, then run: devrouter ensure ${repoPath}`
12103
+ `Run: devrouter stop ${checkout}`,
12104
+ `Lower the requested capacity in .devrouter.yml, then run: devrouter ensure ${checkout}`
11969
12105
  ];
11970
12106
  case "capacity-parked":
11971
- return [`Run: devrouter ensure ${repoPath} (waits for capacity to free up)`];
12107
+ return [
12108
+ "Parked for host capacity: the enrolled foreground controller resumes this checkout after its pressure dwell and live-consumer checks pass.",
12109
+ `Inspect the parked intent with: devrouter status --repo ${checkout} --json`,
12110
+ `'devrouter ensure' refuses while the journal stays parked; release the intent instead with: devrouter stop ${checkout}`
12111
+ ];
11972
12112
  case "capacity-waiting":
11973
- return [`Run: devrouter ensure ${repoPath} (still queued until capacity frees up)`];
12113
+ return [`Run: devrouter ensure ${checkout} (still queued until capacity frees up)`];
11974
12114
  default:
11975
12115
  return [];
11976
12116
  }
@@ -12719,10 +12859,10 @@ function inspectLegacyNetworkCapacity(input) {
12719
12859
  }
12720
12860
 
12721
12861
  // src/core/network-managed.ts
12722
- var import_node_crypto20 = require("crypto");
12862
+ var import_node_crypto21 = require("crypto");
12723
12863
 
12724
12864
  // src/core/network-compose.ts
12725
- var import_node_crypto18 = require("crypto");
12865
+ var import_node_crypto19 = require("crypto");
12726
12866
  var SAFE_ENDPOINT_UPPER_BOUND_SEMANTICS = "full-lifecycle-demand";
12727
12867
  function isRecord5(value) {
12728
12868
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -13528,12 +13668,12 @@ function stableValue(value) {
13528
13668
  }
13529
13669
  function fingerprintComposeNetworkModel(input) {
13530
13670
  const projection = normalizedFingerprintProjection(input);
13531
- return (0, import_node_crypto18.createHash)("sha256").update(stableValue(projection), "utf8").digest("hex");
13671
+ return (0, import_node_crypto19.createHash)("sha256").update(stableValue(projection), "utf8").digest("hex");
13532
13672
  }
13533
13673
 
13534
13674
  // src/core/network-compose-files.ts
13535
13675
  var import_node_child_process25 = require("child_process");
13536
- var import_node_crypto19 = require("crypto");
13676
+ var import_node_crypto20 = require("crypto");
13537
13677
  var import_node_fs33 = __toESM(require("fs"));
13538
13678
  var import_node_path38 = __toESM(require("path"));
13539
13679
  var import_yaml4 = __toESM(require("yaml"));
@@ -13634,7 +13774,7 @@ ${JSON.stringify(extended.config, null, 2)}
13634
13774
  ...plan,
13635
13775
  contents,
13636
13776
  composeFiles: [...plan.composeFiles, overlayPath],
13637
- effectiveConfigSha256: (0, import_node_crypto19.createHash)("sha256").update(contents).digest("hex")
13777
+ effectiveConfigSha256: (0, import_node_crypto20.createHash)("sha256").update(contents).digest("hex")
13638
13778
  };
13639
13779
  return {
13640
13780
  plan: result,
@@ -13952,7 +14092,7 @@ function createManagedNetworkSession(input) {
13952
14092
  "Insufficient endpoint headroom; request an allowed larger network before first allocation."
13953
14093
  );
13954
14094
  const authority = readNetworkOperationAuthority(identity2);
13955
- const fingerprint = (0, import_node_crypto20.createHash)("sha256").update(input.plan().sourceConfigSha256).update(fingerprintComposeNetworkModel(model)).digest("hex");
14095
+ const fingerprint = (0, import_node_crypto21.createHash)("sha256").update(input.plan().sourceConfigSha256).update(fingerprintComposeNetworkModel(model)).digest("hex");
13956
14096
  if (!saved) {
13957
14097
  if (policy.status !== "valid")
13958
14098
  throw new Error("New network allocation requires valid machine policy.");
@@ -16279,7 +16419,7 @@ async function devpodExecOutcome(repoPath, command) {
16279
16419
  }
16280
16420
  assertRunningDevpod(devpod.id, repoPath);
16281
16421
  const workspaceDirectory = resolveWorkspaceDirectory(repoPath);
16282
- const statusMarker = `__DEVROUTER_EXIT_${(0, import_node_crypto22.randomUUID)()}__:`;
16422
+ const statusMarker = `__DEVROUTER_EXIT_${(0, import_node_crypto23.randomUUID)()}__:`;
16283
16423
  const statusMarkerBytes = Buffer.from(statusMarker, "ascii");
16284
16424
  const literalCommand = command.map(quotePosixArg).join(" ");
16285
16425
  const wrappedCommand = `${literalCommand}; __devrouter_status=$?; printf '${statusMarker}%s\\n' "$__devrouter_status" >&2; exit 0`;