UNPKG

@mastra/core

Version:
1,453 lines (1,450 loc) • 48 kB
import { createHash } from 'crypto'; import os from 'os'; // ../_internals/auth/dist/chunk-BHFQZXOC.js function hashTelemetryValue(value) { return createHash("sha256").update(value).digest("hex"); } function getHashedHostname() { return hashTelemetryValue(os.hostname() || "unknown-host").slice(0, 16); } function getEETelemetryFallbackDistinctId() { return `mastra-${getHashedHostname()}`; } var EE_TELEMETRY_BRIDGE = /* @__PURE__ */ Symbol.for("mastra.eeTelemetryBridge"); function getTelemetryBridge() { return globalThis[EE_TELEMETRY_BRIDGE]; } function captureEEEvent(event, distinctId, properties) { getTelemetryBridge()?.captureEEEvent?.(event, distinctId, properties); } var LicenseClient = class _LicenseClient { static instance; logger; licenseKey; licenseUrl; mode = "open-source"; status = "pending"; cachedResult = null; cacheExpiry = 0; gracePeriodEnd = 0; revalidationTimeout = null; GRACE_PERIOD_MS = 72 * 60 * 60 * 1e3; // 72 hours DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3; // 24 hours constructor(logger) { this.logger = logger; this.licenseKey = process.env.MASTRA_LICENSE_KEY || process.env.MASTRA_EE_LICENSE; this.licenseUrl = process.env.MASTRA_LICENSE_URL || "https://license.mastra.ai"; if (this.licenseKey) { this.mode = "enterprise"; } else { this.mode = "open-source"; } } static getInstance(logger) { if (!_LicenseClient.instance) { _LicenseClient.instance = new _LicenseClient(logger); } else if (logger) { _LicenseClient.instance.logger = logger; } return _LicenseClient.instance; } /** * Reset the singleton so the next getInstance() re-reads env vars. * Intended for tests. */ static resetInstance() { if (_LicenseClient.instance?.revalidationTimeout) { clearTimeout(_LicenseClient.instance.revalidationTimeout); } _LicenseClient.instance = void 0; } REQUEST_TIMEOUT_MS = 1e4; async fetchWithRetry(url, options, retries = 3) { for (let i = 0; i < retries; i++) { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), this.REQUEST_TIMEOUT_MS); timer.unref?.(); try { const signal = options.signal ? AbortSignal.any([options.signal, controller.signal]) : controller.signal; const response = await fetch(url, { ...options, signal }); if (response.status === 429 || response.status >= 500) { if (i === retries - 1) return response; } else { return response; } } catch (error) { if (i === retries - 1) throw error; } finally { clearTimeout(timer); } const delay = Math.pow(2, i) * 1e3; await new Promise((resolve) => setTimeout(resolve, delay)); } throw new Error("Unreachable"); } validationPromise = null; async validate() { if (this.mode === "open-source") { return true; } if (this.cachedResult && Date.now() < this.cacheExpiry) { return true; } return this.revalidate(); } /** * Contact the server regardless of cache freshness, coalescing concurrent * callers (e.g. the Mastra constructor and the auth/ee helpers both kicking * off validation at startup) into a single in-flight request so the server * is contacted — and the outcome logged — only once. Used directly by the * background revalidation timer, which must bypass the cache check. */ revalidate() { if (!this.validationPromise) { this.validationPromise = this.performValidation().finally(() => { this.validationPromise = null; }); } return this.validationPromise; } async performValidation() { const now = Date.now(); try { if (!this.licenseUrl?.startsWith("https://") && !this.licenseUrl?.includes("localhost")) { this.logger?.warn("License URL is not HTTPS. Proceeding, but this is insecure."); } const response = await this.fetchWithRetry(`${this.licenseUrl}/validate`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ licenseKey: this.licenseKey }) }); if (response.status === 429 || response.status >= 500) { throw new Error(`License server responded with ${response.status}`); } const data = await response.json(); if (data.valid) { this.status = "valid"; this.logger?.info( `License validated: ${data.planTier} tier${data.expiresAt ? `, expires ${data.expiresAt.slice(0, 10)}` : ""}` ); this.cachedResult = data; const ttlSeconds = data.leaseTtlSeconds || this.DEFAULT_TTL_MS / 1e3; this.cacheExpiry = now + ttlSeconds * 1e3; this.gracePeriodEnd = now + this.GRACE_PERIOD_MS; this.scheduleRevalidation(ttlSeconds); return true; } else if (data.code === "RATE_LIMITED") { throw new Error(`License server rate limited: ${data.reason}`); } else { this.status = "invalid"; this.logger?.error(`License validation failed: ${data.code} - ${data.reason}`); this.clearCache(); return false; } } catch { if (this.cachedResult && now < this.gracePeriodEnd) { this.logger?.warn("License server unreachable. Using cached license (within grace period)."); this.status = "valid"; this.scheduleRevalidation(this.DEFAULT_TTL_MS / 1e3); return true; } else if (this.cachedResult) { this.logger?.error("License server unreachable and grace period expired. Disabling enterprise features."); this.status = "invalid"; this.clearCache(); return false; } else { this.logger?.warn("License server unreachable on startup. Failing open (allowing features) and will retry."); this.status = "valid"; this.cachedResult = { valid: true, entitlements: [], planTier: "unknown", expiresAt: null, leaseTtlSeconds: 300 // 5 minutes }; this.cacheExpiry = now + 300 * 1e3; this.gracePeriodEnd = now + this.GRACE_PERIOD_MS; this.scheduleRevalidation(300); return true; } } } scheduleRevalidation(ttlSeconds) { if (this.revalidationTimeout) { clearTimeout(this.revalidationTimeout); } const revalidateMs = ttlSeconds * 1e3 * 0.75; this.revalidationTimeout = setTimeout(() => { this.logger?.info("Performing background license revalidation..."); this.revalidate().catch((err) => { this.logger?.error( `Background license revalidation failed: ${err instanceof Error ? err.message : String(err)}` ); }); }, revalidateMs); this.revalidationTimeout.unref(); } clearCache() { this.cachedResult = null; this.cacheExpiry = 0; this.gracePeriodEnd = 0; this.status = "invalid"; if (this.revalidationTimeout) { clearTimeout(this.revalidationTimeout); this.revalidationTimeout = null; } } hasFeature(featureName) { if (this.mode === "open-source") return true; if (this.status === "pending") return true; if (this.status === "invalid") return false; if (!this.cachedResult) return false; if (this.cachedResult.planTier === "unknown") return true; return this.cachedResult.entitlements.includes(featureName); } getEntitlements() { if (this.mode === "open-source") return null; return this.cachedResult?.entitlements || null; } getSnapshot() { return { mode: this.mode, status: this.status, entitlements: this.cachedResult?.entitlements ?? null, planTier: this.cachedResult?.planTier ?? null, expiresAt: this.cachedResult?.expiresAt ?? null }; } }; function getLicenseKey() { return process.env["MASTRA_LICENSE_KEY"] || process.env["MASTRA_EE_LICENSE"]; } var validationStarted = false; var hasWarnedAboutDevLicense = false; function getClient() { const client = LicenseClient.getInstance(); if (!validationStarted) { validationStarted = true; void client.validate().catch(() => { }); } return client; } function startLicenseValidation() { const client = LicenseClient.getInstance(); validationStarted = true; return client.validate(); } function validateLicense(licenseKey) { const configuredKey = getLicenseKey(); const key = licenseKey ?? configuredKey; if (!key) { return { valid: false }; } if (licenseKey !== void 0 && licenseKey !== configuredKey) { return { valid: false }; } const snap = getClient().getSnapshot(); return { valid: snap.status !== "invalid", features: snap.entitlements ?? void 0, tier: snap.planTier ?? void 0, expiresAt: snap.expiresAt ? new Date(snap.expiresAt) : void 0 }; } function isLicenseValid() { if (!getLicenseKey()) { return false; } return getClient().getSnapshot().status !== "invalid"; } var isEELicenseValid = isLicenseValid; function isFeatureEnabled(feature) { if (!getLicenseKey()) { return false; } return getClient().hasFeature(feature); } function getSafeLicenseSummary() { const key = getLicenseKey(); const info = validateLicense(key); const licenseHash = key ? hashTelemetryValue(key) : void 0; return { valid: info.valid, isDevEnvironment: isDevEnvironment(), licenseHash: licenseHash ? licenseHash.slice(0, 16) : void 0, anonymousId: licenseHash ? `${licenseHash.slice(0, 16)}-anonymous` : void 0, features: info.features, tier: info.tier }; } function warnIfDevEENeedsLicense() { if (hasWarnedAboutDevLicense || !isDevEnvironment() || isLicenseValid()) { return; } hasWarnedAboutDevLicense = true; console.warn( "[mastra/auth-ee] Mastra Enterprise features are enabled for local development, but no valid MASTRA_LICENSE_KEY is configured. These features will be disabled in production without a valid license. Contact us to get a production license: https://mastra.ai/contact" ); } function clearLicenseCache() { validationStarted = false; hasWarnedAboutDevLicense = false; LicenseClient.resetInstance(); } function isDevEnvironment() { return process.env["MASTRA_DEV"] === "true" || process.env["MASTRA_DEV"] === "1" || process.env["NODE_ENV"] !== "production" && process.env["NODE_ENV"] !== "prod"; } function isEEEnabled() { if (isDevEnvironment()) { warnIfDevEENeedsLicense(); return true; } return isLicenseValid(); } function isAuthenticated(caps) { return "user" in caps && caps.user !== null; } function implementsInterface(auth, method) { return auth !== null && typeof auth === "object" && typeof auth[method] === "function"; } function isMastraCloudAuth(auth) { if (!auth || typeof auth !== "object") return false; return "isMastraCloudAuth" in auth && auth.isMastraCloudAuth === true; } function isSimpleAuth(auth) { if (!auth || typeof auth !== "object") return false; return "isSimpleAuth" in auth && auth.isSimpleAuth === true; } function hasAdminBypassPermissions(permissions) { return permissions.some((p) => p === "*" || p === "*:*"); } function getRequestIp(request) { const forwardedFor = request.headers.get("x-forwarded-for"); if (forwardedFor) { return forwardedFor.split(",")[0]?.trim(); } return request.headers.get("x-real-ip") ?? void 0; } function captureLicenseCheck({ request, user, hasLicense, isDev, isCloud, isSimple, capabilities }) { const license = getSafeLicenseSummary(); try { const ip = getRequestIp(request); captureEEEvent("ee_license_check", user?.id || license.anonymousId || getEETelemetryFallbackDistinctId(), { license_valid: hasLicense, license_hash: license.licenseHash, is_dev_environment: isDev, is_cloud: isCloud, is_simple_auth: isSimple, capabilities, user_id: user?.id, $ip: ip, license_features: license.features, license_tier: license.tier }); } catch { } } async function buildCapabilities(auth, request, options) { if (!auth) { return { enabled: false, login: null }; } const hasLicense = isLicenseValid(); const isCloud = isMastraCloudAuth(auth); const isSimple = isSimpleAuth(auth); const isDev = isDevEnvironment(); if (isDev && !hasLicense) { warnIfDevEENeedsLicense(); } const isLicensedOrCloud = hasLicense || isCloud || isSimple || isDev; const isFeatureLicensed = (feature) => isCloud || isSimple || isDev || hasLicense && isFeatureEnabled(feature); let login = null; const hasSSO = implementsInterface(auth, "getLoginUrl") && isLicensedOrCloud; const hasCredentials = implementsInterface(auth, "signIn") && isLicensedOrCloud; const raw = (options?.apiPrefix || "/api").trim(); const withSlash = raw.startsWith("/") ? raw : `/${raw}`; const prefix = withSlash.endsWith("/") ? withSlash.slice(0, -1) : withSlash; const ssoLoginUrl = `${prefix}/auth/sso/login`; let signUpEnabled = true; if (implementsInterface(auth, "signIn")) { const credentialsProvider = auth; if (typeof credentialsProvider.isSignUpEnabled === "function") { signUpEnabled = credentialsProvider.isSignUpEnabled(); } } if (hasSSO && hasCredentials) { const ssoConfig = auth.getLoginButtonConfig(); login = { type: "both", signUpEnabled, description: ssoConfig.description, sso: { ...ssoConfig, url: ssoLoginUrl } }; } else if (hasSSO) { const ssoConfig = auth.getLoginButtonConfig(); login = { type: "sso", description: ssoConfig.description, sso: { ...ssoConfig, url: ssoLoginUrl } }; } else if (hasCredentials) { login = { type: "credentials", signUpEnabled }; } let user = null; if (implementsInterface(auth, "getCurrentUser") && isLicensedOrCloud) { try { user = await auth.getCurrentUser(request); } catch { user = null; } } if (!user) { captureLicenseCheck({ request, user, hasLicense, isDev, isCloud, isSimple }); return { enabled: true, login }; } const rbacProvider = options?.rbac; const hasRBAC = !!rbacProvider && isFeatureLicensed("rbac"); const hasFGA = !!options?.fga && isFeatureLicensed("fga"); const capabilities = { user: implementsInterface(auth, "getCurrentUser") && isLicensedOrCloud, session: implementsInterface(auth, "createSession") && isLicensedOrCloud, sso: implementsInterface(auth, "getLoginUrl") && isLicensedOrCloud, rbac: hasRBAC, acl: implementsInterface(auth, "canAccess") && isFeatureLicensed("acl"), fga: hasFGA }; let access = null; if (hasRBAC && rbacProvider) { try { const roles = await rbacProvider.getRoles(user); const permissions = await rbacProvider.getPermissions(user); access = { roles, permissions }; const license = getSafeLicenseSummary(); try { const ip = getRequestIp(request); captureEEEvent("ee_feature_used", user.id || license.anonymousId || getEETelemetryFallbackDistinctId(), { feature: "rbac", user_id: user.id, organization_membership_id: user.metadata?.["organizationMembershipId"], role_count: roles.length, permission_count: permissions.length, $ip: ip, license_valid: license.valid, license_hash: license.licenseHash, is_dev_environment: license.isDevEnvironment }); } catch { } } catch { access = null; } } let availableRoles; if (access && rbacProvider?.getAvailableRoles) { if (hasAdminBypassPermissions(access.permissions)) { try { const allRoles = await rbacProvider.getAvailableRoles(); const getPermissionsForRole = rbacProvider.getPermissionsForRole?.bind(rbacProvider); if (getPermissionsForRole) { const rolePermissions = await Promise.allSettled( allRoles.map(async (role) => ({ role, perms: await getPermissionsForRole(role.id) })) ); availableRoles = rolePermissions.flatMap((result) => { if (result.status !== "fulfilled") { console.warn("[auth/ee] failed to list permissions for role:", result.reason); return []; } return hasAdminBypassPermissions(result.value.perms) ? [] : [result.value.role]; }); } else { availableRoles = allRoles; } } catch (error) { console.warn("[auth/ee] failed to list available roles for admin user:", error); } } } captureLicenseCheck({ request, user, hasLicense, isDev, isCloud, isSimple, capabilities }); return { enabled: true, login, user: { id: user.id, email: user.email, name: user.name, avatarUrl: user.avatarUrl }, capabilities, access, availableRoles }; } // ../_internals/auth/dist/chunk-H3EJ4GVJ.js var RESOURCES = [ "a2a", "agent-builder", "agent-controller", "agents", "auth", "background-tasks", "channels", "datasets", "embedders", "experiments", "infrastructure", "logs", "mcp", "memory", "observability", "processor-providers", "processors", "schedules", "scores", "stored-agents", "stored-mcp-clients", "stored-prompt-blocks", "stored-scorers", "stored-skills", "stored-workspaces", "system", "tool-providers", "tools", "vector", "vectors", "workflows", "workspaces" ]; var ACTIONS = ["create", "delete", "execute", "publish", "read", "share", "write"]; var PERMISSION_PATTERNS = { /** Full access to all resources and actions */ "*": "*", /** Create all resources */ "*:create": "*:create", /** Delete all resources */ "*:delete": "*:delete", /** Execute all resources */ "*:execute": "*:execute", /** Publish, activate, or restore all resources */ "*:publish": "*:publish", /** View all resources */ "*:read": "*:read", /** Change visibility/audience all resources */ "*:share": "*:share", /** Create and modify all resources */ "*:write": "*:write", /** Full access to agent-to-agent communication */ "a2a:*": "a2a:*", /** Full access to agent builder */ "agent-builder:*": "agent-builder:*", /** Full access to agent controller sessions */ "agent-controller:*": "agent-controller:*", /** Full access to agents */ "agents:*": "agents:*", /** Full access to auth */ "auth:*": "auth:*", /** Full access to background tasks */ "background-tasks:*": "background-tasks:*", /** Full access to channels */ "channels:*": "channels:*", /** Full access to datasets */ "datasets:*": "datasets:*", /** Full access to embedders */ "embedders:*": "embedders:*", /** Full access to experiments */ "experiments:*": "experiments:*", /** Full access to infrastructure */ "infrastructure:*": "infrastructure:*", /** Full access to logs */ "logs:*": "logs:*", /** Full access to MCP servers */ "mcp:*": "mcp:*", /** Full access to memory and threads */ "memory:*": "memory:*", /** Full access to traces and spans */ "observability:*": "observability:*", /** Full access to processor-providers */ "processor-providers:*": "processor-providers:*", /** Full access to processors */ "processors:*": "processors:*", /** Full access to schedules */ "schedules:*": "schedules:*", /** Full access to evaluation scores */ "scores:*": "scores:*", /** Full access to stored agents */ "stored-agents:*": "stored-agents:*", /** Full access to stored MCP clients */ "stored-mcp-clients:*": "stored-mcp-clients:*", /** Full access to stored prompt blocks */ "stored-prompt-blocks:*": "stored-prompt-blocks:*", /** Full access to stored scorers */ "stored-scorers:*": "stored-scorers:*", /** Full access to stored skills */ "stored-skills:*": "stored-skills:*", /** Full access to stored workspaces */ "stored-workspaces:*": "stored-workspaces:*", /** Full access to system info */ "system:*": "system:*", /** Full access to tool-providers */ "tool-providers:*": "tool-providers:*", /** Full access to tools */ "tools:*": "tools:*", /** Full access to vector stores */ "vector:*": "vector:*", /** Full access to vectors */ "vectors:*": "vectors:*", /** Full access to workflows */ "workflows:*": "workflows:*", /** Full access to workspaces */ "workspaces:*": "workspaces:*", /** View agent-to-agent communication */ "a2a:read": "a2a:read", /** Create and modify agent-to-agent communication */ "a2a:write": "a2a:write", /** Execute agent builder */ "agent-builder:execute": "agent-builder:execute", /** View agent builder */ "agent-builder:read": "agent-builder:read", /** Create and modify agent builder */ "agent-builder:write": "agent-builder:write", /** Execute agent controller sessions */ "agent-controller:execute": "agent-controller:execute", /** View agent controller sessions */ "agent-controller:read": "agent-controller:read", /** Create agents */ "agents:create": "agents:create", /** Delete agents */ "agents:delete": "agents:delete", /** Execute agents */ "agents:execute": "agents:execute", /** View agents */ "agents:read": "agents:read", /** Create and modify agents */ "agents:write": "agents:write", /** View auth */ "auth:read": "auth:read", /** View background tasks */ "background-tasks:read": "background-tasks:read", /** View channels */ "channels:read": "channels:read", /** Create and modify channels */ "channels:write": "channels:write", /** Delete datasets */ "datasets:delete": "datasets:delete", /** Execute datasets */ "datasets:execute": "datasets:execute", /** View datasets */ "datasets:read": "datasets:read", /** Create and modify datasets */ "datasets:write": "datasets:write", /** View embedders */ "embedders:read": "embedders:read", /** View experiments */ "experiments:read": "experiments:read", /** View infrastructure */ "infrastructure:read": "infrastructure:read", /** View logs */ "logs:read": "logs:read", /** Execute MCP servers */ "mcp:execute": "mcp:execute", /** View MCP servers */ "mcp:read": "mcp:read", /** Create and modify MCP servers */ "mcp:write": "mcp:write", /** Delete memory and threads */ "memory:delete": "memory:delete", /** Execute memory and threads */ "memory:execute": "memory:execute", /** View memory and threads */ "memory:read": "memory:read", /** Create and modify memory and threads */ "memory:write": "memory:write", /** View traces and spans */ "observability:read": "observability:read", /** Create and modify traces and spans */ "observability:write": "observability:write", /** View processor-providers */ "processor-providers:read": "processor-providers:read", /** Execute processors */ "processors:execute": "processors:execute", /** View processors */ "processors:read": "processors:read", /** Delete schedules */ "schedules:delete": "schedules:delete", /** Execute schedules */ "schedules:execute": "schedules:execute", /** View schedules */ "schedules:read": "schedules:read", /** Create and modify schedules */ "schedules:write": "schedules:write", /** View evaluation scores */ "scores:read": "scores:read", /** Create and modify evaluation scores */ "scores:write": "scores:write", /** Delete stored agents */ "stored-agents:delete": "stored-agents:delete", /** Publish, activate, or restore stored agents */ "stored-agents:publish": "stored-agents:publish", /** View stored agents */ "stored-agents:read": "stored-agents:read", /** Create and modify stored agents */ "stored-agents:write": "stored-agents:write", /** Delete stored MCP clients */ "stored-mcp-clients:delete": "stored-mcp-clients:delete", /** Publish, activate, or restore stored MCP clients */ "stored-mcp-clients:publish": "stored-mcp-clients:publish", /** View stored MCP clients */ "stored-mcp-clients:read": "stored-mcp-clients:read", /** Create and modify stored MCP clients */ "stored-mcp-clients:write": "stored-mcp-clients:write", /** Delete stored prompt blocks */ "stored-prompt-blocks:delete": "stored-prompt-blocks:delete", /** Publish, activate, or restore stored prompt blocks */ "stored-prompt-blocks:publish": "stored-prompt-blocks:publish", /** View stored prompt blocks */ "stored-prompt-blocks:read": "stored-prompt-blocks:read", /** Create and modify stored prompt blocks */ "stored-prompt-blocks:write": "stored-prompt-blocks:write", /** Delete stored scorers */ "stored-scorers:delete": "stored-scorers:delete", /** Publish, activate, or restore stored scorers */ "stored-scorers:publish": "stored-scorers:publish", /** View stored scorers */ "stored-scorers:read": "stored-scorers:read", /** Create and modify stored scorers */ "stored-scorers:write": "stored-scorers:write", /** Delete stored skills */ "stored-skills:delete": "stored-skills:delete", /** Publish, activate, or restore stored skills */ "stored-skills:publish": "stored-skills:publish", /** View stored skills */ "stored-skills:read": "stored-skills:read", /** Create and modify stored skills */ "stored-skills:write": "stored-skills:write", /** Delete stored workspaces */ "stored-workspaces:delete": "stored-workspaces:delete", /** View stored workspaces */ "stored-workspaces:read": "stored-workspaces:read", /** Create and modify stored workspaces */ "stored-workspaces:write": "stored-workspaces:write", /** View system info */ "system:read": "system:read", /** Delete tool-providers */ "tool-providers:delete": "tool-providers:delete", /** View tool-providers */ "tool-providers:read": "tool-providers:read", /** Create and modify tool-providers */ "tool-providers:write": "tool-providers:write", /** Execute tools */ "tools:execute": "tools:execute", /** View tools */ "tools:read": "tools:read", /** Delete vector stores */ "vector:delete": "vector:delete", /** Execute vector stores */ "vector:execute": "vector:execute", /** View vector stores */ "vector:read": "vector:read", /** Create and modify vector stores */ "vector:write": "vector:write", /** View vectors */ "vectors:read": "vectors:read", /** Delete workflows */ "workflows:delete": "workflows:delete", /** Execute workflows */ "workflows:execute": "workflows:execute", /** View workflows */ "workflows:read": "workflows:read", /** Create and modify workflows */ "workflows:write": "workflows:write", /** Delete workspaces */ "workspaces:delete": "workspaces:delete", /** View workspaces */ "workspaces:read": "workspaces:read", /** Create and modify workspaces */ "workspaces:write": "workspaces:write", /** Full access to all stored resource families */ "stored:*": "stored:*", /** View all stored resource families */ "stored:read": "stored:read", /** Create and modify all stored resource families */ "stored:write": "stored:write", /** Delete all stored resource families */ "stored:delete": "stored:delete", /** Change visibility/audience stored agents */ "stored-agents:share": "stored-agents:share", /** Change visibility/audience stored skills */ "stored-skills:share": "stored-skills:share" }; var PERMISSIONS = [ "a2a:read", "a2a:write", "agent-builder:execute", "agent-builder:read", "agent-builder:write", "agent-controller:execute", "agent-controller:read", "agents:create", "agents:delete", "agents:execute", "agents:read", "agents:write", "auth:read", "background-tasks:read", "channels:read", "channels:write", "datasets:delete", "datasets:execute", "datasets:read", "datasets:write", "embedders:read", "experiments:read", "infrastructure:read", "logs:read", "mcp:execute", "mcp:read", "mcp:write", "memory:delete", "memory:execute", "memory:read", "memory:write", "observability:read", "observability:write", "processor-providers:read", "processors:execute", "processors:read", "schedules:delete", "schedules:execute", "schedules:read", "schedules:write", "scores:read", "scores:write", "stored-agents:delete", "stored-agents:publish", "stored-agents:read", "stored-agents:write", "stored-mcp-clients:delete", "stored-mcp-clients:publish", "stored-mcp-clients:read", "stored-mcp-clients:write", "stored-prompt-blocks:delete", "stored-prompt-blocks:publish", "stored-prompt-blocks:read", "stored-prompt-blocks:write", "stored-scorers:delete", "stored-scorers:publish", "stored-scorers:read", "stored-scorers:write", "stored-skills:delete", "stored-skills:publish", "stored-skills:read", "stored-skills:write", "stored-workspaces:delete", "stored-workspaces:read", "stored-workspaces:write", "system:read", "tool-providers:delete", "tool-providers:read", "tool-providers:write", "tools:execute", "tools:read", "vector:delete", "vector:execute", "vector:read", "vector:write", "vectors:read", "workflows:delete", "workflows:execute", "workflows:read", "workflows:write", "workspaces:delete", "workspaces:read", "workspaces:write" ]; var MastraFGAPermissions = { /** View agent-to-agent communication */ A2A_READ: "a2a:read", /** Create and modify agent-to-agent communication */ A2A_WRITE: "a2a:write", /** Execute agent builder */ AGENT_BUILDER_EXECUTE: "agent-builder:execute", /** View agent builder */ AGENT_BUILDER_READ: "agent-builder:read", /** Create and modify agent builder */ AGENT_BUILDER_WRITE: "agent-builder:write", /** Execute agent controller sessions */ AGENT_CONTROLLER_EXECUTE: "agent-controller:execute", /** View agent controller sessions */ AGENT_CONTROLLER_READ: "agent-controller:read", /** Create agents */ AGENTS_CREATE: "agents:create", /** Delete agents */ AGENTS_DELETE: "agents:delete", /** Execute agents */ AGENTS_EXECUTE: "agents:execute", /** View agents */ AGENTS_READ: "agents:read", /** Create and modify agents */ AGENTS_WRITE: "agents:write", /** View auth */ AUTH_READ: "auth:read", /** View background tasks */ BACKGROUND_TASKS_READ: "background-tasks:read", /** View channels */ CHANNELS_READ: "channels:read", /** Create and modify channels */ CHANNELS_WRITE: "channels:write", /** Delete datasets */ DATASETS_DELETE: "datasets:delete", /** Execute datasets */ DATASETS_EXECUTE: "datasets:execute", /** View datasets */ DATASETS_READ: "datasets:read", /** Create and modify datasets */ DATASETS_WRITE: "datasets:write", /** View embedders */ EMBEDDERS_READ: "embedders:read", /** View experiments */ EXPERIMENTS_READ: "experiments:read", /** View infrastructure */ INFRASTRUCTURE_READ: "infrastructure:read", /** View logs */ LOGS_READ: "logs:read", /** Execute MCP servers */ MCP_EXECUTE: "mcp:execute", /** View MCP servers */ MCP_READ: "mcp:read", /** Create and modify MCP servers */ MCP_WRITE: "mcp:write", /** Delete memory and threads */ MEMORY_DELETE: "memory:delete", /** Execute memory and threads */ MEMORY_EXECUTE: "memory:execute", /** View memory and threads */ MEMORY_READ: "memory:read", /** Create and modify memory and threads */ MEMORY_WRITE: "memory:write", /** View traces and spans */ OBSERVABILITY_READ: "observability:read", /** Create and modify traces and spans */ OBSERVABILITY_WRITE: "observability:write", /** View processor-providers */ PROCESSOR_PROVIDERS_READ: "processor-providers:read", /** Execute processors */ PROCESSORS_EXECUTE: "processors:execute", /** View processors */ PROCESSORS_READ: "processors:read", /** Delete schedules */ SCHEDULES_DELETE: "schedules:delete", /** Execute schedules */ SCHEDULES_EXECUTE: "schedules:execute", /** View schedules */ SCHEDULES_READ: "schedules:read", /** Create and modify schedules */ SCHEDULES_WRITE: "schedules:write", /** View evaluation scores */ SCORES_READ: "scores:read", /** Create and modify evaluation scores */ SCORES_WRITE: "scores:write", /** Delete stored agents */ STORED_AGENTS_DELETE: "stored-agents:delete", /** Publish, activate, or restore stored agents */ STORED_AGENTS_PUBLISH: "stored-agents:publish", /** View stored agents */ STORED_AGENTS_READ: "stored-agents:read", /** Create and modify stored agents */ STORED_AGENTS_WRITE: "stored-agents:write", /** Delete stored MCP clients */ STORED_MCP_CLIENTS_DELETE: "stored-mcp-clients:delete", /** Publish, activate, or restore stored MCP clients */ STORED_MCP_CLIENTS_PUBLISH: "stored-mcp-clients:publish", /** View stored MCP clients */ STORED_MCP_CLIENTS_READ: "stored-mcp-clients:read", /** Create and modify stored MCP clients */ STORED_MCP_CLIENTS_WRITE: "stored-mcp-clients:write", /** Delete stored prompt blocks */ STORED_PROMPT_BLOCKS_DELETE: "stored-prompt-blocks:delete", /** Publish, activate, or restore stored prompt blocks */ STORED_PROMPT_BLOCKS_PUBLISH: "stored-prompt-blocks:publish", /** View stored prompt blocks */ STORED_PROMPT_BLOCKS_READ: "stored-prompt-blocks:read", /** Create and modify stored prompt blocks */ STORED_PROMPT_BLOCKS_WRITE: "stored-prompt-blocks:write", /** Delete stored scorers */ STORED_SCORERS_DELETE: "stored-scorers:delete", /** Publish, activate, or restore stored scorers */ STORED_SCORERS_PUBLISH: "stored-scorers:publish", /** View stored scorers */ STORED_SCORERS_READ: "stored-scorers:read", /** Create and modify stored scorers */ STORED_SCORERS_WRITE: "stored-scorers:write", /** Delete stored skills */ STORED_SKILLS_DELETE: "stored-skills:delete", /** Publish, activate, or restore stored skills */ STORED_SKILLS_PUBLISH: "stored-skills:publish", /** View stored skills */ STORED_SKILLS_READ: "stored-skills:read", /** Create and modify stored skills */ STORED_SKILLS_WRITE: "stored-skills:write", /** Delete stored workspaces */ STORED_WORKSPACES_DELETE: "stored-workspaces:delete", /** View stored workspaces */ STORED_WORKSPACES_READ: "stored-workspaces:read", /** Create and modify stored workspaces */ STORED_WORKSPACES_WRITE: "stored-workspaces:write", /** View system info */ SYSTEM_READ: "system:read", /** Delete tool-providers */ TOOL_PROVIDERS_DELETE: "tool-providers:delete", /** View tool-providers */ TOOL_PROVIDERS_READ: "tool-providers:read", /** Create and modify tool-providers */ TOOL_PROVIDERS_WRITE: "tool-providers:write", /** Execute tools */ TOOLS_EXECUTE: "tools:execute", /** View tools */ TOOLS_READ: "tools:read", /** Delete vector stores */ VECTOR_DELETE: "vector:delete", /** Execute vector stores */ VECTOR_EXECUTE: "vector:execute", /** View vector stores */ VECTOR_READ: "vector:read", /** Create and modify vector stores */ VECTOR_WRITE: "vector:write", /** View vectors */ VECTORS_READ: "vectors:read", /** Delete workflows */ WORKFLOWS_DELETE: "workflows:delete", /** Execute workflows */ WORKFLOWS_EXECUTE: "workflows:execute", /** View workflows */ WORKFLOWS_READ: "workflows:read", /** Create and modify workflows */ WORKFLOWS_WRITE: "workflows:write", /** Delete workspaces */ WORKSPACES_DELETE: "workspaces:delete", /** View workspaces */ WORKSPACES_READ: "workspaces:read", /** Create and modify workspaces */ WORKSPACES_WRITE: "workspaces:write" }; function isValidPermissionPattern(pattern) { return pattern in PERMISSION_PATTERNS; } function validatePermissions(permissions) { return permissions.every(isValidPermissionPattern); } function mergeFGAContext({ context, requestContext, metadata }) { const mergedContext = { ...context }; if (requestContext) { mergedContext.requestContext = requestContext; } if (metadata || context?.metadata) { mergedContext.metadata = { ...context?.metadata ?? {}, ...metadata ?? {} }; } return Object.keys(mergedContext).length > 0 ? mergedContext : void 0; } function isActorSignal(actor) { if (actor === true) { return true; } if (typeof actor !== "object" || actor === null) { return false; } const candidate = actor; return candidate.actorKind === "system" && (candidate.sourceWorkflow === void 0 || typeof candidate.sourceWorkflow === "string"); } function getAgentFGAResourceId(agentId) { return agentId; } function getWorkflowFGAResourceId(workflowId) { return workflowId; } function getStandaloneToolFGAResourceId(toolName) { return toolName; } function getAgentToolFGAResourceId(agentId, toolName) { return `${agentId}:${toolName}`; } function getMCPToolFGAResourceId(serverName, toolName) { return JSON.stringify([serverName, toolName]); } async function checkFGA(options) { await requireFGA(options); } async function requireFGA(options) { const { fgaProvider, user, resource, permission, context, requestContext, metadata, actor } = options; if (!fgaProvider) { return; } const fgaContext = mergeFGAContext({ context, requestContext, metadata }); const license = getSafeLicenseSummary(); if (isActorSignal(actor)) { const tenantOrganizationId = fgaContext?.requestContext?.get("organizationId"); if (typeof tenantOrganizationId !== "string" || tenantOrganizationId.length === 0) { throw new FGADeniedError(user, resource, permission, "trusted actor requires organizationId / tenant scope"); } const sourceWorkflow = (actor === true ? void 0 : actor.sourceWorkflow) ?? (typeof fgaContext?.metadata?.["sourceWorkflow"] === "string" ? fgaContext.metadata["sourceWorkflow"] : void 0); try { captureEEEvent("ee_feature_used", license.anonymousId || getEETelemetryFallbackDistinctId(), { feature: "fga", actor_kind: "system", resource_type: resource.type, resource_id: resource.id, permission, user_id: null, organization_membership_id: null, source_workflow: sourceWorkflow, license_valid: license.valid, license_hash: license.licenseHash, is_dev_environment: license.isDevEnvironment }); } catch { } return; } if (!user) { throw new FGADeniedError(user, resource, permission, "authenticated user is required"); } await fgaProvider.require( user, fgaContext ? { resource, permission, context: fgaContext } : { resource, permission } ); try { captureEEEvent("ee_feature_used", user?.id || license.anonymousId || getEETelemetryFallbackDistinctId(), { feature: "fga", actor_kind: "user", resource_type: resource.type, resource_id: resource.id, permission, user_id: user?.id ?? null, organization_membership_id: user?.organizationMembershipId ?? null, license_valid: license.valid, license_hash: license.licenseHash, is_dev_environment: license.isDevEnvironment }); } catch { } } var FGADeniedError = class extends Error { user; resource; permission; status; constructor(user, resource, permission, reason) { const userId = user?.id || user?.workosId || "unknown"; const permissionLabel = Array.isArray(permission) ? `any of [${permission.join(", ")}]` : permission; super( reason ? `FGA authorization denied: ${reason}` : `FGA authorization denied: user ${userId} cannot ${permissionLabel} on ${resource.type}:${resource.id}` ); this.name = "FGADeniedError"; this.user = user; this.resource = resource; this.permission = permission; this.status = 403; } }; var DEFAULT_ROLES = [ { id: "owner", name: "Owner", description: "Full access to all features and settings", permissions: ["*"] }, { id: "admin", name: "Admin", description: "Manage agents, workflows, and team members", permissions: [ "*:read", "*:write", "*:execute", "*:publish", "*:share" // Note: admins cannot delete resources ] }, { id: "member", name: "Member", description: "Execute agents and workflows", permissions: ["*:read", "*:execute"] }, { id: "viewer", name: "Viewer", description: "Read-only access", permissions: ["*:read"] } ]; function getDefaultRole(roleId) { return DEFAULT_ROLES.find((role) => role.id === roleId); } function resolvePermissions(roleIds, roles = DEFAULT_ROLES) { const permissions = /* @__PURE__ */ new Set(); const visited = /* @__PURE__ */ new Set(); function resolveRole(roleId) { if (visited.has(roleId)) return; visited.add(roleId); const role = roles.find((r) => r.id === roleId); if (!role) return; for (const permission of role.permissions) { permissions.add(permission); } if (role.inherits) { for (const inheritedRoleId of role.inherits) { resolveRole(inheritedRoleId); } } } for (const roleId of roleIds) { resolveRole(roleId); } return Array.from(permissions); } var RESOURCE_EXPANSIONS = { stored: [ "stored-agents", "stored-mcp-clients", "stored-prompt-blocks", "stored-scorers", "stored-skills", "stored-workspaces" ] }; function matchesPermission(userPermission, requiredPermission) { if (userPermission === "*") { return true; } const grantedParts = userPermission.split(":"); const requiredParts = requiredPermission.split(":"); const expandedFamilies = RESOURCE_EXPANSIONS[grantedParts[0] ?? ""]; if (expandedFamilies && expandedFamilies.includes(requiredParts[0] ?? "")) { const aliased = [requiredParts[0], ...grantedParts.slice(1)].join(":"); return matchesPermission(aliased, requiredPermission); } if (grantedParts.length < 2 || requiredParts.length < 2) { return userPermission === requiredPermission; } const [grantedResource, grantedAction, grantedId] = grantedParts; const [requiredResource, requiredAction, requiredId] = requiredParts; if (grantedResource === "*") { if (grantedAction === "*") { if (grantedId === void 0) { return true; } return grantedId === requiredId; } if (grantedAction !== requiredAction) { return false; } if (grantedId === void 0) { return true; } return grantedId === requiredId; } if (grantedResource !== requiredResource) { return false; } if (grantedAction === "*") { if (grantedId === void 0) { return true; } return grantedId === requiredId; } if (grantedAction !== requiredAction) { return false; } if (grantedId === void 0) { return true; } return grantedId === requiredId; } function hasPermission(userPermissions, requiredPermission) { return userPermissions.some((p) => matchesPermission(p, requiredPermission)); } function resolvePermissionsFromMapping(roles, mapping) { const permissions = /* @__PURE__ */ new Set(); const defaultPerms = mapping["_default"] ?? []; for (const role of roles) { const rolePerms = mapping[role]; if (rolePerms) { for (const perm of rolePerms) { permissions.add(perm); } } else { for (const perm of defaultPerms) { permissions.add(perm); } } } return Array.from(permissions); } var StaticRBACProvider = class { roles; _roleMapping; getUserRolesFn; permissionCache = /* @__PURE__ */ new Map(); /** Expose roleMapping for middleware access */ get roleMapping() { return this._roleMapping; } constructor(options) { if ("roles" in options && options.roles) { this.roles = options.roles; } if ("roleMapping" in options && options.roleMapping) { this._roleMapping = options.roleMapping; } this.getUserRolesFn = options.getUserRoles; } async getRoles(user) { const roleIds = await this.getUserRolesFn(user); return roleIds; } async hasRole(user, role) { const roles = await this.getRoles(user); return roles.includes(role); } async getPermissions(user) { const roleIds = await this.getRoles(user); const cacheKey = roleIds.sort().join(","); const cached = this.permissionCache.get(cacheKey); if (cached) return cached; let permissions; if (this._roleMapping) { permissions = resolvePermissionsFromMapping(roleIds, this._roleMapping); } else if (this.roles) { permissions = resolvePermissions(roleIds, this.roles); } else { permissions = []; } this.permissionCache.set(cacheKey, permissions); return permissions; } async hasPermission(user, permission) { const permissions = await this.getPermissions(user); return permissions.some((p) => matchesPermission(p, permission)); } async hasAllPermissions(user, permissions) { const userPermissions = await this.getPermissions(user); return permissions.every((required) => userPermissions.some((p) => matchesPermission(p, required))); } async hasAnyPermission(user, permissions) { const userPermissions = await this.getPermissions(user); return permissions.some((required) => userPermissions.some((p) => matchesPermission(p, required))); } /** * Clear the permission cache. */ clearCache() { this.permissionCache.clear(); } /** * Get all role definitions. * Only available when using role definitions mode (not role mapping). */ getRoleDefinitions() { return this.roles ?? []; } /** * Get a specific role definition. * Only available when using role definitions mode (not role mapping). */ getRoleDefinition(roleId) { return this.roles?.find((r) => r.id === roleId); } /** * Get all available roles in the system. */ async getAvailableRoles() { if (this.roles) { return this.roles.map((r) => ({ id: r.id, name: r.name })); } if (this._roleMapping) { return Object.keys(this._roleMapping).filter((k) => k !== "_default").map((k) => ({ id: k, name: k })); } return []; } /** * Get the resolved permissions for a specific role. */ async getPermissionsForRole(roleId) { if (this._roleMapping) { return resolvePermissionsFromMapping([roleId], this._roleMapping); } if (this.roles) { return resolvePermissions([roleId], this.roles); } return []; } }; /** * EE Authentication Interfaces * * Enterprise interfaces for RBAC, ACL, and advanced authorization. * * @license Mastra Enterprise License - see ee/LICENSE * @packageDocumentation */ /** * FGA enforcement utility for checking fine-grained authorization. * * @license Mastra Enterprise License - see ee/LICENSE */ /** * RBAC provider implementations. * * @license Mastra Enterprise License - see ee/LICENSE */ /** * Default implementations for EE authentication. * * @license Mastra Enterprise License - see ee/LICENSE */ /** * @mastra/core/auth/ee * * Enterprise authentication capabilities for Mastra. * This code is licensed under the Mastra Enterprise License - see ee/LICENSE. * * @license Mastra Enterprise License - see ee/LICENSE * @packageDocumentation */ export { ACTIONS, DEFAULT_ROLES, FGADeniedError, MastraFGAPermissions, PERMISSIONS, PERMISSION_PATTERNS, RESOURCES, StaticRBACProvider, buildCapabilities, checkFGA, clearLicenseCache, getAgentFGAResourceId, getAgentToolFGAResourceId, getDefaultRole, getMCPToolFGAResourceId, getSafeLicenseSummary, getStandaloneToolFGAResourceId, getWorkflowFGAResourceId, hasPermission, isAuthenticated, isDevEnvironment, isEEEnabled, isEELicenseValid, isFeatureEnabled, isLicenseValid, isValidPermissionPattern, matchesPermission, requireFGA, resolvePermissions, resolvePermissionsFromMapping, startLicenseValidation, validateLicense, validatePermissions, warnIfDevEENeedsLicense }; //# sourceMappingURL=chunk-HIW7BSXS.js.map //# sourceMappingURL=chunk-HIW7BSXS.js.map