GCP Sandbox Provider
@smthrs/gcp is a first-class Smithers SandboxProvider for
Google Cloud. It executes a <Sandbox> child workflow’s request on Cloud Run
Jobs and ships the request/result bundle through a Cloud Storage bucket,
since Cloud Run Jobs give the caller no shared filesystem. The shared
provider-kit owns the request/result protocol, egress, secret scrubbing, and
cleanup; this package supplies just the GCS transport and the Cloud Run runner.
The provider id is gcp-sandbox (exported as GCP_SANDBOX_PROVIDER_ID).
Credentials
Authentication is Application Default Credentials:GOOGLE_APPLICATION_CREDENTIALS (a service-account key file) or workload
identity, plus GOOGLE_CLOUD_PROJECT. Local credentials never reach the
container; its env is options.env plus the Smithers, egress, and
GCS-transport variables.
@google-cloud/run and @google-cloud/storage are optional, lazily-imported
dependencies, so the package loads without them; install both to use the
real provider:
Prerequisites
The provider doesn’t create the bucket; set these up first:- A pre-existing Cloud Storage
bucket(the transport). Set a short lifecycle TTL on thesmithers/sandbox/prefix to reap crash leftovers. - A Cloud Run
jobNameto run, orcreateJobto create and tear down a per-run Job.createJobalso requires a containerimage(Cloud Run needs one to create the Job). The job’s service account needs read/write on the bucket prefix.
Required options
createGcpSandboxProvider({ projectId, location, bucket, jobName }): all four
are required and missing ones throw INVALID_INPUT. projectId falls back to
GOOGLE_CLOUD_PROJECT.
Other knobs:
prefix (default smithers/sandbox), command, workdir
(default /workspace), env, cleanup ("destroy" or "keep"),
timeoutSec, createJob, sandboxId(request), and
client/clients/clientOptions for SDK injection.
Usage
registerGcpSandboxProvider(...) then <Sandbox provider="gcp-sandbox" />.
Request/result contract
The kit writes.smithers/sandbox-request.json and expects
.smithers/sandbox-result.json back, handing the container
SMITHERS_SANDBOX_REQUEST_PATH and SMITHERS_SANDBOX_RESULT_PATH. Since
there’s no shared filesystem, the container round-trips those files through
GCS via four extra vars the runner injects:
SMITHERS_SANDBOX_GCS_BUCKET: the transport bucket.SMITHERS_SANDBOX_GCS_PREFIX: object-name prefix.SMITHERS_SANDBOX_REQUEST_GCS_OBJECT: object holding the request JSON.SMITHERS_SANDBOX_RESULT_GCS_OBJECT: object the entry must write result JSON to.
<prefix>/<runId>/<sandboxId>/<percent-encoded workdir-relative path> (the full path, not just the basename, so same-named files never collide). Cloud Run reports task counts
and conditions, not a numeric exit code: a succeeded task is exit 0 and a failed
task is exit 1. An infra failure (execution failed, no result written) throws;
a run that writes status: "failed" result JSON is just a normal failed
bundle the kit materializes.
Cleanup and cost
cleanup: "destroy" (default) deletes the transient GCS objects and, when
createJob made a per-run job, that job too; cleanup: "keep" leaves
everything. The bucket itself is never created or deleted. You pay for Cloud Run
Job execution time plus GCS storage of the small transient objects. Compute
Engine execution is future work.
createMockGcpSandboxEnvironment(handler, config?) provides in-memory Cloud
Storage and Cloud Run doubles for tests, needing zero real GCP credentials or
bucket, so unit tests run in CI without touching GCP.