zudoku 0.82.3 → 0.82.4

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/dist/cli/cli.js CHANGED
@@ -134,7 +134,6 @@ var init_llms = __esm({
134
134
  });
135
135
 
136
136
  // src/cli/cli.ts
137
- import * as Sentry2 from "@sentry/node";
138
137
  import { hideBin } from "yargs/helpers";
139
138
  import yargs from "yargs/yargs";
140
139
 
@@ -3384,6 +3383,25 @@ var AuthenticationSchema = z7.discriminatedUnion("type", [
3384
3383
  authorizationParams: z7.record(z7.string(), z7.string()).optional(),
3385
3384
  forwardAuthorizationParams: z7.array(z7.string()).optional()
3386
3385
  }),
3386
+ z7.object({
3387
+ type: z7.literal("entra"),
3388
+ basePath: z7.string().optional(),
3389
+ clientId: z7.string(),
3390
+ // Tenant id or one of Entra's multi-tenant authorities
3391
+ // (common/organizations/consumers). Defaults to "common".
3392
+ tenantId: z7.string().optional(),
3393
+ // Full issuer override, e.g. for CIAM tenants on *.ciamlogin.com.
3394
+ issuer: z7.string().optional(),
3395
+ audience: z7.string().optional(),
3396
+ scopes: z7.array(z7.string()).optional(),
3397
+ redirectToAfterSignUp: z7.string().optional(),
3398
+ redirectToAfterSignIn: z7.string().optional(),
3399
+ redirectToAfterSignOut: z7.string().optional(),
3400
+ signUp: SignUpOpenIdSchema.optional(),
3401
+ disableSignUp: z7.boolean().optional(),
3402
+ authorizationParams: z7.record(z7.string(), z7.string()).optional(),
3403
+ forwardAuthorizationParams: z7.array(z7.string()).optional()
3404
+ }),
3387
3405
  z7.object({
3388
3406
  type: z7.literal("azureb2c"),
3389
3407
  basePath: z7.string().optional(),
@@ -3840,6 +3858,7 @@ async function loadZudokuConfig(configEnv, rootDir) {
3840
3858
  }
3841
3859
 
3842
3860
  // src/lib/authentication/providers/util.ts
3861
+ var getEntraIssuer = (config) => config.issuer ?? `https://login.microsoftonline.com/${config.tenantId ?? "common"}/v2.0`;
3843
3862
  var getClerkFrontendApi = (publishableKey) => {
3844
3863
  const parts = publishableKey.split("_");
3845
3864
  if (parts.length !== 3 || !parts[2]) {
@@ -3873,6 +3892,9 @@ var getIssuer = async (config) => {
3873
3892
  case "openid": {
3874
3893
  return config.authentication.issuer;
3875
3894
  }
3895
+ case "entra": {
3896
+ return getEntraIssuer(config.authentication);
3897
+ }
3876
3898
  case "supabase": {
3877
3899
  return config.authentication.supabaseUrl;
3878
3900
  }
@@ -8506,17 +8528,7 @@ var bundleSSREntry = async (options) => {
8506
8528
  };
8507
8529
 
8508
8530
  // src/cli/common/output.ts
8509
- import * as Sentry from "@sentry/node";
8510
8531
  import colors8 from "picocolors";
8511
-
8512
- // src/cli/common/constants.ts
8513
- var CLI_XDG_FOLDER_NAME = "zudoku";
8514
- var VERSION_CHECK_FILE = "version.json";
8515
- var SENTRY_DSN = void 0;
8516
- var MAX_WAIT_PENDING_TIME_MS = 1e3;
8517
- var POST_HOG_CAPTURE_KEY = void 0;
8518
-
8519
- // src/cli/common/output.ts
8520
8532
  function printDiagnosticsToConsole(message) {
8521
8533
  console.error(colors8.bold(colors8.blue(message)));
8522
8534
  }
@@ -8590,6 +8602,11 @@ async function build(argv) {
8590
8602
  // src/cli/common/analytics/lib.ts
8591
8603
  import { PostHog } from "posthog-node";
8592
8604
 
8605
+ // src/cli/common/constants.ts
8606
+ var CLI_XDG_FOLDER_NAME = "zudoku";
8607
+ var VERSION_CHECK_FILE = "version.json";
8608
+ var POST_HOG_CAPTURE_KEY = void 0;
8609
+
8593
8610
  // src/cli/common/machine-id/lib.ts
8594
8611
  import { execSync } from "node:child_process";
8595
8612
  import { createHash } from "node:crypto";
@@ -9402,12 +9419,6 @@ To fix, run:
9402
9419
  // src/cli/cli.ts
9403
9420
  process.env.ZUDOKU_ENV = process.env.ZUDOKU_INTERNAL_DEV ? "internal" : "module";
9404
9421
  var packageJson = getZudokuPackageJson();
9405
- if (SENTRY_DSN) {
9406
- Sentry2.init({
9407
- dsn: SENTRY_DSN,
9408
- release: packageJson?.version
9409
- });
9410
- }
9411
9422
  var cli = yargs(hideBin(process.argv)).option("zuplo", {
9412
9423
  type: "boolean",
9413
9424
  description: "Enable Zuplo mode",
@@ -9421,14 +9432,7 @@ var cli = yargs(hideBin(process.argv)).option("zuplo", {
9421
9432
  try {
9422
9433
  void warnIfOutdatedVersion(packageJson?.version);
9423
9434
  await cli.argv;
9424
- void Sentry2.close(MAX_WAIT_PENDING_TIME_MS).then(() => {
9425
- process.exit(0);
9426
- });
9427
- } catch (err) {
9428
- if (err instanceof Error) {
9429
- Sentry2.captureException(err);
9430
- }
9431
- throw err;
9432
9435
  } finally {
9433
9436
  await shutdownAnalytics();
9434
9437
  }
9438
+ process.exit();
@@ -2617,6 +2617,25 @@ var AuthenticationSchema = z4.discriminatedUnion("type", [
2617
2617
  authorizationParams: z4.record(z4.string(), z4.string()).optional(),
2618
2618
  forwardAuthorizationParams: z4.array(z4.string()).optional()
2619
2619
  }),
2620
+ z4.object({
2621
+ type: z4.literal("entra"),
2622
+ basePath: z4.string().optional(),
2623
+ clientId: z4.string(),
2624
+ // Tenant id or one of Entra's multi-tenant authorities
2625
+ // (common/organizations/consumers). Defaults to "common".
2626
+ tenantId: z4.string().optional(),
2627
+ // Full issuer override, e.g. for CIAM tenants on *.ciamlogin.com.
2628
+ issuer: z4.string().optional(),
2629
+ audience: z4.string().optional(),
2630
+ scopes: z4.array(z4.string()).optional(),
2631
+ redirectToAfterSignUp: z4.string().optional(),
2632
+ redirectToAfterSignIn: z4.string().optional(),
2633
+ redirectToAfterSignOut: z4.string().optional(),
2634
+ signUp: SignUpOpenIdSchema.optional(),
2635
+ disableSignUp: z4.boolean().optional(),
2636
+ authorizationParams: z4.record(z4.string(), z4.string()).optional(),
2637
+ forwardAuthorizationParams: z4.array(z4.string()).optional()
2638
+ }),
2620
2639
  z4.object({
2621
2640
  type: z4.literal("azureb2c"),
2622
2641
  basePath: z4.string().optional(),
@@ -22,3 +22,6 @@ export type FirebaseAuthenticationConfig = Extract<AuthenticationConfig, {
22
22
  export type AzureB2CAuthenticationConfig = Extract<AuthenticationConfig, {
23
23
  type: "azureb2c";
24
24
  }>;
25
+ export type EntraAuthenticationConfig = Extract<AuthenticationConfig, {
26
+ type: "entra";
27
+ }>;
@@ -248,6 +248,25 @@ declare const AuthenticationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
248
248
  disableSignUp: z.ZodOptional<z.ZodBoolean>;
249
249
  authorizationParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
250
250
  forwardAuthorizationParams: z.ZodOptional<z.ZodArray<z.ZodString>>;
251
+ }, z.core.$strip>, z.ZodObject<{
252
+ type: z.ZodLiteral<"entra">;
253
+ basePath: z.ZodOptional<z.ZodString>;
254
+ clientId: z.ZodString;
255
+ tenantId: z.ZodOptional<z.ZodString>;
256
+ issuer: z.ZodOptional<z.ZodString>;
257
+ audience: z.ZodOptional<z.ZodString>;
258
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
259
+ redirectToAfterSignUp: z.ZodOptional<z.ZodString>;
260
+ redirectToAfterSignIn: z.ZodOptional<z.ZodString>;
261
+ redirectToAfterSignOut: z.ZodOptional<z.ZodString>;
262
+ signUp: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
263
+ url: z.ZodString;
264
+ }, z.core.$strict>, z.ZodObject<{
265
+ authorizationParams: z.ZodRecord<z.ZodString, z.ZodString>;
266
+ }, z.core.$strict>]>>;
267
+ disableSignUp: z.ZodOptional<z.ZodBoolean>;
268
+ authorizationParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
269
+ forwardAuthorizationParams: z.ZodOptional<z.ZodArray<z.ZodString>>;
251
270
  }, z.core.$strip>, z.ZodObject<{
252
271
  type: z.ZodLiteral<"azureb2c">;
253
272
  basePath: z.ZodOptional<z.ZodString>;
@@ -7040,6 +7059,25 @@ export declare const ZudokuConfig: z.ZodObject<{
7040
7059
  disableSignUp: z.ZodOptional<z.ZodBoolean>;
7041
7060
  authorizationParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
7042
7061
  forwardAuthorizationParams: z.ZodOptional<z.ZodArray<z.ZodString>>;
7062
+ }, z.core.$strip>, z.ZodObject<{
7063
+ type: z.ZodLiteral<"entra">;
7064
+ basePath: z.ZodOptional<z.ZodString>;
7065
+ clientId: z.ZodString;
7066
+ tenantId: z.ZodOptional<z.ZodString>;
7067
+ issuer: z.ZodOptional<z.ZodString>;
7068
+ audience: z.ZodOptional<z.ZodString>;
7069
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
7070
+ redirectToAfterSignUp: z.ZodOptional<z.ZodString>;
7071
+ redirectToAfterSignIn: z.ZodOptional<z.ZodString>;
7072
+ redirectToAfterSignOut: z.ZodOptional<z.ZodString>;
7073
+ signUp: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
7074
+ url: z.ZodString;
7075
+ }, z.core.$strict>, z.ZodObject<{
7076
+ authorizationParams: z.ZodRecord<z.ZodString, z.ZodString>;
7077
+ }, z.core.$strict>]>>;
7078
+ disableSignUp: z.ZodOptional<z.ZodBoolean>;
7079
+ authorizationParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
7080
+ forwardAuthorizationParams: z.ZodOptional<z.ZodArray<z.ZodString>>;
7043
7081
  }, z.core.$strip>, z.ZodObject<{
7044
7082
  type: z.ZodLiteral<"azureb2c">;
7045
7083
  basePath: z.ZodOptional<z.ZodString>;
@@ -0,0 +1,13 @@
1
+ import type * as oauth from "oauth4webapi";
2
+ import type { EntraAuthenticationConfig } from "../../../config/config.js";
3
+ import type { AuthenticationPlugin, AuthenticationProviderInitializer } from "../authentication.js";
4
+ import type { UserProfile } from "../state.js";
5
+ import { OpenIDAuthenticationProvider } from "./openid.js";
6
+ export declare class EntraAuthenticationProvider extends OpenIDAuthenticationProvider implements AuthenticationPlugin {
7
+ constructor(config: EntraAuthenticationConfig);
8
+ protected getExpectedDiscoveryIssuer(issuerUrl: URL, response: Response): Promise<URL>;
9
+ protected resolveTokenIssuer(as: oauth.AuthorizationServer, response: Response): Promise<oauth.AuthorizationServer>;
10
+ protected buildUserProfile(userInfo: oauth.UserInfoResponse, claims: oauth.IDToken | undefined): UserProfile;
11
+ }
12
+ declare const entraAuth: AuthenticationProviderInitializer<EntraAuthenticationConfig>;
13
+ export default entraAuth;
@@ -3,6 +3,7 @@ import type { NavigateFunction } from "react-router";
3
3
  import type { OpenIDAuthenticationConfig } from "../../../config/config.js";
4
4
  import type { AuthActionContext, AuthActionOptions, AuthenticationPlugin, AuthenticationProviderInitializer, VerifyAccessTokenResult } from "../authentication.js";
5
5
  import { CoreAuthenticationPlugin } from "../AuthenticationPlugin.js";
6
+ import { type UserProfile } from "../state.js";
6
7
  export interface OpenIdProviderData {
7
8
  type: "openid" | undefined;
8
9
  accessToken: string;
@@ -48,6 +49,8 @@ export declare class OpenIDAuthenticationProvider extends CoreAuthenticationPlug
48
49
  [oauth.allowInsecureRequests]?: undefined;
49
50
  };
50
51
  protected getAuthServer(): Promise<oauth.AuthorizationServer>;
52
+ protected getExpectedDiscoveryIssuer(issuerUrl: URL, _response: Response): Promise<URL>;
53
+ protected resolveTokenIssuer(as: oauth.AuthorizationServer, _response: Response): Promise<oauth.AuthorizationServer>;
51
54
  protected setTokensFromResponse(response: oauth.TokenEndpointResponse): void;
52
55
  signUp({ navigate }: {
53
56
  navigate: NavigateFunction;
@@ -56,7 +59,7 @@ export declare class OpenIDAuthenticationProvider extends CoreAuthenticationPlug
56
59
  replace?: boolean;
57
60
  }): Promise<void>;
58
61
  signIn(_: AuthActionContext, { redirectTo, replace }: AuthActionOptions): Promise<void>;
59
- private buildUserProfile;
62
+ protected buildUserProfile(userInfo: oauth.UserInfoResponse, claims: oauth.IDToken | undefined): UserProfile;
60
63
  verifyAccessToken(token: string): Promise<VerifyAccessTokenResult>;
61
64
  refreshUserProfile(): Promise<boolean>;
62
65
  private authorize;
@@ -1,3 +1,7 @@
1
1
  import type { NavigateFunction } from "react-router";
2
2
  export declare const redirectToSignUpUrl: (url: string, navigate: NavigateFunction, replace?: boolean) => void;
3
+ export declare const getEntraIssuer: (config: {
4
+ issuer?: string;
5
+ tenantId?: string;
6
+ }) => string;
3
7
  export declare const getClerkFrontendApi: (publishableKey: string) => string;
@@ -0,0 +1,4 @@
1
+ export declare const McpClientLogo: ({ appId, className, }: {
2
+ appId: string;
3
+ className?: string;
4
+ }) => import("react").JSX.Element;
@@ -26,3 +26,6 @@ export declare const getCursorConfig: (name: string, mcpUrl: string, auth?: Auth
26
26
  export declare const getVscodeConfig: (name: string, mcpUrl: string, auth?: AuthHeader) => string;
27
27
  export declare const getCodexConfig: (name: string, mcpUrl: string, auth?: AuthHeader) => string;
28
28
  export declare const getGenericConfig: (name: string, mcpUrl: string, auth?: AuthHeader) => string;
29
+ export declare const getCursorDeepLink: (name: string, mcpUrl: string, auth?: AuthHeader) => string;
30
+ export declare const getVscodeDeepLink: (name: string, mcpUrl: string, auth?: AuthHeader) => string;
31
+ export declare const CLAUDE_CONNECTORS_URL = "https://claude.ai/customize/connectors?modal=add-custom-connector";
@@ -303,6 +303,23 @@ export interface FlatZudokuConfig {
303
303
  [k: string]: string
304
304
  }
305
305
  forwardAuthorizationParams?: string[]
306
+ } | {
307
+ type: "entra"
308
+ basePath?: string
309
+ clientId: string
310
+ tenantId?: string
311
+ issuer?: string
312
+ audience?: string
313
+ scopes?: string[]
314
+ redirectToAfterSignUp?: string
315
+ redirectToAfterSignIn?: string
316
+ redirectToAfterSignOut?: string
317
+ signUp?: _Schema13
318
+ disableSignUp?: boolean
319
+ authorizationParams?: {
320
+ [k: string]: string
321
+ }
322
+ forwardAuthorizationParams?: string[]
306
323
  } | {
307
324
  type: "azureb2c"
308
325
  basePath?: string
@@ -72,9 +72,9 @@ to integrate Azure AD with your Zudoku documentation site.
72
72
  export default {
73
73
  // ... other configuration
74
74
  authentication: {
75
- type: "openid",
75
+ type: "entra",
76
76
  clientId: "<your-application-client-id>",
77
- issuer: "https://login.microsoftonline.com/<your-tenant-id>/v2.0",
77
+ tenantId: "<your-tenant-id>",
78
78
  scopes: ["openid", "profile", "email"], // Optional: customize scopes
79
79
  },
80
80
  // ... other configuration
@@ -91,20 +91,21 @@ For single tenant (organization-only access):
91
91
 
92
92
  ```typescript
93
93
  authentication: {
94
- type: "openid",
94
+ type: "entra",
95
95
  clientId: "<your-application-client-id>",
96
- issuer: "https://login.microsoftonline.com/<your-tenant-id>/v2.0",
96
+ tenantId: "<your-tenant-id>",
97
97
  scopes: ["openid", "profile", "email"],
98
98
  }
99
99
  ```
100
100
 
101
- For multitenant (any Azure AD organization):
101
+ For multitenant (any Azure AD organization), use `tenantId: "common"` or `"organizations"` — this is
102
+ also the default if `tenantId` is omitted:
102
103
 
103
104
  ```typescript
104
105
  authentication: {
105
- type: "openid",
106
+ type: "entra",
106
107
  clientId: "<your-application-client-id>",
107
- issuer: "https://login.microsoftonline.com/common/v2.0",
108
+ tenantId: "common",
108
109
  scopes: ["openid", "profile", "email"],
109
110
  }
110
111
  ```
@@ -115,9 +116,9 @@ Request additional Microsoft Graph API scopes:
115
116
 
116
117
  ```typescript
117
118
  authentication: {
118
- type: "openid",
119
+ type: "entra",
119
120
  clientId: "<your-application-client-id>",
120
- issuer: "https://login.microsoftonline.com/<your-tenant-id>/v2.0",
121
+ tenantId: "<your-tenant-id>",
121
122
  scopes: [
122
123
  "openid",
123
124
  "profile",
@@ -136,7 +137,7 @@ Protect specific documentation routes using the `protectedRoutes` configuration:
136
137
  {
137
138
  // ... other configuration
138
139
  authentication: {
139
- type: "openid",
140
+ type: "entra",
140
141
  // ... Azure AD config
141
142
  },
142
143
  protectedRoutes: [
@@ -217,16 +218,17 @@ Azure AD provides rich user profile data through OpenID Connect:
217
218
  2. **Redirect URI Mismatch**: The redirect URI must exactly match one configured in Azure AD,
218
219
  including protocol and path.
219
220
 
220
- 3. **Tenant Access Issues**: For single-tenant apps, ensure users are from the correct tenant. For
221
- multi-tenant, verify the issuer URL uses "common" or "organizations".
221
+ 3. **Tenant Access Issues**: For single-tenant apps, ensure users are from the correct tenant and
222
+ `tenantId` is set to that tenant's GUID. For multi-tenant, use `tenantId: "common"` or
223
+ `"organizations"`.
222
224
 
223
225
  4. **Missing User Information**: Check that required API permissions are granted and admin consent
224
226
  is provided if needed.
225
227
 
226
- 5. **Token Validation Errors**: Ensure your issuer URL is correct and includes the `/v2.0` endpoint
227
- for the Microsoft identity platform.
228
+ 5. **Token Validation Errors**: Ensure your `tenantId` is correct. If you use a CIAM tenant
229
+ (`*.ciamlogin.com`), set the `issuer` option to override the default issuer instead.
228
230
 
229
- 6. **Authentication Not Working**: Verify your issuer URL and client ID are correct, and that your
231
+ 6. **Authentication Not Working**: Verify your `tenantId` and client ID are correct, and that your
230
232
  app registration is configured as a Single-page application (SPA) with the correct redirect URIs.
231
233
 
232
234
  ## Security Best Practices
@@ -15,8 +15,8 @@ authentication provider you use.
15
15
 
16
16
  ## Authentication Providers
17
17
 
18
- Zudoku supports Clerk, Auth0, Supabase, Firebase, Azure B2C, and any OpenID Connect provider
19
- (including Okta, Keycloak, Authentik, and PingFederate).
18
+ Zudoku supports Clerk, Auth0, Supabase, Firebase, Microsoft Entra ID, Azure B2C, and any OpenID
19
+ Connect provider (including Okta, Keycloak, Authentik, and PingFederate).
20
20
 
21
21
  Not seeing your authentication provider? [Let us know](https://github.com/zuplo/zudoku/issues)
22
22
 
@@ -99,6 +99,26 @@ providing your own array of scopes.
99
99
  For provider-specific guides (Okta, Keycloak, etc.), see the
100
100
  [OpenID Connect setup page](./authentication-openid.md).
101
101
 
102
+ ### Microsoft Entra ID
103
+
104
+ For Microsoft Entra ID (formerly Azure AD), you will need the `clientId` from your app registration
105
+ and your `tenantId`.
106
+
107
+ ```typescript
108
+ {
109
+ // ...
110
+ authentication: {
111
+ type: "entra",
112
+ clientId: "<your-application-client-id>",
113
+ tenantId: "<your-tenant-id>", // Or "common" for multitenant. Defaults to "common".
114
+ },
115
+ // ...
116
+ }
117
+ ```
118
+
119
+ For full setup instructions, see the
120
+ [Azure AD / Entra ID setup guide](./authentication-azure-ad.md).
121
+
102
122
  ### Firebase
103
123
 
104
124
  For Firebase authentication, you will need your Firebase project configuration. You can find this in
@@ -187,3 +187,29 @@ since they use a different interaction model.
187
187
  If you are using [Zuplo](https://zuplo.com) to host your API, the `x-mcp-server` extension is
188
188
  automatically added to POST operations that use the `mcpServerHandler`. No manual schema changes are
189
189
  needed. See the [Zuplo MCP documentation](https://zuplo.com/docs/handlers/mcp-server) for details.
190
+
191
+ The server name shown in the install snippets (for example `claude mcp add … 'MCP Server' …`) is
192
+ taken from the handler's `name` option — the same name your MCP server advertises to clients. Set it
193
+ to override the default `"MCP Server"` title:
194
+
195
+ ```json title="config/routes.oas.json (paths section)"
196
+ {
197
+ "/mcp": {
198
+ "post": {
199
+ "operationId": "mcpServerHandler",
200
+ "x-zuplo-route": {
201
+ "handler": {
202
+ "export": "mcpServerHandler",
203
+ "module": "$import(@zuplo/runtime)",
204
+ "options": {
205
+ "name": "Acme API",
206
+ "operations": [{ "file": "./config/routes.oas.json", "id": "get-users" }]
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+ ```
214
+
215
+ With this configuration the snippets read `claude mcp add --transport http 'Acme API' …`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zudoku",
3
- "version": "0.82.3",
3
+ "version": "0.82.4",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=20.19.0 <21.0.0 || >=22.12.0"
@@ -57,6 +57,10 @@
57
57
  "types": "./dist/declarations/lib/authentication/providers/openid.d.ts",
58
58
  "default": "./src/lib/authentication/providers/openid.tsx"
59
59
  },
60
+ "./auth/entra": {
61
+ "types": "./dist/declarations/lib/authentication/providers/entra.d.ts",
62
+ "default": "./src/lib/authentication/providers/entra.tsx"
63
+ },
60
64
  "./auth/supabase": {
61
65
  "types": "./dist/declarations/lib/authentication/providers/supabase.d.ts",
62
66
  "default": "./src/lib/authentication/providers/supabase.tsx"
@@ -173,13 +177,13 @@
173
177
  },
174
178
  "dependencies": {
175
179
  "@apidevtools/json-schema-ref-parser": "15.3.5",
176
- "@base-ui/react": "^1.4.1",
180
+ "@base-ui/react": "^1.6.0",
177
181
  "@envelop/core": "5.5.1",
178
182
  "@graphiql/toolkit": "0.12.1",
179
183
  "@graphql-typed-document-node/core": "3.2.0",
180
184
  "@hono/node-server": "2.0.8",
181
185
  "@lekoarts/rehype-meta-as-attributes": "3.0.3",
182
- "@mdx-js/mdx": "3.1.0",
186
+ "@mdx-js/mdx": "3.1.1",
183
187
  "@mdx-js/react": "3.1.1",
184
188
  "@mdx-js/rollup": "3.1.1",
185
189
  "@pothos/core": "4.12.0",
@@ -209,7 +213,6 @@
209
213
  "@radix-ui/react-visually-hidden": "1.2.4",
210
214
  "@scalar/openapi-parser": "0.28.4",
211
215
  "@scalar/snippetz": "0.9.11",
212
- "@sentry/node": "10.62.0",
213
216
  "@shikijs/langs": "4.2.0",
214
217
  "@shikijs/rehype": "4.2.0",
215
218
  "@shikijs/themes": "4.2.0",
@@ -220,8 +223,8 @@
220
223
  "@tanstack/react-query": "5.101.0",
221
224
  "@types/react": "19.2.17",
222
225
  "@types/react-dom": "19.2.3",
223
- "@vitejs/plugin-react": "6.0.2",
224
- "@x0k/json-schema-merge": "1.0.3",
226
+ "@vitejs/plugin-react": "6.0.3",
227
+ "@x0k/json-schema-merge": "1.0.4",
225
228
  "@unhead/react": "3.1.3",
226
229
  "@zuplo/mcp": "0.0.32",
227
230
  "bs58": "6.0.0",
@@ -250,7 +253,7 @@
250
253
  "json-schema-to-typescript-lite": "15.0.0",
251
254
  "loglevel": "1.9.2",
252
255
  "lucide-react": "1.16.0",
253
- "mdast-util-from-markdown": "2.0.2",
256
+ "mdast-util-from-markdown": "2.0.3",
254
257
  "mdast-util-mdx": "3.0.0",
255
258
  "mdast-util-mdx-jsx": "3.2.0",
256
259
  "micromark-extension-mdxjs": "3.0.0",
@@ -262,7 +265,7 @@
262
265
  "pagefind": "1.5.2",
263
266
  "picocolors": "1.1.1",
264
267
  "piscina": "5.2.0",
265
- "posthog-node": "5.36.2",
268
+ "posthog-node": "5.40.0",
266
269
  "quick-lru": "7.3.0",
267
270
  "react-error-boundary": "6.1.1",
268
271
  "react-hook-form": "7.76.1",
@@ -316,7 +319,7 @@
316
319
  "@types/yargs": "17.0.35",
317
320
  "@typescript/native-preview": "7.0.0-dev.20260624.1",
318
321
  "@vitest/coverage-v8": "4.1.9",
319
- "happy-dom": "20.10.2",
322
+ "happy-dom": "20.10.6",
320
323
  "oxc-parser": "^0.135.0",
321
324
  "react": "19.2.7",
322
325
  "react-dom": "19.2.7",
@@ -33,3 +33,7 @@ export type AzureB2CAuthenticationConfig = Extract<
33
33
  AuthenticationConfig,
34
34
  { type: "azureb2c" }
35
35
  >;
36
+ export type EntraAuthenticationConfig = Extract<
37
+ AuthenticationConfig,
38
+ { type: "entra" }
39
+ >;
@@ -486,6 +486,25 @@ const AuthenticationSchema = z.discriminatedUnion("type", [
486
486
  authorizationParams: z.record(z.string(), z.string()).optional(),
487
487
  forwardAuthorizationParams: z.array(z.string()).optional(),
488
488
  }),
489
+ z.object({
490
+ type: z.literal("entra"),
491
+ basePath: z.string().optional(),
492
+ clientId: z.string(),
493
+ // Tenant id or one of Entra's multi-tenant authorities
494
+ // (common/organizations/consumers). Defaults to "common".
495
+ tenantId: z.string().optional(),
496
+ // Full issuer override, e.g. for CIAM tenants on *.ciamlogin.com.
497
+ issuer: z.string().optional(),
498
+ audience: z.string().optional(),
499
+ scopes: z.array(z.string()).optional(),
500
+ redirectToAfterSignUp: z.string().optional(),
501
+ redirectToAfterSignIn: z.string().optional(),
502
+ redirectToAfterSignOut: z.string().optional(),
503
+ signUp: SignUpOpenIdSchema.optional(),
504
+ disableSignUp: z.boolean().optional(),
505
+ authorizationParams: z.record(z.string(), z.string()).optional(),
506
+ forwardAuthorizationParams: z.array(z.string()).optional(),
507
+ }),
489
508
  z.object({
490
509
  type: z.literal("azureb2c"),
491
510
  basePath: z.string().optional(),
@@ -1,5 +1,8 @@
1
1
  import type { ZudokuConfig } from "../../config/validators/ZudokuConfig.js";
2
- import { getClerkFrontendApi } from "../authentication/providers/util.js";
2
+ import {
3
+ getClerkFrontendApi,
4
+ getEntraIssuer,
5
+ } from "../authentication/providers/util.js";
3
6
 
4
7
  export const getIssuer = async (config: ZudokuConfig) => {
5
8
  switch (config.authentication?.type) {
@@ -12,6 +15,9 @@ export const getIssuer = async (config: ZudokuConfig) => {
12
15
  case "openid": {
13
16
  return config.authentication.issuer;
14
17
  }
18
+ case "entra": {
19
+ return getEntraIssuer(config.authentication);
20
+ }
15
21
  case "supabase": {
16
22
  return config.authentication.supabaseUrl;
17
23
  }