import { ContainerRuntimeInfo, RuntimePreference, UserMappingPayload } from "./types.js"; /** * Detect if the Signal K server is itself running inside a container. * Indicators: * - /.dockerenv file (Docker) * - /run/.containerenv file (Podman) * - container env var (some setups) */ export declare function isContainerized(): boolean; /** * Resolve the effective host user (uid/gid) that managed containers * should run as. Source of truth is the Signal K server's own * process — files created inside a container started with `--user * :` (or `--userns=keep-id` on rootless Podman) end up * owned by this same identity on the host, so a chmod sweep is no * longer necessary. * * Returns `null` on platforms where `process.getuid`/`process.getgid` * are undefined (Windows); the upcoming ownership translator must * suppress `--user` flags in that case. */ export declare function probeHostUser(): { uid: number; gid: number; } | null; /** * Test-only override for the host UID/GID resolver. Stubs let unit * tests assert flag emission against deterministic UIDs without * needing a particular runtime user. */ export declare function _setCurrentHostIdsForTesting(fn: (() => { uid: number; gid: number; } | null) | null): void; /** * Apply the plugin-config "disable user-namespace remap" toggle. * Called from `plugin.start()` whenever the config is (re)read. * Defaults to `false` so existing deployments keep the historical * keep-id behaviour verbatim. */ export declare function setDisableUserns(disabled: boolean): void; /** * Read the current "disable user-namespace remap" toggle. Exposed * for tests; consumer code should not need to call this directly. */ export declare function isDisableUserns(): boolean; /** * Shape shared by `ContainerJobConfig.user` and `ContainerConfig.user`. * Inline-typed rather than imported to keep `runtime.ts` free of * `types.ts` imports (it's the lowest layer). */ type UserMappingIntent = { inImageUid?: number; inImageGid?: number; } | false | undefined; /** * Build the UID-mapping flags to pass to the runtime for one * container. Used by both `runJob` (one-shot helpers) and * `buildRunArgs` (long-running managed containers) so the decision * matrix is identical across both code paths. * * The decision matrix: * * - `user === false` → no flag. Caller opted out (debugging, or the * container doesn't write to a host-owned bind mount). * - host UID resolver returns null (Windows) → no flag. Docker * Desktop / Windows handles UID translation internally. * - rootless Podman with `disableUserNamespaceRemap` active → no * flag. Used on hosts whose backing filesystem refuses kernel * idmapped mounts (ZFS being the canonical case). Container runs * in the default rootless userns; for root-by-default images * (`inImageUid === 0`) bind-mount file ownership still lands on * the host caller. Non-root in-image images give up host-caller * ownership in exchange for being able to start at all. * - rootless Podman → `HostConfig.UsernsMode = "keep-id:uid=,gid="`. * Rewrites the in-image UID back to the host caller via the user- * namespace mapping. (keep-id is meaningless under rootful Podman — * there is no user namespace to map into, so podman silently no-ops * it and the container runs as in-image root with host files owned * by root; we therefore use `User` on the rootful branches to get * caller ownership.) * - Docker / rootful Podman, caller declared a `user` object → * `User = ":"`. Direct process-UID override * so the in-container process matches the image's USER directive. * No namespace remap is available on this branch, so bind-mounted * host files keep their host-side ownership and must be readable * by the in-image UID for the in-container process to use them. * Callers needing to deliver host-owned secrets to a non-root * in-image UID should pass them via `env` instead of bind mounts. * - Docker / rootful Podman, caller omitted `user` → * `User = ":"`. Sets the in-container process UID * to the host caller's UID so files created on bind mounts land * owned by the same identity on the host. Implicit assumption is * that the image's USER directive is root (or absent). * * `inImageUID/GID` defaults to 0 when the caller doesn't pass them — * matching the historical behaviour of helper images shipped before * this field existed (osgeo/gdal, the legacy tippecanoe image, …). * Images with a non-root `USER` directive (e.g. `charts-toolbox`'s * `USER toolbox` at UID 1001, mayara's `USER mayara` at UID 1000) need * the caller to declare the right value. */ export declare function userMappingFlags(runtime: ContainerRuntimeInfo, user: UserMappingIntent, resolveHost?: () => { uid: number; gid: number; } | null): UserMappingPayload; /** * Resolve the container runtime by finding a socket that answers the * Docker API and reading its `version()`/`info()`. Replaces the old * binary-probe (`podman --version` / `docker --version`) detection. * * The `ContainerRuntimeInfo` shape is preserved so every consumer and * the diff logic are untouched; only the SOURCE of each field changes * from CLI-template parsing to JSON field access. `preference` biases the * socket pick order so `PluginConfig.runtime = "docker" | "podman"` is * honoured on a host where both endpoints are reachable; an explicit * endpoint via `DOCKER_HOST`/`CONTAINER_HOST` always wins (see * `client.ts`). */ export declare function detectRuntime(preference: RuntimePreference): Promise; /** * Buffered line splitter for stdout/stderr chunks. Returns a function * that takes raw chunk strings and emits complete lines, holding partial * data across calls so a line split across two `data` events is not * truncated. Treats `\r\n`, bare `\n`, and bare `\r` as line terminators * — tools like tippecanoe repaint a progress line in place using bare * `\r`, and a naive `split("\n")` would silently swallow every update * after the first. Empty lines are dropped. Call the returned `flush` * helper after the stream ends to emit any trailing partial data. */ export declare function makeLineSplitter(emit: (line: string) => void): { push: (chunk: string) => void; flush: () => void; }; /** * Handle returned by `tailContainerLogs`. The caller MUST call `stop()` * when done — a follow-mode log stream does not end on its own. */ export interface StreamingProcessHandle { /** Stop the stream by destroying the underlying Readable; idempotent. */ stop(): void; /** Always `undefined` for the dockerode log stream (a socket stream has * no process). Retained on the interface for debug logging only. */ pid: number | undefined; /** True when the stream could not be established (e.g. the logs API * call rejected). The log-stream broker checks THIS rather than * `pid === undefined` to decide a tail failed, since dockerode * streams never carry a pid. */ spawnFailed?: boolean; } export {}; //# sourceMappingURL=runtime.d.ts.map