Skip to main content

AWS Sandbox Provider

@smithers-orchestrator/aws is a first-class Smithers SandboxProvider that runs a <Sandbox> child workflow’s request on AWS. It has two modes: Fargate (ECS RunTask, the default) and CodeBuild. AWS gives the orchestrator no shared filesystem with the remote task, so the request/result bundle is transported through an S3 bucket you already own. The shared provider-kit owns the request/result protocol, egress, secret scrubbing, and cleanup; this package supplies the S3 transport plus the ECS/CodeBuild runners. The provider id is aws-sandbox (exported as AWS_SANDBOX_PROVIDER_ID).
import {
  createAwsSandboxProvider,
  registerAwsSandboxProvider,
  AWS_SANDBOX_PROVIDER_ID,
} from "smithers-orchestrator/aws";

Credentials

Authentication uses the standard AWS SDK v3 credential chain: env vars, shared config, SSO, or an instance/task role. No explicit credentials are passed to the factory and none are ever forwarded into the remote task env. The remote task authenticates with its own task or build IAM role. The @aws-sdk/* clients are optional dependencies, imported lazily. Install the ones your mode needs:
  • @aws-sdk/client-s3 (always).
  • @aws-sdk/client-ecs (Fargate).
  • @aws-sdk/client-codebuild (CodeBuild).
  • @aws-sdk/client-cloudwatch-logs (only with captureLogs).

Prerequisites

The provider does not provision infrastructure. Set these up first:
  • An S3 bucket that already exists. The provider only manages the key prefix smithers/sandbox/<runId>/<sandboxId>/ under it.
  • For Fargate: an ECS cluster, a registered taskDefinition, at least one VPC subnet, optional securityGroups, and the containerName inside the task definition. The task role needs S3 read/write on the prefix.
  • For CodeBuild: a CodeBuild projectName. The build role needs S3 read/write on the prefix.

Usage

import { createAwsSandboxProvider } from "smithers-orchestrator/aws";

// Fargate (default)
const provider = createAwsSandboxProvider({
  region: "us-east-1",
  bucket: "my-smithers-sandbox-bucket", // must already exist
  cluster: "smithers",
  taskDefinition: "smithers-sandbox:7",
  subnets: ["subnet-abc123"],
  securityGroups: ["sg-def456"],
  assignPublicIp: "ENABLED",
  containerName: "runner",
});

// <Sandbox provider={provider} workflow={child} output={outputs.result} />
// CodeBuild
const codebuild = createAwsSandboxProvider({
  mode: "codebuild",
  region: "us-east-1",
  bucket: "my-smithers-sandbox-bucket",
  projectName: "smithers-sandbox",
});
Or register either provider once and reference it by id with registerAwsSandboxProvider(...) then <Sandbox provider="aws-sandbox" />.

Request/result contract

The kit hands the entry command SMITHERS_SANDBOX_REQUEST_PATH and SMITHERS_SANDBOX_RESULT_PATH. Because there is no shared filesystem, the container round-trips those files through S3. The provider injects four more vars so the entry can find them:
  • SMITHERS_SANDBOX_S3_BUCKET: the transport bucket.
  • SMITHERS_SANDBOX_S3_PREFIX: smithers/sandbox/<runId>/<sandboxId>.
  • SMITHERS_SANDBOX_REQUEST_S3_KEY: S3 key of the request JSON.
  • SMITHERS_SANDBOX_RESULT_S3_KEY: S3 key the entry must write the result to.
Every workdir path maps to s3://<bucket>/<prefix>/<runId>/<sandboxId>/<encodeURIComponent(workdir-relative path)> so two files that share a basename never collide. The entry either prints the result JSON to stdout or writes it to the result key. An infra failure (task or build fails with no result written) throws. A result file with status: "failed" is a normal failed bundle. Fargate reports a real numeric container exit code; CodeBuild reports a status (SUCCEEDED maps to 0, else 1).

Factory options

  • mode: "fargate" (default) or "codebuild".
  • region, bucket: required in both modes.
  • Fargate: cluster, taskDefinition, subnets, containerName (required), securityGroups, assignPublicIp, logGroupName.
  • CodeBuild: projectName (required).
  • captureLogs: pull CloudWatch logs, truncated to maxOutputBytes.
  • command, workdir (default /workspace), env.
  • cleanup: "destroy" (default) or "keep".
  • clients / client / clientOptions: inject SDK doubles or client options.

Cleanup and cost

cleanup: "destroy" (default) stops the task or build if it is still running and deletes the transient S3 objects. cleanup: "keep" leaves them. You pay for Fargate task time or CodeBuild build minutes, plus S3 storage of the small transient bundle objects. Set a short lifecycle TTL on the smithers/sandbox/ prefix to reap anything a crash leaves behind. EC2 mode is documented future work. createMockAwsSandboxEnvironment(handler, mockOptions?) provides in-memory S3, ECS, CodeBuild, and CloudWatch Logs doubles for tests. It needs zero AWS credentials, so unit tests run in CI without touching AWS.