@logto/schemas 1.39.0 → 1.40.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.
Files changed (70) hide show
  1. package/alterations/1.40.0-1776516232-add-account-center-profile-fields.ts +20 -0
  2. package/alterations/1.40.0-1778318116-add-custom-ui-csp-to-sie.ts +20 -0
  3. package/alterations/1.40.0-1778500000-add-organization-user-relations-user-id-index.ts +41 -0
  4. package/alterations/1.40.0-1778500001-add-organization-role-user-relations-org-user-index.ts +43 -0
  5. package/alterations/1.40.0-1779421396-add-application-access-control-schema.ts +90 -0
  6. package/alterations-js/1.40.0-1776516232-add-account-center-profile-fields.js +16 -0
  7. package/alterations-js/1.40.0-1778318116-add-custom-ui-csp-to-sie.js +16 -0
  8. package/alterations-js/1.40.0-1778500000-add-organization-user-relations-user-id-index.js +37 -0
  9. package/alterations-js/1.40.0-1778500001-add-organization-role-user-relations-org-user-index.js +39 -0
  10. package/alterations-js/1.40.0-1779421396-add-application-access-control-schema.js +82 -0
  11. package/lib/consts/application.d.ts +1 -0
  12. package/lib/consts/application.js +1 -0
  13. package/lib/consts/index.d.ts +1 -0
  14. package/lib/consts/index.js +1 -0
  15. package/lib/db-entries/account-center.d.ts +6 -2
  16. package/lib/db-entries/account-center.js +5 -1
  17. package/lib/db-entries/application-access-control-org-role-relation.d.ts +22 -0
  18. package/lib/db-entries/application-access-control-org-role-relation.js +33 -0
  19. package/lib/db-entries/application-access-control-organization-relation.d.ts +20 -0
  20. package/lib/db-entries/application-access-control-organization-relation.js +29 -0
  21. package/lib/db-entries/application-access-control-user-relation.d.ts +20 -0
  22. package/lib/db-entries/application-access-control-user-relation.js +29 -0
  23. package/lib/db-entries/application-access-control-user-role-relation.d.ts +20 -0
  24. package/lib/db-entries/application-access-control-user-role-relation.js +29 -0
  25. package/lib/db-entries/application.d.ts +3 -1
  26. package/lib/db-entries/application.js +4 -0
  27. package/lib/db-entries/index.d.ts +4 -0
  28. package/lib/db-entries/index.js +4 -0
  29. package/lib/db-entries/sign-in-experience.d.ts +4 -2
  30. package/lib/db-entries/sign-in-experience.js +5 -1
  31. package/lib/foundations/jsonb-types/account-centers.d.ts +26 -0
  32. package/lib/foundations/jsonb-types/account-centers.js +4 -0
  33. package/lib/foundations/jsonb-types/applications.d.ts +3 -0
  34. package/lib/foundations/jsonb-types/applications.js +4 -0
  35. package/lib/foundations/jsonb-types/applications.test.d.ts +1 -0
  36. package/lib/foundations/jsonb-types/applications.test.js +23 -0
  37. package/lib/foundations/jsonb-types/sign-in-experience.d.ts +1 -1
  38. package/lib/foundations/jsonb-types/sign-in-experience.js +1 -0
  39. package/lib/foundations/jsonb-types/sign-in-experience.test.d.ts +1 -0
  40. package/lib/foundations/jsonb-types/sign-in-experience.test.js +18 -0
  41. package/lib/seeds/application.js +2 -0
  42. package/lib/seeds/sign-in-experience.d.ts +13 -1
  43. package/lib/seeds/sign-in-experience.js +10 -1
  44. package/lib/seeds/sign-in-experience.test.d.ts +1 -0
  45. package/lib/seeds/sign-in-experience.test.js +27 -0
  46. package/lib/types/application.d.ts +99 -0
  47. package/lib/types/application.js +55 -0
  48. package/lib/types/application.test.d.ts +1 -0
  49. package/lib/types/application.test.js +120 -0
  50. package/lib/types/consent.d.ts +6 -0
  51. package/lib/types/logto-config/index.d.ts +38 -0
  52. package/lib/types/logto-config/jwt-customizer.d.ts +65 -0
  53. package/lib/types/saml-application.d.ts +3 -0
  54. package/lib/types/sign-in-experience.d.ts +14 -0
  55. package/lib/types/sign-in-experience.js +1 -0
  56. package/lib/types/system.d.ts +46 -7
  57. package/lib/types/system.js +9 -0
  58. package/lib/types/user-assets.d.ts +1 -1
  59. package/lib/types/user-sessions.d.ts +2516 -0
  60. package/lib/types/user-sessions.js +21 -0
  61. package/package.json +4 -4
  62. package/tables/account_centers.sql +2 -0
  63. package/tables/application_access_control_org_role_relations.sql +16 -0
  64. package/tables/application_access_control_organization_relations.sql +12 -0
  65. package/tables/application_access_control_user_relations.sql +12 -0
  66. package/tables/application_access_control_user_role_relations.sql +14 -0
  67. package/tables/applications.sql +1 -0
  68. package/tables/organization_role_user_relations.sql +3 -0
  69. package/tables/organization_user_relations.sql +3 -0
  70. package/tables/sign_in_experiences.sql +1 -0
@@ -0,0 +1,20 @@
1
+ import { GeneratedSchema } from './../foundations/index.js';
2
+ /**
3
+ * The user role allow relations for application-level access control.
4
+ *
5
+ * @remarks This is a type for database creation.
6
+ * @see {@link ApplicationAccessControlUserRoleRelation} for the original type.
7
+ */
8
+ export type CreateApplicationAccessControlUserRoleRelation = {
9
+ tenantId?: string;
10
+ applicationId: string;
11
+ roleId: string;
12
+ };
13
+ /** The user role allow relations for application-level access control. */
14
+ export type ApplicationAccessControlUserRoleRelation = {
15
+ tenantId: string;
16
+ applicationId: string;
17
+ roleId: string;
18
+ };
19
+ export type ApplicationAccessControlUserRoleRelationKeys = 'tenantId' | 'applicationId' | 'roleId';
20
+ export declare const ApplicationAccessControlUserRoleRelations: GeneratedSchema<ApplicationAccessControlUserRoleRelationKeys, CreateApplicationAccessControlUserRoleRelation, ApplicationAccessControlUserRoleRelation, 'application_access_control_user_role_relations', 'application_access_control_user_role_relation'>;
@@ -0,0 +1,29 @@
1
+ // THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2
+ import { z } from 'zod';
3
+ const createGuard = z.object({
4
+ tenantId: z.string().max(21).optional(),
5
+ applicationId: z.string().min(1).max(21),
6
+ roleId: z.string().min(1).max(21),
7
+ });
8
+ const guard = z.object({
9
+ tenantId: z.string().max(21),
10
+ applicationId: z.string().min(1).max(21),
11
+ roleId: z.string().min(1).max(21),
12
+ });
13
+ export const ApplicationAccessControlUserRoleRelations = Object.freeze({
14
+ table: 'application_access_control_user_role_relations',
15
+ tableSingular: 'application_access_control_user_role_relation',
16
+ fields: {
17
+ tenantId: 'tenant_id',
18
+ applicationId: 'application_id',
19
+ roleId: 'role_id',
20
+ },
21
+ fieldKeys: [
22
+ 'tenantId',
23
+ 'applicationId',
24
+ 'roleId',
25
+ ],
26
+ createGuard,
27
+ guard,
28
+ updateGuard: guard.partial(),
29
+ });
@@ -18,6 +18,7 @@ export type CreateApplication = {
18
18
  protectedAppMetadata?: ProtectedAppMetadata | null;
19
19
  customData?: JsonObject;
20
20
  isThirdParty?: boolean;
21
+ appLevelAccessControlEnabled?: boolean;
21
22
  createdAt?: number;
22
23
  };
23
24
  export type Application = {
@@ -33,7 +34,8 @@ export type Application = {
33
34
  protectedAppMetadata: ProtectedAppMetadata | null;
34
35
  customData: JsonObject;
35
36
  isThirdParty: boolean;
37
+ appLevelAccessControlEnabled: boolean;
36
38
  createdAt: number;
37
39
  };
38
- export type ApplicationKeys = 'tenantId' | 'id' | 'name' | 'secret' | 'description' | 'type' | 'oidcClientMetadata' | 'customClientMetadata' | 'protectedAppMetadata' | 'customData' | 'isThirdParty' | 'createdAt';
40
+ export type ApplicationKeys = 'tenantId' | 'id' | 'name' | 'secret' | 'description' | 'type' | 'oidcClientMetadata' | 'customClientMetadata' | 'protectedAppMetadata' | 'customData' | 'isThirdParty' | 'appLevelAccessControlEnabled' | 'createdAt';
39
41
  export declare const Applications: GeneratedSchema<ApplicationKeys, CreateApplication, Application, 'applications', 'application'>;
@@ -14,6 +14,7 @@ const createGuard = z.object({
14
14
  protectedAppMetadata: protectedAppMetadataGuard.nullable().optional(),
15
15
  customData: jsonObjectGuard.optional(),
16
16
  isThirdParty: z.boolean().optional(),
17
+ appLevelAccessControlEnabled: z.boolean().optional(),
17
18
  createdAt: z.number().optional(),
18
19
  });
19
20
  const guard = z.object({
@@ -28,6 +29,7 @@ const guard = z.object({
28
29
  protectedAppMetadata: protectedAppMetadataGuard.nullable(),
29
30
  customData: jsonObjectGuard,
30
31
  isThirdParty: z.boolean(),
32
+ appLevelAccessControlEnabled: z.boolean(),
31
33
  createdAt: z.number(),
32
34
  });
33
35
  export const Applications = Object.freeze({
@@ -45,6 +47,7 @@ export const Applications = Object.freeze({
45
47
  protectedAppMetadata: 'protected_app_metadata',
46
48
  customData: 'custom_data',
47
49
  isThirdParty: 'is_third_party',
50
+ appLevelAccessControlEnabled: 'app_level_access_control_enabled',
48
51
  createdAt: 'created_at',
49
52
  },
50
53
  fieldKeys: [
@@ -59,6 +62,7 @@ export const Applications = Object.freeze({
59
62
  'protectedAppMetadata',
60
63
  'customData',
61
64
  'isThirdParty',
65
+ 'appLevelAccessControlEnabled',
62
66
  'createdAt',
63
67
  ],
64
68
  createGuard,
@@ -5,6 +5,10 @@ export * from './-before-all.js';
5
5
  export * from './-function.js';
6
6
  export * from './account-center.js';
7
7
  export * from './aggregated-daily-active-user.js';
8
+ export * from './application-access-control-org-role-relation.js';
9
+ export * from './application-access-control-organization-relation.js';
10
+ export * from './application-access-control-user-relation.js';
11
+ export * from './application-access-control-user-role-relation.js';
8
12
  export * from './application-secret.js';
9
13
  export * from './application-sign-in-experience.js';
10
14
  export * from './application-user-consent-organization-resource-scope.js';
@@ -6,6 +6,10 @@ export * from './-before-all.js';
6
6
  export * from './-function.js';
7
7
  export * from './account-center.js';
8
8
  export * from './aggregated-daily-active-user.js';
9
+ export * from './application-access-control-org-role-relation.js';
10
+ export * from './application-access-control-organization-relation.js';
11
+ export * from './application-access-control-user-relation.js';
12
+ export * from './application-access-control-user-role-relation.js';
9
13
  export * from './application-secret.js';
10
14
  export * from './application-sign-in-experience.js';
11
15
  export * from './application-user-consent-organization-resource-scope.js';
@@ -1,4 +1,4 @@
1
- import { Color, Branding, LanguageInfo, SignIn, SignUp, SocialSignIn, ConnectorTargets, CustomContent, CustomUiAssets, PartialPasswordPolicy, Mfa, AdaptiveMfa, CaptchaPolicy, SentinelPolicy, EmailBlocklistPolicy, ForgotPasswordMethods, PasskeySignIn, SignUpProfileFields, GeneratedSchema } from './../foundations/index.js';
1
+ import { Color, Branding, LanguageInfo, SignIn, SignUp, SocialSignIn, ConnectorTargets, CustomContent, CustomUiAssets, CustomUiCsp, PartialPasswordPolicy, Mfa, AdaptiveMfa, CaptchaPolicy, SentinelPolicy, EmailBlocklistPolicy, ForgotPasswordMethods, PasskeySignIn, SignUpProfileFields, GeneratedSchema } from './../foundations/index.js';
2
2
  import { AgreeToTermsPolicy, SignInMode } from './custom-types.js';
3
3
  /**
4
4
  *
@@ -24,6 +24,7 @@ export type CreateSignInExperience = {
24
24
  customCss?: string | null;
25
25
  customContent?: CustomContent;
26
26
  customUiAssets?: CustomUiAssets | null;
27
+ customUiCsp?: CustomUiCsp;
27
28
  passwordPolicy?: PartialPasswordPolicy;
28
29
  mfa?: Mfa;
29
30
  adaptiveMfa?: AdaptiveMfa;
@@ -58,6 +59,7 @@ export type SignInExperience = {
58
59
  customCss: string | null;
59
60
  customContent: CustomContent;
60
61
  customUiAssets: CustomUiAssets | null;
62
+ customUiCsp: CustomUiCsp;
61
63
  passwordPolicy: PartialPasswordPolicy;
62
64
  mfa: Mfa;
63
65
  adaptiveMfa: AdaptiveMfa;
@@ -73,5 +75,5 @@ export type SignInExperience = {
73
75
  /** Nullable by design: null keeps legacy full-catalog behavior and [] collects no custom profile fields. */
74
76
  signUpProfileFields: SignUpProfileFields | null;
75
77
  };
76
- export type SignInExperienceKeys = 'tenantId' | 'id' | 'color' | 'branding' | 'hideLogtoBranding' | 'languageInfo' | 'termsOfUseUrl' | 'privacyPolicyUrl' | 'agreeToTermsPolicy' | 'signIn' | 'signUp' | 'socialSignIn' | 'socialSignInConnectorTargets' | 'signInMode' | 'customCss' | 'customContent' | 'customUiAssets' | 'passwordPolicy' | 'mfa' | 'adaptiveMfa' | 'singleSignOnEnabled' | 'supportEmail' | 'supportWebsiteUrl' | 'unknownSessionRedirectUrl' | 'captchaPolicy' | 'sentinelPolicy' | 'emailBlocklistPolicy' | 'forgotPasswordMethods' | 'passkeySignIn' | 'signUpProfileFields';
78
+ export type SignInExperienceKeys = 'tenantId' | 'id' | 'color' | 'branding' | 'hideLogtoBranding' | 'languageInfo' | 'termsOfUseUrl' | 'privacyPolicyUrl' | 'agreeToTermsPolicy' | 'signIn' | 'signUp' | 'socialSignIn' | 'socialSignInConnectorTargets' | 'signInMode' | 'customCss' | 'customContent' | 'customUiAssets' | 'customUiCsp' | 'passwordPolicy' | 'mfa' | 'adaptiveMfa' | 'singleSignOnEnabled' | 'supportEmail' | 'supportWebsiteUrl' | 'unknownSessionRedirectUrl' | 'captchaPolicy' | 'sentinelPolicy' | 'emailBlocklistPolicy' | 'forgotPasswordMethods' | 'passkeySignIn' | 'signUpProfileFields';
77
79
  export declare const SignInExperiences: GeneratedSchema<SignInExperienceKeys, CreateSignInExperience, SignInExperience, 'sign_in_experiences', 'sign_in_experience'>;
@@ -1,6 +1,6 @@
1
1
  // THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2
2
  import { z } from 'zod';
3
- import { colorGuard, brandingGuard, languageInfoGuard, signInGuard, signUpGuard, socialSignInGuard, connectorTargetsGuard, customContentGuard, customUiAssetsGuard, partialPasswordPolicyGuard, mfaGuard, adaptiveMfaGuard, captchaPolicyGuard, sentinelPolicyGuard, emailBlocklistPolicyGuard, forgotPasswordMethodsGuard, passkeySignInGuard, signUpProfileFieldsGuard } from './../foundations/index.js';
3
+ import { colorGuard, brandingGuard, languageInfoGuard, signInGuard, signUpGuard, socialSignInGuard, connectorTargetsGuard, customContentGuard, customUiAssetsGuard, customUiCspGuard, partialPasswordPolicyGuard, mfaGuard, adaptiveMfaGuard, captchaPolicyGuard, sentinelPolicyGuard, emailBlocklistPolicyGuard, forgotPasswordMethodsGuard, passkeySignInGuard, signUpProfileFieldsGuard } from './../foundations/index.js';
4
4
  import { AgreeToTermsPolicy, SignInMode } from './custom-types.js';
5
5
  const createGuard = z.object({
6
6
  tenantId: z.string().max(21).optional(),
@@ -20,6 +20,7 @@ const createGuard = z.object({
20
20
  customCss: z.string().nullable().optional(),
21
21
  customContent: customContentGuard.optional(),
22
22
  customUiAssets: customUiAssetsGuard.nullable().optional(),
23
+ customUiCsp: customUiCspGuard.optional(),
23
24
  passwordPolicy: partialPasswordPolicyGuard.optional(),
24
25
  mfa: mfaGuard.optional(),
25
26
  adaptiveMfa: adaptiveMfaGuard.optional(),
@@ -52,6 +53,7 @@ const guard = z.object({
52
53
  customCss: z.string().nullable(),
53
54
  customContent: customContentGuard,
54
55
  customUiAssets: customUiAssetsGuard.nullable(),
56
+ customUiCsp: customUiCspGuard,
55
57
  passwordPolicy: partialPasswordPolicyGuard,
56
58
  mfa: mfaGuard,
57
59
  adaptiveMfa: adaptiveMfaGuard,
@@ -87,6 +89,7 @@ export const SignInExperiences = Object.freeze({
87
89
  customCss: 'custom_css',
88
90
  customContent: 'custom_content',
89
91
  customUiAssets: 'custom_ui_assets',
92
+ customUiCsp: 'custom_ui_csp',
90
93
  passwordPolicy: 'password_policy',
91
94
  mfa: 'mfa',
92
95
  adaptiveMfa: 'adaptive_mfa',
@@ -119,6 +122,7 @@ export const SignInExperiences = Object.freeze({
119
122
  'customCss',
120
123
  'customContent',
121
124
  'customUiAssets',
125
+ 'customUiCsp',
122
126
  'passwordPolicy',
123
127
  'mfa',
124
128
  'adaptiveMfa',
@@ -49,4 +49,30 @@ export declare const accountCenterFieldControlGuard: z.ZodObject<{
49
49
  export type AccountCenterFieldControl = z.infer<typeof accountCenterFieldControlGuard>;
50
50
  export declare const webauthnRelatedOriginsGuard: z.ZodArray<z.ZodString, "many">;
51
51
  export type WebauthnRelatedOrigins = z.infer<typeof webauthnRelatedOriginsGuard>;
52
+ /**
53
+ * Configuration for which custom profile fields are exposed in the prebuilt account center and
54
+ * in which order. Each entry references an existing field by name in the `custom_profile_fields`
55
+ * catalog; fields in the catalog but not in this list are not shown in the account center.
56
+ *
57
+ * Kept separate from `signUpProfileFields` so the sign-up and account-center surfaces can be
58
+ * configured independently against the same catalog.
59
+ */
60
+ export type AccountCenterProfileFieldItem = {
61
+ name: string;
62
+ };
63
+ export declare const accountCenterProfileFieldItemGuard: z.ZodObject<{
64
+ name: z.ZodString;
65
+ }, "strip", z.ZodTypeAny, {
66
+ name: string;
67
+ }, {
68
+ name: string;
69
+ }>;
70
+ export declare const accountCenterProfileFieldsGuard: z.ZodArray<z.ZodObject<{
71
+ name: z.ZodString;
72
+ }, "strip", z.ZodTypeAny, {
73
+ name: string;
74
+ }, {
75
+ name: string;
76
+ }>, "many">;
77
+ export type AccountCenterProfileFields = z.infer<typeof accountCenterProfileFieldsGuard>;
52
78
  export declare const deleteAccountUrlGuard: z.ZodEffects<z.ZodString, string, string>;
@@ -26,6 +26,10 @@ export const accountCenterFieldControlGuard = z
26
26
  })
27
27
  .partial();
28
28
  export const webauthnRelatedOriginsGuard = z.array(z.string());
29
+ export const accountCenterProfileFieldItemGuard = z.object({
30
+ name: z.string(),
31
+ });
32
+ export const accountCenterProfileFieldsGuard = z.array(accountCenterProfileFieldItemGuard);
29
33
  export const deleteAccountUrlGuard = z
30
34
  .string()
31
35
  .max(2048)
@@ -217,6 +217,7 @@ export declare const protectedAppMetadataGuard: z.ZodObject<{
217
217
  }, {
218
218
  path: string;
219
219
  }>, "many">;
220
+ additionalScopes: z.ZodOptional<z.ZodArray<z.ZodEnum<[import("@logto/core-kit").UserScope.CustomData, import("@logto/core-kit").UserScope.Identities, import("@logto/core-kit").UserScope.Roles, import("@logto/core-kit").UserScope.Organizations, import("@logto/core-kit").UserScope.OrganizationRoles]>, "many">>;
220
221
  customDomains: z.ZodOptional<z.ZodArray<z.ZodObject<{
221
222
  domain: z.ZodString;
222
223
  status: z.ZodNativeEnum<typeof import("./custom-domain.js").DomainStatus>;
@@ -327,6 +328,7 @@ export declare const protectedAppMetadataGuard: z.ZodObject<{
327
328
  pageRules: {
328
329
  path: string;
329
330
  }[];
331
+ additionalScopes?: (import("@logto/core-kit").UserScope.CustomData | import("@logto/core-kit").UserScope.Identities | import("@logto/core-kit").UserScope.Roles | import("@logto/core-kit").UserScope.Organizations | import("@logto/core-kit").UserScope.OrganizationRoles)[] | undefined;
330
332
  customDomains?: {
331
333
  status: import("./custom-domain.js").DomainStatus;
332
334
  domain: string;
@@ -355,6 +357,7 @@ export declare const protectedAppMetadataGuard: z.ZodObject<{
355
357
  pageRules: {
356
358
  path: string;
357
359
  }[];
360
+ additionalScopes?: (import("@logto/core-kit").UserScope.CustomData | import("@logto/core-kit").UserScope.Identities | import("@logto/core-kit").UserScope.Roles | import("@logto/core-kit").UserScope.Organizations | import("@logto/core-kit").UserScope.OrganizationRoles)[] | undefined;
358
361
  customDomains?: {
359
362
  status: import("./custom-domain.js").DomainStatus;
360
363
  domain: string;
@@ -1,5 +1,7 @@
1
+ import { protectedAppAdditionalScopes } from '@logto/core-kit';
1
2
  import { z } from 'zod';
2
3
  import { cloudflareDataGuard, domainDnsRecordsGuard, domainStatusGuard } from './custom-domain.js';
4
+ const protectedAppAdditionalScopeGuard = z.enum(protectedAppAdditionalScopes);
3
5
  export const customDomainGuard = z.object({
4
6
  /* The domain name, e.g app.example.com */
5
7
  domain: z.string(),
@@ -24,6 +26,8 @@ export const protectedAppMetadataGuard = z.object({
24
26
  /* The path pattern (regex) to match */
25
27
  path: z.string(),
26
28
  })),
29
+ /* Additional scopes requested by protected app sign-in */
30
+ additionalScopes: z.array(protectedAppAdditionalScopeGuard).optional(),
27
31
  /* Custom domain */
28
32
  customDomains: customDomainsGuard.optional(),
29
33
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ import { UserScope } from '@logto/core-kit';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { protectedAppMetadataGuard } from './applications.js';
4
+ const protectedAppMetadata = {
5
+ host: 'example.com',
6
+ origin: 'https://example.com',
7
+ sessionDuration: 3600,
8
+ pageRules: [],
9
+ };
10
+ describe('protectedAppMetadataGuard', () => {
11
+ it('accepts additional scopes with extended ID token claims', () => {
12
+ expect(protectedAppMetadataGuard.safeParse({
13
+ ...protectedAppMetadata,
14
+ additionalScopes: [UserScope.CustomData],
15
+ }).success).toBe(true);
16
+ });
17
+ it('rejects additional scopes without extended ID token claims', () => {
18
+ expect(protectedAppMetadataGuard.safeParse({
19
+ ...protectedAppMetadata,
20
+ additionalScopes: [UserScope.Sessions],
21
+ }).success).toBe(false);
22
+ });
23
+ });
@@ -441,4 +441,4 @@ export declare const signUpProfileFieldsGuard: z.ZodArray<z.ZodObject<{
441
441
  name: string;
442
442
  }>, "many">;
443
443
  export type SignUpProfileFields = z.infer<typeof signUpProfileFieldsGuard>;
444
- export {};
444
+ export { customUiCspGuard, type CustomUiCsp } from '@logto/core-kit';
@@ -142,3 +142,4 @@ export const signUpProfileFieldItemGuard = z.object({
142
142
  name: z.string(),
143
143
  });
144
144
  export const signUpProfileFieldsGuard = z.array(signUpProfileFieldItemGuard);
145
+ export { customUiCspGuard } from '@logto/core-kit';
@@ -0,0 +1,18 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { customUiCspGuard } from './sign-in-experience.js';
3
+ describe('customUiCspGuard', () => {
4
+ it.each([
5
+ {},
6
+ { scriptSrc: ['https://example.com'] },
7
+ { connectSrc: ['https://api.example.com'] },
8
+ {
9
+ scriptSrc: ['https://example.com'],
10
+ connectSrc: ['https://api.example.com'],
11
+ },
12
+ ])('accepts %p', (value) => {
13
+ expect(customUiCspGuard.safeParse(value).success).toBe(true);
14
+ });
15
+ it('rejects unsupported directives', () => {
16
+ expect(customUiCspGuard.safeParse({ imgSrc: ['https://example.com'] }).success).toBe(false);
17
+ });
18
+ });
@@ -21,6 +21,7 @@ const buildSpaApplicationData = (tenantId, { id, name, description, }) => ({
21
21
  customClientMetadata: {},
22
22
  protectedAppMetadata: null,
23
23
  isThirdParty: false,
24
+ appLevelAccessControlEnabled: false,
24
25
  createdAt: 0,
25
26
  customData: {},
26
27
  });
@@ -45,6 +46,7 @@ const buildNativeApplicationData = (tenantId, { id, name, description, }) => ({
45
46
  customClientMetadata: { isDeviceFlow: true },
46
47
  protectedAppMetadata: null,
47
48
  isThirdParty: false,
49
+ appLevelAccessControlEnabled: false,
48
50
  createdAt: 0,
49
51
  customData: {},
50
52
  });
@@ -3,4 +3,16 @@ export declare const defaultPrimaryColor = "#6139F6";
3
3
  export declare const createDefaultSignInExperience: (forTenantId: string, isCloud: boolean) => Readonly<CreateSignInExperience>;
4
4
  /** @deprecated Use `createDefaultSignInExperience()` instead. */
5
5
  export declare const defaultSignInExperience: Readonly<CreateSignInExperience>;
6
- export declare const createAdminTenantSignInExperience: () => Readonly<CreateSignInExperience>;
6
+ export type AdminSignInExperienceSeedOptions = {
7
+ /**
8
+ * When true, the seeded admin-tenant `passwordPolicy` explicitly disables the
9
+ * HaveIBeenPwned (HIBP) breach check by setting `rejects.pwned = false`. Intended
10
+ * for air-gapped or offline OSS deployments where `api.pwnedpasswords.com` is
11
+ * unreachable; otherwise the first admin sign-up will hang on the breach check.
12
+ *
13
+ * Defaults to `false`, which preserves the historical seeded value (`{}`) and lets
14
+ * the runtime fall back to the default policy (HIBP check enabled).
15
+ */
16
+ disablePwnedPasswordCheck?: boolean;
17
+ };
18
+ export declare const createAdminTenantSignInExperience: (options?: AdminSignInExperienceSeedOptions) => Readonly<CreateSignInExperience>;
@@ -50,7 +50,7 @@ export const createDefaultSignInExperience = (forTenantId, isCloud) => Object.fr
50
50
  });
51
51
  /** @deprecated Use `createDefaultSignInExperience()` instead. */
52
52
  export const defaultSignInExperience = createDefaultSignInExperience(defaultTenantId, false);
53
- export const createAdminTenantSignInExperience = () => Object.freeze({
53
+ export const createAdminTenantSignInExperience = (options = {}) => Object.freeze({
54
54
  ...defaultSignInExperience,
55
55
  tenantId: adminTenantId,
56
56
  color: {
@@ -62,6 +62,15 @@ export const createAdminTenantSignInExperience = () => Object.freeze({
62
62
  logoUrl: 'https://logto.io/logo.svg',
63
63
  darkLogoUrl: 'https://logto.io/logo-dark.svg',
64
64
  },
65
+ passwordPolicy: options.disablePwnedPasswordCheck
66
+ ? {
67
+ ...defaultSignInExperience.passwordPolicy,
68
+ rejects: {
69
+ ...defaultSignInExperience.passwordPolicy?.rejects,
70
+ pwned: false,
71
+ },
72
+ }
73
+ : defaultSignInExperience.passwordPolicy,
65
74
  mfa: {
66
75
  factors: [MfaFactor.TOTP, MfaFactor.WebAuthn, MfaFactor.BackupCode],
67
76
  policy: MfaPolicy.NoPrompt,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,27 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { createAdminTenantSignInExperience, createDefaultSignInExperience, } from './sign-in-experience.js';
3
+ import { adminTenantId } from './tenant.js';
4
+ describe('createAdminTenantSignInExperience', () => {
5
+ it('seeds an empty passwordPolicy by default', () => {
6
+ const row = createAdminTenantSignInExperience();
7
+ expect(row.passwordPolicy).toEqual({});
8
+ });
9
+ it('seeds an empty passwordPolicy when option is explicitly false', () => {
10
+ const row = createAdminTenantSignInExperience({ disablePwnedPasswordCheck: false });
11
+ expect(row.passwordPolicy).toEqual({});
12
+ });
13
+ it('seeds rejects.pwned=false when disablePwnedPasswordCheck is true', () => {
14
+ const row = createAdminTenantSignInExperience({ disablePwnedPasswordCheck: true });
15
+ expect(row.passwordPolicy).toEqual({ rejects: { pwned: false } });
16
+ });
17
+ it('still targets the admin tenant id when the option is set', () => {
18
+ const row = createAdminTenantSignInExperience({ disablePwnedPasswordCheck: true });
19
+ expect(row.tenantId).toBe(adminTenantId);
20
+ });
21
+ });
22
+ describe('createDefaultSignInExperience (unchanged contract)', () => {
23
+ it('still has a two-parameter signature and seeds an empty passwordPolicy', () => {
24
+ const row = createDefaultSignInExperience('some-tenant-id', false);
25
+ expect(row.passwordPolicy).toEqual({});
26
+ });
27
+ });
@@ -48,6 +48,7 @@ export declare const featuredApplicationGuard: z.ZodObject<Pick<{
48
48
  pageRules: {
49
49
  path: string;
50
50
  }[];
51
+ additionalScopes?: (UserScope.CustomData | UserScope.Identities | UserScope.Roles | UserScope.Organizations | UserScope.OrganizationRoles)[] | undefined;
51
52
  customDomains?: {
52
53
  status: import("../index.js").DomainStatus;
53
54
  domain: string;
@@ -76,6 +77,7 @@ export declare const featuredApplicationGuard: z.ZodObject<Pick<{
76
77
  pageRules: {
77
78
  path: string;
78
79
  }[];
80
+ additionalScopes?: (UserScope.CustomData | UserScope.Identities | UserScope.Roles | UserScope.Organizations | UserScope.OrganizationRoles)[] | undefined;
79
81
  customDomains?: {
80
82
  status: import("../index.js").DomainStatus;
81
83
  domain: string;
@@ -100,6 +102,7 @@ export declare const featuredApplicationGuard: z.ZodObject<Pick<{
100
102
  } | null>;
101
103
  customData: z.ZodType<import("@withtyped/server").JsonObject, z.ZodTypeDef, import("@withtyped/server").JsonObject>;
102
104
  isThirdParty: z.ZodType<boolean, z.ZodTypeDef, boolean>;
105
+ appLevelAccessControlEnabled: z.ZodType<boolean, z.ZodTypeDef, boolean>;
103
106
  createdAt: z.ZodType<number, z.ZodTypeDef, number>;
104
107
  }, "type" | "name" | "id">, "strip", z.ZodTypeAny, {
105
108
  type: import("../db-entries/custom-types.js").ApplicationType;
@@ -144,6 +147,7 @@ export declare const applicationCreateGuard: z.ZodObject<{
144
147
  pageRules: {
145
148
  path: string;
146
149
  }[];
150
+ additionalScopes?: (UserScope.CustomData | UserScope.Identities | UserScope.Roles | UserScope.Organizations | UserScope.OrganizationRoles)[] | undefined;
147
151
  customDomains?: {
148
152
  status: import("../index.js").DomainStatus;
149
153
  domain: string;
@@ -172,6 +176,7 @@ export declare const applicationCreateGuard: z.ZodObject<{
172
176
  pageRules: {
173
177
  path: string;
174
178
  }[];
179
+ additionalScopes?: (UserScope.CustomData | UserScope.Identities | UserScope.Roles | UserScope.Organizations | UserScope.OrganizationRoles)[] | undefined;
175
180
  customDomains?: {
176
181
  status: import("../index.js").DomainStatus;
177
182
  domain: string;
@@ -251,6 +256,7 @@ export declare const applicationPatchGuard: z.ZodObject<Omit<{
251
256
  pageRules: {
252
257
  path: string;
253
258
  }[];
259
+ additionalScopes?: (UserScope.CustomData | UserScope.Identities | UserScope.Roles | UserScope.Organizations | UserScope.OrganizationRoles)[] | undefined;
254
260
  customDomains?: {
255
261
  status: import("../index.js").DomainStatus;
256
262
  domain: string;
@@ -279,6 +285,7 @@ export declare const applicationPatchGuard: z.ZodObject<Omit<{
279
285
  pageRules: {
280
286
  path: string;
281
287
  }[];
288
+ additionalScopes?: (UserScope.CustomData | UserScope.Identities | UserScope.Roles | UserScope.Organizations | UserScope.OrganizationRoles)[] | undefined;
282
289
  customDomains?: {
283
290
  status: import("../index.js").DomainStatus;
284
291
  domain: string;
@@ -319,6 +326,98 @@ export declare const applicationPatchGuard: z.ZodObject<Omit<{
319
326
  customClientMetadata?: import("../index.js").CustomClientMetadata;
320
327
  protectedAppMetadata?: import("../index.js").ProtectedAppMetadata | null;
321
328
  }>;
329
+ /** The guard for one organization role access-control rule group. */
330
+ export declare const applicationAccessControlOrganizationRoleRuleGuard: z.ZodObject<{
331
+ organizationId: z.ZodString;
332
+ organizationRoleIds: z.ZodPipeline<z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], string[]>, z.ZodArray<z.ZodString, "many">>;
333
+ }, "strip", z.ZodTypeAny, {
334
+ organizationId: string;
335
+ organizationRoleIds: string[];
336
+ }, {
337
+ organizationId: string;
338
+ organizationRoleIds: string[];
339
+ }>;
340
+ /** The guard for application-level access control rule payloads. */
341
+ export declare const applicationAccessControlGuard: z.ZodPipeline<z.ZodEffects<z.ZodObject<{
342
+ userIds: z.ZodPipeline<z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], string[]>, z.ZodArray<z.ZodString, "many">>;
343
+ userRoleIds: z.ZodPipeline<z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], string[]>, z.ZodArray<z.ZodString, "many">>;
344
+ organizationIds: z.ZodPipeline<z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], string[]>, z.ZodArray<z.ZodString, "many">>;
345
+ organizationRoleRules: z.ZodArray<z.ZodObject<{
346
+ organizationId: z.ZodString;
347
+ organizationRoleIds: z.ZodPipeline<z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], string[]>, z.ZodArray<z.ZodString, "many">>;
348
+ }, "strip", z.ZodTypeAny, {
349
+ organizationId: string;
350
+ organizationRoleIds: string[];
351
+ }, {
352
+ organizationId: string;
353
+ organizationRoleIds: string[];
354
+ }>, "many">;
355
+ }, "strip", z.ZodTypeAny, {
356
+ userIds: string[];
357
+ userRoleIds: string[];
358
+ organizationIds: string[];
359
+ organizationRoleRules: {
360
+ organizationId: string;
361
+ organizationRoleIds: string[];
362
+ }[];
363
+ }, {
364
+ userIds: string[];
365
+ userRoleIds: string[];
366
+ organizationIds: string[];
367
+ organizationRoleRules: {
368
+ organizationId: string;
369
+ organizationRoleIds: string[];
370
+ }[];
371
+ }>, {
372
+ organizationRoleRules: {
373
+ organizationId: string;
374
+ organizationRoleIds: string[];
375
+ }[];
376
+ userIds: string[];
377
+ userRoleIds: string[];
378
+ organizationIds: string[];
379
+ }, {
380
+ userIds: string[];
381
+ userRoleIds: string[];
382
+ organizationIds: string[];
383
+ organizationRoleRules: {
384
+ organizationId: string;
385
+ organizationRoleIds: string[];
386
+ }[];
387
+ }>, z.ZodObject<{
388
+ userIds: z.ZodArray<z.ZodString, "many">;
389
+ userRoleIds: z.ZodArray<z.ZodString, "many">;
390
+ organizationIds: z.ZodArray<z.ZodString, "many">;
391
+ organizationRoleRules: z.ZodArray<z.ZodObject<{
392
+ organizationId: z.ZodString;
393
+ organizationRoleIds: z.ZodPipeline<z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], string[]>, z.ZodArray<z.ZodString, "many">>;
394
+ }, "strip", z.ZodTypeAny, {
395
+ organizationId: string;
396
+ organizationRoleIds: string[];
397
+ }, {
398
+ organizationId: string;
399
+ organizationRoleIds: string[];
400
+ }>, "many">;
401
+ }, "strip", z.ZodTypeAny, {
402
+ userIds: string[];
403
+ userRoleIds: string[];
404
+ organizationIds: string[];
405
+ organizationRoleRules: {
406
+ organizationId: string;
407
+ organizationRoleIds: string[];
408
+ }[];
409
+ }, {
410
+ userIds: string[];
411
+ userRoleIds: string[];
412
+ organizationIds: string[];
413
+ organizationRoleRules: {
414
+ organizationId: string;
415
+ organizationRoleIds: string[];
416
+ }[];
417
+ }>>;
418
+ export type ApplicationAccessControl = z.infer<typeof applicationAccessControlGuard>;
419
+ /** Create an empty application-level access control rule set. */
420
+ export declare const createDefaultApplicationAccessControl: () => ApplicationAccessControl;
322
421
  export declare const applicationUserConsentScopesResponseGuard: z.ZodObject<{
323
422
  organizationScopes: z.ZodArray<z.ZodObject<Pick<{
324
423
  tenantId: z.ZodType<string, z.ZodTypeDef, string>;