@norskvideo/ctl-sdk 0.1.47 → 0.1.49

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@norskvideo/ctl-sdk",
3
- "version": "0.1.47",
3
+ "version": "0.1.49",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -44,7 +44,7 @@
44
44
  "main": "./index.js",
45
45
  "types": "./index.d.ts",
46
46
  "dependencies": {
47
- "@norskvideo/ctl-foundation": "^0.1.0",
47
+ "@norskvideo/ctl-foundation": "^0.1.20",
48
48
  "@norskvideo/ctl-product-template-schema": "^0.1.20",
49
49
  "express": "5",
50
50
  "lucide-react": "^0.483.0",
@@ -5,5 +5,7 @@ export type ProductReach = "host" | "container-address";
5
5
  export declare function parseContainerIdFromCgroup(text: string): string | null;
6
6
  export declare function detectProductReach(opts: {
7
7
  cgroup?: () => string;
8
+ /** Whether /.dockerenv exists; injectable so a test does not read the host it runs on. */
9
+ dockerenv?: () => boolean;
8
10
  env?: Record<string, string | undefined>;
9
11
  }): ProductReach;
package/product-reach.js CHANGED
@@ -5,11 +5,21 @@
5
5
  // host, not to the daemon, and every registration times out at readiness. The
6
6
  // container's own bridge address on the internal port is what such a daemon
7
7
  // can dial, so a containerised daemon uses that and remembers it on the
8
- // registration (`reachHost`). Detection reads the daemon's own cgroup, the
9
- // same tell the test harness uses; NORSK_CTL_PRODUCT_REACH overrides it.
10
- import { readFileSync } from "node:fs";
8
+ // registration (`reachHost`). Detection reads the daemon's own cgroup, then
9
+ // /.dockerenv; NORSK_CTL_PRODUCT_REACH overrides both.
10
+ //
11
+ // The cgroup alone is not enough. Under a cgroup NAMESPACE (docker's default on
12
+ // cgroup v2) a container sees `0::/` and no id, so it reads as a bare host from
13
+ // inside a container. That sent funke's image-mode demo check on an arm DooD
14
+ // runner to 127.0.0.1:<host port> on 2026-10-04, which never answers. The test
15
+ // harness fixed the same false negative in its own resolveContainerId; this is
16
+ // the daemon's copy of that fix. /.dockerenv is written by the docker daemon
17
+ // into every container it creates, and answers the question asked here: is
18
+ // THIS process containerised.
19
+ import { existsSync, readFileSync } from "node:fs";
11
20
  const CGROUP_PATH = "/proc/self/cgroup";
12
21
  const REACH_ENV = "NORSK_CTL_PRODUCT_REACH";
22
+ const DOCKERENV_PATH = "/.dockerenv";
13
23
  /** The 64-hex docker container id from a /proc/self/cgroup dump, or null on a
14
24
  * bare host. Present in both cgroup v1 (`/docker/<id>`) and v2
15
25
  * (`docker-<id>.scope`) layouts. */
@@ -23,10 +33,13 @@ export function detectProductReach(opts) {
23
33
  if (forced === "host" || forced === "container-address")
24
34
  return forced;
25
35
  const read = opts.cgroup ?? (() => readFileSync(CGROUP_PATH, "utf-8"));
36
+ const dockerenv = opts.dockerenv ?? (() => existsSync(DOCKERENV_PATH));
26
37
  try {
27
- return parseContainerIdFromCgroup(read()) ? "container-address" : "host";
38
+ if (parseContainerIdFromCgroup(read()))
39
+ return "container-address";
28
40
  }
29
41
  catch {
30
- return "host";
42
+ // No /proc: fall through to the marker file.
31
43
  }
44
+ return dockerenv() ? "container-address" : "host";
32
45
  }