Repository navigation
GA next-gen: sandbox pause/resume/fork, spawn contract + manager authz, cost + security hardening - #254
Closed
dshakes wants to merge 48 commits into
Closed
GA next-gen: sandbox pause/resume/fork, spawn contract + manager authz, cost + security hardening#254dshakes wants to merge 48 commits into
dshakes wants to merge 48 commits into
Conversation
…ped before it existed
A freeform self-chat message landing within milliseconds of a draft being
staged was treated as the owner's deliberate replacement text and forwarded
verbatim to the draft's contact. Live incident: an owner message about an
unrelated SLA digest ("morning, those are auto-nudges not real tasks") landed
11ms after a draft was staged for contact Safiya and got queued to send to her
as-is — blocked only because the channel happened to be muted at that moment.
classifyPendingReply now requires >=3s between the draft's issuedAt and the
reply before falling through to "replace" (approve/reject are unaffected).
Shared in bridge-core, so both bridges get the fix from one change.
… to production; add values-prod
…callers attach it
…; fail closed on Slack signing, Twilio auth off, claude-code in prod
…empotency keys, scheduler quota leak + tenant-scoped idempotency, SSE exec streaming
…re-drive gets a fresh VM
…N_WORKLOAD_UID Every child ran as PID 1's root, so the SO_PEERCRED secrets check always passed (workload uid == harness uid), the iptables REDIRECT (which exempts the harness uid) did not apply to the workload, and tls.key was readable. Spawn via CommandExt uid/gid (gid defaults to uid; std clears supplementary groups). The secrets and OTLP sockets are chmod 0666 so the unprivileged workload can still connect; SO_PEERCRED stays the authorization.
The kernel cmdline splits on whitespace and strips quotes, so argv like 'python main.py' and JSON egress lists arrived mangled. spawn.json (workload_cmd, env, egress_rules, workload_uid/gid; all optional, unknown fields ignored) now takes precedence over boot-args; typed fields beat free-form env. Malformed file: fatal in prod, warn + cmdline in dev. The cert material is copied into a root-only 0700 dir and the drive is unmounted, so tls.key and spawn.json are unreachable by the workload uid regardless of the image's file modes.
…d file tools http_fetch buffered the whole body before checking the 1 MiB cap and shell_exec used unbounded .output(). Both now stream with a bounded read and truncate with a marker; shell_exec runs as the workload uid under the timeout. New read_file / write_file / list_dir tools are confined to LANTERN_WORKSPACE (default /workspace): canonicalize + prefix check, leaf O_NOFOLLOW|O_NONBLOCK, hard links rejected, writes chowned to the workload.
…e wired in both bridges
…tments on verbatim evidence
…crypted sent-reply log; introspect 36h staleness alarm
…thropic streaming system prompts, per-request LLM idempotency keys
…x workflowEngine env nil in helm values; gofmt
…and tsc is enforced in CI; update stale group-reply tests
…start without a workload uid Children inherited the harness's whole environment, including LANTERN_HARNESS_EXEC_TOKEN, LANTERN_AGENT_INSTANCE_TOKEN and the TLS key path. as_workload() now env_clear()s and passes the harness env minus the LANTERN_* namespace (except a short non-secret allowlist: VM/run id, socket paths, workspace, trace parent, LANTERN_WORKLOAD_*), then drops the uid. Used by the supervisor, vm exec (tty and not) and shell_exec. The prod 'LANTERN_WORKLOAD_UID missing' check ran in the secrets task, racing the supervisor; parse_env now fails first. The secrets check stays. fs tools open through openat2(RESOLVE_BENEATH|RESOLVE_NO_SYMLINKS) on a root fd on Linux, closing the parent-dir swap window after the path check; pre-5.6 kernels (ENOSYS) and non-Linux keep the plain open.
…t context rust:1.85 cannot build the current Cargo.lock, build.rs needs protoc, and 'COPY . .' from services/harness could never reach ../../packages/proto. Build from the repo root; a per-Dockerfile .dockerignore keeps the context to packages/proto + services/harness.
…ool tenant scoping, snapshot ownership
…'s tenant Adds field 8 so the runtime-manager can scope ExecTool to the VM's owning tenant (ADR 0025). gen/go regenerated with the pinned protoc v6.33.4 + protoc-gen-go v1.36.11 (byte-identical to the tracked stub before the change).
…xecTool/snapshots - spawn.json (version/workload_cmd/env/egress_rules/workload_uid/gid) written at the cert-image root; cmdline kept for compat, manager-owned LANTERN_WORKLOAD_UID appended, caller-set value dropped - RuntimeManager interceptor: VM certs (OU=lantern-vm) refused; shared x-lantern-service-token required (constant-time); prod refuses to start without LANTERN_GRPC_SERVICE_TOKEN, dev warns+allows - ExecTool: tenant mismatch / empty-in-prod -> NotFound (vm_id and run_id paths) - spawn reserves the wire vm_id before boot (concurrent duplicate -> Aborted) - restore_snapshot_id restores through the post-gate backend with ownership check (NotFound cross-tenant/legacy/bogus id); non-restoring backend -> FailedPrecondition; bare firecracker resolves store:// ids - snapshots record tenant_id + real agent_version_id; save streams artifacts (1 MiB buffer, streamed S3 multipart) instead of loading guest memory - ExecTool harness call bounded by deadline + 1 MiB output cap; timeout capped - warm pool cold-starts through the post-isolation-gate backend; keyed by tenant Refs ADR 0025.
… honest snapshot restore (ADR 0025)
This was referenced Oct 23, 2026
Closed
Closed
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GA next-gen: audit-driven hardening plus sandbox lifecycle. The full plan and findings table are in
docs/roadmap/2026-10-nextgen-sandbox-and-harness.md.Wave 1: correctness and security
JWT_SECRETis now wired from a secretKeyRef, andLANTERN_ENVdefaults toproduction, so the prod guards are on. Addedvalues-prod.yaml.spawn.jsonon the cert drive (ADR 0025). Workloads drop privileges toLANTERN_WORKLOAD_UID.ExecToolis tenant-scoped (proto field 8).WithScope.Cost
ai-stepcalls, confidence votes andweb_searchare now metered and budget-checked./v1/budgets/tenant.Wave 2: pause, resume, fork
POST /v1/runtime/vms/{id}/pausePOST /v1/runtime/vms/{id}/resumePOST /v1/runtime/vms/{id}/forkwith body{"count":N}, N from 1 to 10vm_idand re-identifies itself.DeleteSnapshotRPC is listed as a follow-up in ADR 0025.Bridges
Deps
npm audit --omit=devreports 0.Verification (run locally on the integrated branch)
gofmt,vetandtestpass in every module that usesgen/go(control-plane with DATABASE_URL). runtime-scheduler also passes with-race.fmt,clippy -D warningsandtestpass for runtime-manager (398), harness (186) and model-router.tscand tests pass for bridge-core, the WhatsApp bridge, the iMessage bridge and sdk-ts.apps/webtsc, eslint and build pass. The docs build withPAGES_BASE_PATH=/lanternpasses.helm templaterenders with the default, dev, staging and prod values.HTTP_ADDR=:8090, its own DB, stub scheduler). On the dashboard VM detail page, Pause → Resume → Fork ×3 all completed, with no console errors.Needs a human
helm installon a real cluster.