Skip to content

feat: surface caveat evaluation diagnostics for denied checks#2933

Open
ugoenyioha wants to merge 1 commit intoauthzed:mainfrom
ugoenyioha:feature/caveat-eval-diagnostics
Open

feat: surface caveat evaluation diagnostics for denied checks#2933
ugoenyioha wants to merge 1 commit intoauthzed:mainfrom
ugoenyioha:feature/caveat-eval-diagnostics

Conversation

@ugoenyioha
Copy link

Summary

  • Add CaveatEvalResult and caveat_eval_info to internal dispatch check results so denied caveated checks can report which caveat(s) evaluated to false.
  • Collect per-leaf caveat evaluation details in computeCaveatedCheckResult and attach diagnostics only when debug/tracing is enabled, avoiding unconditional data exposure and extra hot-path cost.
  • Surface diagnostics via gRPC trailer metadata (io.spicedb.respmeta.caveat-eval-info) and add targeted tests covering false caveats, mixed intersection outcomes, and no-diagnostics behavior without debug mode.

Validation

  • go test ./internal/graph/computed/... -count=1 -timeout=300s
  • go test ./internal/services/v1/... -count=1 -timeout=300s
  • go test ./internal/caveats/... ./pkg/caveats/... -count=1 -timeout=300s

…hzed#2802)

When CheckPermission returns NOT_MEMBER because a caveat evaluated to
false and debugging is enabled, the response now includes diagnostic
information identifying which specific caveat(s) caused the denial.

Diagnostics are gated behind the existing debug mechanism (the
io.spicedb.requestdebuginfo header or WithTracing) to avoid:
- Information disclosure: caveat expressions and context values would
  leak schema internals and relationship data in production responses
- Performance impact: re-evaluation of caveat expressions on every
  denied caveated check

Changes:
- Add CaveatEvalResult message to internal dispatch proto with fields
  for caveat name, result, expression, context, and missing params
- Add CaveatEvalInfo field to ResourceCheckResult in dispatch proto
- Extend ExpressionResult interface with LeafCaveatResults() to collect
  per-leaf caveat evaluation results from expression trees
- In computeCaveatedCheckResult, re-evaluate with debug enabled on
  NOT_MEMBER to collect per-caveat diagnostics (only when DebugOption
  is not NoDebugging)
- Surface diagnostics via gRPC response trailer metadata
  (io.spicedb.respmeta.caveat-eval-info) as JSON, requiring no changes
  to the public API proto in authzed/api
- Add 5 test cases covering: single false caveat, written context
  precedence, intersection with mixed results, non-caveated denial,
  and allowed result; each test also verifies diagnostics are NOT
  populated without debug mode

Fixes authzed#2802
Ref authzed#1970
@ugoenyioha ugoenyioha requested a review from a team as a code owner March 2, 2026 14:44
@github-actions
Copy link

github-actions bot commented Mar 2, 2026

CLA Assistant Lite bot:
Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request

@github-actions github-actions bot added area/api v1 Affects the v1 API area/tooling Affects the dev or user toolchain (e.g. tests, ci, build tools) labels Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api v1 Affects the v1 API area/tooling Affects the dev or user toolchain (e.g. tests, ci, build tools)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants