@tula-tech/contract 0.1.1 → 0.3.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.
@@ -49,6 +49,22 @@ var ERROR_DEFINITIONS2 = {
49
49
  status: 409,
50
50
  message: 'This account has no password yet. Use "forgot password" to set one.'
51
51
  },
52
+ "import.unsupported_algorithm": {
53
+ status: 422,
54
+ message: "That password hash algorithm is not supported."
55
+ },
56
+ "import.hash_malformed": {
57
+ status: 422,
58
+ message: "That password hash is malformed."
59
+ },
60
+ "import.hash_parameters_too_weak": {
61
+ status: 422,
62
+ message: "That password hash is too weak to import."
63
+ },
64
+ "import.hash_parameters_too_costly": {
65
+ status: 422,
66
+ message: "That password hash is too costly to verify."
67
+ },
52
68
  "verification.invalid_code": { status: 422, message: "That code is incorrect." },
53
69
  "verification.expired": { status: 410, message: "That code has expired. Request a new one." },
54
70
  "verification.too_many_attempts": {
@@ -214,6 +230,182 @@ var ERROR_DEFINITIONS2 = {
214
230
  status: 400,
215
231
  message: "Signing in here needs a device key."
216
232
  },
233
+ "user.last_organization_manager": {
234
+ status: 409,
235
+ message: "This user is the only manager of an organization. Add another manager or delete the organization first."
236
+ },
237
+ "user.managed": {
238
+ status: 403,
239
+ message: "This account is managed by your organization. Ask your administrator to change it."
240
+ },
241
+ "organization.disabled": {
242
+ status: 403,
243
+ message: "Organizations are not enabled for this environment."
244
+ },
245
+ "organization.slug_taken": {
246
+ status: 409,
247
+ message: "An organization with that slug already exists."
248
+ },
249
+ "organization.member_exists": {
250
+ status: 409,
251
+ message: "That user is already a member of this organization."
252
+ },
253
+ "organization.last_manager": {
254
+ status: 409,
255
+ message: "An organization must keep at least one member who can manage its members."
256
+ },
257
+ "organization.role_unknown": {
258
+ status: 422,
259
+ message: "That role does not exist in this environment."
260
+ },
261
+ "organization.not_a_member": {
262
+ status: 403,
263
+ message: "You are not a member of that organization."
264
+ },
265
+ "organization.creation_disabled": {
266
+ status: 403,
267
+ message: "Creating an organization is not allowed in this environment."
268
+ },
269
+ "organization.limit_reached": {
270
+ status: 403,
271
+ message: "You have reached the number of organizations you can create."
272
+ },
273
+ "organization.personal_account_disabled": {
274
+ status: 409,
275
+ message: "An organization must be active in this environment."
276
+ },
277
+ "organization.role_exists": {
278
+ status: 409,
279
+ message: "A role with that key already exists in this environment."
280
+ },
281
+ "organization.role_in_use": {
282
+ status: 409,
283
+ message: "Members still hold this role. Give them another role first."
284
+ },
285
+ "organization.role_built_in": {
286
+ status: 409,
287
+ message: "A built-in role cannot be changed or deleted."
288
+ },
289
+ "organization.role_limit": {
290
+ status: 409,
291
+ message: "This environment has the most custom roles it can have."
292
+ },
293
+ "organization.permission_required": {
294
+ status: 403,
295
+ message: "Your role does not allow that."
296
+ },
297
+ "organization.role_not_assignable": {
298
+ status: 403,
299
+ message: "You can only invite to a role no stronger than yours."
300
+ },
301
+ "organization.invitation_exists": {
302
+ status: 409,
303
+ message: "That address already has a pending invitation."
304
+ },
305
+ "organization.invitation_not_found": {
306
+ status: 404,
307
+ message: "This invitation does not exist."
308
+ },
309
+ "organization.invitation_expired": {
310
+ status: 410,
311
+ message: "This invitation has expired."
312
+ },
313
+ "organization.invitation_revoked": {
314
+ status: 410,
315
+ message: "This invitation was withdrawn."
316
+ },
317
+ "organization.invitation_used": {
318
+ status: 410,
319
+ message: "This invitation was already used."
320
+ },
321
+ "organization.invitation_wrong_account": {
322
+ status: 403,
323
+ message: "This invitation was sent to another email address."
324
+ },
325
+ "organization.invitation_email_unverified": {
326
+ status: 403,
327
+ message: "Verify your email address to accept this invitation."
328
+ },
329
+ "organization.invitation_role_gone": {
330
+ status: 409,
331
+ message: "The role this invitation offers no longer exists."
332
+ },
333
+ "organization.domain_public": {
334
+ status: 422,
335
+ message: "A public email domain cannot be claimed by an organization."
336
+ },
337
+ "organization.domain_taken": {
338
+ status: 409,
339
+ message: "That domain is verified for an organization already."
340
+ },
341
+ "organization.domain_address_mismatch": {
342
+ status: 422,
343
+ message: "That address is not on the domain."
344
+ },
345
+ "organization.domain_limit": {
346
+ status: 409,
347
+ message: "This organization has the most domains it can have."
348
+ },
349
+ "organization.suggestion_unavailable": {
350
+ status: 403,
351
+ message: "You cannot join that organization."
352
+ },
353
+ "sso.disabled": {
354
+ status: 403,
355
+ message: "Single sign-on is not enabled for this environment."
356
+ },
357
+ "sso.connection_not_found": { status: 404, message: "No such single sign-on connection." },
358
+ "sso.name_taken": {
359
+ status: 409,
360
+ message: "The organization already has a connection with that name."
361
+ },
362
+ "sso.domain_taken": {
363
+ status: 409,
364
+ message: "Another active connection already serves one of those domains."
365
+ },
366
+ "sso.domain_not_verified": {
367
+ status: 422,
368
+ message: "Every domain must be one of the organization's verified domains."
369
+ },
370
+ "sso.issuer_not_allowed": {
371
+ status: 422,
372
+ message: "The issuer is not an address the server may call."
373
+ },
374
+ "sso.saml_invalid": {
375
+ status: 422,
376
+ message: "The SAML settings could not be read or are incomplete."
377
+ },
378
+ "sso.connection_in_use": {
379
+ status: 409,
380
+ message: "The connection is active; disable it before deleting it."
381
+ },
382
+ "sso.invalid_transition": {
383
+ status: 409,
384
+ message: "A connection cannot move to that status from its current one."
385
+ },
386
+ "sso.url_not_https": {
387
+ status: 422,
388
+ message: "The identity provider’s sign-in address must start with https."
389
+ },
390
+ "sso.test_required": {
391
+ status: 409,
392
+ message: "Run a passing test sign-in of the connection’s current settings before activating it."
393
+ },
394
+ "sso.test_not_found": { status: 404, message: "No such test sign-in." },
395
+ "sso.role_not_allowed": {
396
+ status: 403,
397
+ message: "A setup link cannot map a group to a role that holds system permissions."
398
+ },
399
+ "sso.unavailable": { status: 400, message: "Single sign-on is not available for that address." },
400
+ "sso.provider_error": { status: 401, message: "The identity provider did not sign you in." },
401
+ "sso.user_not_provisioned": {
402
+ status: 403,
403
+ message: "Your account has not been set up for this organization. Ask its administrator."
404
+ },
405
+ "sso.email_domain_mismatch": {
406
+ status: 403,
407
+ message: "Your email address is not on this connection's domains."
408
+ },
217
409
  rate_limited: { status: 429, message: "Too many requests. Try again shortly." },
218
410
  "request.malformed": { status: 400, message: "The request could not be read." },
219
411
  "request.too_large": { status: 413, message: "The request body is too large." },
@@ -1,6 +1,7 @@
1
1
  // src/event-types.ts
2
2
  var ACTIVITY_TYPES2 = [
3
3
  "user.created",
4
+ "user.imported",
4
5
  "user.email_verified",
5
6
  "user.banned",
6
7
  "user.unbanned",
@@ -12,6 +13,7 @@ var ACTIVITY_TYPES2 = [
12
13
  "user.backup_code_used",
13
14
  "user.identity_linked",
14
15
  "user.identity_unlinked",
16
+ "user.sso_linked",
15
17
  "user.email_added",
16
18
  "user.passkey_added",
17
19
  "user.passkey_renamed",
@@ -44,16 +46,48 @@ var ACTIVITY_TYPES2 = [
44
46
  "native_app.created",
45
47
  "native_app.updated",
46
48
  "native_app.deleted",
49
+ "sso_connection.created",
50
+ "sso_connection.updated",
51
+ "sso_connection.deleted",
52
+ "scim_token.created",
53
+ "scim_token.revoked",
54
+ "setup_link.created",
55
+ "setup_link.revoked",
56
+ "user.scim_provisioned",
57
+ "user.scim_updated",
58
+ "scim_group.created",
59
+ "scim_group.updated",
60
+ "scim_group.deleted",
61
+ "organization.created",
62
+ "organization.updated",
63
+ "organization.deleted",
64
+ "organization_membership.added",
65
+ "organization_membership.role_changed",
66
+ "organization_membership.removed",
67
+ "organization_role.created",
68
+ "organization_role.updated",
69
+ "organization_role.deleted",
70
+ "organization_domain.claimed",
71
+ "organization_domain.verified",
72
+ "organization_domain.updated",
73
+ "organization_domain.removed",
74
+ "organization_invitation.created",
75
+ "organization_invitation.accepted",
76
+ "organization_invitation.declined",
77
+ "organization_invitation.revoked",
47
78
  "proposal.created",
48
79
  "proposal.approved",
80
+ "proposal.rejected",
49
81
  "proposal.executed",
50
82
  "proposal.failed",
83
+ "audit.exported",
51
84
  "sign_in_test.started",
52
85
  "sign_in_test.finished"
53
86
  ];
54
87
  var EVENT_SCHEMA_VERSION2 = 1;
55
88
  var EVENT_TARGET_TYPES2 = {
56
89
  "user.created": "user",
90
+ "user.imported": "user",
57
91
  "user.email_verified": "user",
58
92
  "user.banned": "user",
59
93
  "user.unbanned": "user",
@@ -66,6 +100,7 @@ var EVENT_TARGET_TYPES2 = {
66
100
  "user.identity_linked": "user",
67
101
  "user.email_added": "user",
68
102
  "user.identity_unlinked": "user",
103
+ "user.sso_linked": "user",
69
104
  "user.passkey_added": "user",
70
105
  "user.passkey_renamed": "user",
71
106
  "user.passkey_removed": "user",
@@ -97,10 +132,41 @@ var EVENT_TARGET_TYPES2 = {
97
132
  "native_app.created": "native_app",
98
133
  "native_app.updated": "native_app",
99
134
  "native_app.deleted": "native_app",
135
+ "sso_connection.created": "sso_connection",
136
+ "sso_connection.updated": "sso_connection",
137
+ "sso_connection.deleted": "sso_connection",
138
+ "scim_token.created": "scim_token",
139
+ "scim_token.revoked": "scim_token",
140
+ "setup_link.created": "setup_link",
141
+ "setup_link.revoked": "setup_link",
142
+ "user.scim_provisioned": "user",
143
+ "user.scim_updated": "user",
144
+ "scim_group.created": "scim_group",
145
+ "scim_group.updated": "scim_group",
146
+ "scim_group.deleted": "scim_group",
147
+ "organization.created": "organization",
148
+ "organization.updated": "organization",
149
+ "organization.deleted": "organization",
150
+ "organization_membership.added": "organization_membership",
151
+ "organization_membership.role_changed": "organization_membership",
152
+ "organization_membership.removed": "organization_membership",
153
+ "organization_role.created": "organization_role",
154
+ "organization_role.updated": "organization_role",
155
+ "organization_role.deleted": "organization_role",
156
+ "organization_domain.claimed": "organization_domain",
157
+ "organization_domain.verified": "organization_domain",
158
+ "organization_domain.updated": "organization_domain",
159
+ "organization_domain.removed": "organization_domain",
160
+ "organization_invitation.created": "organization_invitation",
161
+ "organization_invitation.accepted": "organization_invitation",
162
+ "organization_invitation.declined": "organization_invitation",
163
+ "organization_invitation.revoked": "organization_invitation",
100
164
  "proposal.created": "proposal",
101
165
  "proposal.approved": "proposal",
166
+ "proposal.rejected": "proposal",
102
167
  "proposal.executed": "proposal",
103
168
  "proposal.failed": "proposal",
169
+ "audit.exported": "environment",
104
170
  "sign_in_test.started": "environment",
105
171
  "sign_in_test.finished": "environment"
106
172
  };
@@ -0,0 +1,151 @@
1
+ // src/organization-domain-rules.ts
2
+ var MAX_DOMAIN_LENGTH2 = 253;
3
+ var MAX_DOMAIN_LABEL_LENGTH2 = 63;
4
+ var MIN_DOMAIN_LENGTH2 = 4;
5
+ var MAX_DOMAINS_PER_ORGANIZATION2 = 10;
6
+ var DOMAIN_VERIFICATION_LIFETIME_DAYS2 = 365;
7
+ var DOMAIN_REMINDER_DAYS2 = [30, 7];
8
+ var DOMAIN_REVERIFICATION_GRACE_DAYS2 = 30;
9
+ var ORGANIZATION_DOMAIN_STATUSES2 = ["pending", "verified", "needs_reverification"];
10
+ var ORGANIZATION_DOMAIN_MODES2 = ["suggest", "auto_join"];
11
+ var DOMAIN_PATTERN2 = /^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2,}|xn--[a-z0-9-]*[a-z0-9])$/;
12
+ var PUBLIC_EMAIL_DOMAINS2 = [
13
+ "gmail.com",
14
+ "googlemail.com",
15
+ "outlook.com",
16
+ "hotmail.com",
17
+ "live.com",
18
+ "msn.com",
19
+ "passport.com",
20
+ "icloud.com",
21
+ "me.com",
22
+ "mac.com",
23
+ "proton.me",
24
+ "protonmail.com",
25
+ "protonmail.ch",
26
+ "pm.me",
27
+ "aol.com",
28
+ "aim.com",
29
+ "ymail.com",
30
+ "rocketmail.com",
31
+ "duck.com",
32
+ "privaterelay.appleid.com",
33
+ "simplelogin.com",
34
+ "simplelogin.co",
35
+ "aleeas.com",
36
+ "slmail.me",
37
+ "anonaddy.com",
38
+ "anonaddy.me",
39
+ "addy.io",
40
+ "mozmail.com",
41
+ "relay.firefox.com",
42
+ "passmail.net",
43
+ "passinbox.com",
44
+ "mailinator.com",
45
+ "guerrillamail.com",
46
+ "guerrillamail.net",
47
+ "10minutemail.com",
48
+ "tempmail.com",
49
+ "temp-mail.org",
50
+ "yopmail.com",
51
+ "sharklasers.com",
52
+ "trashmail.com",
53
+ "getnada.com",
54
+ "maildrop.cc",
55
+ "mail.com",
56
+ "email.com",
57
+ "zoho.com",
58
+ "zohomail.com",
59
+ "fastmail.com",
60
+ "fastmail.fm",
61
+ "hey.com",
62
+ "tutanota.com",
63
+ "tutanota.de",
64
+ "tutamail.com",
65
+ "tuta.io",
66
+ "tuta.com",
67
+ "hushmail.com",
68
+ "yandex.com",
69
+ "yandex.ru",
70
+ "ya.ru",
71
+ "mail.ru",
72
+ "inbox.ru",
73
+ "list.ru",
74
+ "bk.ru",
75
+ "gmx.com",
76
+ "gmx.net",
77
+ "gmx.de",
78
+ "gmx.at",
79
+ "gmx.ch",
80
+ "web.de",
81
+ "freenet.de",
82
+ "t-online.de",
83
+ "posteo.de",
84
+ "mailbox.org",
85
+ "runbox.com",
86
+ "comcast.net",
87
+ "verizon.net",
88
+ "att.net",
89
+ "sbcglobal.net",
90
+ "bellsouth.net",
91
+ "cox.net",
92
+ "charter.net",
93
+ "earthlink.net",
94
+ "btinternet.com",
95
+ "virginmedia.com",
96
+ "sky.com",
97
+ "talktalk.net",
98
+ "orange.fr",
99
+ "wanadoo.fr",
100
+ "free.fr",
101
+ "laposte.net",
102
+ "sfr.fr",
103
+ "libero.it",
104
+ "virgilio.it",
105
+ "tiscali.it",
106
+ "wp.pl",
107
+ "o2.pl",
108
+ "onet.pl",
109
+ "interia.pl",
110
+ "seznam.cz",
111
+ "rediffmail.com",
112
+ "qq.com",
113
+ "163.com",
114
+ "126.com",
115
+ "sina.com",
116
+ "naver.com",
117
+ "daum.net",
118
+ "hanmail.net"
119
+ ];
120
+ var PUBLIC_EMAIL_BRANDS2 = [
121
+ "yahoo",
122
+ "hotmail",
123
+ "outlook",
124
+ "live",
125
+ "gmail",
126
+ "icloud",
127
+ "protonmail"
128
+ ];
129
+ var PUBLIC_DOMAINS = new Set(PUBLIC_EMAIL_DOMAINS2);
130
+ var BRAND_PATTERN = new RegExp(`^(?:${PUBLIC_EMAIL_BRANDS2.join("|")})\\.(?:(?:co|com|net|org|ne|or|ac|gov|edu)\\.)?[a-z]{2,}$`);
131
+ function isPublicEmailDomain2(domain) {
132
+ return PUBLIC_DOMAINS.has(domain) || BRAND_PATTERN.test(domain);
133
+ }
134
+ function domainRefusal2(domain) {
135
+ if (domain.length > 2 * MAX_DOMAIN_LENGTH2 || !DOMAIN_PATTERN2.test(domain)) {
136
+ return "grammar";
137
+ }
138
+ if (domain.length > MAX_DOMAIN_LENGTH2 || domain.length < MIN_DOMAIN_LENGTH2 || domain.split(".").some((label) => label.length > MAX_DOMAIN_LABEL_LENGTH2)) {
139
+ return "length";
140
+ }
141
+ return isPublicEmailDomain2(domain) ? "public" : null;
142
+ }
143
+ function domainOfAddress2(address) {
144
+ const at = address.lastIndexOf("@");
145
+ if (at < 1 || at === address.length - 1) {
146
+ return null;
147
+ }
148
+ return address.slice(at + 1);
149
+ }
150
+
151
+ export { MAX_DOMAIN_LENGTH2, MAX_DOMAIN_LABEL_LENGTH2, MIN_DOMAIN_LENGTH2, MAX_DOMAINS_PER_ORGANIZATION2, DOMAIN_VERIFICATION_LIFETIME_DAYS2, DOMAIN_REMINDER_DAYS2, DOMAIN_REVERIFICATION_GRACE_DAYS2, ORGANIZATION_DOMAIN_STATUSES2, ORGANIZATION_DOMAIN_MODES2, DOMAIN_PATTERN2, PUBLIC_EMAIL_DOMAINS2, PUBLIC_EMAIL_BRANDS2, isPublicEmailDomain2, domainRefusal2, domainOfAddress2 };
@@ -1,5 +1,15 @@
1
+ import {
2
+ MAX_PERMISSION_KEY_LENGTH2,
3
+ ROLE_KEY_PATTERN2,
4
+ PERMISSION_KEY_PATTERN2
5
+ } from "./chunk-yzgakhtb.js";
6
+
1
7
  // src/custom-claims.ts
2
8
  var CUSTOM_CLAIMS_CLAIM2 = "ext";
9
+ var ORGANIZATION_ID_CLAIM2 = "org_id";
10
+ var SSO_CONNECTION_CLAIM2 = "sso_conn";
11
+ var ORGANIZATION_ROLE_CLAIM2 = "org_role";
12
+ var ORGANIZATION_PERMISSIONS_CLAIM2 = "org_perms";
3
13
  var RESERVED_CLAIM_NAMES2 = [
4
14
  "iss",
5
15
  "sub",
@@ -16,9 +26,59 @@ var RESERVED_CLAIM_NAMES2 = [
16
26
  "amr",
17
27
  "sp",
18
28
  "cnf",
29
+ ORGANIZATION_ID_CLAIM2,
30
+ ORGANIZATION_ROLE_CLAIM2,
31
+ ORGANIZATION_PERMISSIONS_CLAIM2,
32
+ SSO_CONNECTION_CLAIM2,
19
33
  CUSTOM_CLAIMS_CLAIM2
20
34
  ];
21
35
  var MAX_CUSTOM_CLAIMS_BYTES2 = 1024;
36
+ var MAX_ORGANIZATION_CLAIMS_BYTES2 = 2560;
37
+ var MAX_ORGANIZATION_PERMISSIONS_CLAIM2 = 32;
38
+ function organizationClaimsBytes2(claims) {
39
+ return utf8Length(JSON.stringify({
40
+ [ORGANIZATION_ID_CLAIM2]: claims.orgId,
41
+ [ORGANIZATION_ROLE_CLAIM2]: claims.orgRole,
42
+ [ORGANIZATION_PERMISSIONS_CLAIM2]: claims.orgPermissions
43
+ }));
44
+ }
45
+ var ORGANIZATION_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
46
+ function readOrganizationClaims2(claims) {
47
+ if (typeof claims !== "object" || claims === null) {
48
+ return null;
49
+ }
50
+ const record = claims;
51
+ const [id, role, permissions] = [
52
+ record[ORGANIZATION_ID_CLAIM2],
53
+ record[ORGANIZATION_ROLE_CLAIM2],
54
+ record[ORGANIZATION_PERMISSIONS_CLAIM2]
55
+ ];
56
+ if (typeof id !== "string" || !ORGANIZATION_ID_PATTERN.test(id) || typeof role !== "string" || !ROLE_KEY_PATTERN2.test(role) || !Array.isArray(permissions) || permissions.length > MAX_ORGANIZATION_PERMISSIONS_CLAIM2 || !permissions.every((permission) => typeof permission === "string" && permission.length <= MAX_PERMISSION_KEY_LENGTH2 && PERMISSION_KEY_PATTERN2.test(permission))) {
57
+ return null;
58
+ }
59
+ const read = Object.freeze({
60
+ orgId: id,
61
+ orgRole: role,
62
+ orgPermissions: Object.freeze([...permissions])
63
+ });
64
+ return organizationClaimsBytes2(read) > MAX_ORGANIZATION_CLAIMS_BYTES2 ? null : read;
65
+ }
66
+ function hasOrganizationAccess2(claims, check) {
67
+ if (!claims || typeof check !== "object" || check === null) {
68
+ return false;
69
+ }
70
+ const { permission, role } = check;
71
+ if (permission !== undefined && role !== undefined) {
72
+ return false;
73
+ }
74
+ if (typeof permission === "string" && permission !== "") {
75
+ return claims.orgPermissions.includes(permission);
76
+ }
77
+ if (typeof role === "string" && role !== "") {
78
+ return claims.orgRole === role;
79
+ }
80
+ return false;
81
+ }
22
82
  var MAX_JWT_TEMPLATES2 = 10;
23
83
  var MAX_JWT_TEMPLATE_CLAIMS2 = 16;
24
84
  var MAX_CUSTOM_CLAIM_KEY_LENGTH2 = 32;
@@ -99,4 +159,4 @@ function readCustomClaims2(claims) {
99
159
  return customClaimsBytes2(read) <= MAX_CUSTOM_CLAIMS_BYTES2 ? Object.freeze(read) : null;
100
160
  }
101
161
 
102
- export { CUSTOM_CLAIMS_CLAIM2, RESERVED_CLAIM_NAMES2, MAX_CUSTOM_CLAIMS_BYTES2, MAX_JWT_TEMPLATES2, MAX_JWT_TEMPLATE_CLAIMS2, MAX_CUSTOM_CLAIM_KEY_LENGTH2, MAX_CUSTOM_CLAIM_CONSTANT_LENGTH2, isCustomClaimKey2, isCustomClaimValue2, customClaimsBytes2, checkCustomClaims2, readCustomClaims2 };
162
+ export { CUSTOM_CLAIMS_CLAIM2, ORGANIZATION_ID_CLAIM2, SSO_CONNECTION_CLAIM2, ORGANIZATION_ROLE_CLAIM2, ORGANIZATION_PERMISSIONS_CLAIM2, RESERVED_CLAIM_NAMES2, MAX_CUSTOM_CLAIMS_BYTES2, MAX_ORGANIZATION_CLAIMS_BYTES2, MAX_ORGANIZATION_PERMISSIONS_CLAIM2, organizationClaimsBytes2, readOrganizationClaims2, hasOrganizationAccess2, MAX_JWT_TEMPLATES2, MAX_JWT_TEMPLATE_CLAIMS2, MAX_CUSTOM_CLAIM_KEY_LENGTH2, MAX_CUSTOM_CLAIM_CONSTANT_LENGTH2, isCustomClaimKey2, isCustomClaimValue2, customClaimsBytes2, checkCustomClaims2, readCustomClaims2 };
@@ -35,44 +35,44 @@ var THEME_TOKENS2 = [
35
35
  var DEFAULT_THEME2 = {
36
36
  light: {
37
37
  background: "#ffffff",
38
- surface: "#f5f4f0",
38
+ surface: "#f1efe8",
39
39
  input: "#ffffff",
40
- text: "#17171c",
41
- textMuted: "#5c5a55",
42
- primary: "#5b4cf0",
43
- primaryHover: "#4a3bdc",
44
- primaryText: "#ffffff",
40
+ text: "#1a1a18",
41
+ textMuted: "#5f5e5a",
42
+ primary: "#1a1a18",
43
+ primaryHover: "#3a3935",
44
+ primaryText: "#f1efe8",
45
45
  link: "#4a3bdc",
46
- border: "#e3e0d8",
46
+ border: "#d9d6cb",
47
47
  borderStrong: "#8a877e",
48
48
  danger: "#b42318",
49
- dangerSurface: "#fdecea",
49
+ dangerSurface: "#fcefec",
50
50
  success: "#1a6b3c",
51
- focus: "#5b4cf0",
52
- overlay: "rgba(23, 23, 28, 0.55)",
53
- shadow: "0 1px 2px rgba(23, 23, 28, 0.06), 0 12px 32px rgba(23, 23, 28, 0.1)"
51
+ focus: "#4a3bdc",
52
+ overlay: "rgba(26, 26, 24, 0.55)",
53
+ shadow: "0 1px 2px rgba(26, 26, 24, 0.05), 0 8px 24px rgba(26, 26, 24, 0.08)"
54
54
  },
55
55
  dark: {
56
- background: "#17171c",
57
- surface: "#202128",
58
- input: "#101014",
59
- text: "#f4f4f6",
60
- textMuted: "#a9a9b4",
61
- primary: "#8f84ff",
62
- primaryHover: "#a59cff",
63
- primaryText: "#121117",
64
- link: "#aaa2ff",
65
- border: "#2e2f39",
66
- borderStrong: "#74758a",
67
- danger: "#ff8a80",
68
- dangerSurface: "#3a1a1c",
69
- success: "#6fd49a",
70
- focus: "#aaa2ff",
56
+ background: "#1c1c19",
57
+ surface: "#232320",
58
+ input: "#141412",
59
+ text: "#f1efe8",
60
+ textMuted: "#b0ada2",
61
+ primary: "#f1efe8",
62
+ primaryHover: "#ffffff",
63
+ primaryText: "#141412",
64
+ link: "#a69dff",
65
+ border: "#34332e",
66
+ borderStrong: "#7a776d",
67
+ danger: "#ff8a7a",
68
+ dangerSurface: "#3a1f1b",
69
+ success: "#5fcb8a",
70
+ focus: "#a69dff",
71
71
  overlay: "rgba(0, 0, 0, 0.65)",
72
- shadow: "0 1px 2px rgba(0, 0, 0, 0.4), 0 12px 32px rgba(0, 0, 0, 0.5)"
72
+ shadow: "0 1px 2px rgba(0, 0, 0, 0.4), 0 16px 40px rgba(0, 0, 0, 0.5)"
73
73
  },
74
- radius: "12px",
75
- radiusSmall: "8px",
74
+ radius: "10px",
75
+ radiusSmall: "6px",
76
76
  fontFamily: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
77
77
  fontFamilyMono: 'ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace',
78
78
  fontSize: "0.9375rem",
@@ -27,13 +27,17 @@ var EMAIL_TEMPLATE_KINDS2 = [
27
27
  "identity_linked",
28
28
  "identity_unlinked",
29
29
  "email_in_use",
30
- "email_added"
30
+ "email_added",
31
+ "organization_domain_verification",
32
+ "organization_domain_expiring",
33
+ "organization_invitation"
31
34
  ];
32
35
  var EMAIL_TEMPLATE_PLACEHOLDERS2 = [
33
36
  "appName",
34
37
  "code",
35
38
  "link",
36
39
  "expiresInMinutes",
40
+ "expiresInDays",
37
41
  "device",
38
42
  "time",
39
43
  "provider",
@@ -42,6 +46,7 @@ var EMAIL_TEMPLATE_PLACEHOLDERS2 = [
42
46
  var EMAIL_TEMPLATE_DIGIT_PLACEHOLDERS2 = [
43
47
  "code",
44
48
  "expiresInMinutes",
49
+ "expiresInDays",
45
50
  "time",
46
51
  "backupCodesLeft"
47
52
  ];
@@ -84,7 +89,14 @@ var EMAIL_TEMPLATE_RULES2 = {
84
89
  identity_linked: { ...NOTICE, optional: ["appName", "time", "provider"] },
85
90
  identity_unlinked: { ...NOTICE, optional: ["appName", "time", "provider"] },
86
91
  email_in_use: DECOY,
87
- email_added: NOTICE
92
+ email_added: NOTICE,
93
+ organization_domain_verification: CODE,
94
+ organization_domain_expiring: { ...NOTICE, optional: ["appName", "expiresInDays"] },
95
+ organization_invitation: {
96
+ category: "invitation",
97
+ required: ["link"],
98
+ optional: ["appName", "expiresInDays"]
99
+ }
88
100
  };
89
101
  var MAX_EMAIL_SUBJECT_LENGTH2 = 200;
90
102
  var MAX_EMAIL_BODY_LENGTH2 = 2000;
@@ -235,7 +247,7 @@ function fieldProblems(kind, field, text) {
235
247
  if (readsAsLink2(withStandIns(tokens))) {
236
248
  problems.push(problem("reads_as_link", "must not contain a link, an address or a domain name (put a space after a full stop)"));
237
249
  }
238
- if (rules.category === "notice" && field === "subject" && /^\p{Nd}/u.test(visibleEmailText2(withLeadingStandIns(tokens)))) {
250
+ if (rules.category !== "code" && field === "subject" && /^\p{Nd}/u.test(visibleEmailText2(withLeadingStandIns(tokens)))) {
239
251
  problems.push(problem("leading_digit", "the subject of a notice must not start with a digit, or with a placeholder that is always a number or a time"));
240
252
  }
241
253
  return problems;
@@ -385,6 +397,9 @@ function webKindOf(value) {
385
397
  if (url.username !== "" || url.password !== "" || url.hash !== "") {
386
398
  return null;
387
399
  }
400
+ if (value.includes("#")) {
401
+ return null;
402
+ }
388
403
  if (url.protocol === "https:") {
389
404
  return "https";
390
405
  }