diff --git a/.github/workflows/boot-init.yml b/.github/workflows/boot-init.yml index 59631a4ed..9bad16653 100644 --- a/.github/workflows/boot-init.yml +++ b/.github/workflows/boot-init.yml @@ -12,6 +12,7 @@ on: pull_request: paths: - "boot/init/**" + - ".github/workflows/boot-init.yml" workflow_dispatch: permissions: diff --git a/.github/workflows/silkd.yml b/.github/workflows/silkd.yml index 849cff735..30eb602e9 100644 --- a/.github/workflows/silkd.yml +++ b/.github/workflows/silkd.yml @@ -14,6 +14,7 @@ on: paths: - "silkd/**" - "protocol/**" + - ".github/workflows/silkd.yml" workflow_dispatch: permissions: diff --git a/README.md b/README.md index f4048dbac..7843d2057 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,9 @@ performance) — source in `StartLsp`, `Spawn/Ps/Kill/Logs/Attach`; `protocol/wire` carries the frame vocabulary, `sdk/go/silkd` the conn layer, `silkdtest` a test fake - `sdk/python/` — Python SDK (stdlib-only, sync), matching the Go guest and - data-plane surface for the Python-first agent ecosystem; node pool retuning - remains Go-only; round-trips the shared fixture corpus + data-plane surface for the Python-first agent ecosystem; node pool and + tenant administration and the claim env remain Go-only; round-trips the + shared fixture corpus - `mcp/` — `sandbox-mcp`, an MCP stdio server exposing the surface as tools for Claude Code / Cursor / agent frameworks - `sdk/openai/` — `cocoonstack-sandbox-openai`, a custom sandbox provider @@ -62,7 +63,8 @@ performance) — source in `smoke`, `meshsmoke`, `crossnode`, `coldproof`, `egresssmoke`, `interceptsmoke`, `sockssmoke`, `volumesmoke`, `lifecycle` (idle→hibernate→archive), `androidsmoke`, `browsersmoke`, `ringsmoke` (output ring cap, exec as a user), - `portsmoke` (the guest-port relay), `credsmoke` (claim credential injection), + `portsmoke` (the guest-port relay, with `guestserver` as its guest listener), + `credsmoke` (claim credential injection), and the `pullbench`/`pushbench`/`rpcbench`/`qaab` perf drivers - `boot/kernel/` — kernel version pin (`VERSION` + matching tarball `SHA256`, bump both together) + config fragment (amd64: over `x86_64_defconfig` + @@ -78,7 +80,7 @@ performance) — source in e2b-compatible data plane), and `e2b-ci` (e2b-rt plus e2b's code interpreter) - `scripts/` — `boot-bench.sh` (boot phase timing), `bench.sh` (the published benchmark procedure), `sandboxd-e2e.sh` (bare-metal e2e, below), plus the - `archive`/`egress`/`intercept`/`socks`/`port` e2e drivers + `archive`/`egress`/`intercept`/`socks`/`credentials`/`port` e2e drivers - `packaging/` — the systemd unit deploy installs ## Build & test @@ -126,7 +128,8 @@ TEMPLATE=rt:24.04 scripts/sandboxd-e2e.sh - `silkd.yml` / `sandboxd.yml` — Rust and Go test+lint suites - `boot-init.yml` — the boot/init crate's own fmt+clippy+test gate -- `python.yml` — ruff + pytest for the three Python packages +- `python.yml` — ruff + pytest for the three Python packages, mypy for the + base SDK - `shell.yml` — shellcheck over every tracked shell script - `images.yml` — the single image entry point: on a push touching `boot/**`, `silkd/**`, `protocol/**`, or `os-image/**` it builds the diff --git a/boot/init/Cargo.lock b/boot/init/Cargo.lock index 5d4d4a90f..5363429f4 100644 --- a/boot/init/Cargo.lock +++ b/boot/init/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "libc" -version = "0.2.189" +version = "0.2.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" [[package]] name = "sandbox-init" diff --git a/docs/deploy.md b/docs/deploy.md index 4db8ca626..00b1155d1 100644 --- a/docs/deploy.md +++ b/docs/deploy.md @@ -535,7 +535,7 @@ through `/v1/tenants` on any node. ```sql CREATE TABLE IF NOT EXISTS sandboxd_tenants ( name text PRIMARY KEY, - token_sha256 bytea NOT NULL UNIQUE CHECK (length(token_sha256) = 32), + token_sha256 bytea NOT NULL UNIQUE DEFERRABLE INITIALLY DEFERRED CHECK (length(token_sha256) = 32), max_claims integer NOT NULL DEFAULT 0 CHECK (max_claims >= 0), egress_class text NOT NULL DEFAULT '', updated_at timestamptz NOT NULL DEFAULT now() diff --git a/docs/egress.md b/docs/egress.md index ec47fb39d..0f54997f2 100644 --- a/docs/egress.md +++ b/docs/egress.md @@ -523,7 +523,8 @@ install is off the claim path). It is **not** re-installed on re-claim: a clone, checkpoint restore, archive wake, or reconcile adopts the guest with whatever root it was born with. Each golden's `.stamp` file records what it baked (the root fingerprint, the lane verdict, -and the warmup argv), and a golden is adopted only when its stamp exists and +the image id, a sized pool's disk size, and the warmup argv), and a golden is +adopted only when its stamp exists and matches, so a changed root rebuilds goldens; a golden from before the stamp has none and is rebuilt once. Nothing rebuilds an existing checkpoint, archive, promoted template, or live/hibernated claim. Because the baked cert diff --git a/docs/index.md b/docs/index.md index 791bc7db1..0492301e8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -29,7 +29,8 @@ vsock-only I/O (hardened default); `net=egress` attaches a bridge/CNI NIC. - [Go SDK](sdk.md) — connecting (single node and clusters), every option, the full sandbox surface, error handling - [Python SDK](sdk-python.md) — the guest and data-plane surface for the - Python-first agent ecosystem, stdlib-only; node pool retuning remains Go-only + Python-first agent ecosystem, stdlib-only; node pool and tenant + administration and the claim env remain Go-only - [LangChain toolkit](langchain.md) — sandbox tools for LangChain/LangGraph agents, with checkpoint branching - [MCP server](mcp.md) — sandboxes as Model Context Protocol tools for diff --git a/docs/sandboxd-api.md b/docs/sandboxd-api.md index 2e59ee1d3..159188652 100644 --- a/docs/sandboxd-api.md +++ b/docs/sandboxd-api.md @@ -426,6 +426,7 @@ only templates it promoted — anything else is 404, root labels anything. 204 o success, 400 bad labels or body, 404 unknown template, 409 when the key belongs to a configured pool. The call speaks only for the node it reaches; it does not follow a redirect. + ## PUT /v1/pools Auth: root only (tenant tokens get 403). Replaces the node's desired warm @@ -530,8 +531,9 @@ Which fields reload, and what happens to live claims and goldens, is described in [deploy](deploy.md#reloading-the-config). The status codes: - **400**: the file does not parse or does not validate. -- **409**: a field needs a restart (the message names it), or intercept is - turned on for a key this node has served or without a CA loaded at boot. +- **409**: a field needs a restart (the message names it), intercept is + turned on for a key this node has served or without a CA loaded at boot, or + a pool's egress policy is removed while live claims still use it. A refused reload changes nothing. diff --git a/docs/sdk-python.md b/docs/sdk-python.md index 54d6c6cff..212ed9a6f 100644 --- a/docs/sdk-python.md +++ b/docs/sdk-python.md @@ -11,9 +11,11 @@ with client.new("ghcr.io/cocoonstack/sandbox/rt:24.04") as sb: `pip install cocoonstack-sandbox` — stdlib-only, no dependencies, and synchronous by design (agent frameworks that need async wrap calls in `asyncio.to_thread`, exactly like the [OpenAI adapter](openai-adapter.md) -does). It matches the [Go SDK](sdk.md) guest and data-plane surface, with four -exceptions: operator pool retuning (`SetPools`/`SetPoolsCluster`) and setting -claim `metadata` or `on_expire` remain Go-only, `Template.new` takes no `claim_ref`, and file and tar payloads are whole `bytes` values rather than +does). It matches the [Go SDK](sdk.md) guest and data-plane surface, with these +exceptions: the operator pool and tenant verbs (`SetPools`, `PutTenant` and +their siblings), the claim env (`WithEnv`, `Env`/`SetEnv`/`PatchEnv`) and +setting claim `metadata` or `on_expire` remain Go-only, `Template.new` takes no +`claim_ref`, and file and tar payloads are whole `bytes` values rather than streams (`read_file`/`pull` return them, `write_file`/`push` take them; the wire is chunked, the caller's copy is not). Wire fidelity is pinned by the shared protocol fixture corpus that the Rust guest, Go, and diff --git a/e2e/go.mod b/e2e/go.mod index 8a86c8270..49fc1b26b 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -8,7 +8,7 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.33.6 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.20.6 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.20.1 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.10 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.13 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.4 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.8.4 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.5.4 // indirect @@ -16,7 +16,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.11.5 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.20.4 // indirect - github.com/aws/aws-sdk-go-v2/service/s3 v1.113.4 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.114.0 // indirect github.com/aws/aws-sdk-go-v2/service/signin v1.10.1 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.38.1 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.43.1 // indirect @@ -33,15 +33,15 @@ require ( github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.11.0 // indirect - github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/jackc/puddle/v2 v2.2.3 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-colorable v0.1.15 // indirect + github.com/mattn/go-colorable v0.1.16 // indirect github.com/mattn/go-isatty v0.0.24 // indirect github.com/mdlayher/netlink v1.11.2 // indirect github.com/mdlayher/socket v0.7.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/projecteru2/core v0.1.5 // indirect + github.com/projecteru2/core v0.1.7 // indirect github.com/rogpeppe/go-internal v1.16.0 // indirect github.com/rs/zerolog v1.35.1 // indirect golang.org/x/mod v0.41.0 // indirect @@ -50,7 +50,7 @@ require ( golang.org/x/sys v0.48.0 // indirect golang.org/x/text v0.42.0 // indirect golang.org/x/time v0.16.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260904194346-d0f1323225a4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8 // indirect google.golang.org/grpc v1.84.0 // indirect google.golang.org/protobuf v1.36.12 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect diff --git a/e2e/go.sum b/e2e/go.sum index 3380dd5ce..4a35bbb85 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -8,8 +8,8 @@ github.com/aws/aws-sdk-go-v2/credentials v1.20.6 h1:NpAFXCU7NzXNkdGK3zQTtsRJ+3v9 github.com/aws/aws-sdk-go-v2/credentials v1.20.6/go.mod h1:mcZCoiPnyMvP8VMNbygNX5lLqSlkYJIMPODylQMurOk= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.20.1 h1:8gALAAmacnIXh+z6VkdDanv4/IkG5APdg4DZLDTmLog= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.20.1/go.mod h1:Z7IJhJU+poOdJjUR2wpyY21ossQ1XS/R3Lk9Msq5kM4= -github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.10 h1:DaCvPvqeZCMqziWeKPiLCv/tUvpe4/Cq79bjE1ZGtHY= -github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.10/go.mod h1:eHZtvcgtQ2WQDWcIs/VUuM3zglCEGipTaxfaTmzZxpw= +github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.13 h1:wO7TVbywHwdpHLUiX6DnmP2RDYOACVeJCb6zMfSFViU= +github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.13/go.mod h1:Zc9r0r7wMid/NkbsLrkGxe5vZufWyP0CiC2dDXZ8ldk= github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.4 h1:CLq4+8UHCI+ZZYl/EuJxXovaIVN2xeeT8JV+dsApQ5E= github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.4/go.mod h1:Wv4q5sAM04xAMkoOedxLx2inVf6K5FdxYp+A61L+q/0= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.8.4 h1:dD4MR81I7YkpEBRk6UP9rocC2QnT3qVuXwzlYTtfGEs= @@ -24,8 +24,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.4 h1:29SvnfGhX github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.4/go.mod h1:wm04I5DMuNVvZHFe/dHnUxincvNbbK7AiNBbYsQivek= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.20.4 h1:pPiWfgeNxqluKEph7hvU88kuGKBPOWzO+Dk9t2zqqNs= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.20.4/go.mod h1:YlwGoIUDG/3kBQbdNOVs/xKZ9J01G8e/6D1mRBj9uTk= -github.com/aws/aws-sdk-go-v2/service/s3 v1.113.4 h1:n6kO3OlBvnDEksQpvBLbAldjHwGlu8kErvhHJkhlaRY= -github.com/aws/aws-sdk-go-v2/service/s3 v1.113.4/go.mod h1:9APRWGLFITKD+xzWSIyT9V7QV4bNlEuIieWlzXgGFlI= +github.com/aws/aws-sdk-go-v2/service/s3 v1.114.0 h1:VMAdYqr4Jn/8ATs9BHC5riwrs0d6m1Z2ohFriSwZwm0= +github.com/aws/aws-sdk-go-v2/service/s3 v1.114.0/go.mod h1:9APRWGLFITKD+xzWSIyT9V7QV4bNlEuIieWlzXgGFlI= github.com/aws/aws-sdk-go-v2/service/signin v1.10.1 h1:DzCCWLzcIRQ77F3DEUljud7bEjTgFOIKXP52NmVRyhU= github.com/aws/aws-sdk-go-v2/service/signin v1.10.1/go.mod h1:xpo/geVldu8payT375WekctUzopG/hBU7miiqItMUlw= github.com/aws/aws-sdk-go-v2/service/sso v1.38.1 h1:Umtl/0YZhng4xndfW3lKJrYYP7NLEjI6bGXVomwLcs0= @@ -62,16 +62,16 @@ github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7Ulw github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.11.0 h1:IzBBtyK9AHqf98cctWFifYSci2hgQR/cd56wB4p+ogg= github.com/jackc/pgx/v5 v5.11.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= -github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= -github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jackc/puddle/v2 v2.2.3 h1:f8HoREISb3l5eO9coPgK7U3hKLhWGokOFVcThl5jrao= +github.com/jackc/puddle/v2 v2.2.3/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY= -github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-colorable v0.1.16 h1:+2YjeAe7xP1OQbZW1jERPWWCDLlNqFNCvjiqGiAt84A= +github.com/mattn/go-colorable v0.1.16/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= github.com/mdlayher/netlink v1.11.2 h1:HKh2jqe+omdSWcQ88nrT7INE61B0NXfiSPFdgL4YbNI= @@ -84,8 +84,8 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/projecteru2/core v0.1.5 h1:cS3xfqa6I1bMXtGdbu2A2UzhjiHaP2mogjQWFTkSEF0= -github.com/projecteru2/core v0.1.5/go.mod h1:MDMJmmlJ3ZVvFQl5BnRcKV1/AVCHyiWoI4BI+sCnuYM= +github.com/projecteru2/core v0.1.7 h1:f2EdndjWFBYX6pqLZ68VcFYMkXZu6RivotaKUGCNwDQ= +github.com/projecteru2/core v0.1.7/go.mod h1:iVfdX4r9/qD52il7DbV18BFEp8fgoUMBp/60WMqFxPc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g= github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= @@ -104,8 +104,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= -go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -145,8 +143,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260904194346-d0f1323225a4 h1:5t+ZydAFj5kGVLrgCvLmpmCf9ylGRd64hpEronfRaws= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260904194346-d0f1323225a4/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8 h1:0SXBqli5dnuCKMjI/X3FM226zEaEa0GUcSCJtN1vL2o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc= google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0= google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= diff --git a/mcp/go.mod b/mcp/go.mod index 47d42e876..91a4be0fe 100644 --- a/mcp/go.mod +++ b/mcp/go.mod @@ -5,7 +5,7 @@ go 1.27.1 require ( github.com/cocoonstack/sandbox/protocol/wire v0.1.16 github.com/cocoonstack/sandbox/sdk/go v0.0.0 - github.com/projecteru2/core v0.1.5 + github.com/projecteru2/core v0.1.7 ) require ( @@ -17,14 +17,14 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-colorable v0.1.15 // indirect + github.com/mattn/go-colorable v0.1.16 // indirect github.com/mattn/go-isatty v0.0.24 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rogpeppe/go-internal v1.16.0 // indirect github.com/rs/zerolog v1.35.1 // indirect golang.org/x/sys v0.48.0 // indirect golang.org/x/text v0.42.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260904194346-d0f1323225a4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8 // indirect google.golang.org/grpc v1.84.0 // indirect google.golang.org/protobuf v1.36.12 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect diff --git a/mcp/go.sum b/mcp/go.sum index 9bc5e3d17..8257c939a 100644 --- a/mcp/go.sum +++ b/mcp/go.sum @@ -21,8 +21,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY= -github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-colorable v0.1.16 h1:+2YjeAe7xP1OQbZW1jERPWWCDLlNqFNCvjiqGiAt84A= +github.com/mattn/go-colorable v0.1.16/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -30,8 +30,8 @@ github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTw github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/projecteru2/core v0.1.5 h1:cS3xfqa6I1bMXtGdbu2A2UzhjiHaP2mogjQWFTkSEF0= -github.com/projecteru2/core v0.1.5/go.mod h1:MDMJmmlJ3ZVvFQl5BnRcKV1/AVCHyiWoI4BI+sCnuYM= +github.com/projecteru2/core v0.1.7 h1:f2EdndjWFBYX6pqLZ68VcFYMkXZu6RivotaKUGCNwDQ= +github.com/projecteru2/core v0.1.7/go.mod h1:iVfdX4r9/qD52il7DbV18BFEp8fgoUMBp/60WMqFxPc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g= github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= @@ -45,8 +45,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= -go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -80,8 +78,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260904194346-d0f1323225a4 h1:5t+ZydAFj5kGVLrgCvLmpmCf9ylGRd64hpEronfRaws= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260904194346-d0f1323225a4/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8 h1:0SXBqli5dnuCKMjI/X3FM226zEaEa0GUcSCJtN1vL2o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc= google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0= google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= diff --git a/os-image/android/15/Dockerfile b/os-image/android/15/Dockerfile index 591cc5942..d5015c479 100644 --- a/os-image/android/15/Dockerfile +++ b/os-image/android/15/Dockerfile @@ -9,7 +9,7 @@ ARG ANDROID_BASE_IMAGE=ghcr.io/cocoonstack/cocoon/android:15.0 # silkd carrier image (built from silkd/Dockerfile); CI passes the # version-pinned tag. -ARG SILKD_IMAGE=ghcr.io/cocoonstack/sandbox/silkd:0.1.13 +ARG SILKD_IMAGE=ghcr.io/cocoonstack/sandbox/silkd:0.1.16 FROM ${SILKD_IMAGE} AS silkd diff --git a/sandboxd/go.mod b/sandboxd/go.mod index 994ffc3fc..838839642 100644 --- a/sandboxd/go.mod +++ b/sandboxd/go.mod @@ -5,15 +5,15 @@ go 1.27.1 require ( github.com/aws/aws-sdk-go-v2 v1.47.1 github.com/aws/aws-sdk-go-v2/config v1.33.6 - github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.10 - github.com/aws/aws-sdk-go-v2/service/s3 v1.113.4 + github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.13 + github.com/aws/aws-sdk-go-v2/service/s3 v1.114.0 github.com/aws/smithy-go v1.28.2 github.com/cocoonstack/sandbox/protocol/wire v0.0.0-00010101000000-000000000000 github.com/docker/go-units v0.5.0 github.com/google/nftables v0.3.0 github.com/hashicorp/memberlist v0.7.0 github.com/jackc/pgx/v5 v5.11.0 - github.com/projecteru2/core v0.1.5 + github.com/projecteru2/core v0.1.7 github.com/rs/zerolog v1.35.1 golang.org/x/mod v0.41.0 golang.org/x/net v0.59.0 @@ -53,10 +53,10 @@ require ( github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/jackc/puddle/v2 v2.2.3 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-colorable v0.1.15 // indirect + github.com/mattn/go-colorable v0.1.16 // indirect github.com/mattn/go-isatty v0.0.24 // indirect github.com/mdlayher/netlink v1.11.2 // indirect github.com/mdlayher/socket v0.7.0 // indirect @@ -66,7 +66,7 @@ require ( github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/vishvananda/netns v0.0.5 // indirect golang.org/x/text v0.42.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260904194346-d0f1323225a4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8 // indirect google.golang.org/grpc v1.84.0 // indirect google.golang.org/protobuf v1.36.12 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect diff --git a/sandboxd/go.sum b/sandboxd/go.sum index 90aadfd90..050936534 100644 --- a/sandboxd/go.sum +++ b/sandboxd/go.sum @@ -8,8 +8,8 @@ github.com/aws/aws-sdk-go-v2/credentials v1.20.6 h1:NpAFXCU7NzXNkdGK3zQTtsRJ+3v9 github.com/aws/aws-sdk-go-v2/credentials v1.20.6/go.mod h1:mcZCoiPnyMvP8VMNbygNX5lLqSlkYJIMPODylQMurOk= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.20.1 h1:8gALAAmacnIXh+z6VkdDanv4/IkG5APdg4DZLDTmLog= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.20.1/go.mod h1:Z7IJhJU+poOdJjUR2wpyY21ossQ1XS/R3Lk9Msq5kM4= -github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.10 h1:DaCvPvqeZCMqziWeKPiLCv/tUvpe4/Cq79bjE1ZGtHY= -github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.10/go.mod h1:eHZtvcgtQ2WQDWcIs/VUuM3zglCEGipTaxfaTmzZxpw= +github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.13 h1:wO7TVbywHwdpHLUiX6DnmP2RDYOACVeJCb6zMfSFViU= +github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.4.13/go.mod h1:Zc9r0r7wMid/NkbsLrkGxe5vZufWyP0CiC2dDXZ8ldk= github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.4 h1:CLq4+8UHCI+ZZYl/EuJxXovaIVN2xeeT8JV+dsApQ5E= github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.4/go.mod h1:Wv4q5sAM04xAMkoOedxLx2inVf6K5FdxYp+A61L+q/0= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.8.4 h1:dD4MR81I7YkpEBRk6UP9rocC2QnT3qVuXwzlYTtfGEs= @@ -24,8 +24,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.4 h1:29SvnfGhX github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.4/go.mod h1:wm04I5DMuNVvZHFe/dHnUxincvNbbK7AiNBbYsQivek= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.20.4 h1:pPiWfgeNxqluKEph7hvU88kuGKBPOWzO+Dk9t2zqqNs= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.20.4/go.mod h1:YlwGoIUDG/3kBQbdNOVs/xKZ9J01G8e/6D1mRBj9uTk= -github.com/aws/aws-sdk-go-v2/service/s3 v1.113.4 h1:n6kO3OlBvnDEksQpvBLbAldjHwGlu8kErvhHJkhlaRY= -github.com/aws/aws-sdk-go-v2/service/s3 v1.113.4/go.mod h1:9APRWGLFITKD+xzWSIyT9V7QV4bNlEuIieWlzXgGFlI= +github.com/aws/aws-sdk-go-v2/service/s3 v1.114.0 h1:VMAdYqr4Jn/8ATs9BHC5riwrs0d6m1Z2ohFriSwZwm0= +github.com/aws/aws-sdk-go-v2/service/s3 v1.114.0/go.mod h1:9APRWGLFITKD+xzWSIyT9V7QV4bNlEuIieWlzXgGFlI= github.com/aws/aws-sdk-go-v2/service/signin v1.10.1 h1:DzCCWLzcIRQ77F3DEUljud7bEjTgFOIKXP52NmVRyhU= github.com/aws/aws-sdk-go-v2/service/signin v1.10.1/go.mod h1:xpo/geVldu8payT375WekctUzopG/hBU7miiqItMUlw= github.com/aws/aws-sdk-go-v2/service/sso v1.38.1 h1:Umtl/0YZhng4xndfW3lKJrYYP7NLEjI6bGXVomwLcs0= @@ -84,16 +84,16 @@ github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7Ulw github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.11.0 h1:IzBBtyK9AHqf98cctWFifYSci2hgQR/cd56wB4p+ogg= github.com/jackc/pgx/v5 v5.11.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= -github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= -github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jackc/puddle/v2 v2.2.3 h1:f8HoREISb3l5eO9coPgK7U3hKLhWGokOFVcThl5jrao= +github.com/jackc/puddle/v2 v2.2.3/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY= -github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-colorable v0.1.16 h1:+2YjeAe7xP1OQbZW1jERPWWCDLlNqFNCvjiqGiAt84A= +github.com/mattn/go-colorable v0.1.16/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= github.com/mdlayher/netlink v1.11.2 h1:HKh2jqe+omdSWcQ88nrT7INE61B0NXfiSPFdgL4YbNI= @@ -108,8 +108,8 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/projecteru2/core v0.1.5 h1:cS3xfqa6I1bMXtGdbu2A2UzhjiHaP2mogjQWFTkSEF0= -github.com/projecteru2/core v0.1.5/go.mod h1:MDMJmmlJ3ZVvFQl5BnRcKV1/AVCHyiWoI4BI+sCnuYM= +github.com/projecteru2/core v0.1.7 h1:f2EdndjWFBYX6pqLZ68VcFYMkXZu6RivotaKUGCNwDQ= +github.com/projecteru2/core v0.1.7/go.mod h1:iVfdX4r9/qD52il7DbV18BFEp8fgoUMBp/60WMqFxPc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g= github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= @@ -130,8 +130,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= -go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -171,8 +169,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260904194346-d0f1323225a4 h1:5t+ZydAFj5kGVLrgCvLmpmCf9ylGRd64hpEronfRaws= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260904194346-d0f1323225a4/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8 h1:0SXBqli5dnuCKMjI/X3FM226zEaEa0GUcSCJtN1vL2o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc= google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0= google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= diff --git a/sandboxd/pool/checkpoint_test.go b/sandboxd/pool/checkpoint_test.go index a512d8dc2..3346bac95 100644 --- a/sandboxd/pool/checkpoint_test.go +++ b/sandboxd/pool/checkpoint_test.go @@ -168,7 +168,7 @@ func TestReconcileSweepsCheckpointStaging(t *testing.T) { if err := m.Reconcile(t.Context()); err != nil { t.Fatalf("Reconcile: %v", err) } - if _, err := os.Stat(stale); !os.IsNotExist(err) { + if _, err := os.Stat(stale); !errors.Is(err, os.ErrNotExist) { t.Errorf("staging survived reconcile: %v", err) } if ckpts, err := m.Checkpoints(t.Context(), ""); err != nil || len(ckpts) != 0 { diff --git a/sandboxd/pool/pool.go b/sandboxd/pool/pool.go index cc41105b7..ffda09f1f 100644 --- a/sandboxd/pool/pool.go +++ b/sandboxd/pool/pool.go @@ -220,12 +220,13 @@ type pool struct { goldenDir string imageID string // goldenGen counts installs, so a clone of a retired golden never lands after a rebuild at the same path. - goldenGen uint64 - building bool - nextBuild time.Time - removed bool // dropped from the desired set while building/refilling; swept by refillOnce - warm []*types.Sandbox - refilling int + goldenGen uint64 + building bool + nextBuild time.Time + removed bool // dropped from the desired set while unsettled; swept by refillOnce + warm []*types.Sandbox + refilling int + claimClones int // Without a streak gate a node-wide dead cause is retried every tick at full concurrency refillFails int @@ -236,6 +237,10 @@ func newPool(key types.PoolKey) *pool { return &pool{key: key, hash: key.Hash()} } +func (p *pool) settled() bool { + return !p.building && p.refilling == 0 && p.claimClones == 0 +} + // refillGated reports whether a refill may not spawn: backoff wait, or one probe in flight. func (p *pool) refillGated(now time.Time) bool { return now.Before(p.nextRefill) || (p.refillFails >= refillFailStreak && p.refilling > 0) diff --git a/sandboxd/pool/pool_test.go b/sandboxd/pool/pool_test.go index 264988be3..b1304f4d7 100644 --- a/sandboxd/pool/pool_test.go +++ b/sandboxd/pool/pool_test.go @@ -511,6 +511,7 @@ func TestARemovedPoolKeepsItsGoldenUntilItSettles(t *testing.T) { }{ {"build", func(p *pool) { p.building = true }}, {"refill", func(p *pool) { p.refilling = 1 }}, + {"claim clone", func(p *pool) { p.claimClones = 1 }}, } { t.Run(tt.name, func(t *testing.T) { m := newTestManager(t, newFakeEngine(), config.PoolSpec{PoolKey: testKey, Warm: 0}) @@ -527,7 +528,7 @@ func TestARemovedPoolKeepsItsGoldenUntilItSettles(t *testing.T) { t.Fatalf("golden deleted while the removed pool's %s was in flight", tt.name) } m.mu.Lock() - p.building, p.refilling = false, 0 + p.building, p.refilling, p.claimClones = false, 0, 0 m.mu.Unlock() m.refillOnce(t.Context()) for _, path := range []string{g, g + goldenStampSuffix} { @@ -539,6 +540,44 @@ func TestARemovedPoolKeepsItsGoldenUntilItSettles(t *testing.T) { } } +func TestAClaimCloneHoldsTheGoldenOfItsRemovedPool(t *testing.T) { + eng := newFakeEngine() + eng.cloneStall = make(chan struct{}) + m := newTestManager(t, eng, config.PoolSpec{PoolKey: testKey, Warm: 0}) + g := seedGolden(t, m, "") + m.mu.Lock() + m.pools[testKey].goldenDir = g + m.mu.Unlock() + + cloned := make(chan error, 1) + go func() { + _, err := m.ClaimProvision(t.Context(), testKey, ClaimOptions{}) + cloned <- err + }() + waitFor(t, func() bool { return eng.cloneCount() == 1 }) + if err := m.SetPools(t.Context(), nil); err != nil { + t.Fatalf("SetPools: %v", err) + } + if !dirExists(g) { + t.Fatal("golden deleted under a claim that is cloning from it") + } + close(eng.cloneStall) + if err := <-cloned; err != nil { + t.Fatalf("claim across the removal of its pool: %v", err) + } + + if _, err := m.ClaimProvision(t.Context(), testKey, ClaimOptions{}); err != nil { + t.Fatalf("claim of the removed key: %v", err) + } + if clones, colds := eng.cloneCount(), eng.coldCount(); clones != 1 || colds != 1 { + t.Errorf("clones=%d colds=%d, want a claim after the removal to cold-boot, not clone the retiring golden", clones, colds) + } + m.refillOnce(t.Context()) + if dirExists(g) { + t.Error("golden survived the sweep of its settled pool") + } +} + func TestSetPoolsWarmZeroKeepsTheGolden(t *testing.T) { m := newTestManager(t, newFakeEngine(), config.PoolSpec{PoolKey: testKey, Warm: 1}) g := seedGolden(t, m, "") diff --git a/sandboxd/pool/promote_test.go b/sandboxd/pool/promote_test.go index 21287dcaf..f14c07d5a 100644 --- a/sandboxd/pool/promote_test.go +++ b/sandboxd/pool/promote_test.go @@ -210,7 +210,7 @@ func TestReconcileSweepsGoldenTmpDirs(t *testing.T) { if err := m.Reconcile(t.Context()); err != nil { t.Fatalf("Reconcile: %v", err) } - if _, err := os.Stat(stale); !os.IsNotExist(err) { + if _, err := os.Stat(stale); !errors.Is(err, os.ErrNotExist) { t.Errorf("stale export staging survived reconcile: %v", err) } } diff --git a/sandboxd/pool/reconcile.go b/sandboxd/pool/reconcile.go index 8c644869e..744496195 100644 --- a/sandboxd/pool/reconcile.go +++ b/sandboxd/pool/reconcile.go @@ -14,6 +14,7 @@ import ( "github.com/cocoonstack/sandbox/sandboxd/engine" "github.com/cocoonstack/sandbox/sandboxd/types" + "github.com/cocoonstack/sandbox/sandboxd/utils" ) // Reconcile aligns claims and VMs after a restart; it runs before the server because it swaps in fresh records that would bypass in-flight Transition locks. @@ -98,10 +99,7 @@ func (m *Manager) Reconcile(ctx context.Context) error { } } // a crash mid-export leaves a fork-* staging dir nothing in this life reuses - forks, _ := filepath.Glob(filepath.Join(m.dataDir, "fork-*")) - for _, fork := range forks { - _ = os.RemoveAll(fork) - } + _ = utils.RemoveDirEntries(m.dataDir, func(name string) bool { return strings.HasPrefix(name, "fork-") }) m.reclaimOrphanArchiveCks(ctx, claims) m.retryArchiveDeletes(ctx) diff --git a/sandboxd/pool/refill.go b/sandboxd/pool/refill.go index 4e989180b..635f47c00 100644 --- a/sandboxd/pool/refill.go +++ b/sandboxd/pool/refill.go @@ -40,9 +40,9 @@ func (m *Manager) refillOnce(ctx context.Context) { inFlight := 0 for _, p := range m.pools { inFlight += p.refilling - // SetPools leaves a removed pool in place while a build or refill is in flight + // SetPools leaves a removed pool in place while a build, refill or claim clone is in flight if p.removed { - if !p.building && p.refilling == 0 { + if p.settled() { m.dropPool(ctx, p) } continue diff --git a/sandboxd/pool/reload.go b/sandboxd/pool/reload.go index f029a6a6c..ab1d67d83 100644 --- a/sandboxd/pool/reload.go +++ b/sandboxd/pool/reload.go @@ -21,7 +21,7 @@ type ReloadResult struct { Ignored []string `json:"ignored,omitempty"` } -// ReloadConfig applies next's reloadable settings at once or not at all: a field that needs a restart, or intercept turned on for a key this node has served, refuses the whole reload. +// ReloadConfig applies next's reloadable settings at once or not at all. func (m *Manager) ReloadConfig(ctx context.Context, next *config.Config) (ReloadResult, error) { m.reloadMu.Lock() defer m.reloadMu.Unlock() diff --git a/sandboxd/pool/setpools.go b/sandboxd/pool/setpools.go index 569394dc1..cfe5178cd 100644 --- a/sandboxd/pool/setpools.go +++ b/sandboxd/pool/setpools.go @@ -82,7 +82,7 @@ func (m *Manager) applyPools(ctx context.Context, desired map[types.PoolKey]conf p.applySpec(spec) p.removed = !ok trim = append(trim, p.trimWarm(p.effectiveTarget(now))...) - if !ok && !p.building && p.refilling == 0 { + if !ok && p.settled() { m.dropPool(ctx, p) } } diff --git a/sandboxd/pool/template.go b/sandboxd/pool/template.go index c26576ddc..7578e81ae 100644 --- a/sandboxd/pool/template.go +++ b/sandboxd/pool/template.go @@ -196,8 +196,8 @@ func (m *Manager) HasGolden(ctx context.Context, key types.PoolKey, tenant strin func (m *Manager) HasPoolGolden(key types.PoolKey) bool { m.mu.Lock() defer m.mu.Unlock() - p := m.pools[key] - return p != nil && p.goldenDir != "" + p, ok := m.activePool(key) + return ok && p.goldenDir != "" } // HasPromotedTemplate is resolveGolden's test exactly, so routing never promises a refused golden. @@ -341,12 +341,14 @@ func (g goldenResolution) release() { func (m *Manager) resolveGolden(ctx context.Context, key types.PoolKey, tenant string) (goldenResolution, error) { m.mu.Lock() var dir string - if p := m.pools[key]; p != nil { + p, ok := m.activePool(key) + if ok && p.goldenDir != "" { dir = p.goldenDir + p.claimClones++ } m.mu.Unlock() if dir != "" { - return goldenResolution{dir: dir}, nil + return goldenResolution{dir: dir, unlock: func() { m.mu.Lock(); p.claimClones--; m.mu.Unlock() }}, nil } if key.Net == types.NetEgress { return goldenResolution{}, nil // never resume a live-captured template on the egress lane; cold-boot instead diff --git a/sandboxd/store/peer/transport.go b/sandboxd/store/peer/transport.go index dc16f45a7..059fdb915 100644 --- a/sandboxd/store/peer/transport.go +++ b/sandboxd/store/peer/transport.go @@ -17,6 +17,8 @@ import ( "path/filepath" "strings" "time" + + "github.com/cocoonstack/sandbox/sandboxd/store" ) const ( @@ -25,8 +27,7 @@ const ( maxRecordBytes = 1 << 40 // 1 TiB - metaFile = "meta.json" - exportPrefix = "export/" + exportPrefix = store.ExportDir + "/" // recordTrailer is written last, so EOF without it means the transfer stopped early. recordTrailer = ".record-complete" @@ -82,7 +83,7 @@ func TarRecord(exportDir string, meta []byte, w io.Writer) error { defer func() { _ = tw.Close() }() if err := tw.WriteHeader(&tar.Header{ - Name: metaFile, Mode: 0o600, Size: int64(len(meta)), Typeflag: tar.TypeReg, + Name: store.MetaFile, Mode: 0o600, Size: int64(len(meta)), Typeflag: tar.TypeReg, }); err != nil { return fmt.Errorf("tar record meta: %w", err) } diff --git a/sandboxd/store/peer/transport_test.go b/sandboxd/store/peer/transport_test.go index 2fcd6a224..6ac3862b8 100644 --- a/sandboxd/store/peer/transport_test.go +++ b/sandboxd/store/peer/transport_test.go @@ -288,7 +288,7 @@ func TestTarRecordUntarRoundTripComplete(t *testing.T) { if err := Untar(&buf, dst); err != nil { t.Fatalf("Untar: %v", err) } - if _, err := os.Stat(filepath.Join(dst, recordTrailer)); !os.IsNotExist(err) { + if _, err := os.Stat(filepath.Join(dst, recordTrailer)); !errors.Is(err, os.ErrNotExist) { t.Errorf("completion marker was written to disk (%v); it must be consumed, not stored", err) } if _, err := os.Stat(filepath.Join(dst, "export", "mem")); err != nil { diff --git a/sandboxd/store/storetest/storetest.go b/sandboxd/store/storetest/storetest.go index 829d812ff..ef4adbb99 100644 --- a/sandboxd/store/storetest/storetest.go +++ b/sandboxd/store/storetest/storetest.go @@ -70,7 +70,7 @@ func RunContract(t *testing.T, st store.Store) { if digest != "" { t.Fatalf("Fetch digest after plain re-publish: %q, want empty", digest) } - if _, statErr := os.Stat(filepath.Join(dir, "disk.img")); !os.IsNotExist(statErr) { + if _, statErr := os.Stat(filepath.Join(dir, "disk.img")); !errors.Is(statErr, os.ErrNotExist) { t.Errorf("first-generation file survived re-publish: %v", statErr) } if got, readErr := os.ReadFile(filepath.Join(dir, "disk2.img")); readErr != nil || string(got) != "second-gen" { //nolint:gosec // test path diff --git a/sdk/go/pools.go b/sdk/go/pools.go index 428a3d511..4ce157c63 100644 --- a/sdk/go/pools.go +++ b/sdk/go/pools.go @@ -25,8 +25,8 @@ type poolUpdate struct { Pools []PoolSpec `json:"pools"` } -// SetPools replaces the entry node's desired warm pools (PUT /v1/pools): a -// declarative full replace, so omitted pools drain. Requires the operator token. +// SetPools replaces the entry node's desired warm pools (PUT /v1/pools): omitted +// pools drain and lose their golden once idle. Requires the operator token. func (c *Client) SetPools(ctx context.Context, pools []PoolSpec) (*NodeInfo, error) { return c.setPoolsAt(ctx, c.addr, pools) } diff --git a/silkd/Cargo.lock b/silkd/Cargo.lock index 9af5da808..dafd1b5f3 100644 --- a/silkd/Cargo.lock +++ b/silkd/Cargo.lock @@ -219,9 +219,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.189" +version = "0.2.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" [[package]] name = "linux-raw-sys" @@ -252,9 +252,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" +checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee" dependencies = [ "libc", "log", @@ -501,9 +501,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.53.1" +version = "1.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044" dependencies = [ "bytes", "libc", diff --git a/silkd/src/lsp.rs b/silkd/src/lsp.rs index 0916374d0..865835ca6 100644 --- a/silkd/src/lsp.rs +++ b/silkd/src/lsp.rs @@ -221,6 +221,5 @@ async fn read_manifest(language: &str) -> Option> { .ok()?; let mut raw = String::new(); f.read_to_string(&mut raw).await.ok()?; - let argv: Vec = raw.split_whitespace().map(str::to_string).collect(); - (!argv.is_empty()).then_some(argv) + Some(raw.split_whitespace().map(str::to_string).collect()) }