diff --git a/docs/user/clusters/index.md b/docs/user/clusters/index.md index 089fd4b8..22738e05 100644 --- a/docs/user/clusters/index.md +++ b/docs/user/clusters/index.md @@ -121,6 +121,20 @@ audit entries and threaded into the engine's commit history. Set default when `--as` is omitted (the flag always wins; `approve` requires one of the two). +**`apply` runs out-of-band, with direct storage access — there are no server +routes for it.** Like `init`/`load` and the maintenance verbs (§7), +`cluster apply` reaches the object store directly: it reads and writes the +cluster ledger under `__cluster/` *and* opens each graph's Lance datasets to +create, migrate, or delete them. It never goes through a running +`omnigraph-server`, so the host that runs it (an operator or CI) needs storage +access — the `AWS_*` credential contract for an `s3://` cluster. This is by +design, not a missing feature: the control plane is **declarative** (config → +cluster), not a runtime mutation API on the serving process — intent lives in +the config files, outside the running system (the reasoning is +[cluster-axioms.md](../../dev/cluster-axioms.md) §3 and §4). The server only ever +*reads* the converged ledger, which is why a held apply lock never blocks +serving (see §5 below, in this guide). + What each change kind does: | You edit | Plan shows | Apply does | diff --git a/skills/omnigraph/SKILL.md b/skills/omnigraph/SKILL.md index 7bf044a0..ede18324 100644 --- a/skills/omnigraph/SKILL.md +++ b/skills/omnigraph/SKILL.md @@ -295,7 +295,7 @@ A graph's bytes live in one of two backends: set -a && source .env.omni && set +a ``` -`init` and `load` write storage directly (bypassing the server); the server reads from it. Validate with `curl http://127.0.0.1:8080/healthz`, then `omnigraph snapshot --json`. +`init`, `load`, and **`cluster apply`** write storage directly (bypassing the server). `cluster apply` is a storage-direct control-plane command — it reaches the object store directly (the `__cluster/` ledger *and* each graph's Lance datasets, to create/migrate/delete them), never through a running server, so the host that runs it needs storage access (the `AWS_*` contract for an `s3://` cluster). That is by design: the control plane is declarative (config → cluster), not a runtime mutation API on the serving process. The server reads **cluster** state read-only at boot, but it is not read-only against storage overall — data-plane HTTP writes (`mutate`/`load`/`branch`) still go through the server to the graph datasets, so it needs read-write storage access. Validate with `curl http://127.0.0.1:8080/healthz`, then `omnigraph snapshot --json`. ## Project Layout