@aglyn/aglyn 1.0.0-beta.277 → 1.0.0-beta.283

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/package.json +11 -11
  2. package/src/lib/app-utils/account-preferences.d.ts +146 -11
  3. package/src/lib/app-utils/account-preferences.js +266 -18
  4. package/src/lib/app-utils/account-preferences.js.map +1 -1
  5. package/src/lib/app-utils/activity-presenter.js +2 -26
  6. package/src/lib/app-utils/activity-presenter.js.map +1 -1
  7. package/src/lib/app-utils/activity-type-labels.d.ts +18 -0
  8. package/src/lib/app-utils/activity-type-labels.js +46 -0
  9. package/src/lib/app-utils/activity-type-labels.js.map +1 -0
  10. package/src/lib/app-utils/artifact-provenance.d.ts +3 -1
  11. package/src/lib/app-utils/artifact-provenance.js.map +1 -1
  12. package/src/lib/app-utils/bundle-intent.d.ts +37 -0
  13. package/src/lib/app-utils/bundle-intent.js +47 -3
  14. package/src/lib/app-utils/bundle-intent.js.map +1 -1
  15. package/src/lib/app-utils/compose-reusable-components.d.ts +17 -1
  16. package/src/lib/app-utils/compose-reusable-components.js +80 -5
  17. package/src/lib/app-utils/compose-reusable-components.js.map +1 -1
  18. package/src/lib/app-utils/docs-help-sections.generated.js +13 -1
  19. package/src/lib/app-utils/docs-help-sections.generated.js.map +1 -1
  20. package/src/lib/app-utils/docs-help.generated.d.ts +23 -11
  21. package/src/lib/app-utils/docs-help.generated.js +64 -7
  22. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  23. package/src/lib/app-utils/docs-index.generated.js +359 -51
  24. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  25. package/src/lib/app-utils/error-beacon.d.ts +19 -0
  26. package/src/lib/app-utils/error-beacon.js +28 -0
  27. package/src/lib/app-utils/error-beacon.js.map +1 -1
  28. package/src/lib/app-utils/health-report.d.ts +3 -2
  29. package/src/lib/app-utils/health-report.js +22 -2
  30. package/src/lib/app-utils/health-report.js.map +1 -1
  31. package/src/lib/app-utils/native-nav.d.ts +39 -4
  32. package/src/lib/app-utils/native-nav.js +69 -3
  33. package/src/lib/app-utils/native-nav.js.map +1 -1
  34. package/src/lib/app-utils/native-themes.d.ts +28 -17
  35. package/src/lib/app-utils/native-themes.js +123 -45
  36. package/src/lib/app-utils/native-themes.js.map +1 -1
  37. package/src/lib/app-utils/operator-alerts.js +4 -2
  38. package/src/lib/app-utils/operator-alerts.js.map +1 -1
  39. package/src/lib/app-utils/org-permission-editor.d.ts +75 -0
  40. package/src/lib/app-utils/org-permission-editor.js +124 -0
  41. package/src/lib/app-utils/org-permission-editor.js.map +1 -0
  42. package/src/lib/app-utils/org-permissions.d.ts +36 -0
  43. package/src/lib/app-utils/org-permissions.js +78 -26
  44. package/src/lib/app-utils/org-permissions.js.map +1 -1
  45. package/src/lib/app-utils/org-role-grants.d.ts +59 -9
  46. package/src/lib/app-utils/org-role-grants.js +97 -10
  47. package/src/lib/app-utils/org-role-grants.js.map +1 -1
  48. package/src/lib/app-utils/plan-entitlements.d.ts +13 -0
  49. package/src/lib/app-utils/plan-entitlements.js +22 -0
  50. package/src/lib/app-utils/plan-entitlements.js.map +1 -1
  51. package/src/lib/app-utils/release-flags.d.ts +52 -1
  52. package/src/lib/app-utils/release-flags.js +68 -2
  53. package/src/lib/app-utils/release-flags.js.map +1 -1
  54. package/src/lib/app-utils/reusable-component-keys.d.ts +13 -0
  55. package/src/lib/app-utils/reusable-component-keys.js +12 -0
  56. package/src/lib/app-utils/reusable-component-keys.js.map +1 -1
  57. package/src/lib/app-utils/screen-analytics-aggregate.d.ts +34 -0
  58. package/src/lib/app-utils/screen-analytics-aggregate.js +37 -0
  59. package/src/lib/app-utils/screen-analytics-aggregate.js.map +1 -1
  60. package/src/lib/app-utils/site-care.d.ts +35 -0
  61. package/src/lib/app-utils/site-care.js +48 -0
  62. package/src/lib/app-utils/site-care.js.map +1 -1
  63. package/src/lib/app-utils/site-font-pairings.d.ts +59 -0
  64. package/src/lib/app-utils/site-font-pairings.js +514 -0
  65. package/src/lib/app-utils/site-font-pairings.js.map +1 -0
  66. package/src/lib/app-utils/site-starter.d.ts +136 -0
  67. package/src/lib/app-utils/site-starter.js +116 -0
  68. package/src/lib/app-utils/site-starter.js.map +1 -0
  69. package/src/lib/app-utils/stock-photos/stock-photo-picker-server.d.ts +95 -0
  70. package/src/lib/app-utils/stock-photos/stock-photo-picker-server.js +333 -0
  71. package/src/lib/app-utils/stock-photos/stock-photo-picker-server.js.map +1 -0
  72. package/src/lib/app-utils/stock-photos/stock-photo-picker.d.ts +188 -0
  73. package/src/lib/app-utils/stock-photos/stock-photo-picker.js +193 -0
  74. package/src/lib/app-utils/stock-photos/stock-photo-picker.js.map +1 -0
  75. package/src/lib/plugin-manager/feature-plugins.d.ts +32 -0
  76. package/src/lib/plugin-manager/feature-plugins.js +12 -0
  77. package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
  78. package/src/lib/plugin-manager/first-party-plugins.generated.js +27 -1
  79. package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
  80. package/src/lib/plugin-manager/plugin-entitlements.d.ts +37 -0
  81. package/src/lib/plugin-manager/plugin-entitlements.js +84 -2
  82. package/src/lib/plugin-manager/plugin-entitlements.js.map +1 -1
  83. package/src/lib/plugin-manager/plugin-media-ingest.d.ts +15 -0
  84. package/src/lib/plugin-manager/plugin-media-ingest.js.map +1 -1
  85. package/src/lib/plugin-manager/plugin-permissions.d.ts +7 -0
  86. package/src/lib/plugin-manager/plugin-permissions.js.map +1 -1
  87. package/src/lib/plugin-manager/plugin-product-catalog.d.ts +12 -0
  88. package/src/lib/plugin-manager/plugin-product-catalog.js.map +1 -1
  89. package/src/lib/plugin-manager/plugin-site-starters.d.ts +73 -0
  90. package/src/lib/plugin-manager/plugin-site-starters.js +30 -0
  91. package/src/lib/plugin-manager/plugin-site-starters.js.map +1 -0
  92. package/src/lib/plugin-manager/plugin-sitemap-sections.d.ts +8 -1
  93. package/src/lib/plugin-manager/plugin-sitemap-sections.js.map +1 -1
  94. package/src/lib/plugin-manager/stock-photo-provider.d.ts +12 -0
  95. package/src/lib/plugin-manager/stock-photo-provider.js.map +1 -1
@@ -1 +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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"}
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/**\n * Where a key is decided (AGL-4047). `org`: by the member's org role, custom\n * role and overrides, the same on every site. `site`: as `org` for a member\n * who reaches the whole workspace, and per site for a site collaborator,\n * from the host role they hold there and that site's toggle.\n */\nexport type OrgPermissionScope = 'org' | 'site'\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 /** The group the role editor files it under (`ORG_PERMISSION_GROUPS`, or the declaring plugin's id). */\n group?: string\n /** Where it is decided; absent reads as `org`. */\n scope?: OrgPermissionScope\n}\n\n/** A heading the role editor groups keys under. */\nexport interface OrgPermissionGroup {\n id: string\n label: string\n /** The plugin whose keys it holds; absent for a core group. */\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 /** The groups the keys are filed under, in display order; absent in a catalog written before them. */\n groups?: OrgPermissionGroup[]\n}\n\n/**\n * A key a plugin declares into the catalog: `PluginOrgPermissionDeclaration`\n * with org-role defaults, or a `registerPluginPermissions` key (`managePos`),\n * whose `defaults` are per role tier, the owner holding the admin tier's.\n */\nexport interface OrgPermissionDeclaration {\n key: string\n label: string\n description?: string\n roleDefaults?: Record<OrgRoleName, boolean>\n /** The tier defaults of a `registerPluginPermissions` key, used when `roleDefaults` is absent. */\n defaults?: { admin: boolean; editor: boolean; viewer: boolean }\n /** The host-role defaults of a key a site collaborator holds per site. */\n hostRoleDefaults?: Record<string, boolean>\n /** The group it is filed under; absent: a group named by the declaring plugin's id. */\n group?: string\n /** That group's heading, for a group the core does not name. */\n groupLabel?: string\n pluginId?: string\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 groups, in display order. A plugin's keys are filed under a group\n * named by the plugin's id unless its declaration names one of these, so no\n * core group id is a plugin id.\n */\nexport const CORE_ORG_PERMISSION_GROUPS: readonly OrgPermissionGroup[] = [\n { id: 'organization', label: 'Organization' },\n { id: 'billing', label: 'Billing' },\n { id: 'team', label: 'Team' },\n { id: 'sites', label: 'Sites' },\n { id: 'datasets', label: 'Data' },\n { id: 'extensions', label: 'Marketplace and plugins' },\n]\n\n/**\n * A declaration's verdict for each org role: its `roleDefaults`, or, for a\n * `registerPluginPermissions` key, its tier `defaults` with the owner on the\n * admin tier (the tier `ORG_ROLE_TIER` resolves the owner onto).\n */\nexport function declarationRoleDefaults(\n declaration: Pick<OrgPermissionDeclaration, 'roleDefaults' | 'defaults'>,\n): Record<OrgRoleName, boolean> {\n if (declaration.roleDefaults) {\n return {\n owner: declaration.roleDefaults.owner === true,\n admin: declaration.roleDefaults.admin === true,\n editor: declaration.roleDefaults.editor === true,\n viewer: declaration.roleDefaults.viewer === true,\n }\n }\n const tiers = declaration.defaults\n return {\n owner: tiers?.admin === true,\n admin: tiers?.admin === true,\n editor: tiers?.editor === true,\n viewer: tiers?.viewer === true,\n }\n}\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 group: 'organization',\n label: 'Organization settings',\n description: 'Rename the organization, change its slug, transfer it.',\n },\n {\n key: 'org.auditLog',\n group: 'organization',\n label: 'Activity & audit log',\n description: 'See the organization activity feed.',\n },\n {\n key: 'billing.view',\n group: 'billing',\n label: 'View billing',\n description: 'See the plan, usage meters, and invoices.',\n },\n {\n key: 'billing.manage',\n group: 'billing',\n label: 'Manage billing',\n description: 'Change plans, buy add-ons, update payment details.',\n },\n {\n key: 'members.manage',\n group: 'team',\n label: 'Manage members',\n description: 'Invite, remove, and re-role organization members.',\n },\n {\n key: 'hosts.create',\n group: 'sites',\n label: 'Create sites',\n description: 'Create new sites in the organization.',\n },\n {\n key: 'hosts.delete',\n group: 'sites',\n label: 'Delete sites',\n description: 'Delete sites the member can access.',\n },\n {\n key: 'data.manage',\n group: 'datasets',\n label: 'Manage data',\n description: 'Create, edit, and delete organization datasets.',\n },\n {\n key: 'marketplace.publish',\n group: 'extensions',\n label: 'Publish to marketplace',\n description: 'Publish listings under the organization profile.',\n },\n {\n key: 'plugins.install',\n group: 'extensions',\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 groups: CORE_ORG_PERMISSION_GROUPS.map((group) => ({ ...group })),\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 defaults say so. A\n * declaration naming a key already taken is refused, as the console's\n * catalog refuses it: the first declaration keeps its meaning and defaults.\n * Every declaration list after the first is folded in the same way, so the\n * org catalog keys (`PluginOrgPermissionDeclaration`) and the\n * `registerPluginPermissions` keys land in one catalog (AGL-4047).\n */\nexport function assembleOrgRoleGrants(\n core: OrgRoleGrants,\n ...declarationLists: ReadonlyArray<readonly OrgPermissionDeclaration[]>\n): OrgRoleGrants {\n const permissions = [...core.permissions]\n const groups = [...(core.groups ?? [])]\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 const groupIds = new Set(groups.map((group) => group.id))\n for (const declaration of declarationLists.flat()) {\n if (!declaration?.key || taken.has(declaration.key)) continue\n taken.add(declaration.key)\n const group = declaration.group ?? declaration.pluginId\n permissions.push({\n key: declaration.key,\n label: declaration.label,\n description: declaration.description ?? '',\n ...(declaration.pluginId ? { pluginId: declaration.pluginId } : {}),\n ...(group ? { group } : {}),\n scope: declaration.hostRoleDefaults ? 'site' : 'org',\n })\n if (group && !groupIds.has(group)) {\n groupIds.add(group)\n groups.push({\n id: group,\n label: declaration.groupLabel ?? group,\n ...(declaration.pluginId ? { pluginId: declaration.pluginId } : {}),\n })\n }\n const defaults = declarationRoleDefaults(declaration)\n for (const role of ORG_ROLE_NAMES) {\n if (defaults[role]) grants[role].push(declaration.key)\n }\n }\n return { permissions, grants, groups }\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_GROUPS","id","label","declarationRoleDefaults","declaration","roleDefaults","owner","admin","editor","viewer","tiers","defaults","CORE_ORG_PERMISSION_ENTRIES","key","group","description","CORE_KEYS","map","entry","CORE_ORG_ROLE_GRANTS","ORG_ROLE_GRANTS","permissions","groups","grants","assembleOrgRoleGrants","core","declarationLists","Object","fromEntries","role","taken","Set","groupIds","flat","has","add","pluginId","push","scope","hostRoleDefaults","groupLabel","rolePermissions","catalog","customRole","overrides","keys","name","held","out","layer","values"],"mappings":"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"}
@@ -2099,6 +2099,19 @@ export declare function planGrantingFeature(feature: keyof OrgFeatureFlags): Org
2099
2099
  * or undefined when {@link planGrantingFeature} has no answer.
2100
2100
  */
2101
2101
  export declare function planLabelGrantingFeature(feature: keyof OrgFeatureFlags): string | undefined;
2102
+ /**
2103
+ * The cheapest plan whose base `quota` is at least `atLeast`, in the same
2104
+ * ladder order as {@link planGrantingFeature} — the quota half of "which plan
2105
+ * do I need for this?". `atLeast` of 1 asks which plan includes the quota at
2106
+ * all (campaign email starts at Pro); a larger figure asks which plan holds
2107
+ * a campaign of that size this month.
2108
+ *
2109
+ * Returns `undefined` when no plan's base tier reaches `atLeast`, and an
2110
+ * upsell must then name no plan rather than the top one.
2111
+ */
2112
+ export declare function planGrantingQuota(quota: keyof Omit<ResolvedOrgEntitlements, 'features'>, atLeast: number): OrgPlan | undefined;
2113
+ /** {@link planGrantingQuota} as the plan name an upsell interpolates. */
2114
+ export declare function planLabelGrantingQuota(quota: keyof Omit<ResolvedOrgEntitlements, 'features'>, atLeast: number): string | undefined;
2102
2115
  /**
2103
2116
  * True when the org's plan (or overrides) enables the boolean feature. A
2104
2117
  * key outside `OrgFeatureFlags` is one a plugin declared (AGL-2940) and is
@@ -3430,6 +3430,28 @@ export function saleProcessingCostCents(chargeCents) {
3430
3430
  const plan = planGrantingFeature(feature);
3431
3431
  return plan ? PLAN_LABELS[plan] : undefined;
3432
3432
  }
3433
+ /**
3434
+ * The cheapest plan whose base `quota` is at least `atLeast`, in the same
3435
+ * ladder order as {@link planGrantingFeature} — the quota half of "which plan
3436
+ * do I need for this?". `atLeast` of 1 asks which plan includes the quota at
3437
+ * all (campaign email starts at Pro); a larger figure asks which plan holds
3438
+ * a campaign of that size this month.
3439
+ *
3440
+ * Returns `undefined` when no plan's base tier reaches `atLeast`, and an
3441
+ * upsell must then name no plan rather than the top one.
3442
+ */ export function planGrantingQuota(quota, atLeast) {
3443
+ return [
3444
+ ...SELF_SERVE_PLANS,
3445
+ 'enterprise'
3446
+ ].find((plan)=>{
3447
+ var _PLAN_ENTITLEMENTS_plan_quota;
3448
+ return Number((_PLAN_ENTITLEMENTS_plan_quota = PLAN_ENTITLEMENTS[plan][quota]) != null ? _PLAN_ENTITLEMENTS_plan_quota : 0) >= atLeast;
3449
+ });
3450
+ }
3451
+ /** {@link planGrantingQuota} as the plan name an upsell interpolates. */ export function planLabelGrantingQuota(quota, atLeast) {
3452
+ const plan = planGrantingQuota(quota, atLeast);
3453
+ return plan ? PLAN_LABELS[plan] : undefined;
3454
+ }
3433
3455
  /**
3434
3456
  * True when the org's plan (or overrides) enables the boolean feature. A
3435
3457
  * key outside `OrgFeatureFlags` is one a plugin declared (AGL-2940) and is