> ## Documentation Index
> Fetch the complete documentation index at: https://smithers-feat-claude-workflow-mirror.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Control Plane

> Organization, project, identity, billing, usage, secret-reference, and audit primitives for hosted Smithers deployments.

The control-plane package adds a durable SQLite store for multi-tenant objects: orgs, projects, teams, billing records, usage, secret references, and audit events. Import it alongside the Gateway when you need these boundaries.

## ControlPlaneStore API

Import the store from the public facade:

```ts theme={null}
import { ControlPlaneStore } from "smithers-orchestrator/control-plane";
```

Or from the scoped package:

```ts theme={null}
import { ControlPlaneStore } from "@smithers-orchestrator/control-plane";
```

The store creates SQLite tables for:

* organizations
* teams and team membership
* projects and project team grants
* billing account records
* identity-provider records for SAML/OIDC configuration
* usage events, summaries, and quota checks
* secret manager references, not secret values
* audit events and org audit export

Constructing `new ControlPlaneStore(sqlite)` calls `ensureControlPlaneTables(sqlite)`. You can call `ensureControlPlaneTables(sqlite)` directly when you only need to bootstrap the schema.

## Store Methods

| Method                     | Purpose                                                                                                                    |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `createOrg()`              | Create an organization.                                                                                                    |
| `getOrg()`                 | Load an organization by ID.                                                                                                |
| `createTeam()`             | Create a team in an organization.                                                                                          |
| `addTeamMember()`          | Add or update a user's team role.                                                                                          |
| `createProject()`          | Create a project in an organization.                                                                                       |
| `addProjectTeam()`         | Grant or update a team's project role.                                                                                     |
| `upsertBillingAccount()`   | Create or update the org billing record.                                                                                   |
| `upsertIdentityProvider()` | Create or update a SAML/OIDC identity provider record.                                                                     |
| `listIdentityProviders()`  | List org identity providers, optionally filtered by status.                                                                |
| `recordUsage()`            | Append a usage event.                                                                                                      |
| `summarizeUsage()`         | Aggregate usage by metric and unit for an org.                                                                             |
| `setUsageLimit()`          | Create or update an org/project usage limit.                                                                               |
| `checkUsageLimit()`        | Return the matching limit plus `usedQuantity`, `remainingQuantity`, and `exceeded`, or `null` when no limit is configured. |
| `putSecretRef()`           | Store an external secret reference, not the secret value.                                                                  |
| `listSecretRefs()`         | List org or project secret references.                                                                                     |
| `recordAuditEvent()`       | Append an audit event.                                                                                                     |
| `exportOrgAudit()`         | Export org data, usage summaries, secret refs, and audit events.                                                           |

```ts theme={null}
const store = new ControlPlaneStore(sqlite);

// Required: create the org and at least one project before recording any data.
const org = store.createOrg({
  orgId: "org_acme",
  slug: "acme",
  name: "Acme",
});

const project = store.createProject({
  orgId: org.orgId,
  projectId: "project_app",
  slug: "app",
  name: "App",
});

// Optional: record a usage event and set a quota for a metric.
store.recordUsage({
  orgId: org.orgId,
  projectId: project.projectId,
  runId: "run_123",
  metric: "agent_runtime_ms",
  quantity: 42_000,
  unit: "ms",
});

store.setUsageLimit({
  orgId: org.orgId,
  projectId: project.projectId,
  metric: "agent_runtime_ms",
  unit: "ms",
  period: "monthly",
  limitQuantity: 10_000_000,
});
// period must be "daily", "weekly", or "monthly"; checkUsageLimit uses it
// as the default rolling window when sinceMs is omitted.

// Optional: register a SAML or OIDC provider for the org.
store.upsertIdentityProvider({
  orgId: org.orgId,
  providerId: "idp_okta",
  type: "saml",
  issuer: "https://acme.okta.com",
  ssoUrl: "https://acme.okta.com/app/smithers/sso/saml",
  certificateRef: "vault://identity/acme-okta-cert",
});

// Optional: store a reference to a secret in an external provider (not the value).
store.putSecretRef({
  orgId: org.orgId,
  projectId: project.projectId,
  name: "deploy-token",
  provider: "aws-secrets-manager",
  ref: "arn:aws:secretsmanager:us-east-1:123:secret:deploy",
});

// Check whether recorded project usage exceeds the configured limit.
const quota = store.checkUsageLimit({
  orgId: org.orgId,
  projectId: project.projectId,
  metric: "agent_runtime_ms",
  unit: "ms",
  period: "monthly",
});
// quota is null when no matching limit exists; otherwise it includes
// { usedQuantity, remainingQuantity, exceeded, limitQuantity, ...limitMetadata }.
// `period` is a label used to match a configured limit; `checkUsageLimit()` does not reset usage automatically for calendar periods.
// Pass sinceMs/untilMs when you need the used quantity scoped to a billing or reporting window.

const audit = store.exportOrgAudit({ orgId: org.orgId });
```

Deleting an org cascades to all its child rows: projects, teams, identity providers, billing account, usage rows, usage limits, secret references, and audit rows. There is no soft-delete; use a status flag in your application layer if you need recoverable deletion.

## Hosted Boundary

A hosted Smithers service should layer these primitives behind:

* SSO/SAML or OIDC authentication
* billing provider checkout and invoices
* cloud object storage for large artifacts
* managed secret provider reads at worker runtime
* audit export delivery and retention policy
* SLAs, support, compliance controls, and incident response

The open-source package owns the durable data contract. The hosted service owns identity, payment collection, tenant isolation, compliance operations, and infrastructure support.
