---
title: "Bootstrap Control State"
url: "https://docs.caracal.run/v1.0/examples/control-bootstrap/"
markdown_url: "https://docs.caracal.run/markdown/v1.0/examples/control-bootstrap.md"
description: "Keep an agent environment in sync with a declared plan through a scoped Control API automation key."
page_type: "workflow"
concepts: []
requires: []
---

# Bootstrap Control State

Canonical URL: https://docs.caracal.run/v1.0/examples/control-bootstrap/
Markdown URL: https://docs.caracal.run/markdown/v1.0/examples/control-bootstrap.md
Description: Keep an agent environment in sync with a declared plan through a scoped Control API automation key.
Page type: workflow
Concepts: none
Requires: none

---

Control Bootstrap is the canonical Control API automation example in the [Caracal examples repository](https://github.com/Garudex-Labs/examples) under `controlBootstrap/`. A small CI/CD-style pipeline keeps one workload environment - Application, Provider, Resource, and Policy - matching a declared plan without adding product-management verbs to the runtime CLI.

## When to use it

Use it when CI must reconcile objects inside one existing zone through scoped Control credentials. Use the Admin SDK from a trusted operator environment when automation must create zones or use management surfaces not exposed by Control.

## Prerequisites

* A ready runtime and existing target zone.
* Separate Control keys for apply, verify, and teardown with only documented scopes.
* A reviewed plan containing no production secrets.

## What it demonstrates

| Area               | Behavior                                                                                                    |
| ------------------ | ----------------------------------------------------------------------------------------------------------- |
| Automation surface | Calls `/v1/control/invoke` instead of using a root admin token.                                             |
| Identity model     | Uses scoped, short-lived control keys created in the web console, one scope tier per pipeline stage.        |
| Reconciliation     | `apply` creates missing objects, patches drifted ones, and publishes a new policy version on content drift. |
| CI gating          | `verify` is a read-only drift check that exits non-zero when the zone does not match the plan.              |
| Safety model       | Uses replay protection, rate limits, scoped control permissions, and audit.                                 |

The plan describes the PiperNet reporter's environment: its Application, the `provider://pipernet-mandate` Provider, the `resource://pipernet` Resource wired to it, and the baseline Policy that allows `read`.

## Web Console Setup

1. Start the runtime and open the web console:

   ```bash
   caracal up
   caracal status --ready
   ```

   Open the packaged web console at `http://localhost:3001`.

2. Create or select the target zone.

3. Create a control key with only the scopes the stage needs: read/write on app, provider, resource, and policy for `apply`; read for `verify`; read/delete for `teardown`.

4. Save the `client_id` and `client_secret`. STS resolves the zone from the bound control key; the secret stays retrievable from **Services → Control** through an audited reveal.

## Run the pipeline

```bash
git clone https://github.com/Garudex-Labs/examples.git caracal-examples
cd caracal-examples/controlBootstrap
cp env.example .env
$EDITOR .env
. .env
npm run apply
npm run verify
```

`apply` is idempotent: rerunning it against an in-sync zone changes nothing, and rerunning it against a drifted zone converges the drift. Run teardown when you want to remove the environment:

```bash
npm run teardown
```

## Files to study

| File                | Purpose                                                                             |
| ------------------- | ----------------------------------------------------------------------------------- |
| `controlClient.mjs` | Exchanges client credentials at STS and calls the Control API.                      |
| `plan.mjs`          | Declares the desired environment, drift checks, scope tiers, and env-driven config. |
| `apply.mjs`         | Reconciles the live zone with the plan.                                             |
| `verify.mjs`        | Read-only drift gate for CI.                                                        |
| `teardown.mjs`      | Removes the environment in reverse dependency order.                                |

## Test

```bash
cd caracal-examples/controlBootstrap
npm test
```

The tests use a fake zone and mock transport and do not call a live Caracal stack.

## Validate the workflow

Run `apply` twice, then `verify`, introduce one safe drift, and run `verify` again. Expect no second write on unchanged apply, a clean verification, then a non-zero drift result. Teardown must remove objects in dependency order without affecting objects outside the plan.

:::caution[Failure point: credential boundary]
Never give the example a root admin token or application credential. Control keys are zone-bound automation credentials; keep each pipeline stage least-privileged and short-lived.
:::

## Next Step

Continue to [Check Provider Readiness](/v1.0/examples/provider-preflight/) before sending traffic through a provider-backed Gateway resource.
