Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Sep 10, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Corrects negation handling across SQL dialects for policy expressions.
    • Improves reliability of complex AND/OR logic via conditional parentheses.
    • Adds short-circuit simplifications for AND/OR (empty/single inputs, true/false).
    • Ensures consistent policy enforcement through the query builder for create operations.
  • Tests

    • Adds comprehensive update policy tests (allow/deny, this-member checks, default deny, auth-based rules, mixed policies, query builder paths).
    • Enhances create tests for mixed allow/deny policies and query builder behavior.
  • Refactor

    • Centralizes conditional parentheses handling to reduce expression-construction inconsistencies.

Copilot AI review requested due to automatic review settings September 10, 2025 06:07
@coderabbitai
Copy link

coderabbitai bot commented Sep 10, 2025

Walkthrough

Implements dialect-aware logical negation and centralized parentheses handling in policy expression utils, updates transformer call sites, and expands/introduces CRUD policy tests for create and update paths. Also adjusts conjunction/disjunction short-circuits and modifies test expectations/policies accordingly.

Changes

Cohort / File(s) Summary of changes
Policy negation & parentheses handling
packages/runtime/src/plugins/policy/utils.ts, packages/runtime/src/plugins/policy/expression-transformer.ts
Makes logicalNot accept a dialect and adds simplifications (true/false). Introduces wrapParensIf and updates conjunction/disjunction to handle empty/single cases and conditional parentheses. Updates transformer to call logicalNot with dialect for collection predicates and unary '!'.
CRUD create policy tests
packages/runtime/test/policy/crud/create.test.ts
Adds query-builder-based insert checks and adjusts mixed allow/deny policy (allow: x <= 0 || x > 1; deny: x <= 0) with updated expectations.
CRUD update policy tests
packages/runtime/test/policy/crud/update.test.ts
New test suite covering update permissions: scalar field checks, this-member rules, default-deny, deny rules, mixed allow/deny, and auth-based checks via db.$setAuth.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title concisely conveys the fix to policy logical combination handling and the addition of more update tests, reflecting the main changes in both the utility code and test files.

Poem

In burrows of logic, I twitch my nose,
Wrap parens neatly where the boolean grows.
NOT learns the dialect, hops left and right,
ANDs, ORs trimmed for a tidier bite.
Tests sprout like clover—green and bright—
Approve the carrots; deny the blight. 🥕🐇

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/update-policy

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.

@claude
Copy link

claude bot commented Sep 10, 2025

Claude finished @ymc9's task —— View job


Code Review Complete ✅

Reviewed PR: fix(policy): logical combination issue and more tests for update

Todo List:

  • Read and analyze all 4 changed files
  • Review policy logic changes in expression-transformer.ts and utils.ts
  • Review test additions and coverage
  • Check for code quality and best practices
  • Identify potential bugs or issues
  • Assess performance considerations
  • Check for security concerns
  • Provide comprehensive review feedback

Review Summary

This PR implements important fixes to the policy engine's logical combination handling and adds comprehensive test coverage for update operations. The changes are well-structured and address key issues in the expression transformation logic.

✅ Strengths

1. Logical Combination Fixes (utils.ts:49-86)

  • Early return optimizations: Added proper handling for empty arrays and single-element arrays in conjunction and disjunction functions
  • Consistent parentheses wrapping: Introduced wrapParensIf helper function for cleaner and more consistent parentheses handling
  • Improved code maintainability: Consolidated redundant logic across conjunction and disjunction functions

2. Expression Transformer Improvements (expression-transformer.ts:234,308)

  • Fixed function signature: Corrected logicalNot calls to include the required dialect parameter
  • API consistency: All logical operations now consistently accept dialect parameter for proper value transformation

3. Comprehensive Test Coverage

  • New update.test.ts: Adds 123 lines of comprehensive test coverage for update policies
  • Improved create.test.ts: Added Kysely query builder testing alongside ORM tests
  • Edge case testing: Tests mixed allow/deny rules, auth checks, and scalar field validation

4. Test Quality

  • Parallel testing patterns: Tests both ORM API (db.foo.update) and Kysely API (db.$qb.updateTable)
  • Realistic scenarios: Tests authentication-based policies and complex logical combinations
  • Proper assertions: Uses appropriate matchers like toBeRejectedNotFound() for update operations

🔍 Detailed Analysis

Logical Operations Fix (Critical)
The logicalNot, conjunction, and disjunction functions now properly handle:

  • Early returns for empty/single-element arrays (performance optimization)
  • Consistent parentheses wrapping using the new wrapParensIf helper
  • Proper boolean literal optimization (true/false nodes)

Expression Transformer Consistency
Lines 234 and 308 in expression-transformer.ts were missing the dialect parameter, which could have caused runtime errors or incorrect SQL generation.

Test Coverage Enhancement
The new test file mirrors the create test patterns but focuses on update-specific behavior, ensuring policy evaluation works correctly for existing records.

🚀 Performance Considerations

  • Early returns: New optimizations prevent unnecessary SQL generation for trivial logical expressions
  • Boolean literal folding: Proper handling of true/false nodes eliminates redundant SQL conditions
  • Reduced parentheses: wrapParensIf only adds parentheses when necessary

🔒 Security Assessment

  • Policy enforcement: Tests confirm that unauthorized updates are properly blocked
  • Authentication integration: Auth-based policies are tested and working correctly
  • No security vulnerabilities: Changes are focused on logical correctness without introducing attack vectors

📝 Minor Suggestions

  1. Documentation: Consider adding JSDoc comments to the new wrapParensIf helper function
  2. Test naming: Update test descriptions could be more specific about which logical operations they're testing
  3. Error messages: No improvements needed - existing error handling is appropriate

🎯 Overall Assessment

Score: 9/10

This is a high-quality PR that addresses important logical combination issues with proper testing. The fixes are necessary for correct policy evaluation, and the test coverage ensures reliability. The code follows established patterns and maintains consistency with the existing codebase.

Recommended Action: ✅ Approve and Merge

The changes are safe, well-tested, and fix genuine issues in the policy engine's logical expression handling.


Copy link
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

This PR fixes logical combination issues in the policy system and adds comprehensive test coverage for update operations. The changes improve the handling of logical operations (AND, OR, NOT) and ensure proper parenthesization in SQL generation.

  • Fixes logical combination handling with proper parenthesization and edge case management
  • Adds comprehensive test suite for update policy scenarios
  • Updates existing test to correct logical condition

Reviewed Changes

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

File Description
packages/runtime/test/policy/crud/update.test.ts New comprehensive test suite covering various update policy scenarios
packages/runtime/test/policy/crud/create.test.ts Adds query builder tests and fixes logical condition in existing test
packages/runtime/src/plugins/policy/utils.ts Improves logical combination functions with edge case handling and parenthesization
packages/runtime/src/plugins/policy/expression-transformer.ts Updates to use improved logicalNot function signature

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link

@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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/runtime/src/plugins/policy/expression-transformer.ts (1)

233-243: Fix swapped semantics for collection predicates: '!' vs '^'.

For quantifiers:

  • some ('?'): count(predicate) > 0
  • none ('!'): count(predicate) == 0
  • every ('^'): count(not predicate) == 0

Current code negates the predicate for '!' instead of '^', effectively swapping 'none' and 'every'. Move the negation to the '^' branch.

Apply:

-        if (expr.op === '!') {
-            predicateFilter = logicalNot(this.dialect, predicateFilter);
-        }
+        if (expr.op === '^') {
+            predicateFilter = logicalNot(this.dialect, predicateFilter);
+        }
🧹 Nitpick comments (3)
packages/runtime/test/policy/crud/create.test.ts (1)

76-76: Mixed allow/deny rule updated — precedence validated.

Allow now includes x <= 0 while deny blocks it; tests correctly keep 0 and 1 rejected and 2 allowed. Consider adding a sibling test that toggles parentheses (e.g., (x <= 0 || x > 1) && true) to guard against future precedence regressions.

packages/runtime/test/policy/crud/update.test.ts (1)

101-122: Auth-gated update path exercised.

Good use of db.$setAuth to flip authorization boundaries.

Add tests for collection predicates on update (some/none/every) to catch quantifier-negation regressions (e.g., posts ? { x > 0 }, posts ! { x > 0 }, posts ^ { x > 0 }).

packages/runtime/src/plugins/policy/utils.ts (1)

108-111: Nit: add JSDoc to clarify intent of wrapParensIf.

Tiny doc improves readability for future maintainers.

Apply:

-function wrapParensIf(node: OperationNode, predicate: (node: OperationNode) => boolean): OperationNode {
+/**
+ * Conditionally wrap the node in ParensNode when predicate(node) is true.
+ * If the node is already parenthesized, no additional wrapping is added.
+ */
+function wrapParensIf(node: OperationNode, predicate: (node: OperationNode) => boolean): OperationNode {
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ef27c7 and a9e739b.

📒 Files selected for processing (4)
  • packages/runtime/src/plugins/policy/expression-transformer.ts (2 hunks)
  • packages/runtime/src/plugins/policy/utils.ts (1 hunks)
  • packages/runtime/test/policy/crud/create.test.ts (2 hunks)
  • packages/runtime/test/policy/crud/update.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
{packages,samples,tests}/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place packages only under packages/, samples/, or tests/

Files:

  • packages/runtime/test/policy/crud/update.test.ts
  • packages/runtime/src/plugins/policy/expression-transformer.ts
  • packages/runtime/test/policy/crud/create.test.ts
  • packages/runtime/src/plugins/policy/utils.ts
🧬 Code graph analysis (3)
packages/runtime/test/policy/crud/update.test.ts (1)
packages/runtime/test/policy/utils.ts (1)
  • createPolicyTestClient (14-25)
packages/runtime/src/plugins/policy/expression-transformer.ts (1)
packages/runtime/src/plugins/policy/utils.ts (1)
  • logicalNot (92-106)
packages/runtime/src/plugins/policy/utils.ts (1)
packages/sdk/src/schema/schema.ts (1)
  • SchemaDef (10-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: claude-review
  • GitHub Check: build-test (20.x)
🔇 Additional comments (12)
packages/runtime/src/plugins/policy/expression-transformer.ts (1)

308-309: Good: dialect-aware NOT usage.

Passing this.dialect into logicalNot aligns with the updated utils API and ensures dialect-correct NOT generation.

packages/runtime/test/policy/crud/create.test.ts (1)

19-24: Nice: QB insert path covered.

Good to assert policy enforcement through the query builder, not just the model API.

packages/runtime/test/policy/crud/update.test.ts (5)

5-28: Solid coverage for scalar-check updates, including QB path.

Covers both model API and QB .updateTable() with row-count and returningAll() assertions.

If CI runs across multiple dialects, confirm returningAll() is supported or polyfilled for all of them; otherwise, gate or adjust expectations for dialects lacking RETURNING.


30-46: 'this' member check path covered.

Validates policy evaluation against instance values during update.


48-61: Default deny for update verified.

Good negative test to prevent permissive regressions.


63-78: Deny rule precedence confirmed for update.

Ensures @@deny('update', x <= 0) wins even with broad allow.


80-99: Mixed allow/deny update semantics validated.

Selective success/failure across rows is well asserted.

packages/runtime/src/plugins/policy/utils.ts (5)

53-58: Good short-circuiting for conjunction base cases.

Avoids reduce on empty arrays and returns identity/singleton correctly.


66-66: Correct precedence-preserving AND reduction.

Wrapping OR operands with Parens when combining via AND preserves intended grouping. Symmetric to OR-path below. LGTM.


73-78: Good short-circuiting for disjunction base cases.

Identity and singleton handling look correct and avoid unnecessary work.


86-86: Correct precedence-preserving OR reduction.

Wrapping AND operands with Parens under OR is a safe, dialect-agnostic way to retain grouping.


92-106: Manual verification of logicalNot call sites
Automated checks were inconclusive; ensure every invocation now passes both dialect and node.

@ymc9 ymc9 merged commit f01bcde into dev Sep 10, 2025
5 checks passed
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