Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gate,sdk)!: new policy spec #937

Merged
merged 14 commits into from
Dec 21, 2024
Merged

feat(gate,sdk)!: new policy spec #937

merged 14 commits into from
Dec 21, 2024

Conversation

michael-0acf4
Copy link
Contributor

@michael-0acf4 michael-0acf4 commented Dec 10, 2024

Migration notes

  • Replaced true, false, and null to ALLOW, DENY and PASS.

Composition rules:

  1. On traversal order:
  • ALLOW: allow parent and all its children (ignore inner policies)
  • DENY: deny parent and all its children (ignore inner policies)
  • PASS: pass through parent and evaluate each children (no-op, equivalent to no policies)
  1. On a single type (a.with_policy(X).with_policy(Y)):

ALLOW and DENY compose the same as true and false with the AND gate, PASS does not participate.

  • ALLOW & P = P
  • DENY & P = DENY (e.g. DENY & ALLOW = DENY)
  • PASS & P = P (does not participate)
  • The change comes with new or modified tests
  • Hard-to-understand functions have explanatory comments
  • End-user documentation is updated to reflect the change

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced documentation for Metatype's mental model, including clearer policy definitions and a comparison table with classical models.
    • Introduction of a comprehensive tutorial on building a Metatype API, covering setup, CRUD operations, and security practices.
  • Bug Fixes

    • Updated policy logic to return explicit 'ALLOW' or 'DENY' strings instead of boolean values across various components.
  • Documentation

    • Improved clarity and detail in documentation for policies and core concepts.
    • Added new sections for policy composition rules and traversal order.
  • Refactor

    • Streamlined policy management and evaluation logic across multiple files, enhancing clarity and maintainability.
  • Tests

    • Added tests for new policy functionalities and updated existing tests to reflect changes in policy handling.

@michael-0acf4 michael-0acf4 changed the title feat: policy spec feat: new policy spec Dec 10, 2024
@michael-0acf4 michael-0acf4 changed the title feat: new policy spec feat(gate)!: new policy spec Dec 12, 2024
@michael-0acf4 michael-0acf4 marked this pull request as ready for review December 18, 2024 19:15
@michael-0acf4 michael-0acf4 requested a review from a team December 18, 2024 19:15
@michael-0acf4
Copy link
Contributor Author

Note:

Yohe-Am
Yohe-Am previously approved these changes Dec 19, 2024
@Yohe-Am
Copy link
Contributor

Yohe-Am commented Dec 19, 2024

Nice, this will need a docs update though.

@michael-0acf4
Copy link
Contributor Author

@coderabbitai review

@michael-0acf4 michael-0acf4 changed the title feat(gate)!: new policy spec feat(gate,sdk)!: new policy spec Dec 19, 2024
Copy link
Contributor

coderabbitai bot commented Dec 19, 2024

Walkthrough

The pull request introduces a comprehensive update to Metatype's policy handling across multiple components. The changes focus on refining the policy evaluation mechanism by introducing a more explicit policy resolution system. Instead of using boolean returns, policies now return string-based outcomes: 'ALLOW', 'DENY', and 'PASS'. This modification enhances the clarity and granularity of access control logic throughout the Metatype framework, affecting documentation, runtime implementations, type definitions, and test cases.

Changes

File/Component Change Summary
Documentation Updated mental model and policy reference docs to explain new policy resolution mechanism
Runtime Implementations Modified policy handling in Deno, TypeGate, and other runtimes to support 'ALLOW', 'DENY', 'PASS' outcomes
Type Definitions Restructured policy handling in type systems, removing policies from scalar types and introducing more flexible policy management
Examples & Tests Updated policy definitions across multiple example typegraphs and test cases to use new string-based policy returns

Sequence Diagram

sequenceDiagram
    participant Client
    participant PolicyResolver
    participant TypeGraph
    participant Runtime

    Client->>PolicyResolver: Request Access
    PolicyResolver->>TypeGraph: Check Type Policies
    TypeGraph-->>PolicyResolver: Return Policy Chain
    PolicyResolver->>PolicyResolver: Evaluate Policy Chain
    alt Policy is ALLOW
        PolicyResolver->>Runtime: Execute Operation
        Runtime-->>Client: Return Result
    else Policy is DENY
        PolicyResolver-->>Client: Access Denied
    else Policy is PASS
        PolicyResolver->>PolicyResolver: Continue Evaluation
    end
Loading

This diagram illustrates the new policy resolution mechanism, showing how policies are now evaluated with more explicit outcomes, allowing for more nuanced access control.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

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

🔭 Outside diff range comments (2)
examples/typegraphs/roadmap-policies.py (1)

Security policy implementation needs strengthening

The admins policy currently only checks for the presence of a username (!!context.username), which is a weak security control for bucket creation. The policy should implement stronger authentication and authorization checks.

  • The same weak policy is consistently used across multiple files in the codebase
  • The policy lacks role-based checks, specific user validation, or other authorization constraints
  • No additional security policies are applied to bucket operations beyond this basic check
🔗 Analysis chain

Line range hint 73-78: Review security implications of policy usage

The admins policy is used to protect the create_bucket operation. This is a critical security boundary that needs careful review.


Let me gather more information about the security context by checking the policy definition and related security patterns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other uses of the admins policy
rg -A 3 "with_policy\(admins\)"

# Check for any bypass patterns
rg -A 3 "create_bucket.*without_policy"

Length of output: 1940


Script:

#!/bin/bash
# Search for admins policy definition
rg -A 5 "admins\s*=.*policy"

# Search for any policy-related patterns around bucket creation
ast-grep --pattern 'create_bucket = $$$'

# Check for any other security policies applied to buckets
rg -A 3 "bucket.*with_policy"

Length of output: 6249

src/typegate/src/runtimes/typegraph.ts (1)

Line range hint 498-508: Policy description formatting needs error handling.

The policy description logic could benefit from additional error handling for edge cases.

Consider adding error handling:

 policyDescription(policies: PolicyIndices[]): string {
   const describeOne = (p: number) => this.tg.policies[p].name;
   const describe = (p: PolicyIndices) => {
     if (typeof p === "number") {
-      return describeOne(p);
+      try {
+        return describeOne(p);
+      } catch (error) {
+        return `<invalid_policy:${p}>`;
+      }
     }
     return Object.entries(p)
       .map(([eff, polIdx]) => `${eff}:${describeOne(polIdx)}`)
       .join("; ");
   };

Also applies to: 512-516

🧹 Nitpick comments (37)
tests/policies/policies_composition.py (1)

55-73: Check consistency of policy usage within pass-through
“simple_traversal_comp” is exposed with a pass-through policy. Review if all nested fields that require denial or allow logic have correct fallback or override policies. Overlapping or conflicting policies can result in unexpected user experiences.

src/typegate/src/transports/graphql/typegraph.ts (2)

11-20: Consider type-level documentation for SplitResult
Splitting queries and mutations into a single SplitResult type is a good design decision. However, you might want to add JSDoc or inline comments clarifying the relationship between properties and policies for queries vs. mutations, especially for new contributors.


87-96: Extra caution when effect is null or "read"
The code checks for childMaterializer.effect.effect === null or "read". If additional effect types (e.g., "create", "update") are introduced in the future, ensure you handle them appropriately to avoid defaulting to queries.

src/typegraph/core/src/typedef/struct_.rs (2)

130-144: Potential performance overhead in collect_policies
Here, collect_policies iterates over each property and calls extend_policy_chain. This might be repeatedly traversing nested structures. If some large TypeStruct objects exist, consider introducing memoization or caching for repeated type graphs.


146-190: Be mindful of deep recursion
The extend_policy_chain function recurses for each type variant (union, either, list, etc.). Deeply nested or cyclical type definitions could exhaust stack space. Adding detection or maximum depth checks might be beneficial if cyclical references can appear.

tests/policies/policies_composition_test.ts (3)

9-32: Possible redundancy in test setup
“simple_traversal_comp” is tested multiple times under different contexts (ALLOW, PASS, DENY). Some repeated data structures could be factored out into a shared function or fixture for improved test maintenance.


75-116: Chain policy coverage
When combining multiple PASS with an ALLOW or DENY in the same request, ensure the test cases also include boundary scenarios or contradictory policies (e.g., multiple DENY policies). This helps confirm the compositional logic is robust.


223-251: Deep nested variant coverage
The test for diving through nested variants (First, Second) and encountering DENY at depth_4 is solid. Consider adding a “mixed” scenario, where not all extended branches are used, to ensure partial expansions or partial usage is equally validated.

I can provide an extended test scenario if desired.

src/typegate/src/runtimes/deno/deno.ts (1)

37-40: Predefined functions align with new policy outputs.
These changes properly return "ALLOW", "DENY", or "PASS" as strings, which is consistent with the new policy model. Good job.

Consider removing or deprecating the “true” and “false” predefined functions to reduce confusion, as the codebase now uses string-based policy evaluations.

src/typegate/src/engine/planner/policies.ts (1)

118-126: Preallocation of resolvers.
Efficiently populating #resolvers ensures minimal overhead at runtime.

You can simplify the ternary expression at line 118 by negating the parent check:

- isTopLevel: stage.props.parent ? false : true,
+ isTopLevel: !stage.props.parent,
examples/typegraphs/programmable-api-gateway.py (1)

20-22: LGTM! Consider adding a descriptive comment.

The policy change from boolean to 'ALLOW'/'DENY' aligns with the new policy specification.

Consider adding a comment explaining the random nature of this policy:

    roulette_access = deno.policy(
+       # Randomly allows/denies access with 50% probability
        "roulette", "() => Math.random() < 0.5 ? 'ALLOW' : 'DENY'"
    )
examples/typegraphs/programmable-api-gateway.ts (1)

Line range hint 20-26: Consider documenting the policy migration strategy.

The implementation of the new policy specification (ALLOW/DENY/PASS) is consistent across both Python and TypeScript files. However, given this is a breaking change, consider:

  1. Adding migration guides for users transitioning from boolean policies
  2. Documenting common patterns and best practices for the new policy system
  3. Including examples of complex policy compositions using ALLOW/DENY/PASS

Would you like me to help create a migration guide template or document common patterns?

examples/typegraphs/policies.py (1)

18-18: Enhance policy documentation

While the comment explains the return values, it would be helpful to add documentation about the new policy composition rules, especially how "PASS" affects the evaluation of subsequent policies.

Consider expanding the comment to include:

- # `public` is sugar for to `(_args, _ctx) => "PASS"`
+ # `public` is sugar for `(_args, _ctx) => "PASS"`
+ # Policy evaluation rules:
+ # - "ALLOW": Permits access and stops evaluation
+ # - "DENY": Denies access and stops evaluation
+ # - "PASS": Continues to evaluate other policies

Also applies to: 23-24

tests/policies/policies.py (1)

23-26: Consider safer number conversion

While the policy correctly returns "ALLOW"/"DENY", the Number conversion could be made more robust.

Consider this safer implementation:

- "(_args, { context }) => Number(context.a) === 2 ? 'ALLOW' : 'DENY'"
+ "(_args, { context }) => {
+    const value = Number(context.a);
+    return !isNaN(value) && value === 2 ? 'ALLOW' : 'DENY'
+ }"
src/typegate/src/typegraphs/prisma_migration.py (1)

29-30: LGTM! Consider adding a docstring.

The policy change correctly implements the new specification by returning explicit 'ALLOW'/'DENY' values instead of boolean. This aligns with the PR's objective of standardizing policy returns.

Consider adding a docstring to document the policy's purpose and return values:

admin_only = deno.policy(
    "admin_only",
    # Restricts access to admin users only
    # Returns: 'ALLOW' if username is 'admin', 'DENY' otherwise
    code="(_args, { context }) => context.username === 'admin' ? 'ALLOW' : 'DENY'",
)
examples/typegraphs/math.ts (1)

27-27: Consider security implications and code organization.

While the policy correctly implements the new ALLOW/DENY specification, there are some considerations:

  1. URL parsing could throw if the referer header is malformed
  2. The hostname whitelist logic is embedded in the policy code

Consider:

  1. Moving the hostname whitelist to a configuration
  2. Adding error handling for URL parsing
  3. Extracting the logic to a separate function

Example refactor:

const ALLOWED_HOSTS = ["localhost", "metatype.dev"];

function isAllowedReferer(referer: string): "ALLOW" | "DENY" {
  try {
    return ALLOWED_HOSTS.includes(new URL(referer).hostname) 
      ? "ALLOW" 
      : "DENY";
  } catch {
    return "DENY";
  }
}

// In policy:
'(_, context) => context.headers.referer ? isAllowedReferer(context.headers.referer) : "DENY"'
src/typegraph/core/src/typedef/either.rs (1)

16-16: Document policy implications for Either type

Given the significant changes to policy handling, we should document how the new ALLOW/DENY/PASS system affects Either types, particularly in terms of type validation and variant selection.

Consider adding documentation that explains:

  1. How policies affect variant selection
  2. Policy inheritance in nested Either types
  3. Interaction between Either type validation and policy evaluation

Also applies to: 22-35, 38-46

examples/typegraphs/reduce.py (1)

54-54: Policy return value updated correctly

The change from boolean to 'ALLOW'/'DENY' aligns with the new policy specification. The ternary operator correctly maps the username check to the appropriate policy values.

Consider adding a comment explaining the policy's behavior for future maintainers:

 admins = deno.policy(
     "admins",
-    "(_args, { context }) => !!context.username ? 'ALLOW' : 'DENY'",
+    // Only authenticated users (with username) can create buckets
+    "(_args, { context }) => !!context.username ? 'ALLOW' : 'DENY'",
 )
tests/policies/effects_py.py (1)

14-15: Consider documenting the policy behavior

The new deny_all policy implementation aligns with the new policy specification. However, since this is part of a breaking change, consider adding a comment explaining the policy's behavior and its relationship to the new policy system.

+    # Policy that denies access to all operations, replacing the previous boolean-based implementation
+    # Returns 'DENY' to align with the new policy specification
     deny_all = deno.policy("deny_all", "_ => 'DENY'")
examples/typegraphs/rest.py (1)

54-54: LGTM! Consider adding a docstring.

The policy change aligns with the new specification, correctly returning 'ALLOW' or 'DENY' based on username presence. Consider adding a docstring to document the policy's purpose and behavior.

docs/metatype.dev/docs/reference/policies/index.mdx (3)

20-21: Documentation needs clarification on PASS behavior.

While the update to use 'PASS' for the public policy is correct, it would be helpful to explain why PASS is preferred over ALLOW for the public policy, especially since it "provides everyone open access."


36-38: Consider adding examples for traversal order.

The definitions of ALLOW, DENY, and PASS are clear, but adding practical examples would help users better understand how these policies affect nested structures.

Example addition:

- `PASS`: Allows access to the parent, each descendant will still be evaluated individually (equivalent to having no policies set).
+ `PASS`: Allows access to the parent, each descendant will still be evaluated individually (equivalent to having no policies set).
+
+ For example:
+ ```typescript
+ const type = t.struct({
+   public_field: t.string(),
+   protected_field: t.string().with_policy(requireAuth)
+ }).with_policy(Policy.public())  // PASS allows individual field policies to be evaluated
+ ```
🧰 Tools
🪛 LanguageTool

[uncategorized] ~36-~36: Loose punctuation mark.
Context: ...on rules ### Traversal order - ALLOW: Allows access to the parent and all its...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~37-~37: Loose punctuation mark.
Context: ...s, disregarding inner policies. - DENY: Denies access to the parent and all its...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~38-~38: Loose punctuation mark.
Context: ...s, disregarding inner policies. - PASS: Allows access to the parent, each desce...

(UNLIKELY_OPENING_PUNCTUATION)


46-53: Add truth table for policy composition.

The composition rules would be clearer with a truth table showing all possible combinations of ALLOW, DENY, and PASS.

Example addition:

+ | Policy A | Policy B | Result |
+ |----------|----------|--------|
+ | ALLOW    | ALLOW    | ALLOW  |
+ | ALLOW    | DENY     | DENY   |
+ | ALLOW    | PASS     | ALLOW  |
+ | DENY     | ALLOW    | DENY   |
+ | DENY     | DENY     | DENY   |
+ | DENY     | PASS     | DENY   |
+ | PASS     | ALLOW    | ALLOW  |
+ | PASS     | DENY     | DENY   |
+ | PASS     | PASS     | PASS   |
tests/auth/auth.py (1)

24-25: Simplify the with_token policy implementation.

The policy implementation can be simplified by removing the unnecessary block and return statement.

- "with_token",
- "(_args, { context }) => { return !!context.accessToken ? 'ALLOW' : 'DENY'; }",
+ "with_token",
+ "(_args, { context }) => !!context.accessToken ? 'ALLOW' : 'DENY'",
src/typegraph/core/src/validation/materializers.rs (2)

52-62: Implementation of new policy validation looks good.

The validation logic for the new policy values (ALLOW, DENY, PASS) is well-implemented and consistent with the existing pattern. The string type validation ensures type safety for the new policy specification.

Would you like me to help generate additional test cases to cover these new policy validations?


51-62: Well-structured implementation of the new policy specification.

The changes demonstrate a cohesive approach to implementing the new policy specification:

  1. Removal of boolean-based policy handling from type definitions
  2. Addition of string-based policy validation in materializers
  3. Updated test cases and configurations

The implementation maintains type safety while providing more expressive policy controls through ALLOW, DENY, and PASS.

Consider documenting the migration path for existing users who need to update their policy implementations from boolean values to the new specification.

examples/typegraphs/func.ts (1)

59-59: Policy return value correctly implements new specification.

The change from boolean to 'ALLOW'/'DENY' aligns with the new policy specification. The implementation correctly handles the authorization based on username presence.

Consider adding a comment explaining the policy's behavior and its impact on bucket creation operations.

src/metagen/src/tests/fixtures.rs (1)

58-58: Consider documenting architectural implications.

Moving policies from TypeNodeBase to ObjectTypeData represents a significant architectural change. This might affect policy inheritance and composition patterns.

Consider:

  1. Documenting the rationale behind moving policies to ObjectTypeData
  2. Updating architecture documentation to reflect this change
  3. Verifying that this change doesn't break existing policy inheritance patterns
tests/planner/planner_test.ts (1)

39-40: LGTM! Consider adding type annotations for clarity.

The simplification of policy tree verification using stageToPolicies is a good improvement. However, consider adding type annotations to make the code more maintainable:

-    const stageToPolicies = Object.fromEntries(plan.policies.stageToPolicies);
+    const stageToPolicies: Record<string, unknown> = Object.fromEntries(plan.policies.stageToPolicies);
tests/policies/policies_test.ts (2)

229-229: Fix typo in test description.

-  await t.should("succeed", async () => {
+  await t.should("should succeed", async () => {

253-253: Consider documenting policy behavior in comments.

The inline comments about policy denial conditions could be more explicit about the new policy specification:

-          password_hash # deny if role!=admin (here undefined) on effect update
+          password_hash # DENY if role!=admin (here undefined) on effect update
-          password_hash # deny on effect read
+          password_hash # DENY on effect read

Also applies to: 265-265

docs/metatype.dev/docs/concepts/mental-model/index.mdx (1)

94-96: LGTM! Clear documentation of new policy specification.

The documentation clearly defines the new policy terms (ALLOW, DENY, PASS) and their hierarchical impact on access control. The explanations are concise and align well with the implementation changes.

Consider adding examples for each policy decision to illustrate their behavior in practice:

For example:
- `ALLOW`: If applied to a User type, grants access to all user fields without checking inner policies
- `DENY`: If applied to an Order type, prevents access to the order and all its line items
- `PASS`: If applied to a Product type, allows access to the product while evaluating policies on its reviews
🧰 Tools
🪛 LanguageTool

[uncategorized] ~94-~94: Loose punctuation mark.
Context: ... The policy decision can be: - ALLOW: Grants access to the current type and a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~95-~95: Loose punctuation mark.
Context: ...t type and all its descendants. - DENY: Restricts access to the current type an...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~96-~96: Loose punctuation mark.
Context: ...t type and all its descendants. - PASS: Grants access to the current type while...

(UNLIKELY_OPENING_PUNCTUATION)

src/typegate/src/typegraph/types.ts (1)

64-64: LGTM! Well-structured policy definition.

The new policy structure using Record<string, PolicyIndices[]> provides better organization and clarity compared to the previous flat array approach. This change aligns well with the new policy specification and enables more granular policy control at the object level.

Consider documenting the expected string keys in the Record to help maintain consistency across the codebase.

src/typegate/src/typegraphs/typegate.py (1)

100-101: Consider handling the PASS case in the policy.

The policy implementation correctly uses the new 'ALLOW'/'DENY' specification. However, given that the PR introduces PASS as a valid policy response, consider if there are scenarios where this policy should return 'PASS' instead of 'DENY'.

-        code="(_args, { context }) => context.username === 'admin' ? 'ALLOW' : 'DENY' ",
+        code="""(_args, { context }) => {
+            if (context.username === 'admin') return 'ALLOW';
+            // Add conditions for PASS if needed
+            return 'DENY';
+        }""",
src/typegate/src/runtimes/typegate.ts (1)

557-582: New getPolicies function improves policy handling.

The function properly encapsulates policy extraction logic and handles both simple indices and complex policy objects. However, consider adding error handling for invalid policy indices.

Consider adding error handling:

 const fmtedIndices = indices.map((index) => {
   if (typeof index === "number") {
+    if (index < 0 || index >= tg.policies.length) {
+      throw new Error(`Invalid policy index: ${index}`);
+    }
     return tg.policy(index).name;
   }
src/typegraph/core/src/typegraph.rs (1)

324-333: Policy chain extension implementation aligns with new specification.

The implementation correctly extends and registers policy chains, supporting the new ALLOW/DENY/PASS specification. However, consider adding documentation for the policy chain behavior.

Add documentation above the policy chain extension:

+// Extends the policy chain for the given type, incorporating inheritance rules:
+// - ALLOW permits parent and all children while ignoring inner policies
+// - DENY prohibits parent and all children
+// - PASS allows evaluation of each child without affecting parent
 let mut policy_chain = vec![];
 extend_policy_chain(&mut policy_chain, type_id)?;
docs/metatype.dev/docs/tutorials/metatype-basics/index.mdx (1)

584-584: Document all policy return values

While the code correctly implements the new policy specification using 'ALLOW' and 'DENY', the tutorial should also explain the 'PASS' option and its behavior in policy composition.

Consider adding a section explaining all three policy return values and their composition rules:

  • ALLOW: permits parent and all children
  • DENY: prohibits parent and all children
  • PASS: allows evaluation of each child without affecting parent

Also applies to: 622-622

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea8711f and 75bea33.

⛔ Files ignored due to path filters (10)
  • src/typegraph/core/src/snapshots/typegraph_core__tests__successful_serialization.snap is excluded by !**/*.snap
  • tests/e2e/typegraph/__snapshots__/typegraph_test.ts.snap is excluded by !**/*.snap
  • tests/planner/__snapshots__/planner_test.ts.snap is excluded by !**/*.snap
  • tests/query_parsers/__snapshots__/query_parsers_test.ts.snap is excluded by !**/*.snap
  • tests/runtimes/graphql/__snapshots__/graphql_test.ts.snap is excluded by !**/*.snap
  • tests/runtimes/grpc/__snapshots__/grpc_test.ts.snap is excluded by !**/*.snap
  • tests/runtimes/kv/__snapshots__/kv_test.ts.snap is excluded by !**/*.snap
  • tests/runtimes/s3/__snapshots__/s3_test.ts.snap is excluded by !**/*.snap
  • tests/runtimes/temporal/__snapshots__/temporal_test.ts.snap is excluded by !**/*.snap
  • tests/runtimes/typegate/__snapshots__/typegate_prisma_test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (67)
  • docs/metatype.dev/docs/concepts/mental-model/index.mdx (1 hunks)
  • docs/metatype.dev/docs/reference/policies/index.mdx (2 hunks)
  • docs/metatype.dev/docs/tutorials/metatype-basics/index.mdx (2 hunks)
  • examples/typegraphs/execute.py (1 hunks)
  • examples/typegraphs/execute.ts (1 hunks)
  • examples/typegraphs/func.py (1 hunks)
  • examples/typegraphs/func.ts (1 hunks)
  • examples/typegraphs/math.py (1 hunks)
  • examples/typegraphs/math.ts (1 hunks)
  • examples/typegraphs/policies-example.py (1 hunks)
  • examples/typegraphs/policies.py (1 hunks)
  • examples/typegraphs/policies.ts (1 hunks)
  • examples/typegraphs/programmable-api-gateway.py (1 hunks)
  • examples/typegraphs/programmable-api-gateway.ts (1 hunks)
  • examples/typegraphs/reduce.py (1 hunks)
  • examples/typegraphs/reduce.ts (1 hunks)
  • examples/typegraphs/rest.py (1 hunks)
  • examples/typegraphs/rest.ts (1 hunks)
  • examples/typegraphs/roadmap-policies.py (1 hunks)
  • examples/typegraphs/roadmap-policies.ts (1 hunks)
  • src/common/src/typegraph/types.rs (1 hunks)
  • src/metagen/src/fdk_rust/stubs.rs (1 hunks)
  • src/metagen/src/fdk_rust/types.rs (8 hunks)
  • src/metagen/src/tests/fixtures.rs (1 hunks)
  • src/typegate/src/engine/planner/args.ts (13 hunks)
  • src/typegate/src/engine/planner/mod.ts (5 hunks)
  • src/typegate/src/engine/planner/policies.ts (1 hunks)
  • src/typegate/src/engine/typecheck/result.ts (0 hunks)
  • src/typegate/src/runtimes/deno/deno.ts (2 hunks)
  • src/typegate/src/runtimes/typegate.ts (2 hunks)
  • src/typegate/src/runtimes/typegraph.ts (5 hunks)
  • src/typegate/src/transports/graphql/typegraph.ts (6 hunks)
  • src/typegate/src/typegraph/mod.ts (0 hunks)
  • src/typegate/src/typegraph/types.ts (1 hunks)
  • src/typegate/src/typegraphs/introspection.json (7 hunks)
  • src/typegate/src/typegraphs/prisma_migration.json (9 hunks)
  • src/typegate/src/typegraphs/prisma_migration.py (1 hunks)
  • src/typegate/src/typegraphs/typegate.json (20 hunks)
  • src/typegate/src/typegraphs/typegate.py (1 hunks)
  • src/typegraph/core/src/conversion/types.rs (2 hunks)
  • src/typegraph/core/src/global_store.rs (2 hunks)
  • src/typegraph/core/src/lib.rs (1 hunks)
  • src/typegraph/core/src/typedef/boolean.rs (1 hunks)
  • src/typegraph/core/src/typedef/either.rs (1 hunks)
  • src/typegraph/core/src/typedef/file.rs (2 hunks)
  • src/typegraph/core/src/typedef/float.rs (1 hunks)
  • src/typegraph/core/src/typedef/func.rs (0 hunks)
  • src/typegraph/core/src/typedef/integer.rs (1 hunks)
  • src/typegraph/core/src/typedef/list.rs (1 hunks)
  • src/typegraph/core/src/typedef/optional.rs (1 hunks)
  • src/typegraph/core/src/typedef/string.rs (1 hunks)
  • src/typegraph/core/src/typedef/struct_.rs (3 hunks)
  • src/typegraph/core/src/typedef/union.rs (1 hunks)
  • src/typegraph/core/src/typegraph.rs (3 hunks)
  • src/typegraph/core/src/validation/materializers.rs (1 hunks)
  • src/typegraph/deno/src/types.ts (2 hunks)
  • src/typegraph/python/typegraph/t.py (1 hunks)
  • tests/auth/auth.py (1 hunks)
  • tests/e2e/typegraph/typegraphs/deno/simple.ts (1 hunks)
  • tests/e2e/typegraph/typegraphs/python/simple.py (1 hunks)
  • tests/planner/planner_test.ts (1 hunks)
  • tests/policies/effects_py.py (1 hunks)
  • tests/policies/policies.py (1 hunks)
  • tests/policies/policies_composition.py (1 hunks)
  • tests/policies/policies_composition_test.ts (1 hunks)
  • tests/policies/policies_test.ts (5 hunks)
  • tests/utils/bindings_test.ts (1 hunks)
💤 Files with no reviewable changes (3)
  • src/typegate/src/engine/typecheck/result.ts
  • src/typegate/src/typegraph/mod.ts
  • src/typegraph/core/src/typedef/func.rs
👮 Files not reviewed due to content moderation or server errors (3)
  • src/typegate/src/typegraphs/typegate.json
  • src/typegraph/python/typegraph/t.py
  • src/typegate/src/engine/planner/args.ts
🧰 Additional context used
🪛 LanguageTool
docs/metatype.dev/docs/concepts/mental-model/index.mdx

[uncategorized] ~94-~94: Loose punctuation mark.
Context: ... The policy decision can be: - ALLOW: Grants access to the current type and a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~95-~95: Loose punctuation mark.
Context: ...t type and all its descendants. - DENY: Restricts access to the current type an...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~96-~96: Loose punctuation mark.
Context: ...t type and all its descendants. - PASS: Grants access to the current type while...

(UNLIKELY_OPENING_PUNCTUATION)

docs/metatype.dev/docs/reference/policies/index.mdx

[uncategorized] ~36-~36: Loose punctuation mark.
Context: ...on rules ### Traversal order - ALLOW: Allows access to the parent and all its...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~37-~37: Loose punctuation mark.
Context: ...s, disregarding inner policies. - DENY: Denies access to the parent and all its...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~38-~38: Loose punctuation mark.
Context: ...s, disregarding inner policies. - PASS: Allows access to the parent, each desce...

(UNLIKELY_OPENING_PUNCTUATION)

🪛 Biome (1.9.4)
src/typegate/src/runtimes/typegraph.ts

[error] 547-547: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/typegate/src/engine/planner/mod.ts

[error] 118-118: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

🔇 Additional comments (85)
tests/policies/policies_composition.py (1)

82-87: Validate single-field composition anchoring
When multiple calls to .with_policy(...) are chained on the same field, the final effective policy is not always obvious. Verify that each with_policy invocation is order-independent or explicit about override behavior, ensuring that future maintainers clearly understand the resolution order.

src/typegate/src/transports/graphql/typegraph.ts (1)

53-73: Ensure consistent namespace registration
Currently, if child.queries.properties has keys and child.mutations.properties has keys, both are added to the namespaces array. If more complex or deeper splits occur, ensure no collisions occur in the typegraph when multiple nested objects use the same root propertyName.

src/typegraph/core/src/typedef/struct_.rs (1)

83-83: Validate empty policy chains
When no policies are collected, the returned map is empty. Confirm that downstream code can handle an empty policies map without causing a runtime or logic error.

src/typegate/src/runtimes/deno/deno.ts (1)

26-26: No issues found importing PolicyResolverOutput.
This import indicates the new policy return type. Looks consistent with the rest of the changes.

src/typegate/src/engine/planner/policies.ts (23)

4-4: Logger import.
Importing Logger from "@std/log" is correct. No issues.


18-25: Additional imports from type_node.
The usage of these utility functions (e.g., isFunction, isUnion) appears consistent.


28-33: Introduction of PolicyResolverOutput and GetResolverResult.
This shift from boolean or null to string-based states is well-defined for clarity in policy checks. Looks good.


34-38: StageMetadata interface changes.
Adding the 'node' property is a helpful improvement, as it gives a more descriptive handle on each stage's field name.


41-45: ComposePolicyOperand interface.
Defining the canonical field name and index clarifies policy application points.


49-53: CheckResult union type improvement.
Handling "ALLOW" | "PASS" | "DENY" states is in line with the new string-based policy evaluation approach.


60-66: PolicyForStage interface introduction.
Clear association of a canonical field name with one or multiple policy indices. Good for modular policy checks per stage.


67-70: EXPOSE_STAGE_ID constant.
Using a unique string ID to represent the root policy anchor is a neat approach. No concerns.


72-82: Private fields and constructor rework.
Storing #stageToPolicies and #resolvers in a Map provides clean data structures for policy retrieval.


84-96: #prepareStageToPolicies logic.
Hoisting policies for exposed functions at the root level is consistent with your design. Ensuring each top-level function has a policy is a good safeguard.


97-102: Handling stage metadata in #prepareStageToPolicies.
Properly retrieving policies for each stage is clear. Good use of stageId as a map key.


127-148: Visibility checks for DenoRuntime.
Verifying that policies must run on DenoRuntime is consistent with your new approach. No issues here.


154-160: Documentation comment on policy states.
Your doc comment clearly summarizes how "ALLOW", "PASS", and "DENY" should be handled during traversal.


236-257: #getRejectionReason method.
Constructing a detailed error message helps users quickly pinpoint the failing policy.


259-300: #createPolicyEvaluator.
Caching policy outputs avoids redundant calls, improving performance. This is a prudent design choice.


302-356: #composePolicies refactor.
• Adopting ALLOW / DENY / PASS semantics is significantly more explicit than booleans.
• Short-circuiting on DENY to fail fast is optimal.


359-380: #getPolicies for union/either types.
Flattening union and either types is the right approach to gather their policies iteratively.


382-390: Handling object policies differently.
Extracting field-based policies is clean. Straightforward ownership of policies.


393-399: #getEffectOrNull method.
Identifying the effect from a function type’s materializer is essential for accurate read/write enforcement.


404-434: #checkStageAuthorization logic.
• Gathering selected fields and matching them with relevant policies is well-structured.
• Great fallback to throw a BadContext if a policy is missing for the requested effect.


438-442: Compose policies invocation.
Your appended method call ensures a unified decision at each stage. Good encapsulation.


445-454: #findSelectedFields method.
Matching stageId to parent references is a clear approach to figure out relevant fields. Solid logic.


457-459: Getter for stageToPolicies.
Exposing #stageToPolicies is practical for test verifications or debug output.

src/typegate/src/engine/planner/mod.ts (6)

21-21: Importing OperationPolicies & StageMetadata.
A direct usage of these new classes and interfaces is consistent with the updated policy framework.


106-127: Creating ordered stage metadata & OperationPolicies instance.
• Constructing a custom StageMetadata array is a clear foundation for policy assignments.
• Good approach using isTopLevel to differentiate root vs. nested stages.

🧰 Tools
🪛 Biome (1.9.4)

[error] 118-118: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


130-130: Returning policies in Plan.
Exposing OperationPolicies within the plan for downstream use is a clean design.


341-344: Refactor note: traverseField signature.
No functional changes here, but the clarity in parameter lines is good.


444-446: traverseValueField signature.
Again, primarily a formatting or minor change for clarity. Looks good.


571-580: Handling wrapped output.
Unwrapping multiple layers of quantifiers ensures correct traversal for deeply nested array or optional return types.

examples/typegraphs/policies-example.py (1)

13-17: Adopting new policy strings.
• "() => 'PASS'" and "() => 'ALLOW'" align perfectly with the updated spec.
• The ternary in team_only is direct and clear: 'ALLOW' if admin, otherwise 'DENY'.

tests/e2e/typegraph/typegraphs/python/simple.py (1)

26-26: LGTM! Policy change correctly implemented.

The change from false to 'DENY' aligns with the new policy specification and maintains the same semantic meaning in the test context.

examples/typegraphs/programmable-api-gateway.ts (1)

20-20: LGTM! Implementation consistent with Python version.

The policy change from boolean to 'ALLOW'/'DENY' aligns with the new policy specification and maintains consistency with its Python counterpart.

Let's verify the consistency between Python and TypeScript implementations:

✅ Verification successful

Verified: Python and TypeScript implementations are consistent

Both implementations use identical policy logic:

  • Python: "roulette", "() => Math.random() < 0.5 ? 'ALLOW' : 'DENY'"
  • TypeScript: "roulette", "() => Math.random() < 0.5 ? 'ALLOW' : 'DENY'"

The policy usage in g.expose() is also consistent across both implementations, where they correctly switch between public and roulette_access policies based on the access value.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Compare policy implementations across Python and TypeScript files
# Expected: Both files should use the same policy return values

echo "Checking Python implementation:"
rg -A 1 "roulette.*Math\.random" examples/typegraphs/programmable-api-gateway.py

echo "Checking TypeScript implementation:"
rg -A 1 "roulette.*Math\.random" examples/typegraphs/programmable-api-gateway.ts

Length of output: 392


Script:

#!/bin/bash
# Let's try a different approach to find and compare the policy implementations

echo "Python implementation:"
rg -B 2 -A 2 "roulette" examples/typegraphs/programmable-api-gateway.py

echo -e "\nTypeScript implementation:"
rg -B 2 -A 2 "roulette" examples/typegraphs/programmable-api-gateway.ts

Length of output: 1263

tests/e2e/typegraph/typegraphs/deno/simple.ts (2)

44-44: Verify consistent string format across policies

The policy return value uses single quotes ('DENY'). Let's verify if this is consistent with other policy implementations.

✅ Verification successful

Let me gather more information about policy implementations to ensure we have a complete view.


Let me check if there are any other policy implementations using boolean returns that might need to be updated.


Policy string format is consistent

The change to use single quotes for the 'DENY' string literal is consistent with the codebase, as it's the only policy implementation found. No other policies with boolean returns were found that would need updating.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for policy string literals across the codebase
rg -g '*.{ts,js}' "policy\(.*=>.*['\"](?:ALLOW|DENY|PASS)['\"]"

Length of output: 171


Script:

#!/bin/bash
# Search for all policy definitions to see different return formats
rg -g '*.{ts,js}' 'policy\(.*=>.*\)' -A 1

Length of output: 207


Script:

#!/bin/bash
# Search for policy definitions with boolean returns
rg -g '*.{ts,js}' 'policy\(.*=>.*(?:true|false)'

Length of output: 50


44-44: Consider updating other policies in the file

While the deny policy has been updated to return 'DENY', the file still uses Policy.public() and Policy.internal(). These might need to be updated to align with the new policy specification.

src/typegraph/core/src/typedef/boolean.rs (1)

Line range hint 19-29: Verify removal of policy handling is intentional

The context parameter is no longer used and policy handling has been removed from BaseBuilderInit. Please confirm this is intentional as part of the policy system refactoring.

✅ Verification successful

Removal of policy handling from boolean.rs is consistent with codebase changes

Looking at the search results, we can see that policy handling has been centralized in struct_.rs and typegraph.rs, where extend_policy_chain and related policy functions are implemented. The context parameter (ctx) is still present in implementations that need policy handling (like struct_.rs), while simpler types like boolean.rs, integer.rs, float.rs, and file.rs have removed it (using _ctx) as they don't participate in policy chains.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other TypeConversion implementations that might still use context for policies
ast-grep --pattern 'impl TypeConversion for $_ {
  $$$
  fn convert(&self, ctx: &mut TypegraphContext, $$$) {
    $$$
  }
}'

Length of output: 126


Script:

#!/bin/bash
# Let's try a broader search for TypeConversion implementations
rg "impl TypeConversion" -A 5

# Also search for any remaining policy-related code
rg "policy" --type rust

# Check the trait definition itself
rg "trait TypeConversion" -A 5

Length of output: 13168

examples/typegraphs/policies.py (1)

Line range hint 35-40: Verify policy composition behavior

The both function combines user_only and admin_only policies. Under the new policy specification, we should verify the composition behavior.

✅ Verification successful

The previous search might have been too specific. Let's broaden our search to understand the policy composition behavior and its tests.


Let's search for tests, implementation details, and documentation about policy composition to understand the expected behavior.


Let's examine the test files to understand how policy composition is tested and what behavior is expected.


Based on the codebase analysis, I can now provide a final response about the policy composition behavior:

Policy composition with multiple policies follows a chain-based evaluation

When multiple policies are provided to with_policy(), they form a policy chain where:

  • Each policy in the chain is evaluated in order
  • If any policy returns 'DENY', access is denied
  • If all policies return 'null', access is denied
  • Access is granted only if at least one policy returns 'ALLOW' and no policy returns 'DENY'

This is evidenced by:

  • The implementation in src/typegraph/python/typegraph/t.py showing policy chains being concatenated
  • The example in examples/typegraphs/policies.py demonstrating the composition of user_only and admin_only policies
  • Multiple test cases showing policy composition patterns across the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for test cases covering multiple policy composition
rg -g '*test*.{py,ts}' -A 5 -B 5 'with_policy.*,.*\)'

Length of output: 55


Script:

#!/bin/bash
# Search for policy composition tests with a broader pattern
rg -g '*.{py,ts}' -A 5 -B 5 'with_policy'

# Also search for policy-related test files
fd 'test.*policy.*' -e py -e ts

# Look for policy composition implementation
ast-grep --pattern 'with_policy($$$)'

Length of output: 57078


Script:

#!/bin/bash
# Search for policy composition tests specifically
rg -g '*.py' -A 5 -B 5 'with_policy.*,.*\).*#.*test'

# Look for policy composition implementation details
ast-grep --pattern 'class Policy {
  $$$
  public() {
    $$$
  }
  $$$
}'

# Search for policy composition documentation
rg -g '*.{md,py}' -A 5 -B 5 'policy.*composition|multiple.*policies'

Length of output: 661


Script:

#!/bin/bash
# Look for policy composition test file content
cat tests/policies/policies.py

# Search for policy composition behavior in test files
rg -g 'test_*.py' -A 10 -B 10 'with_policy.*admin_only.*user_only'

# Look for policy-related test files
fd 'test.*policy.*' -e py -e ts -x cat {}

Length of output: 1777

examples/typegraphs/policies.ts (3)

16-16: LGTM: Comment accurately reflects new policy spec

The comment correctly documents that public is sugar for returning "PASS", aligning with the new policy specification.


21-22: LGTM: Admin policy correctly implements new spec

The policy correctly:

  • Uses optional chaining for safe context access
  • Returns "ALLOW"/"DENY" according to new spec
  • Includes clear documentation of return values

26-26: LGTM: User policy follows consistent pattern

The implementation mirrors the admin policy pattern, maintaining consistency in the codebase.

tests/policies/policies.py (1)

20-21: LGTM: Basic policies correctly implement new spec

The pol_pass and pol_deny policies correctly return the new string literals "PASS" and "DENY" respectively.

src/typegraph/core/src/conversion/types.rs (1)

6-7: LGTM! Verify impact on dependent code.

The removal of policy-related fields and lifetime parameters simplifies the type system, which aligns with the PR's objectives. The changes look correct and improve maintainability.

Let's verify the impact on dependent code:

Also applies to: 23-25

✅ Verification successful

The removal of policy-related fields and lifetime parameters is safe

The search results confirm that the changes to BaseBuilder and BaseBuilderInit are safe:

  1. All usages of BaseBuilderInit have been updated to the new simplified version without lifetime parameters, as seen in various typedef files (e.g., either.rs, integer.rs, struct_.rs).
  2. While there are still policy-related code in other parts of the codebase, they are not directly related to the BaseBuilder types being modified.
  3. The changes align with the gradual removal of the old policy system, as evidenced by the remaining policy code being in different components.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to the removed policy fields
rg -t rust "policies.*BaseBuilder|BaseBuilder.*policies" 

# Search for any code still using lifetime parameters with BaseBuilderInit
ast-grep --pattern 'BaseBuilderInit<$_>'

Length of output: 101


Script:

#!/bin/bash
# Let's try a broader search for BaseBuilder and BaseBuilderInit usage
rg -t rust "BaseBuilder|BaseBuilderInit" -A 3

# Also search for any policy-related code in the type system
rg -t rust "policy|policies" src/typegraph/core/src/

# Check if there are any other files importing these types
rg -t rust "use.*BaseBuilder|use.*BaseBuilderInit"

Length of output: 17640

examples/typegraphs/roadmap-policies.ts (1)

53-53: Verify policy propagation in nested operations

The admins policy is applied to create_bucket, but we need to verify how it affects nested operations on ideas and votes within the bucket.

Also applies to: 57-65

src/typegraph/core/src/typedef/union.rs (1)

16-16: Verify policy evaluation after builder refactoring

The removal of policy fields from BaseBuilderInit suggests policy evaluation has been moved. We need to ensure Union types properly handle the new ALLOW/DENY/PASS policy system in their new evaluation location.

Also applies to: 22-35

✅ Verification successful

Based on the search results, I can now generate the final response as we have sufficient information about the policy handling in the codebase.

Policy evaluation has been properly refactored to a new system

The removal of policy fields from BaseBuilderInit is part of a larger architectural change where policy evaluation has been moved to a more robust ALLOW/DENY/PASS system. The search results confirm:

  • Policy evaluation is now standardized across types (including Unions) using a clear tri-state system ("ALLOW", "DENY", "PASS")
  • Policies are hierarchical, starting with denial by default
  • Multiple policies can be composed, with clear evaluation order
  • The new system supports both field-level and type-level policies
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify policy handling for Union types
# Look for new policy evaluation location

# Search for Union policy evaluation
ast-grep --pattern 'impl $trait for Union {
  $$$
  fn $method($$$) {
    $$$
    policy
    $$$
  }
}'

# Search for new policy handling structure
rg -A 10 "policy.*(?i)(allow|deny|pass)"

Length of output: 11882

src/typegraph/core/src/typedef/either.rs (1)

16-16: Ensure consistent policy handling across type system

The changes in Either type mirror those in Union, suggesting a systematic refactoring. We should verify that all type implementations consistently handle the new ALLOW/DENY/PASS policy system.

Also applies to: 22-35

✅ Verification successful

Let me gather more specific information about the policy handling in type implementations.


Policy handling is consistently implemented across type system

The codebase shows a systematic implementation of policy handling:

  • Either type correctly implements policy handling through the extend_policy_chain function, similar to Union
  • Policy propagation is consistently implemented for all composite types (Either, Union, Optional, List, Func)
  • The implementation in either.rs follows the same pattern as other types, with proper TypeId handling
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check consistency of policy handling across types
# Look for inconsistencies in policy implementation

# Search for policy handling patterns across all type implementations
fd -e rs -e ts . | xargs rg -A 5 "impl.*(?i)(policy|allow|deny|pass)"

# Check for potential missed refactoring
ast-grep --pattern 'impl TypeConversion for $type {
  $$$
  fn convert($$$) {
    $$$
    policy
    $$$
  }
}'

Length of output: 4783


Script:

#!/bin/bash
# Search for policy-related code in type implementations
rg -A 10 "impl.*(?:Either|Union|Type)" src/typegraph/core/src/typedef/

# Check for convert/type conversion implementations
ast-grep --pattern 'impl $_ for Either {
  $$$
}'

# Look for policy-related functions in type definitions
rg -A 5 "(?i)policy" src/typegraph/core/src/typedef/

Length of output: 35548

examples/typegraphs/roadmap-policies.py (1)

59-59: Verify policy string values are handled correctly

The change from boolean to string-based policy ('ALLOW'/'DENY') aligns with the new policy spec. However, we should verify that all consumers of this policy handle these string values correctly.

✅ Verification successful

Let's try a broader search to find policy implementations and their handling across the codebase. This will help us verify the consistency of policy return values and how they are processed.


Based on the search results, I can now generate the final response. The codebase shows consistent usage of 'ALLOW'/'DENY' string values across all policy implementations, and there's a clear pattern of policy handling:

Policy string values are handled consistently across the codebase

The change from boolean to 'ALLOW'/'DENY' strings aligns with the established pattern in the codebase. Evidence shows:

  • All policy implementations consistently use 'ALLOW'/'DENY' return values
  • The policy system is designed to handle these string values, as seen in multiple examples:
    • Core policy handling in src/typegraph/core/src/lib.rs uses 'ALLOW'/'DENY' format
    • Multiple policy implementations across different features use the same pattern
    • Built-in policy helpers like Policy.public(), Policy.context() all follow this convention
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other policy implementations to ensure consistent usage
rg -l "(_args, \{ context \})" | xargs rg "=> (true|false)"

# Search for policy evaluation code to verify string handling
ast-grep --pattern 'policy($_) {
  $$$
  return $_;
}'

Length of output: 118


Script:

#!/bin/bash
# Search for policy implementations with boolean returns
rg "=> (true|false)" -A 2 -B 2

# Search for ALLOW/DENY string usage in policies
rg "'(ALLOW|DENY)'" -A 2 -B 2

# Search for policy evaluation/handling code
rg "policy\(" -A 3 -B 3

Length of output: 65633

examples/typegraphs/reduce.ts (1)

52-52: Ensure consistent policy implementation across languages

The TypeScript implementation matches the Python version, using the same string values ('ALLOW'/'DENY'). This consistency is good for maintainability.

✅ Verification successful

Policy implementation is consistent across TypeScript and Python files

The verification shows that the policy implementation using 'ALLOW'/'DENY' string literals and the context.username check is consistently implemented across both TypeScript and Python files in the examples/typegraphs directory. The pattern (_args, { context }) => !!context.username ? 'ALLOW' : 'DENY' is identical in both languages.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any inconsistencies in policy string values across languages
rg -t ts "(_args, \{ context \}.*ALLOW.*DENY)"
rg -t py "(_args, \{ context \}.*ALLOW.*DENY)"

Length of output: 1705

src/typegraph/core/src/typedef/file.rs (2)

12-12: Review import changes

The removal of FindAttribute from imports suggests a simplification of the type system. Verify if this is part of the policy specification changes.


52-52: Verify impact of removing context usage

The change from ctx to _ctx suggests policy handling has been moved elsewhere. This aligns with the new policy specification changes.

✅ Verification successful

Context parameter removal in file.rs is safe

The change from ctx to _ctx in the convert method of file.rs is safe because:

  1. The implementation doesn't use the context parameter at all, as confirmed by the absence of any ctx. usage in the file
  2. Other type implementations (func, list, struct) that need the context are still using it actively
  3. The change only marks an unused parameter and doesn't affect the type conversion system's functionality
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other type conversions that might still use context
ast-grep --pattern 'impl TypeConversion for $_ {
  $$$
  fn convert(&self, ctx: &mut TypegraphContext, $_) $_
}'

# Check for any remaining policy-related context usage
rg "ctx.*policy" src/typegraph/core/

Length of output: 394


Script:

#!/bin/bash
# Let's check the implementation of TypeConversion trait to understand the context usage pattern
ast-grep --pattern 'trait TypeConversion {
  $$$
}'

# Check the actual implementation in file.rs to see if context is used in the function body
rg -A 10 "fn convert.*TypegraphContext" src/typegraph/core/src/typedef/file.rs

# Check for any other files that implement TypeConversion to compare context usage
fd "\.rs$" src/typegraph/core/src/typedef/ --exec rg -l "impl TypeConversion"

Length of output: 1084


Script:

#!/bin/bash
# Let's check how context is used in other type implementations
rg -A 5 "fn convert.*TypegraphContext" src/typegraph/core/src/typedef/struct_.rs src/typegraph/core/src/typedef/list.rs src/typegraph/core/src/typedef/func.rs

# Check if there are any direct usages of context in the implementation bodies
rg "ctx\." src/typegraph/core/src/typedef/file.rs

# Look for any recent changes in the type conversion system
rg "trait TypeConversion" src/typegraph/core/src/

Length of output: 1942

tests/policies/effects_py.py (1)

22-22: LGTM: Policy composition follows new specification

The use of Policy.on with separate read/update policies correctly implements the new policy composition rules, where DENY prohibits access while allowing specific operations through admin_only policy.

examples/typegraphs/execute.ts (1)

55-55: Verify policy migration completeness

The policy correctly implements the new string-based return values. However, let's verify that all similar policies in the codebase have been migrated.

✅ Verification successful

Policy migration is complete across the codebase

The verification shows that all policy implementations in the codebase are consistently using the new string-based 'ALLOW'/'DENY' return values. Found identical implementations in:

  • examples/typegraphs/roadmap-policies.ts
  • examples/typegraphs/rest.ts
  • examples/typegraphs/func.ts
  • examples/typegraphs/reduce.ts
  • examples/typegraphs/execute.ts
  • examples/typegraphs/math.ts (with a different but compliant implementation)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for any remaining boolean-returning policies that need migration
# Look for policy definitions that might still return true/false

# Search for policy definitions returning boolean values
rg -g '*.{ts,js}' "deno\.policy.*=>.*(?:true|false)[^'\"]"

# Search for potential policy definitions that might need updating
ast-grep --pattern 'deno.policy($_, $expr)' 

Length of output: 108


Script:

#!/bin/bash
# Let's try a different approach to find policy definitions and their return values

# Search for policy-related code with more context
rg -g '*.{ts,js}' -B 2 -A 2 'policy.*=.*=>.*' 

# Also look for specific policy function definitions
ast-grep --pattern '($_ = $_) => $$$'

Length of output: 885


Script:

#!/bin/bash
# Let's search more specifically for policy definitions in the examples directory
# and any test files that might contain policy implementations

# Search in examples directory
rg -g '*.{ts,js}' -B 3 -A 3 '(policy|policies).*=>.*' examples/

# Search in test files
rg -g '*test*.{ts,js}' -B 3 -A 3 '(policy|policies).*=>.*'

# Look for policy-related function definitions with ast-grep
ast-grep --pattern 'policy($$$) {
  $$$
}'

Length of output: 2266


Script:

#!/bin/bash
# Let's try one final search focusing specifically on the examples/typegraphs directory
# and looking for any policy-related return statements

# Search for policy definitions in typegraphs directory
rg -g '*.{ts,js}' -B 5 -A 5 'context\..*\?' examples/typegraphs/

# Look for return statements in policy-related code
ast-grep --pattern 'return $expr ? $true : $false'

# Search for other policy definitions in execute.ts
rg -g 'execute.ts' -B 5 -A 5 '(policy|policies)'

Length of output: 4395

src/typegraph/core/src/typedef/string.rs (1)

21-21: LGTM: Unused parameter properly marked

The renaming of ctx to _ctx correctly follows Rust conventions for marking unused parameters.

src/typegraph/core/src/typedef/integer.rs (1)

21-21: LGTM: Parameter renaming aligns with broader refactoring

The renaming of ctx to _ctx is consistent with the codebase-wide effort to simplify type conversion implementations. The parameter is properly marked as unused.

examples/typegraphs/rest.ts (1)

52-52: Policy implementation needs to consider PASS case

While the change from boolean to ALLOW/DENY is correct, consider scenarios where PASS might be more appropriate. According to the PR objectives, PASS allows evaluation of each child without affecting the parent.

Let's verify other policy implementations in the codebase:

Consider the following pattern for more granular control:

(_args, { context }) => {
  if (!context.username) return 'DENY';
  // Add conditions where PASS might be more appropriate
  return 'ALLOW';
}
examples/typegraphs/execute.py (1)

56-56: 🛠️ Refactor suggestion

Consider extracting shared policy logic

The policy implementation is duplicated across rest.ts and execute.py. Consider extracting this into a shared policy definition to maintain consistency and reduce duplication.

Example approach:

// policies/admin.ts
export const adminPolicy = `(_args, { context }) => {
  if (!context.username) return 'DENY';
  // Add conditions where PASS might be more appropriate
  return 'ALLOW';
}`

// rest.ts and execute.py can import this shared definition

Additionally, verify that all policy implementations follow the new specification:

tests/auth/auth.py (1)

20-22: LGTM! Private policy updated correctly.

The private policy has been properly updated to use the new policy specification.

tests/utils/bindings_test.ts (2)

50-57: New policy structure aligns with PR objectives.

The new policy structure using arrays for __type and __schema reflects the transition from boolean values to the new policy specification system (ALLOW, DENY, PASS).


43-43: Verify the schema ID change impact.

The schema ID has been changed from 64 to 26. This could have implications on schema compatibility.

✅ Verification successful

Let's examine the content of these files to understand the schema ID usage and its implications.


Schema ID change is consistent with introspection schema

The schema ID change from 64 to 26 in bindings_test.ts aligns with the schema ID used in the introspection schema (src/typegate/src/typegraphs/introspection.json). The occurrences of "schema.*64" in openapi_schema.json are unrelated as they refer to integer format specifications (int64) in OpenAPI definitions, not schema IDs.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for other occurrences of schema ID 64 or 26
rg -l '(schema.*64|schema.*26)' --type ts --type json

Length of output: 167


Script:

#!/bin/bash
# Check the context of schema IDs in these files
echo "=== bindings_test.ts ==="
rg -A 5 -B 5 '(schema.*64|schema.*26)' tests/utils/bindings_test.ts

echo -e "\n=== openapi_schema.json ==="
rg -A 5 -B 5 '(schema.*64|schema.*26)' tests/importers/openapi_schema.json

echo -e "\n=== introspection.json ==="
rg -A 5 -B 5 '(schema.*64|schema.*26)' src/typegate/src/typegraphs/introspection.json

Length of output: 3060

examples/typegraphs/func.py (1)

61-61: Policy implementation maintains cross-language consistency.

The Python implementation correctly mirrors the TypeScript version, ensuring consistent behavior across different language implementations.

Let's verify that all policy implementations across the codebase follow the same pattern:

✅ Verification successful

Based on the search results, I can see that the policy implementation pattern is consistent across the codebase. The policy in the review comment:

"(_args, { context }) => !!context.username ? 'ALLOW' : 'DENY'"

follows the same pattern used throughout the codebase for authentication policies, particularly for admin access control. This exact pattern appears in multiple files including examples/typegraphs/func.py, examples/typegraphs/reduce.py, examples/typegraphs/roadmap-policies.py, etc.

Policy implementation is consistent with codebase patterns

The implementation follows the standard pattern used across the codebase for username-based authentication policies, ensuring consistent behavior.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for policy definitions across the codebase
rg -g '!{*.md,*.json}' -A 2 -B 2 "policy\(" 

Length of output: 65888

src/metagen/src/tests/fixtures.rs (1)

58-58: Verify test coverage for the new policy field.

The addition of the policies field in ObjectTypeData supports the new policy specification. However, we should ensure comprehensive test coverage for the new field.

Let's check for policy-related tests:

tests/policies/policies_test.ts (2)

32-41: LGTM! Query name updated to reflect new policy terminology.

The renaming from pol_true to pol_pass aligns with the new policy specification.


Line range hint 48-55: LGTM! Query name and error handling aligned with new policy specification.

The renaming from pol_false to pol_deny and the corresponding authorization failure test case properly validate the new policy behavior.

src/typegate/src/typegraphs/prisma_migration.json (3)

21-37: Policy structure standardization looks good

The addition of empty policy arrays to all objects establishes a consistent pattern for policy management. This provides a clear structure for future policy additions while maintaining backward compatibility.

Also applies to: 59-63, 114-119


8-11: Verify type reference updates

The numeric values for operations have been modified, which could affect type resolution. Please ensure these values correctly map to their corresponding types.

✅ Verification successful

After examining the JSON file structure, I can now provide a definitive response:

Type reference indices are correctly mapped

The numeric values in the properties section (apply: 7, create: 11, deploy: 14, reset: 18) correctly reference the corresponding function type definitions in the typegraph:

  • 7 maps to "root_apply_fn"
  • 11 maps to "root_create_fn"
  • 14 maps to "root_deploy_fn"
  • 18 maps to "root_reset_fn"

Each referenced index points to the appropriate function type definition with matching input/output types and materializers for the respective operations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for references to these type indices
rg -A 2 '"type": "(function|object)".*"title": "(root_apply_fn|root_create_fn|root_deploy_fn|root_reset_fn)"'

Length of output: 111


Script:

#!/bin/bash
# Let's first check the structure of the JSON file
cat src/typegate/src/typegraphs/prisma_migration.json

# Also search for any references to these operations in the codebase
rg -l "apply|create|deploy|reset" --type ts --type js

Length of output: 13443


275-275: Policy materializer correctly implements the new ALLOW/DENY specification

The script now returns explicit 'ALLOW'/'DENY' values instead of booleans, aligning with the new policy specification.

Let's verify if this pattern is consistently applied across other materializers:

✅ Verification successful

The previous search might have missed matches because it was looking specifically for "return true/false" patterns. Let's broaden the search to include:

  1. String literals containing 'true' or 'false' at the end of lines (case-insensitive)
  2. Return statements with boolean values
  3. Include more context lines for better understanding

Let's try a more focused search specifically looking at script contents within JSON files, as the previous results only showed GraphQL introspection defaults which aren't relevant to our verification. We want to find any policy materializer scripts that might still be using boolean values.


Let's search for all policy materializer scripts to see their implementations and verify if they're consistently using the new ALLOW/DENY pattern. The previous searches might have missed matches due to escaped characters or complex patterns, so let's look at all materializer scripts directly.


Policy materializer implementation is consistent across the codebase

The verification confirms that both policy materializer scripts in the codebase (typegate.json and prisma_migration.json) correctly implement the new ALLOW/DENY pattern. No instances of boolean returns were found, and both materializers use the same consistent implementation for admin-only access control.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining boolean returns in policy materializers
rg -l "return (true|false)" --type json

Length of output: 41


Script:

#!/bin/bash
# Search for boolean patterns in policy materializer scripts within JSON files
rg -g "*.json" "(?i)(true|false)['\"]\s*$|return\s+(true|false)" -A 2 -B 2

Length of output: 1947


Script:

#!/bin/bash
# Search specifically for policy materializer scripts in JSON files
# Looking for script content that might contain boolean values
rg -g "*.json" -A 3 -B 3 '"script":\s*"[^"]*(?:true|false)[^"]*"'

Length of output: 67


Script:

#!/bin/bash
# Search for all policy materializer scripts to inspect their return values
rg -g "*.json" -A 2 -B 2 '"script":\s*"var\s+_my_lambda'

Length of output: 852

src/metagen/src/fdk_rust/stubs.rs (1)

116-116: LGTM: ObjectTypeData correctly updated with policies field

The addition of the policies field with Default::default() maintains compatibility while supporting the new policy specification.

src/typegate/src/typegraphs/introspection.json (3)

304-311: Schema objects correctly updated with policy support

The addition of policy arrays to schema and directive objects maintains consistency with the new policy structure while allowing for future policy definitions.

Also applies to: 330-336


Line range hint 424-427: Verify __public policy behavior with new PASS return value

The __public policy now uses the updated predefined_function materializer which returns PASS instead of true. Ensure this change doesn't affect existing public access patterns.

✅ Verification successful

Let me gather more information about the usage of this policy and materializer.


Let me try one more search to find materializer implementations and policy evaluations.


Let me try one final search to find policy evaluation code.


Based on the search results, I can now generate the final response:

Change from true to PASS in __public policy materializer is safe

The change in the __public policy materializer's return value from true to PASS is verified to be safe because:

  1. PASS is a valid policy resolver output that acts as a no-op in policy evaluation
  2. Test cases confirm that PASS does not affect the authorization outcome
  3. Policy composition logic explicitly handles PASS values by continuing evaluation without impact
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for references to __public policy
rg -l '"name":\s*"__public"' --type json

Length of output: 89


Script:

#!/bin/bash
# Search for references to __public policy in code files
rg -A 5 "__public" --type ts --type js

# Search for materializer references and implementations
ast-grep --pattern 'function $FUNC($$$) {
  $$$
  return PASS;
  $$$
}'

# Look for policy evaluation code
rg -A 5 "materializer.*PASS" --type ts --type js

Length of output: 444


Script:

#!/bin/bash
# Search for materializer implementations and constants
rg -A 10 "const.*materializer" --type ts --type js
rg -A 10 "function.*materializer" --type ts --type js

# Search for policy evaluation logic
rg -A 10 "evaluate.*policy" --type ts --type js
rg -A 10 "policy.*result" --type ts --type js

Length of output: 26934


Script:

#!/bin/bash
# Search for policy evaluation and materializer implementation
rg -A 10 "policy.*materializer" --type ts --type js
rg -A 10 "predefined_function" --type ts --type js
rg -A 10 "PASS" --type ts --type js

Length of output: 23882


396-396: ⚠️ Potential issue

Critical change: Predefined function now returns PASS instead of true

This change is fundamental to the new policy specification, replacing the boolean true with PASS. This affects how policies are evaluated and composed.

Let's verify the impact:

✅ Verification successful

Based on the search results, I can now generate the final response:

Verified: Policy materializer change from "true" to "pass" is part of a broader policy evaluation update

The change from "true" to "pass" in the predefined function materializer aligns with the new policy evaluation system, as evidenced by:

  • No remaining instances of "name": "true" in JSON files
  • The presence of policy evaluation types and configurations in the codebase
  • The existence of PolicyResolverOutput type in src/typegate/src/engine/planner/policies.ts that explicitly includes "PASS" as a valid policy result
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining "true" policy materializers
rg -l '"name":\s*"true"' --type json

Length of output: 38


Script:

#!/bin/bash
# Let's search for both old and new policy materializer patterns to understand the transition
echo "=== Searching for 'true' pattern ==="
rg '"name":\s*"true"' --type json -C 2

echo -e "\n=== Searching for 'pass' pattern ==="
rg '"name":\s*"pass"' --type json -C 2

echo -e "\n=== Searching for policy evaluation related code ==="
rg -g '*.{ts,js}' 'policy.*eval' -C 2

Length of output: 2610


Script:

#!/bin/bash
# Let's examine the policy evaluation implementation to understand how the result is handled
echo "=== Searching for policy result handling ==="
ast-grep --pattern 'delegate($_, $_, $_)' 

echo -e "\n=== Looking for policy result type definitions ==="
rg -g '*.{ts,js}' 'type.*Policy.*Result' -C 3

Length of output: 307


Script:

#!/bin/bash
# Let's look for policy-related type definitions and enums
echo "=== Searching for policy-related types and enums ==="
rg -g '*.{ts,js}' 'enum.*Policy|type.*Policy|interface.*Policy' -C 3

echo -e "\n=== Looking for policy materializer implementations ==="
rg -g '*.{ts,js}' 'materializer|Materializer' -C 3

echo -e "\n=== Checking for policy evaluation logic ==="
rg -g '*.{ts,js}' 'PASS|DENY|SKIP' -C 3

Length of output: 75523

src/common/src/typegraph/types.rs (1)

160-162: LGTM! Well-configured serialization handling.

The implementation correctly uses IndexMap for ordered policy storage and includes appropriate serde attributes for efficient serialization. The structure mirrors the TypeScript implementation, maintaining consistency across the codebase.

src/typegraph/deno/src/types.ts (3)

84-84: Type update aligns with new policy specification.

The change from Policy[] | null to WitPolicySpec[] | null reflects the new policy specification system.


102-102: Policy chain reference updated.

The proxy now returns the new chain format consistently with the updated policy specification.


93-95: Policy chain construction updated for new specification.

The policy chain is now constructed by merging existing and new policies using the updated getPolicyChain function.

✅ Verification successful

Let me gather more information about the policy chain implementation to verify the changes.


Let me check one more aspect to understand the complete policy chain implementation.


Based on the gathered information, I can now provide the final response:

Policy chain implementation verified and correctly updated

The implementation correctly handles policy chain construction by:

  • Converting single policy or policy array to a consistent chain format via getPolicyChain
  • Properly merging existing policies (this.policy) with new ones
  • Correctly applying the chain using core.withPolicy

The changes align with the type system where PolicySpec can be either a Policy, PolicyPerEffectObject, or a policy object with specific effects.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of getPolicyChain function
# Test: Search for all usages of getPolicyChain to ensure consistent implementation
rg -A 5 'getPolicyChain'

Length of output: 1682


Script:

#!/bin/bash
# Check the implementation of Policy class and related types
ast-grep --pattern 'class Policy {
  $$$
}'

# Also check the core.withPolicy usage
rg -A 3 'core\.withPolicy'

Length of output: 3380


Script:

#!/bin/bash
# Check the type definitions and interfaces related to PolicySpec
rg -A 5 'type PolicySpec'
rg -A 5 'type WitPolicySpec'

# Also check the implementation of getPolicyChain function
ast-grep --pattern 'function getPolicyChain($$$) {
  $$$
}'

Length of output: 418

src/typegraph/core/src/global_store.rs (2)

92-92: Materializer name updated to align with new policy specification.

Changed from "true" to "pass" to reflect the new policy terminology.


488-491: New utility method added for type checking.

The is_struct method provides a convenient way to check if a type definition is a Struct variant.

✅ Verification successful

Let me gather more context about the implementation and usage pattern.


Let me try a different approach to gather the necessary context.


Utility method is_struct is properly implemented and used correctly

The method is well-implemented as a type checker for the Struct variant of the TypeDef enum, and it's being used appropriately in typedef/struct_.rs for type checking in policy chain extensions. The implementation correctly matches against the TypeDef::Struct variant as defined in the enum, and its usage in both Union and Either type contexts shows consistent pattern matching behavior.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of is_struct method
# Test: Search for all usages to ensure proper implementation
rg -A 3 'is_struct'

Length of output: 887


Script:

#!/bin/bash
# Check the TypeDef enum definition and related code
ast-grep --pattern 'enum TypeDef {
  $$$
}'

# Check the implementation block containing is_struct
ast-grep --pattern 'impl $_ {
  $$$
  fn is_struct($$$) {
    $$$
  }
  $$$
}'

Length of output: 126


Script:

#!/bin/bash
# Search for TypeDef enum definition using ripgrep
rg -A 10 "enum TypeDef"

# Look for the context where is_struct is used
rg -B 3 -A 3 "is_struct\(\)" src/typegraph/core/src/typedef/struct_.rs

Length of output: 1321

src/typegate/src/runtimes/typegate.ts (1)

593-593: Policy field updated to use new getPolicies function.

The change improves code organization by using the newly extracted getPolicies function.

src/typegate/src/runtimes/typegraph.ts (3)

61-65: Well-structured type definition for field information.

The new FieldInfo type provides a clear structure for field metadata, including policy information. This improves type safety and code readability.


409-415: Consistent implementation of field formatting with policy support.

The field formatting has been updated to use the new FieldInfo type consistently across both input and output fields. The implementation properly handles policy inheritance with the null coalescing operator.

Also applies to: 428-434


521-565: Verify the policy application in function fields.

The field formatting implementation for functions needs to be verified for correct policy inheritance.

✅ Verification successful

Based on the gathered information, I can now provide the final response:

Policy handling in function fields is correctly implemented

The implementation properly handles policies for function fields through:

  • Policy information is correctly passed via the FieldInfo interface
  • Policies are properly described in field descriptions via policyDescription
  • Function fields inherit policies from their parent field definition, as seen in the type system implementation where policies: type.policies?.[name] ?? [] handles policy inheritance
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for function field policy inheritance patterns
# Test: Search for function field policy handling patterns
rg -A 5 'policies.*function.*field'

Length of output: 37


Script:

#!/bin/bash
# Let's analyze the policy handling in the codebase more broadly
# First, let's look for policy-related code in typegraph.ts
rg -l "policies" src/typegate/src/runtimes/typegraph.ts

# Then let's examine how policies are handled in the context of fields
ast-grep --pattern 'policies: $_'

# And check for any policy-related methods
ast-grep --pattern 'function $_(policies$_) {
  $$$
}'

# Finally, let's look for policy description implementation
rg -A 5 "policyDescription"

Length of output: 1443


Script:

#!/bin/bash
# Let's examine the complete implementation of formatField and related functions
ast-grep --pattern 'formatField = $_'

# Check how field policies are used in the type system
ast-grep --pattern 'interface FieldInfo {
  $$$
}'

# Look for any policy inheritance or propagation logic
rg -A 10 "type.*policies" src/typegate/src/runtimes/typegraph.ts

Length of output: 1143

🧰 Tools
🪛 Biome (1.9.4)

[error] 547-547: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/typegraph/core/src/lib.rs (1)

217-228: Verify policy check expressions in tests.

The new policy check expressions should be thoroughly tested.

✅ Verification successful

Based on the search results, I can now generate a final response:

Policy check expressions are well tested across the codebase

The policy check expressions are extensively used and tested across the codebase:

  • Unit tests in tests/policies/policies_test.ts and tests/policies/policies_composition_test.ts
  • Integration tests in tests/auth/auth.py
  • Multiple example implementations in examples/typegraphs/ demonstrating various use cases:
    • Basic authentication (policies.ts/py)
    • Role-based access control (policies-example.py)
    • Username validation (roadmap-policies.ts/py)
    • Random access control (programmable-api-gateway.ts/py)

The expressions follow a consistent pattern of condition ? 'ALLOW' : 'DENY' across all implementations, and the three variants in the code (NotNull, Value, Pattern) align with the tested patterns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for policy-related test coverage
# Test: Search for policy check test cases
rg -A 5 'test.*policy.*check|test.*context.*policy'

Length of output: 53


Script:

#!/bin/bash
# Let's try a broader search for test files related to policy or context checks
fd "test.*\.(rs|ts|js)" | xargs rg -l "policy|context.*check"

Length of output: 269


Script:

#!/bin/bash
# Search for test assertions or test cases in files containing ContextCheck
rg -A 5 "assert|#\[test\]" $(rg -l "ContextCheck")

Length of output: 6879


Script:

#!/bin/bash
# Look for test files specifically in the typegraph directory
fd "test.*\.(rs|ts|js)" src/typegraph/ | xargs cat

Length of output: 10413


Script:

#!/bin/bash
# Search for any usage of the policy check expressions we're concerned about
rg -A 3 "'ALLOW' : 'DENY'"

Length of output: 7421

src/metagen/src/fdk_rust/types.rs (2)

441-441: LGTM: Policy field addition

The addition of the policies field with Default::default() initialization is consistent with the PR's objective of enhancing policy support.


619-619: LGTM: Consistent policy field implementation in test cases

The test cases correctly implement the policies field across different object type scenarios, maintaining consistency with the new policy specification.

Also applies to: 629-629, 641-641, 672-672, 684-684, 723-723, 735-735

tests/policies/policies_composition.py Show resolved Hide resolved
examples/typegraphs/math.py Show resolved Hide resolved
examples/typegraphs/roadmap-policies.ts Outdated Show resolved Hide resolved
src/typegraph/core/src/typedef/float.rs Show resolved Hide resolved
src/typegraph/core/src/lib.rs Outdated Show resolved Hide resolved
@michael-0acf4 michael-0acf4 requested review from a team and Yohe-Am December 19, 2024 18:11
docs/metatype.dev/docs/reference/policies/index.mdx Outdated Show resolved Hide resolved
examples/typegraphs/execute.py Outdated Show resolved Hide resolved
@michael-0acf4 michael-0acf4 requested a review from a team December 20, 2024 13:27
Copy link

codecov bot commented Dec 20, 2024

Codecov Report

Attention: Patch coverage is 88.68778% with 50 lines in your changes missing coverage. Please review.

Project coverage is 77.69%. Comparing base (64ed210) to head (f525410).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/typegate/src/engine/planner/policies.ts 94.42% 15 Missing ⚠️
src/typegate/src/runtimes/typegate.ts 43.47% 12 Missing and 1 partial ⚠️
src/typegate/src/engine/planner/args.ts 66.66% 9 Missing ⚠️
src/typegate/src/transports/graphql/typegraph.ts 88.23% 4 Missing ⚠️
src/typegraph/deno/src/types.ts 20.00% 4 Missing ⚠️
src/typegate/src/runtimes/deno/deno.ts 25.00% 3 Missing ⚠️
src/typegate/src/runtimes/typegraph.ts 96.07% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #937      +/-   ##
==========================================
- Coverage   77.81%   77.69%   -0.12%     
==========================================
  Files         153      153              
  Lines       18960    19096     +136     
  Branches     1894     1924      +30     
==========================================
+ Hits        14754    14837      +83     
- Misses       4182     4235      +53     
  Partials       24       24              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@Yohe-Am Yohe-Am left a comment

Choose a reason for hiding this comment

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

nitpick: maybe too late but now I'm a bit confused around PASS and ALLOW naming lol. PASS is for PASSTHROUGH and not BYPASS right?

Edit: yeah, it is PASSTHROUGH.

@michael-0acf4 michael-0acf4 merged commit 37f51aa into main Dec 21, 2024
13 checks passed
@michael-0acf4 michael-0acf4 deleted the policy-spec-impl branch December 21, 2024 20:27
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.

3 participants