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

# Browser testing in a sandbox

> Run browser automation, control outbound access, expose authenticated previews, and retain test evidence.

Browser automation runs on the same Kata-isolated substrate as every other sandbox workload. Use a digest-pinned browser-compatible template and the `browser` profile; executions, processes, ports, artifacts, events, and network policy remain the canonical resources.

## Create a browser sandbox

```bash theme={null}
stackshift --timeout 10m sandbox create \
  --name checkout-browser-test \
  --sandbox-profile browser \
  --template 'ghcr.io/acme/browser@sha256:<64-hex-digest>' \
  --tags browser,e2e \
  --wait
```

Inspect `effective_spec.network` and the sandbox capability decisions before starting. The requested policy may be narrowed by account or platform policy.

## Run the test

Install dependencies into the declared workspace or bake them into the immutable template. Then execute the test as argv:

```bash theme={null}
stackshift sandbox exec <sandbox-id> \
  --cwd /workspace \
  --command-timeout 1800 \
  -- npx playwright test --reporter=line
```

For a development server needed by the test, create a background process through an SDK or the process API. Wait for its readiness result before launching the browser run; a running PID is not proof that the HTTP service is ready.

## Control outbound traffic

Allow only the public hosts required by the test. Host allowlisting does not bypass protected destinations: loopback, link-local, private, metadata, and StackShift control-plane addresses stay denied unless an explicitly authorized private network applies.

The worker revalidates DNS answers and redirects. A hostname that resolves or rebinds to a protected address is denied. Treat downloaded pages, scripts, archives, and browser extensions as untrusted input.

When a test needs an upstream credential, prefer a proxy-delivered secret scoped to that host. Do not put bearer tokens in test URLs, Playwright config committed to source, screenshots, traces, or command arguments.

## Preview a service

Inbound access is off until a port resource is created. Start the service inside the sandbox, then open a private HTTP port with the TypeScript SDK:

```ts theme={null}
const sandbox = client.sandbox(sandboxId)
const port = await sandbox.ports.open(3000, 'http', 'private', false)
```

Private access requires a short-lived token or current authenticated session. Public exposure is policy-controlled and should be used only after reviewing the application and secret bindings. Port access logs report allowed and denied requests without storing sensitive paths in plaintext.

## Retain evidence

Upload screenshots, videos, traces, console exports, coverage, and reports as artifacts. Include content type, logical path, size, and SHA-256 checksum; mark uploads complete only after object transfer succeeds. Artifact download authorization is checked again when a short-lived download URL is requested.

Keep browser evidence separate from source deployment handoff. Captures may contain customer data, cookies, tokens, or page content and should have an explicit retention policy.

## Cleanup

Sleep the sandbox if its workspace or sidecars are still needed. Destroy it only after required evidence is retained:

```bash theme={null}
stackshift --timeout 5m sandbox sleep <sandbox-id> --wait
stackshift --yes --timeout 10m sandbox destroy <sandbox-id> --wait
```

<Warning>
  A passed browser test proves application behavior under that run's template and policy. It does not make the visited content or downloaded code trustworthy.
</Warning>
