omnigraph/docs/user
Andrew Altshuler f3f2a051ba
policy: server 3-state default-deny matrix (MR-723) (#105)
Closes the "tokens but no policy" trap. Pre-MR-723, an operator who
configured bearer tokens and forgot to set policy.file got a server
that required auth and then permitted every action — the illusion of
protection. After MR-723, that configuration is default-deny: only
`read` actions succeed; every other action returns HTTP 403.

Three startup states, classified deterministically:

- **Open** — no tokens, no policy. Requires explicit
  `--unauthenticated` flag or `OMNIGRAPH_UNAUTHENTICATED=1`; otherwise
  `serve()` refuses to start. Forces the operator to opt in to
  "fully open dev mode" so it can't happen accidentally.
- **DefaultDeny** — tokens configured, no policy. `authorize_request`
  rejects every action except `Read` with 403. The warn-log on
  startup names the misconfiguration explicitly.
- **PolicyEnabled** — policy file configured. Cedar evaluates every
  request, unchanged from pre-MR-723.

What landed:

- `ServerConfig.allow_unauthenticated: bool` + `--unauthenticated` flag
  on the `omnigraph-server` bin + `OMNIGRAPH_UNAUTHENTICATED` env var
  (`load_server_settings` honors both).
- New `classify_server_runtime_state(has_tokens, has_policy,
  allow_unauthenticated) -> Result<ServerRuntimeState>` pure function.
  `serve()` calls it before opening the engine and bails with a clear
  error when the operator hits the no-tokens-no-policy-no-flag cell.
- `authorize_request` state-2 branch: when `policy_engine()` is None
  but the bearer-auth middleware delivered an authenticated actor, any
  action other than `Read` returns 403 with a message that names the
  misconfiguration.
- `AppState::with_policy_engine(self, engine)` builder method so
  integration tests that need a custom workload (`new_with_workload`)
  can still install a permit-all policy without a new constructor.
- `app_for_loaded_repo_with_auth(token)` and
  `app_for_loaded_repo_with_auth_tokens(tokens)` test helpers now
  install a permit-all policy alongside tokens — they previously
  represented the "tokens but no policy" state that MR-723 makes
  default-deny, and tests that don't care about policy were
  inadvertently coupled to the loophole.

Tests:

- `classify_*` unit tests (3) — every cell of the matrix.
- `default_deny_mode_allows_read_for_authenticated_actor` — GET
  /snapshot succeeds with bearer token + no policy.
- `default_deny_mode_rejects_change_with_forbidden` — POST /change
  rejected with 403 + "default-deny" message.
- `default_deny_mode_rejects_schema_apply_with_forbidden` — POST
  /schema/apply rejected with 403 + "default-deny" message.
- New `app_for_repo_with_auth_tokens_only(schema, tokens)` helper
  builds the State-2 fixture without policy. The pre-MR-723 helpers
  `app_for_loaded_repo_with_auth*` shift semantics to "tokens +
  permit-all" so existing tests retain their original intent.

docs/user/policy.md: new "Server runtime states (MR-723)" section
documents the matrix and the explicit `--unauthenticated` opt-in.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 17:02:26 +03:00
..
audit.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
branches-commits.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
changes.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
cli-reference.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
cli.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
constants.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
deployment.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
embeddings.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
errors.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
index.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
indexes.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
install.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
maintenance.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
policy.md policy: server 3-state default-deny matrix (MR-723) (#105) 2026-05-18 17:02:26 +03:00
query-language.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
schema-language.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
schema-lint.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
server.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
storage.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00
transactions.md docs: split user and developer docs (#93) 2026-05-15 03:45:22 +03:00