mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-18 02:24:27 +02:00
feat!: delete the legacy OmnigraphConfig + config migrate; finish the omnigraph.yaml docs sweep (#252)
* refactor(cli): own ReadOutputFormat/TableCellLayout in the CLI The two output-presentation enums lived in `omnigraph-server::config` and were re-exported for the CLI, even though the server never used them. Move both definitions into `omnigraph-cli/src/read_format.rs` (where the renderer already lives) and drop them from the server's public re-export. This is a step toward deleting the legacy `omnigraph-server::config` module entirely — a CLI presentation concern has no business in the server crate. No behavior change. The server keeps private copies in `config.rs` only for the soon-to-be-deleted legacy `CliDefaults`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(cli)!: remove the `config migrate` command and migrate.rs `config migrate` was the last CLI consumer of the legacy `omnigraph.yaml` (`OmnigraphConfig` + `load_config`). With the excision complete there is no legacy file to split, so the whole `omnigraph config` command group is removed along with `migrate.rs`. The `OmnigraphConfig` type, `load_config`, and the deprecation machinery are deleted next. - Remove `Command::Config` / `ConfigCommand` from the clap surface and the dispatch arm; drop `mod migrate;` and the now-unused `load_config` import. - Drop the `Command::Config` arms in `planes.rs`. - Delete the `config_migrate_splits_legacy_config` integration test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(server)!: delete the legacy OmnigraphConfig type and load_config With `config migrate` gone, nothing loads `omnigraph.yaml` anymore. Delete the entire `omnigraph-server::config` module: the `OmnigraphConfig` type and its sub-structs (`ProjectConfig`, `TargetConfig`, `CliDefaults`, `ServerDefaults`, `AuthDefaults`, `QueryDefaults`, `AliasConfig`, `AliasCommand`, `PolicySettings`, `QueryEntry`, `McpSettings`), `load_config`, and the RFC-008 deprecation machinery (`OMNIGRAPH_CONFIG`, `OMNIGRAPH_NO_LEGACY_CONFIG`, `OMNIGRAPH_SUPPRESS_YAML_DEPRECATION`, the deprecation map + warner). - `QueryRegistry::load` (the only `OmnigraphConfig`/`QueryEntry` consumer; its only caller was its own test) is removed — server boot and the CLI both build registries via `QueryRegistry::from_specs`. - `graph_resource_id_for_selection` (CLI-only) moves into the CLI (`helpers.rs`), with its unit test; the server no longer exports it. - Drop the already-dead `format_registry_load_errors` helper (config-adjacent). No behavior change — every deleted item was unreachable after the excision. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs: purge the legacy omnigraph.yaml surface from the docs Finish the RFC-011 excision in the docs: the CLI no longer reads omnigraph.yaml and the server boots cluster-only, so every doc that described the legacy file as a live config is now wrong. - AGENTS.md: rewrite the HTTP-server line to cluster-only boot (drop the single-graph/flat-route and omnigraph.yaml-boot framing); rewrite the CLI two-surface-config passage (drop `config migrate`, the deprecation env vars, and "Never extend omnigraph.yaml"); fix the topic table + capability rows. - cli/reference.md: delete the entire "omnigraph.yaml schema (legacy combined file)" section and the `config migrate` row; re-home the `policy` row, the bearer-token chain, the actor/format/param-precedence references, and the `--config` mentions to the operator config + `--cluster`. - cli/index.md: rewrite the multi-graph-server + add-graph paragraphs to cluster (`--cluster` + `cluster apply`); fix the policy examples to `--cluster`; replace the `## Config` omnigraph.yaml example with the operator/cluster two-surface model. - operations/policy.md: rewrite per-graph-vs-server-level policy to the cluster `policies:`/`applies_to` model; re-home the actor + CLI tooling sections. - clusters/config.md, clusters/index.md, deployment.md: server boots from the cluster only; per-operator facts come from ~/.omnigraph/config.yaml. - architecture.md, testing.md: drop the stale omnigraph.yaml / deleted-test references. RFCs, design specs, and prior release notes are left as historical records. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
0bee746a31
commit
4601e5f4bf
20 changed files with 177 additions and 1950 deletions
|
|
@ -78,20 +78,26 @@ literal URL); a positional `http(s)://` URI is rejected. If the server requires
|
|||
auth, set its bearer token and `omnigraph login <server>` (or
|
||||
`OMNIGRAPH_BEARER_TOKEN`).
|
||||
|
||||
## Multi-graph servers (v0.6.0+)
|
||||
## Multi-graph servers
|
||||
|
||||
Against a multi-graph server (started with `--config omnigraph.yaml` referencing a non-empty `graphs:` map), use `omnigraph graphs list` to enumerate the registered graphs. The server must configure bearer tokens and `server.policy.file` with a rule that allows `graph_list`; `/graphs` is closed by default even when the server runs with `--unauthenticated`.
|
||||
A server boots from a cluster directory (`omnigraph-server --cluster <dir>`) and
|
||||
serves every graph the cluster declares. Use `omnigraph graphs list` to enumerate
|
||||
them. The cluster's server-level policy must allow `graph_list`; `/graphs` is
|
||||
closed by default even when the server runs with `--unauthenticated`.
|
||||
|
||||
```bash
|
||||
OMNIGRAPH_BEARER_TOKEN=admin-token \
|
||||
omnigraph graphs list --uri http://server.example.com --json
|
||||
omnigraph graphs list --server http://server.example.com --json
|
||||
```
|
||||
|
||||
For config-driven clients, set the remote graph's `bearer_token_env` to an environment variable containing a token whose actor is authorized by `server.policy.file`.
|
||||
For an operator-defined server, store its token with `omnigraph login <name>` (or
|
||||
`OMNIGRAPH_TOKEN_<NAME>`); the actor must be authorized by the cluster's
|
||||
server-level policy.
|
||||
|
||||
`list` rejects local URI targets — it's for remote multi-graph servers only.
|
||||
`list` rejects local (`--store`) targets — it's for remote multi-graph servers only.
|
||||
|
||||
Runtime add/remove is **not** in v0.6.0. To add a graph, stop the server, add a `graphs.<id>` entry to `omnigraph.yaml`, then restart. To remove, stop the server, delete the entry, restart.
|
||||
Runtime add/remove via API is not exposed. To add or remove a graph, edit the
|
||||
cluster's `cluster.yaml`, run `omnigraph cluster apply`, then restart the server.
|
||||
|
||||
Per-graph addressing: select a graph on a multi-graph server with `--graph`:
|
||||
|
||||
|
|
@ -107,9 +113,9 @@ omnigraph check --query queries.gq graph.omni --json
|
|||
|
||||
omnigraph schema plan --schema next.pg graph.omni --json
|
||||
omnigraph schema apply --schema next.pg graph.omni --json
|
||||
omnigraph policy validate --config omnigraph.yaml
|
||||
omnigraph policy test --config omnigraph.yaml
|
||||
omnigraph policy explain --config omnigraph.yaml --actor act-alice --action read --branch main
|
||||
omnigraph policy validate --cluster ./company-brain --graph knowledge
|
||||
omnigraph policy test --cluster ./company-brain --graph knowledge --tests policy.tests.yaml
|
||||
omnigraph policy explain --cluster ./company-brain --graph knowledge --actor act-alice --action read --branch main
|
||||
|
||||
omnigraph commit list graph.omni --json
|
||||
omnigraph commit show --uri graph.omni <commit-id> --json
|
||||
|
|
@ -123,34 +129,29 @@ also pass `--schema`.
|
|||
|
||||
## Config
|
||||
|
||||
`omnigraph.yaml` lets the CLI and server share named graphs, defaults, and
|
||||
query roots:
|
||||
Configuration has two surfaces with single owners (see the
|
||||
[CLI reference](reference.md#config-surfaces) for the full schema):
|
||||
|
||||
- **`~/.omnigraph/config.yaml`** — your personal operator config: default actor
|
||||
(`--as`), named servers + credentials, clusters, profiles, aliases, and
|
||||
default scope (`defaults.server` / `defaults.store` / `default_graph`). It
|
||||
decides *who you are* and *what you address by default*.
|
||||
- **`cluster.yaml`** (a team-owned cluster directory) — declares *what the system
|
||||
is*: graphs, schemas, stored queries, policies, and storage. A server boots
|
||||
from it (`--cluster <dir>`); see the [cluster guide](../clusters/index.md).
|
||||
|
||||
```yaml
|
||||
graphs:
|
||||
local:
|
||||
uri: demo.omni
|
||||
# ~/.omnigraph/config.yaml
|
||||
operator:
|
||||
actor: act-andrew
|
||||
servers:
|
||||
dev:
|
||||
uri: http://127.0.0.1:8080
|
||||
bearer_token_env: OMNIGRAPH_BEARER_TOKEN
|
||||
|
||||
cli:
|
||||
graph: local
|
||||
branch: main
|
||||
|
||||
query:
|
||||
roots:
|
||||
- queries
|
||||
- .
|
||||
url: http://127.0.0.1:8080
|
||||
defaults:
|
||||
server: dev
|
||||
default_graph: knowledge
|
||||
```
|
||||
|
||||
The config file can also define:
|
||||
|
||||
- server bind defaults
|
||||
- auth env files
|
||||
- query aliases for common read and change commands
|
||||
- `policy.file` for Cedar authorization rules
|
||||
|
||||
When policy is enabled, `schema apply` is authorized through the
|
||||
`schema_apply` action and is typically limited to admins on protected `main`.
|
||||
|
||||
|
|
@ -168,6 +169,6 @@ one-line warning to stderr and otherwise behave identically.
|
|||
| `omnigraph query lint` | `omnigraph lint` | Same flags. The argv-level shim rewrites `query lint` to `lint`. |
|
||||
| `omnigraph query check` | `omnigraph check` | `check` is a visible alias of `omnigraph lint`. |
|
||||
|
||||
The `command:` field in `aliases.<name>` in `omnigraph.yaml` accepts both
|
||||
`read` / `change` (legacy) and `query` / `mutate` (canonical); the two
|
||||
The `command:` field in `aliases.<name>` in `~/.omnigraph/config.yaml` accepts
|
||||
both `read` / `change` (legacy) and `query` / `mutate` (canonical); the two
|
||||
spellings are interchangeable on the wire via serde aliases.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# CLI Reference (`omnigraph`)
|
||||
|
||||
A reference for the `omnigraph` binary's command surface and `omnigraph.yaml` schema. For a quick-start guide, see [cli.md](index.md).
|
||||
A reference for the `omnigraph` binary's command surface and the per-operator `~/.omnigraph/config.yaml` schema. For a quick-start guide, see [cli.md](index.md).
|
||||
|
||||
Top-level command families and subcommands. Graph-targeting commands accept a positional `file://`/`s3://` URI, `--server <name|url>` (an operator-defined server from `~/.omnigraph/config.yaml` by name, or a literal `http(s)://` URL, optionally with `--graph <id>` for multi-graph servers; exclusive with a positional URI), `--store <uri>` (a single graph's storage directly), or `--profile <name>` / `$OMNIGRAPH_PROFILE` (a named scope bundle; see [Scopes & profiles](#scopes--profiles-rfc-011)); `cluster` commands use `--config <dir>`. A remote server is addressed only with `--server` — a positional `http(s)://` URI is rejected. **`query`/`mutate` are the exception**: their positional is a stored-query *name* (RFC-011 D3), not a graph URI, so they address the graph only via `--store`/`--server`/`--profile`/defaults.
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ Top-level command families and subcommands. Graph-targeting commands accept a po
|
|||
|
||||
| Command | Purpose |
|
||||
|---|---|
|
||||
| `init` | `--schema <pg>` → initialize a graph (no longer scaffolds `omnigraph.yaml`; start cluster configs from the [cluster.md](../clusters/index.md) quick-start or `config migrate`) |
|
||||
| `init` | `--schema <pg>` → initialize a graph (start cluster configs from the [cluster.md](../clusters/index.md) quick-start) |
|
||||
| `load` | bulk load a branch, local or remote (`--mode overwrite\|append\|merge` is **required** — overwrite is destructive, so there is no default). Without `--from` the target branch must exist; `--from <base>` forks a missing `--branch` from `<base>` first |
|
||||
| `ingest` | deprecated alias of `load --from <base>` (defaults: `--from main --mode merge`); prints a one-line warning to stderr |
|
||||
| `query <name>` (alias: `read`) | run a read query. **Catalog lane** (default): `<name>` is a stored query invoked **by name** from the served catalog (served-only — address with `--server`/`--profile`; the verb asserts the query is a read). **Ad-hoc lane**: with `--query <path>` or `-e`/`--query-string <GQ>`, runs that source (the positional `<name>` then selects which query in it). No positional graph URI — address via `--store`/`--server`/`--profile`. `read` is the deprecated previous name (one-line stderr warning) |
|
||||
|
|
@ -20,13 +20,12 @@ Top-level command families and subcommands. Graph-targeting commands accept a po
|
|||
| `commit list \| show` | inspect commit graph |
|
||||
| `schema plan \| apply \| show (alias: get)` | migrations |
|
||||
| `lint` (alias: `check`) | offline / graph-backed query validation. Replaces `query lint` / `query check`, which are kept as deprecated argv-level shims that print a one-line warning and rewrite to `omnigraph lint` |
|
||||
| `config migrate` | propose (or `--write`: apply) the split of a legacy `omnigraph.yaml` — team half → ready-to-review `cluster.yaml`, personal half → `~/.omnigraph/config.yaml` (key-level merge, existing entries win), plus dropped-key reasons and manual steps |
|
||||
| `cluster validate \| plan \| apply \| approve \| status \| refresh \| import \| force-unlock` | declarative cluster control plane. `validate` checks a local `cluster.yaml` folder and referenced schema/query/policy files; `plan` diffs it against local JSON state at `__cluster/state.json`, annotates dispositions, and embeds real schema-migration previews; `apply` converges the cluster — stored-query/policy catalog writes (content-addressed under `__cluster/resources/`), graph creates, schema updates (soft drops only; `--as` records the actor), and graph deletes behind a digest-bound approval from `cluster approve <resource> --as <actor>` (`apply`/`approve` default the actor from the per-operator `omnigraph.yaml`'s `cli.actor` when `--as` is omitted; nothing else in that file affects cluster commands); what apply converges is what an `omnigraph-server --cluster <dir>` deployment serves on its next restart (`--cluster` is the server's only boot source — RFC-011 cluster-only); `status` reads the state ledger; `refresh`/`import` explicitly update local JSON state from read-only graph observations; `force-unlock <LOCK_ID>` manually removes a held local state lock by exact id |
|
||||
| `cluster validate \| plan \| apply \| approve \| status \| refresh \| import \| force-unlock` | declarative cluster control plane. `validate` checks a local `cluster.yaml` folder and referenced schema/query/policy files; `plan` diffs it against local JSON state at `__cluster/state.json`, annotates dispositions, and embeds real schema-migration previews; `apply` converges the cluster — stored-query/policy catalog writes (content-addressed under `__cluster/resources/`), graph creates, schema updates (soft drops only; `--as` records the actor), and graph deletes behind a digest-bound approval from `cluster approve <resource> --as <actor>` (`apply`/`approve` default the actor from `~/.omnigraph/config.yaml`'s `operator.actor` when `--as` is omitted); what apply converges is what an `omnigraph-server --cluster <dir>` deployment serves on its next restart (`--cluster` is the server's only boot source — RFC-011 cluster-only); `status` reads the state ledger; `refresh`/`import` explicitly update local JSON state from read-only graph observations; `force-unlock <LOCK_ID>` manually removes a held local state lock by exact id |
|
||||
| `optimize` | non-destructive Lance compaction (skips tables with `Blob` columns or uncovered drift; `--json` reports `skipped`) |
|
||||
| `repair [--confirm] [--force]` | preview or explicitly publish uncovered manifest/head drift. `--confirm` heals verified maintenance drift and exits non-zero if suspicious/unverifiable drift is refused; `--force --confirm` publishes suspicious/unverifiable drift after operator review |
|
||||
| `cleanup --keep N --older-than 7d --confirm` | destructive version GC (`--confirm` to execute; also needs `--yes` against a non-local `s3://` target — see *Write diagnostics & destructive confirmation*) |
|
||||
| `embed` | offline JSONL embedding pipeline |
|
||||
| `policy validate \| test \| explain` | Cedar tooling. Selects `cli.graph`, else `server.graph`, else top-level `policy.file` |
|
||||
| `policy validate \| test \| explain` | Cedar tooling against a cluster's applied policies (`--cluster <dir>`; `--graph <id>` picks a graph's bundle when several apply). `test` takes `--tests <file>`; `explain` takes `--actor`/`--action`/`--branch`/`--target-branch` |
|
||||
| `version` / `-v` | print `omnigraph 0.3.x` |
|
||||
|
||||
## Command capabilities
|
||||
|
|
@ -69,21 +68,16 @@ Two config surfaces with single owners, plus a zero-config tier:
|
|||
| Operator config | one person | `~/.omnigraph/config.yaml` (override dir with `$OMNIGRAPH_HOME`) | who **I** am: identity, ergonomics |
|
||||
| Flags / env | per invocation | — | everything, explicitly |
|
||||
|
||||
`omnigraph.yaml` (below) is the legacy combined file — fully supported
|
||||
today, slated for staged deprecation; its keys' future homes are
|
||||
listed there.
|
||||
|
||||
### `~/.omnigraph/config.yaml` (operator)
|
||||
|
||||
```yaml
|
||||
operator:
|
||||
actor: act-andrew # default identity for every --as cascade:
|
||||
# --as > legacy cli.actor > operator.actor > none
|
||||
actor: act-andrew # default identity for the --as cascade: --as > operator.actor > none
|
||||
servers: # operator-owned endpoints; names key the credentials
|
||||
prod:
|
||||
url: https://graph.example.com # no tokens in this file, ever
|
||||
defaults:
|
||||
output: table # read format default, below --json/--format/alias/legacy
|
||||
output: table # read format default, below --json/--format/alias
|
||||
server: prod # the everyday SERVED scope when no address is given (RFC-011)
|
||||
# store: file:///data/dev.omni # OR a zero-flag LOCAL default (mutually
|
||||
# # exclusive with `server`); the local-dev
|
||||
|
|
@ -98,8 +92,8 @@ profiles: # named scope bundles (RFC-011); pick with --profile
|
|||
```
|
||||
|
||||
Absent file = empty layer. Unknown keys warn and load (a file written for a
|
||||
newer CLI works on an older one). `$OMNIGRAPH_CONFIG=<path>` stands in for
|
||||
`--config` (the flag wins) in both the CLI and the server.
|
||||
newer CLI works on an older one). Override the config directory with
|
||||
`$OMNIGRAPH_HOME`.
|
||||
|
||||
#### Scopes & profiles (RFC-011)
|
||||
|
||||
|
|
@ -131,7 +125,7 @@ sticky "current" mode.
|
|||
|
||||
`--target`, `--cluster-graph`, and the positional-`http(s)://`→remote dispatch
|
||||
have been **removed** (`--graph` is now the one graph selector across server and
|
||||
cluster scopes); `omnigraph.yaml`'s `cli.graph` default still works and an
|
||||
cluster scopes); operator `defaults`/`--profile` supply the no-flag scope and an
|
||||
explicit address always wins.
|
||||
|
||||
#### Credentials keyed by server name
|
||||
|
|
@ -164,8 +158,7 @@ aliases:
|
|||
`POST <server>/graphs/spike/queries/weekly_triage` with the keyed
|
||||
credential. Aliases live in their own `alias` namespace (RFC-011 Decision 4),
|
||||
so an alias can never shadow — or be shadowed by — a built-in verb. (The old
|
||||
`--alias <name>` flag on `query`/`mutate` was removed; legacy `omnigraph.yaml`
|
||||
`aliases:` no longer have a CLI entry point.)
|
||||
`--alias <name>` flag on `query`/`mutate` was removed.)
|
||||
|
||||
A remote command whose URL prefix-matches an operator server's `url` (the
|
||||
`gh` host model — no flags needed) resolves its token through:
|
||||
|
|
@ -174,61 +167,10 @@ A remote command whose URL prefix-matches an operator server's `url` (the
|
|||
|---|---|
|
||||
| 1 | `OMNIGRAPH_TOKEN_<NAME>` env (`prod` → `OMNIGRAPH_TOKEN_PROD`) |
|
||||
| 2 | `[<name>]` section in `~/.omnigraph/credentials` |
|
||||
| 3 | the legacy chain unchanged (`bearer_token_env` → `OMNIGRAPH_BEARER_TOKEN` → `auth.env_file`) |
|
||||
| 3 | the default `OMNIGRAPH_BEARER_TOKEN` env |
|
||||
|
||||
A token is only ever sent to the server it is keyed to: URLs matching no
|
||||
operator server use the legacy chain alone.
|
||||
|
||||
## `omnigraph.yaml` schema (legacy combined file)
|
||||
|
||||
> **Deprecated.** Loading this file prints a per-key notice
|
||||
> naming each present key's new home (suppress in CI with
|
||||
> `OMNIGRAPH_SUPPRESS_YAML_DEPRECATION=1`); `omnigraph config migrate`
|
||||
> produces the split. The file keeps working through the deprecation
|
||||
> window. Migrated teams can set `OMNIGRAPH_NO_LEGACY_CONFIG=1` to turn
|
||||
> any legacy-file load into a hard error (regression guard; the file's
|
||||
> absence is always fine).
|
||||
|
||||
```yaml
|
||||
project: { name }
|
||||
graphs:
|
||||
<name>:
|
||||
uri: <local|s3://|http(s)://>
|
||||
bearer_token_env: <ENV_NAME>
|
||||
queries: # per-graph stored-query registry (server-role; multi-graph mode)
|
||||
<query-name>: # key MUST equal the `query <name>` symbol inside the .gq
|
||||
file: <path-to-.gq> # relative to this config's directory
|
||||
mcp:
|
||||
expose: true # default true: listed in the MCP catalog (GET /queries); set false to hide (still HTTP-callable)
|
||||
tool_name: <name> # optional MCP tool-name override (defaults to <query-name>;
|
||||
# must be unique across exposed queries)
|
||||
server:
|
||||
graph: <name>
|
||||
bind: <ip:port>
|
||||
cli:
|
||||
graph: <name>
|
||||
branch: <name>
|
||||
output_format: json|jsonl|csv|kv|table
|
||||
table_max_column_width: 80
|
||||
table_cell_layout: truncate|wrap
|
||||
query:
|
||||
roots: [<dir>, …] # search path for .gq files
|
||||
auth:
|
||||
env_file: .env.omni
|
||||
aliases: # legacy file-aliases — parsed but no longer
|
||||
<alias>: # reachable from the CLI (RFC-011 D4 removed
|
||||
command: read|change|query|mutate # the `--alias` flag). Use operator
|
||||
query: <path-to-.gq> # aliases (`~/.omnigraph/config.yaml`
|
||||
name: <query-name> # `aliases:`) via `omnigraph alias <name>`.
|
||||
args: [<positional-name>, …]
|
||||
graph: <name>
|
||||
branch: <name>
|
||||
format: <output-format>
|
||||
queries: # top-level registry — applies only to a bare-URI (anonymous) graph; a graph served by name uses its `graphs.<id>.queries`. Mirrors top-level `policy`.
|
||||
<query-name>: { file: <path-to-.gq> } # mcp.expose defaults to true
|
||||
policy:
|
||||
file: policy.yaml
|
||||
```
|
||||
A keyed token is only ever sent to the server it is keyed to: a URL matching no
|
||||
operator server falls back to `OMNIGRAPH_BEARER_TOKEN` alone.
|
||||
|
||||
## Cluster config preview
|
||||
|
||||
|
|
@ -251,8 +193,8 @@ apply, refresh, and import acquire `__cluster/lock.json` by default and release
|
|||
it before returning. `cluster apply` executes only stored-query/policy catalog
|
||||
writes (content-addressed under `__cluster/resources/`) and requires an
|
||||
existing `state.json`; graph/schema changes are deferred with warnings, and
|
||||
applied resources do not serve traffic — the server still boots from
|
||||
`omnigraph.yaml`. `cluster status` reads state only and reports any existing
|
||||
applied resources do not serve traffic until an `omnigraph-server --cluster
|
||||
<dir>` restart picks them up. `cluster status` reads state only and reports any existing
|
||||
lock metadata. `force-unlock` removes a lock only when the supplied id exactly
|
||||
matches the lock file. `refresh` requires an existing `state.json`; `import`
|
||||
creates one only when it is missing. Both observe declared graphs read-only at
|
||||
|
|
@ -271,7 +213,7 @@ embeddings, aliases, and bindings are reserved for later stages. See
|
|||
|
||||
## Param resolution
|
||||
|
||||
Precedence (high to low): explicit `--params` / `--params-file`, alias positional args, `omnigraph.yaml` defaults. JS-safe-integer handling is built in (`is_js_safe_integer_i64`, `JS_MAX_SAFE_INTEGER_U64`) so 64-bit ids round-trip safely through JSON clients.
|
||||
Precedence (high to low): explicit `--params` / `--params-file`, alias positional args. JS-safe-integer handling is built in (`is_js_safe_integer_i64`, `JS_MAX_SAFE_INTEGER_U64`) so 64-bit ids round-trip safely through JSON clients.
|
||||
|
||||
## Bearer token resolution (CLI)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ that ledger, manually remove a held local state lock by exact lock id, and
|
|||
catalog writes, **graph creation** (a declared graph that does not exist yet
|
||||
is initialized by apply at the derived root), **schema updates** (soft drops
|
||||
only), and — behind an explicit, digest-bound **approval** — **graph
|
||||
deletion**. It does not perform data-loss schema migrations, start servers,
|
||||
or serve anything it applies: the server still boots from `omnigraph.yaml`.
|
||||
deletion**. It does not perform data-loss schema migrations or start servers:
|
||||
a separate `omnigraph-server --cluster <dir>` serves the applied revision on
|
||||
its next (re)start.
|
||||
|
||||
## Commands
|
||||
|
||||
|
|
@ -31,26 +32,24 @@ omnigraph cluster force-unlock <LOCK_ID> --config company-brain --json
|
|||
`--config` points at a directory, not a file. The directory must contain
|
||||
`cluster.yaml`. When omitted, it defaults to the current directory.
|
||||
|
||||
## Relationship to `omnigraph.yaml`
|
||||
## Relationship to `~/.omnigraph/config.yaml`
|
||||
|
||||
`cluster.yaml` does not replace `omnigraph.yaml`, and the two never describe
|
||||
the same fact. `omnigraph.yaml` is the permanent **per-operator** layer (CLI
|
||||
defaults, the operator's identity and credential references, graph targets
|
||||
for data-plane commands); `cluster.yaml` is the shared desired state of a
|
||||
`cluster.yaml` and the per-operator `~/.omnigraph/config.yaml` never describe
|
||||
the same fact. The operator config is the permanent **per-operator** layer
|
||||
(the operator's identity and credential references, named servers/clusters,
|
||||
profiles, and CLI defaults); `cluster.yaml` is the shared desired state of a
|
||||
whole deployment, read only by the `cluster` commands via `--config`.
|
||||
|
||||
The exact contract:
|
||||
|
||||
- **Cluster commands read `omnigraph.yaml` for exactly one thing**: the
|
||||
`cli.actor` default used by `apply`/`approve` when `--as` is omitted —
|
||||
operator identity is a per-operator fact. With `--as` present, no config
|
||||
is read at all. Nothing else (its graph set, targets, bind, queries,
|
||||
policies) ever influences a cluster command; a malformed `omnigraph.yaml`
|
||||
breaks only the no-flag actor lookup, loudly.
|
||||
- **A `--cluster` server reads `omnigraph.yaml` for nothing** — not even the
|
||||
implicit current-directory search runs (mode-inference rule 0). Boot from
|
||||
cluster state XOR `omnigraph.yaml`, never a merge.
|
||||
- **The other direction is ergonomics, not coupling**: a per-operator
|
||||
- **Cluster commands read the operator config for exactly one thing**: the
|
||||
`operator.actor` default used by `apply`/`approve` when `--as` is omitted —
|
||||
operator identity is a per-operator fact. With `--as` present, the operator
|
||||
config is not needed. Nothing else in it influences a cluster command.
|
||||
- **No legacy `omnigraph.yaml`**: the CLI does not read `omnigraph.yaml` at
|
||||
all, and a `--cluster` server reads only the cluster catalog — boot is
|
||||
cluster-only.
|
||||
- **The other direction is ergonomics, not coupling**: per-operator
|
||||
data-plane commands address a cluster graph by its derived storage root
|
||||
(`company-brain/graphs/knowledge.omni`) with `--store <uri>` — an ordinary
|
||||
local path, no special handling.
|
||||
|
|
@ -234,12 +233,11 @@ Deletes remove the resource from state; their old payload blobs stay on disk
|
|||
(garbage collection is a later stage). Re-running a converged apply is a no-op:
|
||||
no state write, no revision change (`state_written: false`).
|
||||
|
||||
**Applied means serving — for deployments that opt in.** A server started
|
||||
with `--cluster <dir>` boots from the applied revision (see
|
||||
**Applied means serving.** A server started with `--cluster <dir>` boots from
|
||||
the applied revision (see
|
||||
[Serving from the cluster](#serving-from-the-cluster-the-mode-switch)); it
|
||||
picks up newly applied state on its next restart. Deployments still booting
|
||||
from `omnigraph.yaml` are untouched: for them, applied means recorded in the
|
||||
catalog, nothing more.
|
||||
picks up newly applied state on its next restart. Until that restart, applied
|
||||
means recorded in the catalog, nothing more.
|
||||
|
||||
### Graph creation
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ omnigraph cluster apply --config company-brain --as andrew
|
|||
|
||||
`--as <actor>` attributes the run: it is recorded in recovery sidecars and
|
||||
audit entries and threaded into the engine's commit history. Set
|
||||
`cli: { actor: <you> }` in your per-operator `omnigraph.yaml` to make it the
|
||||
`operator: { actor: <you> }` in your `~/.omnigraph/config.yaml` to make it the
|
||||
default when `--as` is omitted (the flag always wins; `approve` requires one
|
||||
of the two).
|
||||
|
||||
|
|
@ -244,12 +244,12 @@ with an in-flight apply.
|
|||
- **CI-driven convergence**: `validate` and `plan --json` are read-only and
|
||||
safe in pipelines; gate `apply --as ci` on plan review. Approvals are the
|
||||
human step by design — keep `cluster approve` out of automation.
|
||||
- **`omnigraph.yaml` still has a job**: per-operator settings — your
|
||||
`cli.actor` default for `--as`, CLI defaults, credentials, and data-plane
|
||||
ergonomics (address a cluster graph by its derived root like
|
||||
`company-brain/graphs/knowledge.omni` with `--store` for loads). It just no
|
||||
longer describes the deployment — a server boots from one source or the
|
||||
other, never a merge of both.
|
||||
- **`~/.omnigraph/config.yaml` is the per-operator config**: your
|
||||
`operator.actor` default for `--as`, named servers/clusters, credentials,
|
||||
profiles, and data-plane ergonomics (address a cluster graph by its derived
|
||||
root like `company-brain/graphs/knowledge.omni` with `--store` for loads). The
|
||||
cluster directory's `cluster.yaml` is the **sole deployment declaration** — the
|
||||
server boots from the cluster only.
|
||||
|
||||
## 7. Maintaining a cluster graph
|
||||
|
||||
|
|
|
|||
|
|
@ -13,13 +13,10 @@ Omnigraph supports two broad deployment shapes:
|
|||
|
||||
The server binary and container image expose the same HTTP surface.
|
||||
|
||||
The server also has two **boot sources**: `omnigraph.yaml` (graph targets
|
||||
declared in the per-operator config) or a **cluster directory**
|
||||
(`omnigraph-server --cluster <dir>`), which serves the cluster control
|
||||
The server has a single **boot source**: a **cluster directory**
|
||||
(`omnigraph-server --cluster <dir | s3://…>`), which serves the cluster control
|
||||
plane's applied revision — see
|
||||
[cluster-config.md](clusters/config.md#serving-from-the-cluster-the-mode-switch).
|
||||
The two are exclusive per deployment; switching is a restart with a different
|
||||
flag.
|
||||
|
||||
## Binary Deployment
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Server-scoped action (v0.6.0+; binds to `Omnigraph::Server::"root"`):
|
|||
|
||||
10. `graph_list` — `GET /graphs` registry enumeration (multi-graph mode)
|
||||
|
||||
Server-scoped actions cannot use `branch_scope` or `target_branch_scope` — they operate on the registry, not on a graph's branches. A rule cannot mix server-scoped and per-graph actions; split into separate rules. (Runtime `graph_create` / `graph_delete` are reserved but not shipped in v0.6.0; operators add/remove graphs by editing `omnigraph.yaml` and restarting.)
|
||||
Server-scoped actions cannot use `branch_scope` or `target_branch_scope` — they operate on the registry, not on a graph's branches. A rule cannot mix server-scoped and per-graph actions; split into separate rules. (Runtime `graph_create` / `graph_delete` over HTTP are reserved but not shipped; operators add/remove graphs by editing the cluster's `cluster.yaml`, running `omnigraph cluster apply`, and restarting the server.)
|
||||
|
||||
## Scope kinds
|
||||
|
||||
|
|
@ -28,38 +28,34 @@ Server-scoped actions cannot use `branch_scope` or `target_branch_scope` — the
|
|||
- `target_branch_scope` — applied to destination (`schema_apply`, branch ops, run ops)
|
||||
- `protected_branches` — named list with special rules; rule scopes are `any | protected | unprotected`
|
||||
|
||||
## Per-graph vs. server-level policy (multi-graph mode)
|
||||
## Per-graph vs. server-level policy
|
||||
|
||||
In multi mode (`omnigraph.yaml` with a non-empty `graphs:` map), policy files attach at two levels:
|
||||
A server boots from a cluster (`--cluster <dir>`), and the cluster's
|
||||
`cluster.yaml` declares its policy bundles in a `policies:` section. Each bundle
|
||||
names the scopes it `applies_to`: a graph id (per-graph rules — `read`, `change`,
|
||||
`branch_*`, `schema_apply`) or the literal `cluster` (server-level rules —
|
||||
`graph_list`).
|
||||
|
||||
```yaml
|
||||
server:
|
||||
policy:
|
||||
file: server-policy.yaml # server-level: graph_list
|
||||
|
||||
graphs:
|
||||
# cluster.yaml
|
||||
policies:
|
||||
base:
|
||||
file: base.policy.yaml
|
||||
applies_to: [cluster, knowledge] # cluster-level + the `knowledge` graph
|
||||
alpha:
|
||||
uri: s3://tenant-bucket/alpha
|
||||
policy:
|
||||
file: policies/alpha.yaml # per-graph: read, change, branch_*, schema_apply
|
||||
beta:
|
||||
uri: s3://tenant-bucket/beta
|
||||
# no per-graph policy → no engine-layer Cedar enforcement on beta
|
||||
file: policies/alpha.yaml
|
||||
applies_to: [alpha] # per-graph: alpha only
|
||||
```
|
||||
|
||||
**Config follows graph identity, not server mode.** A graph served by **name**
|
||||
(`--target <name>` or `server.graph`) uses its own `graphs.<name>.policy.file`,
|
||||
exactly as in multi-graph mode. Top-level `policy.file` applies only to an
|
||||
**anonymous** graph — one served by a bare `<URI>` with no `graphs:` entry.
|
||||
Serving a **named** graph (single- or multi-graph mode) while top-level
|
||||
`policy.file` (or `queries:`) is populated **refuses boot**, naming the block,
|
||||
since the top-level value would otherwise be silently shadowed by the per-graph
|
||||
block. Move per-graph rules to `graphs.<graph_id>.policy.file` and `graph_list`
|
||||
rules to `server.policy.file`.
|
||||
A graph with no bundle bound to it has no engine-layer Cedar enforcement. Each
|
||||
graph's HTTP request flows through its bound bundle; the management endpoint
|
||||
(`GET /graphs`) flows through the `cluster`-scoped bundle. When no bundle binds
|
||||
`cluster`, `GET /graphs` is denied in every runtime state, including
|
||||
`--unauthenticated`; with bearer tokens configured it returns 403 after admission
|
||||
control because `graph_list` is not a `read`-equivalent action. The operator must
|
||||
bind a `cluster`-scoped bundle granting `graph_list` to expose `/graphs`.
|
||||
|
||||
Each graph's HTTP request flows through its own per-graph policy. The management endpoint (`GET /graphs`) flows through the server-level policy. When `server.policy.file` is unset, `GET /graphs` is denied in every runtime state, including `--unauthenticated`; with bearer tokens configured, it returns 403 after admission control because `graph_list` is not a `read`-equivalent action. The operator must explicitly authorize via `server-policy.yaml` to expose `/graphs`.
|
||||
|
||||
Example server-level policy:
|
||||
Example `cluster`-scoped bundle:
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
|
|
@ -72,38 +68,26 @@ rules:
|
|||
actions: [graph_list]
|
||||
```
|
||||
|
||||
## Configuration
|
||||
Each per-graph rule may use at most one of `branch_scope` or
|
||||
`target_branch_scope`. Server-scoped rules (`graph_list`) take neither — they
|
||||
have no branch context.
|
||||
|
||||
`omnigraph.yaml`:
|
||||
## Actor for direct-engine writes
|
||||
|
||||
```yaml
|
||||
policy:
|
||||
file: policy.yaml # Cedar rules + groups
|
||||
tests: policy.tests.yaml # declarative test cases
|
||||
|
||||
cli:
|
||||
actor: act-andrew # default actor for CLI direct-engine writes
|
||||
```
|
||||
|
||||
Each per-graph rule may use at most one of `branch_scope` or `target_branch_scope`. Server-scoped rules (`graph_list`) take neither — they have no branch context.
|
||||
|
||||
`cli.actor` is the default actor identity for CLI direct-engine writes
|
||||
when `policy.file` is configured. Override per-invocation with `--as
|
||||
<ACTOR>` (top-level flag) — `--as` wins, otherwise `cli.actor` is used,
|
||||
otherwise no actor. With policy configured and neither set, the
|
||||
engine-layer footgun guard intentionally denies the write (silent bypass
|
||||
via "I forgot the actor" is exactly what the guard prevents). Remote
|
||||
HTTP writes ignore both — they resolve their actor server-side from the
|
||||
bearer token.
|
||||
The default actor identity for CLI direct-engine (`--store`) writes is
|
||||
`operator.actor` in `~/.omnigraph/config.yaml`. Override per-invocation with
|
||||
`--as <ACTOR>` — `--as` wins, otherwise `operator.actor`, otherwise no actor.
|
||||
Remote HTTP writes ignore both — they resolve their actor server-side from the
|
||||
bearer token. (Direct-store access carries no Cedar policy under RFC-011; policy
|
||||
lives in the cluster/server.)
|
||||
|
||||
## CLI
|
||||
|
||||
Policy tooling resolves its graph like server single-mode policy: `cli.graph`
|
||||
wins, otherwise `server.graph` is used, otherwise the top-level `policy.file`
|
||||
is validated/tested/explained as the anonymous policy.
|
||||
Policy tooling reads a cluster's applied policy bundles: pass `--cluster <dir>`,
|
||||
and `--graph <id>` to pick a graph's bundle when several apply.
|
||||
|
||||
- `omnigraph policy validate` — parse + count actors, exit 1 on parse error.
|
||||
- `omnigraph policy test` — run cases in `policy.tests.yaml`, exit 1 on any expectation mismatch.
|
||||
- `omnigraph policy test --tests <file>` — run the declarative cases in `<file>` against the selected bundle, exit 1 on any expectation mismatch.
|
||||
- `omnigraph policy explain --actor … --action … [--branch …] [--target-branch …]` — show decision and matched rule.
|
||||
- `omnigraph --as <ACTOR> <subcommand>` — set the actor for the duration of one invocation. Effective for `change`, `load` (and its deprecated `ingest` alias), `branch create|delete|merge`, and `schema apply` against a direct (`--store`) graph. **Rejected** on a served write (`--server`): the actor is bearer-token-resolved server-side, so `--as` can't set it there.
|
||||
|
||||
|
|
@ -132,7 +116,7 @@ reaches the authorization gate without a matching policy permit.
|
|||
|---|---|---|---|
|
||||
| **Open** | no | no | Every request is permitted. Refuses to start unless `--unauthenticated` or `OMNIGRAPH_UNAUTHENTICATED=1` is set — the operator must explicitly opt in. |
|
||||
| **DefaultDeny** | yes | no | Every authenticated request for an action other than `read` is rejected with HTTP 403. Closes the "tokens but forgot the policy file" trap — an operator who sets up auth and forgot to point at a policy file used to ship the illusion of protection. |
|
||||
| **PolicyEnabled** | yes | yes | Authenticated requests that reach a configured policy engine are evaluated by Cedar. Server-scoped actions still require `server.policy.file`. |
|
||||
| **PolicyEnabled** | yes | yes | Authenticated requests that reach a configured policy engine are evaluated by Cedar. Server-scoped actions still require a `cluster`-scoped policy bundle. |
|
||||
|
||||
The server refuses to start for the "no tokens, no policy, no flag" cell
|
||||
and for "policy file, no tokens" — instead of silently shipping an open
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue