@devrouter/cli 0.5.3 → 0.5.5

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.
@@ -2752,7 +2752,7 @@ function assertManagedContainerConfigUnchanged(options) {
2752
2752
  cwd: workingDirectory,
2753
2753
  encoding: "utf-8",
2754
2754
  env,
2755
- input: rendered.stdout,
2755
+ input: rendered.stdout.replaceAll("$$", "$"),
2756
2756
  stdio: ["pipe", "pipe", "ignore"],
2757
2757
  timeout: COMPOSE_HASH_TIMEOUT_MS,
2758
2758
  maxBuffer: 1024 * 1024
@@ -2924,12 +2924,10 @@ function buildHostRoutesDocument(routes, tlsEnabled) {
2924
2924
  }
2925
2925
  };
2926
2926
  }
2927
- const document = {
2928
- http: {
2929
- routers,
2930
- services
2931
- }
2932
- };
2927
+ const document = {};
2928
+ if (Object.keys(routers).length > 0) {
2929
+ document.http = { routers, services };
2930
+ }
2933
2931
  if (Object.keys(tcpRouters).length > 0) {
2934
2932
  document.tcp = { routers: tcpRouters, services: tcpServices };
2935
2933
  }
@@ -3065,7 +3063,11 @@ function parseCanonicalState(raw) {
3065
3063
  throw new Error(`Canonical host-route document is invalid: ${error.message}`);
3066
3064
  }
3067
3065
  const expectedDocument = buildHostRoutesDocument(routes, metadata.tlsEnabled);
3068
- if (!(0, import_node_util2.isDeepStrictEqual)(document, expectedDocument)) {
3066
+ const matchesLegacyEmptyHttp = expectedDocument.http === void 0 && (0, import_node_util2.isDeepStrictEqual)(document, {
3067
+ ...expectedDocument,
3068
+ http: { routers: {}, services: {} }
3069
+ });
3070
+ if (!(0, import_node_util2.isDeepStrictEqual)(document, expectedDocument) && !matchesLegacyEmptyHttp) {
3069
3071
  throw new Error("Canonical host-route document does not match its metadata.");
3070
3072
  }
3071
3073
  return { kind: "canonical", metadata };
@@ -5397,7 +5399,7 @@ function retain(session, previous) {
5397
5399
 
5398
5400
  // src/core/reliability-operation-store.ts
5399
5401
  function installedCliVersion() {
5400
- return true ? "0.5.3" : "0.0.0-dev";
5402
+ return true ? "0.5.5" : "0.0.0-dev";
5401
5403
  }
5402
5404
  function compareCliVersions(left, right) {
5403
5405
  const parts = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
@@ -7407,7 +7409,7 @@ function loadRepoConfig(repoPath, read2 = (file) => import_node_fs19.default.rea
7407
7409
  const config = parseConfig(parsed ?? {}, configPath);
7408
7410
  const requiredVersion = config.devrouter?.version;
7409
7411
  if (requiredVersion && !hasWarnedVersionMismatch) {
7410
- const cliVersion = true ? "0.5.3" : "0.0.0-dev";
7412
+ const cliVersion = true ? "0.5.5" : "0.0.0-dev";
7411
7413
  if (cliVersion !== "0.0.0-dev" && compareSemver2(requiredVersion, cliVersion) > 0) {
7412
7414
  hasWarnedVersionMismatch = true;
7413
7415
  process.stderr.write(
package/dist/devrouter.js CHANGED
@@ -2651,12 +2651,10 @@ function buildHostRoutesDocument(routes, tlsEnabled) {
2651
2651
  }
2652
2652
  };
2653
2653
  }
2654
- const document = {
2655
- http: {
2656
- routers,
2657
- services
2658
- }
2659
- };
2654
+ const document = {};
2655
+ if (Object.keys(routers).length > 0) {
2656
+ document.http = { routers, services };
2657
+ }
2660
2658
  if (Object.keys(tcpRouters).length > 0) {
2661
2659
  document.tcp = { routers: tcpRouters, services: tcpServices };
2662
2660
  }
@@ -2790,7 +2788,11 @@ function parseCanonicalState(raw) {
2790
2788
  throw new Error(`Canonical host-route document is invalid: ${error.message}`);
2791
2789
  }
2792
2790
  const expectedDocument = buildHostRoutesDocument(routes, metadata.tlsEnabled);
2793
- if (!(0, import_node_util2.isDeepStrictEqual)(document, expectedDocument)) {
2791
+ const matchesLegacyEmptyHttp = expectedDocument.http === void 0 && (0, import_node_util2.isDeepStrictEqual)(document, {
2792
+ ...expectedDocument,
2793
+ http: { routers: {}, services: {} }
2794
+ });
2795
+ if (!(0, import_node_util2.isDeepStrictEqual)(document, expectedDocument) && !matchesLegacyEmptyHttp) {
2794
2796
  throw new Error("Canonical host-route document does not match its metadata.");
2795
2797
  }
2796
2798
  return { kind: "canonical", metadata };
@@ -4788,7 +4790,7 @@ function loadRepoConfig(repoPath, read2 = (file) => import_node_fs8.default.read
4788
4790
  const config = parseConfig(parsed ?? {}, configPath);
4789
4791
  const requiredVersion = config.devrouter?.version;
4790
4792
  if (requiredVersion && !hasWarnedVersionMismatch) {
4791
- const cliVersion = true ? "0.5.3" : "0.0.0-dev";
4793
+ const cliVersion = true ? "0.5.5" : "0.0.0-dev";
4792
4794
  if (cliVersion !== "0.0.0-dev" && compareSemver(requiredVersion, cliVersion) > 0) {
4793
4795
  hasWarnedVersionMismatch = true;
4794
4796
  process.stderr.write(
@@ -6787,7 +6789,7 @@ var init_reliability_contract = __esm({
6787
6789
 
6788
6790
  // src/core/reliability-operation-store.ts
6789
6791
  function installedCliVersion() {
6790
- return true ? "0.5.3" : "0.0.0-dev";
6792
+ return true ? "0.5.5" : "0.0.0-dev";
6791
6793
  }
6792
6794
  function compareCliVersions(left, right) {
6793
6795
  const parts = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
@@ -11399,7 +11401,7 @@ function assertManagedContainerConfigUnchanged(options) {
11399
11401
  cwd: workingDirectory,
11400
11402
  encoding: "utf-8",
11401
11403
  env,
11402
- input: rendered.stdout,
11404
+ input: rendered.stdout.replaceAll("$$", "$"),
11403
11405
  stdio: ["pipe", "pipe", "ignore"],
11404
11406
  timeout: COMPOSE_HASH_TIMEOUT_MS,
11405
11407
  maxBuffer: 1024 * 1024
@@ -24523,7 +24525,7 @@ function probeInstalledCliVersion(executable) {
24523
24525
  }
24524
24526
  function buildCliPathCheck(options = {}) {
24525
24527
  const id5 = "global.cli-path";
24526
- const runningVersion = options.runningVersion ?? (true ? "0.5.3" : "0.0.0-dev");
24528
+ const runningVersion = options.runningVersion ?? (true ? "0.5.5" : "0.0.0-dev");
24527
24529
  if (runningVersion === "0.0.0-dev") {
24528
24530
  return {
24529
24531
  id: id5,
@@ -25419,7 +25421,7 @@ async function buildDoctorReport(options = {}) {
25419
25421
  suggestion: `Remedy ${expansionNotice.remedy.code}: set a named default profile other than '${expansionNotice.profile}'${remedyCandidates}.`
25420
25422
  });
25421
25423
  }
25422
- const cliVersion = true ? "0.5.3" : "0.0.0-dev";
25424
+ const cliVersion = true ? "0.5.5" : "0.0.0-dev";
25423
25425
  const configVersion = config.devrouter?.version;
25424
25426
  const installedKnown = cliVersion !== "0.0.0-dev";
25425
25427
  const versionComparison = installedKnown && configVersion ? compareSemver(configVersion, cliVersion) : void 0;
@@ -34082,7 +34084,7 @@ var init_version = __esm({
34082
34084
 
34083
34085
  // src/cli.ts
34084
34086
  var import_commander = require("commander");
34085
- var CLI_VERSION = true ? "0.5.3" : "0.0.0-dev";
34087
+ var CLI_VERSION = true ? "0.5.5" : "0.0.0-dev";
34086
34088
  var VERSION_FLAGS = /* @__PURE__ */ new Set(["-V", "--version"]);
34087
34089
  function withErrorHandling(action2) {
34088
34090
  return async (...args) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devrouter/cli",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "description": "Local dev routing CLI with shared Traefik reverse proxy",
5
5
  "author": "Roland Schlaefli",
6
6
  "homepage": "https://github.com/rschlaefli/devrouter#readme",
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "commander": "^12.1.0",
27
- "dockerode": "^4.0.9",
27
+ "dockerode": "^5.0.1",
28
28
  "jsonc-parser": "3.3.1",
29
29
  "yaml": "^2.5.1"
30
30
  },
@@ -0,0 +1,29 @@
1
+ # Upgrade to devrouter 0.5.4
2
+
3
+ This patch release fixes false Compose identity drift when provider-generated
4
+ entrypoints or configuration values contain literal dollar signs. Devrouter
5
+ undoes Compose serialization escaping before hashing the resolved configuration,
6
+ without another interpolation pass. There is no configuration schema migration.
7
+
8
+ ## Task
9
+
10
+ Install the published 0.5.4 CLI. Remove any temporary local patch for the Compose
11
+ dollar-escaping fix in PR #146 by replacing it with the published package.
12
+ Bump a consumer's `devrouter.version` only when consumer source changes are
13
+ authorized. No generated configuration or agent artifacts require changes.
14
+ Preserve existing runtime ownership, containers, databases and dependency volumes.
15
+
16
+ ## Validation
17
+
18
+ 1. Run `devrouter -V` from the consumer checkout and confirm 0.5.4.
19
+ 2. Run `devrouter doctor --json` and inspect runtime ownership and readiness.
20
+ 3. Run `devrouter ensure .` with the intended profile and verify that an existing
21
+ app container is retained without a false Compose drift failure.
22
+ 4. Run an existing application smoke test. If stop/resume is tested, confirm
23
+ the same container and volumes are retained. Do not replay destructive
24
+ bootstrap hooks or bypass lifecycle ownership checks to test an upgrade.
25
+
26
+ ## Report
27
+
28
+ Report the installed version, selected runtime, tested profile, container
29
+ retention and functional results, and any remaining limitations.
@@ -0,0 +1,35 @@
1
+ # Upgrade to devrouter 0.5.5
2
+
3
+ This patch release fixes TCP-only and empty host-route generations. Devrouter
4
+ omits empty HTTP router/service maps so Traefik can load the file provider.
5
+ Existing v1 route metadata remains readable; the next route write or refresh
6
+ emits the corrected document. Other metadata/YAML mismatches still fail closed.
7
+ It also updates Dockerode to 5 to remove the UUID 10 dependency affected by
8
+ CVE-2026-41907. The existing Node >=24 requirement remains unchanged. There is
9
+ no configuration schema migration.
10
+
11
+ ## Task
12
+
13
+ Install the published 0.5.5 CLI. Replace any temporary local patch for the
14
+ TCP-only rendering fix in PR #148 with the published package. Bump a consumer's
15
+ `devrouter.version` only when consumer source changes are authorized. No
16
+ generated configuration or agent artifacts require changes. Preserve existing
17
+ runtime ownership, containers, databases and dependency volumes.
18
+
19
+ ## Validation
20
+
21
+ 1. Run `devrouter -V` from the consumer checkout and confirm 0.5.5.
22
+ 2. Run `devrouter doctor --json` and inspect runtime ownership and readiness.
23
+ Verify a fresh installation resolves Dockerode 5 without UUID 10.
24
+ 3. If the repository defines a TCP-only profile, run `devrouter ensure .` with
25
+ that profile. Verify route publication succeeds and the expected TCP router
26
+ is loaded. Test a client connection with the required TLS/SNI settings; for
27
+ PostgreSQL direct TLS, retain ALPN `postgresql`.
28
+ 4. Restore the intended application profile and run an existing application
29
+ smoke test. Confirm the same app container and volumes are retained. Do not
30
+ replay destructive bootstrap hooks or bypass lifecycle ownership checks.
31
+
32
+ ## Report
33
+
34
+ Report the installed version, selected runtime and profiles, TCP/client and
35
+ application results, container/volume retention, and remaining limitations.