Conversation
- Refactored role hierarchy to align with Supabase Auth and RLS, simplifying role definitions and inheritance. - Introduced new roles: 'service_role', 'moderator', and updated existing roles to streamline access control. - Revised subscription tiers to include 'free', 'pro', and 'enterprise' with clear inheritance and access levels. - Added RLS policy helpers for better role-based access control. refactor: Enhance tracing configuration - Removed unused imports and cleaned up code formatting for better readability. - Improved error handling and logging in the LangfuseExporter class. feat: Implement AI Gateway configuration - Created a new AI Gateway configuration file to manage API interactions with various AI models. - Added support for multiple AI models from different providers, including OpenAI, Anthropic, Google, and others. - Implemented dynamic model discovery and credit retrieval functions. feat: Add Claude Code provider integration - Introduced a new configuration for Claude Code provider, allowing interaction with Claude models. - Defined model selection functions for easy access to different Claude Code models. feat: Integrate GitHub Copilot provider - Developed a configuration for GitHub Copilot integration, supporting various models. - Added environment variable management for flexible configuration. - Created model selection function for easy access to GitHub Copilot models.
|
Keep this PR in a mergeable state → Learn moreAll Green is an AI agent that automatically: ✅ Addresses code review comments ✅ Fixes failing CI checks ✅ Resolves merge conflicts |
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings. WalkthroughThis PR adds three new AI provider integrations (GitHub Copilot, AI Gateway, Claude Code), refactors existing model configurations into centralized registries with accessor functions, expands documentation with new providers, removes a processors module, updates role hierarchy for Supabase RLS, and adjusts tracing imports with enhanced logging. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Areas requiring extra attention:
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
|
🤖 Hi @ssdeanx, I've received your request, and I'm working on it now! You can track my progress in the logs for more details. |
Summary of ChangesHello @ssdeanx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a substantial expansion of AI model integrations, allowing for a wider array of AI capabilities and providers to be utilized. Concurrently, it overhauls the application's access control system by refactoring the role hierarchy to be Supabase-compatible and defining clear subscription tiers. These changes are supported by comprehensive updates to the configuration documentation and minor improvements to the tracing system, ensuring a more robust, flexible, and well-documented foundation for AI-driven features and user management. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
|
🤖 I'm sorry @ssdeanx, but I was unable to process your request. Please see the logs for more details. |
Greptile OverviewGreptile SummaryThis PR refactors role hierarchy to align with Supabase Auth/RLS patterns and adds three new AI provider integrations (AI Gateway, Claude Code, GitHub Copilot), significantly expanding model access options. Key Changes
Issues Found
Confidence Score: 2/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant App as Application
participant Auth as Supabase Auth
participant RH as Role Hierarchy
participant TC as Tier Config
participant Provider as AI Provider
participant Gateway as AI Gateway
App->>Auth: User authenticates
Auth-->>App: JWT with role metadata
App->>RH: hasRoleAccess(userRole, requiredRole)
RH->>RH: Check ROLE_HIERARCHY inheritance
RH-->>App: Access decision (true/false)
App->>TC: getTierForRole(role)
TC-->>App: SubscriptionTier (free/pro/enterprise)
App->>TC: getTierConfig(tier)
TC->>TC: Lookup TIER_CONFIGS
TC-->>App: TierConfig with features & limits
App->>RH: getRLSPolicyForRole(role)
RH->>TC: getTierForRole(role)
TC-->>RH: tier
RH->>TC: TIER_CONFIGS[tier].rlsPolicy
TC-->>RH: RLS policy string
RH-->>App: Policy for database queries
App->>Provider: Select AI model (OpenAI/Anthropic/Copilot/Claude Code)
Provider-->>App: Model instance
alt Using AI Gateway
App->>Gateway: aiGateway(modelId)
Gateway->>Gateway: Route to provider (OpenAI/Anthropic/Google/xAI/etc)
Gateway-->>App: Unified model interface
end
App->>Provider: Generate response
Provider-->>App: AI response
|
| free: { | ||
| maxDocuments: 500, | ||
| maxApiRequestsPerDay: 50, | ||
| maxUsersPerTenant: 1, | ||
| features: ['basic-rag', 'basic-search', 'public-docs'], | ||
| supportLevel: 'community', | ||
| customIntegrations: false, | ||
| advancedAnalytics: false, | ||
| whiteLabel: false, | ||
| onPremise: false, | ||
| maxRequests: 100, | ||
| features: ['basic-chat', 'public-docs'], | ||
| rlsPolicy: RLS_POLICIES.publicRead, |
There was a problem hiding this comment.
logic: free tier pointing to RLS_POLICIES.publicRead ('anon') is incorrect - free users are authenticated, not anonymous
| free: { | |
| maxDocuments: 500, | |
| maxApiRequestsPerDay: 50, | |
| maxUsersPerTenant: 1, | |
| features: ['basic-rag', 'basic-search', 'public-docs'], | |
| supportLevel: 'community', | |
| customIntegrations: false, | |
| advancedAnalytics: false, | |
| whiteLabel: false, | |
| onPremise: false, | |
| maxRequests: 100, | |
| features: ['basic-chat', 'public-docs'], | |
| rlsPolicy: RLS_POLICIES.publicRead, | |
| free: { | |
| maxRequests: 100, | |
| features: ['basic-chat', 'public-docs'], | |
| rlsPolicy: RLS_POLICIES.userAccess, | |
| }, |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mastra/config/role-hierarchy.ts
Line: 125:128
Comment:
**logic:** `free` tier pointing to `RLS_POLICIES.publicRead` ('anon') is incorrect - free users are authenticated, not anonymous
```suggestion
free: {
maxRequests: 100,
features: ['basic-chat', 'public-docs'],
rlsPolicy: RLS_POLICIES.userAccess,
},
```
How can I resolve this? If you propose a fix, please make it concise.| export function getRLSPolicyForRole(role: string): string { | ||
| const tier = getTierForRole(role) | ||
| return TIER_CONFIGS[tier].rlsPolicy | ||
| } |
There was a problem hiding this comment.
logic: getTierForRole only handles exact matches for 'enterprise', 'pro', 'free' but doesn't handle other roles like 'admin', 'moderator', 'authenticated'
| export function getRLSPolicyForRole(role: string): string { | |
| const tier = getTierForRole(role) | |
| return TIER_CONFIGS[tier].rlsPolicy | |
| } | |
| export function getTierForRole(role: string): SubscriptionTier { | |
| if (role === 'enterprise' || role === 'admin' || role === 'service_role') { | |
| return 'enterprise' | |
| } | |
| if (role === 'pro' || role === 'moderator') { | |
| return 'pro' | |
| } | |
| return 'free' | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mastra/config/role-hierarchy.ts
Line: 176:179
Comment:
**logic:** `getTierForRole` only handles exact matches for 'enterprise', 'pro', 'free' but doesn't handle other roles like 'admin', 'moderator', 'authenticated'
```suggestion
export function getTierForRole(role: string): SubscriptionTier {
if (role === 'enterprise' || role === 'admin' || role === 'service_role') {
return 'enterprise'
}
if (role === 'pro' || role === 'moderator') {
return 'pro'
}
return 'free'
}
```
How can I resolve this? If you propose a fix, please make it concise.| continue: true, | ||
| maxThinkingTokens: 1000, | ||
| additionalDirectories: [], | ||
| cwd: process.env.CLAUDE_CODE_CLI_CWD ?? 'claude', |
There was a problem hiding this comment.
logic: default value 'claude' doesn't make sense for cwd parameter - should be process.cwd()
| cwd: process.env.CLAUDE_CODE_CLI_CWD ?? 'claude', | |
| cwd: process.env.CLAUDE_CODE_CLI_CWD ?? process.cwd(), |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mastra/config/claude-code.ts
Line: 13:13
Comment:
**logic:** default value 'claude' doesn't make sense for `cwd` parameter - should be `process.cwd()`
```suggestion
cwd: process.env.CLAUDE_CODE_CLI_CWD ?? process.cwd(),
```
How can I resolve this? If you propose a fix, please make it concise.| @@ -0,0 +1,70 @@ | |||
| import { createGitHubCopilotOpenAICompatible } from '@opeoginni/github-copilot-openai-compatible'; | |||
| import { logError } from './logger'; | |||
There was a problem hiding this comment.
syntax: logError imported but never used in this file
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mastra/config/github-copilot.ts
Line: 2:2
Comment:
**syntax:** `logError` imported but never used in this file
How can I resolve this? If you propose a fix, please make it concise.| @@ -0,0 +1,82 @@ | |||
| import { createGateway } from '@ai-sdk/gateway' | |||
| import { logError } from './logger' | |||
There was a problem hiding this comment.
syntax: logError imported but never used in this file
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mastra/config/ai-gateway.ts
Line: 2:2
Comment:
**syntax:** `logError` imported but never used in this file
How can I resolve this? If you propose a fix, please make it concise.| // Default model | ||
| export const aiGatewayModel = aiGatewayModels.openaiGpt5 | ||
|
|
||
| export default aiGateway No newline at end of file |
There was a problem hiding this comment.
style: missing newline at end of file
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mastra/config/ai-gateway.ts
Line: 82:82
Comment:
**style:** missing newline at end of file
How can I resolve this? If you propose a fix, please make it concise.| export const claudeCodeSonnet = claudeCodeChatModels.claudeSonnet; | ||
| export const claudeCodeHaiku = claudeCodeChatModels.claudeHaiku; | ||
|
|
||
| export default claudeCodeProvider; |
There was a problem hiding this comment.
style: missing newline at end of file
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mastra/config/claude-code.ts
Line: 39:39
Comment:
**style:** missing newline at end of file
How can I resolve this? If you propose a fix, please make it concise.| } | ||
|
|
||
| // Default model | ||
| export const githubCopilotModel = githubCopilotModels.gpt5; |
There was a problem hiding this comment.
style: missing newline at end of file
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mastra/config/github-copilot.ts
Line: 70:70
Comment:
**style:** missing newline at end of file
How can I resolve this? If you propose a fix, please make it concise.| # OpenRouter Configuration | ||
| OPENROUTER_API_KEY='your_openrouter_api_key_here' | ||
|
|
||
| # AI Ga |
There was a problem hiding this comment.
syntax: incomplete comment "# AI Ga" should be "# AI Gateway Configuration"
| # AI Ga | |
| # AI Gateway Configuration |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .env.example
Line: 23:23
Comment:
**syntax:** incomplete comment "# AI Ga" should be "# AI Gateway Configuration"
```suggestion
# AI Gateway Configuration
```
How can I resolve this? If you propose a fix, please make it concise.| @@ -0,0 +1,39 @@ | |||
| import { createClaudeCode } from 'ai-sdk-provider-claude-code' | |||
| import { logError } from './logger' | |||
There was a problem hiding this comment.
syntax: logError imported but never used
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mastra/config/claude-code.ts
Line: 2:2
Comment:
**syntax:** `logError` imported but never used
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Code Review
This pull request significantly expands and refactors the configuration system, primarily focusing on AI model providers, storage, and authentication. Key changes include the introduction of new AI model providers such as AI Gateway, GitHub Copilot, and Claude Code, along with a comprehensive restructuring of existing Anthropic, Gemini CLI, Google, OpenAI, and OpenRouter model configurations into organized objects with selector functions and backward compatibility. The .env.example file was updated to include the AI_GATEWAY_API_KEY. Documentation files (AGENTS.md and README.md) were extensively updated to reflect these new providers, detail the architecture, directory structure, quick start guides, storage systems, and authentication/authorization using a Supabase-compatible RBAC system. The role-hierarchy.ts file was refactored to simplify role definitions, introduce RLS policies, and update tier configurations. The processors.ts file was removed. Review comments highlighted several areas for improvement: the hasRoleAccess function in role-hierarchy.ts was identified as non-recursive and a corrected BFS-based implementation was suggested; the dotenv.config() call in github-copilot.ts was flagged as an anti-pattern and recommended for removal; the getTierForRole function in role-hierarchy.ts was deemed too simplistic and a more robust implementation based on ROLE_LEVELS was provided; minor issues like a typo in .env.example, trailing whitespace in AGENTS.md, an undefined userRole in a README.md example, a missing newline in ai-gateway.ts, and a suggestion to add braces to a single-line if statement in tracing.ts were also noted.
| export function hasRoleAccess(userRole: string, requiredRole: string): boolean { | ||
| if (userRole === requiredRole) { | ||
| return true | ||
| } | ||
|
|
||
| if (!(userRole in ROLE_HIERARCHY)) { | ||
| return false | ||
| } | ||
|
|
||
| const inheritedRoles = ROLE_HIERARCHY[userRole] | ||
| return inheritedRoles.includes(requiredRole) | ||
| } |
There was a problem hiding this comment.
The hasRoleAccess function is not recursive and will fail to check inherited permissions correctly. For example, hasRoleAccess('service_role', 'moderator') would incorrectly return false because 'moderator' is inherited by 'admin', which is in turn inherited by 'service_role'. The check needs to traverse the entire inheritance chain.
The suggested implementation uses a breadth-first search to correctly and safely traverse the role hierarchy, preventing potential infinite loops if cycles were ever introduced.
export function hasRoleAccess(userRole: string, requiredRole: string): boolean {
if (userRole === requiredRole) {
return true;
}
const queue: string[] = [userRole];
const visited = new Set<string>([userRole]);
while (queue.length > 0) {
const currentRole = queue.shift()!;
const inheritedRoles = ROLE_HIERARCHY[currentRole] || [];
for (const inheritedRole of inheritedRoles) {
if (inheritedRole === requiredRole) {
return true;
}
if (!visited.has(inheritedRole)) {
visited.add(inheritedRole);
queue.push(inheritedRole);
}
}
}
return false;
}| // Load environment variables | ||
| dotenv.config(); |
There was a problem hiding this comment.
Calling dotenv.config() inside a library module is an anti-pattern. It creates side effects, making the module less reusable and harder to test. Environment variables should be loaded once at the application's entry point, not within individual modules. Please remove these lines and the corresponding dotenv import on line 3.
| export function getTierForRole(role: string): SubscriptionTier { | ||
| if (role === 'public') { | ||
| return 'free' | ||
| } | ||
| if (role === 'free_user') { | ||
| return 'free' | ||
| if (role === 'enterprise') { | ||
| return 'enterprise' | ||
| } | ||
| if (role.startsWith('pro_') || role === 'employee' || role === 'reader') { | ||
| if (role === 'pro') { | ||
| return 'pro' | ||
| } | ||
| if (role.startsWith('enterprise_') || role === 'admin' || role.endsWith('.admin') || role.endsWith('.viewer')) { | ||
| return 'enterprise' | ||
| if (role === 'free') { | ||
| return 'free' | ||
| } | ||
| return 'free' | ||
| } |
There was a problem hiding this comment.
The getTierForRole function is too simplistic. It only handles the exact roles 'enterprise', 'pro', and 'free', incorrectly defaulting all other roles like 'admin' or 'moderator' to the 'free' tier. This is likely incorrect, as higher-privilege roles should map to higher subscription tiers. A more robust implementation should consider the role's privilege level defined in ROLE_LEVELS.
export function getTierForRole(role: string): SubscriptionTier {
const level = getRoleLevel(role);
// Check from highest tier to lowest
if (level >= ROLE_LEVELS.enterprise) {
return 'enterprise';
}
if (level >= ROLE_LEVELS.pro) {
return 'pro';
}
// Default to free for any other valid role
return 'free';
}| # OpenRouter Configuration | ||
| OPENROUTER_API_KEY='your_openrouter_api_key_here' | ||
|
|
||
| # AI Ga |
| | `upstash.ts` | Upstash Redis configuration | Caching and session storage | | ||
| | `upstashMemory.ts` | Upstash Redis memory configuration | Alternative memory provider | | ||
| | `logger.ts` | Structured logging (Pino) | Standard log helpers & transports | | ||
| | `tracing.ts` | Distributed tracing configuration | Performance monitoring and debugging | |
There was a problem hiding this comment.
This line, and several others in the markdown tables, have trailing whitespace. This can affect the readability of the raw markdown and create noisy diffs in the future. Please remove the trailing spaces from all affected lines in this file (e.g., lines 31, 33, 48, 49, 51, 52, and throughout the 'Model Providers' table).
|
|
||
| // Role-based access control | ||
| import { hasRoleAccess } from './role-hierarchy' | ||
| if (hasRoleAccess(userRole, 'admin')) { |
There was a problem hiding this comment.
The example code here references userRole, but it's not defined in the snippet. This could be confusing for users trying to copy and paste the example. Please define it to make the example self-contained and runnable.
| if (hasRoleAccess(userRole, 'admin')) { | |
| const userRole = 'admin'; // Example user role | |
| if (hasRoleAccess(userRole, 'admin')) { |
| // Default model | ||
| export const aiGatewayModel = aiGatewayModels.openaiGpt5 | ||
|
|
||
| export default aiGateway No newline at end of file |
| // @ts-expect-error - traceMap is protected in base class but we need to check it | ||
| const traceMap = this.traceMap as Map<string, unknown> | undefined | ||
| if (!traceMap || !span.traceId) return | ||
| if (!traceMap || !span.traceId) {return} |
There was a problem hiding this comment.
While functionally correct, adding braces to a single-line if statement can improve readability and prevent potential issues if more logic is added to the block later. It's a good practice for consistency and maintainability.
| if (!traceMap || !span.traceId) {return} | |
| if (!traceMap || !span.traceId) return |
There was a problem hiding this comment.
Actionable comments posted: 27
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
src/mastra/config/openrouter.ts (2)
2-2: Unused import:logErroris imported but never used.Remove the unused import to keep the code clean.
import { createOpenRouter } from '@openrouter/ai-sdk-provider' -import { logError } from './logger'
319-344: Duplicate model definitions detected.
openQwenAI,openGLMAI, andopenAIFreeare duplicates of entries inopenRouterModels(lines 109, 280, 190). Consider aliasing from the registry instead.-export const openQwenAI = openrouter('qwen/qwen3-coder:free', { - includeReasoning: true, - extraBody: { - reasoning: { max_tokens: 20000 }, - stream: true, - }, - usage: { include: true }, -}) - -export const openGLMAI = openrouter('z-ai/glm-4.5-air:free', { - includeReasoning: true, - extraBody: { - reasoning: { max_tokens: 20000 }, - stream: true, - }, - usage: { include: true }, -}) - -export const openAIFree = openrouter('openai/gpt-oss-20b:free', { - includeReasoning: true, - extraBody: { - reasoning: { max_tokens: 20000 }, - stream: true, - }, - usage: { include: true }, -}) +// Backward compatibility exports +export const openQwenAI = openRouterModels.qwenQwen3CoderFree; +export const openGLMAI = openRouterModels.zAiGlm45AirFree; +export const openAIFree = openRouterModels.openaiGptOss20bFree;src/mastra/config/tracing.ts (1)
341-356: Mask sensitive span data before logginginput,output, anderrorInfofields.The
SensitiveDataFilterdoesn't protect these fields at the exporter level. UsemaskSensitiveMessageData()fromsrc/mastra/config/pg-storage.tsto maskspan.input,span.output, andspan.errorInfobefore logging them at lines 352-355, since these may contain PII, API keys, or other secrets depending on the span's contents.src/mastra/config/gemini-cli.ts (1)
6-13: Avoid using API‑key auth in production whenGOOGLE_GENERATIVE_AI_API_KEYis missing
useApiKeybecomestruein production even ifGOOGLE_GENERATIVE_AI_API_KEYis unset, which results in:apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY ?? ''An empty string here will likely cause confusing runtime errors from the provider.
Consider tightening this logic so that in production you either:
- Require the env var and throw/log a clear error if it’s missing, or
- Fall back to OAuth only when you explicitly allow that in prod.
For example:
const hasApiKey = !!process.env.GOOGLE_GENERATIVE_AI_API_KEY; const isProd = process.env.NODE_ENV === 'production'; if (isProd && !hasApiKey) { // logError('GOOGLE_GENERATIVE_AI_API_KEY is required in production'); throw new Error('GOOGLE_GENERATIVE_AI_API_KEY is required in production'); } const useApiKey = hasApiKey || isProd;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (18)
.agent/rules/conventions.md(0 hunks).env.example(1 hunks)app/chat/config/openrouter-models.ts(1 hunks)package.json(2 hunks)src/mastra/config/AGENTS.md(3 hunks)src/mastra/config/README.md(1 hunks)src/mastra/config/ai-gateway.ts(1 hunks)src/mastra/config/anthropic.ts(1 hunks)src/mastra/config/claude-code.ts(1 hunks)src/mastra/config/gemini-cli.ts(5 hunks)src/mastra/config/github-copilot.ts(1 hunks)src/mastra/config/google.ts(1 hunks)src/mastra/config/index.ts(1 hunks)src/mastra/config/openai.ts(2 hunks)src/mastra/config/openrouter.ts(1 hunks)src/mastra/config/processors.ts(0 hunks)src/mastra/config/role-hierarchy.ts(3 hunks)src/mastra/config/tracing.ts(16 hunks)
💤 Files with no reviewable changes (2)
- .agent/rules/conventions.md
- src/mastra/config/processors.ts
🧰 Additional context used
📓 Path-based instructions (23)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)
**/*.{js,jsx,ts,tsx}: Usenext/dynamicfor dynamic imports to load components only when needed, improving initial load time.
Usenext/imagecomponent for automatic image optimization, including lazy loading and responsive images.
Use React.memo to prevent unnecessary re-renders of components.
Use the<Link prefetch>tag to prefetch pages that are likely to be visited.
Use getServerSideProps, getStaticProps, or server components for fetching data on the server-side.
Use SWR or React Query for client-side data fetching and caching.
Use CSS Modules, Styled Components, or Tailwind CSS for component-level styling. Prefer Tailwind CSS for rapid development.
Use React Context, Zustand, Jotai, or Recoil for managing global state. Avoid Redux unless necessary.
Usereact-hook-formfor managing forms and validation.
Only fetch the data that is needed by the component to avoid over-fetching.
Avoid long-running synchronous operations in the main thread to prevent blocking.
Always usesetStateor hooks to update state instead of mutating state directly.
Include a complete dependency array inuseEffecthooks to prevent unexpected behavior.
Avoid writing server-side code in client components to prevent exposing secrets or causing unexpected behavior.
Usetry...catchblocks for handling errors in asynchronous operations.
Implement error boundary components usinggetDerivedStateFromErrororcomponentDidCatchlifecycle methods.
Sanitize user input to prevent Cross-Site Scripting (XSS) attacks. Be especially careful when rendering HTML directly from user input.
Store authentication tokens in HTTP-only cookies or local storage securely.
Implement role-based access control to restrict access to sensitive resources.
Clean up event listeners and timers inuseEffecthooks to avoid memory leaks.
Only update state when necessary to reduce the number of re-renders and improve performance.
Use immutable data structures and avoid mutating data directly to prevent unexpected...
Files:
src/mastra/config/github-copilot.tssrc/mastra/config/ai-gateway.tsapp/chat/config/openrouter-models.tssrc/mastra/config/anthropic.tssrc/mastra/config/index.tssrc/mastra/config/openai.tssrc/mastra/config/claude-code.tssrc/mastra/config/openrouter.tssrc/mastra/config/gemini-cli.tssrc/mastra/config/tracing.tssrc/mastra/config/role-hierarchy.tssrc/mastra/config/google.ts
**/*.{js,ts}
📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)
Use parameterized queries or an ORM to prevent SQL injection attacks.
Files:
src/mastra/config/github-copilot.tssrc/mastra/config/ai-gateway.tsapp/chat/config/openrouter-models.tssrc/mastra/config/anthropic.tssrc/mastra/config/index.tssrc/mastra/config/openai.tssrc/mastra/config/claude-code.tssrc/mastra/config/openrouter.tssrc/mastra/config/gemini-cli.tssrc/mastra/config/tracing.tssrc/mastra/config/role-hierarchy.tssrc/mastra/config/google.ts
src/mastra/config/**/*.ts
📄 CodeRabbit inference engine (src/mastra/config/AGENTS.md)
All external service initialization in the config directory must be environment-driven, with sensitive credentials loaded from environment variables and never hardcoded
src/mastra/config/**/*.ts: Centralize provider clients (Google, OpenAI, Anthropic, OpenRouter) and storage configuration in src/mastra/config
Use pg-storage with PgVector for vector store functionality in the configuration
Use src/mastra/config for role hierarchy and provider client configuration
Files:
src/mastra/config/github-copilot.tssrc/mastra/config/ai-gateway.tssrc/mastra/config/anthropic.tssrc/mastra/config/index.tssrc/mastra/config/openai.tssrc/mastra/config/claude-code.tssrc/mastra/config/openrouter.tssrc/mastra/config/gemini-cli.tssrc/mastra/config/tracing.tssrc/mastra/config/role-hierarchy.tssrc/mastra/config/google.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never commit API keys or secrets to the repository; use maskSensitiveMessageData() helper from src/mastra/config/pg-storage.ts when logging
**/*.{ts,tsx}: Document interface and type definitions with TSDoc comments explaining their purpose and usage context
Document interface properties with /** */ comments explaining each field's purpose and constraints
Document generic type parameters with @template tags explaining what each type parameter represents
Use type guards with comments explaining the runtime validation logic being performed
Document advanced/complex TypeScript types with explanatory comments about their purpose and use cases
Files:
src/mastra/config/github-copilot.tssrc/mastra/config/ai-gateway.tsapp/chat/config/openrouter-models.tssrc/mastra/config/anthropic.tssrc/mastra/config/index.tssrc/mastra/config/openai.tssrc/mastra/config/claude-code.tssrc/mastra/config/openrouter.tssrc/mastra/config/gemini-cli.tssrc/mastra/config/tracing.tssrc/mastra/config/role-hierarchy.tssrc/mastra/config/google.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Run eslint with --max-warnings=0 on src/**/*.{ts,tsx} to enforce linting standards
Files:
src/mastra/config/github-copilot.tssrc/mastra/config/ai-gateway.tssrc/mastra/config/anthropic.tssrc/mastra/config/index.tssrc/mastra/config/openai.tssrc/mastra/config/claude-code.tssrc/mastra/config/openrouter.tssrc/mastra/config/gemini-cli.tssrc/mastra/config/tracing.tssrc/mastra/config/role-hierarchy.tssrc/mastra/config/google.ts
**/*.{ts,tsx,js,jsx,py,java,cs,rb,go,rs,cpp,c,h,hpp,swift,kotlin,php,scala,clj,groovy,lua,sh,bash}
📄 CodeRabbit inference engine (.github/instructions/self-explanatory-code-commenting.instructions.md)
**/*.{ts,tsx,js,jsx,py,java,cs,rb,go,rs,cpp,c,h,hpp,swift,kotlin,php,scala,clj,groovy,lua,sh,bash}: Write code that speaks for itself. Comment only when necessary to explain WHY, not WHAT. Avoid obvious comments that state what the code literally does.
Avoid redundant comments that simply repeat what the code is doing
Keep comments accurate and up-to-date with code changes. Remove or update outdated comments that no longer match the implementation.
Write comments for complex business logic that explain the WHY behind specific calculations or business rules
Document non-obvious algorithms with comments explaining the algorithm choice and its reasoning
Add comments explaining what regex patterns match, especially for complex patterns
Document API constraints, rate limits, gotchas, and external dependencies with explanatory comments
Avoid commenting out dead code. Use version control instead of maintaining commented code blocks.
Do not maintain code change history or modification logs as comments. Rely on git history and commit messages instead.
Avoid decorative divider comments (e.g., lines of equals signs or asterisks) for section separation
Ensure comments are placed appropriately above or adjacent to the code they describe
Write comments using proper grammar, spelling, and professional language
Prefer self-documenting code with clear variable/function names over adding comments to explain unclear code
Files:
src/mastra/config/github-copilot.tssrc/mastra/config/ai-gateway.tsapp/chat/config/openrouter-models.tssrc/mastra/config/anthropic.tssrc/mastra/config/index.tssrc/mastra/config/openai.tssrc/mastra/config/claude-code.tssrc/mastra/config/openrouter.tssrc/mastra/config/gemini-cli.tssrc/mastra/config/tracing.tssrc/mastra/config/role-hierarchy.tssrc/mastra/config/google.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/instructions/self-explanatory-code-commenting.instructions.md)
**/*.{ts,tsx,js,jsx}: Document public APIs with TSDoc/JSDoc comments including parameter descriptions, return types, examples, and thrown exceptions
Add TSDoc comments to configuration constants and environment variables explaining their source, reasoning, or constraints
Use TSDoc annotation tags (TODO, FIXME, HACK, NOTE, WARNING, PERF, SECURITY, BUG, REFACTOR, DEPRECATED) to mark special comments
Include file headers with @fileoverview, @author, @copyright, and @license tags to document file purpose and ownership
Document function parameters with @param tags, return values with @returns tags, and exceptions with @throws tags in TSDoc comments
Use @see tags in TSDoc comments to reference related functions, methods, or documentation
Include @example tags in public API documentation with code examples showing typical usage
Files:
src/mastra/config/github-copilot.tssrc/mastra/config/ai-gateway.tsapp/chat/config/openrouter-models.tssrc/mastra/config/anthropic.tssrc/mastra/config/index.tssrc/mastra/config/openai.tssrc/mastra/config/claude-code.tssrc/mastra/config/openrouter.tssrc/mastra/config/gemini-cli.tssrc/mastra/config/tracing.tssrc/mastra/config/role-hierarchy.tssrc/mastra/config/google.ts
**/.env*
📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)
Use environment variables to store configuration values in the application.
Files:
.env.example
.env*
📄 CodeRabbit inference engine (AGENTS.md)
.env*: Use .env file locally for environment variables and secure env variables in CI/CD systems like GitHub Actions Secrets
Configure minimum required environment variables: SUPABASE/DATABASE_URL, GOOGLE_GENERATIVE_AI_API_KEY, and optional provider keys (OPENAI_API_KEY, ANTHROPIC_API_KEY, OPENROUTER_API_KEY) for local development
Files:
.env.example
**/app/**
📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)
Use the
app/directory structure for route handlers, server components, and client components (Next.js 13+). Prefer this over thepages/directory for new projects.
Files:
app/chat/config/openrouter-models.ts
app/**/*.{tsx,ts}
📄 CodeRabbit inference engine (app/AGENTS.md)
app/**/*.{tsx,ts}: Use Tailwind CSS 4 with oklch color variables for styling in Next.js App Router pages and layouts
Use React 19 latest features in component implementations within the app directory
Files:
app/chat/config/openrouter-models.ts
app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Next.js 16 App Router with React 19 for frontend development in the app/ directory
Files:
app/chat/config/openrouter-models.ts
{app,ui,src/components}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Tailwind CSS 4 with oklch color variables for styling in UI components
Files:
app/chat/config/openrouter-models.ts
{app,src/components}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
{app,src/components}/**/*.{ts,tsx}: Use shadcn/ui base components (34 components) located in ui/ directory for common UI elements
Use AI Elements library (30 components) from src/components/ai-elements/ for chat, reasoning, and canvas UIs
Files:
app/chat/config/openrouter-models.ts
**/*.md
📄 CodeRabbit inference engine (.github/instructions/markdown.instructions.md)
**/*.md: Use appropriate heading levels (H2, H3, etc.) to structure markdown content. Do not use H1 headings, as these will be generated from the title. Use##for H2 and###for H3 in a hierarchical manner. Recommend restructuring if content includes H4 or higher levels.
Use bullet points (with-) or numbered lists (with1.) for lists in markdown. Indent nested lists with two spaces and ensure proper indentation and spacing.
Use fenced code blocks (triple backticks) for code snippets in markdown. Specify the language after the opening backticks for syntax highlighting (e.g.,csharp).
Use proper markdown syntax for links:[link text](URL). Ensure that link text is descriptive and URLs are valid and accessible.
Use proper markdown syntax for images:. Include a brief description of the image in the alt text for accessibility.
Use markdown tables (with|delimiters) for tabular data. Ensure proper formatting, alignment, and inclusion of headers.
Limit line length to 80 characters in markdown for readability. Use soft line breaks for long paragraphs.
Use appropriate whitespace in markdown to separate sections and improve readability. Use blank lines between sections and avoid excessive whitespace.
Include YAML front matter at the beginning of markdown files with required metadata fields:post_title,author1,post_slug,microsoft_alias,featured_image,categories(from /categories.txt),tags,ai_note,summary, andpost_date.
Files:
src/mastra/config/README.mdsrc/mastra/config/AGENTS.md
src/mastra/config/anthropic.ts
📄 CodeRabbit inference engine (src/mastra/config/AGENTS.md)
Anthropic model provider configuration in
anthropic.tsshould support Claude 3.5 Sonnet, Opus, and Haiku models with API key fromANTHROPIC_API_KEYenvironment variable
Files:
src/mastra/config/anthropic.ts
src/mastra/config/index.ts
📄 CodeRabbit inference engine (src/mastra/config/AGENTS.md)
Index file (
index.ts) in/src/mastra/configshould aggregate and export all provider configuration modules
Files:
src/mastra/config/index.ts
src/mastra/config/AGENTS.md
📄 CodeRabbit inference engine (src/mastra/AGENTS.md)
When adding new tools or providers, add env var placeholders to
.envand document them insrc/mastra/config/AGENTS.md
Files:
src/mastra/config/AGENTS.md
src/mastra/config/openai.ts
📄 CodeRabbit inference engine (src/mastra/config/AGENTS.md)
OpenAI model provider configuration in
openai.tsshould support GPT-4, GPT-4o, and GPT-3.5 models with API key fromOPENAI_API_KEYenvironment variable
Files:
src/mastra/config/openai.ts
src/mastra/config/openrouter.ts
📄 CodeRabbit inference engine (src/mastra/config/AGENTS.md)
OpenRouter model provider configuration in
openrouter.tsshould enable routing to multiple models viaOPENROUTER_API_KEYenvironment variable
Files:
src/mastra/config/openrouter.ts
src/mastra/config/gemini-cli.ts
📄 CodeRabbit inference engine (src/mastra/config/AGENTS.md)
Gemini CLI provider configuration in
gemini-cli.tsshould support local development and testing scenarios
Files:
src/mastra/config/gemini-cli.ts
src/mastra/config/role-hierarchy.ts
📄 CodeRabbit inference engine (src/mastra/config/AGENTS.md)
Role-based access control (RBAC) inheritance model in
role-hierarchy.tsshould drive policy decisions and access filters
Files:
src/mastra/config/role-hierarchy.ts
src/mastra/config/google.ts
📄 CodeRabbit inference engine (src/mastra/config/AGENTS.md)
Google AI model provider configuration in
google.tsshould support Gemini 2.5 Flash, Pro, and Flash Lite models with API key fromGOOGLE_GENERATIVE_AI_API_KEYenvironment variable
Files:
src/mastra/config/google.ts
🧬 Code graph analysis (2)
src/mastra/config/ai-gateway.ts (1)
src/mastra/config/logger.ts (1)
logError(153-174)
src/mastra/config/tracing.ts (1)
lib/types/mastra-api.ts (1)
AISpanType(177-184)
🪛 dotenv-linter (4.0.0)
.env.example
[warning] 24-24: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Agent
- GitHub Check: Codacy Security Scan
🔇 Additional comments (12)
src/mastra/config/README.md (2)
1-370: Documentation is comprehensive and well-structured.The README provides thorough coverage of the configuration system including architecture, usage examples, environment variables, and development guidelines. The modular organization with clear sections for providers, storage, and auth aligns well with the codebase structure.
41-44: Remove non-existentprocessors.tsreference from Infrastructure section.The directory structure at line 44 references
processors.ts, but this file does not exist in the codebase. Either remove this line or replace it with an actual file that exists in the Infrastructure module.Likely an incorrect or invalid review comment.
src/mastra/config/index.ts (1)
13-16: LGTM!The new barrel exports for
github-copilot,gemini-cli,ai-gateway, andclaude-codefollow the established pattern and align with the coding guidelines for aggregating provider configuration modules in the index file.src/mastra/config/anthropic.ts (2)
25-28: LGTM!The selector function follows the established pattern for model access, providing type-safe model selection via
keyof typeof anthropicChatModels.
30-33: Backward compatibility exports are well-documented.The comments clarify the mapping for each alias, which helps maintainability.
src/mastra/config/openai.ts (2)
59-62: LGTM!The selector function provides type-safe model selection consistent with the pattern used across other provider configurations.
36-57: > Likely an incorrect or invalid review comment.package.json (2)
79-79: @opeoginni/github-copilot-openai-compatible is in early development stage (v0.1.21) — verify production readiness.The package exists on npm and was recently updated (November 2025), but the pre-release version number (0.1.x) indicates early-stage software. Confirm this dependency is suitable for production use and consider the maintenance risk of a single-maintainer package.
97-97: No action needed onai-sdk-provider-claude-codepackage.The package is actively maintained with the latest update on 2025-12-05. Version 2.2.4 specified in package.json is the current latest release, and the package has a dedicated maintainer.
src/mastra/config/tracing.ts (2)
62-63: LGTM: Import formatting improvement.Moving
BaseAISpanto the type import block is a minor formatting cleanup with no functional impact.
370-512: LGTM: Expanded span attribute logging for observability.The enhanced logging for different
AISpanTypecases (AgentRun, ModelGeneration, ToolCall, WorkflowRun, etc.) improves debugging and aligns with the broader observability patterns in the PR.src/mastra/config/google.ts (1)
42-102: Google provider registry + selectors look consistent and env‑drivenThe new
googleChatModels/googleImageModels/googleEmbeddingModelsregistries, along withgetGoogle*Modelhelpers and default model aliases, form a coherent, centralized config surface. Initialization viacreateGoogleGenerativeAI({ apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY })satisfies the env-driven requirement and avoids hardcoded credentials.No issues from a correctness or configuration perspective in this section.
| # AI Ga | ||
| AI_GATEWAY_API_KEY='your_api_key_here' |
There was a problem hiding this comment.
Fix truncated comment.
The comment on line 23 is incomplete (# AI Ga). This should likely read # AI Gateway or similar to describe the environment variable.
-# AI Ga
+# AI Gateway Configuration
AI_GATEWAY_API_KEY='your_api_key_here'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # AI Ga | |
| AI_GATEWAY_API_KEY='your_api_key_here' | |
| # AI Gateway Configuration | |
| AI_GATEWAY_API_KEY='your_api_key_here' |
🧰 Tools
🪛 dotenv-linter (4.0.0)
[warning] 24-24: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
🤖 Prompt for AI Agents
In .env.example around lines 23 to 24, the inline comment for the AI gateway API
key is truncated ("# AI Ga"); replace it with a complete descriptive comment
such as "# AI Gateway" (or "# AI Gateway API key") so the environment variable
is clearly documented, ensuring punctuation and capitalization are consistent
with other comments in the file.
| { | ||
| id: "openrouter/openai/gpt-oss-20b:free", | ||
| name: "GPT OSS 20B (Free)", | ||
| provider: "openrouter", | ||
| contextWindow: 8000, | ||
| capabilities: ["chat", "code"], | ||
| description: "Open-source GPT via OR", | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
OpenRouter gpt-oss-20b free model
💡 Result:
Yes — gpt-oss-20b is an OpenAI open‑weight model (Apache‑2.0) and is available to run locally or via third‑party hosts (including OpenRouter). Key facts and how to access:
- What it is: gpt-oss-20b is a 21B‑parameter, Mixture‑of‑Experts model released by OpenAI (Apache‑2.0, full chain‑of‑thought, 131k context). [1][2]
- Official downloads / repo: weights, reference code, and instructions are on OpenAI's repo and Hugging Face. [2][3]
- Third‑party hosting (OpenRouter and others): many providers (including OpenRouter/third‑party APIs) offer hosted endpoints for gpt-oss-20b; some expose a “free” model variant or low‑cost access keys (model IDs you’ll see include names like openrouter/gpt-oss-20b or openai/gpt-oss-20b:free depending on provider). Check the provider’s docs for exact model ID, rate limits, and pricing. [4][5]
- Quick next steps: (1) pick a host (OpenRouter, Hugging Face Inference, Ollama, etc.), (2) read their model listing for the exact model ID and quota, (3) call the host’s API with that model ID (or download weights to run locally if you have suitable hardware). [1][3][4]
Sources: OpenAI introducing gpt‑oss (model details & availability) [1]; OpenAI GitHub model repo (README + download instructions) [2]; examples of third‑party hosted/free listings (provider docs / libraries) [4][5].
Fix incorrect context window for gpt-oss-20b model.
The context window is set to 8000 tokens, but gpt-oss-20b is a 21B-parameter open-weight model with a 131k context window. Update line 299 to reflect the correct context window value.
🤖 Prompt for AI Agents
In app/chat/config/openrouter-models.ts around lines 296 to 303, the gpt-oss-20b
model's contextWindow is incorrectly set to 8000; change the contextWindow value
on line 299 to the correct 131000 (131k) to reflect the model's actual
~131k-token context window.
| @@ -1,4 +1,4 @@ | |||
| <!-- AGENTS-META {"title":"Mastra Config","version":"2.0.0","last_updated":"2025-11-26T00:00:00Z","applies_to":"/src/mastra/config","tags":["layer:backend","domain:infra","type:config","status":"stable"],"status":"stable"} --> | |||
| <!-- AGENTS-META {"title":"Mastra Config","version":"2.2.1","last_updated":"2025-12-08T00:00:00Z","applies_to":"/src/mastra/config","tags":["layer:backend","domain:infra","type:config","status":"stable"],"status":"stable"} --> | |||
There was a problem hiding this comment.
Align AGENTS-META version with Change Log entries
The metadata header declares version 2.2.1, but the Change Log introduces 2.3.0 as the latest entry. Consider bumping the AGENTS-META version field to 2.3.0 (or whatever is intended as the current doc version) to avoid confusion about which version the page represents.
Also applies to: 145-150
🤖 Prompt for AI Agents
In src/mastra/config/AGENTS.md lines 1-1 and 145-150, the AGENTS-META header
still lists version "2.2.1" while the Change Log shows "2.3.0"; update the
metadata version field (and any other AGENTS-META occurrences at lines 145-150)
to "2.3.0" (or the intended current doc version) so the header matches the
Change Log and avoids confusion.
| ### Supported Supabase Roles | ||
|
|
||
| - `anon` - Public/unauthenticated access | ||
| - `authenticated` - Logged-in users | ||
| - `admin` - Administrative access | ||
| - `service_role` - Backend service operations | ||
| - Subscription tiers: `free`, `pro`, `enterprise` | ||
|
|
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Keep documented Supabase roles in sync with role-hierarchy.ts
The “Supported Supabase Roles” list documents anon, authenticated, admin, and service_role, plus subscription tiers. The RBAC config in role-hierarchy.ts also introduces a moderator role and treats free, pro, and enterprise as role-like entries.
It would be helpful to either:
- Add
moderatorto this list (and clarify it’s app-level but RLS-relevant), or - Explicitly distinguish Supabase core roles from app roles and subscription tiers.
This keeps RLS policy docs aligned with the actual hierarchy.
🤖 Prompt for AI Agents
In src/mastra/config/AGENTS.md around lines 76 to 83, the documented “Supported
Supabase Roles” list is out of sync with role-hierarchy.ts which includes a
moderator role and treats subscription tiers as role-like entries; update this
section to either add `moderator` (noting it is an app-level role that impacts
RLS) or split the list into two clearly labeled groups — “Supabase core roles”
(`anon`, `authenticated`, `service_role`, `admin`) and “App-level roles /
subscription tiers” (`moderator`, `free`, `pro`, `enterprise`) — so the docs
match the RBAC config and clarify intent.
| export const aiGatewayConfig = { | ||
| apiKey: process.env.AI_GATEWAY_API_KEY ?? '', | ||
| baseURL: process.env.AI_GATEWAY_BASE_URL ?? 'https://ai-gateway.vercel.sh/v1/ai', | ||
| metadataCacheRefreshMillis: parseInt(process.env.AI_GATEWAY_CACHE_REFRESH ?? '300000'), // 5 minutes | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Add validation or warning for missing API key.
An empty apiKey will silently pass initialization but cause runtime API failures. Consider logging a warning when the key is missing. As per coding guidelines, add TSDoc documenting the environment variables.
+/**
+ * AI Gateway configuration loaded from environment variables.
+ * @property apiKey - AI_GATEWAY_API_KEY environment variable (required for API calls)
+ * @property baseURL - AI_GATEWAY_BASE_URL environment variable
+ * @property metadataCacheRefreshMillis - AI_GATEWAY_CACHE_REFRESH parsed as integer (default: 5 minutes)
+ */
export const aiGatewayConfig = {
apiKey: process.env.AI_GATEWAY_API_KEY ?? '',
baseURL: process.env.AI_GATEWAY_BASE_URL ?? 'https://ai-gateway.vercel.sh/v1/ai',
metadataCacheRefreshMillis: parseInt(process.env.AI_GATEWAY_CACHE_REFRESH ?? '300000'), // 5 minutes
}
+
+if (!aiGatewayConfig.apiKey) {
+ console.warn('[ai-gateway] AI_GATEWAY_API_KEY is not set. API calls will fail.');
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const aiGatewayConfig = { | |
| apiKey: process.env.AI_GATEWAY_API_KEY ?? '', | |
| baseURL: process.env.AI_GATEWAY_BASE_URL ?? 'https://ai-gateway.vercel.sh/v1/ai', | |
| metadataCacheRefreshMillis: parseInt(process.env.AI_GATEWAY_CACHE_REFRESH ?? '300000'), // 5 minutes | |
| } | |
| /** | |
| * AI Gateway configuration loaded from environment variables. | |
| * @property apiKey - AI_GATEWAY_API_KEY environment variable (required for API calls) | |
| * @property baseURL - AI_GATEWAY_BASE_URL environment variable | |
| * @property metadataCacheRefreshMillis - AI_GATEWAY_CACHE_REFRESH parsed as integer (default: 5 minutes) | |
| */ | |
| export const aiGatewayConfig = { | |
| apiKey: process.env.AI_GATEWAY_API_KEY ?? '', | |
| baseURL: process.env.AI_GATEWAY_BASE_URL ?? 'https://ai-gateway.vercel.sh/v1/ai', | |
| metadataCacheRefreshMillis: parseInt(process.env.AI_GATEWAY_CACHE_REFRESH ?? '300000'), // 5 minutes | |
| } | |
| if (!aiGatewayConfig.apiKey) { | |
| console.warn('[ai-gateway] AI_GATEWAY_API_KEY is not set. API calls will fail.'); | |
| } |
🤖 Prompt for AI Agents
In src/mastra/config/ai-gateway.ts around lines 5 to 9, the aiGatewayConfig
allows an empty apiKey which will cause runtime failures; add a runtime check
that logs a warning (using the app logger or console.warn if no logger) when
process.env.AI_GATEWAY_API_KEY is missing or empty, and keep the existing
default for baseURL and parsed cache refresh; also add TSDoc above the exported
aiGatewayConfig describing the expected environment variables
(AI_GATEWAY_API_KEY, AI_GATEWAY_BASE_URL, AI_GATEWAY_CACHE_REFRESH) and their
defaults/types so callers and maintainers understand required configuration.
| // Model selector function | ||
| export function getOpenRouterModel(modelId: keyof typeof openRouterModels) { | ||
| return openRouterModels[modelId]; | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Add TSDoc comment documenting the function.
As per coding guidelines, public API functions should include TSDoc with @param and @returns tags.
-// Model selector function
+/**
+ * Retrieves an OpenRouter model instance by its identifier.
+ * @param modelId - The key of the model in the openRouterModels registry
+ * @returns The configured OpenRouter model instance
+ * @example
+ * const model = getOpenRouterModel('anthropicClaudeSonnet45');
+ */
export function getOpenRouterModel(modelId: keyof typeof openRouterModels) {
return openRouterModels[modelId];
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Model selector function | |
| export function getOpenRouterModel(modelId: keyof typeof openRouterModels) { | |
| return openRouterModels[modelId]; | |
| } | |
| /** | |
| * Retrieves an OpenRouter model instance by its identifier. | |
| * @param modelId - The key of the model in the openRouterModels registry | |
| * @returns The configured OpenRouter model instance | |
| * @example | |
| * const model = getOpenRouterModel('anthropicClaudeSonnet45'); | |
| */ | |
| export function getOpenRouterModel(modelId: keyof typeof openRouterModels) { | |
| return openRouterModels[modelId]; | |
| } |
🤖 Prompt for AI Agents
In src/mastra/config/openrouter.ts around lines 314 to 317, the
getOpenRouterModel function is missing a TSDoc comment; add a TSDoc block above
the function that documents the function purpose, includes a @param tag
describing the modelId parameter (that it is a key of openRouterModels) and a
@returns tag describing the returned model (the corresponding entry from
openRouterModels or undefined if not found), and ensure the description is
concise and follows existing project TSDoc style.
| export type SubscriptionTier = 'free' | 'pro' | 'enterprise' | ||
|
|
||
| export type SupabaseRole = 'anon' | 'authenticated' | 'admin' | 'moderator' | 'user' | ||
|
|
There was a problem hiding this comment.
Align SupabaseRole and role levels with the actual hierarchy
SupabaseRole is declared as:
export type SupabaseRole = 'anon' | 'authenticated' | 'admin' | 'moderator' | 'user'but:
ROLE_HIERARCHYandROLE_LEVELSincludeservice_role,enterprise,pro, andfree.- There is no
userentry anywhere in the hierarchy or RLS helpers. - Docs in
AGENTS.mdcall outservice_roleexplicitly as a supported role.
To avoid type drift and confusion, consider either:
- Expanding
SupabaseRoleto include all actual Supabase / app roles used here (e.g.'service_role' | 'anon' | 'authenticated' | 'admin' | 'moderator'), and introducing a separate type for subscription tiers, or - Removing/renaming
SupabaseRoleif it’s not actually used, and replacing it with more precise types for “auth roles” vs “subscription tiers”.
Right now the exported type does not accurately describe the role set this module models.
Also applies to: 16-36, 41-50
| /** | ||
| * Get all roles that inherit from a specific role | ||
| * @param targetRole The role to find inheritors for | ||
| * @returns Array of roles that can access the target role | ||
| * Check if a user role has access to a required role | ||
| */ | ||
| export function hasRoleAccess(userRole: string, requiredRole: string): boolean { | ||
| if (userRole === requiredRole) { | ||
| return true | ||
| } | ||
|
|
||
| if (!(userRole in ROLE_HIERARCHY)) { | ||
| return false | ||
| } | ||
|
|
||
| const inheritedRoles = ROLE_HIERARCHY[userRole] | ||
| return inheritedRoles.includes(requiredRole) | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
hasRoleAccess only checks direct inheritance; confirm if transitive access is required
hasRoleAccess currently returns true only when:
userRole === requiredRole, orrequiredRoleis directly listed inROLE_HIERARCHY[userRole].
It does not traverse multiple inheritance levels. For example, with the current hierarchy:
service_role→admin,authenticated,anonadmin→moderator,authenticated,anon
hasRoleAccess('service_role', 'moderator') will return false, even though service_role > admin > moderator in the conceptual hierarchy.
If you intend roles to inherit transitively (which is typical for RBAC), this function should walk the hierarchy (e.g., via BFS/DFS) until it finds requiredRole or exhausts ancestors. If one-step inheritance is intentional, consider documenting that explicitly to avoid surprises when the helper is used for access checks.
🤖 Prompt for AI Agents
In src/mastra/config/role-hierarchy.ts around lines 84 to 98, hasRoleAccess only
checks direct inheritance and must be updated to support transitive role
inheritance: implement a traversal (BFS or DFS) starting from userRole that
walks ROLE_HIERARCHY until requiredRole is found, keeping a visited set to avoid
cycles, returning true if requiredRole is encountered and false when traversal
completes; also keep the current direct-equality and missing-userRole checks,
and add a small comment noting transitive lookup behavior.
| export interface TierConfig { | ||
| maxRequests: number | ||
| features: string[] | ||
| supportLevel: 'community' | 'email' | 'priority' | 'phone_24x7' | ||
| customIntegrations: boolean | ||
| advancedAnalytics: boolean | ||
| whiteLabel: boolean | ||
| onPremise: boolean | ||
| rlsPolicy: string | ||
| } | ||
|
|
||
| export const TIER_QUOTAS: Record<SubscriptionTier, TierQuota> = { | ||
| export const TIER_CONFIGS: Record<SubscriptionTier, TierConfig> = { | ||
| free: { | ||
| maxDocuments: 500, | ||
| maxApiRequestsPerDay: 50, | ||
| maxUsersPerTenant: 1, | ||
| features: ['basic-rag', 'basic-search', 'public-docs'], | ||
| supportLevel: 'community', | ||
| customIntegrations: false, | ||
| advancedAnalytics: false, | ||
| whiteLabel: false, | ||
| onPremise: false, | ||
| maxRequests: 100, | ||
| features: ['basic-chat', 'public-docs'], | ||
| rlsPolicy: RLS_POLICIES.publicRead, | ||
| }, | ||
| pro: { | ||
| maxDocuments: 50000, | ||
| maxApiRequestsPerDay: 10000, | ||
| maxUsersPerTenant: -1, // unlimited | ||
| features: [ | ||
| 'basic-rag', | ||
| 'basic-search', | ||
| 'advanced-search', | ||
| 'public-docs', | ||
| 'internal-docs', | ||
| 'ai-insights', | ||
| 'advanced-analytics', | ||
| 'custom-integrations', | ||
| 'api-access', | ||
| 'priority-support', | ||
| ], | ||
| supportLevel: 'priority', | ||
| customIntegrations: true, | ||
| advancedAnalytics: true, | ||
| whiteLabel: false, | ||
| onPremise: false, | ||
| maxRequests: 10000, | ||
| features: ['advanced-chat', 'private-docs', 'api-access'], | ||
| rlsPolicy: RLS_POLICIES.proFeatures, | ||
| }, | ||
| enterprise: { | ||
| maxDocuments: -1, // unlimited | ||
| maxApiRequestsPerDay: -1, // unlimited | ||
| maxUsersPerTenant: -1, // unlimited | ||
| features: [ | ||
| 'basic-rag', | ||
| 'basic-search', | ||
| 'advanced-search', | ||
| 'public-docs', | ||
| 'internal-docs', | ||
| 'confidential-docs', | ||
| 'ai-insights', | ||
| 'advanced-analytics', | ||
| 'custom-workflows', | ||
| 'custom-integrations', | ||
| 'api-access', | ||
| 'white-label', | ||
| 'on-premise', | ||
| 'phone-support', | ||
| 'dedicated-account-manager', | ||
| ], | ||
| supportLevel: 'phone_24x7', | ||
| customIntegrations: true, | ||
| advancedAnalytics: true, | ||
| whiteLabel: true, | ||
| onPremise: true, | ||
| maxRequests: -1, // unlimited | ||
| features: ['unlimited-chat', 'all-docs', 'custom-models', 'admin-panel'], | ||
| rlsPolicy: RLS_POLICIES.enterpriseFeatures, | ||
| }, | ||
| } |
There was a problem hiding this comment.
Clarify tier–role mapping in getTierForRole / getRLSPolicyForRole to avoid misconfigured RLS
getTierForRole only distinguishes 'enterprise', 'pro', and 'free'; all other roles (including service_role, admin, moderator, authenticated, anon) fall through to 'free':
export function getTierForRole(role: string): SubscriptionTier {
if (role === 'enterprise') return 'enterprise'
if (role === 'pro') return 'pro'
if (role === 'free') return 'free'
return 'free'
}getRLSPolicyForRole then derives the policy solely from this tier:
export function getRLSPolicyForRole(role: string): string {
const tier = getTierForRole(role)
return TIER_CONFIGS[tier].rlsPolicy
}This means:
getRLSPolicyForRole('service_role')andgetRLSPolicyForRole('admin')both currently resolve to thefreetier’srlsPolicy(backed byRLS_POLICIES.publicRead/'anon'), even thoughRLS_POLICIESdefines stronger policies likeserviceOnlyandadminOnly.
If these helpers are used to drive RLS policy selection, that behavior is likely unintended and could lead to confusing or incorrect policy mapping.
Consider either:
- Making
getRLSPolicyForRoleexplicitly handle privileged roles (e.g.,service_role→RLS_POLICIES.serviceOnly,admin→RLS_POLICIES.adminOnly), or - Narrowing the function to only accept
SubscriptionTier(or a dedicated “tier role” type), leaving Supabase/auth roles to be mapped via a different helper.
Right now, the generic role: string signature combined with a tier-only switch makes it easy to misuse this in RLS configuration.
Also applies to: 159-179
🤖 Prompt for AI Agents
In src/mastra/config/role-hierarchy.ts around lines 118-140 (and apply same
change to lines 159-179), getTierForRole/getRLSPolicyForRole currently treat all
unknown roles as 'free', causing privileged roles (service_role, admin,
moderator, authenticated, anon) to inherit the free-tier RLS policy; explicitly
map those privileged roles to the correct RLS policies (e.g., service_role →
RLS_POLICIES.serviceOnly, admin → RLS_POLICIES.adminOnly, moderator →
appropriate policy, authenticated/anon → publicRead or their intended policies)
in getRLSPolicyForRole, or change the API so getRLSPolicyForRole accepts a
SubscriptionTier only and create a separate helper that maps auth role strings
to tiers/policies; update both functions so privileged roles never fall through
to 'free' and add a small unit test or comment documenting the intended mapping.
| /** | ||
| * Check if a user can access a resource based on their role | ||
| */ | ||
| export function canAccessResource(userRole: string, resourcePolicy: string): boolean { | ||
| const userLevel = getRoleLevel(userRole) | ||
| const requiredLevel = getRoleLevel(resourcePolicy) | ||
|
|
||
| // Check based on role level | ||
| switch (tier) { | ||
| case 'free': | ||
| return roleLevel >= 10 | ||
| case 'pro': | ||
| return roleLevel >= 50 | ||
| case 'enterprise': | ||
| return roleLevel >= 75 | ||
| default: | ||
| return false | ||
| } | ||
| return userLevel >= requiredLevel | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Clarify what resourcePolicy represents in canAccessResource
canAccessResource compares numeric levels:
const userLevel = getRoleLevel(userRole)
const requiredLevel = getRoleLevel(resourcePolicy)
return userLevel >= requiredLevelThis assumes resourcePolicy is itself a role key from ROLE_LEVELS (e.g., 'pro', 'enterprise', 'service_role'), but the name reads more like a Supabase policy identifier (e.g., 'proFeatures' from RLS_POLICIES).
To avoid misuse:
- Either tighten the type/signature (e.g.,
resourceRole: keyof typeof ROLE_LEVELS) and/or - Add a small doc comment noting that callers should pass the underlying role (
RLS_POLICIES.proFeatures→'pro'), not the policy key ('proFeatures').
This makes it clearer how to combine RLS_POLICIES and canAccessResource correctly.
🤖 Prompt for AI Agents
In src/mastra/config/role-hierarchy.ts around lines 181 to 189, the parameter
resourcePolicy is misleadingly named and typed — callers may pass an RLS policy
key (e.g., 'proFeatures') instead of a role key from ROLE_LEVELS, causing silent
misuse; change the parameter name to resourceRole and tighten its type to keyof
typeof ROLE_LEVELS (or otherwise document it) and add a short doc comment
stating callers must pass the underlying role key (e.g.,
RLS_POLICIES.proFeatures -> 'pro'), and also add a runtime guard that throws or
returns false if getRoleLevel returns undefined to fail loudly on invalid
inputs.
There was a problem hiding this comment.
Pull request overview
This pull request implements a comprehensive refactoring and expansion of the Mastra configuration system, including:
Purpose: Modernize the configuration architecture to support multiple AI providers with a unified interface, align with Supabase authentication patterns, and prepare for future model expansions.
Key Changes:
- Role hierarchy refactor: Simplified RBAC system with Supabase-compatible roles (anon, authenticated, admin, service_role) and subscription tiers (free, pro, enterprise)
- Provider consolidation: Refactored all AI provider configs (Google, OpenAI, Anthropic, etc.) to use consistent patterns with model collections and selector functions
- New integrations: Added GitHub Copilot, Claude Code, and AI Gateway providers with comprehensive model support
Reviewed changes
Copilot reviewed 18 out of 19 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
src/mastra/config/tracing.ts |
Minor formatting cleanup - moved BaseAISpan import, removed trailing whitespace |
src/mastra/config/role-hierarchy.ts |
Major refactor to Supabase-compatible RBAC with simplified role hierarchy and subscription tiers |
src/mastra/config/processors.ts |
Deleted entire file (584 lines removed) - processor implementations removed |
src/mastra/config/openrouter.ts |
Added 300+ lines of model configurations with reasoning support for 50+ models across providers |
src/mastra/config/openai.ts |
Refactored to use model collections pattern with GPT-4/5 series models |
src/mastra/config/google.ts |
Reorganized into separate collections for chat, image, and embedding models |
src/mastra/config/github-copilot.ts |
New file - GitHub Copilot integration with 20+ model configurations |
src/mastra/config/gemini-cli.ts |
Refactored into organized model collections with audio/video support |
src/mastra/config/claude-code.ts |
New file - Claude Code CLI provider integration |
src/mastra/config/anthropic.ts |
Refactored to model collections pattern with Claude 3.5/4.x series |
src/mastra/config/ai-gateway.ts |
New file - Unified AI Gateway integration with dynamic model discovery |
src/mastra/config/index.ts |
Added exports for new providers (github-copilot, gemini-cli, ai-gateway, claude-code) |
src/mastra/config/README.md |
Comprehensive documentation rewrite with architecture overview and usage examples |
src/mastra/config/AGENTS.md |
Updated to reflect new providers, roles, and environment variables |
package.json |
Added dependencies for github-copilot and claude-code providers |
package-lock.json |
Dependency lock updates including @anthropic-ai/claude-agent-sdk |
app/chat/config/openrouter-models.ts |
Added GPT OSS 20B free model configuration |
.env.example |
Added AI_GATEWAY_API_KEY (incomplete comment) |
.agent/rules/conventions.md |
Removed duplicate RuntimeContext import |
Comments suppressed due to low confidence (3)
src/mastra/config/AGENTS.md:153
- The changelog shows dates of
2025-12-08,2025-11-26,2025-10-15,2025-10-08, and2025-09-24, which are all in the future (current date is December 8, 2024, and the knowledge cutoff is January 2025). These should be corrected to use 2024 instead of 2025 for the year.
| 2.3.0 | 2025-12-08 | Added AI Gateway provider for unified multi-provider access |
| 2.2.1 | 2025-12-08 | Fixed database environment variables (SUPABASE instead of PG_CONNECTION) |
| 2.1.0 | 2025-12-08 | Added GitHub Copilot, updated all providers, comprehensive model coverage |
| 2.0.0 | 2025-11-26 | Major update: added all providers, env vars documented |
| 1.2.0 | 2025-10-15 | Enhanced pg-storage.ts description |
| 1.1.0 | 2025-10-08 | Verified content accuracy and updated metadata. |
| 1.0.0 | 2025-09-24 | Standardized template applied |
src/mastra/config/claude-code.ts:2
- Unused import logError.
import { logError } from './logger'
src/mastra/config/github-copilot.ts:2
- Unused import logError.
import { logError } from './logger';
| import { AISpanType, InternalSpans } from "@mastra/core/ai-tracing"; | ||
| import type { RuntimeContext } from "@mastra/core/runtime-context"; | ||
| import { log } from "../config/logger"; | ||
| import type { RuntimeContext } from '@mastra/core/runtime-context' |
There was a problem hiding this comment.
Duplicate import statement. The line import type { RuntimeContext } from '@mastra/core/runtime-context' appears at both line 22 and line 23. One of these should be removed to avoid confusion and maintain clean code.
| import type { RuntimeContext } from '@mastra/core/runtime-context' | |
| import type { RuntimeContext } from '@mastra/core/runtime-context'; |
| // @ts-expect-error - traceMap is protected in base class but we need to check it | ||
| const traceMap = this.traceMap as Map<string, unknown> | undefined | ||
| if (!traceMap || !span.traceId) return | ||
| if (!traceMap || !span.traceId) {return} |
There was a problem hiding this comment.
Unnecessary braces around the return statement. The code if (!traceMap || !span.traceId) {return} should be if (!traceMap || !span.traceId) return to maintain consistency with the rest of the codebase and avoid unnecessary syntax.
| if (!traceMap || !span.traceId) {return} | |
| if (!traceMap || !span.traceId) return |
| const requiredLevel = getRoleLevel(resourcePolicy) | ||
|
|
There was a problem hiding this comment.
The canAccessResource function has flawed logic. It compares userLevel >= requiredLevel, which means users with higher numeric levels can access resources requiring lower levels. However, looking at ROLE_LEVELS, service_role: 1000 is the highest level and anon: 0 is the lowest. This is correct. But the function uses resourcePolicy as input, which would be a string like 'publicRead' from RLS_POLICIES, not a role name. The function should map the policy to a role first:
export function canAccessResource(userRole: string, resourcePolicy: string): boolean {
const userLevel = getRoleLevel(userRole)
const policyRole = Object.entries(RLS_POLICIES).find(([, policy]) => policy === resourcePolicy)?.[1] ?? resourcePolicy
const requiredLevel = getRoleLevel(policyRole)
return userLevel >= requiredLevel
}| const requiredLevel = getRoleLevel(resourcePolicy) | |
| // Map resourcePolicy to the required role by searching TIER_CONFIGS | |
| const policyRole = Object.entries(TIER_CONFIGS).find(([, config]) => config.rlsPolicy === resourcePolicy)?.[0] ?? resourcePolicy | |
| const requiredLevel = getRoleLevel(policyRole) |
| // Load environment variables | ||
| dotenv.config(); | ||
|
|
There was a problem hiding this comment.
The dotenv.config() call on line 6 is unnecessary in config files. Environment variables should be loaded once at the application entry point, not in individual configuration modules. This could lead to redundant file reads and potential conflicts.
| // Load environment variables | |
| dotenv.config(); |
| // Claude 4.1 Opus (most capable) | ||
| claudeOpus: claudeCodeProvider('opus'), | ||
| // Claude 4.5 Sonnet (balanced performance) | ||
| claudeSonnet: claudeCodeProvider('sonnet'), | ||
| // Claude 4.5 Haiku (fastest, most cost-effective) |
There was a problem hiding this comment.
The comments describe the models using version numbers that don't match the actual model IDs. For example, line 21 says "Claude 4.1 Opus" but the model ID is just 'opus', and line 23 says "Claude 4.5 Sonnet" but the model ID is 'sonnet'. These comments are misleading. Consider either updating the comments to match the actual Claude Code CLI naming convention, or clarifying that these are shorthand identifiers that map to specific versions.
| // Claude 4.1 Opus (most capable) | |
| claudeOpus: claudeCodeProvider('opus'), | |
| // Claude 4.5 Sonnet (balanced performance) | |
| claudeSonnet: claudeCodeProvider('sonnet'), | |
| // Claude 4.5 Haiku (fastest, most cost-effective) | |
| // 'opus' model ID (Claude Code CLI). Currently maps to Claude Opus (most capable). | |
| claudeOpus: claudeCodeProvider('opus'), | |
| // 'sonnet' model ID (Claude Code CLI). Currently maps to Claude Sonnet (balanced performance). | |
| claudeSonnet: claudeCodeProvider('sonnet'), | |
| // 'haiku' model ID (Claude Code CLI). Currently maps to Claude Haiku (fastest, most cost-effective). |
| import { logError } from './logger' | ||
|
|
There was a problem hiding this comment.
The logError import is unused in this file. It should be removed to keep imports clean.
| import { logError } from './logger' |
|
|
||
| ```env | ||
| # Database | ||
| SUPABASE=postgres://user:password@localhost:5432/mastra |
There was a problem hiding this comment.
The environment variable name SUPABASE is misleading. Based on the AGENTS.md file showing PG_CONNECTION was used previously, and the fact that this appears to be a PostgreSQL connection string (not Supabase-specific), a more accurate name would be DATABASE_URL or PG_CONNECTION_STRING. If the codebase actually uses SUPABASE as the variable name, this should be clarified in the documentation to explain why a generic PostgreSQL connection uses this name.
| SUPABASE=postgres://user:password@localhost:5432/mastra | |
| DATABASE_URL=postgres://user:password@localhost:5432/mastra |
|
|
||
| BaseAISpan} from '@mastra/core/ai-tracing' |
There was a problem hiding this comment.
The import statement formatting is inconsistent. BaseAISpan should be moved to line 62 with a trailing comma to maintain consistency with the rest of the import block.
| BaseAISpan} from '@mastra/core/ai-tracing' | |
| BaseAISpan, | |
| } from '@mastra/core/ai-tracing' |
| } | ||
|
|
||
| const inheritedRoles = ROLE_HIERARCHY[userRole] | ||
| return inheritedRoles.includes(requiredRole) |
There was a problem hiding this comment.
The hasRoleAccess function only checks direct inheritance (one level deep). It does not recursively check transitive role inheritance. For example, if 'admin' inherits 'moderator', and 'moderator' inherits 'authenticated', then hasRoleAccess('admin', 'authenticated') would return false even though admin should have authenticated access through the hierarchy. Consider implementing recursive checking to properly handle multi-level inheritance:
export function hasRoleAccess(userRole: string, requiredRole: string): boolean {
if (userRole === requiredRole) {
return true
}
if (!(userRole in ROLE_HIERARCHY)) {
return false
}
const inheritedRoles = ROLE_HIERARCHY[userRole]
if (inheritedRoles.includes(requiredRole)) {
return true
}
// Check transitive inheritance
return inheritedRoles.some(role => hasRoleAccess(role, requiredRole))
}| return inheritedRoles.includes(requiredRole) | |
| if (inheritedRoles.includes(requiredRole)) { | |
| return true | |
| } | |
| // Recursively check transitive inheritance | |
| return inheritedRoles.some(role => hasRoleAccess(role, requiredRole)) |
| return 'enterprise' | ||
| if (role === 'free') { | ||
| return 'free' | ||
| } |
There was a problem hiding this comment.
The getTierForRole function only handles subscription tier roles ('enterprise', 'pro', 'free'), but not other roles like 'admin', 'moderator', 'authenticated', or 'anon'. When called with any of these roles, it will always return 'free' as the default. This could lead to incorrect tier assignments. Consider either:
- Documenting that this function only works with subscription tier roles, or
- Adding logic to handle all role types:
export function getTierForRole(role: string): SubscriptionTier {
// Subscription tier roles
if (role === 'enterprise') return 'enterprise'
if (role === 'pro') return 'pro'
if (role === 'free') return 'free'
// Non-subscription roles - map to appropriate tier
if (role === 'admin' || role === 'service_role') return 'enterprise'
if (role === 'moderator') return 'pro'
// Default for authenticated/anon
return 'free'
}| } | |
| } | |
| // Non-subscription roles - map to appropriate tier | |
| if (role === 'admin' || role === 'service_role') { | |
| return 'enterprise' | |
| } | |
| if (role === 'moderator') { | |
| return 'pro' | |
| } | |
| // Default for authenticated/anon and any unknown role |
refactor: Enhance tracing configuration
feat: Implement AI Gateway configuration
feat: Add Claude Code provider integration
feat: Integrate GitHub Copilot provider