mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-27 02:39:38 +02:00
policy: chassis fan-out — _as variants on the remaining 6 writers (MR-722) (#103)
PR #102 wired apply_schema_as. This PR completes the chassis-side coverage so every public mutating engine entry point hits the same Omnigraph::enforce(action, scope, actor) gate regardless of transport: - mutate_as → enforce(Change, Branch(branch), actor) - load_as → enforce(Change, Branch(branch), actor) - ingest_as → enforce(Change, Branch(branch), actor); also threads actor through the implicit branch_create_from_as so fresh-branch ingest correctly hits BranchCreate too - branch_create_as → enforce(BranchCreate, TargetBranch(name), actor) - branch_create_from_as → enforce(BranchCreate, BranchTransition { source, target }, actor) - branch_delete_as → enforce(BranchDelete, TargetBranch(name), actor) - branch_merge_as → enforce(BranchMerge, BranchTransition { source, target }, actor) Three new _as variants for branch ops (create, create_from, delete) that had no actor surface before; existing actor-less variants delegate with actor=None so the no-policy path is a strict no-op. HTTP handlers updated to thread the resolved actor into the new _as variants for branch_create and branch_delete (was previously dropped). 14 new SDK chassis tests (one allow + one deny pair per wired writer); the existing 4 apply_schema_as tests stay. All 18 pass. docs/user/policy.md updated to describe engine-wide enforcement and the coarse-vs-fine layer split (engine = action gate, query layer per-row = MR-725 future). AGENTS.md capability matrix updated to match. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
9973683261
commit
da42beec41
8 changed files with 437 additions and 32 deletions
|
|
@ -90,6 +90,18 @@ impl Omnigraph {
|
|||
mode: LoadMode,
|
||||
actor_id: Option<&str>,
|
||||
) -> Result<IngestResult> {
|
||||
// Engine-layer policy gate (MR-722 fan-out / PR #3). Scope is
|
||||
// `Branch(branch)` for the data-write portion. If ingest creates
|
||||
// a new branch as a side-effect (target branch doesn't exist),
|
||||
// the inner `branch_create_from_as` call below additionally
|
||||
// checks `BranchCreate` — both authorities are genuinely needed
|
||||
// for "ingest into a fresh branch", so the layered check is
|
||||
// correct, not redundant.
|
||||
self.enforce(
|
||||
omnigraph_policy::PolicyAction::Change,
|
||||
&omnigraph_policy::ResourceScope::Branch(branch.to_string()),
|
||||
actor_id,
|
||||
)?;
|
||||
self.ingest_with_current_actor(branch, from, data, mode, actor_id)
|
||||
.await
|
||||
}
|
||||
|
|
@ -135,8 +147,18 @@ impl Omnigraph {
|
|||
.iter()
|
||||
.any(|name| name == &target_branch);
|
||||
if branch_created {
|
||||
self.branch_create_from(crate::db::ReadTarget::branch(&base_branch), &target_branch)
|
||||
.await?;
|
||||
// Thread the actor through to the implicit BranchCreate so
|
||||
// policy decisions match what an explicit `branch_create_from_as`
|
||||
// call would see. Calling the no-actor variant here would
|
||||
// bypass BranchCreate enforcement when policy is installed —
|
||||
// the footgun guard catches that case too, but threading is
|
||||
// the correct fix.
|
||||
self.branch_create_from_as(
|
||||
crate::db::ReadTarget::branch(&base_branch),
|
||||
&target_branch,
|
||||
actor_id,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let result = self.load_as(&target_branch, data, mode, actor_id).await?;
|
||||
|
|
@ -160,6 +182,17 @@ impl Omnigraph {
|
|||
mode: LoadMode,
|
||||
actor_id: Option<&str>,
|
||||
) -> Result<LoadResult> {
|
||||
// Engine-layer policy gate (MR-722 fan-out / PR #3). Scope is
|
||||
// `Branch(branch)` to match the HTTP-layer Change convention.
|
||||
// `ingest_as` also calls `load_as` after enforcing its own
|
||||
// Change gate — that double-check is fine because both gates
|
||||
// resolve to identical Cedar decisions for the same actor +
|
||||
// branch (the second check is a structurally-correct no-op).
|
||||
self.enforce(
|
||||
omnigraph_policy::PolicyAction::Change,
|
||||
&omnigraph_policy::ResourceScope::Branch(branch.to_string()),
|
||||
actor_id,
|
||||
)?;
|
||||
self.ensure_schema_state_valid().await?;
|
||||
// Reject internal `__run__*` / system-prefixed branches at the
|
||||
// public write boundary. Direct-publish paths assert this
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue