signalk-container 1.30.0 → 1.32.0

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.
Files changed (37) hide show
  1. package/AGENTS.md +22 -0
  2. package/README.md +51 -24
  3. package/dist/client.d.ts +24 -3
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/client.js +78 -4
  6. package/dist/client.js.map +1 -1
  7. package/dist/containers.d.ts +119 -16
  8. package/dist/containers.d.ts.map +1 -1
  9. package/dist/containers.js +308 -37
  10. package/dist/containers.js.map +1 -1
  11. package/dist/devices.d.ts +55 -3
  12. package/dist/devices.d.ts.map +1 -1
  13. package/dist/devices.js +100 -15
  14. package/dist/devices.js.map +1 -1
  15. package/dist/index.d.ts +19 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +76 -7
  18. package/dist/index.js.map +1 -1
  19. package/dist/namespace.d.ts +9 -0
  20. package/dist/namespace.d.ts.map +1 -1
  21. package/dist/namespace.js +11 -0
  22. package/dist/namespace.js.map +1 -1
  23. package/dist/runtime.d.ts +1 -13
  24. package/dist/runtime.d.ts.map +1 -1
  25. package/dist/runtime.js +38 -2
  26. package/dist/runtime.js.map +1 -1
  27. package/dist/types.d.ts +116 -23
  28. package/dist/types.d.ts.map +1 -1
  29. package/doc/plugin-developer-guide.md +99 -28
  30. package/doc/run-in-container.md +12 -4
  31. package/package.json +5 -4
  32. package/public/chunks/_virtual_mf-localSharedImportMap___mfe_internal__signalk_container__mf_owner__1-COEdWfIZ.js +1 -0
  33. package/public/chunks/dist-S2EeZB5F.js +4 -0
  34. package/public/chunks/{hostInit-B9SMrbCX.js → hostInit-D-1ZoiV2.js} +1 -1
  35. package/public/remoteEntry.js +1 -1
  36. package/public/chunks/_virtual_mf-localSharedImportMap___mfe_internal__signalk_container__mf_owner__1-CfjL8DWB.js +0 -1
  37. package/public/chunks/dist-CMZwYQxm.js +0 -4
package/AGENTS.md CHANGED
@@ -42,6 +42,14 @@ Do not add error handling, fallbacks, or validation for scenarios that cannot ha
42
42
  - `npm test` — unit only (`dist/test/*.test.js`, no recursion). Safe to run anywhere.
43
43
  - `npm run test:integration` — integration only (`dist/test/integration/*.test.js`). Requires podman or docker; tests still self-skip on Windows and when no runtime is found.
44
44
  - `npm run test:all` — both. The pre-PR full sweep on a dev box.
45
+ - **Known Windows CI flake.** `node --test` intermittently marks a whole test
46
+ file failed with a bare `'test failed'` at `:1:1` while every assertion
47
+ inside it passed — the file's child process exits non-zero after its work
48
+ completes. It is not tied to any particular file or to the change under
49
+ test, and `--test-concurrency=1` does not prevent it. Diagnose it by
50
+ checking whether the reported file's own tests all show ✔; if they do,
51
+ re-run the job. `npm test` writes `test-results/junit.xml`, which plugin-CI
52
+ uploads as an artifact — attach that to any upstream report.
45
53
  - All new code requires tests. Test behavior at the function boundary, not internal control flow.
46
54
  - Inject `client: ContainerClient = getClient()` rather than calling dockerode directly. Tests stub via `makeMockClient(spec)` from `src/test/helpers/mockClient.ts`. See `src/test/getLiveResources.test.ts` for the canonical pattern: a mock whose `getContainer().inspect()` returns the JSON object under test, no real podman/docker invocations.
47
55
  - Container-integration tests (those that actually pull `alpine:3.19`) live under `src/test/integration/` and gate on `hasContainerRuntime()` which returns `null` on Windows. Do not add new tests that pull real Linux images without putting them under `src/test/integration/` AND gating on the helper.
@@ -130,6 +138,20 @@ See `src/client.ts`, `src/containers.ts`, `src/log-stream-broker.ts`, and the te
130
138
 
131
139
  `qualifyImage("foo/bar:tag", podmanRuntime)` prefixes `docker.io/` when needed (podman requires fully qualified names unless `unqualified-search-registries` is set; this holds over the API too). Docker passes through. Use this everywhere we feed an image string to a dockerode call.
132
140
 
141
+ ### The compat endpoint silently drops what the CLI honours
142
+
143
+ Everything except `/libpod/info` goes through Podman's **Docker-compat** API via dockerode. That endpoint accepts several fields the CLI supports, returns 201, and then ignores them. Three are known and each cost real debugging time:
144
+
145
+ | Field | CLI | Compat endpoint |
146
+ | -------------------------------- | ------------------------ | --------------------------------------------------------------------------------- |
147
+ | `HostConfig.Ulimits` (nofile) | honoured | dropped below podman 5.5.0 (containers/podman#25881) |
148
+ | `HostConfig.UsernsMode` | honoured | accepted, stored as `private` |
149
+ | `Mounts[].VolumeOptions.Subpath` | `--mount subpath=` works | accepted, ignored (measured on 5.4.2; Docker Engine honours it — 29.7.2/API 1.55) |
150
+
151
+ The lesson is procedural: **a runtime's changelog or man page describes its CLI, not this endpoint.** "Podman 5.4 supports volume subpaths" is true and irrelevant — the plugin cannot use it. Before writing a capability claim into a comment, an error message, or the docs, measure it through dockerode against the socket. `src/test/integration/` is where such a probe belongs.
152
+
153
+ This also means an operator-facing error must name the mechanism precisely. Telling someone "named volumes cannot be subpath-mounted" sends them to the podman docs, which say otherwise, and they conclude the plugin is broken.
154
+
133
155
  ### Inspect-format diff pattern
134
156
 
135
157
  When we need to read live container state, call `getContainer(name).inspect()` once (through `safeInspect`, which returns `null` on a 404 instead of throwing) and read the JSON fields directly. dockerode returns the same field shapes on podman and docker (verified live: `HostConfig.NanoCpus`, `HostConfig.Memory`, `NetworkSettings.Ports`, `Mounts[].{Type,Source,Destination}`, `Config.{Image,Cmd,Env,Healthcheck}`, etc.), so there's no Go-template parsing and no podman-vs-docker text divergence to guard against. `getLiveResources` and `getLiveContainerConfig` are the canonical examples. `diffContainerConfig` is a pure function over those inspect-derived values — keep new live-state probes reading inspect JSON directly so the diff stays uniform across runtimes.
package/README.md CHANGED
@@ -18,7 +18,7 @@ Instead of each plugin implementing its own container orchestration, they delega
18
18
  - **CPU caps that fit the host** -- a `cpus` limit above the daemon's core count is lowered to it instead of failing the container create (Docker rejects `--cpus 1.5` on a 1-vCPU host outright); the consumer plugin can surface it via the optional `onResourceClamped` callback (otherwise it is a debug-log line). See the [developer guide](doc/plugin-developer-guide.md#resource-limits).
19
19
  - **Per-process ulimits** -- `ContainerConfig.ulimits` pins per-process limits (`nofile`, `nproc`, …) on a container. A containerized process inherits these from the runtime, not the host sysctl, so raising the host `fs.file-max` alone does not lift a database's open-files limit; setting `ulimits` does. A `nofile` request over the host ceiling is clamped (not rejected) so the container still starts. See the [developer guide](doc/plugin-developer-guide.md#per-process-ulimits-nofile-) and, for raising the host limit, [Raising the open-files limit](#raising-the-open-files-limit-nofile).
20
20
  - **Image management** -- scheduled pruning of dangling images (weekly/monthly), plus optional cleanup of superseded versions of managed-container images
21
- - **Zero-config data dir sharing** -- `signalkDataMount` mounts the SignalK data directory into any managed container automatically, whether Signal K runs bare-metal, in Docker (named volume), or in Podman (named volume or bind mount). No host paths to configure.
21
+ - **Zero-config persistent storage** -- `signalkDataMount` mounts signalk-container's own data directory into any managed container automatically, whether Signal K runs on bare metal, in Docker (named volume), or in Podman (named volume or bind mount). No host paths to configure; namespace a subdirectory, since every managed container shares it.
22
22
  - **Zero-config config root sharing** -- `signalkConfigRootMount` mounts the entire SignalK installation config (`~/.signalk/`) — for backup, audit, or config-sync tools that need the whole tree, not the per-plugin subdirectory.
23
23
  - **Zero-config container service connectivity** -- `signalkAccessiblePorts` lets the SignalK process connect back to a service running inside a managed container (e.g. an HTTP or TCP server). signalk-container picks the right networking strategy automatically — port binding on the host loopback for bare-metal deployments, or a shared Docker network with DNS for containerised ones. No host ports are exposed unnecessarily.
24
24
  - **Host timezone propagation** -- managed containers and one-shot jobs get `TZ=<host zone>` injected automatically, so time-based logic inside them (cron-style Node-RED flows, Grafana/QuestDB time rendering, log timestamps) agrees with the host clock instead of defaulting to UTC. Consumer plugins that set `env.TZ` themselves keep full control; shell-level tools inside minimal images may additionally need the image's `tzdata` package to interpret the zone name. See the [developer guide](doc/plugin-developer-guide.md#host-timezone).
@@ -644,9 +644,28 @@ The plugin developer guide has a detailed walk-through in [doc/plugin-developer-
644
644
  > appears to be ignored, the host's cgroup controller delegation is
645
645
  > almost certainly the cause — see [Cgroup controller delegation](#cgroup-controller-delegation) above.
646
646
 
647
- ## Mounting the SignalK data directory (`signalkDataMount`)
647
+ ## Persistent storage for managed containers (`signalkDataMount`)
648
648
 
649
- When a managed container needs to read or write files that Signal K also accesses (e.g. HLS segments, exports, caches), use `signalkDataMount` instead of computing and hardcoding a host path or volume name.
649
+ When a managed container needs somewhere durable to read and write (e.g. HLS segments, exports, caches), use `signalkDataMount` instead of computing and hardcoding a host path or volume name.
650
+
651
+ It mounts **signalk-container's own plugin data directory** —
652
+ `<configRoot>/plugin-config-data/signalk-container/`. Signal K rewrites
653
+ `getDataDirPath()` per plugin and this resolves it against signalk-container's
654
+ app, so the source is the same for every managed container whichever plugin
655
+ asked — never the caller's own directory, since a cross-plugin API reached
656
+ through `globalThis` never learns who called it.
657
+
658
+ The container never sees more than that directory. A bind mount is narrowed
659
+ to the exact host path; a **named volume** is accepted only when it is
660
+ attached to the directory itself, because signalk-container mounts a volume
661
+ whole, and one covering a parent would expose that volume's entire contents —
662
+ sibling plugins' data, or the whole SignalK config tree when the volume sits
663
+ on the config root. That case fails with an error rather than over-sharing —
664
+ see the note below.
665
+
666
+ **Namespace a subdirectory** (as the example below does) so two consumers
667
+ cannot collide. For the SignalK config root see `signalkConfigRootMount`; to
668
+ mount your own plugin's data dir, translate it with `resolveHostPath`.
650
669
 
651
670
  ```typescript
652
671
  const SK_MOUNT = "/signalk-data";
@@ -654,7 +673,7 @@ const SK_MOUNT = "/signalk-data";
654
673
  await containers.ensureRunning("my-worker", {
655
674
  image: "myorg/myworker",
656
675
  tag: "latest",
657
- signalkDataMount: SK_MOUNT, // ← mount the SignalK data dir here
676
+ signalkDataMount: SK_MOUNT, // ← shared managed-container storage
658
677
  command: ["--output", path.join(SK_MOUNT, "my-plugin/output/result.bin")],
659
678
  });
660
679
  ```
@@ -668,22 +687,30 @@ signalk-container resolves the correct source automatically:
668
687
  | Docker, bind-backed data dir | the exact host path, even when a parent directory is bind-mounted |
669
688
  | Podman (rootless or root) | same logic; named volumes receive no `:Z` flag |
670
689
 
671
- The content at `SK_MOUNT` inside the managed container always corresponds to the root of `app.getDataDirPath()`. Build paths using `path.join`:
690
+ On bare metal or a bind mount, `SK_MOUNT` corresponds to the root of the
691
+ resolved directory, so paths compose with `path.join`:
672
692
 
673
693
  ```typescript
674
- // Path inside managed container that corresponds to an absolute SignalK path:
675
- const containerPath = path.join(
676
- SK_MOUNT,
677
- path.relative(app.getDataDirPath(), absSignalkPath),
678
- );
694
+ // Path inside the managed container, for a path under the resolved dir:
695
+ const containerPath = path.join(SK_MOUNT, "my-plugin", "output", "result.bin");
679
696
  ```
680
697
 
698
+ A **named volume** backing the directory works the same way, since it is
699
+ only accepted when attached to that directory. Call
700
+ `containers.resolveSignalkDataMount()` if you need the resolved source (a
701
+ host path or a volume name) at runtime.
702
+
681
703
  > [!note]
682
- > Docker/Podman do not support subpath mounts on named volumes. If your data directory
683
- > is backed by a named volume, the entire volume is mounted at `SK_MOUNT`. Avoid writing
684
- > to paths inside `SK_MOUNT` that are also bind-mounted in the Signal K container (e.g.
685
- > a plugin's own directory if mounted with `./:/home/node/.signalk/node_modules/my-plugin`)
686
- > those paths are not visible from inside the managed container.
704
+ > signalk-container mounts a named volume whole: it sends no subpath, and podman's
705
+ > Docker-compat endpoint ignores one anyway (measured on 5.4.2 Docker Engine would
706
+ > honour it, so narrowing cannot work uniformly). A volume attached to the
707
+ > resolved directory is mounted whole, which is exactly that directory fine. A volume
708
+ > attached to a **parent** (the SignalK config root, say) would expose far more than was
709
+ > asked for, so `ensureRunning` rejects it with an error naming the volume and the fix:
710
+ > attach the volume to the data directory, or use `resolveHostPath()` and handle the
711
+ > returned `subPath` deliberately. Also avoid writing to paths inside `SK_MOUNT` that are
712
+ > separately bind-mounted in the Signal K container — those are not visible from inside
713
+ > the managed container.
687
714
 
688
715
  You can also call `containers.resolveSignalkDataMount()` if you need to inspect the resolved source at runtime (e.g. for logging).
689
716
 
@@ -712,7 +739,7 @@ The deployment-mode resolution is identical to `signalkDataMount`: bare-metal re
712
739
  `app.config.configPath` is provided by the SignalK server runtime. If the caller's `app` object lacks it (a non-standard host), `ensureRunning()` throws.
713
740
 
714
741
  > [!note]
715
- > The same named-volume subpath caveat applies — Docker doesn't support subpath mounts on volumes. If `app.config.configPath` happens to live under a parent-directory bind, signalk-container computes the exact host path so the container sees the right tree.
742
+ > The same named-volume caveat applies — the volume is mounted whole. If `app.config.configPath` happens to live under a parent-directory bind, signalk-container computes the exact host path so the container sees the right tree.
716
743
 
717
744
  ### When SignalK runs in a container: self-container detection
718
745
 
@@ -902,7 +929,7 @@ See [doc/plugin-developer-guide.md](doc/plugin-developer-guide.md) for the full
902
929
  | `updateResources(name, limits)` | Apply new resource limits live, fall back to recreate |
903
930
  | `getResources(name)` | Currently effective limits (plugin defaults ⊕ user override) |
904
931
  | `resolveSignalkDataMount()` | Resolve the volume name or host path that backs `app.getDataDirPath()` in the current deployment; returns `null` if the runtime is not yet initialised |
905
- | `probeHostDevice(path)` | Ask whether a device path exists **on the host** and which groups own its nodes — a plugin cannot `stat()` this itself once SignalK is containerized. Returns `null` for "unknown", which is not the same as `{exists:false}`. 1.30.0+ |
932
+ | `probeHostDevice(path)` | Ask whether a device path exists **on the host** and which groups own its nodes — a plugin cannot `stat()` this itself once SignalK is containerized. Returns `null` for "unknown", which is not the same as `{exists:false}`. 1.30.0+ |
906
933
  | `resolveHostPath(absPath)` | Translate an arbitrary absolute path into the `{ source, subPath }` pair the runtime needs to mount it; handles bare-metal, bind, and named-volume topologies |
907
934
  | `resolveContainerAddress(name, port)` | Return the `host:port` string to reach `port` on a managed container from the SignalK process; call after `ensureRunning()` with `signalkAccessiblePorts` set |
908
935
  | `doctor.imageRunsAsUser(image, user?)` | Probe whether `image` runs cleanly under the host-UID mapping signalk-container will emit (1.8.0+). Never throws — returns `{ ok, output, error? }` |
@@ -955,10 +982,10 @@ All mounted at `/plugins/signalk-container/api/`:
955
982
  device you might pass through — from a plugin that cannot see the host:
956
983
 
957
984
  ```js
958
- const gpu = await containers.probeHostDevice?.('/dev/dri')
985
+ const gpu = await containers.probeHostDevice?.("/dev/dri");
959
986
  if (gpu?.exists) {
960
- config.devices = ['/dev/dri']
961
- config.groupAdd = gpu.groups // names, resolved per host
987
+ config.devices = ["/dev/dri"];
988
+ config.groupAdd = gpu.groups; // names, resolved per host
962
989
  }
963
990
  ```
964
991
 
@@ -973,10 +1000,10 @@ number loses access on someone else's machine.
973
1000
 
974
1001
  Three results, and the difference matters:
975
1002
 
976
- | Result | Meaning |
977
- | ------------------------------- | ------------------------------------------------------ |
978
- | `{exists: true, nodes, groups}` | Device is there; pass `groups` to `groupAdd` |
979
- | `{exists: false, …}` | Definitely absent |
1003
+ | Result | Meaning |
1004
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
1005
+ | `{exists: true, nodes, groups}` | Device is there; pass `groups` to `groupAdd` |
1006
+ | `{exists: false, …}` | Definitely absent |
980
1007
  | `null` | **Unknown** — no runtime, the path could not be read (a permission error, say), or the nodes are there but their owning group could not be determined |
981
1008
 
982
1009
  Treat `null` as "assume no device, but do not report it as absent".
package/dist/client.d.ts CHANGED
@@ -62,15 +62,36 @@ export interface LibpodNetworkBackendInfo {
62
62
  path?: string;
63
63
  };
64
64
  }
65
+ /** One `container_id`/`host_id`/`size` triple from podman's `/info`. */
66
+ export interface LibpodIdMapEntry {
67
+ container_id?: number;
68
+ host_id?: number;
69
+ size?: number;
70
+ }
65
71
  /**
66
72
  * Podman's native `/libpod/info` — the docker-compat `/info` the rest of the
67
73
  * plugin uses does NOT expose `networkBackendInfo`, so host-side network
68
74
  * facts (which DNS helper netavark resolved, if any) are only visible here.
69
- * The version prefix is required (unversioned libpod paths 404); Podman
70
- * accepts any client version for this endpoint. Returns `null` on Docker,
71
- * on any request failure, and when the modem can't dial (test mocks).
75
+ * Returns `null` on Docker, on any request failure, and when the modem
76
+ * can't dial (test mocks).
72
77
  */
73
78
  export declare function libpodNetworkBackendInfo(client: ContainerClient): Promise<LibpodNetworkBackendInfo | null>;
79
+ /**
80
+ * Subordinate ID range podman has for the calling user, from its own
81
+ * `/info` — the sum of every mapping entry beyond the identity one.
82
+ *
83
+ * `--userns=keep-id:uid=N` asks for a 65536-wide subordinate block. Where
84
+ * the account's `/etc/subuid` allocation is narrower, podman clamps the
85
+ * length, and at the limit clamps it to zero — which the kernel rejects
86
+ * with `writing file /proc/<pid>/gid_map: Invalid argument`. Reading the
87
+ * real width lets the caller bound the request to what exists.
88
+ *
89
+ * Asked of podman rather than read from `/etc/subuid` because the plugin
90
+ * usually runs inside a container, where that file is absent while the
91
+ * socket still answers. Returns `null` on Docker, on any failure, and when
92
+ * the modem cannot dial.
93
+ */
94
+ export declare function libpodSubordinateUidCount(client: Pick<ContainerClient, "modem">): Promise<number | null>;
74
95
  /** Runtime the caller prefers when more than one socket is reachable. */
75
96
  export type SocketPreference = "auto" | "podman" | "docker";
76
97
  export interface ResolvedClient {
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js CHANGED
@@ -19,13 +19,18 @@ import Docker from "dockerode";
19
19
  import { stat } from "node:fs/promises";
20
20
  import { PassThrough } from "node:stream";
21
21
  import { categorizeError, messageWithRaw, } from "./errors.js";
22
+ /**
23
+ * Podman's native info endpoint. The version prefix is required —
24
+ * unversioned libpod paths 404 — and podman accepts any client version
25
+ * here. Shared by both probes so the two cannot drift apart.
26
+ */
27
+ const LIBPOD_INFO_PATH = "/v4.0.0/libpod/info";
22
28
  /**
23
29
  * Podman's native `/libpod/info` — the docker-compat `/info` the rest of the
24
30
  * plugin uses does NOT expose `networkBackendInfo`, so host-side network
25
31
  * facts (which DNS helper netavark resolved, if any) are only visible here.
26
- * The version prefix is required (unversioned libpod paths 404); Podman
27
- * accepts any client version for this endpoint. Returns `null` on Docker,
28
- * on any request failure, and when the modem can't dial (test mocks).
32
+ * Returns `null` on Docker, on any request failure, and when the modem
33
+ * can't dial (test mocks).
29
34
  */
30
35
  export function libpodNetworkBackendInfo(client) {
31
36
  return new Promise((resolve) => {
@@ -36,7 +41,7 @@ export function libpodNetworkBackendInfo(client) {
36
41
  }
37
42
  try {
38
43
  dial({
39
- path: "/v4.0.0/libpod/info",
44
+ path: LIBPOD_INFO_PATH,
40
45
  method: "GET",
41
46
  statusCodes: { 200: true, 500: "server error" },
42
47
  }, (err, data) => {
@@ -55,6 +60,75 @@ export function libpodNetworkBackendInfo(client) {
55
60
  }
56
61
  });
57
62
  }
63
+ /**
64
+ * Total width of the subordinate entries in one mapping table, or `null`
65
+ * when the table is absent or contributes nothing usable.
66
+ *
67
+ * The identity entry maps the caller's own id and is not part of the
68
+ * subordinate block. Sizes must be positive safe integers: podman parses
69
+ * `size` as a uint and rejects `size=1.5` outright, and a negative would
70
+ * shrink the total below what the account actually has.
71
+ */
72
+ function subordinateWidth(map) {
73
+ if (!Array.isArray(map))
74
+ return null;
75
+ const total = map
76
+ .filter((e) => (e?.container_id ?? 0) !== 0)
77
+ .reduce((n, e) => {
78
+ const size = e?.size;
79
+ return typeof size === "number" && Number.isSafeInteger(size) && size > 0
80
+ ? n + size
81
+ : n;
82
+ }, 0);
83
+ return total > 0 ? total : null;
84
+ }
85
+ /**
86
+ * Subordinate ID range podman has for the calling user, from its own
87
+ * `/info` — the sum of every mapping entry beyond the identity one.
88
+ *
89
+ * `--userns=keep-id:uid=N` asks for a 65536-wide subordinate block. Where
90
+ * the account's `/etc/subuid` allocation is narrower, podman clamps the
91
+ * length, and at the limit clamps it to zero — which the kernel rejects
92
+ * with `writing file /proc/<pid>/gid_map: Invalid argument`. Reading the
93
+ * real width lets the caller bound the request to what exists.
94
+ *
95
+ * Asked of podman rather than read from `/etc/subuid` because the plugin
96
+ * usually runs inside a container, where that file is absent while the
97
+ * socket still answers. Returns `null` on Docker, on any failure, and when
98
+ * the modem cannot dial.
99
+ */
100
+ export function libpodSubordinateUidCount(client) {
101
+ return new Promise((resolve) => {
102
+ const dial = client.modem.dial?.bind(client.modem);
103
+ if (!dial) {
104
+ resolve(null);
105
+ return;
106
+ }
107
+ try {
108
+ dial({
109
+ path: LIBPOD_INFO_PATH,
110
+ method: "GET",
111
+ statusCodes: { 200: true, 500: "server error" },
112
+ }, (err, data) => {
113
+ if (err || typeof data !== "object" || data === null) {
114
+ resolve(null);
115
+ return;
116
+ }
117
+ const maps = data.host?.idMappings;
118
+ const uid = subordinateWidth(maps?.uidmap);
119
+ const gid = subordinateWidth(maps?.gidmap);
120
+ // One `size` governs both the uid and gid mappings, so the usable
121
+ // width is the smaller of the two — asking for the uid width when
122
+ // fewer gids exist reproduces the very failure this bounds.
123
+ // Unknown on either side means no safe bound at all.
124
+ resolve(uid === null || gid === null ? null : Math.min(uid, gid));
125
+ });
126
+ }
127
+ catch {
128
+ resolve(null);
129
+ }
130
+ });
131
+ }
58
132
  /**
59
133
  * Socket candidates, in priority order, plus whether the operator pinned an
60
134
  * explicit endpoint. When `DOCKER_HOST`/`CONTAINER_HOST` is set we honour ONLY
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type Docker from "dockerode";
2
- import { ContainerConfig, ContainerInfo, ContainerRuntimeInfo, ContainerState, DeviceIssue, EnsureRunningOptions, LocalImageSummary, ManagedImageRef, NofileLimits, PruneResult, ContainerWedged, ResourceClamp, UlimitClamp, VolumeIssue, VolumeSpec } from "./types.js";
2
+ import { ContainerConfig, ContainerInfo, ContainerRuntimeInfo, ContainerState, DeviceIssue, EnsureRunningOptions, LocalImageSummary, ManagedImageRef, NofileLimits, PruneResult, ContainerStateDetail, RequestedConfigProvenance, ContainerWedged, ResourceClamp, UlimitClamp, VolumeIssue, VolumeSpec } from "./types.js";
3
3
  import { StreamingProcessHandle } from "./runtime.js";
4
4
  import { type ContainerClient } from "./client.js";
5
5
  import { type ErrorKind } from "./errors.js";
@@ -84,7 +84,17 @@ export declare function resolveHostTimezone(systemZone?: () => string): string |
84
84
  * `defaultHomeForConfigRoot`.
85
85
  */
86
86
  export declare function defaultTimezoneEnv(env: Record<string, string> | undefined, zone: string | undefined): Record<string, string> | undefined;
87
- export declare function classifyVolumeSources(volumes: Record<string, string | VolumeSpec> | undefined, probe?: (path: string) => boolean): {
87
+ /**
88
+ * What a host-source probe could establish about a path.
89
+ *
90
+ * `"unknown"` is NOT a synonym for absent. When the manager runs inside a
91
+ * container its filesystem is not the one the runtime resolves bind sources
92
+ * against, so `existsSync` on a host path answers a different question than
93
+ * the one asked. Reporting that as absent drops a volume whose source is
94
+ * perfectly real — the bug this type exists to prevent.
95
+ */
96
+ export type VolumeSourceState = boolean | "unknown";
97
+ export declare function classifyVolumeSources(volumes: Record<string, string | VolumeSpec> | undefined, probe?: (path: string) => VolumeSourceState): {
88
98
  kept: Record<string, string>;
89
99
  skipped: Array<{
90
100
  containerPath: string;
@@ -94,6 +104,11 @@ export declare function classifyVolumeSources(volumes: Record<string, string | V
94
104
  containerPath: string;
95
105
  source: string;
96
106
  }>;
107
+ /** Host paths whose existence could not be established. Kept, not dropped. */
108
+ unverified: Array<{
109
+ containerPath: string;
110
+ source: string;
111
+ }>;
97
112
  };
98
113
  /**
99
114
  * Given the volume issues from the last `ensureRunning` call (both
@@ -325,6 +340,19 @@ export declare function getLiveContainerDigest(runtime: ContainerRuntimeInfo, co
325
340
  */
326
341
  export declare function pullImage(runtime: ContainerRuntimeInfo, image: string, onProgress?: (msg: string) => void, client?: ContainerClient): Promise<void>;
327
342
  export declare function getContainerState(runtime: ContainerRuntimeInfo, name: string, client?: ContainerClient): Promise<ContainerState>;
343
+ /**
344
+ * Coarse state plus the detail that explains it — exit code, OOM kill,
345
+ * restart count and the container's own healthcheck verdict.
346
+ *
347
+ * `getContainerState` answers "can I talk to it"; this answers "why is
348
+ * it like that". Both read the same `State` block from one inspect, and
349
+ * share `coarseStateFrom` so the two can never disagree about running.
350
+ *
351
+ * Returns `state: "missing"` with no detail when the container is gone.
352
+ * Individual fields stay undefined when the runtime omits them rather
353
+ * than defaulting to a zero that would read as real data.
354
+ */
355
+ export declare function getContainerStateDetail(name: string, client?: ContainerClient): Promise<ContainerStateDetail>;
328
356
  /**
329
357
  * Upper bound on the `.State.Error` text surfaced to callers. Some OCI
330
358
  * runtime rejections embed multi-kilobyte detail (spec dumps, nested
@@ -377,6 +405,19 @@ export declare function getLiveResources(runtime: ContainerRuntimeInfo, name: st
377
405
  * current-vs-target check minus runtime-injected fields.
378
406
  */
379
407
  export declare function getRequestedResources(name: string, client?: ContainerClient): Promise<import("./types.js").ContainerResourceLimits | undefined>;
408
+ /**
409
+ * Parse the requested-config provenance label written at create time.
410
+ *
411
+ * Returns `undefined` — meaning "no provenance", so the caller keeps
412
+ * today's positive-only drift behaviour — when the label is absent,
413
+ * unparseable, or not an object. It must never return `{}` for a
414
+ * missing label: an empty provenance reads as "the container was
415
+ * created with no env at all", which would mask a genuine unset.
416
+ *
417
+ * Never throws. A hand-edited or truncated label degrades to
418
+ * `undefined` rather than breaking `ensureRunning`.
419
+ */
420
+ export declare function parseRequestedConfigLabel(raw: string | undefined): RequestedConfigProvenance | undefined;
380
421
  /**
381
422
  * One host-side endpoint for a single container port. Mirror of the
382
423
  * `{ HostIp, HostPort }` shape that podman/docker emit under
@@ -503,18 +544,20 @@ export declare function getLiveContainerConfig(runtime: ContainerRuntimeInfo, na
503
544
  * for floating tags (`:latest` digest drift) is the update service's job.
504
545
  * - command: explicit drift when `requested.command` is set and differs
505
546
  * from `live.command`. When `requested.command` is undefined, drift is
506
- * reported only if a `prior.command` was set (i.e. the user is now
507
- * unsetting it). Without a `prior`, an undefined `requested.command`
508
- * can't be told apart from "image's baked CMD" so we skip — the
509
- * wrapper's prior-config cache (`lastConfigs`) closes that loop on the
510
- * second-and-later calls within a single signalk-container lifetime.
547
+ * reported only if a prior `command` was set (i.e. the user is now
548
+ * unsetting it). The prior comes from the wrapper's `lastConfigs`
549
+ * cache when warm, and otherwise from the create-time provenance
550
+ * label; with neither, an undefined `requested.command` can't be
551
+ * told apart from "image's baked CMD" so we skip.
511
552
  * - networkMode: runtime defaults (`bridge`, `slirp4netns`, etc.) are
512
553
  * normalized to `""` and compared as equivalent to requested undefined.
513
554
  * - env: requested keys must match live values. Additionally, any key
514
- * present in `prior.env` but absent from `requested.env` is treated
515
- * as drift (the user is unsetting it). Image-baked env keys not in
516
- * either `requested.env` or `prior.env` are ignored — they were never
517
- * ours.
555
+ * present in the prior env but absent from `requested.env` is treated
556
+ * as drift (the user is unsetting it). Image-baked env keys in neither
557
+ * `requested.env` nor the prior are ignored — they were never ours.
558
+ * The prior is the warm `lastConfigs` entry, falling back to the env
559
+ * KEY NAMES recorded in the create-time provenance label; values are
560
+ * never recorded there because this check reads only key presence.
518
561
  * - volumes: trailing slashes stripped on both sides; `(host, container)`
519
562
  * tuples compared as a Map keyed by container path. Live binds have
520
563
  * their `:Z`/`:ro` flags already stripped by `getLiveContainerConfig`.
@@ -612,8 +655,10 @@ export declare function ensureRunning(runtime: ContainerRuntimeInfo, name: strin
612
655
  * this signalk-container lifetime, if any. Used to detect "unset" drift
613
656
  * — env keys removed, `command` previously set and now undefined. The
614
657
  * wrapper in `index.ts` reads from its `lastConfigs` cache before
615
- * overwriting it; on the first call (or after a Signal K restart) this
616
- * will be undefined and only positive drift is detected.
658
+ * overwriting it. On the first call (or after a Signal K restart) it
659
+ * is undefined and the diff falls back to the requested-config
660
+ * provenance label stamped at create time, so an unset is still
661
+ * detected across a restart.
617
662
  */
618
663
  prior?: ContainerConfig, _postRecreate?: boolean, _pull?: PullFn): Promise<void>;
619
664
  export declare function startContainer(runtime: ContainerRuntimeInfo, name: string, client?: ContainerClient): Promise<void>;
@@ -877,6 +922,24 @@ export declare function readSelfContainerIdsFromMountinfo(): string[];
877
922
  * return null to the caller (depends on the consumer).
878
923
  */
879
924
  export declare function findSelfContainerId(runtime: ContainerRuntimeInfo, debug?: (msg: string) => void, client?: ContainerClient): Promise<string | null>;
925
+ /**
926
+ * Refuse a named volume that covers more than the requested directory.
927
+ *
928
+ * Neither runtime can subpath-mount a volume, so a volume attached to a
929
+ * PARENT of the requested directory would hand the managed container
930
+ * everything in it — for `signalkDataMount`, the whole SignalK config tree
931
+ * with `security.json` in it, when the container asked only for scratch
932
+ * space. Throwing gives the caller a clear failure instead of silent access
933
+ * to files it never requested.
934
+ *
935
+ * A volume attached to the requested directory itself is exactly what was
936
+ * asked for and passes. Callers who genuinely want a parent-backed volume
937
+ * have `resolveHostPath`, which reports `subPath` so the choice is explicit.
938
+ *
939
+ * `field` names the API the consumer actually used, since one resolver
940
+ * serves both `signalkDataMount` and `signalkConfigRootMount`.
941
+ */
942
+ export declare function assertVolumeIsNotBroaderThanRequested(volumeName: string, volumeDest: string, requestedDir: string, field: string): void;
880
943
  /**
881
944
  * Resolve what to mount in a managed container to give it access to
882
945
  * the SignalK data directory, regardless of how SignalK itself is deployed.
@@ -890,10 +953,13 @@ export declare function findSelfContainerId(runtime: ContainerRuntimeInfo, debug
890
953
  * fail gracefully at container-create time with a clear Docker error.
891
954
  *
892
955
  * The result can be used directly as `volumes: { [mountPoint]: source }` in
893
- * a ContainerConfig. The content visible at mountPoint inside the managed
894
- * container will always correspond to the root of dataDir.
956
+ * a ContainerConfig. The content visible at mountPoint corresponds to the
957
+ * root of dataDir: a bind is narrowed to the exact host path, and a named
958
+ * volume is only accepted when it is mounted on dataDir itself. A volume
959
+ * covering a parent throws rather than over-sharing: the plugin sends no
960
+ * subpath, and podman's compat endpoint would ignore one.
895
961
  */
896
- export declare function resolveSignalkDataSource(dataDir: string, runtime: ContainerRuntimeInfo, debug?: (msg: string) => void, client?: ContainerClient): Promise<string>;
962
+ export declare function resolveSignalkDataSource(dataDir: string, runtime: ContainerRuntimeInfo, debug?: (msg: string) => void, client?: ContainerClient, field?: string): Promise<string>;
897
963
  /**
898
964
  * Mount entry as parsed from `podman inspect --format '{{range .Mounts}}...'`.
899
965
  * Exposed so tests can drive `resolveHostPathFromMounts` directly without
@@ -959,6 +1025,43 @@ export interface ContainerMountResolution {
959
1025
  * `resolveSignalkDataSource` does for backwards-compat).
960
1026
  */
961
1027
  export declare function resolveHostPath(absPath: string, runtime: ContainerRuntimeInfo, debug?: (msg: string) => void, client?: ContainerClient): Promise<ContainerMountResolution | null>;
1028
+ /**
1029
+ * Can `existsSync(hostPath)` be trusted inside this container?
1030
+ *
1031
+ * The caller holds a HOST path and stats that same string locally, so the
1032
+ * mount has to make those two the same thing. Three conditions, and all are
1033
+ * load-bearing:
1034
+ *
1035
+ * - **Bind mounts only.** A named volume's contents are not the host
1036
+ * filesystem at that path, so a file seen inside one proves nothing.
1037
+ * - **Path-preserving only** (`source === dest`). A bind of `/host/data` to
1038
+ * `/data` puts the host's `/host/data` at `/data`; the string `/data` inside
1039
+ * the container names `/host/data` on the host, and the host's own `/data`
1040
+ * is not visible at all. Verified against a real runtime. Trusting such a
1041
+ * mount would let `existsSync("/data/certs")` answer about
1042
+ * `/host/data/certs` and report a nonexistent required source as present --
1043
+ * exactly the `ifMissing: "abort"` failure this guards.
1044
+ * - **Exact-or-child.** A mount at `/data` covers `/data` and `/data/sub`,
1045
+ * never `/database`.
1046
+ *
1047
+ * Factored out of `ownBindMountCoverage` so the rule is testable without a
1048
+ * runtime.
1049
+ */
1050
+ export declare function isPathUnderBindMount(absPath: string, mounts: readonly InspectedMount[]): boolean;
1051
+ /**
1052
+ * Host paths this container can see truthfully, as a predicate.
1053
+ *
1054
+ * A bind mount makes this container's view of a path the HOST's view at a
1055
+ * known offset, so `existsSync` under one is authoritative in both directions.
1056
+ * Anywhere else a containerized process is looking at a different filesystem
1057
+ * entirely, and neither answer means anything about the host.
1058
+ *
1059
+ * Returns a predicate rather than resolving one path so the inspect happens
1060
+ * ONCE per reconcile instead of once per volume. On bare metal, or when the
1061
+ * self-inspect fails, every path is covered / not covered respectively — the
1062
+ * caller decides what that means.
1063
+ */
1064
+ export declare function ownBindMountCoverage(runtime: ContainerRuntimeInfo, debug?: (msg: string) => void, client?: ContainerClient): Promise<(absPath: string) => boolean>;
962
1065
  /**
963
1066
  * Release a port that was reserved by `findAvailablePort()`.
964
1067
  * Must be called after the container runtime has successfully bound the port