> ## Documentation Index
> Fetch the complete documentation index at: https://smithers.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS Sandbox Provider

> Run a Smithers <Sandbox> child workflow on AWS Fargate or CodeBuild with createAwsSandboxProvider, transporting the bundle through S3.

# 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`).

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
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

```tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
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} />
```

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
// 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.
