# Azure Container Apps Sandbox client library for JavaScript

This package contains an isomorphic SDK for the Azure Container Apps Sandbox API
(data plane + control plane).

Azure Container Apps Sandboxes are secure, hardware-isolated microVMs with
sub-second startup, snapshot-based suspend/resume, and per-sandbox network egress
policy — ideal for running untrusted code, AI agent workspaces, dev environments,
and CI runners.

> **Preview** — This package is in preview. The API surface may change without
> notice. See the [CHANGELOG](./CHANGELOG.md) for migration notes when upgrading.

## Getting started

### Currently supported environments

- [LTS versions of Node.js](https://github.com/nodejs/release#release-schedule)

### Prerequisites

- An [Azure subscription](https://azure.microsoft.com/free/).

### Install the `@azure/containerapps-sandbox` package

Install the client library with [npm](https://www.npmjs.com/):

```bash
npm install @azure/containerapps-sandbox
```

### Create and authenticate a client

To create a client, you need a `TokenCredential` from
[`@azure/identity`](https://www.npmjs.com/package/@azure/identity):

```bash
npm install @azure/identity
```

There are two clients:

- `ContainerAppsSandboxManagementClient` — the ARM **control plane** for creating
  and deleting sandbox groups.
- `SandboxGroupClient` — the **data plane** for a single sandbox group (sandboxes,
  disk images, snapshots, volumes, secrets, ports, egress, files).

```ts
import { DefaultAzureCredential } from "@azure/identity";
import {
  ContainerAppsSandboxManagementClient,
  SandboxGroupClient,
  endpointForRegion,
} from "@azure/containerapps-sandbox";

const credential = new DefaultAzureCredential();
const subscriptionId = "<your-subscription-id>";
const resourceGroupName = "my-rg";
const sandboxGroupName = "my-sandbox-group";
const region = "eastus2";

// 1. Create the sandbox group (ARM control plane).
const mgmt = new ContainerAppsSandboxManagementClient(credential, subscriptionId);
await mgmt.sandboxGroups
  .beginCreateOrUpdate(resourceGroupName, sandboxGroupName, { location: region })
  .then((p) => p.pollUntilDone());

// (Grant yourself the "Container Apps SandboxGroup Data Owner" role on the
//  resource group so the data-plane calls below are authorized.)

// 2. Connect to the data plane and create a sandbox.
const group = new SandboxGroupClient(
  credential,
  endpointForRegion(region),
  subscriptionId,
  resourceGroupName,
  sandboxGroupName,
);
const sandbox = await group.sandboxes.beginCreate({ disk: undefined }).then((p) => p.pollUntilDone());

// 3. Run a command.
const result = await group.sandboxes.exec(sandbox.id, { command: "echo hello && uname -a" });
console.log(result.stdout);

// 4. Clean up.
await group.sandboxes.delete(sandbox.id);
await mgmt.sandboxGroups.beginDelete(resourceGroupName, sandboxGroupName).then((p) => p.pollUntilDone());
```

## Key concepts

### Operation groups

Like the generated Azure management SDKs, operations are grouped on the client by
resource type, e.g. `group.sandboxes.get(...)`, `group.diskImages.list()`,
`mgmt.sandboxGroups.beginCreateOrUpdate(...)`.

### Long-running operations (LRO)

Operations that take more than a few seconds expose a `begin*` method that returns
a `PollerLike<OperationState<T>, T>` from `@azure/core-lro`:

```ts
const poller = group.sandboxes.beginCreate({ sourcesRef: { diskImage: { name: "ubuntu", isPublic: true } } });
const sandbox = await poller.pollUntilDone();
```

### Paged results

List operations return a `PagedAsyncIterableIterator`:

```ts
for await (const sbx of group.sandboxes.list()) {
  console.log(sbx.id, sbx.state);
}
```

### Port IP access control

`PortIpAccessControl` is validated client-side before it is sent (the service's
bulk `ports.update` path is not re-validated server-side). CIDRs must be
network-aligned, at most 10 rules with 1–10 CIDRs each, unique names and
priorities, and priorities in the range 0–1000.

```ts
import type { PortIpAccessControl } from "@azure/containerapps-sandbox";

const acl: PortIpAccessControl = {
  defaultAction: "Deny",
  rules: [{ name: "office", action: "Allow", priority: 10, sourceCidrs: ["10.0.0.0/8"] }],
};
await group.ports.add(sandbox.id, 8443, { ipAccessControl: acl });
```

## Troubleshooting

### Logging

Enabling logging may help uncover useful information about failures. To see a log
of HTTP requests and responses, set the `AZURE_LOG_LEVEL` environment variable to
`info`. Alternatively, logging can be enabled at runtime by calling
`setLogLevel` in the `@azure/logger`:

```ts
import { setLogLevel } from "@azure/logger";
setLogLevel("info");
```

## Next steps

See the [live integration tests](../azure-containerapps-sandbox-live-tests/) for a
worked end-to-end example that exercises every operation group.

## Contributing

This SDK mirrors the [Python](../../python/azure-containerapps-sandbox/) and
[Rust](../../rust/azure-containerapps-sandbox/) SDKs in this repository.
