Skip to content

chore: make slugs required#3295

Merged
chronark merged 5 commits intomainfrom
permission-slug-step-2
Jun 3, 2025
Merged

chore: make slugs required#3295
chronark merged 5 commits intomainfrom
permission-slug-step-2

Conversation

@chronark
Copy link
Collaborator

@chronark chronark commented Jun 3, 2025

Summary by CodeRabbit

  • New Features

    • Permissions are now consistently identified and managed using their slugs instead of names across the application.
    • API schemas updated to introduce slug for permission identification, marking name as deprecated.
  • Bug Fixes

    • Ensured all permission records require a slug, improving data consistency.
  • Refactor

    • Updated relevant interfaces, logic, and database queries to use slugs for permissions, including audit logs and permission handling in keys.
  • Documentation

    • Updated TLS package documentation to reflect the minimum TLS version requirement of 1.3.
  • Tests

    • Adjusted TLS configuration tests to expect TLS 1.3 as the minimum version.

@vercel
Copy link

vercel bot commented Jun 3, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
dashboard ⬜️ Ignored (Inspect) Visit Preview Jun 3, 2025 0:13am
engineering ⬜️ Ignored (Inspect) Visit Preview Jun 3, 2025 0:13am

@changeset-bot
Copy link

changeset-bot bot commented Jun 3, 2025

⚠️ No Changeset found

Latest commit: e02173f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 3, 2025

📝 Walkthrough

Walkthrough

The changes update the system to consistently use the slug field instead of the name field for identifying and managing permissions. This includes modifying database queries, internal logic, and schema definitions to rely on slug values, and making the slug column in the permissions table non-nullable. Additionally, TLS-related documentation and tests were updated to reflect a minimum TLS version of 1.3.

Changes

File(s) Change Summary
apps/api/src/pkg/keys/service.ts, Modified permission extraction logic in KeyService.getData and API routes (v1_apis_listKeys.ts, v1_keys_removePermissions.ts, v1_keys_setPermissions.ts) to use permission slug instead of name. Deprecated name in favor of slug in request schemas and internal logic.
apps/api/src/routes/v1_apis_listKeys.ts, apps/api/src/routes/v1_keys_removePermissions.ts, apps/api/src/routes/v1_keys_setPermissions.ts
apps/dashboard/lib/trpc/routers/rbac.ts Updated upsertPermissions to use slugs instead of names throughout, including function signature, queries, creation, and audit logging.
internal/db/src/schema/rbac.ts Changed the permissions.slug column to be non-nullable in the database schema.
go/pkg/tls/doc.go Removed trailing empty comment line and deleted sentence about enforcing TLS 1.2 minimum version.
go/pkg/tls/tls.go Updated NewFromFiles function comment to reflect minimum TLS version 1.3 instead of 1.2.
go/pkg/tls/tls_test.go Updated tests to expect minimum TLS version 1.3 (0x0304) instead of 1.2 (0x0303).
apps/api/src/routes/v1_keys_removePermissions.happy.test.ts Modified test to assign identical UUID to both name and slug fields of permission for consistency.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API
    participant DB

    Client->>API: Request permission-related action
    API->>DB: Query permissions using slug
    DB-->>API: Return permissions with slugs
    API->>Client: Respond with permissions (slugs)
Loading

Possibly related PRs

  • unkeyed/unkey#3098: Also modifies KeyService.getData, but focuses on filtering out null permissions rather than switching to slugs.
  • unkeyed/unkey#3293: Introduces the initial addition of the optional slug column to the permissions schema, which this PR builds upon.

Suggested reviewers

  • perkinsjr
  • mcstepp
  • MichaelUnkey
  • ogzhanolguncu
✨ Finishing Touches
  • 📝 Generate Docstrings

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

❤️ Share
🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate sequence diagram to generate a sequence diagram of the changes in this 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.

@github-actions
Copy link
Contributor

github-actions bot commented Jun 3, 2025

Thank you for following the naming conventions for pull request titles! 🙏

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

🧹 Nitpick comments (1)
apps/dashboard/lib/trpc/routers/rbac.ts (1)

823-824: Clarify the intention of setting both name and slug to the same value.

Currently, both name and slug are set to the same slug value when creating new permissions. This might not be the intended behavior if these fields should serve different purposes (e.g., name for display, slug for identification).

Consider if this is the intended behavior or if there should be a transformation applied:

  const permission: Permission = {
    id: newId("permission"),
    workspaceId,
-   name: slug,
+   name: slug, // or apply some transformation for human-readable name
    slug: slug,
    description: null,
    updatedAtM: null,
    createdAtM: Date.now(),
  };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 45b7ce8 and 734d8ff.

📒 Files selected for processing (3)
  • apps/api/src/pkg/keys/service.ts (1 hunks)
  • apps/dashboard/lib/trpc/routers/rbac.ts (3 hunks)
  • internal/db/src/schema/rbac.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
apps/dashboard/lib/trpc/routers/rbac.ts (3)
internal/db/src/types.ts (2)
  • Permission (22-22)
  • InsertPermission (23-23)
apps/dashboard/lib/audit.ts (1)
  • UnkeyAuditLog (58-97)
internal/db/src/schema/rbac.ts (1)
  • permissions (14-41)
⏰ Context from checks skipped due to timeout of 90000ms (17)
  • GitHub Check: Test Go API Local / Test (Shard 6/8)
  • GitHub Check: Test Go API Local / Test (Shard 5/8)
  • GitHub Check: Test Go API Local / Test (Shard 3/8)
  • GitHub Check: Test Go API Local / Test (Shard 7/8)
  • GitHub Check: Test Go API Local / Test (Shard 2/8)
  • GitHub Check: Test Go API Local / Test (Shard 4/8)
  • GitHub Check: Test Go API Local / Test (Shard 8/8)
  • GitHub Check: Test Go API Local / Test (Shard 1/8)
  • GitHub Check: Build / Build
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Test Packages / Test ./packages/cache
  • GitHub Check: Test Packages / Test ./packages/rbac
  • GitHub Check: Test Packages / Test ./packages/api
  • GitHub Check: Test Packages / Test ./packages/nextjs
  • GitHub Check: Test Packages / Test ./internal/clickhouse
  • GitHub Check: autofix
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
internal/db/src/schema/rbac.ts (1)

20-20:

Details

❓ Verification inconclusive

Verify migration safety for making slug non-nullable.

Making the slug column non-nullable is a breaking schema change. Ensure all existing permission records have valid slug values before applying this migration.


🏁 Script executed:

#!/bin/bash
# Description: Check for any permission records with null slug values that would break the migration

# Search for any database migration files or seed data that might need updating
fd -e sql -e ts | xargs rg -l "permissions" | head -10

# Look for any existing permission creation logic that might not set slug
rg -A 5 -B 5 "insert.*permissions|permissions.*insert" --type ts

Length of output: 34951


🏁 Script executed:

#!/bin/bash
# Inspect seed logic for permissions in event-generator.ts
rg -A3 -B3 "schema\\.permissions" tools/local/src/cmd/seed/event-generator.ts || echo "No direct permission inserts found"
rg -A3 -B3 "slug" tools/local/src/cmd/seed/event-generator.ts || echo "No slug assignments found in seed file"

Length of output: 306


Verify no null slug values before applying migration

All code‐paths that create or seed permissions explicitly set slug, and no seed files insert permissions without it. However, to guarantee zero downtime, please run:

SELECT COUNT(*) AS null_slugs FROM permissions WHERE slug IS NULL;

Ensure the result is 0 before applying the .notNull() migration.

apps/api/src/pkg/keys/service.ts (1)

280-284: LGTM: Consistent transition to using permission slugs.

The changes correctly update both direct key permissions and role-based permissions to use slug instead of name. This aligns well with the schema changes and maintains consistency in permission identification throughout the system.

apps/dashboard/lib/trpc/routers/rbac.ts (2)

796-858: Consistent transition to slug-based permission handling.

The function has been successfully updated to use slugs consistently throughout. The parameter change, database queries, and audit logging all align with the PR objective.


799-799:

Details

✅ Verification successful

Verify all callers are updated to pass slugs instead of names.

Ensure that all callers of this function have been updated to pass permission slugs rather than names.


🏁 Script executed:

#!/bin/bash
# Description: Find all usages of upsertPermissions to verify they pass slugs

# Search for all calls to upsertPermissions
rg -A 3 -B 3 "upsertPermissions" --type ts

# Look for any remaining usage of permission names in similar contexts
rg -A 5 -B 5 "permission.*name|\.name.*permission" --type ts

Length of output: 69565


🏁 Script executed:

#!/bin/bash
# Inspect input schema for createRootKey
echo "=== createRootKey input schema ==="
rg -n ".input" -A5 -B5 apps/dashboard/lib/trpc/routers/key/createRootKey.ts

# Inspect input schema for addPermissionToRootKey
echo "=== addPermissionToRootKey input schema ==="
rg -n "export const addPermissionToRootKey" -A10 -B2 apps/dashboard/lib/trpc/routers/rbac/addPermissionToRootKey.ts
rg -n ".input" -A5 -B5 apps/dashboard/lib/trpc/routers/rbac/addPermissionToRootKey.ts

Length of output: 4020


All upsertPermissions calls now pass validated slugs
We’ve confirmed that every invocation of upsertPermissions in the TRPC routers supplies string slugs (not names):

  • apps/dashboard/lib/trpc/routers/key/createRootKey.ts → uses input.permissions
  • apps/dashboard/lib/trpc/routers/rbac/addPermissionToRootKey.ts → uses permission.data
  • apps/dashboard/lib/trpc/routers/rbac.ts → bulk calls pass permission.data

No callers remain passing permission names. You can safely resolve this.

chronark added 2 commits June 3, 2025 13:44
this is unrelated but stopped the CI from running
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: 0

🔭 Outside diff range comments (1)
apps/api/src/routes/v1_keys_removePermissions.ts (1)

116-128: ⚠️ Potential issue

Fix the permission filtering logic.

The filtering logic has an issue - it should return true when a match is found, but currently doesn't have explicit return statements for the matching cases.

 const deletePermissions = connectedPermissions.filter((cr) => {
   for (const deleteRequest of req.permissions) {
     if ("id" in deleteRequest) {
-      return cr.permissionId === deleteRequest.id;
+      if (cr.permissionId === deleteRequest.id) {
+        return true;
+      }
     }
     if ("slug" in deleteRequest) {
-      return cr.permission.slug === deleteRequest.slug;
+      if (cr.permission.slug === deleteRequest.slug) {
+        return true;
+      }
     }
     if ("name" in deleteRequest) {
-      return cr.permission.slug === deleteRequest.name;
+      if (cr.permission.slug === deleteRequest.name) {
+        return true;
+      }
     }
   }
+  return false;
 });
🧹 Nitpick comments (2)
apps/api/src/routes/v1_keys_removePermissions.happy.test.ts (1)

19-25: Consider test consistency and naming clarity.

The first test now uses the same UUID for both name and slug fields, while the second test uses different values. This inconsistency could lead to confusion about the expected behavior during the migration.

Consider either:

  1. Updating the test name to reflect that it's testing slug-based removal with backward compatibility
  2. Ensuring both tests follow the same pattern for name/slug assignment
-test("removes permission by name", async (t) => {
+test("removes permission by name (backward compatibility)", async (t) => {
apps/api/src/routes/v1_keys_setPermissions.ts (1)

30-32: Update field description to reflect new slug priority.

The description for the id field still mentions name instead of slug.

                    description:
-                     "The id of the permission. Provide either `id` or `name`. If both are provided `id` is used.",
+                     "The id of the permission. Provide either `id` or `slug`. If both are provided `id` is used.",
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c6c9e70 and e02173f.

📒 Files selected for processing (4)
  • apps/api/src/routes/v1_apis_listKeys.ts (1 hunks)
  • apps/api/src/routes/v1_keys_removePermissions.happy.test.ts (1 hunks)
  • apps/api/src/routes/v1_keys_removePermissions.ts (2 hunks)
  • apps/api/src/routes/v1_keys_setPermissions.ts (7 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
apps/api/src/routes/v1_keys_removePermissions.happy.test.ts (1)
internal/id/src/generate.ts (1)
  • newId (33-52)
⏰ Context from checks skipped due to timeout of 90000ms (16)
  • GitHub Check: Test Go API Local / Test (Shard 8/8)
  • GitHub Check: Test Go API Local / Test (Shard 7/8)
  • GitHub Check: Test Agent Local / test_agent_local
  • GitHub Check: Test Go API Local / Test (Shard 6/8)
  • GitHub Check: Test Go API Local / Test (Shard 5/8)
  • GitHub Check: Test Go API Local / Test (Shard 2/8)
  • GitHub Check: Test Go API Local / Test (Shard 3/8)
  • GitHub Check: Test Go API Local / Test (Shard 4/8)
  • GitHub Check: Build / Build
  • GitHub Check: Test Go API Local / Test (Shard 1/8)
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Test Packages / Test ./internal/clickhouse
  • GitHub Check: Test Packages / Test ./packages/api
  • GitHub Check: Test Packages / Test ./packages/cache
  • GitHub Check: Test Packages / Test ./packages/hono
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (6)
apps/api/src/routes/v1_apis_listKeys.ts (1)

222-224: LGTM! Permission extraction updated correctly.

The changes properly migrate from using permission.name to permission.slug for both direct permissions and role-based permissions. This aligns with the broader codebase migration to use slugs as the primary permission identifier.

apps/api/src/routes/v1_keys_removePermissions.ts (1)

28-41: LGTM! Schema migration implemented correctly.

The schema changes properly implement the migration from name to slug:

  • New slug field with clear description
  • name field marked as deprecated with migration guidance
  • Updated field descriptions reflect the new priority
apps/api/src/routes/v1_keys_setPermissions.ts (4)

28-41: LGTM! Schema migration implemented correctly.

The schema changes properly implement the migration from name to slug with appropriate deprecation warnings and clear descriptions.


133-136: LGTM! Slug extraction logic implemented correctly.

The logic properly extracts slugs from the request, falling back to name when slug is not provided, maintaining backward compatibility.


246-251: LGTM! Permission creation updated correctly.

The permission creation logic properly sets both name and slug to the same value during the transition period, ensuring consistency.


182-193:

Details

✅ Verification successful

Review the permission filtering logic.

The filtering logic for disconnectPermissions has become complex with the slug migration. Ensure that permissions are properly identified for disconnection when slug is present.

The logic at lines 186-193 filters permissions to disconnect based on whether they match requested permissions. Verify that this logic correctly handles the case where a permission has both name and slug fields.


🏁 Script executed:

#!/bin/bash
# Description: Check for any existing permissions without slug values in the database schema
# Expected: All permissions should have slug values if the migration is complete

ast-grep --pattern $'slug: $_ {
  $$$
}'

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Search for Permission entity definition
rg -n "@Entity.*Permission" -A 5 .

# Find slug column declarations in entities
rg -n "@Column.*slug" -A 5 .

# Check migrations for any slug-related changes
rg -n "slug" -n migrations

Length of output: 145


🏁 Script executed:

#!/bin/bash
# Locate Prisma schema if present
prisma_schema=$(find . -type f -name "schema.prisma")
if [ -n "$prisma_schema" ]; then
  echo "Found Prisma schema: $prisma_schema"
  rg -n "model Permission" -A 5 "$prisma_schema"
  rg -n "slug" -A 5 "$prisma_schema"
fi

# Search for Permission entity/model definitions
rg -n "class Permission" -A 5 .
rg -n "interface Permission" -A 5 .
rg -n "type Permission" -A 5 .

# Search for slug property usages in API source
rg -n "slug" -n apps/api/src -A 3

Length of output: 31279


Permission filtering logic is valid as implemented

The disconnectPermissions filter correctly:

  • Excludes any permission whose ID is in requestedIds
  • Excludes any permission whose slug matches an entry in requestedSlugs
  • Guards against orphaned records lacking both slug and name (a defensive check that shouldn’t trigger once slug migration is complete)

No further changes are required here.

@chronark chronark merged commit b972f0e into main Jun 3, 2025
31 of 37 checks passed
@chronark chronark deleted the permission-slug-step-2 branch June 3, 2025 12:17
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