@tula-tech/contract 0.2.0 → 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.
@@ -0,0 +1,132 @@
1
+ /** Longest a whole domain can be, in characters (RFC 1035). */
2
+ declare const MAX_DOMAIN_LENGTH = 253;
3
+ /** Longest one label of a domain can be, in characters (RFC 1035). */
4
+ declare const MAX_DOMAIN_LABEL_LENGTH = 63;
5
+ /** Shortest a domain can be: `a.bc`. */
6
+ declare const MIN_DOMAIN_LENGTH = 4;
7
+ /**
8
+ * How many domains one organization can claim, verified or waiting for a code. A bound so that
9
+ * a signed-in administrator cannot fill the table.
10
+ */
11
+ declare const MAX_DOMAINS_PER_ORGANIZATION = 10;
12
+ /**
13
+ * How long a verification of a domain lasts, in days.
14
+ * A domain can be lost and registered again by someone else, and nothing tells Tula, so a
15
+ * claim is only believed for this long: past it the domain matches nobody (no auto-join, no
16
+ * suggestion) until a manager proves it again with a new emailed code. Counted from the day
17
+ * the code was entered.
18
+ */
19
+ declare const DOMAIN_VERIFICATION_LIFETIME_DAYS = 365;
20
+ /**
21
+ * How many days before a verification lapses the organization's managers are emailed, largest
22
+ * first. Each is sent once per verification: a reminder is never repeated, and re-verifying
23
+ * starts the series again.
24
+ */
25
+ declare const DOMAIN_REMINDER_DAYS: readonly number[];
26
+ /**
27
+ * The least time, in days, that a domain verified before the lifetime existed (migration
28
+ * 0042) keeps matching after the migration: its deadline is the later of the original
29
+ * `verified_at` plus the lifetime and this many days from the migration, so that nobody is
30
+ * cut off the day the change ships and every manager gets a reminder before it ends.
31
+ */
32
+ declare const DOMAIN_REVERIFICATION_GRACE_DAYS = 30;
33
+ /** What a domain row is: waiting for its first code, verified, or past its lifetime. */
34
+ declare const ORGANIZATION_DOMAIN_STATUSES: readonly ["pending", "verified", "needs_reverification"];
35
+ /** One of {@link ORGANIZATION_DOMAIN_STATUSES}. */
36
+ type OrganizationDomainStatus = (typeof ORGANIZATION_DOMAIN_STATUSES)[number];
37
+ /** How an organization treats a user who signs up with a verified address on its domain. */
38
+ declare const ORGANIZATION_DOMAIN_MODES: readonly ["suggest", "auto_join"];
39
+ /** One of {@link ORGANIZATION_DOMAIN_MODES}. */
40
+ type OrganizationDomainMode = (typeof ORGANIZATION_DOMAIN_MODES)[number];
41
+ /**
42
+ * The grammar of a claimable domain: two or more labels of lower-case ASCII letters, digits
43
+ * and hyphens (none at a label's end), joined by single full stops, the last label letters
44
+ * only (or punycode, `xn--…`). So: no upper case, no trailing full stop, no port or path, no
45
+ * underscore, no `@`, no wildcard, and no IP address (a numeric last label is refused, and so
46
+ * is the bracketed IPv6 form).
47
+ *
48
+ * **Internationalised domains are written in punycode** (`xn--bcher-kva.example`, never
49
+ * `bücher.example`): Unicode is refused, not converted, so a domain is stored and compared in
50
+ * the one spelling a mail server uses. The pattern is the grammar alone; the length bounds
51
+ * ({@link MAX_DOMAIN_LENGTH}, {@link MAX_DOMAIN_LABEL_LENGTH}) and the public list are
52
+ * {@link domainRefusal}'s. `domainRefusal` runs it only over text of at most twice the length cap,
53
+ * so its work is bounded.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * DOMAIN_PATTERN.test('acme.com') // true
58
+ * DOMAIN_PATTERN.test('Acme.com') // false
59
+ * DOMAIN_PATTERN.test('192.168.0.1') // false
60
+ * ```
61
+ */
62
+ declare const DOMAIN_PATTERN: RegExp;
63
+ /** Why a string is not a claimable domain. */
64
+ type DomainRefusal = "grammar" | "length" | "public";
65
+ /**
66
+ * Domains that anyone can get an address at, and that so prove nothing about the holder of an
67
+ * address on them. **Documented here and nowhere else**: a claim of one is refused
68
+ * (`organization.domain_public`) and a join never matches one, even a claim stored before the
69
+ * list grew. The list is the large free consumer mailbox providers, the internet providers
70
+ * that give every customer an address, and the common national ones; a company's own domain
71
+ * is never on it.
72
+ *
73
+ * Providers that sell a mailbox under many country domains (`yahoo.co.uk`, `yahoo.fr`,
74
+ * `hotmail.de`, …) are in {@link PUBLIC_EMAIL_BRANDS} instead.
75
+ */
76
+ declare const PUBLIC_EMAIL_DOMAINS: readonly string[];
77
+ /**
78
+ * Provider names whose every country domain is public: `yahoo.com`, `yahoo.co.uk`, `yahoo.fr`
79
+ * and `yahoo.co.jp` are all `yahoo`. A domain matches when its **first** label is one of
80
+ * these and what follows is a top-level domain, or a short second-level one and a top-level
81
+ * one (`co.uk`, `com.br`): `yahoo.com` and `hotmail.co.uk` match, `yahoo.acme.com` and
82
+ * `notyahoo.com` do not.
83
+ */
84
+ declare const PUBLIC_EMAIL_BRANDS: readonly string[];
85
+ /**
86
+ * Whether anyone can get an address on this domain: it is on {@link PUBLIC_EMAIL_DOMAINS} or
87
+ * is a country domain of one of {@link PUBLIC_EMAIL_BRANDS}.
88
+ *
89
+ * @param domain - A domain in the spelling of {@link DOMAIN_PATTERN}.
90
+ * @returns `true` for a public mail domain.
91
+ * @example
92
+ * ```ts
93
+ * isPublicEmailDomain('gmail.com') // true
94
+ * isPublicEmailDomain('yahoo.co.uk') // true
95
+ * isPublicEmailDomain('acme.com') // false
96
+ * ```
97
+ */
98
+ declare function isPublicEmailDomain(domain: string): boolean;
99
+ /**
100
+ * Why a string cannot be claimed as a domain, or `null` when it can.
101
+ *
102
+ * @param domain - The text to judge.
103
+ * @returns `grammar` (not a lower-case ASCII domain name: upper case, Unicode, an IP address,
104
+ * a single label), `length` (a label over {@link MAX_DOMAIN_LABEL_LENGTH}, the whole over
105
+ * {@link MAX_DOMAIN_LENGTH} or under {@link MIN_DOMAIN_LENGTH}), `public` (a public mail
106
+ * domain), or `null`.
107
+ * @example
108
+ * ```ts
109
+ * domainRefusal('acme.com') // null
110
+ * domainRefusal('gmail.com') // 'public'
111
+ * domainRefusal('bücher.example') // 'grammar'
112
+ * ```
113
+ */
114
+ declare function domainRefusal(domain: string): DomainRefusal | null;
115
+ /**
116
+ * The domain of an email address in the spelling the server stores (lower case), or `null`
117
+ * when the text has no `@` or ends in one.
118
+ *
119
+ * It is everything after the **last** `@`, unchanged: no subdomain is cut off, so
120
+ * `a@mail.acme.com` is `mail.acme.com` and **never** matches a claim on `acme.com`. Whether the
121
+ * result is a domain at all is {@link domainRefusal}'s question.
122
+ *
123
+ * @param address - An email address, normalised (lower case) by the caller.
124
+ * @returns The part after the last `@`, or `null`.
125
+ * @example
126
+ * ```ts
127
+ * domainOfAddress('ada@acme.com') // 'acme.com'
128
+ * domainOfAddress('ada@mail.acme.com') // 'mail.acme.com'
129
+ * ```
130
+ */
131
+ declare function domainOfAddress(address: string): string | null;
132
+ export { DOMAIN_PATTERN, DOMAIN_REMINDER_DAYS, DOMAIN_REVERIFICATION_GRACE_DAYS, DOMAIN_VERIFICATION_LIFETIME_DAYS, DomainRefusal, MAX_DOMAINS_PER_ORGANIZATION, MAX_DOMAIN_LABEL_LENGTH, MAX_DOMAIN_LENGTH, MIN_DOMAIN_LENGTH, ORGANIZATION_DOMAIN_MODES, ORGANIZATION_DOMAIN_STATUSES, OrganizationDomainMode, OrganizationDomainStatus, PUBLIC_EMAIL_BRANDS, PUBLIC_EMAIL_DOMAINS, domainOfAddress, domainRefusal, isPublicEmailDomain };
@@ -0,0 +1,34 @@
1
+ import {
2
+ MAX_DOMAIN_LENGTH2,
3
+ MAX_DOMAIN_LABEL_LENGTH2,
4
+ MIN_DOMAIN_LENGTH2,
5
+ MAX_DOMAINS_PER_ORGANIZATION2,
6
+ DOMAIN_VERIFICATION_LIFETIME_DAYS2,
7
+ DOMAIN_REMINDER_DAYS2,
8
+ DOMAIN_REVERIFICATION_GRACE_DAYS2,
9
+ ORGANIZATION_DOMAIN_STATUSES2,
10
+ ORGANIZATION_DOMAIN_MODES2,
11
+ DOMAIN_PATTERN2,
12
+ PUBLIC_EMAIL_DOMAINS2,
13
+ PUBLIC_EMAIL_BRANDS2,
14
+ isPublicEmailDomain2,
15
+ domainRefusal2,
16
+ domainOfAddress2
17
+ } from "./shared/chunk-cdg41bxh.js";
18
+ export {
19
+ DOMAIN_PATTERN2 as DOMAIN_PATTERN,
20
+ DOMAIN_REMINDER_DAYS2 as DOMAIN_REMINDER_DAYS,
21
+ DOMAIN_REVERIFICATION_GRACE_DAYS2 as DOMAIN_REVERIFICATION_GRACE_DAYS,
22
+ DOMAIN_VERIFICATION_LIFETIME_DAYS2 as DOMAIN_VERIFICATION_LIFETIME_DAYS,
23
+ MAX_DOMAINS_PER_ORGANIZATION2 as MAX_DOMAINS_PER_ORGANIZATION,
24
+ MAX_DOMAIN_LABEL_LENGTH2 as MAX_DOMAIN_LABEL_LENGTH,
25
+ MAX_DOMAIN_LENGTH2 as MAX_DOMAIN_LENGTH,
26
+ MIN_DOMAIN_LENGTH2 as MIN_DOMAIN_LENGTH,
27
+ ORGANIZATION_DOMAIN_MODES2 as ORGANIZATION_DOMAIN_MODES,
28
+ ORGANIZATION_DOMAIN_STATUSES2 as ORGANIZATION_DOMAIN_STATUSES,
29
+ PUBLIC_EMAIL_BRANDS2 as PUBLIC_EMAIL_BRANDS,
30
+ PUBLIC_EMAIL_DOMAINS2 as PUBLIC_EMAIL_DOMAINS,
31
+ domainOfAddress2 as domainOfAddress,
32
+ domainRefusal2 as domainRefusal,
33
+ isPublicEmailDomain2 as isPublicEmailDomain
34
+ };
@@ -0,0 +1,185 @@
1
+ /**
2
+ * How many permissions one role can hold. The permissions of the active organization's role are
3
+ * a claim of every access token, so the number is capped.
4
+ */
5
+ declare const MAX_PERMISSIONS_PER_ROLE = 32;
6
+ /** How many custom roles an environment can define, beside the built-in ones. */
7
+ declare const MAX_CUSTOM_ROLES = 50;
8
+ /** The longest a permission key can be, in characters. */
9
+ declare const MAX_PERMISSION_KEY_LENGTH = 100;
10
+ /**
11
+ * The grammar of a role's key: a lower-case letter, then lower-case letters, digits and
12
+ * underscores, up to 32 characters (`admin`, `billing_manager`). Unique in its environment.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * ROLE_KEY_PATTERN.test('billing_manager') // true
17
+ * ```
18
+ */
19
+ declare const ROLE_KEY_PATTERN: RegExp;
20
+ /**
21
+ * The grammar of a permission key: `org:<feature>:<action>`, each of the last two
22
+ * a lower-case letter followed by lower-case letters, digits and underscores (at most 32
23
+ * characters); or, for the permissions Tula's own routes check, `org:sys:<feature>:<action>`.
24
+ * No dot, no other separator: a key is safe in a token and in a URL. The feature `sys` is
25
+ * reserved: a custom key never has it, and a system key is one of
26
+ * {@link SYSTEM_PERMISSIONS}.
27
+ *
28
+ * The pattern is the grammar alone. Whether a role may hold a key is
29
+ * {@link rolePermissionRefusal}.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * PERMISSION_KEY_PATTERN.test('org:billing:read') // true
34
+ * PERMISSION_KEY_PATTERN.test('org:sys:memberships:manage') // true
35
+ * PERMISSION_KEY_PATTERN.test('billing.read') // false
36
+ * ```
37
+ */
38
+ declare const PERMISSION_KEY_PATTERN: RegExp;
39
+ /**
40
+ * The permissions Tula's own organization routes check. The same keys an app's
41
+ * server checks with `has({ permission })`, so Tula's routes hold no privilege an app cannot
42
+ * also give a role.
43
+ */
44
+ declare const SYSTEM_PERMISSIONS: readonly ["org:sys:organization:manage", "org:sys:organization:delete", "org:sys:memberships:read", "org:sys:memberships:manage", "org:sys:invitations:manage", "org:sys:domains:manage", "org:sys:sso:manage"];
45
+ /** One of {@link SYSTEM_PERMISSIONS}. */
46
+ type SystemPermission = (typeof SYSTEM_PERMISSIONS)[number];
47
+ /**
48
+ * The permission that makes a member a manager of the organization's members. **Every
49
+ * organization keeps at least one member who holds it**: the last such member cannot be
50
+ * removed or moved to a role without it (`organization.last_manager`), and a role's
51
+ * permissions cannot be changed so that an organization would be left with none.
52
+ */
53
+ declare const MEMBERSHIPS_MANAGE_PERMISSION: SystemPermission;
54
+ /**
55
+ * The permission that lets a member claim, verify, change and remove the organization's
56
+ * domains through the client routes. Read from the member's
57
+ * role at the time of the request, never from a token.
58
+ */
59
+ declare const DOMAINS_MANAGE_PERMISSION: SystemPermission;
60
+ /**
61
+ * The permission that lets a member invite people to the organization and withdraw
62
+ * invitations. Checked on the server from the membership as it is now,
63
+ * never from a token's claims alone.
64
+ */
65
+ declare const INVITATIONS_MANAGE_PERMISSION: SystemPermission;
66
+ /**
67
+ * The permission that lets a member rename the organization through the client routes.
68
+ * Read from the membership now, never from a token's claims alone.
69
+ */
70
+ declare const ORGANIZATION_MANAGE_PERMISSION: SystemPermission;
71
+ /**
72
+ * The permission that lets a member delete the organization through the client routes.
73
+ * Read from the membership now, never from a token's claims alone.
74
+ */
75
+ declare const ORGANIZATION_DELETE_PERMISSION: SystemPermission;
76
+ /**
77
+ * The permission that lets a member read the organization's member list through the client
78
+ * routes. `org:sys:memberships:manage` also reads it.
79
+ */
80
+ declare const MEMBERSHIPS_READ_PERMISSION: SystemPermission;
81
+ /**
82
+ * The permission that lets a member manage the organization's single sign-on connections.
83
+ * Read from the membership now, never from a token's claims alone.
84
+ */
85
+ declare const SSO_MANAGE_PERMISSION: SystemPermission;
86
+ /** A built-in role: its key, its name and the permissions it holds. */
87
+ interface BuiltInRole {
88
+ readonly key: string;
89
+ readonly name: string;
90
+ readonly permissions: readonly SystemPermission[];
91
+ }
92
+ /**
93
+ * The two roles every environment has: `admin` holds every system permission,
94
+ * `member` may read the member list. They cannot be deleted, renamed or given other
95
+ * permissions. They exist as rows of every environment (`ensureBuiltInRoles`) so that a
96
+ * membership refers to a role the way it does to a custom one.
97
+ */
98
+ declare const BUILT_IN_ROLES: readonly BuiltInRole[];
99
+ /**
100
+ * Whether a string is one of {@link SYSTEM_PERMISSIONS}.
101
+ *
102
+ * @param key - A permission key.
103
+ * @returns `true` for one of Tula's own permissions.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * isSystemPermission('org:sys:memberships:read') // true
108
+ * isSystemPermission('org:billing:read') // false
109
+ * ```
110
+ */
111
+ declare function isSystemPermission(key: string): key is SystemPermission;
112
+ /**
113
+ * Whether a string is the key of a built-in role (`admin`, `member`). A custom role never
114
+ * takes one of these keys.
115
+ *
116
+ * @param key - A role key.
117
+ * @returns `true` for a built-in role's key.
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * isBuiltInRoleKey('admin') // true
122
+ * isBuiltInRoleKey('billing_manager') // false
123
+ * ```
124
+ */
125
+ declare function isBuiltInRoleKey(key: string): boolean;
126
+ /** Why a custom role may not hold a permission key. */
127
+ type RolePermissionRefusal = "grammar" | "reserved";
128
+ /**
129
+ * Whether a **custom** role may hold a permission key.
130
+ *
131
+ * A custom role holds the operator's own permissions (`org:billing:read`) and may also hold
132
+ * any of Tula's {@link SYSTEM_PERMISSIONS}, so that a role such as `owner` can manage members.
133
+ * It can never hold a key of the reserved `sys` feature that is not on that list: a key Tula
134
+ * does not check would mean nothing today and silently grant a privilege tomorrow, when a
135
+ * later version gives that key a meaning.
136
+ *
137
+ * @param key - A permission key.
138
+ * @returns `null` when the role may hold it, `'grammar'` when it is not a permission key at
139
+ * all, `'reserved'` when it is a `sys` key Tula does not define.
140
+ *
141
+ * @example
142
+ * ```ts
143
+ * rolePermissionRefusal('org:billing:read') // null
144
+ * rolePermissionRefusal('org:sys:memberships:manage') // null
145
+ * rolePermissionRefusal('org:sys:billing:read') // 'reserved'
146
+ * rolePermissionRefusal('billing.read') // 'grammar'
147
+ * ```
148
+ */
149
+ declare function rolePermissionRefusal(key: string): RolePermissionRefusal | null;
150
+ /**
151
+ * The permissions of a role as a set: each key once, sorted. How a role is stored, compared
152
+ * and returned, so that the order a caller listed them in is never a difference.
153
+ *
154
+ * @param permissions - Permission keys, in any order, possibly with repeats.
155
+ * @returns The distinct keys, sorted.
156
+ *
157
+ * @example
158
+ * ```ts
159
+ * normalizePermissions(['org:b:read', 'org:a:read', 'org:b:read']) // ['org:a:read', 'org:b:read']
160
+ * ```
161
+ */
162
+ declare function normalizePermissions(permissions: readonly string[]): string[];
163
+ /**
164
+ * What a change to a custom role's permissions widens, the one rule the server records
165
+ * `weakened` with, `tula apply` asks `--allow-weaker` with and the dashboard asks first with.
166
+ *
167
+ * **Adding a permission to a role is a weakening** (members who hold the role gain access at
168
+ * their next refresh); taking one away is not. **Creating a role is not one**: no member holds
169
+ * it until someone assigns it, and that assignment is a membership change of its own. Deleting
170
+ * a role is not one: only a role no member holds can be deleted.
171
+ *
172
+ * @param before - The permissions the role has, or `null` for a role that does not exist yet.
173
+ * @param after - The permissions it would have.
174
+ * @returns `['permissions']` when `after` holds a key `before` does not, otherwise `[]`.
175
+ *
176
+ * @example
177
+ * ```ts
178
+ * organizationRoleWeakenings(['org:billing:read'], ['org:billing:read', 'org:billing:write'])
179
+ * // ['permissions']
180
+ * organizationRoleWeakenings(['org:billing:read'], []) // []
181
+ * organizationRoleWeakenings(null, ['org:billing:read']) // []
182
+ * ```
183
+ */
184
+ declare function organizationRoleWeakenings(before: readonly string[] | null, after: readonly string[]): "permissions"[];
185
+ export { BUILT_IN_ROLES, BuiltInRole, DOMAINS_MANAGE_PERMISSION, INVITATIONS_MANAGE_PERMISSION, MAX_CUSTOM_ROLES, MAX_PERMISSIONS_PER_ROLE, MAX_PERMISSION_KEY_LENGTH, MEMBERSHIPS_MANAGE_PERMISSION, MEMBERSHIPS_READ_PERMISSION, ORGANIZATION_DELETE_PERMISSION, ORGANIZATION_MANAGE_PERMISSION, PERMISSION_KEY_PATTERN, ROLE_KEY_PATTERN, RolePermissionRefusal, SSO_MANAGE_PERMISSION, SYSTEM_PERMISSIONS, SystemPermission, isBuiltInRoleKey, isSystemPermission, normalizePermissions, organizationRoleWeakenings, rolePermissionRefusal };
@@ -0,0 +1,42 @@
1
+ import {
2
+ MAX_PERMISSIONS_PER_ROLE2,
3
+ MAX_CUSTOM_ROLES2,
4
+ MAX_PERMISSION_KEY_LENGTH2,
5
+ ROLE_KEY_PATTERN2,
6
+ PERMISSION_KEY_PATTERN2,
7
+ SYSTEM_PERMISSIONS2,
8
+ MEMBERSHIPS_MANAGE_PERMISSION2,
9
+ DOMAINS_MANAGE_PERMISSION2,
10
+ INVITATIONS_MANAGE_PERMISSION2,
11
+ ORGANIZATION_MANAGE_PERMISSION2,
12
+ ORGANIZATION_DELETE_PERMISSION2,
13
+ MEMBERSHIPS_READ_PERMISSION2,
14
+ SSO_MANAGE_PERMISSION2,
15
+ BUILT_IN_ROLES2,
16
+ isSystemPermission2,
17
+ isBuiltInRoleKey2,
18
+ rolePermissionRefusal2,
19
+ normalizePermissions2,
20
+ organizationRoleWeakenings2
21
+ } from "./shared/chunk-yzgakhtb.js";
22
+ export {
23
+ BUILT_IN_ROLES2 as BUILT_IN_ROLES,
24
+ DOMAINS_MANAGE_PERMISSION2 as DOMAINS_MANAGE_PERMISSION,
25
+ INVITATIONS_MANAGE_PERMISSION2 as INVITATIONS_MANAGE_PERMISSION,
26
+ MAX_CUSTOM_ROLES2 as MAX_CUSTOM_ROLES,
27
+ MAX_PERMISSIONS_PER_ROLE2 as MAX_PERMISSIONS_PER_ROLE,
28
+ MAX_PERMISSION_KEY_LENGTH2 as MAX_PERMISSION_KEY_LENGTH,
29
+ MEMBERSHIPS_MANAGE_PERMISSION2 as MEMBERSHIPS_MANAGE_PERMISSION,
30
+ MEMBERSHIPS_READ_PERMISSION2 as MEMBERSHIPS_READ_PERMISSION,
31
+ ORGANIZATION_DELETE_PERMISSION2 as ORGANIZATION_DELETE_PERMISSION,
32
+ ORGANIZATION_MANAGE_PERMISSION2 as ORGANIZATION_MANAGE_PERMISSION,
33
+ PERMISSION_KEY_PATTERN2 as PERMISSION_KEY_PATTERN,
34
+ ROLE_KEY_PATTERN2 as ROLE_KEY_PATTERN,
35
+ SSO_MANAGE_PERMISSION2 as SSO_MANAGE_PERMISSION,
36
+ SYSTEM_PERMISSIONS2 as SYSTEM_PERMISSIONS,
37
+ isBuiltInRoleKey2 as isBuiltInRoleKey,
38
+ isSystemPermission2 as isSystemPermission,
39
+ normalizePermissions2 as normalizePermissions,
40
+ organizationRoleWeakenings2 as organizationRoleWeakenings,
41
+ rolePermissionRefusal2 as rolePermissionRefusal
42
+ };
@@ -108,6 +108,22 @@ declare const ERROR_DEFINITIONS: {
108
108
  readonly status: 409;
109
109
  readonly message: "This account has no password yet. Use \"forgot password\" to set one.";
110
110
  };
111
+ readonly "import.unsupported_algorithm": {
112
+ readonly status: 422;
113
+ readonly message: "That password hash algorithm is not supported.";
114
+ };
115
+ readonly "import.hash_malformed": {
116
+ readonly status: 422;
117
+ readonly message: "That password hash is malformed.";
118
+ };
119
+ readonly "import.hash_parameters_too_weak": {
120
+ readonly status: 422;
121
+ readonly message: "That password hash is too weak to import.";
122
+ };
123
+ readonly "import.hash_parameters_too_costly": {
124
+ readonly status: 422;
125
+ readonly message: "That password hash is too costly to verify.";
126
+ };
111
127
  readonly "verification.invalid_code": {
112
128
  readonly status: 422;
113
129
  readonly message: "That code is incorrect.";
@@ -300,6 +316,194 @@ declare const ERROR_DEFINITIONS: {
300
316
  readonly status: 400;
301
317
  readonly message: "Signing in here needs a device key.";
302
318
  };
319
+ readonly "user.last_organization_manager": {
320
+ readonly status: 409;
321
+ readonly message: "This user is the only manager of an organization. Add another manager or delete the organization first.";
322
+ };
323
+ readonly "user.managed": {
324
+ readonly status: 403;
325
+ readonly message: "This account is managed by your organization. Ask your administrator to change it.";
326
+ };
327
+ readonly "organization.disabled": {
328
+ readonly status: 403;
329
+ readonly message: "Organizations are not enabled for this environment.";
330
+ };
331
+ readonly "organization.slug_taken": {
332
+ readonly status: 409;
333
+ readonly message: "An organization with that slug already exists.";
334
+ };
335
+ readonly "organization.member_exists": {
336
+ readonly status: 409;
337
+ readonly message: "That user is already a member of this organization.";
338
+ };
339
+ readonly "organization.last_manager": {
340
+ readonly status: 409;
341
+ readonly message: "An organization must keep at least one member who can manage its members.";
342
+ };
343
+ readonly "organization.role_unknown": {
344
+ readonly status: 422;
345
+ readonly message: "That role does not exist in this environment.";
346
+ };
347
+ readonly "organization.not_a_member": {
348
+ readonly status: 403;
349
+ readonly message: "You are not a member of that organization.";
350
+ };
351
+ readonly "organization.creation_disabled": {
352
+ readonly status: 403;
353
+ readonly message: "Creating an organization is not allowed in this environment.";
354
+ };
355
+ readonly "organization.limit_reached": {
356
+ readonly status: 403;
357
+ readonly message: "You have reached the number of organizations you can create.";
358
+ };
359
+ readonly "organization.personal_account_disabled": {
360
+ readonly status: 409;
361
+ readonly message: "An organization must be active in this environment.";
362
+ };
363
+ readonly "organization.role_exists": {
364
+ readonly status: 409;
365
+ readonly message: "A role with that key already exists in this environment.";
366
+ };
367
+ readonly "organization.role_in_use": {
368
+ readonly status: 409;
369
+ readonly message: "Members still hold this role. Give them another role first.";
370
+ };
371
+ readonly "organization.role_built_in": {
372
+ readonly status: 409;
373
+ readonly message: "A built-in role cannot be changed or deleted.";
374
+ };
375
+ readonly "organization.role_limit": {
376
+ readonly status: 409;
377
+ readonly message: "This environment has the most custom roles it can have.";
378
+ };
379
+ readonly "organization.permission_required": {
380
+ readonly status: 403;
381
+ readonly message: "Your role does not allow that.";
382
+ };
383
+ readonly "organization.role_not_assignable": {
384
+ readonly status: 403;
385
+ readonly message: "You can only invite to a role no stronger than yours.";
386
+ };
387
+ readonly "organization.invitation_exists": {
388
+ readonly status: 409;
389
+ readonly message: "That address already has a pending invitation.";
390
+ };
391
+ readonly "organization.invitation_not_found": {
392
+ readonly status: 404;
393
+ readonly message: "This invitation does not exist.";
394
+ };
395
+ readonly "organization.invitation_expired": {
396
+ readonly status: 410;
397
+ readonly message: "This invitation has expired.";
398
+ };
399
+ readonly "organization.invitation_revoked": {
400
+ readonly status: 410;
401
+ readonly message: "This invitation was withdrawn.";
402
+ };
403
+ readonly "organization.invitation_used": {
404
+ readonly status: 410;
405
+ readonly message: "This invitation was already used.";
406
+ };
407
+ readonly "organization.invitation_wrong_account": {
408
+ readonly status: 403;
409
+ readonly message: "This invitation was sent to another email address.";
410
+ };
411
+ readonly "organization.invitation_email_unverified": {
412
+ readonly status: 403;
413
+ readonly message: "Verify your email address to accept this invitation.";
414
+ };
415
+ readonly "organization.invitation_role_gone": {
416
+ readonly status: 409;
417
+ readonly message: "The role this invitation offers no longer exists.";
418
+ };
419
+ readonly "organization.domain_public": {
420
+ readonly status: 422;
421
+ readonly message: "A public email domain cannot be claimed by an organization.";
422
+ };
423
+ readonly "organization.domain_taken": {
424
+ readonly status: 409;
425
+ readonly message: "That domain is verified for an organization already.";
426
+ };
427
+ readonly "organization.domain_address_mismatch": {
428
+ readonly status: 422;
429
+ readonly message: "That address is not on the domain.";
430
+ };
431
+ readonly "organization.domain_limit": {
432
+ readonly status: 409;
433
+ readonly message: "This organization has the most domains it can have.";
434
+ };
435
+ readonly "organization.suggestion_unavailable": {
436
+ readonly status: 403;
437
+ readonly message: "You cannot join that organization.";
438
+ };
439
+ readonly "sso.disabled": {
440
+ readonly status: 403;
441
+ readonly message: "Single sign-on is not enabled for this environment.";
442
+ };
443
+ readonly "sso.connection_not_found": {
444
+ readonly status: 404;
445
+ readonly message: "No such single sign-on connection.";
446
+ };
447
+ readonly "sso.name_taken": {
448
+ readonly status: 409;
449
+ readonly message: "The organization already has a connection with that name.";
450
+ };
451
+ readonly "sso.domain_taken": {
452
+ readonly status: 409;
453
+ readonly message: "Another active connection already serves one of those domains.";
454
+ };
455
+ readonly "sso.domain_not_verified": {
456
+ readonly status: 422;
457
+ readonly message: "Every domain must be one of the organization's verified domains.";
458
+ };
459
+ readonly "sso.issuer_not_allowed": {
460
+ readonly status: 422;
461
+ readonly message: "The issuer is not an address the server may call.";
462
+ };
463
+ readonly "sso.saml_invalid": {
464
+ readonly status: 422;
465
+ readonly message: "The SAML settings could not be read or are incomplete.";
466
+ };
467
+ readonly "sso.connection_in_use": {
468
+ readonly status: 409;
469
+ readonly message: "The connection is active; disable it before deleting it.";
470
+ };
471
+ readonly "sso.invalid_transition": {
472
+ readonly status: 409;
473
+ readonly message: "A connection cannot move to that status from its current one.";
474
+ };
475
+ readonly "sso.url_not_https": {
476
+ readonly status: 422;
477
+ readonly message: "The identity provider’s sign-in address must start with https.";
478
+ };
479
+ readonly "sso.test_required": {
480
+ readonly status: 409;
481
+ readonly message: "Run a passing test sign-in of the connection’s current settings before activating it.";
482
+ };
483
+ readonly "sso.test_not_found": {
484
+ readonly status: 404;
485
+ readonly message: "No such test sign-in.";
486
+ };
487
+ readonly "sso.role_not_allowed": {
488
+ readonly status: 403;
489
+ readonly message: "A setup link cannot map a group to a role that holds system permissions.";
490
+ };
491
+ readonly "sso.unavailable": {
492
+ readonly status: 400;
493
+ readonly message: "Single sign-on is not available for that address.";
494
+ };
495
+ readonly "sso.provider_error": {
496
+ readonly status: 401;
497
+ readonly message: "The identity provider did not sign you in.";
498
+ };
499
+ readonly "sso.user_not_provisioned": {
500
+ readonly status: 403;
501
+ readonly message: "Your account has not been set up for this organization. Ask its administrator.";
502
+ };
503
+ readonly "sso.email_domain_mismatch": {
504
+ readonly status: 403;
505
+ readonly message: "Your email address is not on this connection's domains.";
506
+ };
303
507
  readonly rate_limited: {
304
508
  readonly status: 429;
305
509
  readonly message: "Too many requests. Try again shortly.";
@@ -9,7 +9,7 @@
9
9
  * {@link REDIRECT_SCHEME_FAMILIES_NEVER_CUSTOM}, are refused by this list alone, and a
10
10
  * scheme an operating system handles that nobody put here passes. What bounds that is not
11
11
  * the list: every entry of `urls.allowedRedirectUrls` is written by the operator by hand,
12
- * and a redirect carries only a ticket that is useless without the binding (ADR 0044).
12
+ * and a redirect carries only a ticket that is useless without the binding.
13
13
  *
14
14
  * @example
15
15
  * ```ts
@@ -134,7 +134,7 @@ declare function isRedirectUrl(value: string): boolean;
134
134
  */
135
135
  declare function isCustomSchemeRedirectUrl(value: string): boolean;
136
136
  /**
137
- * The providers whose authorization code Tula binds to the attempt with PKCE (ADR 0026): the
137
+ * The providers whose authorization code Tula binds to the attempt with PKCE: the
138
138
  * code is redeemable only with the verifier the attempt holds.
139
139
  *
140
140
  * @example
@@ -146,7 +146,7 @@ declare const OAUTH_PROVIDERS_WITH_PKCE: readonly ["google", "github", "microsof
146
146
  /**
147
147
  * The providers that do **not** bind their code with PKCE, as a fact about the provider and
148
148
  * not a setting: Apple and LinkedIn document none, and Facebook's has it only in a flow that
149
- * is not used (ADR 0026).
149
+ * is not used.
150
150
  *
151
151
  * A provider sign-in with one of them is never returned to a custom scheme
152
152
  * ({@link customSchemeRedirectRefusal}). A new provider is added to this list or to
@@ -10,7 +10,7 @@ import {
10
10
  bindsCodeWithPkce2,
11
11
  CUSTOM_SCHEME_REDIRECT_REFUSALS2,
12
12
  customSchemeRedirectRefusal2
13
- } from "./shared/chunk-r202nxfw.js";
13
+ } from "./shared/chunk-n1jdq72m.js";
14
14
  export {
15
15
  CUSTOM_SCHEME_REDIRECT_REFUSALS2 as CUSTOM_SCHEME_REDIRECT_REFUSALS,
16
16
  OAUTH_PROVIDERS_WITHOUT_PKCE2 as OAUTH_PROVIDERS_WITHOUT_PKCE,
@@ -12,8 +12,10 @@ var DASHBOARD_HEADER_VALUE2 = "1";
12
12
  var ENVIRONMENT_HEADER2 = "x-tula-environment";
13
13
  var DASHBOARD_SESSION_COOKIE2 = "tula_dashboard";
14
14
  var EMAIL_LINK_TOKEN_PARAM2 = "tula_link";
15
+ var ORGANIZATION_INVITATION_TOKEN_PARAM2 = "tula_invitation";
15
16
  var EMAIL_LINK_ATTEMPT_PARAM2 = "tula_attempt";
16
17
  var OAUTH_TICKET_PARAM2 = "tula_ticket";
17
18
  var OAUTH_ERROR_PARAM2 = "tula_error";
19
+ var SETUP_LINK_HEADER2 = "x-tula-setup-token";
18
20
 
19
- export { PUBLISHABLE_KEY_HEADER2, CLIENT_HEADER2, SESSION_PROFILE_HEADER2, FLOW_ATTEMPT_HEADER2, CAN_STILL_SIGN_IN_HEADER2, CONFIG_MANAGED_BY_HEADER2, CONFIG_HASH_HEADER2, CONFIG_UNMANAGED2, DASHBOARD_HEADER2, DASHBOARD_HEADER_VALUE2, ENVIRONMENT_HEADER2, DASHBOARD_SESSION_COOKIE2, EMAIL_LINK_TOKEN_PARAM2, EMAIL_LINK_ATTEMPT_PARAM2, OAUTH_TICKET_PARAM2, OAUTH_ERROR_PARAM2 };
21
+ export { PUBLISHABLE_KEY_HEADER2, CLIENT_HEADER2, SESSION_PROFILE_HEADER2, FLOW_ATTEMPT_HEADER2, CAN_STILL_SIGN_IN_HEADER2, CONFIG_MANAGED_BY_HEADER2, CONFIG_HASH_HEADER2, CONFIG_UNMANAGED2, DASHBOARD_HEADER2, DASHBOARD_HEADER_VALUE2, ENVIRONMENT_HEADER2, DASHBOARD_SESSION_COOKIE2, EMAIL_LINK_TOKEN_PARAM2, ORGANIZATION_INVITATION_TOKEN_PARAM2, EMAIL_LINK_ATTEMPT_PARAM2, OAUTH_TICKET_PARAM2, OAUTH_ERROR_PARAM2, SETUP_LINK_HEADER2 };