Skip to content

feat: Policy v1 endpoints #479

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

Merged
merged 3 commits into from
Apr 13, 2025
Merged

feat: Policy v1 endpoints #479

merged 3 commits into from
Apr 13, 2025

Conversation

adityachoudhari26
Copy link
Contributor

@adityachoudhari26 adityachoudhari26 commented Apr 12, 2025

Summary by CodeRabbit

  • New Features

    • Introduced new API endpoints for policy creation and resource schema management, supporting detailed data validation and returning comprehensive JSON responses.
    • Added support for creating and managing resource schemas with specific properties and validation.
  • Documentation

    • Updated the API documentation using the OpenAPI 3.0.0 standard to clearly define request and response structures, ensuring seamless integration and an improved user experience.

Copy link
Contributor

coderabbitai bot commented Apr 12, 2025

Walkthrough

This pull request introduces new API functionality for handling policies. A new OpenAPI specification file defines the API’s schemas and POST endpoint for creating policies. An associated route file implements a POST endpoint with middleware for authentication, body parsing, and authorization. In the backend, the policy creation function has been updated to return an extended object containing additional properties such as targets and various approval details. These changes enhance the structure and clarity of the API endpoint and its related controller and service interactions.

Changes

File(s) Change Summary
apps/webservice/src/app/api/v1/policies/openapi.ts
apps/webservice/src/app/api/v1/policies/route.ts
Added new files defining the OpenAPI specification and the corresponding POST route for creating policies. The specification outlines schemas and endpoints, while the route uses middleware for authentication, parsing, and authorization to process policy creation requests.
packages/api/src/router/policy/create.ts Updated createPolicyInTx to return an extended policy object that now includes additional properties such as targets, denyWindows, deploymentVersionSelector, and various version approvals.
openapi.v1.json Introduced new endpoints for creating policies and resource schemas, along with a DELETE method for resource schemas. New schemas were also defined for policies and resource schemas, detailing their structure and required fields.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Route
    participant Middleware
    participant API

    Client->>Route: POST /v1/policies
    Route->>Middleware: Authenticate, Parse Body, Authorize
    Middleware-->>Route: Validated Request
    Route->>API: Call createPolicy with Request Body
    API-->>Route: Return extended policy object
    Route->>Client: Respond 200 OK with policy object
Loading

Poem

I'm a little rabbit on a coding quest,
Hopping through middleware with my best,
New schemas and routes in the API maze,
Extended policies brighten my hop-filled days,
Code carrots crunch as the endpoints impress! 🥕🐇

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @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.

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: 2

🧹 Nitpick comments (4)
apps/webservice/src/app/api/v1/policies/route.ts (1)

26-36: Consider more specific error responses

While the current error handling is adequate, consider returning more specific error types to help API consumers troubleshoot issues more effectively.

  .catch((error) => {
    log.error("Failed to create policy", { error });
    return NextResponse.json(
-     { error: "Failed to create policy" },
+     { 
+       error: "Failed to create policy",
+       code: error.code || "POLICY_CREATE_ERROR",
+       message: process.env.NODE_ENV === "production" 
+         ? "An error occurred while creating the policy"
+         : error.message
+     },
      { status: INTERNAL_SERVER_ERROR },
    );
  }),
apps/webservice/src/app/api/v1/policies/openapi.ts (3)

90-102: Consider making description field optional

In the Policy schema, description is marked as required, but it's a common practice to make description fields optional. This gives users more flexibility when creating policies.

required: [
  "name",
- "description",
  "priority",
  "enabled",
  "workspaceId",
  "targets",
  "denyWindows",
  "deploymentVersionSelector",
  "versionAnyApprovals",
  "versionUserApprovals",
  "versionRoleApprovals",
],

173-194: Consider adding more specific error response types

The error response schema is very generic. Consider adding more specific error types for different failure scenarios (e.g., validation error, unauthorized, forbidden, etc.) to help API consumers better handle errors.

  description: "Internal Server Error",
  content: {
    "application/json": {
      schema: {
        type: "object",
        properties: {
          error: { type: "string" },
+         code: { type: "string" },
+         message: { type: "string" },
        },
      },
    },
  },
},
+  description: "Bad Request",
+  content: {
+    "application/json": {
+      schema: {
+        type: "object",
+        properties: {
+          error: { type: "string" },
+          issues: { 
+            type: "array",
+            items: {
+              type: "object",
+              properties: {
+                path: { type: "array", items: { type: "string" } },
+                message: { type: "string" }
+              }
+            }
+          }
+        },
+      },
+    },
+  },
+},

10-103: Add field descriptions to improve API documentation

The schema definitions would benefit from descriptions for each field to improve the API documentation. This helps API consumers understand the purpose and constraints of each field.

Example for the PolicyTarget schema:

PolicyTarget: {
  type: "object",
  properties: {
-   deploymentSelector: { type: "object", additionalProperties: true },
+   deploymentSelector: { 
+     type: "object", 
+     additionalProperties: true,
+     description: "Selector for targeting specific deployments based on attributes"
+   },
    // Add descriptions for other fields
  },
},
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b8152f and d2d4667.

📒 Files selected for processing (3)
  • apps/webservice/src/app/api/v1/policies/openapi.ts (1 hunks)
  • apps/webservice/src/app/api/v1/policies/route.ts (1 hunks)
  • packages/api/src/router/policy/create.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{ts,tsx}`: **Note on Error Handling:** Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error...

**/*.{ts,tsx}: Note on Error Handling:
Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error handling. These are acceptable as long as they maintain clarity and predictability.

  • apps/webservice/src/app/api/v1/policies/route.ts
  • packages/api/src/router/policy/create.ts
  • apps/webservice/src/app/api/v1/policies/openapi.ts
🧬 Code Graph Analysis (2)
apps/webservice/src/app/api/v1/policies/route.ts (2)
apps/webservice/src/app/api/v1/auth.ts (2)
  • authn (15-21)
  • authz (23-56)
apps/webservice/src/app/api/v1/body-parser.tsx (1)
  • parseBody (6-15)
packages/api/src/router/policy/create.ts (1)
packages/db/src/schema/policy.ts (1)
  • policy (30-46)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Typecheck
  • GitHub Check: Lint
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (5)
apps/webservice/src/app/api/v1/policies/route.ts (3)

14-14: Clear route logging setup

Good practice creating a child logger specifically for this route. This will make log messages more discoverable and easier to filter when troubleshooting issues in production.


16-37: Well-structured API endpoint implementation with proper middleware chain

The implementation correctly uses a middleware chain approach for authentication, body validation, and authorization. This promotes separation of concerns and makes the code more maintainable.

The error handling follows good practices by:

  1. Logging the error with context
  2. Returning a user-friendly error message without exposing internal details
  3. Using standard HTTP status codes

19-25: Authorization check is properly scoped

The authorization middleware correctly verifies the user has permission to create a policy for the specific workspace identified in the request body. This follows the principle of least privilege.

packages/api/src/router/policy/create.ts (1)

92-100: Improved return value with comprehensive policy information

The return value now includes all related policy data, which provides a more complete view of the created policy. This is a good enhancement that eliminates the need for additional API calls to fetch related information.

apps/webservice/src/app/api/v1/policies/openapi.ts (1)

3-9: Good API documentation setup

Clear API metadata with version information. This helps with API discoverability and versioning.

Comment on lines +26 to +27
required: ["timeZone", "rrule"],
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistency in required fields across schema definitions

There's an inconsistency in the DenyWindow schema requirements:

  • In the components schema (line 26), both timeZone and rrule are required
  • In the request body schema (line 136), only timeZone is required

This could lead to validation inconsistencies.

Similar inconsistencies exist for VersionRoleApproval. Ensure that the requirements are consistent across all schema definitions.

// In the request body schema:
required: ["timeZone"],
+required: ["timeZone", "rrule"],

Also applies to: 136-137

Comment on lines +139 to +141
deploymentVersionSelector: {
$ref: "#/components/schemas/DeploymentVersionSelector",
},
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider stricter validation for deploymentVersionSelector

The deploymentVersionSelector field allows any additional properties (additionalProperties: true), which might be too permissive and could lead to unexpected data being accepted.

Consider using a more specific schema that only allows known properties, or at least document the expected structure more clearly.


🌐 Web query:

What are best practices for handling additional properties in OpenAPI schemas?

💡 Result:

Handling additional properties in OpenAPI schemas requires balancing flexibility with strictness to ensure API reliability and clarity. Here are key best practices based on industry standards and expert recommendations:

1. Default to Strict Validation with additionalProperties: false

  • Enforce explicit property definitions by setting additionalProperties: false in schemas where no dynamic fields are expected[7]. This prevents API clients from sending unexpected data and ensures documentation accuracy[2][7].
  • Example:
    components:
      schemas:
        StrictObject:
          type: object
          properties:
            name:
              type: string
          additionalProperties: false

2. Use additionalProperties: true for Controlled Flexibility

  • Allow dynamic but unstructured data in scenarios like user-generated content or future-proof extensibility[2][5]. This enables APIs to accept unknown properties without schema updates[2][7].
  • Example:
    components:
      schemas:
        FlexibleObject:
          type: object
          properties:
            title:
              type: string
          additionalProperties: true

3. Restrict to Typed Additional Properties

  • Constrain additional properties to specific types (e.g., type: string or type: integer) to maintain data consistency while allowing extensibility[2][5][7]. This is critical for scenarios like metadata storage or configuration objects.
  • Example:
    components:
      schemas:
        StringMap:
          type: object
          properties:
            category:
              type: string
          additionalProperties:
            type: string

4. Avoid Overusing Additional Properties

  • Do not use additionalProperties as a shortcut to avoid documenting well-known fields[7]. Explicitly define all expected properties to improve API discoverability and reduce client-side validation errors[7][10].

5. Consider Code Generation Implications

  • Test generated client/server code to ensure compatibility with additionalProperties configurations. For example:
    • additionalProperties: true often translates to Map<String, Object> in Java[7].
    • Typed additional properties (e.g., type: integer) may generate Map<String, Integer>[5][7].

6. Document Usage Clearly

  • Specify in descriptions when and why additional properties are allowed[2][10]. For example:
    components:
      schemas:
        UserMetadata:
          description: >-
            Key-value pairs for user-defined metadata. 
            Additional properties must be strings.
          type: object
          additionalProperties:
            type: string

7. Align with JSON Schema Behavior

  • In OpenAPI 3.1+, additionalProperties follows JSON Schema semantics, where:
    • Unspecified additionalProperties defaults to true[9].
    • Use false to block extras or a schema to validate them[7][9].

Comparison of Approaches

Approach Use Case Code Example
additionalProperties: false Strict data contracts Prevents unexpected fields[7]
additionalProperties: true Dynamic/unstructured data Accepts any type[2][5]
additionalProperties: {type: X} Type-safe extensibility Ensures data integrity[2][7]

By following these practices, developers can create OpenAPI schemas that are both robust for API consumers and adaptable to evolving requirements[2][7].

Citations:


Action: Refine DeploymentVersionSelector Schema Validation

The current definition of deploymentVersionSelector (lines 139–141 in apps/webservice/src/app/api/v1/policies/openapi.ts) references a schema that, based on its usage, defaults to allowing additional properties. This lax validation could inadvertently allow unexpected or malformed data.

Based on best practices:

  • If only known properties are expected: Refine the schema by explicitly defining allowed properties and set additionalProperties: false.
  • If some level of flexibility is needed: Consider constraining additional properties to a specific type (e.g., type: string) or document the expected structure clearly.

Please update the DeploymentVersionSelector schema accordingly to adhere to a stricter validation strategy, ensuring better API reliability and improved client-side validation.

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: 3

♻️ Duplicate comments (5)
apps/webservice/src/app/api/v1/policies/openapi.ts (2)

25-27: ⚠️ Potential issue

Inconsistency in DenyWindow required fields

There's a mismatch between the schema definitions:

  • In the components schema (line 26), both timeZone and rrule are required
  • In the request body schema (line 136-137), only timeZone is required

This inconsistency could lead to validation issues where a request passes validation but fails when processed by backend logic.

      required: ["timeZone"],
+      required: ["timeZone", "rrule"],

Also applies to: 136-137


32-35: 🛠️ Refactor suggestion

Improve schema validation for DeploymentVersionSelector

Using additionalProperties: true creates a lax validation that could allow unexpected data through the API. Consider defining a more specific schema that explicitly lists allowed properties.

  deploymentVersionSelector: {
    type: "object",
-    additionalProperties: true,
+    additionalProperties: false,
+    properties: {
+      // Define specific allowed properties here
+    }
  },
openapi.v1.json (3)

4389-4392: ⚠️ Potential issue

Inconsistency in DenyWindow required fields

Similar to the TypeScript file, there's a mismatch between the schema definitions:

  • In the components schema (line 4389-4392), both timeZone and rrule are required
  • In the request body schema (line 1481-1484), only timeZone is required

Also applies to: 1481-1484


4445-4448: ⚠️ Potential issue

Inconsistency in VersionRoleApproval required fields

Similar to the TypeScript file, there's a mismatch between the schema definitions:

  • In the components schema (line 4445-4448), both roleId and requiredApprovalsCount are required
  • In the request body schema (line 1519-1521), only roleId is required

Also applies to: 1519-1521


4400-4403: 🛠️ Refactor suggestion

Improve schema validation for DeploymentVersionSelector

Using additionalProperties: true creates a lax validation that could allow unexpected data through the API.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2d4667 and c134ee0.

📒 Files selected for processing (2)
  • apps/webservice/src/app/api/v1/policies/openapi.ts (1 hunks)
  • openapi.v1.json (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{ts,tsx}`: **Note on Error Handling:** Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error...

**/*.{ts,tsx}: Note on Error Handling:
Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error handling. These are acceptable as long as they maintain clarity and predictability.

  • apps/webservice/src/app/api/v1/policies/openapi.ts
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Typecheck
  • GitHub Check: Lint
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (5)
apps/webservice/src/app/api/v1/policies/openapi.ts (3)

3-8: LGTM: API metadata is properly defined

The OpenAPI specification metadata is correctly defined with appropriate version information.


108-112: LGTM: POST endpoint is well-defined

The /v1/policies endpoint is properly defined with a clear summary and operation ID.


182-204: LGTM: Response definitions are comprehensive

The response definitions include both success (200) and error (500) cases with appropriate schemas.

openapi.v1.json (2)

1432-1563: LGTM: Policy endpoint implementation matches TypeScript spec

The POST endpoint for /v1/policies is correctly implemented with the same schema structure as defined in the TypeScript specification file.


2225-2382: LGTM: Resource schemas endpoints are well-defined

The resource schemas endpoints (/v1/resource-schemas) are properly defined with appropriate request/response structures for both creation and deletion operations.

Comment on lines +56 to +57
required: ["roleId", "requiredApprovalsCount"],
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistency in VersionRoleApproval required fields

The required fields are inconsistent between schema definitions:

  • In the components schema (line 56), both roleId and requiredApprovalsCount are required
  • In the request body schema (line 167), only roleId is required

This could lead to unexpected validation errors if the backend expects requiredApprovalsCount but the API doesn't enforce it.

    required: ["roleId"],
+    required: ["roleId", "requiredApprovalsCount"],

Also applies to: 167-168

Comment on lines +14 to +16
deploymentSelector: { type: "object", additionalProperties: true },
environmentSelector: { type: "object", additionalProperties: true },
releaseSelector: { type: "object", additionalProperties: true },
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Strengthen validation for selector objects

All selector objects currently use additionalProperties: true, which is too permissive and could lead to unexpected data being accepted. This approach makes it difficult to validate client-provided input and might cause issues during processing.

  deploymentSelector: { type: "object", additionalProperties: true },
  environmentSelector: { type: "object", additionalProperties: true },
  releaseSelector: { type: "object", additionalProperties: true },

Consider using more specific schemas with explicit properties and set additionalProperties: false to ensure only expected data is allowed.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +4450 to 4523
"Policy1": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"priority": {
"type": "number"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"enabled": {
"type": "boolean"
},
"workspaceId": {
"type": "string",
"format": "uuid"
},
"targets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PolicyTarget"
}
},
"denyWindows": {
"type": "array",
"items": {
"$ref": "#/components/schemas/DenyWindow"
}
},
"deploymentVersionSelector": {
"$ref": "#/components/schemas/DeploymentVersionSelector"
},
"versionAnyApprovals": {
"type": "array",
"items": {
"$ref": "#/components/schemas/VersionAnyApproval"
}
},
"versionUserApprovals": {
"type": "array",
"items": {
"$ref": "#/components/schemas/VersionUserApproval"
}
},
"versionRoleApprovals": {
"type": "array",
"items": {
"$ref": "#/components/schemas/VersionRoleApproval"
}
}
},
"required": [
"id",
"name",
"priority",
"createdAt",
"enabled",
"workspaceId",
"targets",
"denyWindows",
"versionUserApprovals",
"versionRoleApprovals"
]
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Schema naming inconsistency with TypeScript definition

The schema in the JSON file is named Policy1, while in the TypeScript file it's named Policy. This inconsistency might cause reference issues if not handled correctly.

Consider aligning the naming convention between both files to avoid confusion and potential bugs.

@adityachoudhari26 adityachoudhari26 merged commit 07ad866 into main Apr 13, 2025
4 of 6 checks passed
@adityachoudhari26 adityachoudhari26 deleted the init-policy-endpoints branch April 13, 2025 04:08
@coderabbitai coderabbitai bot mentioned this pull request Apr 20, 2025
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.

1 participant