Skip to content

Add container deployment and hosted authentication foundations - #5881

Draft
cloutiertyler wants to merge 23 commits into
tyler/agent-hosting-proposalfrom
codex/container-hosting-beta
Draft

Add container deployment and hosted authentication foundations#5881
cloutiertyler wants to merge 23 commits into
tyler/agent-hosting-proposalfrom
codex/container-hosting-beta

Conversation

@cloutiertyler

@cloutiertyler cloutiertyler commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Superseded for active review by public Stage 1 #5893. The replacement is ported to current master and stacked on separate environment-variable and V10 ABI prerequisites, with no file-storage ancestry. This PR and its original branch remain available as review history; the original description below is preserved unchanged and records the pre-port implementation and validation.

Review stack, ported to current master/main without a file-storage dependency:

Layer Public Private
Environment variables #5887 #3940
V10 ABI extensions #5892 #3941
Stage 1 Container Hosting #5893 Private Stage 1

Website companion: #1352. Repository branches are tyler/environment-variablestyler/v10-abi-extensionstyler/agent-hosting-proposal-stage-1; the website Stage 1 branch is directly above main.


This draft adds the public host, SDK and CLI foundations for Container Hosting. Container authority is carried through module execution, transactions, subscriptions, database replay and host replacement. It also adds atomic deployment publication, protected environment storage and local OCI build preparation. The default NodeDelegate continues to reject hosted credentials unless an authentication provider is installed.

ModuleHost now closes admission and waits for accepted physical Wasm/JavaScript work before the storage writer closes. Detached calls, procedure slots and isolate startup retain their ownership after caller cancellation. Direct SQL/subscription commits serialize with one shared database shutdown; late commits roll back with DatabaseClosed. This fixes the queued-disconnect path that could previously reach a closed writer.

The definition format stays V10. Appended visibility variants and a capability section preserve existing BSATN tags and reducer/procedure layouts. Rust, TypeScript, C# and C++ bindings carry verified invocation flags independently of JWT or connection presence. Lifecycle reducers remain event-only, internal status does not grant owner SQL permissions, and historical V9/V10 schedule defaults remain unchanged.

Hosted authentication binds the signer, target Identity, source generation, grant revision and expiration. Verified proofs also retain a local monotonic expiry. A fresh authority confirmation can shorten that deadline using its timestamp and the request start time, so receiving-clock lag, delayed replies and later clock changes cannot extend it. Signed claim values remain unchanged. Idle WebSocket connections retain the same cap while authority reads are blocked. Reducers and SQL check authority inside the admitting transaction; procedures recheck later transactions. Subscription delivery checks again after durability waits and before socket I/O. The host exposes positive completion of cancelled connection actors.

Each database open starts with hosted admission closed. A trusted coordinator must reconcile current authority and complete a ticket tied to that database open. Cancellation, replacement, shutdown and changed fence records invalidate the relevant proof. Bounded host APIs enumerate stored fences, deny an exact orphan record without reducing its generation, and confirm that a read position is durable. These APIs require the caller to establish current authority and recheck the final inventory before admission.

HostController maintains one canonical cell per replica, pinned by queued and active operations. Idle ModuleHost handles do not prevent shutdown. An owned close joins the actual durability writer, and stale executable callbacks cannot close a replacement. The superseded cold-storage cleanup API is removed. Normal database opens and closes retain positive writer completion, including replay errors and caller cancellation; an unconfirmed writer close quarantines the replica. Container snapshot collection therefore does not need a separate database-open path.

Publication commits module/schema changes, the container specification, revision and idempotent receipt in one transaction. An abort fences delayed commits; recovery recognizes an already committed operation without executing initialization again. Container-only databases use a versioned empty Wasm module whose immutable bytes and artifact descriptor are now shared with CLI code. Generic SQL and module table access cannot mutate the protected deployment records.

Database environment reads are available in all four module languages. Authorized SQL SET/DELETE validates mutations and invalidates dependent views. Host-only immutable snapshots bind an instance to its declared keys and exact receipt. Snapshot history is hidden from generic SQL, subscriptions and numeric table/index access. Routine SQL diagnostics omit statement bodies and sensitive parser details.

JavaScript startup, description and calls have finite execution deadlines using a bounded shared V8 termination service. Failed procedure startup or replacement releases capacity. The default deadline is 120 seconds; native syscalls still require their own bounds. Direct top-level logging now checks the available stack-frame count before calling V8, preventing an out-of-bounds frame access that could crash the host. Wrapped logging retains the caller's location. The Rust SDK adds cancellable asynchronous connection setup and releases pending callback captures on terminal disconnect.

The CLI parses typed per-database container declarations and adds local spacetime container build. Dockerfile, explicitly selected Railpack and prebuilt OCI inputs produce a verified OCI layout and normalized specification. Local builds bypass saved CLI server/auth configuration. BuildKit requires an explicit Unix socket; imports isolate registry authentication; process groups, output size, deadlines and output replacement are bounded.

Managed spacetime publish retains exact component actions, revision and creation options in a durable local journal. Uploads resume at verified offsets; ambiguous admission keeps the same operation and request bytes. Artifact completion validates the returned object digest and size while retaining the original upload session and expiry. An already accepted publication can be recovered without original artifact files, including by exact PUT replay when current access no longer permits status reads. Public PUT replay remains subject to the advertised seven-day window. The client validates endpoint, publisher and receipt bindings, refuses redirects, requires explicit approval of an artifact endpoint on another origin, and keeps authentication credentials out of the journal. Naming has a separate partial-success result after publication completes.

Validation of the latest public checkpoint:

  • Fence/durability: 10 tests; hosted authentication: 22; invocation: 7; empty module: 4; HostController: 18. These include real local commit logs, withheld durability acknowledgment, cancellation, stale callbacks and stored JavaScript that must not execute. Strict core Clippy passes.

  • At dcdcb6a11, physical shutdown regressions: 7; admission: 2; HostController: 18; invocation: 7; SQL: 31; subscriptions: 27. Strict core Clippy passes. Tests include actual JavaScript HTTP work that commits after caller cancellation, cancelled isolate startup, and retained SQL/subscription handles after writer closure.

  • At 5cb244845, CLI publication: 52 tests; configuration: 66; local OCI/build: 16. Strict CLI Clippy passes. Tests include lost responses, revoked access, exact replay, mismatched receipts, endpoint restrictions and durable journal recovery. Earlier actual local OCI import using an invalid isolated cli.toml passes. That earlier checkpoint did not qualify real server/CLI or Dockerfile/Railpack acceptance; subsequent builder evidence is listed below. Windows directory crash durability is not qualified.

  • At 15aff92ba, seven expiry regressions and 23 focused core hosted-authentication tests pass, including cancellation at confirmed expiry while an authority read is blocked. Strict auth/core Clippy and independent review pass. No ABI or signed-claim change is introduced.

  • At a00f0880d, the CLI publication group passes 54/54, including the exact artifact completion response, mismatched descriptors and recovery after response loss. The actual CLI entrypoint help regression and strict CLI library/binary/test Clippy pass.

  • At c9596cc01, a real V8 regression verifies direct and wrapped logging during module startup and reducer execution, including the four caller line numbers. The regression and strict core library/test Clippy pass.

  • At fd35a64db, terminal snapshot-worker shutdown closes admission across clones and joins accepted capture/compression work. An actual datastore/snapshot test blocks capture, cancels one shutdown waiter, verifies closed admission, releases the capture and reads the resulting snapshot. It passes in 0.13 seconds; strict core library/test Clippy passes in one minute.

  • At b8b753944, actual Dockerfile and explicitly selected Railpack builds pass with pinned BuildKit 0.33.0 and Railpack 0.35.0 on macOS arm64. The matrix verifies OCI closure, secret-log suppression, failed builds without fallback, artifact modification rejection, concurrent output protection, real buildctl cancellation and deadline cleanup. The macOS process-group correction accepts EPERM only after proving the exact unreaped exited leader is the sole member. Six local process modes, four isolated fixture cleanup tests, strict CLI Clippy and independent review pass. The real matrix completes positive teardown before writing its receipt. It uses an explicitly verified disposable Docker Desktop socket and isolated configuration, and does not connect to a SpacetimeDB server. The reproducible fixture and pinned tool lock are in crates/cli/tests/container_build_acceptance/.

  • Earlier checks cover datastore and schema compatibility, deployment replay/migration, binding generators, OCI validation, environment SQL permissions and rollback, JavaScript deadline recovery, and SDK disconnect cancellation.

  • At 5d9915b02, the cold-storage API and its capacity machinery are removed while preserving ordinary joined database shutdown. All six ordinary lifecycle regressions pass, covering actual close completion and error/cancellation handling.

  • At b1c6d69b7, spacetime container url discovers and validates public HTTPS addresses without login, credentials, redirects, or constructed hostnames. It selects named ports, distinguishes empty declarations from pending allocation, and bounds/validates responses. Five focused URL tests and the actual CLI-to-Node/control fixture pass. The public response DTO rejects undeclared private-address fields. Strict core/CLI library and test Clippy passes after boxing oversized subscription WebSocket error variants; the existing subscription regression also passes. This discovers addresses; HTTPS/WebSocket forwarding remains required in the private integration.

  • At a945a8063, the CLI adds authenticated container status, start, stop and restart. It preserves the original database Identity, selected server and UUIDv7 request ID for ambiguous-result retries, and validates the exact returned action and generation. Status and lifecycle DTO tests, focused CLI tests and strict CLI lint pass. The actual CLI-to-Node/control lifecycle fixture passes (61.66 seconds), including lost-response replay after a later generation and role revocation. A mutation receipt means control admission; physical readiness and stop remain asynchronous.

This remains an incomplete implementation draft. The APIs deliberately require trusted integrations to establish authority, reconcile receiving state and manage execution before enabling hosted clients.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant