Skip to content

Add functions for inspecting TPE determining policies#2401

Merged
john-h-kastner-aws merged 9 commits into
mainfrom
tpe-det-policies
Jun 19, 2026
Merged

Add functions for inspecting TPE determining policies#2401
john-h-kastner-aws merged 9 commits into
mainfrom
tpe-det-policies

Conversation

@john-h-kastner-aws

@john-h-kastner-aws john-h-kastner-aws commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Adds TpeResponse::reason, TpeResponse::satisfied_permits, and TpeResponse::satisfied_forbids to the public TPE API to enable callers to find determining policies for partial authorization responses.

Description of changes

Issue #, if available

Checklist for requesting a review

The change in this PR is (choose one, and delete the other options):

  • A breaking change requiring a major version bump to cedar-policy (e.g., changes to the signature of an existing API).
  • A backwards-compatible change requiring a minor version bump to cedar-policy (e.g., addition of a new API).
  • A bug fix or other functionality change requiring a patch to cedar-policy.
  • A change "invisible" to users (e.g., documentation, changes to "internal" crates like cedar-policy-core, cedar-validator, etc.)
  • A change (breaking or otherwise) that only impacts unreleased or experimental code.

I confirm that this PR (choose one, and delete the other options):

  • Updates the "Unreleased" section of the CHANGELOG with a description of my change (required for major/minor version bumps).
  • Does not update the CHANGELOG because my change does not significantly impact released code.

I confirm that cedar-spec (choose one, and delete the other options):

  • Does not require updates because my change does not impact the Cedar formal model or DRT infrastructure.
  • Requires updates, and I have made / will make these updates myself. (Please include in your description a timeline or link to the relevant PR in cedar-spec, and how you have tested that your updates are correct.)
  • Requires updates, but I do not plan to make them in the near future. (Make sure that your changes are hidden behind a feature flag to mark them as experimental.)
  • I'm not sure how my change impacts cedar-spec. (Post your PR anyways, and we'll discuss in the comments.)

I confirm that docs.cedarpolicy.com (choose one, and delete the other options):

  • Does not require updates because my change does not impact the Cedar language specification.
  • Requires updates, and I have made / will make these updates myself. (Please include in your description a timeline or link to the relevant PR in cedar-docs. PRs should be targeted at a staging-X.Y branch, not main.)
  • I'm not sure how my change impacts the documentation. (Post your PR anyways, and we'll discuss in the comments.)

…peResponse::satisfied_forbids`

Signed-off-by: John Kastner <jkastner@amazon.com>
Signed-off-by: John Kastner <jkastner@amazon.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the (experimental) TPE public API to let callers inspect which policies were satisfied/determining for a partial-authorization outcome, and adjusts cedar-policy-core TPE internals to expose policy IDs by reference.

Changes:

  • Add TpeResponse::reason, TpeResponse::satisfied_permits, and TpeResponse::satisfied_forbids to inspect determining/satisfied policies for partial decisions.
  • Change cedar-policy-core::tpe::ResidualPolicy::get_policy_id to return &PolicyID and update internal logic/tests accordingly.
  • Add/update tests and a changelog entry for the new API surface.

Reviewed changes

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

File Description
cedar-policy/src/api/tpe.rs Adds new TpeResponse inspection methods and corresponding tests.
cedar-policy/CHANGELOG.md Documents the new TPE inspection API (needs alignment with actual changes).
cedar-policy-core/src/tpe/response.rs Changes ResidualPolicy::get_policy_id to borrow the ID and updates set construction.
cedar-policy-core/src/tpe.rs Updates tests to accommodate the borrowed policy ID accessor.

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

Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/CHANGELOG.md Outdated
Comment thread cedar-policy-core/src/tpe/response.rs
@github-actions

This comment was marked as outdated.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions

This comment was marked as outdated.

Comment thread cedar-policy/src/api/tpe.rs Outdated

@luxas luxas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, this is a good addition to the API surface 👍

What the Kubernetes integration in particular is interested in, is understanding that when given decision=Deny, did that originate from a matched deny policy or just no matching policies? In the latter case, one could treat that as a NoOpinion mode, and let other subsequent authorizers (if many) have their say.

Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment on lines +389 to +390
/// These are a subset of the determining policies for any subsequent
/// concrete reauthorization.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not sure I understand the for any subsequent concrete reauthorization part of the comment, the returned policies already evaluated to true, so there is no need for reauthorization?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The idea is that if you were to do concrete authorization, there might be more determining policies that aren't represented here. If you want to take some action based on which policies apply to a request, this might be important.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

expanded comments substantially. let me know if it makes sense

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe determining policies for any subsequent concrete reauthorization could be reworded as determining policies of an concrete authorization request with a complete Entity store? I guess that's what you mean?

Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/src/api/tpe.rs
Signed-off-by: John Kastner <jkastner@amazon.com>
@github-actions

This comment was marked as outdated.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 4 out of 4 changed files in this pull request and generated 3 comments.

Comment thread cedar-policy-core/src/tpe/response.rs
Comment thread cedar-policy/src/api/tpe.rs
Comment thread cedar-policy/CHANGELOG.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions

This comment was marked as outdated.

@luxas luxas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, I like it 👍
Should we make the error change in this or another PR? It could be done in another.

Comment thread cedar-policy/src/api/tpe.rs
Comment thread cedar-policy/src/api/tpe.rs
Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment on lines +389 to +390
/// These are a subset of the determining policies for any subsequent
/// concrete reauthorization.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe determining policies for any subsequent concrete reauthorization could be reworded as determining policies of an concrete authorization request with a complete Entity store? I guess that's what you mean?

Signed-off-by: John Kastner <jkastner@amazon.com>
Signed-off-by: John Kastner <jkastner@amazon.com>
Signed-off-by: John Kastner <jkastner@amazon.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 4 out of 4 changed files in this pull request and generated 2 comments.

Comment thread cedar-policy/src/api/tpe.rs Outdated
Comment thread cedar-policy/CHANGELOG.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Coverage Report

Head Commit: ce2ef49e8fa0379bc475e255b52c69de4c4335fa

Base Commit: 19aea85bd58786eda7db8dc36c21f3b4afd1f8f5

Download the full coverage report.

Coverage of Added or Modified Lines of Rust Code

Required coverage: 80.00%

Actual coverage: 100.00%

Status: PASSED ✅

Details
File Status Covered Coverage Missed Lines
cedar-policy-core/src/tpe/response.rs 🟢 41/41 100.00%
cedar-policy/src/api/tpe.rs 🟢 43/43 100.00%

Coverage of All Lines of Rust Code

Required coverage: 80.00%

Actual coverage: 87.91%

Status: PASSED ✅

Details
Package Status Covered Coverage Base Coverage
cedar-language-server 🟢 4722/5102 92.55% --
cedar-policy 🟢 4573/5687 80.41% --
cedar-policy-cli 🟡 1257/1649 76.23% --
cedar-policy-core 🟢 24599/27905 88.15% --
cedar-policy-formatter 🟢 914/1088 84.01% --
cedar-policy-symcc 🟢 6790/7287 93.18% --
cedar-wasm 🔴 0/28 0.00% --

@luxas luxas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approving with some small renames that could be followed up upon if we like.
Thanks, this should give folks quite a lot of data to play with to deepen the understanding of the decision.

@@ -130,28 +136,32 @@ impl<'a> Response<'a> {
match rp.get_effect() {
Effect::Forbid => {
if r.is_true() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: feels like this could be a good candidate to have an enum / match statement for in the future.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We could write this as a match on the residual, but I don't think I see how it would make the code any nicer

.map(|id| self.residuals.get(id).unwrap())
}

/// Get trivially erroring permit residual policies

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// Get trivially erroring permit residual policies
/// Get permit policies that errored during evaluation

nit: not sure I understand the word trivially in this context, maybe just drop it?

.map(|id| self.residuals.get(id).unwrap())
}

/// Get trivially erroring forbid residual policies

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// Get trivially erroring forbid residual policies
/// Get forbid policies that errored during evaluation

/// Get the forbid policies that did not reach a concrete value or error for the partial request.
///
/// This function only returns the `PolicyId`s for residual policies.
/// To access the residual policy conditions, use [`TpeResponse::nontrivial_residual_policies`].

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this reminds me that we should probably rename TpeResponse::nontrivial_residual_policies to just TpeResponse::residual_policies now, as we've anyways factored out the "trivial" ones to their own constructors and thus don't need that trivial/nontrivial distinction. That'd then be consistent with calling the other getters here "just" residual_forbids/permits

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I need to think more about the naming here. In some places "residual" refers to any output of partial evaluation (even if it reaches a concrete value). In other place "residual" specifically means a policy which didn't reach a concrete value.

/// must return a concrete `Deny`.
pub fn true_forbids(&self) -> impl Iterator<Item = &PolicyId> {
self.0
.satisfied_forbids()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

seems like one missing getter rename

/// policy.
pub fn true_permits(&self) -> impl Iterator<Item = &PolicyId> {
self.0
.satisfied_permits()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

one missing getter rename, or don't we want to update all of these at the same time?

@john-h-kastner-aws john-h-kastner-aws merged commit ce1cacd into main Jun 19, 2026
34 checks passed
@john-h-kastner-aws john-h-kastner-aws deleted the tpe-det-policies branch June 30, 2026 18:51
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.

4 participants