mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-21 02:28:07 +02:00
mr-668: drop actor_id from PolicyRequest; pass actor as separate arg
The MR-731 "server-authoritative actor identity" invariant was enforced by an in-function chokepoint (`request.actor_id = actor.actor_id...` overwrite inside `authorize_request`). That worked but relied on every caller passing in a `PolicyRequest` and trusting the overwrite — a comment-enforced invariant. Move the invariant into the type system: * `PolicyRequest` no longer carries `actor_id`. The struct now models what a caller wants to do, not who they are. * `PolicyEngine::authorize(actor_id: &str, request: &PolicyRequest)` and `validate_request(actor_id, request)` take identity as a separate argument. The same shape `PolicyChecker::check` already had for the engine layer. * `authorize_request` in the HTTP layer extracts `actor_id` from the bearer-resolved `ResolvedActor` and passes it positionally — no overwrite step that could be skipped. * CLI `omnigraph policy explain` updated (the only other consumer that built a `PolicyRequest`). Public API break for the `omnigraph-policy` crate. Worth it: handlers can no longer accidentally populate `actor_id` from a request body field, and external consumers are forced by the compiler to source actor identity from a trusted path. The MR-731 chokepoint test `actor_id_resolves_from_bearer_token_ignoring_client_supplied_headers` still passes — the bearer-resolved actor is what reaches the engine. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
52f28cebe8
commit
76ee061cac
3 changed files with 121 additions and 140 deletions
|
|
@ -1333,12 +1333,12 @@ fn print_commit_human(commit: &CommitOutput) {
|
|||
println!("created_at: {}", commit.created_at);
|
||||
}
|
||||
|
||||
fn print_policy_explain(decision: &PolicyDecision, request: &PolicyRequest) {
|
||||
fn print_policy_explain(decision: &PolicyDecision, actor_id: &str, request: &PolicyRequest) {
|
||||
println!(
|
||||
"decision: {}",
|
||||
if decision.allowed { "allow" } else { "deny" }
|
||||
);
|
||||
println!("actor: {}", request.actor_id);
|
||||
println!("actor: {}", actor_id);
|
||||
println!("action: {}", request.action);
|
||||
if let Some(branch) = &request.branch {
|
||||
println!("branch: {}", branch);
|
||||
|
|
@ -2471,13 +2471,12 @@ async fn main() -> Result<()> {
|
|||
let config = load_cli_config(config.as_ref())?;
|
||||
let engine = resolve_policy_engine(&config)?;
|
||||
let request = PolicyRequest {
|
||||
actor_id: actor,
|
||||
action,
|
||||
branch,
|
||||
target_branch,
|
||||
};
|
||||
let decision = engine.authorize(&request)?;
|
||||
print_policy_explain(&decision, &request);
|
||||
let decision = engine.authorize(&actor, &request)?;
|
||||
print_policy_explain(&decision, &actor, &request);
|
||||
}
|
||||
},
|
||||
Command::Optimize {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue