Skip to content

Realtime: improve scope access to runs with tags and batches #1511

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
Nov 29, 2024

Conversation

ericallam
Copy link
Member

@ericallam ericallam commented Nov 29, 2024

Public access token scopes with just tags or just a batch can now access runs that have those tags or are in the batch. Previously, the only way to access a run was to have a specific scope for that exact run.

  • useTaskTrigger can now submit options
  • auto-generated batch trigger public access tokens no longer need each individual run ID scope

… or are in the batch

- useTaskTrigger can now submit options
- auto-generated batch trigger public access tokens no longer need each individual run ID scope
Copy link

changeset-bot bot commented Nov 29, 2024

🦋 Changeset detected

Latest commit: bd509cb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@trigger.dev/react-hooks Patch
@trigger.dev/sdk Patch
@trigger.dev/build Patch
@trigger.dev/core Patch
@trigger.dev/rsc Patch
@trigger.dev/database Patch
@trigger.dev/otlp-importer Patch
trigger.dev Patch
@internal/redis-worker Patch
@internal/zod-worker Patch
@internal/testcontainers Patch

Not sure what this means? Click here to learn what changesets are.

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

Copy link
Contributor

coderabbitai bot commented Nov 29, 2024

Walkthrough

This pull request includes significant changes across multiple files, primarily focused on the restructuring of presenters and API routes related to batch and run task retrieval. The ApiRetrieveBatchPresenter class has been removed, and its functionality has been integrated into the ApiRetrieveRunPresenter, which now includes a new static method for retrieving task runs. The API routes have shifted from using presenters to direct database queries, altering error handling and response structures. Additionally, various loader functions have been updated to enhance resource retrieval and authorization processes.

Changes

File Change Summary
apps/webapp/app/presenters/v3/ApiRetrieveBatchPresenter.server.ts Removed ApiRetrieveBatchPresenter class and its call method.
apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts Added new static method findRun, refactored call method to accept FoundRun type. Introduced FoundRun type.
apps/webapp/app/routes/api.v1.batches.$batchId.ts Updated loader to directly query database for batch task run, removed presenter layer and error handling for missing batches.
apps/webapp/app/routes/api.v1.packets.$.ts Modified action to check for "PUT" requests and added findResource to loader configuration.
apps/webapp/app/routes/api.v1.runs.$runParam.reschedule.ts Added logic to retrieve run details after updating a task run, updated presenter.call usage.
apps/webapp/app/routes/api.v1.runs.ts Updated loader's authorization structure and added findResource property.
apps/webapp/app/routes/api.v1.tasks.batch.ts Simplified scopes array construction in responseHeaders function for browser clients.
apps/webapp/app/routes/api.v3.runs.$runId.ts Added findResource function to loader configuration, updated authorization structure.
apps/webapp/app/routes/realtime.v1.batches.$batchId.ts Added findResource to retrieve batch task run, updated authorization logic.
apps/webapp/app/routes/realtime.v1.runs.$runId.ts Added findResource to loader, updated authorization structure.
apps/webapp/app/routes/realtime.v1.runs.ts Added findResource to configuration, updated resource function parameters.
apps/webapp/app/routes/realtime.v1.streams.$runId.$streamId.ts Added findResource to loader, updated authorization structure.
apps/webapp/app/services/authorization.server.ts Simplified checkAuthorization function logic and error handling.
apps/webapp/app/services/routeBuilders/apiBuilder.server.ts Updated types to include new generic TResource, added findResource function.
apps/webapp/test/authorization.test.ts Updated test cases for checkAuthorization to reflect new logic and expectations.
packages/core/src/v3/apiClient/index.ts Modified batchTriggerV2 method to change how scopes are constructed for JWT payload.
packages/react-hooks/src/hooks/useTaskTrigger.ts Updated submit method to accept an optional options parameter.
references/nextjs-realtime/src/components/TriggerButton.tsx Updated submit method to accept additional tags parameter.
references/v3-catalog/package.json Updated script command for triggerWithLargePayload.
references/v3-catalog/src/management.ts Added new asynchronous function doRescheduleRun.

Suggested reviewers

  • matt-aitken

🐇 In the code we hop and play,
With presenters gone, we pave the way.
Batch and run, now streamlined bright,
Fetching data with all our might!
A new dawn for tasks, we cheer and sing,
In our coding burrow, let the changes spring! 🌼✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/webapp/app/routes/api.v3.runs.$runId.ts

Oops! Something went wrong! :(

ESLint: 8.45.0

ESLint couldn't find the config "custom" to extend from. Please check that the name of the config is correct.

The config "custom" was referenced from the config file in "/.eslintrc.js".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.


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

🧹 Outside diff range and nitpick comments (18)
apps/webapp/app/routes/api.v3.runs.$runId.ts (2)

28-30: Consider adding type annotations for better type safety

While the code works correctly, adding explicit type annotations would improve maintainability and catch potential issues earlier.

-  async ({ authentication, resource }) => {
+  async ({ authentication, resource }: { authentication: AuthEnvironment; resource: Run }) => {

Line range hint 1-40: Well-designed implementation of scoped access

The overall architecture effectively implements the new scoped access system while maintaining backward compatibility. The separation between resource retrieval, authorization, and response handling creates a maintainable and extensible solution.

Consider documenting these access patterns in the API documentation to help users understand the new capabilities for accessing runs via tags and batches.

references/nextjs-realtime/src/components/TriggerButton.tsx (2)

31-32: Fix typo in city name

"San Fransico" is misspelled. It should be "San Francisco".

-              "Based on the temperature, will I need to wear extra clothes today in San Fransico? Please be detailed.",
+              "Based on the temperature, will I need to wear extra clothes today in San Francisco? Please be detailed.",

34-36: Consider making the user ID dynamic

The user ID is currently hardcoded as "user:1234". Consider making this dynamic by:

  1. Accepting it as a prop
  2. Using a user context
  3. Or fetching it from an authentication service

This would make the component more reusable and maintainable.

Example implementation:

interface TriggerButtonProps {
  accessToken: string;
  userId: string;
}

export default function TriggerButton({ accessToken, userId }: TriggerButtonProps) {
  // ... existing code ...
  
  // Then use it in submit:
  submit(
    { /* ... */ },
    {
      tags: [`user:${userId}`],
    }
  );
}
apps/webapp/app/routes/api.v1.packets.$.ts (1)

Line range hint 50-67: Consider standardizing error response structure

The error response structure in the loader differs slightly from the action function. Consider standardizing the error response format across both functions for consistency.

-      return json({ error: "Failed to generate presigned URL" }, { status: 500 });
+      return json(
+        { error: "Failed to generate presigned URL" },
+        { status: 500, headers: { "Content-Type": "application/json" } }
+      );
apps/webapp/app/routes/api.v1.runs.$runParam.reschedule.ts (3)

64-71: Consider optimizing the double run retrieval and improving error messages

The current implementation performs two separate database queries for the same run. Additionally, the error messages could be more specific.

Consider these improvements:

-    const run = await ApiRetrieveRunPresenter.findRun(
-      updatedRun.friendlyId,
-      authenticationResult.environment
-    );
-
-    if (!run) {
-      return json({ error: "Run not found" }, { status: 404 });
-    }
+    // Reuse the updatedRun or add specific error context
+    const run = await ApiRetrieveRunPresenter.findRun(
+      updatedRun.friendlyId,
+      authenticationResult.environment
+    );
+
+    if (!run) {
+      return json({ error: "Failed to retrieve the rescheduled run" }, { status: 404 });
+    }

Line range hint 74-78: Optimize presenter usage and streamline error handling

The error check after presenter.call might be redundant since we've already verified the run exists. Also, consider reusing the presenter instance.

Consider this improvement:

-    const presenter = new ApiRetrieveRunPresenter();
-    const result = await presenter.call(run, authenticationResult.environment);
-
-    if (!result) {
-      return json({ error: "Run not found" }, { status: 404 });
-    }
-
-    return json(result);
+    const result = await new ApiRetrieveRunPresenter().call(
+      run,
+      authenticationResult.environment
+    );
+    return json(result);

Authentication implementation needs to be updated for new scope requirements

Based on the verification results, the current authentication and authorization system needs attention:

  1. The code is using a deprecated authenticateApiRequest function that doesn't properly handle failure cases. It should be updated to use authenticateApiRequestWithFailure instead.
  2. The authorization system supports granular run-level scopes (e.g., "read:runs:run_1234"), but the rescheduling endpoint isn't leveraging this capability.

Required changes:

  • Update to use authenticateApiRequestWithFailure for proper error handling
  • Add appropriate scope checks using the authorization service to verify run-level access permissions
  • Implement proper authorization checks after authentication using checkAuthorization with the correct run scope
🔗 Analysis chain

Line range hint 19-24: Verify authorization checks align with new scope access requirements

Given that the PR objectives mention improvements to scope access for runs with tags and batches, we should verify that the authentication checks are properly handling these new access patterns.

Let's verify the authentication implementation:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the implementation of authenticateApiRequest to verify scope checks
ast-grep --pattern 'export async function authenticateApiRequest($$$) {
  $$$
}'

# Look for related test files
fd -e test.ts -e spec.ts authenticateApiRequest

Length of output: 132


Script:

#!/bin/bash
# Let's try a broader search for the authentication function
rg -l "authenticateApiRequest"

# Also search for any authentication-related files
fd -e ts auth

# Look for scope-related patterns in authentication files
rg -i "scope.*run" $(fd -e ts auth)

Length of output: 6904


Script:

#!/bin/bash
# Let's check the implementation of authenticateApiRequest in the apiAuth service
rg -A 10 "authenticateApiRequest" apps/webapp/app/services/apiAuth.server.ts

# Also check the authorization service for run-related scope checks
rg -A 10 "scope.*run" apps/webapp/app/services/authorization.server.ts

# Look at the implementation in the API builder since it's used across routes
rg -A 10 "authenticateApiRequest" apps/webapp/app/services/routeBuilders/apiBuilder.server.ts

Length of output: 4451

references/v3-catalog/package.json (1)

13-15: Consider standardizing script execution approach

There's inconsistent usage of tsx vs ts-node across different scripts. For example:

  • management and client use tsx
  • queues uses ts-node
  • triggerWithLargePayload now uses tsx

Consider standardizing the approach across all scripts for better maintainability.

   "scripts": {
     "dev:trigger": "trigger dev",
     "deploy": "trigger deploy --self-hosted --load-image",
     "management": "tsx -r dotenv/config ./src/management.ts",
-    "queues": "ts-node -r dotenv/config -r tsconfig-paths/register ./src/queues.ts",
+    "queues": "tsx -r dotenv/config ./src/queues.ts",
     "build:client": "tsup-node ./src/clientUsage.ts --format esm,cjs",
     "client": "tsx -r dotenv/config ./src/clientUsage.ts",
     "triggerWithLargePayload": "tsx -r dotenv/config ./src/triggerWithLargePayload.ts",
apps/webapp/app/services/authorization.server.ts (2)

97-99: Consider optimizing permission check order for performance.

The current implementation checks both specific and general permissions for each resource. For better performance, consider checking general permissions first, as they would grant access to all resources of that type.

-      if (entity.scopes.includes(specificPermission) || entity.scopes.includes(generalPermission)) {
+      // Check general permission first as it's more broad
+      if (entity.scopes.includes(generalPermission) || entity.scopes.includes(specificPermission)) {
         return { authorized: true };
       }

104-112: Improve error message formatting for better readability.

While the error message is informative, the formatting could be more concise.

-    reason: `Public Access Token is missing required permissions. Token has the following permissions: ${entity.scopes
-      .map((s) => `'${s}'`)
-      .join(
-        ", "
-      )}. See https://trigger.dev/docs/frontend/overview#authentication for more information.`,
+    reason: `Public Access Token is missing required permissions. Token has the following permissions: ${entity.scopes.map(s => `'${s}'`).join(", ")}. See https://trigger.dev/docs/frontend/overview#authentication for more information.`,
apps/webapp/app/routes/api.v1.tasks.batch.ts (1)

Line range hint 89-106: Enhance error messages for security-related failures.

While the error handling is comprehensive, consider adding more specific error messages for security-related failures to help with debugging and auditing.

Consider this enhancement:

 } catch (error) {
   logger.error("Batch trigger error", {
     error: {
       message: (error as Error).message,
       stack: (error as Error).stack,
+      type: error.constructor.name,  // Add error type for better debugging
     },
   });

   if (error instanceof ServiceValidationError) {
-    return json({ error: error.message }, { status: 422 });
+    return json({ 
+      error: error.message,
+      code: 'VALIDATION_ERROR'
+    }, { status: 422 });
   } else if (error instanceof OutOfEntitlementError) {
-    return json({ error: error.message }, { status: 422 });
+    return json({ 
+      error: error.message,
+      code: 'ENTITLEMENT_ERROR'
+    }, { status: 422 });
   }
packages/react-hooks/src/hooks/useTaskTrigger.ts (1)

29-29: Update interface documentation to include the new options parameter.

The interface has been correctly updated to support optional trigger options, but the documentation comment above the interface should be updated to reflect this new parameter.

references/v3-catalog/src/management.ts (1)

274-288: Consider reducing the initial delay for practical testing

The 1-hour initial delay makes this example impractical for testing purposes. Consider using a shorter initial delay (e.g., "10s") to make the example more developer-friendly while still demonstrating the rescheduling functionality.

-  const run = await simpleChildTask.trigger({ message: "Hello, World!" }, { delay: "1h" });
+  const run = await simpleChildTask.trigger({ message: "Hello, World!" }, { delay: "10s" });

Additionally, consider adding validation to ensure the reschedule was successful:

   const reschedule = await runs.reschedule(run.id, {
     delay: "1s",
   });

   console.log("reschedule", reschedule);
+  
+  // Validate reschedule response
+  if (!reschedule?.id) {
+    throw new Error("Failed to reschedule run");
+  }

   const rescheduledRun = await waitForRunToComplete(reschedule.id);
apps/webapp/test/authorization.test.ts (1)

68-68: Consider extracting the documentation URL to a constant

The documentation URL "https://trigger.dev/docs/frontend/overview#authentication" is duplicated across multiple error messages. Consider extracting it to a constant at the top of the file to improve maintainability.

 import { describe, it, expect } from "vitest";
 import { checkAuthorization, AuthorizationEntity } from "../app/services/authorization.server";
+
+const AUTH_DOCS_URL = "https://trigger.dev/docs/frontend/overview#authentication";

Also applies to: 244-244, 281-281, 314-314

apps/webapp/app/routes/api.v1.batches.$batchId.ts (1)

3-3: Ensure correct import path for $replica.

At line 3, $replica is imported from "~/db.server". Verify that this path is correct and that $replica is properly initialized. Misconfigured imports can lead to runtime errors.

Confirm that the import aligns with the project's structure and adjust the path if necessary.

-import { $replica } from "~/db.server";
+import { $replica } from "~/path/to/db.server";
apps/webapp/app/routes/realtime.v1.streams.$runId.$streamId.ts (1)

27-41: Optimize database query by selecting only necessary fields

In the findResource function, consider selecting only the fields required for authorization and response. This optimization reduces data transfer and improves query performance.

Apply this diff to select necessary fields:

 return $replica.taskRun.findFirst({
   where: {
     friendlyId: params.runId,
     runtimeEnvironmentId: auth.environment.id,
   },
+  select: {
+    friendlyId: true,
+    runTags: true,
+    batch: {
+      select: {
+        friendlyId: true,
+      },
+    },
+  },
 });
apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts (1)

18-18: Confirm the necessity of importing both $replica and prisma

You have imported both $replica and prisma. Since $replica is used for read operations and prisma for write operations, ensure that this distinction is intentional and necessary within this file.

If prisma is not used elsewhere in the file, consider removing it to clean up unused imports.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d67023a and a5d43b0.

📒 Files selected for processing (20)
  • apps/webapp/app/presenters/v3/ApiRetrieveBatchPresenter.server.ts (0 hunks)
  • apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts (2 hunks)
  • apps/webapp/app/routes/api.v1.batches.$batchId.ts (2 hunks)
  • apps/webapp/app/routes/api.v1.packets.$.ts (1 hunks)
  • apps/webapp/app/routes/api.v1.runs.$runParam.reschedule.ts (1 hunks)
  • apps/webapp/app/routes/api.v1.runs.ts (1 hunks)
  • apps/webapp/app/routes/api.v1.tasks.batch.ts (1 hunks)
  • apps/webapp/app/routes/api.v3.runs.$runId.ts (1 hunks)
  • apps/webapp/app/routes/realtime.v1.batches.$batchId.ts (1 hunks)
  • apps/webapp/app/routes/realtime.v1.runs.$runId.ts (1 hunks)
  • apps/webapp/app/routes/realtime.v1.runs.ts (1 hunks)
  • apps/webapp/app/routes/realtime.v1.streams.$runId.$streamId.ts (1 hunks)
  • apps/webapp/app/services/authorization.server.ts (1 hunks)
  • apps/webapp/app/services/routeBuilders/apiBuilder.server.ts (6 hunks)
  • apps/webapp/test/authorization.test.ts (6 hunks)
  • packages/core/src/v3/apiClient/index.ts (1 hunks)
  • packages/react-hooks/src/hooks/useTaskTrigger.ts (2 hunks)
  • references/nextjs-realtime/src/components/TriggerButton.tsx (1 hunks)
  • references/v3-catalog/package.json (1 hunks)
  • references/v3-catalog/src/management.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/webapp/app/presenters/v3/ApiRetrieveBatchPresenter.server.ts
🔇 Additional comments (36)
apps/webapp/app/routes/api.v1.runs.ts (1)

15-17: Verify the authorization scope changes

The changes to the resource function align with the PR objective of improving run accessibility via public access tokens. However, let's verify that this implementation correctly handles the new tag and batch-based access patterns mentioned in the PR objectives.

✅ Verification successful

Authorization resource function implementation is consistent with codebase patterns

The resource function implementation is correct and aligns with established patterns in the codebase:

  • The three-parameter signature (_, __, searchParams) matches other route handlers like realtime.v1.runs.ts
  • Task filtering via filter[taskIdentifier] is consistently used across the codebase, appearing in API client, presenters, and routes
  • The superScopes ["read:runs", "read:all", "admin"] align with other run-related endpoints
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent authorization patterns across related files

# Look for similar authorization patterns in other run-related routes
echo "Checking authorization patterns in run-related routes..."
rg -A 5 "authorization.*resource.*tasks" "apps/webapp/app/routes"

# Check for tag and batch-related authorization logic
echo "Checking tag and batch authorization implementations..."
rg -A 10 "authorization.*resource.*(tag|batch)" "apps/webapp/app/routes"

Length of output: 382


Script:

#!/bin/bash
# Let's try a different approach to verify the authorization changes

# 1. First, let's find all files that might contain authorization configurations
echo "Files with authorization configurations:"
rg -l "authorization.*superScopes" --type ts

# 2. Let's examine the resource function patterns in these files
echo -e "\nResource function patterns:"
rg -B2 -A2 "resource:\s*\([^)]*\)\s*=>" --type ts

# 3. Let's also check for any task-related filters in the codebase
echo -e "\nTask filter usage patterns:"
rg "filter\[taskIdentifier\]" --type ts

Length of output: 4532

apps/webapp/app/routes/realtime.v1.runs.ts (2)

19-19: Clarify the purpose of the dummy findResource implementation

The comment indicates this is a dummy value that's not used. However, given the PR's objective to improve scope access, this seems like it could be a missed opportunity or incomplete implementation.

Let's check how findResource is implemented in related files:


22-24: Verify the authorization implementation for tag-based access

The resource function now properly receives searchParams which contain tags, aligning with the PR's objective to enable tag-based access. However, we should verify that the superScopes array properly covers all the access patterns described in the PR objectives.

Let's analyze the scope implementation across the codebase:

✅ Verification successful

Let me gather more information about the tag-based access implementation to ensure complete verification.


Let me check one more aspect of the authorization implementation to complete the verification.


Let me check the complete authorization implementation to understand how tag-based scopes are validated.


Let me check one final piece to understand the complete scope of resource types.


The authorization implementation correctly supports tag-based access control

The implementation is verified to be correct for the following reasons:

  • The superScopes array containing ["read:runs", "read:all", "admin"] provides the necessary high-level access patterns
  • The authorization system supports granular tag-based access through:
    • Tags are included in the ResourceTypes constant
    • The AuthorizationResources type properly handles tag resources
    • The checkAuthorization function validates both super scopes and specific resource-level permissions
  • Test coverage confirms the implementation with examples of tag-specific scopes like read:tags:tag_5678
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other implementations of superScopes to ensure consistency
rg "superScopes:\s+\[" "apps/webapp/app/routes/"

# Search for scope-related tests
rg -g "*.test.*" "read:runs|read:all|admin" "apps/webapp/"

Length of output: 2276


Script:

#!/bin/bash
# Search for tag-based access implementation in authorization code
rg -A 5 "read:runs:" "apps/webapp/"

# Look for tag-related scope implementations
ast-grep --pattern 'function $_($$_) {
  $$$
  read:runs
  $$$
}'

# Check for any tag-based authorization tests
rg -g "*.test.*" "read:tags|read:runs:[a-zA-Z0-9]" "apps/webapp/"

Length of output: 3078


Script:

#!/bin/bash
# Look for the authorization check implementation
rg -A 10 "function checkAuthorization" "apps/webapp/"

# Search for any tag-based scope validation logic
rg -A 5 "superScopes.*\[.*read:runs" "apps/webapp/app/services/"

Length of output: 974


Script:

#!/bin/bash
# Get the full implementation of the authorization check
rg -A 50 "export function checkAuthorization" "apps/webapp/app/services/authorization.server.ts"

# Look for tag-based scope definitions
rg "type.*AuthorizationResources" -A 10 "apps/webapp/"

Length of output: 2808


Script:

#!/bin/bash
# Look for ResourceTypes definition
rg "ResourceTypes.*=.*\[" -A 5 "apps/webapp/"

# Check for any tag-specific resource type handling
rg "tags.*:.*string" "apps/webapp/"

Length of output: 782

apps/webapp/app/routes/api.v3.runs.$runId.ts (2)

15-17: LGTM! Good separation of concerns

The findResource function cleanly separates resource retrieval from authorization logic, following the single responsibility principle.


19-24: Verify the completeness of authorization scopes

The new authorization structure properly implements tag and batch-based access as intended. However, let's verify that all necessary access patterns are covered.

✅ Verification successful

Based on the results, I can now generate the final response as I have sufficient information about the scope configurations across the codebase.

Authorization scopes are properly configured and consistent

The authorization structure is complete and well-aligned across the codebase:

  • All run-related endpoints consistently use the same scope structure (runs, tags, batch) and superScopes ["read:runs", "read:all", "admin"]
  • The authorization service properly handles both regular scopes and superScopes
  • Test coverage confirms the correct behavior of scope-based authorization
  • Other related endpoints (batches, tasks) follow the same pattern with appropriate superScopes
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any other scope-related configurations that might need updating

# Look for other files defining scopes or authorization patterns
rg -A 3 "superScopes|resource: \(" --type ts

# Look for any scope-related tests
rg -A 3 "describe.*scope" --type ts

Length of output: 11593

references/nextjs-realtime/src/components/TriggerButton.tsx (1)

28-37: Verify the new submit options implementation

The changes align with the PR objectives by implementing tag-based run access. Let's verify the implementation across the codebase.

✅ Verification successful

Let me gather more information about the submit implementation and its usage patterns with a different search strategy.


Based on the search results, I can now provide a final response about the tag-based run access implementation:

Tag-based run access is correctly implemented across the codebase

The implementation in TriggerButton.tsx aligns with the established patterns across the codebase:

  • The useTaskTrigger hook properly supports tags in its options (packages/react-hooks/src/hooks/useTaskTrigger.ts)
  • Tag handling is consistently implemented in the backend services (apps/webapp/app/services/)
  • The authorization system correctly validates tag-based access (apps/webapp/test/authorization.test.ts)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent implementation of the new submit options pattern
# and verify the integration with run presenters

# Check for other useTaskTrigger usage patterns
echo "Checking useTaskTrigger usage patterns:"
rg "useTaskTrigger.*submit.*tags" -A 5

# Check for related presenter implementations
echo "Checking run presenter implementations:"
ast-grep --pattern 'class $presenter {
  $$$
  findRun($$$) {
    $$$
  }
  $$$
}'

Length of output: 303


Script:

#!/bin/bash
# Search for useTaskTrigger hook usage
echo "Checking useTaskTrigger hook usage:"
rg "useTaskTrigger" -A 3

# Search for submit function implementations and calls
echo "Checking submit function implementations:"
ast-grep --pattern 'submit($$$) {
  $$$
}'

# Search for any tag-related implementations
echo "Checking tag-related patterns:"
rg "tags:" -A 2

Length of output: 30823

apps/webapp/app/routes/api.v1.packets.$.ts (1)

48-48: Verify security implications of the dummy findResource function

The dummy implementation that always returns 1 appears to bypass resource validation. While this might be intentional as part of the broader scope access improvements mentioned in the PR, we should verify that this doesn't inadvertently create security vulnerabilities.

Let's check how findResource is implemented in related routes:

✅ Verification successful

Dummy findResource function is safe in this context

After reviewing the implementation, the dummy findResource function that returns 1 is safe because:

  1. The route is specifically for handling presigned URL generation for packets
  2. The createLoaderApiRoute still enforces authentication via JWT/API key through authenticateApiRequestWithFailure
  3. The actual authorization is handled through the presigned URL mechanism, not through the resource lookup
  4. Other routes in the codebase (e.g., realtime.v1.runs.ts) also use dummy findResource functions when resource lookup isn't needed
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other implementations of findResource to understand the pattern
rg -A 5 "findResource.*=.*async" --type typescript

# Search for createLoaderApiRoute usage to understand the security context
ast-grep --pattern 'createLoaderApiRoute({
  $$$
})'

Length of output: 142


Script:

#!/bin/bash
# Search for findResource implementations without file type restriction
rg -A 5 "findResource.*=.*async"

# Search for createLoaderApiRoute usage
rg -A 5 "createLoaderApiRoute"

# Look for similar route files handling packets
fd "packets" --type f

Length of output: 7927


Script:

#!/bin/bash
# Let's check the apiBuilder.server.ts to understand the security model
cat apps/webapp/app/services/routeBuilders/apiBuilder.server.ts

# Check the implementation of packets.ts utility
cat apps/webapp/app/utils/packets.ts

Length of output: 21305

references/v3-catalog/package.json (1)

15-15: Verify module resolution after removing tsconfig-paths

The script no longer uses tsconfig-paths/register. Please ensure that all imports in triggerWithLargePayload.ts are using correct paths and the module resolution still works as expected.

✅ Verification successful

Path resolution is working correctly without tsconfig-paths

The file references/v3-catalog/src/triggerWithLargePayload.ts uses standard package imports from @trigger.dev/sdk/v3 and a local relative import ./trigger/simple.js. The removal of tsconfig-paths/register does not impact the imports because:

  1. The @trigger.dev imports are resolved through the package resolution system
  2. The local import uses a relative path which doesn't require path alias resolution
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for path aliases usage in the target file

# Look for potential path aliases (imports starting with @) in the file
echo "Checking for path aliases in triggerWithLargePayload.ts:"
rg "^import.*from ['\"]@" ./src/triggerWithLargePayload.ts

# Look for tsconfig.json path aliases configuration
echo -e "\nChecking for path aliases configuration in tsconfig:"
fd tsconfig.json --exec cat {} | jq '.compilerOptions.paths'

Length of output: 3067


Script:

#!/bin/bash
# Let's first find the correct location of triggerWithLargePayload.ts
echo "Finding triggerWithLargePayload.ts:"
fd triggerWithLargePayload.ts

# Once we find it, let's check its imports
echo -e "\nChecking all imports in the file:"
fd triggerWithLargePayload.ts --exec rg "^import" {}

# Let's also check the directory structure to understand the file location
echo -e "\nChecking directory structure:"
fd --type d --max-depth 3

Length of output: 2577

apps/webapp/app/services/authorization.server.ts (1)

Line range hint 1-112: Verify the implementation covers all access scenarios.

The changes align well with the PR objectives for improving scope access. Let's verify that all access patterns work as expected.

✅ Verification successful

Let me analyze the test coverage specifically for the authorization implementation.


Implementation verified with comprehensive test coverage

The authorization implementation has been thoroughly tested, covering:

  • Tag and batch resource types in the ResourceTypes constant
  • All entity types (PRIVATE, PUBLIC, PUBLIC_JWT)
  • Both specific and general permission patterns
  • Array-based resource access
  • Super scope functionality
  • Edge cases including empty resources and undefined scopes
  • Error scenarios with detailed messages
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the authorization implementation handles all required access patterns

# Check for test coverage of new access patterns
echo "Checking test coverage for tag and batch access patterns..."
rg -l "test|spec|describe.*tag.*scope|batch.*scope" --type ts

# Verify error scenarios are properly tested
echo "Checking error scenario test coverage..."
rg -l "test|spec|describe.*unauthorized|permission.*denied" --type ts

# Look for any hardcoded scope patterns that might conflict
echo "Checking for conflicting scope patterns..."
rg "scope.*tag|scope.*batch|permission.*tag|permission.*batch" --type ts

Length of output: 23223


Script:

#!/bin/bash
# Check the authorization test file content
echo "Checking authorization test coverage..."
cat apps/webapp/test/authorization.test.ts

# Look for any authorization-related test files we might have missed
echo -e "\nChecking for additional authorization test files..."
rg -l "describe.*authorization|test.*authorization" --type ts

Length of output: 12580

apps/webapp/app/routes/api.v1.tasks.batch.ts (1)

136-136: LGTM! Verify authorization checks for batch-scoped access.

The simplified scope approach using read:batch:${batch.id} is a good improvement that:

  • Reduces JWT complexity by eliminating individual run scopes
  • Maintains security through proper scope hierarchy
  • Aligns with the PR objective of improving run accessibility

Let's verify that batch-scoped authorization is properly enforced:

packages/react-hooks/src/hooks/useTaskTrigger.ts (2)

97-99: LGTM! Implementation correctly handles trigger options.

The changes properly integrate the new options parameter with the existing mutation system, maintaining type safety and backward compatibility. This implementation supports the PR's objective of improving scope access through tags.


29-29: Verify tag handling in the codebase.

The changes support tag-based scope access as intended. Let's verify the integration with the rest of the codebase.

Also applies to: 97-99

✅ Verification successful

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

Tag handling is properly integrated in the codebase

The TriggerOptions type in packages/core/src/v3/types/tasks.ts includes tags support, and the implementation in useTaskTrigger.ts correctly passes tags through to the API client. The hook properly handles tags in the options parameter and propagates them during task submission, as seen in the implementation:

options: {
  ...
  tags: options?.tags,
  ...
}
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the integration of tag-based scope access.

# Check for tag-related types and interfaces
echo "Checking for tag-related type definitions..."
rg -t typescript "interface.*TriggerOptions" -A 10

# Check for tag usage in API routes and handlers
echo "Checking for tag handling in API routes..."
rg -t typescript "tags.*TriggerOptions"

# Check for tag-related tests
echo "Checking for tag-related tests..."
fd -e test.ts -e spec.ts | xargs rg "tags.*TriggerOptions"

Length of output: 496


Script:

#!/bin/bash
# Let's try a different approach to verify tag handling

# Search for TriggerOptions interface definition
echo "Searching for TriggerOptions interface..."
rg "interface.*TriggerOptions"

# Look for tag-related properties or methods
echo "Searching for tag-related code..."
rg "tags.*:" -A 2

# Check for tag usage in function parameters
echo "Checking tag usage in parameters..."
rg "options.*TriggerOptions"

# Search for any tag-related implementations
echo "Searching for tag implementations..."
ast-grep --pattern 'interface TriggerOptions {
  $$$
}'

Length of output: 39624


Script:

#!/bin/bash
# Let's find the TriggerOptions interface definition and its usage

# Search for TriggerOptions interface definition
echo "Searching for TriggerOptions interface..."
ast-grep --pattern 'interface TriggerOptions {
  $$$
}'

# Look for the specific file where TriggerOptions is defined
echo "Looking for TriggerOptions definition file..."
fd -e ts -e tsx | xargs rg "interface.*TriggerOptions" -A 5

# Check for tag-related imports and usage in useTaskTrigger
echo "Checking useTaskTrigger implementation..."
rg -A 10 "useTaskTrigger" packages/react-hooks/src/hooks/useTaskTrigger.ts

Length of output: 2168


Script:

#!/bin/bash
# Let's find the core TriggerOptions type definition

# Search in core package
echo "Searching in core package..."
rg "interface.*TriggerOptions" packages/core/src/v3/types/ -A 10

# Search in trigger-sdk package
echo "Searching in trigger-sdk package..."
rg "interface.*TriggerOptions" packages/trigger-sdk/src/ -A 10

# Look for the specific implementation of tags in TriggerOptions
echo "Looking for tags in TriggerOptions..."
ast-grep --pattern 'interface TriggerOptions {
  $$$
  tags?: $_
  $$$
}'

Length of output: 440


Script:

#!/bin/bash
# Let's try a different approach to find TriggerOptions

# Look for type or interface definitions of TriggerOptions
echo "Searching for TriggerOptions type definition..."
rg "export (type|interface) TriggerOptions" -A 10

# Look for the file content directly
echo "Looking at useTaskTrigger.ts content..."
cat packages/react-hooks/src/hooks/useTaskTrigger.ts

# Check for any imports of TriggerOptions
echo "Checking TriggerOptions imports..."
rg "import.*TriggerOptions"

Length of output: 8317

references/v3-catalog/src/management.ts (1)

293-296: Verify test coverage for batch and scope access features

While testing the reschedule functionality is important, the PR objectives mention improvements to scope access for runs with tags and batches. Consider uncommenting doBatchTrigger and adding new test cases to verify:

  1. Access to runs using tag-scoped tokens
  2. Access to runs using batch-scoped tokens
  3. Auto-generated batch trigger public access token functionality

Let's verify if there are any existing tests for these features:

apps/webapp/test/authorization.test.ts (1)

100-101: ⚠️ Potential issue

Breaking Change: Authorization behavior for nonexistent resource types

The test now expects unauthorized access for nonexistent resource types, which is a breaking change from the previous behavior. This change should be:

  1. Documented in the PR description
  2. Added to the changelog
  3. Communicated to users as it may affect existing implementations

Let's verify if this is used in the codebase:

packages/core/src/v3/apiClient/index.ts (2)

Line range hint 150-190: Implementation consistently handles scoped access across features.

The triggerTask method's scope handling (combining run and tag scopes) provides a good precedent for the batch scope implementation. This consistency in access control patterns across different features enhances maintainability.


258-258: LGTM: Simplified batch access scope aligns with PR objectives.

The change to only include read:batch:${data.id} in the JWT scopes aligns with the PR's goal of improving run accessibility through batch scopes. This simplification is secure as it maintains proper access control while reducing token size.

Let's verify that this change is consistent with the batch access patterns in the codebase:

✅ Verification successful

LGTM: Batch scope implementation is consistent across the codebase

The verification confirms that:

  • The read:batch:<batchId> scope is consistently implemented across the codebase
  • No individual run scopes are used in batch contexts
  • Documentation in docs/realtime/subscribe-to-batch.mdx aligns with the implementation
  • The scope pattern is consistently used in both API client and server-side routes
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for batch access patterns and scope usage
# Expected: Only batch-level scope checks, no individual run scope checks for batch access

# Check for batch scope validation in auth middleware or handlers
rg -A 5 "read:batch:" 

# Check for any remaining individual run scope checks in batch contexts
ast-grep --pattern 'read:runs:$_' 

Length of output: 1310

apps/webapp/app/routes/realtime.v1.batches.$batchId.ts (1)

29-29: Function signature updated appropriately to accept batchRun

The async function now accepts resource: batchRun, aligning with the updated structure and providing direct access to the batchRun resource retrieved by findResource.

apps/webapp/app/routes/realtime.v1.runs.$runId.ts (3)

16-30: Correct implementation of findResource function

The findResource function accurately retrieves the taskRun based on friendlyId and runtimeEnvironmentId, including the necessary batch information for authorization.


33-37: Proper construction of the authorization resource

The resource object correctly includes runs, tags, and batch, ensuring that access control is properly enforced based on these attributes.


Line range hint 41-46: Updated handler function aligns with the new resource retrieval

The handler function now correctly accepts { authentication, request, resource: run } and utilizes realtimeClient.streamRun with run.id, maintaining consistency with the refactored resource handling.

apps/webapp/app/routes/realtime.v1.streams.$runId.$streamId.ts (2)

52-54: Function signature update aligns with resource usage

The updated function signature now accepts resource: run, which matches the output of findResource. This change ensures the run object is properly utilized in the response.


44-48: Verify access control implications of 'tags' and 'batch' in authorization resource

Adding tags and batch to the authorization resource might affect access control. Ensure this change aligns with your security policies and that scopes are correctly enforced.

Run the following script to verify usage of tags and batch in access control checks:

✅ Verification successful

Let's analyze the authorization patterns more comprehensively to understand the security implications.


Let's analyze the actual authorization implementation and how resources are handled in the security context.


Adding 'tags' and 'batch' to authorization resource is safe and properly handled

Based on the authorization implementation in authorization.server.ts, both 'tags' and 'batch' are explicitly included in the ResourceTypes constant and are properly handled by the authorization system. The implementation:

  • Validates these resource types against a predefined list
  • Supports both specific and general permission patterns (e.g., read:tags:specific_tag or read:tags)
  • Has comprehensive test coverage for similar resource types
  • Properly handles array-based resources
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for access control checks involving 'tags' and 'batch'.

# Search for authorization usage of 'tags'
rg 'authorize.*tags' -A 5

# Search for authorization usage of 'batch'
rg 'authorize.*batch' -A 5

Length of output: 56


Script:

#!/bin/bash
# Let's try a broader search for authorization patterns and resource definitions

# Search for authorization-related files and patterns
rg -l "authorize|permission|resource" --type ts

# Search for resource definitions in authorization contexts
ast-grep --pattern 'resource: $_'

# Search specifically in the realtime routes directory for authorization
fd realtime.v1 --type f --exec rg -l "authorize|permission|resource" {}

Length of output: 5949


Script:

#!/bin/bash
# Let's examine the authorization implementation and resource usage

# Check the authorization service implementation
cat apps/webapp/app/services/authorization.server.ts

# Look at the realtime stream route implementation
cat apps/webapp/app/routes/realtime.v1.streams.$runId.$streamId.ts

# Check authorization tests for resource patterns
cat apps/webapp/test/authorization.test.ts

Length of output: 16386

apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts (2)

97-100: ⚠️ Potential issue

Update method callers to match new call signature

The call method signature has changed to accept taskRun: FoundRun instead of friendlyId: string. Ensure that all callers of ApiRetrieveRunPresenter.call are updated to pass the taskRun object returned from findRun.

Run the following script to find all invocations of call and check that they pass a taskRun object:

✅ Verification successful

All callers have been updated to match the new signature

Based on the search results, I found all usages of ApiRetrieveRunPresenter.call() in the codebase:

  1. In apps/webapp/app/routes/api.v3.runs.$runId.ts:
const presenter = new ApiRetrieveRunPresenter();
const result = await presenter.call(resource, authentication.environment);
  1. In apps/webapp/app/routes/api.v1.runs.$runParam.reschedule.ts:
const presenter = new ApiRetrieveRunPresenter();
const result = await presenter.call(run, authenticationResult.environment);

In both cases, the callers are correctly passing a taskRun object (named as resource and run respectively) that was obtained from ApiRetrieveRunPresenter.findRun(). The signatures match the new method definition and no updates are needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all `call` method invocations are updated to pass `taskRun`.

# Test: Search for `call` method usages. Expect: First argument is a `taskRun` object.
rg 'ApiRetrieveRunPresenter\.call\(' -A 1

Length of output: 43


Script:

#!/bin/bash
# Let's try a broader search to find usages of ApiRetrieveRunPresenter
rg "ApiRetrieveRunPresenter" -A 5

Length of output: 8749


Script:

#!/bin/bash
# Let's also search for any imports of this presenter
rg "import.*ApiRetrieveRunPresenter" 

Length of output: 458


Script:

#!/bin/bash
# Let's use ast-grep to find class instantiation and method calls
ast-grep --pattern 'new ApiRetrieveRunPresenter'

Length of output: 266


Script:

#!/bin/bash
# Let's check the file itself to understand the class better
cat "apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts"

Length of output: 9996


65-95: ⚠️ Potential issue

Handle potential null return from findRun method

The findRun method uses findFirst, which may return null if no matching taskRun is found. However, the FoundRun type is defined using NonNullable, implying that taskRun is always non-null when passed to the call method. This could lead to runtime errors if null is passed inadvertently.

Ensure that all callers of findRun properly handle the possibility of a null return value before invoking call. Consider throwing an error within findRun when no run is found to enforce non-nullability.

Run the following script to verify that all usages of findRun handle the null case appropriately:

apps/webapp/app/services/routeBuilders/apiBuilder.server.ts (12)

24-25: Addition of 'TResource' generic parameter enhances flexibility

The introduction of TResource with a default of never provides a way to specify the resource type, improving the type safety and flexibility of the code.


32-35: Implementation of 'findResource' function enables resource retrieval

Adding the findResource function allows dynamic retrieval of resources based on parameters and authentication, enhancing modularity and reusability.


53-54: Inclusion of 'TResource' in 'ApiKeyHandlerFunction'

Extending ApiKeyHandlerFunction with TResource ensures that handlers receive a properly typed resource, improving type safety.


63-63: Handler function now receives 'resource' parameter

Including resource in the handler arguments provides direct access to the retrieved resource within the handler, enhancing functionality.


69-70: Adding 'TResource' to 'createLoaderApiRoute' generic parameters

Incorporating TResource into the generic parameters of createLoaderApiRoute allows for consistent typing throughout the API route creation process.


72-73: Passing 'TResource' to options and handler

Propagating TResource through options and handler ensures that resource typing is maintained across the API route, improving code consistency.


83-83: Including 'findResource' in options destructuring

Destructuring findResource from options facilitates resource retrieval within the loader function, enhancing code readability.


159-169: Resource retrieval and 404 handling added

The loader now calls findResource to retrieve the resource and returns a 404 response if not found. This improves error handling and provides clearer feedback to API consumers.


171-177: Authorization now utilizes the retrieved resource

The authorization logic now uses the retrieved resource in checks, enhancing security by ensuring permissions are correctly enforced on the specific resource.


181-181: Logging updated to include authorization resource

Including $authResource in the debug logs provides better traceability and aids in debugging authorization issues.


189-189: Authorization check now uses '$authResource'

Passing $authResource to checkAuthorization ensures accurate permission verification against the specific resource, enhancing security.


216-216: Handler receives the 'resource'

Passing the resource to the handler function allows business logic to access the resource directly, improving the handler's capability to process requests effectively.

authorization: {
action: "read",
resource: (params) => ({ batch: params.batchId }),
resource: (batch) => ({ batch: batch.friendlyId }),
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

Ensure safe access to batch.friendlyId in authorization resource

In the authorization block, the resource function accesses batch.friendlyId. If batch is null, this will cause a runtime error. Verify that the authorization logic handles null resources appropriately to prevent potential exceptions.

Consider adjusting the resource function or ensuring upstream that batch cannot be null at this point.

Copy link

pkg-pr-new bot commented Nov 29, 2024

@trigger.dev/build

npm i https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/build@1511

@trigger.dev/react-hooks

npm i https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/react-hooks@1511

@trigger.dev/rsc

npm i https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/rsc@1511

trigger.dev

npm i https://pkg.pr.new/triggerdotdev/trigger.dev@1511

@trigger.dev/sdk

npm i https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/sdk@1511

@trigger.dev/core

npm i https://pkg.pr.new/triggerdotdev/trigger.dev/@trigger.dev/core@1511

commit: bd509cb

Also removed scopes for tags when auto-generating a public access token as that could be dangerous.
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: 1

🧹 Outside diff range and nitpick comments (5)
apps/webapp/app/routes/realtime.v1.runs.$runId.ts (1)

16-30: Consider adding explicit error handling for missing runs

The database query is well-structured and properly scoped to the environment. However, consider handling the case where no run is found explicitly, rather than letting it propagate to the default error handler.

 findResource: async (params, authentication) => {
   const run = await $replica.taskRun.findFirst({
     where: {
       friendlyId: params.runId,
       runtimeEnvironmentId: authentication.environment.id,
     },
     include: {
       batch: {
         select: {
           friendlyId: true,
         },
       },
     },
   });
+  if (!run) {
+    throw json({ error: `Run ${params.runId} not found` }, { status: 404 });
+  }
   return run;
 },
docs/frontend/overview.mdx (2)

19-19: Add missing comma after "By default"

For better readability and correct grammar, add a comma after "By default".

-By default a Public Access Token has no permissions.
+By default, a Public Access Token has no permissions.

149-149: Consider adding more detail about default scopes.

While the documentation mentions the read scope for the specific run, it would be helpful to explicitly document what default scopes are included for batch-triggered runs, especially given the PR's focus on improving batch trigger public access tokens.

Consider adding a note like:

-By default, tokens returned from the `trigger` function expire after 15 minutes and have a read scope for that specific run.
+By default, tokens returned from the `trigger` function expire after 15 minutes and have a read scope for that specific run. For batch-triggered runs, the token automatically includes read scope for all runs in the batch.
docs/frontend/react-hooks.mdx (2)

147-147: Enhance security documentation for token handling

The comment about token scope could be more detailed to align with the PR's improvements to scope access. Consider expanding it to clarify:

  1. That the token can now access runs via tags and batches
  2. The security implications of storing tokens in cookies

Update the comment to be more comprehensive:

-  cookies().set("publicAccessToken", handle.publicAccessToken); // ✅ this token only has access to read this run
+  cookies().set("publicAccessToken", handle.publicAccessToken, {
+    httpOnly: true,  // Prevents JavaScript access
+    secure: true,    // Only sent over HTTPS
+    sameSite: 'strict'  // CSRF protection
+  }); // ✅ This token has scoped access to read this run and associated runs via tags/batches

Additionally, consider adding a note about token expiration and rotation best practices.


Line range hint 1-24: Add examples demonstrating new token scope capabilities

The documentation would benefit from additional examples that showcase the PR's improvements to token scoping, particularly:

  1. How to generate and use tokens scoped to tags
  2. How to use batch-scoped tokens
  3. Examples of auto-generated batch trigger tokens

Consider adding a new section under "Authentication" with examples like:

// Example of generating a tag-scoped token
const tagScopedToken = auth.createPublicToken({
  scopes: {
    read: {
      tags: ["deployment-123"]  // Access all runs with this tag
    }
  }
});

// Example of generating a batch-scoped token
const batchScopedToken = auth.createPublicToken({
  scopes: {
    read: {
      batches: ["batch-123"]  // Access all runs in this batch
    }
  }
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a5d43b0 and bd509cb.

📒 Files selected for processing (7)
  • .changeset/purple-snakes-divide.md (1 hunks)
  • apps/webapp/app/routes/api.v3.runs.$runId.ts (1 hunks)
  • apps/webapp/app/routes/realtime.v1.runs.$runId.ts (1 hunks)
  • apps/webapp/app/routes/realtime.v1.streams.$runId.$streamId.ts (1 hunks)
  • docs/frontend/overview.mdx (7 hunks)
  • docs/frontend/react-hooks.mdx (1 hunks)
  • packages/core/src/v3/apiClient/index.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/webapp/app/routes/api.v3.runs.$runId.ts
  • packages/core/src/v3/apiClient/index.ts
🧰 Additional context used
🪛 LanguageTool
docs/frontend/overview.mdx

[uncategorized] ~18-~18: Did you mean: “By default,”?
Context: ... so is pretty useless! ``` ### Scopes By default a Public Access Token has no permission...

(BY_DEFAULT_COMMA)

🔇 Additional comments (10)
.changeset/purple-snakes-divide.md (2)

1-4: Verify the semantic versioning impact.

The patch version bumps suggest this is a backwards-compatible enhancement. However, since this modifies access control behavior, we should verify that existing applications won't be impacted negatively.

✅ Verification successful

Based on the search results, I can see that there are significant changes in the access control code, particularly in packages/trigger-sdk/src/v3/auth.ts which shows new functionality for public access tokens with scopes for accessing runs via tags and batches. This aligns with the changeset's purpose. The changes appear to be additive and backwards-compatible, as they're adding new capabilities rather than modifying existing ones.

Patch version bump is appropriate for this enhancement.

The changes add new scoping capabilities to public access tokens while maintaining backward compatibility:

  • New scope options for accessing runs via tags and batches
  • No breaking changes or removals of existing functionality
  • Purely additive feature that enhances access control granularity
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for breaking changes in the codebase
# Look for any removed or renamed functions/methods that might indicate breaking changes

# Search for removed or modified function signatures
rg -g '!{dist,node_modules}/**' -A 2 'export (function|const|class|interface)' 

# Look for potentially breaking changes in types
ast-grep --pattern 'export type $_ = $_'

Length of output: 100202


Script:

#!/bin/bash
# Look for changes in access control related code
rg -g '!{dist,node_modules}/**' -A 5 'scope|access|permission|token' packages/trigger-sdk/src/

# Look for any breaking changes in the SDK
rg -g '!{dist,node_modules}/**' -B 2 'BREAKING CHANGE' packages/trigger-sdk/CHANGELOG.md

# Check for any changes in public API interfaces
ast-grep --pattern 'export interface $_ {
  $$$
}'

Length of output: 112052


Line range hint 6-7: Security review needed for access control changes.

This change broadens access control by allowing tokens with tag/batch scopes to access related runs. While this improves usability, we should verify:

  1. That runs can only be accessed through their associated tags/batches
  2. That there's no potential for privilege escalation
  3. That proper access validation is in place
✅ Verification successful

Let me analyze the access control implementation further by looking specifically at the authorization logic for tags and batches.


Let me analyze the authorization implementation for tags and batches further by looking at the core authorization logic.


Let me check the specific authorization logic for tag and batch access.


Let me try a different approach to find the authorization logic.


Based on the authorization implementation shown in the code, I can now provide a final assessment of the security changes for tag/batch access:

Access control implementation is properly secured for tags and batches

The authorization system implements proper validation for both tag and batch access:

  1. Tags and batches are explicitly defined as valid resource types in ResourceTypes = ["tasks", "tags", "runs", "batch"]
  2. Access is granted only if:
    • The token has a specific permission (e.g., read:tags:tag_123 or read:batch:batch_456)
    • The token has a general permission for the resource type (e.g., read:tags or read:batch)
    • The token has a super scope like read:runs, read:all, or admin
  3. The system validates both individual and array-based resource access
  4. Proper error messages are returned when access is denied
  5. No access is granted if the token has no permissions or invalid scopes

The implementation ensures that runs can only be accessed through their associated tags/batches when the token has the appropriate scopes, with no potential for privilege escalation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify access control implementation
# Look for authorization checks and token validation

# Search for authorization checks
rg -g '!{dist,node_modules}/**' -B 2 -A 5 'authorize|authenticate|isAuthorized|checkAccess'

# Look for token validation logic
rg -g '!{dist,node_modules}/**' -B 2 -A 5 'validateToken|verifyToken|checkToken'

# Search for scope-related code
rg -g '!{dist,node_modules}/**' -B 2 -A 5 'scope|permission|access'

Length of output: 154570


Script:

#!/bin/bash
# Search for tag/batch related authorization checks
rg -g '!{dist,node_modules}/**' -B 5 -A 5 'tags:|batch:|read:tags|read:batch'

# Look for scope validation related to tags/batches
ast-grep --pattern 'if ($expr.includes("read:tags") || $expr.includes("read:batch")) {
  $$$
}'

# Search for tag/batch access validation
rg -g '!{dist,node_modules}/**' -B 5 -A 5 'checkAuthorization.*tags|checkAuthorization.*batch'

Length of output: 127070


Script:

#!/bin/bash
# Search for the core authorization implementation
rg -g '!{dist,node_modules}/**' -B 10 -A 10 'export function checkAuthorization'

# Look for tag/batch scope validation in authorization
ast-grep --pattern 'function checkAuthorization($$$) {
  $$$
  if ($expr.scopes?.includes($scope)) {
    $$$
  }
  $$$
}'

Length of output: 1994


Script:

#!/bin/bash
# Look for the specific resource authorization checks in the authorization service
rg -g '!{dist,node_modules}/**' -B 5 -A 15 'function isAuthorizedForResource|function checkResourceAuthorization' apps/webapp/app/services/authorization.server.ts

# Search for tag/batch specific scope validation
rg -g '!{dist,node_modules}/**' -B 5 -A 15 'read:tags:|read:batch:|tags:|batch:' apps/webapp/app/services/authorization.server.ts

Length of output: 296


Script:

#!/bin/bash
# Search for the authorization implementation in the authorization service file
cat apps/webapp/app/services/authorization.server.ts

# Also look for any test cases related to tag/batch authorization
rg -g '!{dist,node_modules}/**' -B 5 -A 10 'it\(".*tag.*"\)|it\(".*batch.*"\)' apps/webapp/test/authorization.test.ts

Length of output: 4121

apps/webapp/app/routes/realtime.v1.runs.$runId.ts (2)

33-38: LGTM! Well-structured authorization with improved scope access

The authorization configuration successfully implements the enhanced scope access described in the PR objectives. The resource function properly extracts all relevant identifiers (runs, tags, batch, tasks) enabling flexible access control through public tokens.


Line range hint 42-48: Verify streamRun implementation handles the new scope access

The loader implementation is clean and properly utilizes the retrieved run resource. Let's verify that the streamRun function in realtimeClient properly handles the new scope-based access.

✅ Verification successful

Implementation properly handles scope-based access through SQL where clauses

The streamRun implementation correctly handles scope access by:

  • Converting the run ID into a proper SQL where clause (id='${runId}')
  • Using the environment ID in the request to Electric
  • Implementing proper concurrency controls per environment
  • Maintaining backward compatibility with older clients through header rewrites
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for streamRun implementation to verify scope handling
ast-grep --pattern 'streamRun($$$) {
  $$$
}'

# Also check for any tests covering this functionality
rg -l "streamRun.*test" --type ts

Length of output: 83


Script:

#!/bin/bash
# Let's try a broader search for streamRun implementation
rg "streamRun" -A 5 --type ts

# Also search for any realtime client implementation
fd "realtime.*client" --type ts --exec cat {}

Length of output: 7211


Script:

#!/bin/bash
# Let's examine the implementation of #streamRunsWhere which is the core function
cat apps/webapp/app/services/realtimeClient.server.ts

Length of output: 8286

apps/webapp/app/routes/realtime.v1.streams.$runId.$streamId.ts (2)

27-41: Handle null cases in findResource function

The function may return null if no matching taskRun is found, which needs to be handled appropriately downstream.


44-49: LGTM! Authorization scopes properly expanded

The changes align well with the PR objectives, expanding access to runs via tags and batches while maintaining security boundaries.

✅ Verification successful

Based on the search results, I can now generate the final response. The code shows that these properties (runTags, taskIdentifier, and friendlyId) are well-established throughout the codebase, particularly in the TaskRun model and related schemas. The authorization resource function is correctly using these properties.

Properties verified as safe and properly used in authorization context

The properties used in the authorization resource function are valid and secure:

  • friendlyId: Core identifier for runs, used consistently across the codebase
  • runTags: Standard property for run tagging, properly typed as string array
  • taskIdentifier: Well-established property for task identification
  • batch?.friendlyId: Safe optional chaining for batch reference
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify that these properties exist on the TaskRun model
ast-grep --pattern 'model TaskRun {
  $$$
  runTags: $_
  $$$
  taskIdentifier: $_
  $$$
}'

Length of output: 93


Script:

#!/bin/bash
# Let's try to find the model definition using ripgrep
rg "class TaskRun|interface TaskRun|type TaskRun" -A 10

# Also search for property usage to verify their existence
rg "runTags|taskIdentifier|friendlyId" --type typescript

Length of output: 32008


Script:

#!/bin/bash
# Let's search for these properties in TypeScript files
rg "runTags|taskIdentifier|friendlyId" --type ts

# Also search for the TaskRun model/interface definition
rg "interface TaskRun|type TaskRun =|class TaskRun" --type ts -A 5

Length of output: 87796

docs/frontend/overview.mdx (4)

14-14: LGTM! Clear warning about default token behavior.

The comment effectively warns users that a token without scopes is useless, encouraging proper scope configuration.


Line range hint 25-77: LGTM! Well-structured progression of scoping examples.

The examples effectively demonstrate the progression from broad to specific scoping, with clear indicators (❌/✅) of best practices. The new capabilities for tag and batch-based scoping align perfectly with the PR objectives.


Line range hint 79-89: LGTM! Clear demonstration of scope combination.

The example effectively shows how to combine different scope types, enhancing the flexibility of the access control system.


108-119: LGTM! Excellent security recommendation.

The documentation strongly emphasizes the security best practice of using short-lived tokens for write operations, with a clear example of implementation.

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