omnigraph/crates/omnigraph-server/src
Ragnor Comerford 65e53933fb
mr-668: server-scoped actions always require explicit policy (green)
`server_graphs_list` returned 200 in Open mode (`--unauthenticated`,
no tokens, no policy) because `authorize_request`'s no-policy
fallback only denied when `actor.is_some()` AND action != Read.
In Open mode `actor: None`, so the denial branch never fired and
the call returned `Ok(())` — leaking the registry (graph IDs +
URIs that may contain S3 bucket paths or internal hostnames) to
any unauthenticated caller. The docstring on `server_graphs_list`
claimed it was "Cedar-gated" and that the server should "not leak
the registry until the operator explicitly authorizes it" —
docstring intent and code disagreed.

Symptomatic fix: special-case GraphList. Breaks the moment
another server-scoped action (`graph_create`, `graph_delete`) is
added.

Correct-by-design fix: tie authorization to the action's
`resource_kind()`. Server-scoped actions
(`PolicyResourceKind::Server`) always require explicit policy
authorization — there is no runtime state where they're served
by default. Per-graph actions keep the existing default-deny
logic (DefaultDeny denies non-Read for authenticated actors;
Open mode allows everything per the operator's `--unauthenticated`
opt-in for graph DATA, but not for server topology).

The fix uses the existing `PolicyResourceKind` enum that #119
already added — no new abstraction. Future server-scoped actions
(runtime `graph_create`/`graph_delete` when the cluster catalog
ships) automatically pick up the same enforcement without any
per-action handler change.

Changes:

* `crates/omnigraph-server/src/lib.rs:51` — re-export
  `PolicyResourceKind` (the kind discriminator was already public
  on the omnigraph-policy crate; needed in scope here).
* `crates/omnigraph-server/src/lib.rs:1457` — `authorize_request`'s
  no-policy fallback gains a server-scoped-action check that fires
  before the actor-based default-deny logic. Error message names
  the failure mode and points at `server.policy.file`.
* `crates/omnigraph-server/tests/server.rs:5037` —
  `get_graphs_with_server_policy_authorizes_per_cedar` extended
  to register two graphs in non-alphabetical order and assert
  the admin-200 response is sorted alphabetically. Restores the
  sort-order coverage that lived in
  `get_graphs_lists_registered_graphs_in_multi_mode` before the
  red commit renamed it to assert denial.

Also bundles a small adjacent cleanup that the bot-review flagged:

* `crates/omnigraph-server/src/graph_id.rs:124` — drop the
  unreachable `"openapi.json"` entry from `is_reserved`. The
  regex `^[a-zA-Z0-9-]{1,64}$` rejects every dot-containing name
  before `is_reserved` can run, so dotted entries in this list
  were dead code that misled readers into thinking the list
  needed to cover them. Comment now names the structural
  exclusion. The `rejects_reserved_route_names` test loses its
  `openapi.json` row (covered by `rejects_dots` via the regex).

Closes the "server-scoped management actions silently leak in
Open mode" class. Red test from the previous commit
(`get_graphs_denied_in_open_mode_without_server_policy`) turns
green; all 78 server integration tests + 76 lib tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 11:27:01 +02:00
..
api.rs mr-668: align GET /graphs 405 body code with HTTP status 2026-05-27 12:04:51 +02:00
auth.rs Add aws feature + SecretsManagerTokenSource backend 2026-04-18 03:48:51 +03:00
config.rs mr-668: remove POST /graphs and CLI graphs create (defer runtime graph mgmt) 2026-05-26 17:49:38 +02:00
graph_id.rs mr-668: server-scoped actions always require explicit policy (green) 2026-05-28 11:27:01 +02:00
identity.rs mr-668: add GraphId newtype + Cloud-mode forward identity stubs (PR 1/10) 2026-05-25 18:51:49 +02:00
lib.rs mr-668: server-scoped actions always require explicit policy (green) 2026-05-28 11:27:01 +02:00
main.rs Rename repo terminology to graph (#118) 2026-05-24 16:46:00 +01:00
policy.rs policy: chassis core — omnigraph-policy crate + Omnigraph::enforce() (MR-722) (#102) 2026-05-18 00:36:36 +03:00
registry.rs mr-668: cfg(test)-gate GraphRegistry::insert and its mutex 2026-05-27 13:03:59 +02:00
workload.rs server: drop unwired try_admit_rewrite / 503 admission surface 2026-05-09 20:58:17 +00:00