feat(container): per-user Docker sandbox + mapped per-user filesystem
Realizes blueprint §6: each user gets a permanent Docker container
(skald-{userid}, our own skald-runtime image with python+node) as their
execution sandbox. Docker is now a hard requirement — a missing daemon fails
Skald::new and the process exits at boot.
- ContainerManager (crates/skald-core/src/container/): docker availability
check, builds skald-runtime from the embedded Dockerfile, reconciles one
running container per active user at boot, stops them at shutdown, and
ensure/remove on user create/delete. Shells the docker CLI (no client crate).
- UserFs (core-api): pure value type carried in ToolContext, mapping the agent's
single namespace — ~/ → homes/{userid}, shared/{X}/ → shared/{X} (membership),
user-memory/ + shared-memory/ → SQLite — to host and container paths.
- execute_cmd now runs inside the caller's container via `docker exec`.
- fs-tools resolve every physical path through UserFs to the per-user host
workspace, host-side, with fail-closed symlink/`..` containment
(resolve_host_path: canonicalize + prefix-check). grep_files resolves its root
the same way but stays disk-only.
- shared_folders + shared_folder_members (registry, junction table with
can_write) back the shared-folder membership that drives both the container
mounts and the shared/{X} routing.
- Threading: UserContext.fs → ChatSessionManager → handler → ToolContext.fs.
Per-user MCP servers do not yet run in the container (next round).
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
# Per-user execution sandbox for Skald-Circle (blueprint §6).
|
||||
#
|
||||
# Our own image — not a public one — so we can install exactly what the runtime
|
||||
# needs over time without depending on an external base that could change or go
|
||||
# away. Built once at boot by `ContainerManager::ensure_image` (tag `skald-runtime`).
|
||||
#
|
||||
# Holds python + node so `execute_cmd` (and, later, per-user MCP servers) run
|
||||
# inside the user's container against their bind-mounted home. Kept minimal;
|
||||
# grow it here as needs arise.
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
nodejs \
|
||||
npm \
|
||||
ca-certificates \
|
||||
curl \
|
||||
git \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
# The container is long-lived: created once, started at boot, exec'd into per
|
||||
# command. Nothing runs until `docker exec` drives it.
|
||||
CMD ["sleep", "infinity"]
|
||||
Reference in New Issue
Block a user