@aglyn/aglyn 1.0.0-beta.268 → 1.0.0-beta.270
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -11
- package/src/lib/app-utils/account-preferences.d.ts +248 -0
- package/src/lib/app-utils/account-preferences.js +434 -0
- package/src/lib/app-utils/account-preferences.js.map +1 -0
- package/src/lib/app-utils/country-options.d.ts +27 -0
- package/src/lib/app-utils/country-options.js +96 -0
- package/src/lib/app-utils/country-options.js.map +1 -0
- package/src/lib/app-utils/docs-help.generated.d.ts +6 -0
- package/src/lib/app-utils/docs-help.generated.js +13 -0
- package/src/lib/app-utils/docs-help.generated.js.map +1 -1
- package/src/lib/app-utils/docs-index.generated.js +17 -10
- package/src/lib/app-utils/docs-index.generated.js.map +1 -1
- package/src/lib/app-utils/element-motion.d.ts +14 -2
- package/src/lib/app-utils/element-motion.js +33 -13
- package/src/lib/app-utils/element-motion.js.map +1 -1
- package/src/lib/app-utils/mobile-push.d.ts +8 -0
- package/src/lib/app-utils/mobile-push.js +4 -1
- package/src/lib/app-utils/mobile-push.js.map +1 -1
- package/src/lib/app-utils/native-app-association.d.ts +3 -2
- package/src/lib/app-utils/native-app-association.js +4 -2
- package/src/lib/app-utils/native-app-association.js.map +1 -1
- package/src/lib/app-utils/native-nav.d.ts +265 -0
- package/src/lib/app-utils/native-nav.js +741 -0
- package/src/lib/app-utils/native-nav.js.map +1 -0
- package/src/lib/app-utils/native-themes.d.ts +249 -0
- package/src/lib/app-utils/native-themes.js +732 -0
- package/src/lib/app-utils/native-themes.js.map +1 -0
- package/src/lib/app-utils/notifications.d.ts +1 -1
- package/src/lib/app-utils/notifications.js +10 -0
- package/src/lib/app-utils/notifications.js.map +1 -1
- package/src/lib/app-utils/one-box-search.d.ts +108 -0
- package/src/lib/app-utils/one-box-search.js +167 -0
- package/src/lib/app-utils/one-box-search.js.map +1 -0
- package/src/lib/app-utils/org-permissions.js +10 -61
- package/src/lib/app-utils/org-permissions.js.map +1 -1
- package/src/lib/app-utils/org-role-grants.d.ts +95 -0
- package/src/lib/app-utils/org-role-grants.js +193 -0
- package/src/lib/app-utils/org-role-grants.js.map +1 -0
- package/src/lib/app-utils/plan-entitlements.d.ts +41 -1
- package/src/lib/app-utils/plan-entitlements.js +65 -3
- package/src/lib/app-utils/plan-entitlements.js.map +1 -1
- package/src/lib/app-utils/tenant-dns-targets.d.ts +62 -0
- package/src/lib/app-utils/tenant-dns-targets.js +80 -0
- package/src/lib/app-utils/tenant-dns-targets.js.map +1 -0
- package/src/lib/foundation/definitions/org-billing.types.d.ts +14 -0
- package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
- package/src/lib/foundation/definitions/platform.types.d.ts +9 -0
- package/src/lib/foundation/definitions/platform.types.js.map +1 -1
- package/src/lib/plugin-manager/feature-plugins.d.ts +38 -0
- package/src/lib/plugin-manager/feature-plugins.js +20 -0
- package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
- package/src/lib/plugin-manager/first-party-plugins.generated.js +22 -1
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
- package/src/lib/plugin-manager/operator-alerts.js +10 -1
- package/src/lib/plugin-manager/operator-alerts.js.map +1 -1
- package/src/lib/plugin-manager/plugin-config.js +10 -1
- package/src/lib/plugin-manager/plugin-config.js.map +1 -1
- package/src/lib/plugin-manager/plugin-consent-group-change.js +11 -2
- package/src/lib/plugin-manager/plugin-consent-group-change.js.map +1 -1
- package/src/lib/plugin-manager/plugin-console-crons.js +10 -1
- package/src/lib/plugin-manager/plugin-console-crons.js.map +1 -1
- package/src/lib/plugin-manager/plugin-domain-events.d.ts +4 -3
- package/src/lib/plugin-manager/plugin-domain-events.js.map +1 -1
- package/src/lib/plugin-manager/plugin-events.js +11 -2
- package/src/lib/plugin-manager/plugin-events.js.map +1 -1
- package/src/lib/plugin-manager/plugin-lead-conversion.js +10 -1
- package/src/lib/plugin-manager/plugin-lead-conversion.js.map +1 -1
- package/src/lib/plugin-manager/plugin-media-ingest.d.ts +25 -0
- package/src/lib/plugin-manager/plugin-media-ingest.js.map +1 -1
- package/src/lib/plugin-manager/plugin-membership-detach.js +10 -1
- package/src/lib/plugin-manager/plugin-membership-detach.js.map +1 -1
- package/src/lib/plugin-manager/plugin-person-matches.js +10 -1
- package/src/lib/plugin-manager/plugin-person-matches.js.map +1 -1
- package/src/lib/plugin-manager/plugin-search-sources.d.ts +85 -0
- package/src/lib/plugin-manager/plugin-search-sources.js +91 -0
- package/src/lib/plugin-manager/plugin-search-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-services.js +6 -0
- package/src/lib/plugin-manager/plugin-services.js.map +1 -1
- package/src/lib/plugin-manager/plugin-usage-meters.js +10 -1
- package/src/lib/plugin-manager/plugin-usage-meters.js.map +1 -1
- package/src/lib/plugin-manager/usage-alert-contributors.js +10 -1
- package/src/lib/plugin-manager/usage-alert-contributors.js.map +1 -1
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* WHAT EACH ORG ROLE MAY DO, AS DATA (AGL-243, AGL-3950).
|
|
18
|
+
*
|
|
19
|
+
* The core permission catalog and the core keys each org role holds when
|
|
20
|
+
* nothing refines it. `org-permissions.ts` builds the console's live
|
|
21
|
+
* catalog from these (adding the keys plugins declare, with their own role
|
|
22
|
+
* defaults), and the native apps read the same grants through the generated
|
|
23
|
+
* contracts, so a native gate (`hosts.create`, `data.manage`) answers as the
|
|
24
|
+
* console does for a member row that carries no `resolvedPermissions` stamp.
|
|
25
|
+
*
|
|
26
|
+
* `ORG_ROLE_GRANTS` in the contracts is this table with every plugin's
|
|
27
|
+
* declared catalog keys added (`assembleOrgRoleGrants`, run by
|
|
28
|
+
* `generate:native-contracts` over each plugin's declarations), which is
|
|
29
|
+
* exactly the set the console's `DEFAULT_ROLE_PERMISSIONS` holds once the
|
|
30
|
+
* plugins have registered.
|
|
31
|
+
*
|
|
32
|
+
* NO IMPORTS, on purpose: the native apps read it through the generated
|
|
33
|
+
* contracts.
|
|
34
|
+
*/ /** The four org roles. */ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
35
|
+
export const ORG_ROLE_NAMES = [
|
|
36
|
+
'owner',
|
|
37
|
+
'admin',
|
|
38
|
+
'editor',
|
|
39
|
+
'viewer'
|
|
40
|
+
];
|
|
41
|
+
/**
|
|
42
|
+
* The core keys, in display order for role editors. Every key here is
|
|
43
|
+
* enforced server-side (`apps/console/specs/org-permissions-are-enforced.spec.ts`).
|
|
44
|
+
*/ export const CORE_ORG_PERMISSION_ENTRIES = [
|
|
45
|
+
{
|
|
46
|
+
key: 'org.settings',
|
|
47
|
+
label: 'Organization settings',
|
|
48
|
+
description: 'Rename the organization, change its slug, transfer it.'
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
key: 'org.auditLog',
|
|
52
|
+
label: 'Activity & audit log',
|
|
53
|
+
description: 'See the organization activity feed.'
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
key: 'billing.view',
|
|
57
|
+
label: 'View billing',
|
|
58
|
+
description: 'See the plan, usage meters, and invoices.'
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
key: 'billing.manage',
|
|
62
|
+
label: 'Manage billing',
|
|
63
|
+
description: 'Change plans, buy add-ons, update payment details.'
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
key: 'members.manage',
|
|
67
|
+
label: 'Manage members',
|
|
68
|
+
description: 'Invite, remove, and re-role organization members.'
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
key: 'hosts.create',
|
|
72
|
+
label: 'Create sites',
|
|
73
|
+
description: 'Create new sites in the organization.'
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
key: 'hosts.delete',
|
|
77
|
+
label: 'Delete sites',
|
|
78
|
+
description: 'Delete sites the member can access.'
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
key: 'data.manage',
|
|
82
|
+
label: 'Manage data',
|
|
83
|
+
description: 'Create, edit, and delete organization datasets.'
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
key: 'marketplace.publish',
|
|
87
|
+
label: 'Publish to marketplace',
|
|
88
|
+
description: 'Publish listings under the organization profile.'
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
key: 'plugins.install',
|
|
92
|
+
label: 'Install plugins',
|
|
93
|
+
description: 'Install or remove marketplace plugins.'
|
|
94
|
+
}
|
|
95
|
+
];
|
|
96
|
+
const CORE_KEYS = CORE_ORG_PERMISSION_ENTRIES.map((entry)=>entry.key);
|
|
97
|
+
/**
|
|
98
|
+
* The core keys each org role holds when nothing refines it: owners and
|
|
99
|
+
* admins hold every core key (owner-only acts like deleting the
|
|
100
|
+
* organization stay role-checked, not permission-checked); editors work on
|
|
101
|
+
* content and see no money or roster controls; viewers read only.
|
|
102
|
+
*/ export const CORE_ORG_ROLE_GRANTS = {
|
|
103
|
+
owner: CORE_KEYS,
|
|
104
|
+
admin: CORE_KEYS,
|
|
105
|
+
editor: [
|
|
106
|
+
'data.manage',
|
|
107
|
+
'marketplace.publish',
|
|
108
|
+
'plugins.install'
|
|
109
|
+
],
|
|
110
|
+
viewer: []
|
|
111
|
+
};
|
|
112
|
+
/** The core's catalog and grants; the contracts' value adds the plugins' keys. */ export const ORG_ROLE_GRANTS = {
|
|
113
|
+
permissions: CORE_ORG_PERMISSION_ENTRIES.map((entry)=>_extends({}, entry)),
|
|
114
|
+
grants: {
|
|
115
|
+
owner: [
|
|
116
|
+
...CORE_ORG_ROLE_GRANTS.owner
|
|
117
|
+
],
|
|
118
|
+
admin: [
|
|
119
|
+
...CORE_ORG_ROLE_GRANTS.admin
|
|
120
|
+
],
|
|
121
|
+
editor: [
|
|
122
|
+
...CORE_ORG_ROLE_GRANTS.editor
|
|
123
|
+
],
|
|
124
|
+
viewer: [
|
|
125
|
+
...CORE_ORG_ROLE_GRANTS.viewer
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* The catalog with plugins' declared keys after the core ones, each role
|
|
131
|
+
* holding a declared key when its declaration's `roleDefaults` says so. A
|
|
132
|
+
* declaration naming a core key is refused, as the console's catalog refuses
|
|
133
|
+
* it: the core key keeps its meaning and defaults.
|
|
134
|
+
*/ export function assembleOrgRoleGrants(core, declarations) {
|
|
135
|
+
const permissions = [
|
|
136
|
+
...core.permissions
|
|
137
|
+
];
|
|
138
|
+
const grants = Object.fromEntries(ORG_ROLE_NAMES.map((role)=>[
|
|
139
|
+
role,
|
|
140
|
+
[
|
|
141
|
+
...core.grants[role]
|
|
142
|
+
]
|
|
143
|
+
]));
|
|
144
|
+
const taken = new Set(permissions.map((entry)=>entry.key));
|
|
145
|
+
for (const declaration of declarations){
|
|
146
|
+
if (!(declaration == null ? void 0 : declaration.key) || taken.has(declaration.key)) continue;
|
|
147
|
+
taken.add(declaration.key);
|
|
148
|
+
permissions.push(_extends({
|
|
149
|
+
key: declaration.key,
|
|
150
|
+
label: declaration.label,
|
|
151
|
+
description: declaration.description
|
|
152
|
+
}, declaration.pluginId ? {
|
|
153
|
+
pluginId: declaration.pluginId
|
|
154
|
+
} : {}));
|
|
155
|
+
for (const role of ORG_ROLE_NAMES){
|
|
156
|
+
var _declaration_roleDefaults;
|
|
157
|
+
if (((_declaration_roleDefaults = declaration.roleDefaults) == null ? void 0 : _declaration_roleDefaults[role]) === true) grants[role].push(declaration.key);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
permissions,
|
|
162
|
+
grants
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* A member's effective permissions, as the console's `resolveOrgPermissions`
|
|
167
|
+
* answers them: the role's defaults, then the custom role's explicit
|
|
168
|
+
* verdicts (when the member has one), then the member's own overrides,
|
|
169
|
+
* later layers winning key by key, over the catalog's keys only. A missing
|
|
170
|
+
* role reads as viewer; a role the catalog does not know holds nothing.
|
|
171
|
+
*/ export function rolePermissions(catalog, role, customRole, overrides) {
|
|
172
|
+
var _catalog_grants_name;
|
|
173
|
+
const keys = catalog.permissions.map((entry)=>entry.key);
|
|
174
|
+
const name = role != null ? role : 'viewer';
|
|
175
|
+
const held = new Set((_catalog_grants_name = catalog.grants[name]) != null ? _catalog_grants_name : []);
|
|
176
|
+
const out = Object.fromEntries(keys.map((key)=>[
|
|
177
|
+
key,
|
|
178
|
+
held.has(key)
|
|
179
|
+
]));
|
|
180
|
+
for (const layer of [
|
|
181
|
+
customRole,
|
|
182
|
+
overrides
|
|
183
|
+
]){
|
|
184
|
+
const values = layer == null ? void 0 : layer.permissions;
|
|
185
|
+
if (!values) continue;
|
|
186
|
+
for (const key of keys){
|
|
187
|
+
if (typeof values[key] === 'boolean') out[key] = values[key];
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
//# sourceMappingURL=org-role-grants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/org-role-grants.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WHAT EACH ORG ROLE MAY DO, AS DATA (AGL-243, AGL-3950).\n *\n * The core permission catalog and the core keys each org role holds when\n * nothing refines it. `org-permissions.ts` builds the console's live\n * catalog from these (adding the keys plugins declare, with their own role\n * defaults), and the native apps read the same grants through the generated\n * contracts, so a native gate (`hosts.create`, `data.manage`) answers as the\n * console does for a member row that carries no `resolvedPermissions` stamp.\n *\n * `ORG_ROLE_GRANTS` in the contracts is this table with every plugin's\n * declared catalog keys added (`assembleOrgRoleGrants`, run by\n * `generate:native-contracts` over each plugin's declarations), which is\n * exactly the set the console's `DEFAULT_ROLE_PERMISSIONS` holds once the\n * plugins have registered.\n *\n * NO IMPORTS, on purpose: the native apps read it through the generated\n * contracts.\n */\n\n/** The four org roles. */\nexport type OrgRoleName = 'owner' | 'admin' | 'editor' | 'viewer'\n\n/** One key of the org permission catalog. */\nexport interface OrgPermissionEntry {\n key: string\n label: string\n description: string\n /** The plugin that declared it; absent for a core key. */\n pluginId?: string\n}\n\n/** The catalog and each role's default grants. */\nexport interface OrgRoleGrants {\n /** Every key, in the order the role editor lists them. */\n permissions: OrgPermissionEntry[]\n /** The keys each role holds when no custom role or per-member override sets them. */\n grants: Record<OrgRoleName, string[]>\n}\n\n/** A key a plugin declares into the catalog, as `PluginOrgPermissionDeclaration` carries it. */\nexport interface OrgPermissionDeclaration {\n key: string\n label: string\n description: string\n roleDefaults: Record<OrgRoleName, boolean>\n}\n\n/** A custom role (`orgs/{orgId}/roles/{roleId}`) or a member's overrides: explicit verdicts per key. */\nexport interface OrgPermissionLayer {\n permissions?: Record<string, boolean>\n}\n\nexport const ORG_ROLE_NAMES: readonly OrgRoleName[] = ['owner', 'admin', 'editor', 'viewer']\n\n/**\n * The core keys, in display order for role editors. Every key here is\n * enforced server-side (`apps/console/specs/org-permissions-are-enforced.spec.ts`).\n */\nexport const CORE_ORG_PERMISSION_ENTRIES: readonly OrgPermissionEntry[] = [\n {\n key: 'org.settings',\n label: 'Organization settings',\n description: 'Rename the organization, change its slug, transfer it.',\n },\n {\n key: 'org.auditLog',\n label: 'Activity & audit log',\n description: 'See the organization activity feed.',\n },\n {\n key: 'billing.view',\n label: 'View billing',\n description: 'See the plan, usage meters, and invoices.',\n },\n {\n key: 'billing.manage',\n label: 'Manage billing',\n description: 'Change plans, buy add-ons, update payment details.',\n },\n {\n key: 'members.manage',\n label: 'Manage members',\n description: 'Invite, remove, and re-role organization members.',\n },\n {\n key: 'hosts.create',\n label: 'Create sites',\n description: 'Create new sites in the organization.',\n },\n {\n key: 'hosts.delete',\n label: 'Delete sites',\n description: 'Delete sites the member can access.',\n },\n {\n key: 'data.manage',\n label: 'Manage data',\n description: 'Create, edit, and delete organization datasets.',\n },\n {\n key: 'marketplace.publish',\n label: 'Publish to marketplace',\n description: 'Publish listings under the organization profile.',\n },\n {\n key: 'plugins.install',\n label: 'Install plugins',\n description: 'Install or remove marketplace plugins.',\n },\n]\n\nconst CORE_KEYS = CORE_ORG_PERMISSION_ENTRIES.map((entry) => entry.key)\n\n/**\n * The core keys each org role holds when nothing refines it: owners and\n * admins hold every core key (owner-only acts like deleting the\n * organization stay role-checked, not permission-checked); editors work on\n * content and see no money or roster controls; viewers read only.\n */\nexport const CORE_ORG_ROLE_GRANTS: Readonly<Record<OrgRoleName, readonly string[]>> = {\n owner: CORE_KEYS,\n admin: CORE_KEYS,\n editor: ['data.manage', 'marketplace.publish', 'plugins.install'],\n viewer: [],\n}\n\n/** The core's catalog and grants; the contracts' value adds the plugins' keys. */\nexport const ORG_ROLE_GRANTS: OrgRoleGrants = {\n permissions: CORE_ORG_PERMISSION_ENTRIES.map((entry) => ({ ...entry })),\n grants: {\n owner: [...CORE_ORG_ROLE_GRANTS.owner],\n admin: [...CORE_ORG_ROLE_GRANTS.admin],\n editor: [...CORE_ORG_ROLE_GRANTS.editor],\n viewer: [...CORE_ORG_ROLE_GRANTS.viewer],\n },\n}\n\n/**\n * The catalog with plugins' declared keys after the core ones, each role\n * holding a declared key when its declaration's `roleDefaults` says so. A\n * declaration naming a core key is refused, as the console's catalog refuses\n * it: the core key keeps its meaning and defaults.\n */\nexport function assembleOrgRoleGrants(\n core: OrgRoleGrants,\n declarations: readonly (OrgPermissionDeclaration & { pluginId?: string })[],\n): OrgRoleGrants {\n const permissions = [...core.permissions]\n const grants = Object.fromEntries(ORG_ROLE_NAMES.map((role) => [role, [...core.grants[role]]])) as Record<\n OrgRoleName,\n string[]\n >\n const taken = new Set(permissions.map((entry) => entry.key))\n for (const declaration of declarations) {\n if (!declaration?.key || taken.has(declaration.key)) continue\n taken.add(declaration.key)\n permissions.push({\n key: declaration.key,\n label: declaration.label,\n description: declaration.description,\n ...(declaration.pluginId ? { pluginId: declaration.pluginId } : {}),\n })\n for (const role of ORG_ROLE_NAMES) {\n if (declaration.roleDefaults?.[role] === true) grants[role].push(declaration.key)\n }\n }\n return { permissions, grants }\n}\n\n/**\n * A member's effective permissions, as the console's `resolveOrgPermissions`\n * answers them: the role's defaults, then the custom role's explicit\n * verdicts (when the member has one), then the member's own overrides,\n * later layers winning key by key, over the catalog's keys only. A missing\n * role reads as viewer; a role the catalog does not know holds nothing.\n */\nexport function rolePermissions(\n catalog: OrgRoleGrants,\n role: string | null | undefined,\n customRole?: OrgPermissionLayer | null,\n overrides?: OrgPermissionLayer | null,\n): Record<string, boolean> {\n const keys = catalog.permissions.map((entry) => entry.key)\n const name = role ?? 'viewer'\n const held = new Set((catalog.grants as Record<string, string[] | undefined>)[name] ?? [])\n const out: Record<string, boolean> = Object.fromEntries(keys.map((key) => [key, held.has(key)]))\n for (const layer of [customRole, overrides]) {\n const values = layer?.permissions\n if (!values) continue\n for (const key of keys) {\n if (typeof values[key] === 'boolean') out[key] = values[key]\n }\n }\n return out\n}\n"],"names":["ORG_ROLE_NAMES","CORE_ORG_PERMISSION_ENTRIES","key","label","description","CORE_KEYS","map","entry","CORE_ORG_ROLE_GRANTS","owner","admin","editor","viewer","ORG_ROLE_GRANTS","permissions","grants","assembleOrgRoleGrants","core","declarations","Object","fromEntries","role","taken","Set","declaration","has","add","push","pluginId","roleDefaults","rolePermissions","catalog","customRole","overrides","keys","name","held","out","layer","values"],"mappings":"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"}
|
|
@@ -220,6 +220,14 @@ export declare const SELF_SERVE_PLANS: OrgPlan[];
|
|
|
220
220
|
* "free". Revenue for such an org comes from `subscription.customMonthlyUsd`.
|
|
221
221
|
*/
|
|
222
222
|
export declare function isCustomPricedPlan(plan: OrgPlan | undefined | null): boolean;
|
|
223
|
+
/**
|
|
224
|
+
* Whether a plan sells the Site Care add-on (AGL-3954): every paid self-serve
|
|
225
|
+
* plan, never `free` (no subscription to bill it on) and never a
|
|
226
|
+
* custom-priced plan (Enterprise names it in the agreement instead). An
|
|
227
|
+
* unknown plan string sells nothing. The ONE reading of that rule — the
|
|
228
|
+
* add-on ceiling, the checkout refusal and the Billing card all ask it.
|
|
229
|
+
*/
|
|
230
|
+
export declare function planSellsSiteCare(plan: OrgPlan | string | undefined | null): boolean;
|
|
223
231
|
/** Human plan names — the ONE source every plan badge/label reads. */
|
|
224
232
|
export declare const PLAN_LABELS: Record<OrgPlan, string>;
|
|
225
233
|
/**
|
|
@@ -235,6 +243,24 @@ export declare const PLAN_LABELS: Record<OrgPlan, string>;
|
|
|
235
243
|
* The marketing copy on /pricing is written against that behaviour.
|
|
236
244
|
*/
|
|
237
245
|
export declare const EVENT_CALENDAR_ADDON_MONTHLY_USD = 9;
|
|
246
|
+
/**
|
|
247
|
+
* Site Care add-on (AGL-3954): $49/mo per organization, the managed-website
|
|
248
|
+
* service. It buys staff time, not capacity: small changes to the owner's
|
|
249
|
+
* existing site (hours, prices, photos, a staff member, a seasonal banner, a
|
|
250
|
+
* section on an existing page), up to about one hour of work a month, done
|
|
251
|
+
* within two business days, minutes logged and no rollover. New pages, new
|
|
252
|
+
* forms, redesigns, brand work, photography, whole-site copy and ads are
|
|
253
|
+
* quoted separately, and it never raises a plan limit — a 26th page or a
|
|
254
|
+
* second site is still an upgrade.
|
|
255
|
+
*
|
|
256
|
+
* Flat across plans, like the Event Calendar, because the work it pays for
|
|
257
|
+
* is the same hour whichever tier the site is on; the yearly price is ×12
|
|
258
|
+
* with no discount, as every add-on's is. Sold on every paid self-serve plan
|
|
259
|
+
* and never on Free (no subscription to carry it) or Enterprise (quoted per
|
|
260
|
+
* deal) — `planSellsSiteCare` is that rule. `resolveOrgEntitlements` flips
|
|
261
|
+
* the org-wide `features.siteCare` from any purchased quantity >= 1.
|
|
262
|
+
*/
|
|
263
|
+
export declare const SITE_CARE_ADDON_MONTHLY_USD = 49;
|
|
238
264
|
/**
|
|
239
265
|
* POS Pro register add-on (AGL-329): $89/mo per extra register/location
|
|
240
266
|
* (Shopify POS Pro parity). Purchased add-ons land as a per-org
|
|
@@ -762,6 +788,12 @@ export declare function orgListPriceMonthlyUsd(org: Partial<AglynOrgBilling> | n
|
|
|
762
788
|
* `NaN` or a negative is none.
|
|
763
789
|
*/
|
|
764
790
|
export declare function aiAddonUnits(addons: OrgSeatAddons | null | undefined): 0 | 1;
|
|
791
|
+
/**
|
|
792
|
+
* How many Site Care add-ons a purchase map counts as: 0 or 1 (AGL-3954).
|
|
793
|
+
* Org-wide like the Aglyn AI add-on, so a quantity above one is one
|
|
794
|
+
* purchase, and a non-number, `NaN` or a negative is none.
|
|
795
|
+
*/
|
|
796
|
+
export declare function siteCareUnits(addons: OrgSeatAddons | null | undefined): 0 | 1;
|
|
765
797
|
/**
|
|
766
798
|
* A list price net of a discount (AGL-1105). Percentage discounts scale the
|
|
767
799
|
* whole bill; fixed discounts subtract a flat USD amount. Never below 0, and
|
|
@@ -1458,6 +1490,14 @@ export declare function resolveEffectivePlan(org: Partial<AglynOrgBilling> | nul
|
|
|
1458
1490
|
* together rather than leaving a rate on a band that has gone.
|
|
1459
1491
|
*/
|
|
1460
1492
|
export declare function hasAiAddon(org: Partial<AglynOrgBilling> | null | undefined): boolean;
|
|
1493
|
+
/**
|
|
1494
|
+
* Whether the org's Site Care add-on currently applies (AGL-3954): bought,
|
|
1495
|
+
* and on a subscription that is still paying for it, so a dead subscription
|
|
1496
|
+
* reads false here exactly as it drops `features.siteCare`. The reader for
|
|
1497
|
+
* surfaces that ask about the purchase rather than the resolved feature —
|
|
1498
|
+
* the staff org page's chip, the request intake.
|
|
1499
|
+
*/
|
|
1500
|
+
export declare function hasSiteCare(org: Partial<AglynOrgBilling> | null | undefined): boolean;
|
|
1461
1501
|
/**
|
|
1462
1502
|
* Numeric entitlement keys that were REMOVED from `PLAN_ENTITLEMENTS` and
|
|
1463
1503
|
* must never be resolved again from a stored override (AGL-2133).
|
|
@@ -1504,7 +1544,7 @@ export declare const PRICE_ENTITLEMENT_KEYS: ReadonlySet<string>;
|
|
|
1504
1544
|
* per-key overrides applied (features merge key-by-key too), then
|
|
1505
1545
|
* purchased add-ons stacked on top (AGL-524): `seatAddons.hosts` raises
|
|
1506
1546
|
* `hostLimit`, `seatAddons.eventCalendar` switches the `eventCalendar`
|
|
1507
|
-
* feature on, and every seat add-on a plugin declared through
|
|
1547
|
+
* feature on, `seatAddons.siteCare` switches `siteCare` on, and every seat add-on a plugin declared through
|
|
1508
1548
|
* `registerPluginEntitlements` (AGL-2940) widens the quota it names by its
|
|
1509
1549
|
* per-plan figure per unit and switches its features on — the Aglyn AI
|
|
1510
1550
|
* add-on (AGL-2896) is the first such declaration. (Seat/dataset add-ons
|
|
@@ -259,6 +259,10 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
259
259
|
siteExport: false,
|
|
260
260
|
multilingual: false,
|
|
261
261
|
eventCalendar: false,
|
|
262
|
+
// Site Care (AGL-3954) is never granted by a tier, on this plan or any
|
|
263
|
+
// other: it is the managed-website add-on, switched on only by a live
|
|
264
|
+
// `seatAddons.siteCare` purchase (or a staff override), never by a row.
|
|
265
|
+
siteCare: false,
|
|
262
266
|
redirects: false,
|
|
263
267
|
screenAnalytics: false,
|
|
264
268
|
/**
|
|
@@ -377,6 +381,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
377
381
|
siteExport: false,
|
|
378
382
|
multilingual: false,
|
|
379
383
|
eventCalendar: false,
|
|
384
|
+
siteCare: false,
|
|
380
385
|
redirects: true,
|
|
381
386
|
screenAnalytics: false,
|
|
382
387
|
mediaCdn: true,
|
|
@@ -490,6 +495,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
490
495
|
siteExport: true,
|
|
491
496
|
multilingual: false,
|
|
492
497
|
eventCalendar: false,
|
|
498
|
+
siteCare: false,
|
|
493
499
|
redirects: true,
|
|
494
500
|
screenAnalytics: true,
|
|
495
501
|
mediaCdn: true,
|
|
@@ -560,6 +566,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
560
566
|
siteExport: true,
|
|
561
567
|
multilingual: true,
|
|
562
568
|
eventCalendar: false,
|
|
569
|
+
siteCare: false,
|
|
563
570
|
redirects: true,
|
|
564
571
|
screenAnalytics: true,
|
|
565
572
|
mediaCdn: true,
|
|
@@ -633,6 +640,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
633
640
|
siteExport: true,
|
|
634
641
|
multilingual: true,
|
|
635
642
|
eventCalendar: false,
|
|
643
|
+
siteCare: false,
|
|
636
644
|
redirects: true,
|
|
637
645
|
screenAnalytics: true,
|
|
638
646
|
mediaCdn: true,
|
|
@@ -703,6 +711,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
703
711
|
siteExport: true,
|
|
704
712
|
multilingual: true,
|
|
705
713
|
eventCalendar: false,
|
|
714
|
+
siteCare: false,
|
|
706
715
|
redirects: true,
|
|
707
716
|
screenAnalytics: true,
|
|
708
717
|
mediaCdn: true,
|
|
@@ -777,6 +786,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
777
786
|
siteExport: true,
|
|
778
787
|
multilingual: true,
|
|
779
788
|
eventCalendar: false,
|
|
789
|
+
siteCare: false,
|
|
780
790
|
redirects: true,
|
|
781
791
|
screenAnalytics: true,
|
|
782
792
|
mediaCdn: true,
|
|
@@ -888,6 +898,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
888
898
|
multilingual: true,
|
|
889
899
|
// Event Calendar stays an add-on purchase, as on every other tier.
|
|
890
900
|
eventCalendar: false,
|
|
901
|
+
siteCare: false,
|
|
891
902
|
redirects: true,
|
|
892
903
|
screenAnalytics: true,
|
|
893
904
|
mediaCdn: true,
|
|
@@ -955,6 +966,17 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
955
966
|
*/ export function isCustomPricedPlan(plan) {
|
|
956
967
|
return plan === 'enterprise';
|
|
957
968
|
}
|
|
969
|
+
/**
|
|
970
|
+
* Whether a plan sells the Site Care add-on (AGL-3954): every paid self-serve
|
|
971
|
+
* plan, never `free` (no subscription to bill it on) and never a
|
|
972
|
+
* custom-priced plan (Enterprise names it in the agreement instead). An
|
|
973
|
+
* unknown plan string sells nothing. The ONE reading of that rule — the
|
|
974
|
+
* add-on ceiling, the checkout refusal and the Billing card all ask it.
|
|
975
|
+
*/ export function planSellsSiteCare(plan) {
|
|
976
|
+
if (!plan || plan === 'free') return false;
|
|
977
|
+
if (isCustomPricedPlan(plan)) return false;
|
|
978
|
+
return SELF_SERVE_PLANS.includes(plan);
|
|
979
|
+
}
|
|
958
980
|
/** Human plan names — the ONE source every plan badge/label reads. */ export const PLAN_LABELS = {
|
|
959
981
|
free: 'Free',
|
|
960
982
|
starter: 'Starter',
|
|
@@ -977,6 +999,23 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
977
999
|
* boolean from any quantity >= 1. One purchase covers every host in the org.
|
|
978
1000
|
* The marketing copy on /pricing is written against that behaviour.
|
|
979
1001
|
*/ export const EVENT_CALENDAR_ADDON_MONTHLY_USD = 9;
|
|
1002
|
+
/**
|
|
1003
|
+
* Site Care add-on (AGL-3954): $49/mo per organization, the managed-website
|
|
1004
|
+
* service. It buys staff time, not capacity: small changes to the owner's
|
|
1005
|
+
* existing site (hours, prices, photos, a staff member, a seasonal banner, a
|
|
1006
|
+
* section on an existing page), up to about one hour of work a month, done
|
|
1007
|
+
* within two business days, minutes logged and no rollover. New pages, new
|
|
1008
|
+
* forms, redesigns, brand work, photography, whole-site copy and ads are
|
|
1009
|
+
* quoted separately, and it never raises a plan limit — a 26th page or a
|
|
1010
|
+
* second site is still an upgrade.
|
|
1011
|
+
*
|
|
1012
|
+
* Flat across plans, like the Event Calendar, because the work it pays for
|
|
1013
|
+
* is the same hour whichever tier the site is on; the yearly price is ×12
|
|
1014
|
+
* with no discount, as every add-on's is. Sold on every paid self-serve plan
|
|
1015
|
+
* and never on Free (no subscription to carry it) or Enterprise (quoted per
|
|
1016
|
+
* deal) — `planSellsSiteCare` is that rule. `resolveOrgEntitlements` flips
|
|
1017
|
+
* the org-wide `features.siteCare` from any purchased quantity >= 1.
|
|
1018
|
+
*/ export const SITE_CARE_ADDON_MONTHLY_USD = 49;
|
|
980
1019
|
/**
|
|
981
1020
|
* POS Pro register add-on (AGL-329): $89/mo per extra register/location
|
|
982
1021
|
* (Shopify POS Pro parity). Purchased add-ons land as a per-org
|
|
@@ -1582,7 +1621,7 @@ function trimmedOrNull(value) {
|
|
|
1582
1621
|
const annual = (org == null ? void 0 : (_org_subscription1 = org.subscription) == null ? void 0 : _org_subscription1.interval) === 'year';
|
|
1583
1622
|
const addons = (_ref = org == null ? void 0 : org.seatAddons) != null ? _ref : {};
|
|
1584
1623
|
const seats = (quantity, price)=>Math.max(0, quantity != null ? quantity : 0) * (price != null ? price : 0);
|
|
1585
|
-
return (annual ? pricing.basePriceAnnualMonthlyUsd : pricing.basePriceMonthlyUsd) + seats(addons.managers, pricing.extraSeatMonthlyUsd) + seats(addons.members, pricing.extraCollaboratorMonthlyUsd) + seats(addons.datasets, pricing.extraDatasetMonthlyUsd) + seats(addons.hosts, pricing.extraHostMonthlyUsd) + seats(addons.posRegisters, POS_REGISTER_ADDON_MONTHLY_USD) + seats(addons.eventCalendar, EVENT_CALENDAR_ADDON_MONTHLY_USD) + // A toggle, not a quantity: one purchase covers the org, so a stored
|
|
1624
|
+
return (annual ? pricing.basePriceAnnualMonthlyUsd : pricing.basePriceMonthlyUsd) + seats(addons.managers, pricing.extraSeatMonthlyUsd) + seats(addons.members, pricing.extraCollaboratorMonthlyUsd) + seats(addons.datasets, pricing.extraDatasetMonthlyUsd) + seats(addons.hosts, pricing.extraHostMonthlyUsd) + seats(addons.posRegisters, POS_REGISTER_ADDON_MONTHLY_USD) + seats(addons.eventCalendar, EVENT_CALENDAR_ADDON_MONTHLY_USD) + seats(siteCareUnits(addons), SITE_CARE_ADDON_MONTHLY_USD) + // A toggle, not a quantity: one purchase covers the org, so a stored
|
|
1586
1625
|
// quantity above one bills once.
|
|
1587
1626
|
seats(aiAddonUnits(addons), pricing.aiAddonMonthlyUsd);
|
|
1588
1627
|
}
|
|
@@ -1596,6 +1635,15 @@ function trimmedOrNull(value) {
|
|
|
1596
1635
|
const quantity = Number((_ref = addons == null ? void 0 : addons.aiAddon) != null ? _ref : 0);
|
|
1597
1636
|
return Number.isFinite(quantity) && quantity >= 1 ? 1 : 0;
|
|
1598
1637
|
}
|
|
1638
|
+
/**
|
|
1639
|
+
* How many Site Care add-ons a purchase map counts as: 0 or 1 (AGL-3954).
|
|
1640
|
+
* Org-wide like the Aglyn AI add-on, so a quantity above one is one
|
|
1641
|
+
* purchase, and a non-number, `NaN` or a negative is none.
|
|
1642
|
+
*/ export function siteCareUnits(addons) {
|
|
1643
|
+
var _ref;
|
|
1644
|
+
const quantity = Number((_ref = addons == null ? void 0 : addons.siteCare) != null ? _ref : 0);
|
|
1645
|
+
return Number.isFinite(quantity) && quantity >= 1 ? 1 : 0;
|
|
1646
|
+
}
|
|
1599
1647
|
/**
|
|
1600
1648
|
* A list price net of a discount (AGL-1105). Percentage discounts scale the
|
|
1601
1649
|
* whole bill; fixed discounts subtract a flat USD amount. Never below 0, and
|
|
@@ -2401,6 +2449,15 @@ function resolvePlan(org) {
|
|
|
2401
2449
|
*/ export function hasAiAddon(org) {
|
|
2402
2450
|
return aiAddonUnits(resolvePurchasedAddons(org)) === 1;
|
|
2403
2451
|
}
|
|
2452
|
+
/**
|
|
2453
|
+
* Whether the org's Site Care add-on currently applies (AGL-3954): bought,
|
|
2454
|
+
* and on a subscription that is still paying for it, so a dead subscription
|
|
2455
|
+
* reads false here exactly as it drops `features.siteCare`. The reader for
|
|
2456
|
+
* surfaces that ask about the purchase rather than the resolved feature —
|
|
2457
|
+
* the staff org page's chip, the request intake.
|
|
2458
|
+
*/ export function hasSiteCare(org) {
|
|
2459
|
+
return siteCareUnits(resolvePurchasedAddons(org)) === 1;
|
|
2460
|
+
}
|
|
2404
2461
|
/**
|
|
2405
2462
|
* Numeric entitlement keys that were REMOVED from `PLAN_ENTITLEMENTS` and
|
|
2406
2463
|
* must never be resolved again from a stored override (AGL-2133).
|
|
@@ -2484,7 +2541,7 @@ function resolvePlan(org) {
|
|
|
2484
2541
|
* per-key overrides applied (features merge key-by-key too), then
|
|
2485
2542
|
* purchased add-ons stacked on top (AGL-524): `seatAddons.hosts` raises
|
|
2486
2543
|
* `hostLimit`, `seatAddons.eventCalendar` switches the `eventCalendar`
|
|
2487
|
-
* feature on, and every seat add-on a plugin declared through
|
|
2544
|
+
* feature on, `seatAddons.siteCare` switches `siteCare` on, and every seat add-on a plugin declared through
|
|
2488
2545
|
* `registerPluginEntitlements` (AGL-2940) widens the quota it names by its
|
|
2489
2546
|
* per-plan figure per unit and switches its features on — the Aglyn AI
|
|
2490
2547
|
* add-on (AGL-2896) is the first such declaration. (Seat/dataset add-ons
|
|
@@ -2589,17 +2646,22 @@ function resolvePlan(org) {
|
|
|
2589
2646
|
const purchased = resolvePurchasedAddons(org);
|
|
2590
2647
|
const extraHosts = Math.max(0, (_purchased_hosts = purchased.hosts) != null ? _purchased_hosts : 0);
|
|
2591
2648
|
const eventCalendar = ((_purchased_eventCalendar = purchased.eventCalendar) != null ? _purchased_eventCalendar : 0) >= 1;
|
|
2649
|
+
const siteCare = siteCareUnits(purchased) === 1;
|
|
2592
2650
|
// A declared add-on's quota is added AFTER the per-org override, so a
|
|
2593
2651
|
// contracted figure and a purchased add-on stack the way a raised
|
|
2594
2652
|
// `hostLimit` and purchased sites do. The per-unit figure is the PLAN's,
|
|
2595
2653
|
// read off the effective plan rather than the stored one, so a dead
|
|
2596
2654
|
// subscription that resolved to free adds free's figure.
|
|
2597
2655
|
const folded = foldPluginSeatAddons(resolved, purchased, resolvePlan(org));
|
|
2598
|
-
if (!extraHosts && !eventCalendar && folded === resolved)
|
|
2656
|
+
if (!extraHosts && !eventCalendar && !siteCare && folded === resolved) {
|
|
2657
|
+
return resolved;
|
|
2658
|
+
}
|
|
2599
2659
|
return _extends({}, folded, {
|
|
2600
2660
|
hostLimit: folded.hostLimit + extraHosts,
|
|
2601
2661
|
features: _extends({}, folded.features, eventCalendar ? {
|
|
2602
2662
|
eventCalendar: true
|
|
2663
|
+
} : {}, siteCare ? {
|
|
2664
|
+
siteCare: true
|
|
2603
2665
|
} : {})
|
|
2604
2666
|
});
|
|
2605
2667
|
}
|