---
title: "Orleans.Lattice.Api.Schema API reference"
url: "https://nsta1.github.io/Orleans.Lattice/docs/lattice.api.schema/api.html"
source: "https://github.com/NSTA1/Orleans.Lattice/blob/release/9.9/docs/lattice.api.schema/api.md"
package: "Orleans.Lattice.Api.Schema"
version: "9.9.0"
documents: "Orleans.Lattice 9.9.0 (release line 9.9)"
built: "2026-10-04"
all-pages: "https://nsta1.github.io/Orleans.Lattice/llms.txt"
bundle: "https://nsta1.github.io/Orleans.Lattice/docs/lattice.api.schema/llms-full.txt"
---
# Orleans.Lattice.Api.Schema API reference

Part of the [Api.Schema documentation](README.md).

The public surface is the registration extension, the options type, and the control facade interface (`ILatticeSchemaControl`, published in the shared `Orleans.Lattice.Api.Abstractions` package under the `Orleans.Lattice.Api.Schema` namespace, alongside its `LatticeSchemaCapabilities` result and the `ApiSchemaTypeAliases` alias table). The facade interface is the contract the gRPC binding adapts over, and is described by its operations below and in [Architecture](architecture.md).

The schema policy, versioning, dead-letter, remediation, compliance, and transform records are defined in [`Orleans.Lattice.Schema`](../lattice.schema/README.md). This package adds the control facade and its capability result, not a second schema model.

## Registration

### `LatticeApiSchemaServiceCollectionExtensions`

Static extension method on `ISiloBuilder`.

- `ISiloBuilder AddLatticeSchemaApi(this ISiloBuilder builder, Action<LatticeApiSchemaOptions>? configure = null)`

  Adds the transport-agnostic schema-management control facade: binds `LatticeApiSchemaOptions`, registers the internal silo singleton that every transport binding adapts over, and an idempotency marker. Adds no transport behaviour of its own. Must be called after `AddLatticeSchemaEnforcement(...)`; throws `InvalidOperationException` when called first. Throws `ArgumentNullException` when `builder` is null. Idempotent.

## Options

### `LatticeApiSchemaOptions`

The options type reserved for future read-bounding and audit-tuning knobs, mirroring the sibling control-API facades. See [Configuration](configuration.md) for defaults.

It currently has no tunable properties.

## Facade operations

Every `treeId` these operations accept is a **tenant-local name**: the facade resolves it to its effective, tenant-scoped id through `ITenantContextResolver.ResolveEffectiveTreeIdAsync` at the entry point and uses that one id for **both** the authorization check and the operation, so a verb can never authorize one tree and act on another. With the tenancy add-on absent - or registered, but with no active tenant asserted, which resolves the default tenant - the bare name is returned unchanged, so behaviour is byte-for-byte as before. Under an asserted active tenant an unqualified name is scoped into that tenant's `t/{tenant}/{name}` namespace, and an already-qualified `t/` id or a `_lattice_` system-tree name passes through unchanged (a well-formed foreign `t/{other}/{name}` is left to the tenancy access gate to adjudicate). The call fails closed with a `LatticeTenantAccessDeniedException` when the asserted tenant fails validation against the caller's own membership, or when it names a `sys-` tree or a malformed `t/` id that belongs to no tenant. See [`Orleans.Lattice.Tenancy`](../lattice.tenancy/README.md). Results that name a tree carry the effective id rather than echoing the caller's name: under an asserted non-default tenant the `TreeId` of a `LatticeSchemaCapabilities` or `LatticeSchemaComplianceReport` result is the tenant-scoped `t/{tenant}/{name}` id.

The control facade exposes these methods. Each method corresponds to one RPC in the [gRPC binding](../lattice.api.schema.grpc/api.md), with `ListDeadLettersAsync` projected as the server-streaming `StreamDeadLetters` RPC. Every facade method authorizes its tree scope fail-closed before touching the admin plane.

| Method | Signature |
|---|---|
| `SetPolicyAsync` | `Task SetPolicyAsync(string treeId, LatticeSchemaPolicy policy, CancellationToken cancellationToken = default)` |
| `ClearPolicyAsync` | `Task<bool> ClearPolicyAsync(string treeId, CancellationToken cancellationToken = default)` |
| `GetPolicyAsync` | `Task<LatticeSchemaPolicy?> GetPolicyAsync(string treeId, CancellationToken cancellationToken = default)` |
| `ListDeadLettersAsync` | `IAsyncEnumerable<LatticeSchemaDeadLetterEntry> ListDeadLettersAsync(string treeId, CancellationToken cancellationToken = default)` |
| `CountDeadLettersAsync` | `Task<int> CountDeadLettersAsync(string treeId, CancellationToken cancellationToken = default)` |
| `SetVersionConfigAsync` | `Task SetVersionConfigAsync(string treeId, LatticeSchemaVersionConfig config, CancellationToken cancellationToken = default)` |
| `GetVersionConfigAsync` | `Task<LatticeSchemaVersionConfig?> GetVersionConfigAsync(string treeId, CancellationToken cancellationToken = default)` |
| `AdvanceTargetVersionAsync` | `Task<LatticeSchemaVersionConfig> AdvanceTargetVersionAsync(string treeId, uint newTargetVersion, CancellationToken cancellationToken = default)` |
| `AdvanceAndMigrateAsync` | `Task<LatticeSchemaRemediationReport> AdvanceAndMigrateAsync(string treeId, uint newTargetVersion, CancellationToken cancellationToken = default)` |
| `MigrateToTargetVersionAsync` | `Task<LatticeSchemaRemediationReport> MigrateToTargetVersionAsync(string treeId, CancellationToken cancellationToken = default)` |
| `ClearVersionConfigAsync` | `Task<bool> ClearVersionConfigAsync(string treeId, CancellationToken cancellationToken = default)` |
| `RemediateAsync` | `Task<LatticeSchemaRemediationReport> RemediateAsync(string treeId, LatticeValueTransform transform, LatticeSchemaPolicy targetPolicy, CancellationToken cancellationToken = default)` |
| `GetRemediationStatusAsync` | `Task<LatticeSchemaRemediationReport> GetRemediationStatusAsync(string treeId, CancellationToken cancellationToken = default)` |
| `ScanComplianceAsync` | `Task<LatticeSchemaComplianceReport> ScanComplianceAsync(string treeId, CancellationToken cancellationToken = default)` - deprecated (`LATTICE0002`); use `ILatticeSchemaComplianceOperations` |
| `ProbeCapabilitiesAsync` | `Task<LatticeSchemaCapabilities> ProbeCapabilitiesAsync(string treeId, CancellationToken cancellationToken = default)` |

Policy operations manage a tree's write-validation policy. `SetPolicyAsync` and `ClearPolicyAsync` require SchemaAdmin authority; `GetPolicyAsync` requires Read authority. Once authorized, `SetPolicyAsync` compiles the policy before storing it and refuses one it cannot compile - a rule incomplete for its kind, a regex the non-backtracking engine rejects, or a `MaxByteLength` encoding rule with a negative limit - with an `ArgumentException`, storing nothing. The policy type and its enforcement semantics are defined in [`Orleans.Lattice.Schema`](../lattice.schema/README.md).

Dead-letter operations inspect diverted, schema-rejected writes. `ListDeadLettersAsync` streams entries with bounded memory and `CountDeadLettersAsync` returns the current count. Both require Read authority.

Versioning operations require the separate schema-versioning add-on. If the host did not register `AddLatticeSchemaVersioning(...)`, these calls throw a clear `InvalidOperationException` rather than failing dependency resolution. Reads require Read authority; mutations require SchemaAdmin authority. The config and migration semantics are defined in [`Orleans.Lattice.Schema`](../lattice.schema/README.md).

Remediation operations apply or report a tree-wide repair. `RemediateAsync` requires SchemaAdmin authority, applies a `LatticeValueTransform` across a tree, and adopts the supplied target policy. `GetRemediationStatusAsync` requires Read authority and returns the status or last report; it never waits behind a running remediation, and it names the tracked operation that started the run in its `OperationId`.

`RemediateAsync`, `MigrateToTargetVersionAsync` and `AdvanceAndMigrateAsync` are **deprecated** (`LATTICE0002`) and will be removed in the next major version. They block until the run ends, so a long run is cut off by the caller's timeout. The same singleton implements `ILatticeSchemaOperations`, whose start verbs return as soon as the run is accepted and whose status verbs report its phase and values processed:

| Method | Signature |
|---|---|
| `StartRemediationAsync` | `Task<LatticeOperationHandle> StartRemediationAsync(string treeId, LatticeValueTransform transform, LatticeSchemaPolicy targetPolicy, string? operationId = null, CancellationToken cancellationToken = default)` |
| `StartMigrationAsync` | `Task<LatticeOperationHandle> StartMigrationAsync(string treeId, string? operationId = null, CancellationToken cancellationToken = default)` |
| `StartAdvanceAndMigrateAsync` | `Task<LatticeOperationHandle> StartAdvanceAndMigrateAsync(string treeId, uint newTargetVersion, string? operationId = null, CancellationToken cancellationToken = default)` |
| `GetOperationStatusAsync` | `Task<LatticeOperationStatus?> GetOperationStatusAsync(string operationId, CancellationToken cancellationToken = default)` |
| `ListOperationsAsync` | `Task<LatticeOperationPage> ListOperationsAsync(LatticeOperationListRequest request, CancellationToken cancellationToken = default)` |
| `CancelOperationAsync` | `Task<LatticeOperationStatus?> CancelOperationAsync(string operationId, CancellationToken cancellationToken = default)` |

See [Schema operations](operations.md) for the kinds, phases, outcomes, scoping and the migration from the blocking verbs.

Scan compliance is read-only. It scans a tree's entries against the cached compiled policy and reports per-tree compliant and non-compliant counts plus a reason breakdown; when no policy is set, it returns the ungoverned report (`HasPolicy` is `false` and every count is zero). It never mutates values or policy. The blocking `ScanComplianceAsync` is deprecated (`LATTICE0002`, removed in the next major version) because a large scan outlasts the caller's timeout; start the scan with `ILatticeSchemaComplianceOperations` instead (below).

Probe capabilities has no side effects. It performs two fail-closed probes, Read and SchemaAdmin, and maps them to capability flags. The result is advisory only: every real operation still performs its own authorization immediately before touching data.

## Compliance-scan operations

### `ILatticeSchemaComplianceOperations`

The accept-then-poll compliance scan, published in `Orleans.Lattice.Api.Abstractions` under the `Orleans.Lattice.Api.Schema` namespace and registered by `AddLatticeSchemaApi`. It extends the shared `ILatticeOperations` read-and-cancel surface, scoped to the `schema.compliance-scan` kind, the caller's tenant and the trees the caller may read. See [Schema compliance operations](operations.md) for the phases, units, result keys and the migration from the blocking scan.

| Method | Signature |
|---|---|
| `StartComplianceScanAsync` | `Task<LatticeOperationHandle> StartComplianceScanAsync(string treeId, string? operationId = null, CancellationToken cancellationToken = default)` |
| `GetOperationStatusAsync` | `Task<LatticeOperationStatus?> GetOperationStatusAsync(string operationId, CancellationToken cancellationToken = default)` |
| `ListOperationsAsync` | `Task<LatticeOperationPage> ListOperationsAsync(LatticeOperationListRequest request, CancellationToken cancellationToken = default)` |
| `CancelOperationAsync` | `Task<LatticeOperationStatus?> CancelOperationAsync(string operationId, CancellationToken cancellationToken = default)` |

The kind, phase and unit names are the `SchemaComplianceScanOperation` constants and the result keys and `TryReadReport` are on `SchemaComplianceScanResults`, both in [`Orleans.Lattice.Schema`](../lattice.schema/README.md).

## Model records

### `LatticeSchemaCapabilities`

The allowed-operation set the read-only capability probe reports for one tree. Every flag is default-deny (`false` means "not known to be permitted"), and the flags are advisory: the server still authorizes each real operation fail-closed. The probe distinguishes the two authorization grants the access gate models - Read and SchemaAdmin - so read-only flags move together and administrative flags move together.

- `string TreeId` - the tree id these capabilities were evaluated over: the effective id the facade resolved the caller's name to, which under an asserted non-default tenant is the tenant-scoped `t/{tenant}/{name}` id.
- `bool CanViewPolicy` - whether the caller may read the tree policy.
- `bool CanViewDeadLetters` - whether the caller may read the tree's dead-letter entries.
- `bool CanViewVersionConfig` - whether the caller may read the tree's version config.
- `bool CanViewRemediationStatus` - whether the caller may read remediation status for the tree.
- `bool CanScanCompliance` - whether the caller may run a read-only compliance audit.
- `bool CanManagePolicy` - whether the caller may set or clear the tree policy.
- `bool CanManageVersion` - whether the caller may set, advance, migrate, or clear the version config.
- `bool CanRemediate` - whether the caller may run remediation for the tree.

### `ApiSchemaTypeAliases`

A public static class (also in `Orleans.Lattice.Api.Abstractions`, namespace `Orleans.Lattice.Api.Schema`) holding the stable `ois.`-prefixed Orleans serialization aliases of the control-API contract types: `AliasPrefix` and the `LatticeSchemaCapabilities` alias.

The DTO types `LatticeSchemaPolicy`, `LatticeSchemaVersionConfig`, `LatticeSchemaDeadLetterEntry`, `LatticeSchemaRemediationReport`, `LatticeSchemaComplianceReport`, and `LatticeValueTransform` are defined in [`Orleans.Lattice.Schema`](../lattice.schema/README.md).
