@mastra/auth-studio 0.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,27 @@
1
+ # @mastra/auth-studio
2
+
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added `@mastra/auth-studio` — an auth provider for deployed Mastra Studio instances that proxies authentication through the Mastra shared API. ([#13163](https://github.com/mastra-ai/mastra/pull/13163))
8
+
9
+ Deployed instances need no secrets — all WorkOS authentication is handled by the shared API. The package provides SSO login/callback flows, session management via sealed cookies, RBAC with organization-scoped permissions, and automatic forced account picker on deploy logins.
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [[`504fc8b`](https://github.com/mastra-ai/mastra/commit/504fc8b9d0ddab717577ad3bf9c95ea4bd5377bd), [`f9c150b`](https://github.com/mastra-ai/mastra/commit/f9c150b7595ad05ad9cc9a11098e2944361e8c22), [`88de7e8`](https://github.com/mastra-ai/mastra/commit/88de7e8dfe4b7e1951a9e441bb33136e705ce24e), [`edee4b3`](https://github.com/mastra-ai/mastra/commit/edee4b37dff0af515fc7cc0e8d71ee39e6a762f0), [`3790c75`](https://github.com/mastra-ai/mastra/commit/3790c7578cc6a47d854eb12d89e6b1912867fe29), [`e7a235b`](https://github.com/mastra-ai/mastra/commit/e7a235be6472e0c870ed6c791ddb17c492dc188b), [`d51d298`](https://github.com/mastra-ai/mastra/commit/d51d298953967aab1f58ec965b644d109214f085), [`6dbeeb9`](https://github.com/mastra-ai/mastra/commit/6dbeeb94a8b1eebb727300d1a98961f882180794), [`d5f0d8d`](https://github.com/mastra-ai/mastra/commit/d5f0d8d6a03e515ddaa9b5da19b7e44b8357b07b), [`09c3b18`](https://github.com/mastra-ai/mastra/commit/09c3b1802ff14e243a8a8baea327440bc8cc2e32), [`b896379`](https://github.com/mastra-ai/mastra/commit/b8963791c6afa79484645fcec596a201f936b9a2), [`85c84eb`](https://github.com/mastra-ai/mastra/commit/85c84ebb78aebfcba9d209c8e152b16d7a00cb71), [`a89272a`](https://github.com/mastra-ai/mastra/commit/a89272a5d71939b9fcd284e6a6dc1dd091a6bdcf), [`ee9c8df`](https://github.com/mastra-ai/mastra/commit/ee9c8df644f19d055af5f496bf4942705f5a47b7), [`77b4a25`](https://github.com/mastra-ai/mastra/commit/77b4a254e51907f8ff3a3ba95596a18e93ae4b35), [`276246e`](https://github.com/mastra-ai/mastra/commit/276246e0b9066a1ea48bbc70df84dbe528daaf99), [`08ecfdb`](https://github.com/mastra-ai/mastra/commit/08ecfdbdad6fb8285deef86a034bdf4a6047cfca), [`d5f628c`](https://github.com/mastra-ai/mastra/commit/d5f628ca86c6f6f3ff1035d52f635df32dd81cab), [`524c0f3`](https://github.com/mastra-ai/mastra/commit/524c0f3c434c3d9d18f66338dcef383d6161b59c), [`c18a0e9`](https://github.com/mastra-ai/mastra/commit/c18a0e9cef1e4ca004b2963d35e4cfc031971eac), [`4bd21ea`](https://github.com/mastra-ai/mastra/commit/4bd21ea43d44d0a0427414fc047577f9f0aa3bec), [`115a7a4`](https://github.com/mastra-ai/mastra/commit/115a7a47db5e9896fec12ae6507501adb9ec89bf), [`22a48ae`](https://github.com/mastra-ai/mastra/commit/22a48ae2513eb54d8d79dad361fddbca97a155e8), [`3c6ef79`](https://github.com/mastra-ai/mastra/commit/3c6ef798481e00d6d22563be2de98818fd4dd5e0), [`9311c17`](https://github.com/mastra-ai/mastra/commit/9311c17d7a0640d9c4da2e71b814dc67c57c6369), [`7edf78f`](https://github.com/mastra-ai/mastra/commit/7edf78f80422c43e84585f08ba11df0d4d0b73c5), [`1c4221c`](https://github.com/mastra-ai/mastra/commit/1c4221cf6032ec98d0e094d4ee11da3e48490d96), [`d25b9ea`](https://github.com/mastra-ai/mastra/commit/d25b9eabd400167255a97b690ffbc4ee4097ded5), [`fe1ce5c`](https://github.com/mastra-ai/mastra/commit/fe1ce5c9211c03d561606fda95cbfe7df1d9a9b5), [`b03c0e0`](https://github.com/mastra-ai/mastra/commit/b03c0e0389a799523929a458b0509c9e4244d562), [`0a8366b`](https://github.com/mastra-ai/mastra/commit/0a8366b0a692fcdde56c4d526e4cf03c502ae4ac), [`85664e9`](https://github.com/mastra-ai/mastra/commit/85664e9fd857320fbc245e301f764f45f66f32a3), [`bc79650`](https://github.com/mastra-ai/mastra/commit/bc796500c6e0334faa158a96077e3fb332274869), [`9257d01`](https://github.com/mastra-ai/mastra/commit/9257d01d1366d81f84c582fe02b5e200cf9621f4), [`3a3a59e`](https://github.com/mastra-ai/mastra/commit/3a3a59e8ffaa6a985fe3d9a126a3f5ade11a6724), [`3108d4e`](https://github.com/mastra-ai/mastra/commit/3108d4e649c9fddbf03253a6feeb388a5fa9fa5a), [`0c33b2c`](https://github.com/mastra-ai/mastra/commit/0c33b2c9db537f815e1c59e2c898ffce2e395a79), [`191e5bd`](https://github.com/mastra-ai/mastra/commit/191e5bd29b82f5bda35243945790da7bc7b695c2), [`f77cd94`](https://github.com/mastra-ai/mastra/commit/f77cd94c44eabed490384e7d19232a865e13214c), [`e8135c7`](https://github.com/mastra-ai/mastra/commit/e8135c7e300dac5040670eec7eab896ac6092e30), [`daca48f`](https://github.com/mastra-ai/mastra/commit/daca48f0fb17b7ae0b62a2ac40cf0e491b2fd0b7), [`257d14f`](https://github.com/mastra-ai/mastra/commit/257d14faca5931f2e4186fc165b6f0b1f915deee), [`352f25d`](https://github.com/mastra-ai/mastra/commit/352f25da316b24cdd5b410fd8dddf6a8b763da2a), [`93477d0`](https://github.com/mastra-ai/mastra/commit/93477d0769b8a13ea5ed73d508d967fb23eaeed9), [`31c78b3`](https://github.com/mastra-ai/mastra/commit/31c78b3eb28f58a8017f1dcc795c33214d87feac), [`0bc0720`](https://github.com/mastra-ai/mastra/commit/0bc07201095791858087cc56f353fcd65e87ab54), [`36516ac`](https://github.com/mastra-ai/mastra/commit/36516aca1021cbeb42e74751b46a2614101f37c8), [`e947652`](https://github.com/mastra-ai/mastra/commit/e9476527fdecb4449e54570e80dfaf8466901254), [`3c6ef79`](https://github.com/mastra-ai/mastra/commit/3c6ef798481e00d6d22563be2de98818fd4dd5e0), [`9257d01`](https://github.com/mastra-ai/mastra/commit/9257d01d1366d81f84c582fe02b5e200cf9621f4), [`ec248f6`](https://github.com/mastra-ai/mastra/commit/ec248f6b56e8a037c066c49b2178e2507471d988)]:
14
+ - @mastra/core@1.9.0
15
+
16
+ ## 1.1.0-alpha.0
17
+
18
+ ### Minor Changes
19
+
20
+ - Added `@mastra/auth-studio` — an auth provider for deployed Mastra Studio instances that proxies authentication through the Mastra shared API. ([#13163](https://github.com/mastra-ai/mastra/pull/13163))
21
+
22
+ Deployed instances need no secrets — all WorkOS authentication is handled by the shared API. The package provides SSO login/callback flows, session management via sealed cookies, RBAC with organization-scoped permissions, and automatic forced account picker on deploy logins.
23
+
24
+ ### Patch Changes
25
+
26
+ - Updated dependencies [[`504fc8b`](https://github.com/mastra-ai/mastra/commit/504fc8b9d0ddab717577ad3bf9c95ea4bd5377bd), [`f9c150b`](https://github.com/mastra-ai/mastra/commit/f9c150b7595ad05ad9cc9a11098e2944361e8c22), [`88de7e8`](https://github.com/mastra-ai/mastra/commit/88de7e8dfe4b7e1951a9e441bb33136e705ce24e), [`edee4b3`](https://github.com/mastra-ai/mastra/commit/edee4b37dff0af515fc7cc0e8d71ee39e6a762f0), [`3790c75`](https://github.com/mastra-ai/mastra/commit/3790c7578cc6a47d854eb12d89e6b1912867fe29), [`e7a235b`](https://github.com/mastra-ai/mastra/commit/e7a235be6472e0c870ed6c791ddb17c492dc188b), [`d51d298`](https://github.com/mastra-ai/mastra/commit/d51d298953967aab1f58ec965b644d109214f085), [`6dbeeb9`](https://github.com/mastra-ai/mastra/commit/6dbeeb94a8b1eebb727300d1a98961f882180794), [`d5f0d8d`](https://github.com/mastra-ai/mastra/commit/d5f0d8d6a03e515ddaa9b5da19b7e44b8357b07b), [`09c3b18`](https://github.com/mastra-ai/mastra/commit/09c3b1802ff14e243a8a8baea327440bc8cc2e32), [`b896379`](https://github.com/mastra-ai/mastra/commit/b8963791c6afa79484645fcec596a201f936b9a2), [`85c84eb`](https://github.com/mastra-ai/mastra/commit/85c84ebb78aebfcba9d209c8e152b16d7a00cb71), [`a89272a`](https://github.com/mastra-ai/mastra/commit/a89272a5d71939b9fcd284e6a6dc1dd091a6bdcf), [`ee9c8df`](https://github.com/mastra-ai/mastra/commit/ee9c8df644f19d055af5f496bf4942705f5a47b7), [`77b4a25`](https://github.com/mastra-ai/mastra/commit/77b4a254e51907f8ff3a3ba95596a18e93ae4b35), [`276246e`](https://github.com/mastra-ai/mastra/commit/276246e0b9066a1ea48bbc70df84dbe528daaf99), [`08ecfdb`](https://github.com/mastra-ai/mastra/commit/08ecfdbdad6fb8285deef86a034bdf4a6047cfca), [`d5f628c`](https://github.com/mastra-ai/mastra/commit/d5f628ca86c6f6f3ff1035d52f635df32dd81cab), [`524c0f3`](https://github.com/mastra-ai/mastra/commit/524c0f3c434c3d9d18f66338dcef383d6161b59c), [`c18a0e9`](https://github.com/mastra-ai/mastra/commit/c18a0e9cef1e4ca004b2963d35e4cfc031971eac), [`4bd21ea`](https://github.com/mastra-ai/mastra/commit/4bd21ea43d44d0a0427414fc047577f9f0aa3bec), [`115a7a4`](https://github.com/mastra-ai/mastra/commit/115a7a47db5e9896fec12ae6507501adb9ec89bf), [`22a48ae`](https://github.com/mastra-ai/mastra/commit/22a48ae2513eb54d8d79dad361fddbca97a155e8), [`3c6ef79`](https://github.com/mastra-ai/mastra/commit/3c6ef798481e00d6d22563be2de98818fd4dd5e0), [`9311c17`](https://github.com/mastra-ai/mastra/commit/9311c17d7a0640d9c4da2e71b814dc67c57c6369), [`7edf78f`](https://github.com/mastra-ai/mastra/commit/7edf78f80422c43e84585f08ba11df0d4d0b73c5), [`1c4221c`](https://github.com/mastra-ai/mastra/commit/1c4221cf6032ec98d0e094d4ee11da3e48490d96), [`d25b9ea`](https://github.com/mastra-ai/mastra/commit/d25b9eabd400167255a97b690ffbc4ee4097ded5), [`fe1ce5c`](https://github.com/mastra-ai/mastra/commit/fe1ce5c9211c03d561606fda95cbfe7df1d9a9b5), [`b03c0e0`](https://github.com/mastra-ai/mastra/commit/b03c0e0389a799523929a458b0509c9e4244d562), [`0a8366b`](https://github.com/mastra-ai/mastra/commit/0a8366b0a692fcdde56c4d526e4cf03c502ae4ac), [`85664e9`](https://github.com/mastra-ai/mastra/commit/85664e9fd857320fbc245e301f764f45f66f32a3), [`bc79650`](https://github.com/mastra-ai/mastra/commit/bc796500c6e0334faa158a96077e3fb332274869), [`9257d01`](https://github.com/mastra-ai/mastra/commit/9257d01d1366d81f84c582fe02b5e200cf9621f4), [`3a3a59e`](https://github.com/mastra-ai/mastra/commit/3a3a59e8ffaa6a985fe3d9a126a3f5ade11a6724), [`3108d4e`](https://github.com/mastra-ai/mastra/commit/3108d4e649c9fddbf03253a6feeb388a5fa9fa5a), [`0c33b2c`](https://github.com/mastra-ai/mastra/commit/0c33b2c9db537f815e1c59e2c898ffce2e395a79), [`191e5bd`](https://github.com/mastra-ai/mastra/commit/191e5bd29b82f5bda35243945790da7bc7b695c2), [`f77cd94`](https://github.com/mastra-ai/mastra/commit/f77cd94c44eabed490384e7d19232a865e13214c), [`e8135c7`](https://github.com/mastra-ai/mastra/commit/e8135c7e300dac5040670eec7eab896ac6092e30), [`daca48f`](https://github.com/mastra-ai/mastra/commit/daca48f0fb17b7ae0b62a2ac40cf0e491b2fd0b7), [`257d14f`](https://github.com/mastra-ai/mastra/commit/257d14faca5931f2e4186fc165b6f0b1f915deee), [`352f25d`](https://github.com/mastra-ai/mastra/commit/352f25da316b24cdd5b410fd8dddf6a8b763da2a), [`93477d0`](https://github.com/mastra-ai/mastra/commit/93477d0769b8a13ea5ed73d508d967fb23eaeed9), [`31c78b3`](https://github.com/mastra-ai/mastra/commit/31c78b3eb28f58a8017f1dcc795c33214d87feac), [`0bc0720`](https://github.com/mastra-ai/mastra/commit/0bc07201095791858087cc56f353fcd65e87ab54), [`36516ac`](https://github.com/mastra-ai/mastra/commit/36516aca1021cbeb42e74751b46a2614101f37c8), [`e947652`](https://github.com/mastra-ai/mastra/commit/e9476527fdecb4449e54570e80dfaf8466901254), [`3c6ef79`](https://github.com/mastra-ai/mastra/commit/3c6ef798481e00d6d22563be2de98818fd4dd5e0), [`9257d01`](https://github.com/mastra-ai/mastra/commit/9257d01d1366d81f84c582fe02b5e200cf9621f4), [`ec248f6`](https://github.com/mastra-ai/mastra/commit/ec248f6b56e8a037c066c49b2178e2507471d988)]:
27
+ - @mastra/core@1.9.0-alpha.0
package/LICENSE.md ADDED
@@ -0,0 +1,30 @@
1
+ Portions of this software are licensed as follows:
2
+
3
+ - All content that resides under any directory named "ee/" within this
4
+ repository, including but not limited to:
5
+ - `packages/core/src/auth/ee/`
6
+ - `packages/server/src/server/auth/ee/`
7
+ is licensed under the license defined in `ee/LICENSE`.
8
+
9
+ - All third-party components incorporated into the Mastra Software are
10
+ licensed under the original license provided by the owner of the
11
+ applicable component.
12
+
13
+ - Content outside of the above-mentioned directories or restrictions is
14
+ available under the "Apache License 2.0" as defined below.
15
+
16
+ # Apache License 2.0
17
+
18
+ Copyright (c) 2025 Kepler Software, Inc.
19
+
20
+ Licensed under the Apache License, Version 2.0 (the "License");
21
+ you may not use this file except in compliance with the License.
22
+ You may obtain a copy of the License at
23
+
24
+ http://www.apache.org/licenses/LICENSE-2.0
25
+
26
+ Unless required by applicable law or agreed to in writing, software
27
+ distributed under the License is distributed on an "AS IS" BASIS,
28
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29
+ See the License for the specific language governing permissions and
30
+ limitations under the License.
package/dist/index.cjs ADDED
@@ -0,0 +1,292 @@
1
+ 'use strict';
2
+
3
+ var ee = require('@mastra/core/auth/ee');
4
+ var server = require('@mastra/core/server');
5
+
6
+ // src/index.ts
7
+ var COOKIE_NAME = "wos-session";
8
+ var MastraAuthStudio = class extends server.MastraAuthProvider {
9
+ isMastraCloudAuth = true;
10
+ sharedApiUrl;
11
+ organizationId;
12
+ useProductionCookies;
13
+ constructor(options) {
14
+ super({ name: "mastra-studio", ...options });
15
+ this.sharedApiUrl = options?.sharedApiUrl || process.env.MASTRA_SHARED_API_URL || "http://localhost:3010/v1";
16
+ this.organizationId = options?.organizationId || process.env.MASTRA_ORGANIZATION_ID;
17
+ if (this.sharedApiUrl.endsWith("/")) {
18
+ this.sharedApiUrl = this.sharedApiUrl.slice(0, -1);
19
+ }
20
+ this.useProductionCookies = this.sharedApiUrl.includes(".mastra.ai");
21
+ if (options) {
22
+ this.registerOptions(options);
23
+ }
24
+ }
25
+ // ---------------------------------------------------------------------------
26
+ // MastraAuthProvider abstract methods
27
+ // ---------------------------------------------------------------------------
28
+ /**
29
+ * Authenticate an incoming request by forwarding the sealed session cookie
30
+ * to the shared API's /auth/me endpoint, or a Bearer token to /auth/verify.
31
+ */
32
+ async authenticateToken(token, request) {
33
+ let user = null;
34
+ const cookieHeader = request?.headers?.get("Cookie");
35
+ const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);
36
+ if (sessionCookie) {
37
+ user = await this.verifySessionCookie(sessionCookie);
38
+ }
39
+ if (!user && token) {
40
+ user = await this.verifyBearerToken(token);
41
+ }
42
+ if (!user) return null;
43
+ if (this.organizationId && user.organizationId !== this.organizationId) {
44
+ return null;
45
+ }
46
+ return user;
47
+ }
48
+ authorizeUser(user) {
49
+ return !!user?.id;
50
+ }
51
+ // ---------------------------------------------------------------------------
52
+ // ISSOProvider
53
+ // ---------------------------------------------------------------------------
54
+ getLoginUrl(redirectUri, state) {
55
+ let postLoginRedirect = "/";
56
+ if (state) {
57
+ const pipeIndex = state.indexOf("|");
58
+ if (pipeIndex !== -1) {
59
+ try {
60
+ postLoginRedirect = decodeURIComponent(state.slice(pipeIndex + 1));
61
+ } catch {
62
+ }
63
+ }
64
+ }
65
+ const params = new URLSearchParams({
66
+ product: "deploy",
67
+ redirect_uri: redirectUri,
68
+ post_login_redirect: postLoginRedirect,
69
+ // Force re-authentication so AuthKit always shows the account picker
70
+ prompt: "login",
71
+ ...this.organizationId ? { organization_id: this.organizationId } : {}
72
+ });
73
+ return `${this.sharedApiUrl}/auth/login?${params.toString()}`;
74
+ }
75
+ async handleCallback(code, _state) {
76
+ const user = await this.verifySessionCookie(code);
77
+ if (!user) {
78
+ throw new Error("Session validation failed");
79
+ }
80
+ return {
81
+ user,
82
+ tokens: {
83
+ accessToken: code
84
+ }
85
+ };
86
+ }
87
+ setCallbackCookieHeader(_cookieHeader) {
88
+ }
89
+ getLoginCookies() {
90
+ return void 0;
91
+ }
92
+ getLoginButtonConfig() {
93
+ return {
94
+ provider: "mastra-studio",
95
+ text: "Sign in with Mastra"
96
+ };
97
+ }
98
+ async getLogoutUrl(_redirectUri, request) {
99
+ const cookieHeader = request?.headers.get("Cookie");
100
+ const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);
101
+ if (!sessionCookie) return null;
102
+ try {
103
+ const res = await fetch(`${this.sharedApiUrl}/auth/logout`, {
104
+ method: "POST",
105
+ headers: {
106
+ "Content-Type": "application/json",
107
+ Cookie: `${COOKIE_NAME}=${sessionCookie}`
108
+ }
109
+ });
110
+ if (res.ok) {
111
+ const data = await res.json();
112
+ return data.logoutUrl ?? null;
113
+ }
114
+ } catch {
115
+ }
116
+ return null;
117
+ }
118
+ // ---------------------------------------------------------------------------
119
+ // ISessionProvider
120
+ // ---------------------------------------------------------------------------
121
+ async createSession(userId, metadata) {
122
+ const now = /* @__PURE__ */ new Date();
123
+ return {
124
+ id: metadata?.accessToken || crypto.randomUUID(),
125
+ userId,
126
+ expiresAt: new Date(now.getTime() + 24 * 60 * 60 * 1e3),
127
+ // 24 hours
128
+ createdAt: now,
129
+ metadata
130
+ };
131
+ }
132
+ async validateSession(sessionId) {
133
+ const user = await this.verifySessionCookie(sessionId);
134
+ if (!user) return null;
135
+ const now = /* @__PURE__ */ new Date();
136
+ return {
137
+ id: sessionId,
138
+ userId: user.id,
139
+ expiresAt: new Date(now.getTime() + 24 * 60 * 60 * 1e3),
140
+ createdAt: now
141
+ };
142
+ }
143
+ async destroySession(sessionId) {
144
+ try {
145
+ await fetch(`${this.sharedApiUrl}/auth/logout`, {
146
+ method: "POST",
147
+ headers: {
148
+ Cookie: `${COOKIE_NAME}=${sessionId}`
149
+ }
150
+ });
151
+ } catch {
152
+ }
153
+ }
154
+ async refreshSession(sessionId) {
155
+ return this.validateSession(sessionId);
156
+ }
157
+ getSessionIdFromRequest(request) {
158
+ const cookieHeader = request.headers.get("Cookie");
159
+ return parseCookie(cookieHeader, COOKIE_NAME);
160
+ }
161
+ getSessionHeaders(session) {
162
+ const parts = [`${COOKIE_NAME}=${session.id}`, "HttpOnly", "SameSite=Lax", "Path=/", "Max-Age=86400"];
163
+ if (this.useProductionCookies) {
164
+ parts.push("Secure");
165
+ parts.push("Domain=.mastra.ai");
166
+ }
167
+ return { "Set-Cookie": parts.join("; ") };
168
+ }
169
+ getClearSessionHeaders() {
170
+ const parts = [`${COOKIE_NAME}=`, "HttpOnly", "SameSite=Lax", "Path=/", "Max-Age=0"];
171
+ if (this.useProductionCookies) {
172
+ parts.push("Secure");
173
+ parts.push("Domain=.mastra.ai");
174
+ }
175
+ return { "Set-Cookie": parts.join("; ") };
176
+ }
177
+ // ---------------------------------------------------------------------------
178
+ // IUserProvider
179
+ // ---------------------------------------------------------------------------
180
+ async getCurrentUser(request) {
181
+ const cookieHeader = request.headers.get("Cookie");
182
+ const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);
183
+ if (sessionCookie) {
184
+ return this.verifySessionCookie(sessionCookie);
185
+ }
186
+ const authHeader = request.headers.get("Authorization");
187
+ if (authHeader?.startsWith("Bearer ")) {
188
+ return this.verifyBearerToken(authHeader.slice(7));
189
+ }
190
+ return null;
191
+ }
192
+ async getUser(_userId) {
193
+ return null;
194
+ }
195
+ // ---------------------------------------------------------------------------
196
+ // Internal helpers
197
+ // ---------------------------------------------------------------------------
198
+ /**
199
+ * Forward a sealed session cookie to the shared API's /auth/me endpoint
200
+ * to validate it and get user info.
201
+ */
202
+ async verifySessionCookie(sessionCookie) {
203
+ try {
204
+ const res = await fetch(`${this.sharedApiUrl}/auth/me`, {
205
+ headers: {
206
+ Cookie: `${COOKIE_NAME}=${sessionCookie}`
207
+ }
208
+ });
209
+ if (!res.ok) return null;
210
+ const data = await res.json();
211
+ return {
212
+ id: data.user.id,
213
+ email: data.user.email,
214
+ name: [data.user.firstName, data.user.lastName].filter(Boolean).join(" ") || void 0,
215
+ avatarUrl: data.user.profilePictureUrl,
216
+ organizationId: data.organizationId,
217
+ role: data.role,
218
+ permissions: data.permissions
219
+ };
220
+ } catch {
221
+ return null;
222
+ }
223
+ }
224
+ /**
225
+ * Forward a Bearer token to the shared API's /auth/verify endpoint
226
+ * to validate it and get user info (used for CLI tokens).
227
+ */
228
+ async verifyBearerToken(token) {
229
+ try {
230
+ const res = await fetch(`${this.sharedApiUrl}/auth/verify`, {
231
+ headers: {
232
+ Authorization: `Bearer ${token}`
233
+ }
234
+ });
235
+ if (!res.ok) return null;
236
+ const data = await res.json();
237
+ return {
238
+ id: data.user.id,
239
+ email: data.user.email,
240
+ name: [data.user.firstName, data.user.lastName].filter(Boolean).join(" ") || void 0,
241
+ organizationId: data.organizationId
242
+ };
243
+ } catch {
244
+ return null;
245
+ }
246
+ }
247
+ };
248
+ function parseCookie(cookieHeader, name) {
249
+ if (!cookieHeader) return null;
250
+ const match = cookieHeader.match(new RegExp(`${name}=([^;]+)`));
251
+ return match?.[1] ?? null;
252
+ }
253
+ var MastraRBACStudio = class {
254
+ options;
255
+ get roleMapping() {
256
+ return this.options.roleMapping;
257
+ }
258
+ constructor(options) {
259
+ this.options = options;
260
+ }
261
+ async getRoles(user) {
262
+ return user.role ? [user.role] : [];
263
+ }
264
+ async hasRole(user, role) {
265
+ const roles = await this.getRoles(user);
266
+ return roles.includes(role);
267
+ }
268
+ async getPermissions(user) {
269
+ const roles = await this.getRoles(user);
270
+ if (roles.length === 0) {
271
+ return this.options.roleMapping["_default"] ?? [];
272
+ }
273
+ return ee.resolvePermissionsFromMapping(roles, this.options.roleMapping);
274
+ }
275
+ async hasPermission(user, permission) {
276
+ const permissions = await this.getPermissions(user);
277
+ return permissions.some((p) => ee.matchesPermission(p, permission));
278
+ }
279
+ async hasAllPermissions(user, permissions) {
280
+ const userPermissions = await this.getPermissions(user);
281
+ return permissions.every((required) => userPermissions.some((p) => ee.matchesPermission(p, required)));
282
+ }
283
+ async hasAnyPermission(user, permissions) {
284
+ const userPermissions = await this.getPermissions(user);
285
+ return permissions.some((required) => userPermissions.some((p) => ee.matchesPermission(p, required)));
286
+ }
287
+ };
288
+
289
+ exports.MastraAuthStudio = MastraAuthStudio;
290
+ exports.MastraRBACStudio = MastraRBACStudio;
291
+ //# sourceMappingURL=index.cjs.map
292
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["MastraAuthProvider","resolvePermissionsFromMapping","matchesPermission"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n ISSOProvider,\n ISessionProvider,\n IUserProvider,\n Session,\n SSOCallbackResult,\n SSOLoginConfig,\n} from '@mastra/core/auth';\nimport type { EEUser, IRBACProvider, RoleMapping } from '@mastra/core/auth/ee';\nimport { resolvePermissionsFromMapping, matchesPermission } from '@mastra/core/auth/ee';\nimport { MastraAuthProvider } from '@mastra/core/server';\nimport type { MastraAuthProviderOptions } from '@mastra/core/server';\n\nexport interface StudioUser extends EEUser {\n id: string;\n email?: string;\n name?: string;\n avatarUrl?: string;\n organizationId?: string;\n role?: string;\n permissions?: string[];\n}\n\nexport interface MastraAuthStudioOptions extends MastraAuthProviderOptions<StudioUser> {\n /** Base URL of the Mastra shared API (e.g., https://api.mastra.ai/v1) */\n sharedApiUrl?: string;\n /** Organization ID that owns this deployed instance. Users not in this org are rejected. */\n organizationId?: string;\n}\n\nconst COOKIE_NAME = 'wos-session';\n\n/**\n * Auth provider for Mastra Studio deployed instances.\n *\n * Proxies all authentication through the shared API, keeping the\n * WorkOS API key safely in the shared API. Deployed instances only\n * need the shared API URL — no secrets required.\n *\n * The shared API's sealed session cookie (`wos-session`) is set with\n * `Domain=.mastra.ai` in production, so it's included in requests\n * to deployed instances and can be forwarded for validation.\n */\nexport class MastraAuthStudio\n extends MastraAuthProvider<StudioUser>\n implements ISSOProvider<StudioUser>, ISessionProvider<Session>, IUserProvider<StudioUser>\n{\n readonly isMastraCloudAuth = true;\n\n private sharedApiUrl: string;\n private organizationId: string | undefined;\n private useProductionCookies: boolean;\n\n constructor(options?: MastraAuthStudioOptions) {\n super({ name: 'mastra-studio', ...options });\n this.sharedApiUrl = options?.sharedApiUrl || process.env.MASTRA_SHARED_API_URL || 'http://localhost:3010/v1';\n this.organizationId = options?.organizationId || process.env.MASTRA_ORGANIZATION_ID;\n\n // Strip trailing slash\n if (this.sharedApiUrl.endsWith('/')) {\n this.sharedApiUrl = this.sharedApiUrl.slice(0, -1);\n }\n\n // Use production cookie settings (Secure + Domain=.mastra.ai) only when\n // the shared API is actually on .mastra.ai — NOT based on NODE_ENV which\n // may be 'production' even in local dev (e.g. mastra dev sets it).\n this.useProductionCookies = this.sharedApiUrl.includes('.mastra.ai');\n\n if (options) {\n this.registerOptions(options);\n }\n }\n\n // ---------------------------------------------------------------------------\n // MastraAuthProvider abstract methods\n // ---------------------------------------------------------------------------\n\n /**\n * Authenticate an incoming request by forwarding the sealed session cookie\n * to the shared API's /auth/me endpoint, or a Bearer token to /auth/verify.\n */\n async authenticateToken(token: string, request: any): Promise<StudioUser | null> {\n let user: StudioUser | null = null;\n\n // Try sealed session cookie first (browser flow)\n const cookieHeader = request?.headers?.get('Cookie');\n const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);\n\n if (sessionCookie) {\n user = await this.verifySessionCookie(sessionCookie);\n }\n\n // Fall back to Bearer token (CLI / API token flow)\n if (!user && token) {\n user = await this.verifyBearerToken(token);\n }\n\n if (!user) return null;\n\n // Org-scoping: if this instance belongs to a specific org, reject users not in that org\n if (this.organizationId && user.organizationId !== this.organizationId) {\n return null;\n }\n\n return user;\n }\n\n authorizeUser(user: StudioUser): boolean {\n return !!user?.id;\n }\n\n // ---------------------------------------------------------------------------\n // ISSOProvider\n // ---------------------------------------------------------------------------\n\n getLoginUrl(redirectUri: string, state: string): string {\n // Extract the post-login redirect from state (format: uuid|encodedPostLoginRedirect)\n let postLoginRedirect = '/';\n if (state) {\n const pipeIndex = state.indexOf('|');\n if (pipeIndex !== -1) {\n try {\n postLoginRedirect = decodeURIComponent(state.slice(pipeIndex + 1));\n } catch {\n // ignore decode errors\n }\n }\n }\n\n const params = new URLSearchParams({\n product: 'deploy',\n redirect_uri: redirectUri,\n post_login_redirect: postLoginRedirect,\n // Force re-authentication so AuthKit always shows the account picker\n prompt: 'login',\n ...(this.organizationId ? { organization_id: this.organizationId } : {}),\n });\n\n return `${this.sharedApiUrl}/auth/login?${params.toString()}`;\n }\n\n async handleCallback(code: string, _state: string): Promise<SSOCallbackResult<StudioUser>> {\n // The shared API already consumed the OAuth code and passes the sealed\n // session directly as the `code` parameter in the redirect to this callback.\n // Validate it to get user info.\n const user = await this.verifySessionCookie(code);\n if (!user) {\n throw new Error('Session validation failed');\n }\n\n // Omit `cookies` so the Mastra server fallback path calls\n // createSession() + getSessionHeaders() to build a cookie scoped to\n // the deployed instance's domain.\n return {\n user,\n tokens: {\n accessToken: code,\n },\n };\n }\n\n setCallbackCookieHeader(_cookieHeader: string | null): void {\n // No-op: we don't use PKCE cookies — the shared API handles the full OAuth flow\n }\n\n getLoginCookies(): string[] | undefined {\n // No PKCE cookies needed — shared API manages the OAuth state\n return undefined;\n }\n\n getLoginButtonConfig(): SSOLoginConfig {\n return {\n provider: 'mastra-studio',\n text: 'Sign in with Mastra',\n };\n }\n\n async getLogoutUrl(_redirectUri: string, request?: Request): Promise<string | null> {\n const cookieHeader = request?.headers.get('Cookie');\n const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);\n\n if (!sessionCookie) return null;\n\n try {\n const res = await fetch(`${this.sharedApiUrl}/auth/logout`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Cookie: `${COOKIE_NAME}=${sessionCookie}`,\n },\n });\n\n if (res.ok) {\n const data = (await res.json()) as { ok: boolean; logoutUrl?: string };\n return data.logoutUrl ?? null;\n }\n } catch {\n // Failed to get logout URL — return null\n }\n\n return null;\n }\n\n // ---------------------------------------------------------------------------\n // ISessionProvider\n // ---------------------------------------------------------------------------\n\n async createSession(userId: string, metadata?: Record<string, unknown>): Promise<Session> {\n const now = new Date();\n return {\n id: (metadata?.accessToken as string) || crypto.randomUUID(),\n userId,\n expiresAt: new Date(now.getTime() + 24 * 60 * 60 * 1000), // 24 hours\n createdAt: now,\n metadata,\n };\n }\n\n async validateSession(sessionId: string): Promise<Session | null> {\n const user = await this.verifySessionCookie(sessionId);\n if (!user) return null;\n\n const now = new Date();\n return {\n id: sessionId,\n userId: user.id,\n expiresAt: new Date(now.getTime() + 24 * 60 * 60 * 1000),\n createdAt: now,\n };\n }\n\n async destroySession(sessionId: string): Promise<void> {\n try {\n await fetch(`${this.sharedApiUrl}/auth/logout`, {\n method: 'POST',\n headers: {\n Cookie: `${COOKIE_NAME}=${sessionId}`,\n },\n });\n } catch {\n // Best effort\n }\n }\n\n async refreshSession(sessionId: string): Promise<Session | null> {\n return this.validateSession(sessionId);\n }\n\n getSessionIdFromRequest(request: Request): string | null {\n const cookieHeader = request.headers.get('Cookie');\n return parseCookie(cookieHeader, COOKIE_NAME);\n }\n\n getSessionHeaders(session: Session): Record<string, string> {\n const parts = [`${COOKIE_NAME}=${session.id}`, 'HttpOnly', 'SameSite=Lax', 'Path=/', 'Max-Age=86400'];\n if (this.useProductionCookies) {\n parts.push('Secure');\n parts.push('Domain=.mastra.ai');\n }\n return { 'Set-Cookie': parts.join('; ') };\n }\n\n getClearSessionHeaders(): Record<string, string> {\n const parts = [`${COOKIE_NAME}=`, 'HttpOnly', 'SameSite=Lax', 'Path=/', 'Max-Age=0'];\n if (this.useProductionCookies) {\n parts.push('Secure');\n parts.push('Domain=.mastra.ai');\n }\n return { 'Set-Cookie': parts.join('; ') };\n }\n\n // ---------------------------------------------------------------------------\n // IUserProvider\n // ---------------------------------------------------------------------------\n\n async getCurrentUser(request: Request): Promise<StudioUser | null> {\n const cookieHeader = request.headers.get('Cookie');\n const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);\n\n if (sessionCookie) {\n return this.verifySessionCookie(sessionCookie);\n }\n\n // Try bearer token\n const authHeader = request.headers.get('Authorization');\n if (authHeader?.startsWith('Bearer ')) {\n return this.verifyBearerToken(authHeader.slice(7));\n }\n\n return null;\n }\n\n async getUser(_userId: string): Promise<StudioUser | null> {\n // Cannot look up users by ID — only validate sessions\n return null;\n }\n\n // ---------------------------------------------------------------------------\n // Internal helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Forward a sealed session cookie to the shared API's /auth/me endpoint\n * to validate it and get user info.\n */\n private async verifySessionCookie(sessionCookie: string): Promise<StudioUser | null> {\n try {\n const res = await fetch(`${this.sharedApiUrl}/auth/me`, {\n headers: {\n Cookie: `${COOKIE_NAME}=${sessionCookie}`,\n },\n });\n\n if (!res.ok) return null;\n\n const data = (await res.json()) as {\n user: {\n id: string;\n email: string;\n firstName: string;\n lastName: string;\n profilePictureUrl?: string;\n };\n organizationId: string;\n role?: string;\n permissions?: string[];\n };\n\n return {\n id: data.user.id,\n email: data.user.email,\n name: [data.user.firstName, data.user.lastName].filter(Boolean).join(' ') || undefined,\n avatarUrl: data.user.profilePictureUrl,\n organizationId: data.organizationId,\n role: data.role,\n permissions: data.permissions,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Forward a Bearer token to the shared API's /auth/verify endpoint\n * to validate it and get user info (used for CLI tokens).\n */\n private async verifyBearerToken(token: string): Promise<StudioUser | null> {\n try {\n const res = await fetch(`${this.sharedApiUrl}/auth/verify`, {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n });\n\n if (!res.ok) return null;\n\n const data = (await res.json()) as {\n user: {\n id: string;\n email: string;\n firstName: string;\n lastName: string;\n };\n organizationId: string;\n };\n\n return {\n id: data.user.id,\n email: data.user.email,\n name: [data.user.firstName, data.user.lastName].filter(Boolean).join(' ') || undefined,\n organizationId: data.organizationId,\n };\n } catch {\n return null;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Cookie helpers\n// ---------------------------------------------------------------------------\n\nfunction parseCookie(cookieHeader: string | null | undefined, name: string): string | null {\n if (!cookieHeader) return null;\n const match = cookieHeader.match(new RegExp(`${name}=([^;]+)`));\n return match?.[1] ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// MastraRBACStudio — role-based permission provider for Studio auth\n// ---------------------------------------------------------------------------\n\nexport interface MastraRBACStudioOptions {\n /**\n * Mapping from role names to permission arrays.\n *\n * @example\n * ```typescript\n * {\n * admin: ['*'],\n * member: ['agents:read', 'workflows:*'],\n * viewer: ['agents:read', 'workflows:read'],\n * _default: [],\n * }\n * ```\n */\n roleMapping: RoleMapping;\n}\n\n/**\n * RBAC provider for Mastra Studio authentication.\n *\n * Maps user roles (from the shared API's /auth/me endpoint) to Mastra permissions\n * using a configurable role mapping.\n */\nexport class MastraRBACStudio implements IRBACProvider<StudioUser> {\n private options: MastraRBACStudioOptions;\n\n get roleMapping(): RoleMapping {\n return this.options.roleMapping;\n }\n\n constructor(options: MastraRBACStudioOptions) {\n this.options = options;\n }\n\n async getRoles(user: StudioUser): Promise<string[]> {\n return user.role ? [user.role] : [];\n }\n\n async hasRole(user: StudioUser, role: string): Promise<boolean> {\n const roles = await this.getRoles(user);\n return roles.includes(role);\n }\n\n async getPermissions(user: StudioUser): Promise<string[]> {\n const roles = await this.getRoles(user);\n if (roles.length === 0) {\n return this.options.roleMapping['_default'] ?? [];\n }\n return resolvePermissionsFromMapping(roles, this.options.roleMapping);\n }\n\n async hasPermission(user: StudioUser, permission: string): Promise<boolean> {\n const permissions = await this.getPermissions(user);\n return permissions.some(p => matchesPermission(p, permission));\n }\n\n async hasAllPermissions(user: StudioUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n return permissions.every(required => userPermissions.some(p => matchesPermission(p, required)));\n }\n\n async hasAnyPermission(user: StudioUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n return permissions.some(required => userPermissions.some(p => matchesPermission(p, required)));\n }\n}\n"]}
@@ -0,0 +1,102 @@
1
+ import type { ISSOProvider, ISessionProvider, IUserProvider, Session, SSOCallbackResult, SSOLoginConfig } from '@mastra/core/auth';
2
+ import type { EEUser, IRBACProvider, RoleMapping } from '@mastra/core/auth/ee';
3
+ import { MastraAuthProvider } from '@mastra/core/server';
4
+ import type { MastraAuthProviderOptions } from '@mastra/core/server';
5
+ export interface StudioUser extends EEUser {
6
+ id: string;
7
+ email?: string;
8
+ name?: string;
9
+ avatarUrl?: string;
10
+ organizationId?: string;
11
+ role?: string;
12
+ permissions?: string[];
13
+ }
14
+ export interface MastraAuthStudioOptions extends MastraAuthProviderOptions<StudioUser> {
15
+ /** Base URL of the Mastra shared API (e.g., https://api.mastra.ai/v1) */
16
+ sharedApiUrl?: string;
17
+ /** Organization ID that owns this deployed instance. Users not in this org are rejected. */
18
+ organizationId?: string;
19
+ }
20
+ /**
21
+ * Auth provider for Mastra Studio deployed instances.
22
+ *
23
+ * Proxies all authentication through the shared API, keeping the
24
+ * WorkOS API key safely in the shared API. Deployed instances only
25
+ * need the shared API URL — no secrets required.
26
+ *
27
+ * The shared API's sealed session cookie (`wos-session`) is set with
28
+ * `Domain=.mastra.ai` in production, so it's included in requests
29
+ * to deployed instances and can be forwarded for validation.
30
+ */
31
+ export declare class MastraAuthStudio extends MastraAuthProvider<StudioUser> implements ISSOProvider<StudioUser>, ISessionProvider<Session>, IUserProvider<StudioUser> {
32
+ readonly isMastraCloudAuth = true;
33
+ private sharedApiUrl;
34
+ private organizationId;
35
+ private useProductionCookies;
36
+ constructor(options?: MastraAuthStudioOptions);
37
+ /**
38
+ * Authenticate an incoming request by forwarding the sealed session cookie
39
+ * to the shared API's /auth/me endpoint, or a Bearer token to /auth/verify.
40
+ */
41
+ authenticateToken(token: string, request: any): Promise<StudioUser | null>;
42
+ authorizeUser(user: StudioUser): boolean;
43
+ getLoginUrl(redirectUri: string, state: string): string;
44
+ handleCallback(code: string, _state: string): Promise<SSOCallbackResult<StudioUser>>;
45
+ setCallbackCookieHeader(_cookieHeader: string | null): void;
46
+ getLoginCookies(): string[] | undefined;
47
+ getLoginButtonConfig(): SSOLoginConfig;
48
+ getLogoutUrl(_redirectUri: string, request?: Request): Promise<string | null>;
49
+ createSession(userId: string, metadata?: Record<string, unknown>): Promise<Session>;
50
+ validateSession(sessionId: string): Promise<Session | null>;
51
+ destroySession(sessionId: string): Promise<void>;
52
+ refreshSession(sessionId: string): Promise<Session | null>;
53
+ getSessionIdFromRequest(request: Request): string | null;
54
+ getSessionHeaders(session: Session): Record<string, string>;
55
+ getClearSessionHeaders(): Record<string, string>;
56
+ getCurrentUser(request: Request): Promise<StudioUser | null>;
57
+ getUser(_userId: string): Promise<StudioUser | null>;
58
+ /**
59
+ * Forward a sealed session cookie to the shared API's /auth/me endpoint
60
+ * to validate it and get user info.
61
+ */
62
+ private verifySessionCookie;
63
+ /**
64
+ * Forward a Bearer token to the shared API's /auth/verify endpoint
65
+ * to validate it and get user info (used for CLI tokens).
66
+ */
67
+ private verifyBearerToken;
68
+ }
69
+ export interface MastraRBACStudioOptions {
70
+ /**
71
+ * Mapping from role names to permission arrays.
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * {
76
+ * admin: ['*'],
77
+ * member: ['agents:read', 'workflows:*'],
78
+ * viewer: ['agents:read', 'workflows:read'],
79
+ * _default: [],
80
+ * }
81
+ * ```
82
+ */
83
+ roleMapping: RoleMapping;
84
+ }
85
+ /**
86
+ * RBAC provider for Mastra Studio authentication.
87
+ *
88
+ * Maps user roles (from the shared API's /auth/me endpoint) to Mastra permissions
89
+ * using a configurable role mapping.
90
+ */
91
+ export declare class MastraRBACStudio implements IRBACProvider<StudioUser> {
92
+ private options;
93
+ get roleMapping(): RoleMapping;
94
+ constructor(options: MastraRBACStudioOptions);
95
+ getRoles(user: StudioUser): Promise<string[]>;
96
+ hasRole(user: StudioUser, role: string): Promise<boolean>;
97
+ getPermissions(user: StudioUser): Promise<string[]>;
98
+ hasPermission(user: StudioUser, permission: string): Promise<boolean>;
99
+ hasAllPermissions(user: StudioUser, permissions: string[]): Promise<boolean>;
100
+ hasAnyPermission(user: StudioUser, permissions: string[]): Promise<boolean>;
101
+ }
102
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,289 @@
1
+ import { resolvePermissionsFromMapping, matchesPermission } from '@mastra/core/auth/ee';
2
+ import { MastraAuthProvider } from '@mastra/core/server';
3
+
4
+ // src/index.ts
5
+ var COOKIE_NAME = "wos-session";
6
+ var MastraAuthStudio = class extends MastraAuthProvider {
7
+ isMastraCloudAuth = true;
8
+ sharedApiUrl;
9
+ organizationId;
10
+ useProductionCookies;
11
+ constructor(options) {
12
+ super({ name: "mastra-studio", ...options });
13
+ this.sharedApiUrl = options?.sharedApiUrl || process.env.MASTRA_SHARED_API_URL || "http://localhost:3010/v1";
14
+ this.organizationId = options?.organizationId || process.env.MASTRA_ORGANIZATION_ID;
15
+ if (this.sharedApiUrl.endsWith("/")) {
16
+ this.sharedApiUrl = this.sharedApiUrl.slice(0, -1);
17
+ }
18
+ this.useProductionCookies = this.sharedApiUrl.includes(".mastra.ai");
19
+ if (options) {
20
+ this.registerOptions(options);
21
+ }
22
+ }
23
+ // ---------------------------------------------------------------------------
24
+ // MastraAuthProvider abstract methods
25
+ // ---------------------------------------------------------------------------
26
+ /**
27
+ * Authenticate an incoming request by forwarding the sealed session cookie
28
+ * to the shared API's /auth/me endpoint, or a Bearer token to /auth/verify.
29
+ */
30
+ async authenticateToken(token, request) {
31
+ let user = null;
32
+ const cookieHeader = request?.headers?.get("Cookie");
33
+ const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);
34
+ if (sessionCookie) {
35
+ user = await this.verifySessionCookie(sessionCookie);
36
+ }
37
+ if (!user && token) {
38
+ user = await this.verifyBearerToken(token);
39
+ }
40
+ if (!user) return null;
41
+ if (this.organizationId && user.organizationId !== this.organizationId) {
42
+ return null;
43
+ }
44
+ return user;
45
+ }
46
+ authorizeUser(user) {
47
+ return !!user?.id;
48
+ }
49
+ // ---------------------------------------------------------------------------
50
+ // ISSOProvider
51
+ // ---------------------------------------------------------------------------
52
+ getLoginUrl(redirectUri, state) {
53
+ let postLoginRedirect = "/";
54
+ if (state) {
55
+ const pipeIndex = state.indexOf("|");
56
+ if (pipeIndex !== -1) {
57
+ try {
58
+ postLoginRedirect = decodeURIComponent(state.slice(pipeIndex + 1));
59
+ } catch {
60
+ }
61
+ }
62
+ }
63
+ const params = new URLSearchParams({
64
+ product: "deploy",
65
+ redirect_uri: redirectUri,
66
+ post_login_redirect: postLoginRedirect,
67
+ // Force re-authentication so AuthKit always shows the account picker
68
+ prompt: "login",
69
+ ...this.organizationId ? { organization_id: this.organizationId } : {}
70
+ });
71
+ return `${this.sharedApiUrl}/auth/login?${params.toString()}`;
72
+ }
73
+ async handleCallback(code, _state) {
74
+ const user = await this.verifySessionCookie(code);
75
+ if (!user) {
76
+ throw new Error("Session validation failed");
77
+ }
78
+ return {
79
+ user,
80
+ tokens: {
81
+ accessToken: code
82
+ }
83
+ };
84
+ }
85
+ setCallbackCookieHeader(_cookieHeader) {
86
+ }
87
+ getLoginCookies() {
88
+ return void 0;
89
+ }
90
+ getLoginButtonConfig() {
91
+ return {
92
+ provider: "mastra-studio",
93
+ text: "Sign in with Mastra"
94
+ };
95
+ }
96
+ async getLogoutUrl(_redirectUri, request) {
97
+ const cookieHeader = request?.headers.get("Cookie");
98
+ const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);
99
+ if (!sessionCookie) return null;
100
+ try {
101
+ const res = await fetch(`${this.sharedApiUrl}/auth/logout`, {
102
+ method: "POST",
103
+ headers: {
104
+ "Content-Type": "application/json",
105
+ Cookie: `${COOKIE_NAME}=${sessionCookie}`
106
+ }
107
+ });
108
+ if (res.ok) {
109
+ const data = await res.json();
110
+ return data.logoutUrl ?? null;
111
+ }
112
+ } catch {
113
+ }
114
+ return null;
115
+ }
116
+ // ---------------------------------------------------------------------------
117
+ // ISessionProvider
118
+ // ---------------------------------------------------------------------------
119
+ async createSession(userId, metadata) {
120
+ const now = /* @__PURE__ */ new Date();
121
+ return {
122
+ id: metadata?.accessToken || crypto.randomUUID(),
123
+ userId,
124
+ expiresAt: new Date(now.getTime() + 24 * 60 * 60 * 1e3),
125
+ // 24 hours
126
+ createdAt: now,
127
+ metadata
128
+ };
129
+ }
130
+ async validateSession(sessionId) {
131
+ const user = await this.verifySessionCookie(sessionId);
132
+ if (!user) return null;
133
+ const now = /* @__PURE__ */ new Date();
134
+ return {
135
+ id: sessionId,
136
+ userId: user.id,
137
+ expiresAt: new Date(now.getTime() + 24 * 60 * 60 * 1e3),
138
+ createdAt: now
139
+ };
140
+ }
141
+ async destroySession(sessionId) {
142
+ try {
143
+ await fetch(`${this.sharedApiUrl}/auth/logout`, {
144
+ method: "POST",
145
+ headers: {
146
+ Cookie: `${COOKIE_NAME}=${sessionId}`
147
+ }
148
+ });
149
+ } catch {
150
+ }
151
+ }
152
+ async refreshSession(sessionId) {
153
+ return this.validateSession(sessionId);
154
+ }
155
+ getSessionIdFromRequest(request) {
156
+ const cookieHeader = request.headers.get("Cookie");
157
+ return parseCookie(cookieHeader, COOKIE_NAME);
158
+ }
159
+ getSessionHeaders(session) {
160
+ const parts = [`${COOKIE_NAME}=${session.id}`, "HttpOnly", "SameSite=Lax", "Path=/", "Max-Age=86400"];
161
+ if (this.useProductionCookies) {
162
+ parts.push("Secure");
163
+ parts.push("Domain=.mastra.ai");
164
+ }
165
+ return { "Set-Cookie": parts.join("; ") };
166
+ }
167
+ getClearSessionHeaders() {
168
+ const parts = [`${COOKIE_NAME}=`, "HttpOnly", "SameSite=Lax", "Path=/", "Max-Age=0"];
169
+ if (this.useProductionCookies) {
170
+ parts.push("Secure");
171
+ parts.push("Domain=.mastra.ai");
172
+ }
173
+ return { "Set-Cookie": parts.join("; ") };
174
+ }
175
+ // ---------------------------------------------------------------------------
176
+ // IUserProvider
177
+ // ---------------------------------------------------------------------------
178
+ async getCurrentUser(request) {
179
+ const cookieHeader = request.headers.get("Cookie");
180
+ const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);
181
+ if (sessionCookie) {
182
+ return this.verifySessionCookie(sessionCookie);
183
+ }
184
+ const authHeader = request.headers.get("Authorization");
185
+ if (authHeader?.startsWith("Bearer ")) {
186
+ return this.verifyBearerToken(authHeader.slice(7));
187
+ }
188
+ return null;
189
+ }
190
+ async getUser(_userId) {
191
+ return null;
192
+ }
193
+ // ---------------------------------------------------------------------------
194
+ // Internal helpers
195
+ // ---------------------------------------------------------------------------
196
+ /**
197
+ * Forward a sealed session cookie to the shared API's /auth/me endpoint
198
+ * to validate it and get user info.
199
+ */
200
+ async verifySessionCookie(sessionCookie) {
201
+ try {
202
+ const res = await fetch(`${this.sharedApiUrl}/auth/me`, {
203
+ headers: {
204
+ Cookie: `${COOKIE_NAME}=${sessionCookie}`
205
+ }
206
+ });
207
+ if (!res.ok) return null;
208
+ const data = await res.json();
209
+ return {
210
+ id: data.user.id,
211
+ email: data.user.email,
212
+ name: [data.user.firstName, data.user.lastName].filter(Boolean).join(" ") || void 0,
213
+ avatarUrl: data.user.profilePictureUrl,
214
+ organizationId: data.organizationId,
215
+ role: data.role,
216
+ permissions: data.permissions
217
+ };
218
+ } catch {
219
+ return null;
220
+ }
221
+ }
222
+ /**
223
+ * Forward a Bearer token to the shared API's /auth/verify endpoint
224
+ * to validate it and get user info (used for CLI tokens).
225
+ */
226
+ async verifyBearerToken(token) {
227
+ try {
228
+ const res = await fetch(`${this.sharedApiUrl}/auth/verify`, {
229
+ headers: {
230
+ Authorization: `Bearer ${token}`
231
+ }
232
+ });
233
+ if (!res.ok) return null;
234
+ const data = await res.json();
235
+ return {
236
+ id: data.user.id,
237
+ email: data.user.email,
238
+ name: [data.user.firstName, data.user.lastName].filter(Boolean).join(" ") || void 0,
239
+ organizationId: data.organizationId
240
+ };
241
+ } catch {
242
+ return null;
243
+ }
244
+ }
245
+ };
246
+ function parseCookie(cookieHeader, name) {
247
+ if (!cookieHeader) return null;
248
+ const match = cookieHeader.match(new RegExp(`${name}=([^;]+)`));
249
+ return match?.[1] ?? null;
250
+ }
251
+ var MastraRBACStudio = class {
252
+ options;
253
+ get roleMapping() {
254
+ return this.options.roleMapping;
255
+ }
256
+ constructor(options) {
257
+ this.options = options;
258
+ }
259
+ async getRoles(user) {
260
+ return user.role ? [user.role] : [];
261
+ }
262
+ async hasRole(user, role) {
263
+ const roles = await this.getRoles(user);
264
+ return roles.includes(role);
265
+ }
266
+ async getPermissions(user) {
267
+ const roles = await this.getRoles(user);
268
+ if (roles.length === 0) {
269
+ return this.options.roleMapping["_default"] ?? [];
270
+ }
271
+ return resolvePermissionsFromMapping(roles, this.options.roleMapping);
272
+ }
273
+ async hasPermission(user, permission) {
274
+ const permissions = await this.getPermissions(user);
275
+ return permissions.some((p) => matchesPermission(p, permission));
276
+ }
277
+ async hasAllPermissions(user, permissions) {
278
+ const userPermissions = await this.getPermissions(user);
279
+ return permissions.every((required) => userPermissions.some((p) => matchesPermission(p, required)));
280
+ }
281
+ async hasAnyPermission(user, permissions) {
282
+ const userPermissions = await this.getPermissions(user);
283
+ return permissions.some((required) => userPermissions.some((p) => matchesPermission(p, required)));
284
+ }
285
+ };
286
+
287
+ export { MastraAuthStudio, MastraRBACStudio };
288
+ //# sourceMappingURL=index.js.map
289
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n ISSOProvider,\n ISessionProvider,\n IUserProvider,\n Session,\n SSOCallbackResult,\n SSOLoginConfig,\n} from '@mastra/core/auth';\nimport type { EEUser, IRBACProvider, RoleMapping } from '@mastra/core/auth/ee';\nimport { resolvePermissionsFromMapping, matchesPermission } from '@mastra/core/auth/ee';\nimport { MastraAuthProvider } from '@mastra/core/server';\nimport type { MastraAuthProviderOptions } from '@mastra/core/server';\n\nexport interface StudioUser extends EEUser {\n id: string;\n email?: string;\n name?: string;\n avatarUrl?: string;\n organizationId?: string;\n role?: string;\n permissions?: string[];\n}\n\nexport interface MastraAuthStudioOptions extends MastraAuthProviderOptions<StudioUser> {\n /** Base URL of the Mastra shared API (e.g., https://api.mastra.ai/v1) */\n sharedApiUrl?: string;\n /** Organization ID that owns this deployed instance. Users not in this org are rejected. */\n organizationId?: string;\n}\n\nconst COOKIE_NAME = 'wos-session';\n\n/**\n * Auth provider for Mastra Studio deployed instances.\n *\n * Proxies all authentication through the shared API, keeping the\n * WorkOS API key safely in the shared API. Deployed instances only\n * need the shared API URL — no secrets required.\n *\n * The shared API's sealed session cookie (`wos-session`) is set with\n * `Domain=.mastra.ai` in production, so it's included in requests\n * to deployed instances and can be forwarded for validation.\n */\nexport class MastraAuthStudio\n extends MastraAuthProvider<StudioUser>\n implements ISSOProvider<StudioUser>, ISessionProvider<Session>, IUserProvider<StudioUser>\n{\n readonly isMastraCloudAuth = true;\n\n private sharedApiUrl: string;\n private organizationId: string | undefined;\n private useProductionCookies: boolean;\n\n constructor(options?: MastraAuthStudioOptions) {\n super({ name: 'mastra-studio', ...options });\n this.sharedApiUrl = options?.sharedApiUrl || process.env.MASTRA_SHARED_API_URL || 'http://localhost:3010/v1';\n this.organizationId = options?.organizationId || process.env.MASTRA_ORGANIZATION_ID;\n\n // Strip trailing slash\n if (this.sharedApiUrl.endsWith('/')) {\n this.sharedApiUrl = this.sharedApiUrl.slice(0, -1);\n }\n\n // Use production cookie settings (Secure + Domain=.mastra.ai) only when\n // the shared API is actually on .mastra.ai — NOT based on NODE_ENV which\n // may be 'production' even in local dev (e.g. mastra dev sets it).\n this.useProductionCookies = this.sharedApiUrl.includes('.mastra.ai');\n\n if (options) {\n this.registerOptions(options);\n }\n }\n\n // ---------------------------------------------------------------------------\n // MastraAuthProvider abstract methods\n // ---------------------------------------------------------------------------\n\n /**\n * Authenticate an incoming request by forwarding the sealed session cookie\n * to the shared API's /auth/me endpoint, or a Bearer token to /auth/verify.\n */\n async authenticateToken(token: string, request: any): Promise<StudioUser | null> {\n let user: StudioUser | null = null;\n\n // Try sealed session cookie first (browser flow)\n const cookieHeader = request?.headers?.get('Cookie');\n const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);\n\n if (sessionCookie) {\n user = await this.verifySessionCookie(sessionCookie);\n }\n\n // Fall back to Bearer token (CLI / API token flow)\n if (!user && token) {\n user = await this.verifyBearerToken(token);\n }\n\n if (!user) return null;\n\n // Org-scoping: if this instance belongs to a specific org, reject users not in that org\n if (this.organizationId && user.organizationId !== this.organizationId) {\n return null;\n }\n\n return user;\n }\n\n authorizeUser(user: StudioUser): boolean {\n return !!user?.id;\n }\n\n // ---------------------------------------------------------------------------\n // ISSOProvider\n // ---------------------------------------------------------------------------\n\n getLoginUrl(redirectUri: string, state: string): string {\n // Extract the post-login redirect from state (format: uuid|encodedPostLoginRedirect)\n let postLoginRedirect = '/';\n if (state) {\n const pipeIndex = state.indexOf('|');\n if (pipeIndex !== -1) {\n try {\n postLoginRedirect = decodeURIComponent(state.slice(pipeIndex + 1));\n } catch {\n // ignore decode errors\n }\n }\n }\n\n const params = new URLSearchParams({\n product: 'deploy',\n redirect_uri: redirectUri,\n post_login_redirect: postLoginRedirect,\n // Force re-authentication so AuthKit always shows the account picker\n prompt: 'login',\n ...(this.organizationId ? { organization_id: this.organizationId } : {}),\n });\n\n return `${this.sharedApiUrl}/auth/login?${params.toString()}`;\n }\n\n async handleCallback(code: string, _state: string): Promise<SSOCallbackResult<StudioUser>> {\n // The shared API already consumed the OAuth code and passes the sealed\n // session directly as the `code` parameter in the redirect to this callback.\n // Validate it to get user info.\n const user = await this.verifySessionCookie(code);\n if (!user) {\n throw new Error('Session validation failed');\n }\n\n // Omit `cookies` so the Mastra server fallback path calls\n // createSession() + getSessionHeaders() to build a cookie scoped to\n // the deployed instance's domain.\n return {\n user,\n tokens: {\n accessToken: code,\n },\n };\n }\n\n setCallbackCookieHeader(_cookieHeader: string | null): void {\n // No-op: we don't use PKCE cookies — the shared API handles the full OAuth flow\n }\n\n getLoginCookies(): string[] | undefined {\n // No PKCE cookies needed — shared API manages the OAuth state\n return undefined;\n }\n\n getLoginButtonConfig(): SSOLoginConfig {\n return {\n provider: 'mastra-studio',\n text: 'Sign in with Mastra',\n };\n }\n\n async getLogoutUrl(_redirectUri: string, request?: Request): Promise<string | null> {\n const cookieHeader = request?.headers.get('Cookie');\n const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);\n\n if (!sessionCookie) return null;\n\n try {\n const res = await fetch(`${this.sharedApiUrl}/auth/logout`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Cookie: `${COOKIE_NAME}=${sessionCookie}`,\n },\n });\n\n if (res.ok) {\n const data = (await res.json()) as { ok: boolean; logoutUrl?: string };\n return data.logoutUrl ?? null;\n }\n } catch {\n // Failed to get logout URL — return null\n }\n\n return null;\n }\n\n // ---------------------------------------------------------------------------\n // ISessionProvider\n // ---------------------------------------------------------------------------\n\n async createSession(userId: string, metadata?: Record<string, unknown>): Promise<Session> {\n const now = new Date();\n return {\n id: (metadata?.accessToken as string) || crypto.randomUUID(),\n userId,\n expiresAt: new Date(now.getTime() + 24 * 60 * 60 * 1000), // 24 hours\n createdAt: now,\n metadata,\n };\n }\n\n async validateSession(sessionId: string): Promise<Session | null> {\n const user = await this.verifySessionCookie(sessionId);\n if (!user) return null;\n\n const now = new Date();\n return {\n id: sessionId,\n userId: user.id,\n expiresAt: new Date(now.getTime() + 24 * 60 * 60 * 1000),\n createdAt: now,\n };\n }\n\n async destroySession(sessionId: string): Promise<void> {\n try {\n await fetch(`${this.sharedApiUrl}/auth/logout`, {\n method: 'POST',\n headers: {\n Cookie: `${COOKIE_NAME}=${sessionId}`,\n },\n });\n } catch {\n // Best effort\n }\n }\n\n async refreshSession(sessionId: string): Promise<Session | null> {\n return this.validateSession(sessionId);\n }\n\n getSessionIdFromRequest(request: Request): string | null {\n const cookieHeader = request.headers.get('Cookie');\n return parseCookie(cookieHeader, COOKIE_NAME);\n }\n\n getSessionHeaders(session: Session): Record<string, string> {\n const parts = [`${COOKIE_NAME}=${session.id}`, 'HttpOnly', 'SameSite=Lax', 'Path=/', 'Max-Age=86400'];\n if (this.useProductionCookies) {\n parts.push('Secure');\n parts.push('Domain=.mastra.ai');\n }\n return { 'Set-Cookie': parts.join('; ') };\n }\n\n getClearSessionHeaders(): Record<string, string> {\n const parts = [`${COOKIE_NAME}=`, 'HttpOnly', 'SameSite=Lax', 'Path=/', 'Max-Age=0'];\n if (this.useProductionCookies) {\n parts.push('Secure');\n parts.push('Domain=.mastra.ai');\n }\n return { 'Set-Cookie': parts.join('; ') };\n }\n\n // ---------------------------------------------------------------------------\n // IUserProvider\n // ---------------------------------------------------------------------------\n\n async getCurrentUser(request: Request): Promise<StudioUser | null> {\n const cookieHeader = request.headers.get('Cookie');\n const sessionCookie = parseCookie(cookieHeader, COOKIE_NAME);\n\n if (sessionCookie) {\n return this.verifySessionCookie(sessionCookie);\n }\n\n // Try bearer token\n const authHeader = request.headers.get('Authorization');\n if (authHeader?.startsWith('Bearer ')) {\n return this.verifyBearerToken(authHeader.slice(7));\n }\n\n return null;\n }\n\n async getUser(_userId: string): Promise<StudioUser | null> {\n // Cannot look up users by ID — only validate sessions\n return null;\n }\n\n // ---------------------------------------------------------------------------\n // Internal helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Forward a sealed session cookie to the shared API's /auth/me endpoint\n * to validate it and get user info.\n */\n private async verifySessionCookie(sessionCookie: string): Promise<StudioUser | null> {\n try {\n const res = await fetch(`${this.sharedApiUrl}/auth/me`, {\n headers: {\n Cookie: `${COOKIE_NAME}=${sessionCookie}`,\n },\n });\n\n if (!res.ok) return null;\n\n const data = (await res.json()) as {\n user: {\n id: string;\n email: string;\n firstName: string;\n lastName: string;\n profilePictureUrl?: string;\n };\n organizationId: string;\n role?: string;\n permissions?: string[];\n };\n\n return {\n id: data.user.id,\n email: data.user.email,\n name: [data.user.firstName, data.user.lastName].filter(Boolean).join(' ') || undefined,\n avatarUrl: data.user.profilePictureUrl,\n organizationId: data.organizationId,\n role: data.role,\n permissions: data.permissions,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Forward a Bearer token to the shared API's /auth/verify endpoint\n * to validate it and get user info (used for CLI tokens).\n */\n private async verifyBearerToken(token: string): Promise<StudioUser | null> {\n try {\n const res = await fetch(`${this.sharedApiUrl}/auth/verify`, {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n });\n\n if (!res.ok) return null;\n\n const data = (await res.json()) as {\n user: {\n id: string;\n email: string;\n firstName: string;\n lastName: string;\n };\n organizationId: string;\n };\n\n return {\n id: data.user.id,\n email: data.user.email,\n name: [data.user.firstName, data.user.lastName].filter(Boolean).join(' ') || undefined,\n organizationId: data.organizationId,\n };\n } catch {\n return null;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Cookie helpers\n// ---------------------------------------------------------------------------\n\nfunction parseCookie(cookieHeader: string | null | undefined, name: string): string | null {\n if (!cookieHeader) return null;\n const match = cookieHeader.match(new RegExp(`${name}=([^;]+)`));\n return match?.[1] ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// MastraRBACStudio — role-based permission provider for Studio auth\n// ---------------------------------------------------------------------------\n\nexport interface MastraRBACStudioOptions {\n /**\n * Mapping from role names to permission arrays.\n *\n * @example\n * ```typescript\n * {\n * admin: ['*'],\n * member: ['agents:read', 'workflows:*'],\n * viewer: ['agents:read', 'workflows:read'],\n * _default: [],\n * }\n * ```\n */\n roleMapping: RoleMapping;\n}\n\n/**\n * RBAC provider for Mastra Studio authentication.\n *\n * Maps user roles (from the shared API's /auth/me endpoint) to Mastra permissions\n * using a configurable role mapping.\n */\nexport class MastraRBACStudio implements IRBACProvider<StudioUser> {\n private options: MastraRBACStudioOptions;\n\n get roleMapping(): RoleMapping {\n return this.options.roleMapping;\n }\n\n constructor(options: MastraRBACStudioOptions) {\n this.options = options;\n }\n\n async getRoles(user: StudioUser): Promise<string[]> {\n return user.role ? [user.role] : [];\n }\n\n async hasRole(user: StudioUser, role: string): Promise<boolean> {\n const roles = await this.getRoles(user);\n return roles.includes(role);\n }\n\n async getPermissions(user: StudioUser): Promise<string[]> {\n const roles = await this.getRoles(user);\n if (roles.length === 0) {\n return this.options.roleMapping['_default'] ?? [];\n }\n return resolvePermissionsFromMapping(roles, this.options.roleMapping);\n }\n\n async hasPermission(user: StudioUser, permission: string): Promise<boolean> {\n const permissions = await this.getPermissions(user);\n return permissions.some(p => matchesPermission(p, permission));\n }\n\n async hasAllPermissions(user: StudioUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n return permissions.every(required => userPermissions.some(p => matchesPermission(p, required)));\n }\n\n async hasAnyPermission(user: StudioUser, permissions: string[]): Promise<boolean> {\n const userPermissions = await this.getPermissions(user);\n return permissions.some(required => userPermissions.some(p => matchesPermission(p, required)));\n }\n}\n"]}
package/package.json CHANGED
@@ -1,12 +1,60 @@
1
1
  {
2
2
  "name": "@mastra/auth-studio",
3
- "version": "0.0.0",
4
- "description": "Mastra Studio Auth integration",
3
+ "version": "1.1.0",
4
+ "description": "Mastra Studio Auth integration — proxies authentication through Mastra shared API",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.cjs"
17
+ }
18
+ },
19
+ "./package.json": "./package.json"
20
+ },
5
21
  "license": "Apache-2.0",
22
+ "dependencies": {},
23
+ "devDependencies": {
24
+ "@types/node": "22.19.7",
25
+ "@vitest/coverage-v8": "4.0.18",
26
+ "@vitest/ui": "4.0.18",
27
+ "eslint": "^9.37.0",
28
+ "tsup": "^8.5.1",
29
+ "typescript": "^5.9.3",
30
+ "vitest": "4.0.18",
31
+ "@internal/lint": "0.0.64",
32
+ "@internal/types-builder": "0.0.39",
33
+ "@mastra/core": "1.9.0"
34
+ },
35
+ "peerDependencies": {
36
+ "@mastra/core": ">=1.0.0-0 <2.0.0-0"
37
+ },
38
+ "files": [
39
+ "dist",
40
+ "CHANGELOG.md"
41
+ ],
6
42
  "homepage": "https://mastra.ai",
7
43
  "repository": {
8
44
  "type": "git",
9
45
  "url": "git+https://github.com/mastra-ai/mastra.git",
10
46
  "directory": "auth/studio"
47
+ },
48
+ "bugs": {
49
+ "url": "https://github.com/mastra-ai/mastra/issues"
50
+ },
51
+ "engines": {
52
+ "node": ">=22.13.0"
53
+ },
54
+ "scripts": {
55
+ "build": "tsup --silent --config tsup.config.ts",
56
+ "build:watch": "tsup --watch --silent --config tsup.config.ts",
57
+ "test": "vitest run",
58
+ "lint": "eslint ."
11
59
  }
12
- }
60
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # @mastra/auth-studio
2
-
3
- Mastra Studio Auth integration. Coming soon.