Skip to content

fix: improve coverage for permission condition branches#2955

Open
Iineman2 wants to merge 4 commits into
Permify:masterfrom
Iineman2:fix-coverage-condition-components
Open

fix: improve coverage for permission condition branches#2955
Iineman2 wants to merge 4 commits into
Permify:masterfrom
Iineman2:fix-coverage-condition-components

Conversation

@Iineman2
Copy link
Copy Markdown

@Iineman2 Iineman2 commented May 11, 2026

/claim #837

Summary

Fixes #837.

This updates the coverage analyzer so a permission/action assertion can report branch-level condition coverage instead of treating one satisfied branch as complete coverage for the whole permission.

Changes:

  • Extract leaf components from permission rewrites, including direct relations, tuple-to-userset references, attributes, and rule calls.
  • Track uncovered assertion components per scenario alongside the existing top-level uncovered assertions.
  • Use detailed component coverage when calculating total assertion coverage, so partially exercised permissions lower the overall coverage score.
  • Display uncovered assertion components and their per-scenario coverage in the CLI output.
  • Add a regression test for a permission shaped like system or (viewer or owner) where only the system branch is exercised.

Verification

go test ./pkg/development/coverage
go test ./pkg/cmd ./pkg/development/coverage

Summary by CodeRabbit

  • New Features

    • Coverage reporting now shows uncovered assertion components per key.
    • Adds per-key assertion-component coverage percentages with color-coded success/danger indicators (50% threshold).
    • Aggregated coverage now reflects component-level percentages.
  • Tests

    • Added tests validating component-level coverage across branched, cross-entity, and nested permission scenarios.

Review Change Stack

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 11, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0bbb5450-71b7-4c36-8ae2-e89aa011808a

📥 Commits

Reviewing files that changed from the base of the PR and between 9b3572d and bd9ec5b.

📒 Files selected for processing (1)
  • pkg/development/coverage/coverage_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/development/coverage/coverage_test.go

📝 Walkthrough

Walkthrough

Tracks permission assertion components (leaves), computes per-scenario uncovered components and per-key coverage percentages, aggregates component-level percentages into TotalAssertionsCoverage, updates CLI to display uncovered components and percentages, and adds tests for branched, cross-entity, and nested-permission cases.

Changes

Assertion Component Coverage Tracking

Layer / File(s) Summary
Data Model Extensions
pkg/development/coverage/coverage.go
EntityCoverageInfo adds UncoveredAssertionComponents and CoverageAssertionComponentsPercent; SchemaCoverage adds AssertionComponents.
Schema Extraction
pkg/development/coverage/coverage.go
extractEntityReferences populates AssertionComponents from compiled permission condition leaves.
Assertion Component Extraction Logic
pkg/development/coverage/coverage.go
New traversal/formatting logic extracts leaf-based assertion-component strings with fallbacks for unsupported/nil children.
Component Parsing & Support Helpers
pkg/development/coverage/coverage.go
Helpers parse component names, map to base assertions, build assertion coverage contexts, and check component support via covered relationships/attributes (including tuple-to-user-set and computed relation matching).
Per-Scenario Coverage Calculation
pkg/development/coverage/coverage.go
Per-scenario calculation computes uncovered assertion components and component-level coverage percentages and stores them on EntityCoverageInfo.
Coverage Info Initialization
pkg/development/coverage/coverage.go
newEntityCoverageInfo initializes the new component-level maps.
Total Coverage Aggregation
pkg/development/coverage/coverage.go
Aggregation now averages CoverageAssertionComponentsPercent values into TotalAssertionsCoverage.
Coverage Display Output
pkg/cmd/coverage.go
DisplayCoverageInfo prints "uncovered assertion components" and "coverage assertion components percentage" sections with success/danger styling based on a 50% threshold.
Test Validation
pkg/development/coverage/coverage_test.go
Ginkgo tests added for branched permission components, cross-entity component exclusion, and nested permission expansion coverage.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant CoverageCLI
  participant CoverageEngine
  participant ChecksRunner
  participant Aggregator
  Client->>CoverageCLI: request coverage report
  CoverageCLI->>CoverageEngine: build schema refs & extract assertion components
  CoverageEngine->>ChecksRunner: evaluate scenarios (relationships/attributes)
  ChecksRunner-->>CoverageEngine: per-scenario coverage contexts
  CoverageEngine->>Aggregator: compute uncovered components & component percentages
  Aggregator-->>CoverageCLI: aggregated coverage info
  CoverageCLI-->>Client: render report (uncovered components, percentages)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 Leaves split into branches, I peek and prance,

Each tiny component gets a fair chance.
I hop through assertions, one, two, three,
No hidden branch shall escape me! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main objective: improving coverage analysis for permission condition branches by tracking component-level coverage instead of treating one satisfied branch as complete.
Linked Issues check ✅ Passed The code changes fully address the requirements in issue #837 by implementing component-level coverage tracking, detailed branch evaluation, and preventing partial coverage from being treated as complete coverage.
Out of Scope Changes check ✅ Passed All changes directly support the stated objectives: extending DisplayCoverageInfo output, adding component-level tracking to EntityCoverageInfo and SchemaCoverage, and adding comprehensive test cases for the new functionality.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Iineman2 Iineman2 changed the title Improve coverage for permission condition branches fix: improve coverage for permission condition branches May 11, 2026
@Iineman2
Copy link
Copy Markdown
Author

Demo video for the coverage change: https://github.com/Iineman2/permify/releases/download/permify-837-demo/permify-837-demo.mp4

It shows the partial-coverage scenario from the regression test: view = system or (viewer or owner) with only system exercised now reports uncovered owner and viewer assertion components instead of treating the entire permission as fully covered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/development/coverage/coverage_test.go (1)

250-292: ⚡ Quick win

Add one cross-entity false-positive regression case for components.

This new case is solid, but it won’t catch the scenario where a branch is marked covered from tuples on a different entity instance (same entity type).
A small follow-up case (e.g., check on document:1, supporting tuple only on document:2) would lock down the branch-coverage guarantee.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/development/coverage/coverage_test.go` around lines 250 - 292, Add a
follow-up test that prevents cross-entity-instance false positives by asserting
that coverage recorded for a check on one entity instance is not satisfied by
tuples on a different instance of the same entity type: update the test file
around the existing Case 2.1 (the Run(file.Shape{...}) block) or add a new It()
case that uses a Check with Entity "document:1" while providing the supporting
relationship tuple only on "document:2" in the Relationships slice, then assert
that the relevant branch/component for "document:1" remains uncovered (use the
same assertions you have for EntityCoverageInfo[*].UncoveredAssertionComponents
and CoverageAssertionComponentsPercent to verify the branch is not marked
covered and TotalAssertionsCoverage reflects the uncovered branch).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/development/coverage/coverage.go`:
- Around line 365-377: The current logic in findUncoveredAssertionComponents
uses extractCoveredAssertions and assertionComponentHasSupportingData to mark
components covered even when supporting relation/attribute data belong to
unrelated entity instances or when tuple-to-userset components only verify the
first hop; fix this by scoping supporting-data checks to the specific
scenario-relevant entity instances derived from the given checks/filters (use
the same subject tuples or filtered entity IDs when calling
assertionComponentHasSupportingData) and update the tuple-to-userset validation
code (the tuple-to-userset branch inside assertionComponentHasSupportingData or
its helper) to resolve and verify the second hop (the computed hop like 'b' in
'a.b') for each candidate subject instance rather than only checking the first
hop; ensure you iterate per-entity-instance, confirm the computed-hop tuple
existence for that instance, and only then mark the assertion component as
covered.

---

Nitpick comments:
In `@pkg/development/coverage/coverage_test.go`:
- Around line 250-292: Add a follow-up test that prevents cross-entity-instance
false positives by asserting that coverage recorded for a check on one entity
instance is not satisfied by tuples on a different instance of the same entity
type: update the test file around the existing Case 2.1 (the
Run(file.Shape{...}) block) or add a new It() case that uses a Check with Entity
"document:1" while providing the supporting relationship tuple only on
"document:2" in the Relationships slice, then assert that the relevant
branch/component for "document:1" remains uncovered (use the same assertions you
have for EntityCoverageInfo[*].UncoveredAssertionComponents and
CoverageAssertionComponentsPercent to verify the branch is not marked covered
and TotalAssertionsCoverage reflects the uncovered branch).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c945891d-9fcb-4e8e-bb04-92204286ca00

📥 Commits

Reviewing files that changed from the base of the PR and between ba21b2e and 96f2490.

📒 Files selected for processing (3)
  • pkg/cmd/coverage.go
  • pkg/development/coverage/coverage.go
  • pkg/development/coverage/coverage_test.go

Comment thread pkg/development/coverage/coverage.go
@Iineman2
Copy link
Copy Markdown
Author

Addressed CodeRabbit's entity-instance coverage concern in commit 67a9baa. Component support is now scoped to the checked/filtered entity IDs, tuple-to-userset components verify the computed hop against the scenario subject, and Case 2.2 covers the cross-instance false-positive regression. Verification: go test ./pkg/cmd ./pkg/development/coverage.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
pkg/development/coverage/coverage_test.go (1)

250-292: ⚡ Quick win

Consider adding a comment to explain the TotalAssertionsCoverage calculation.

The test correctly verifies the new component-level coverage behavior. However, the expected TotalAssertionsCoverage value of 66% may not be immediately obvious to future maintainers. Consider adding a brief comment explaining how this value is derived (e.g., averaging component coverage across entities).

📝 Suggested comment addition
 		})).Should(Equal(true))
 		Expect(sci.EntityCoverageInfo[1].CoverageAssertionComponentsPercent["scenario 1"]).Should(Equal(33))
+		// TotalAssertionsCoverage averages component coverage across entities: (user:100% + document:33%) / 2 = 66%
 		Expect(sci.TotalAssertionsCoverage).Should(Equal(66))
 	})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/development/coverage/coverage_test.go` around lines 250 - 292, Add a
brief clarifying comment above the
Expect(sci.TotalAssertionsCoverage).Should(Equal(66)) assertion explaining how
66 is calculated (e.g., derive from component-level coverage: document has two
uncovered components out of three across the scenario => scenario component
coverage 33% and overall assertion coverage averages to 66%). Locate the check
in the test case "Case 2.1: Tracks partially covered permission conditions"
where the test inspects sci (the Run result) and the EntityCoverageInfo and
TotalAssertionsCoverage fields and insert the one-line comment to document the
calculation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pkg/development/coverage/coverage_test.go`:
- Around line 250-292: Add a brief clarifying comment above the
Expect(sci.TotalAssertionsCoverage).Should(Equal(66)) assertion explaining how
66 is calculated (e.g., derive from component-level coverage: document has two
uncovered components out of three across the scenario => scenario component
coverage 33% and overall assertion coverage averages to 66%). Locate the check
in the test case "Case 2.1: Tracks partially covered permission conditions"
where the test inspects sci (the Run result) and the EntityCoverageInfo and
TotalAssertionsCoverage fields and insert the one-line comment to document the
calculation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1d06ab12-1728-440e-8c49-8db39d33b92b

📥 Commits

Reviewing files that changed from the base of the PR and between 96f2490 and 67a9baa.

📒 Files selected for processing (2)
  • pkg/development/coverage/coverage.go
  • pkg/development/coverage/coverage_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/development/coverage/coverage.go

@Iineman2
Copy link
Copy Markdown
Author

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

github-actions Bot added a commit that referenced this pull request May 11, 2026
@Iineman2
Copy link
Copy Markdown
Author

recheck

@Iineman2
Copy link
Copy Markdown
Author

Iineman2 commented May 11, 2026

Added one more focused coverage improvement in commit 9b3572d: nested same-entity permissions now expand into their leaf components for the outer permission as well, with Case 2.3 covering view = can_view or owner. Verification: go test ./pkg/cmd ./pkg/development/coverage.

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.

Enhancing the 'Coverage' Command for Detailed Action/Permission Conditions

1 participant