# Build a multi-tenant platform

This recipe releases a bounded game-server control plane whose customers can
create instances only inside the capabilities and artifacts admitted by that
release.

The `.one` and Rust APIs below are illustrative end-product syntax.

## 1. Separate product choice from infrastructure

```one
one 1

semantic games.product
    domain one.contracts@1
    struct ServerOffering@1
        distribution: DistributionId
        version: Version
        plan: ServerPlan
        extensions: Set<ExtensionId>(maximum: 20)

    operation CreateServer@1
        input CreateServerRequest
        output GameServer
        faults [OfferingUnavailable, QuotaExceeded]
        effect create(game_server)
        authority tenant_server:create
```

Minecraft, a mod set, or another distribution is product/runtime meaning. An
OCI or Kubernetes host is a physical realization. Rust or TypeScript is an
implementation-language choice. The contract does not collapse those axes.

## 2. Bound the released catalog

```one
semantic games.control_plane
    domain one.components@1
    application GameControlPlane@1
        root api
        operation CreateServer

        catalog offerings
            allow Vanilla version "1.22" plans [Small, Medium]
            allow Paper version "1.22" plans [Medium, Large]
        quota servers_per_tenant 10
        quota storage_per_tenant gib(200)
        budget monthly_per_tenant eur(250)
```

The released closure contains every distribution artifact, extension family,
host capability, grant shape, and bound required by those choices. Package
installation outside that closure does not expand the customer catalog.

## 3. Create an instance inside the envelope

```rust,ignore
pub async fn create_server(
    ctx: CreateServer,
    request: CreateServerRequest,
) -> Result<GameServer, CreateServerFault> {
    let offering = ctx.catalog().require(request.offering)?;
    ctx.quotas().reserve(request.tenant_id, offering.resources()).await?;

    ctx.instances().create(InstanceIntent {
        tenant: request.tenant_id,
        offering,
        name: request.name,
    }).await
}
```

The customer request creates a managed instance through an already selected
binding. It cannot discover a provider, invoke the One CLI, select an unplanned
artifact, replace an Authority epoch, or widen the release envelope.

## 4. Isolate every tenant dimension

```text
tenant identity
  -> names and instance identities
  -> data partition and encryption context
  -> secrets and runtime grants
  -> quotas, budgets, and rate limits
  -> logs, observations, backups, and erasure
```

A tenant label is not used as an ambient authorization key. Every lookup
resolves an owner-qualified instance identity and checks current authority.

## 5. Reconcile customer-visible operations

```rust,ignore
match ctx.instances().create(intent).await {
    CreateResult::Ready(instance) => Ok(instance),
    CreateResult::Rejected(reason) => Err(reason.into()),
    CreateResult::OutcomeUnknown(operation) => {
        Ok(ctx.instances().reconcile(operation).await?)
    }
}
```

Provisioning, restart, backup, restore, upgrade, and deletion retain durable
intent, attempts, provider observations, receipts, and tenant-visible recovery
state.

See [multi-tenant platforms](/one/guides/multi-tenant-platforms) and
[deployment](/one/platform/deployment).
