Skip to content

Improve authorization docs and tracing guidance#16

Merged
hardbyte merged 3 commits intomainfrom
codex/docs-clarity-and-tracing
Mar 31, 2026
Merged

Improve authorization docs and tracing guidance#16
hardbyte merged 3 commits intomainfrom
codex/docs-clarity-and-tracing

Conversation

@hardbyte
Copy link
Copy Markdown
Contributor

Summary

  • align the README with the actual public API and runtime semantics
  • document short-circuit evaluation, summary denial reasons, and PolicyBuilder::effect(Effect::Deny) behavior
  • add reference docs for tracing fields and clarify ReBAC resolver/error semantics

Verification

  • cargo fmt --all
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo test --all-targets --all-features
  • cargo test --doc

Copilot AI review requested due to automatic review settings March 31, 2026 10:04
claude[bot]

This comment was marked as off-topic.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates Gatehouse’s public-facing documentation to better match actual evaluation behavior and emitted tracing/telemetry, and clarifies a few semantics around policy composition and ReBAC resolution.

Changes:

  • Documented decision semantics (short-circuit behavior, summary denial reasons, and PolicyBuilder::effect(Effect::Deny) semantics) in crate docs and README.
  • Added explicit tracing/telemetry field reference (including fallback behavior when security_rule() isn’t overridden).
  • Clarified RelationshipResolver error semantics (resolver must flatten failures into false) and updated examples/docs accordingly.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/lib.rs Expanded crate-level docs for decision/trace semantics, tracing fields, and clarified to_result() + PolicyBuilder::effect + RelationshipResolver behavior.
README.md Added Quick Start + decision semantics + tracing field reference; aligned README API descriptions with the crate.
examples/rebac_policy.rs Updated example docs to reflect that resolver failures must map to denial due to bool return type.
examples/groups_policy.rs Fixed trace output comment to match the actual policy name shown (StaffPolicy).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +41 to +69
let admin_policy = PolicyBuilder::<User, Document, Action, Context>::new("AdminOnly")
.subjects(|user| user.roles.iter().any(|role| role == "admin"))
.build();

let owner_policy = PolicyBuilder::<User, Document, Action, Context>::new("OwnerOnly")
.when(|user, _action, resource, _ctx| resource.owner_id == user.id)
.build();

let mut checker = PermissionChecker::new();
checker.add_policy(admin_policy);
checker.add_policy(owner_policy);

# tokio_test::block_on(async {
let user = User {
id: 1,
roles: vec!["admin".to_string()],
};
let document = Document { owner_id: 1 };

let evaluation = checker
.evaluate_access(&user, &Action, &document, &Context)
.await;

assert!(evaluation.is_granted());
println!("{}", evaluation.display_trace());

let outcome: Result<(), String> = evaluation.to_result(|reason| reason.to_string());
assert!(outcome.is_ok());
# });
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Quick Start snippet uses rustdoc-style hidden lines (# tokio_test::block_on(async { ... # });). In a README code fence these # prefixes are not hidden, so the example is harder to copy/paste and also depends on tokio_test. Consider rewriting the snippet as a normal #[tokio::main] async fn main() (or similar) without #-prefixed lines so it works as a standalone example.

Suggested change
let admin_policy = PolicyBuilder::<User, Document, Action, Context>::new("AdminOnly")
.subjects(|user| user.roles.iter().any(|role| role == "admin"))
.build();
let owner_policy = PolicyBuilder::<User, Document, Action, Context>::new("OwnerOnly")
.when(|user, _action, resource, _ctx| resource.owner_id == user.id)
.build();
let mut checker = PermissionChecker::new();
checker.add_policy(admin_policy);
checker.add_policy(owner_policy);
# tokio_test::block_on(async {
let user = User {
id: 1,
roles: vec!["admin".to_string()],
};
let document = Document { owner_id: 1 };
let evaluation = checker
.evaluate_access(&user, &Action, &document, &Context)
.await;
assert!(evaluation.is_granted());
println!("{}", evaluation.display_trace());
let outcome: Result<(), String> = evaluation.to_result(|reason| reason.to_string());
assert!(outcome.is_ok());
# });
#[tokio::main]
async fn main() {
let admin_policy = PolicyBuilder::<User, Document, Action, Context>::new("AdminOnly")
.subjects(|user| user.roles.iter().any(|role| role == "admin"))
.build();
let owner_policy = PolicyBuilder::<User, Document, Action, Context>::new("OwnerOnly")
.when(|user, _action, resource, _ctx| resource.owner_id == user.id)
.build();
let mut checker = PermissionChecker::new();
checker.add_policy(admin_policy);
checker.add_policy(owner_policy);
let user = User {
id: 1,
roles: vec!["admin".to_string()],
};
let document = Document { owner_id: 1 };
let evaluation = checker
.evaluate_access(&user, &Action, &document, &Context)
.await;
assert!(evaluation.is_granted());
println!("{}", evaluation.display_trace());
let outcome: Result<(), String> = evaluation.to_result(|reason| reason.to_string());
assert!(outcome.is_ok());
}

Copilot uses AI. Check for mistakes.
Comment on lines 89 to 105
```rust
#[async_trait]
trait Policy<Subject, Resource, Action, Context> {
trait Policy<Subject, Resource, Action, Context>: Send + Sync {
async fn evaluate_access(
&self,
subject: &Subject,
action: &Action,
resource: &Resource,
context: &Context,
) -> PolicyEvalResult;

fn policy_type(&self) -> String;

fn security_rule(&self) -> SecurityRuleMetadata {
SecurityRuleMetadata::default()
}
}
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Policy trait snippet is missing the imports needed to compile (async_trait::async_trait, PolicyEvalResult, and SecurityRuleMetadata / gatehouse::*). Since the surrounding text emphasizes aligning docs with the public API, it would be helpful if this example were copy/paste compilable by adding the minimal use lines or qualifying the types.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings March 31, 2026 10:16
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@hardbyte hardbyte merged commit fc8d08c into main Mar 31, 2026
6 checks passed
@hardbyte hardbyte deleted the codex/docs-clarity-and-tracing branch March 31, 2026 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants