@aglyn/aglyn 1.0.0-beta.152 → 1.0.0-beta.153

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 (42) hide show
  1. package/package.json +10 -10
  2. package/src/lib/app-utils/crm-csv.d.ts +10 -3
  3. package/src/lib/app-utils/crm-csv.js +37 -2
  4. package/src/lib/app-utils/crm-csv.js.map +1 -1
  5. package/src/lib/app-utils/crm-email-templates.js +15 -0
  6. package/src/lib/app-utils/crm-email-templates.js.map +1 -1
  7. package/src/lib/app-utils/crm.d.ts +69 -2
  8. package/src/lib/app-utils/crm.js +126 -1
  9. package/src/lib/app-utils/crm.js.map +1 -1
  10. package/src/lib/app-utils/docs-help.generated.d.ts +1 -1
  11. package/src/lib/app-utils/docs-help.generated.js +2 -0
  12. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  13. package/src/lib/app-utils/docs-index.generated.js +25 -11
  14. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  15. package/src/lib/app-utils/email-starter-policy.js +5 -3
  16. package/src/lib/app-utils/email-starter-policy.js.map +1 -1
  17. package/src/lib/app-utils/plan-entitlements.d.ts +34 -0
  18. package/src/lib/app-utils/plan-entitlements.js +40 -0
  19. package/src/lib/app-utils/plan-entitlements.js.map +1 -1
  20. package/src/lib/app-utils/server.d.ts +0 -1
  21. package/src/lib/app-utils/server.js +0 -1
  22. package/src/lib/app-utils/server.js.map +1 -1
  23. package/src/lib/plugin-manager/first-party-plugins.generated.js +1 -0
  24. package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
  25. package/src/lib/plugin-manager/plugin-artifact-inventory.d.ts +145 -0
  26. package/src/lib/plugin-manager/plugin-artifact-inventory.js +126 -0
  27. package/src/lib/plugin-manager/plugin-artifact-inventory.js.map +1 -0
  28. package/src/lib/plugin-manager/plugin-contact-capture.d.ts +32 -1
  29. package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -1
  30. package/src/lib/plugin-manager/plugin-lead-conversion.d.ts +67 -0
  31. package/src/lib/plugin-manager/plugin-lead-conversion.js +93 -0
  32. package/src/lib/plugin-manager/plugin-lead-conversion.js.map +1 -0
  33. package/src/lib/plugin-manager/plugin-org-capacity.d.ts +12 -0
  34. package/src/lib/plugin-manager/plugin-org-capacity.js.map +1 -1
  35. package/src/lib/plugin-manager/plugin-record-timeline.d.ts +8 -1
  36. package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -1
  37. package/src/lib/app-utils/marketplace-verification.d.ts +0 -95
  38. package/src/lib/app-utils/marketplace-verification.js +0 -81
  39. package/src/lib/app-utils/marketplace-verification.js.map +0 -1
  40. package/src/lib/app-utils/publisher-attestation.d.ts +0 -99
  41. package/src/lib/app-utils/publisher-attestation.js +0 -158
  42. package/src/lib/app-utils/publisher-attestation.js.map +0 -1
@@ -128,7 +128,6 @@ export * from './measure-node-map';
128
128
  export * from './resolve-named-tokens';
129
129
  export * from './screen-route';
130
130
  export * from './host-naming';
131
- export * from './marketplace-verification';
132
131
  export * from './name-search';
133
132
  export * from './name-match';
134
133
  export * from './api-plugins';
@@ -256,7 +256,6 @@ export * from "./measure-node-map.js";
256
256
  export * from "./resolve-named-tokens.js";
257
257
  export * from "./screen-route.js";
258
258
  export * from "./host-naming.js";
259
- export * from "./marketplace-verification.js";
260
259
  export * from "./name-search.js";
261
260
  export * from "./name-match.js";
262
261
  export * from "./api-plugins.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/server.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2022 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 * Server-safe app-utils: every app-util EXCEPT the client-only React\n * contexts (see ./contexts). Nothing here calls `createContext` at module\n * scope, so this barrel — re-exported by `@aglyn/aglyn/server` — is safe to\n * import from tenant Server Components (AGL-405). The full `./index` barrel\n * re-adds the contexts for client consumers.\n */\nexport * from './binding-token-catalog'\nexport * from './binding-tokens'\nexport * from './breadcrumb-json-ld'\n// What a search listing holds and how long each field may be (AGL-2910):\n// the SEO editors and anything that proposes a value read one catalog.\nexport * from './seo-listing-fields'\n// `VideoObject` for the Video elements a page actually ships (AGL-2747).\n// Beside the other structured-data builders, and server-only like them: only\n// the route emits JSON-LD, and a crawler-facing block has no client caller.\nexport * from './video-object'\nexport * from './collection-delete'\nexport * from './collection-entries'\nexport * from './collection-kind'\nexport * from './collection-slug'\nexport * from './content-authors'\nexport * from './content-schema-type'\nexport * from './content-author-profile'\nexport * from './url-slug'\nexport * from './child-contract'\nexport * from './child-contract-compose'\n// The one reading of `restrictChildren`/`restrictParent`, shared by the\n// besigner's drop check and the AI plugin's node-tree validator (AGL-2905).\nexport * from './lineal-order'\n// What a node tree must satisfy before it lands on a canvas that did not\n// author it (AGL-2939): the marketplace's install sanitizer and the AI\n// plugin's node-tree validator both pass through it.\nexport * from './node-definition-sanitizer'\nexport * from './console-routes'\nexport * from './console-record-links'\n// What a stored screen-link value means, with no React attached — the\n// where-used scan reads these on the server (AGL-703).\nexport * from './screen-link-value'\n// Which entries a page's links name (AGL-3118). The tenant render reads\n// exactly those entry documents, so the walk runs on the server.\nexport * from './link-references'\nexport * from './analytics-path-key'\nexport * from './contacts'\n// The records that sit beside a contact — companies, pipelines, deals, tasks,\n// activities, field definitions (AGL-2595). Pure like `contacts`, and beside\n// it because `ContactFacet` names its lifecycle stage and custom-value types;\n// the scope stamp every CRM creator writes lives here too.\nexport * from './crm'\n// Email templates, snippets and the merge-field resolver (AGL-2658): the\n// letter a rep keeps under a name, and the one grammar the send route and\n// the dialog fill it in by. Pure like `crm`, and beside it because a\n// template is scoped the way a task is.\nexport * from './crm-email-templates'\n// The booking door's shared vocabulary (AGL-2660): the query keys a booking\n// link carries, the record reference inside it, and the wording and due\n// date of what a booking files back on the record.\nexport * from './crm-booking'\n// Two contact documents folded into one (AGL-2625): the plan the console\n// previews and the server writes, reading the facet shape from `contacts`\n// and the company mirror from `crm`.\nexport * from './contact-merge'\n// A person's privacy erasure from one workspace (AGL-2623): the request's\n// shape and id, the marker a record carries while it waits, and the lists\n// the dialog and the docs share. Pure like `crm`; the sweep is server-side.\nexport * from './person-erasure'\n// What the CRM's reports compute from what they read — periods, weekly\n// buckets, the lifecycle funnel, pipeline totals (AGL-2604). Pure like `crm`,\n// and beside it because it reads the stage list and the deal weighting from\n// there rather than restating either.\nexport * from './crm-reports'\n// Every CRM CSV, written once (AGL-2662): the column lists and the cells\n// each section's Export button writes, and the server's whole-collection\n// export streams — one implementation, because the console app may not\n// import the plugin whose sections used to hold it.\nexport * from './crm-csv'\n// Which holder a cross-site reader sees one contact through (AGL-2630),\n// beside the files that write it: the org-level list and the server's\n// export both flatten a contact this way.\nexport * from './contact-holder'\n// What one member is owed this morning — the day's window in a named zone,\n// the task and lead bucketing, and the words the notification and the mail\n// say (AGL-2619). Pure like `crm-reports`, read by the scheduled route.\nexport * from './crm-digest'\n// A task's reminder at its own time (AGL-2659): which reminder a save\n// leaves, whether one is owed, and the words the notification and the mail\n// say. Pure like `crm-digest`, read by the hourly route and by every\n// writer of the field.\nexport * from './crm-task-reminders'\n// Email capture (AGL-2657): the address's shape and token, which of a\n// message's addresses is the correspondent, the excerpt, and the row a\n// captured message becomes. Pure like `crm-digest`; the webhook route and\n// the address route are the readers with Firestore.\nexport * from './crm-inbound'\n// A member's own addresses in a workspace (AGL-2975): the ones they have\n// confirmed count as theirs wherever the roster is asked who wrote a\n// message. Pure; the store and the confirmation link are server-side.\nexport * from './member-email-aliases'\n// The next activity a record carries (AGL-2661): what `nextTaskAtMs` IS given\n// a record's open tasks, the view clause a list filters on, the report figure.\n// Pure like `crm`; the admin library's `recomputeCrmNextTaskAt` is the writer.\nexport * from './crm-next-activity'\n// The CSV cell grammar the exports write with (AGL-2621), and the target a\n// mapped column names for a custom field — named rather than starred, because\n// an importer built on this file exports the shared ceilings under its own\n// names.\nexport {\n csvCell,\n csvDocument,\n customImportTarget,\n customImportTargetKey,\n} from './csv-import'\nexport type {\n ImportChunkResult,\n ImportDroppedValue,\n ImportSkippedRow,\n} from './csv-import'\n// What a VALUE under a custom contact field may be, and the coercion every\n// door applies to one (AGL-2601): a mapped form field, an API `custom` body,\n// and the carry-over that keeps a mapping across a publish. Pure like `crm`.\nexport * from './contact-custom-fields'\n// The consent JOIN (`docs/specs/email-overhaul.md` §3f). Pure, and it composes\n// `contacts` for the normalizer, so it sits directly beside it. No Node\n// builtin, which is what keeps it out of the `/server`-only group `person-key`\n// belongs to.\nexport * from './consent-groups'\nexport * from './marketing-consent'\n// The ENROLLMENT-time half of the same question, beside its reader for the\n// same reason: `marketing-consent` decides whether a recorded basis lets us\n// mail somebody, and this decides what basis putting them on a list may\n// record. Two enrollment surfaces import it — the Inbox assignment route and\n// the Emails console's audience card — and neither could import the other.\nexport * from './list-assignment-policy'\n// Reading the FILE a merchant arrives with (`docs/specs/email-competitive-gaps.md`\n// G5/P4), directly after the policy it hands its addresses to: parsing and\n// mechanical screening only, so that an import asks the enrollment question\n// through the same module the one-address add path asks it through rather\n// than answering it a second way.\nexport * from './list-import'\n// The dynamic-list rule (§3b/§3c), beside it for the same reasons: pure, and\n// it composes `contacts` for the segment vocabulary rather than restating it.\nexport * from './dynamic-list-rule'\n// The subscribable streams a recipient can leave one at a time\n// (`docs/specs/email-competitive-gaps.md` §1f). Pure, and read from all three\n// sides of the feature: the composer picks one, the send path signs it into\n// the unsubscribe link, and the unauthenticated preference page renders the\n// catalog. No Node builtin, so it stays out of the `/server`-only group.\nexport * from './email-topics'\nexport * from './compose-layout-nodes'\n// Layout properties applied through the chain (AGL-2893).\nexport * from './compose-layout-props'\nexport * from './document-landmark'\nexport * from './functions'\nexport * from './compose-reusable-components'\nexport * from './compress'\nexport * from './merge-node-sx'\nexport * from './palette-sx'\nexport * from './scheme-sx'\nexport * from './create-resource-uid'\nexport * from './decompress'\nexport * from './stored-nodes'\nexport * from './strip-undefined'\nexport * from './organizations'\nexport * from './org-permissions'\n// The AI verdict on either membership axis (AGL-2927). After both modules it\n// composes: the org catalog for org-wide members, the host role for site\n// collaborators.\nexport * from './host-permissions'\nexport * from './password-policy'\nexport * from './idp-profile'\nexport * from './onboarding-deep-link'\n// Where an account came from (AGL-1731). Beside the plan intent because\n// they are the same hop — the marketing CTA's query string — and both are\n// remembered on `users/{uid}` across the verification wall.\nexport * from './campaign-attribution'\n// The edge between a campaign and the forms, screens and contacts a push is\n// coordinated across. Beside the attribution above because the two answer\n// opposite questions about the same word: attribution records where somebody\n// CAME from, this records what a merchant DECLARED belongs together.\nexport * from './campaign-membership'\nexport * from './deployment-shape'\n// Which browser origins may complete a signed direct-to-GCS upload (AGL-1452).\n// GCS matches the origin list EXACTLY, so every serving console name needs its\n// own entry — the rule nobody could be expected to remember at attach time.\nexport * from './upload-cors'\n// The docs-help subset the first-party plugin consoles read (AGL-2213) — the\n// console's own registry lives in apps/console/constants and a lib cannot\n// import an app.\nexport * from './docs-help'\nexport * from './platform-brand'\nexport * from './plan-entitlements'\n// The free plan's bandwidth hard cap (AGL-1967/2070/2155). After\n// `plan-entitlements`, which owns the predicate it keys off.\nexport * from './bandwidth-cap'\nexport * from './form-abuse-ceiling'\nexport * from './forms'\n// What a form's DESIGN must still satisfy for its submissions to arrive.\n// After `forms`, whose field walk it reads the drawn fields with.\nexport * from './form-contract'\nexport * from './visitor-record-ceiling'\nexport * from './health-report'\n// Did a webhook delivery actually DO anything (AGL-1954)? After\n// `health-report`, whose billing verdict consumes the counts this produces.\nexport * from './webhook-delivery'\nexport * from './support-tiers'\nexport * from './release-flags'\n// Who runs THIS deployment, and where its notices go (AGL-2016). Ordered\n// before the four surfaces that print it, all of which used to declare their\n// own `support@aglyn.com` literal.\nexport * from './operator-identity'\nexport * from './lockdown'\nexport * from './media-quarantine'\nexport * from './media-takedown-reach'\nexport * from './upload-inspection'\nexport * from './abuse-report'\n// The other three quarters of §512 (AGL-1983): the put-back procedure that\n// answers a notice, and the strike ledger that conditions the safe harbour.\nexport * from './dmca-counter-notice'\nexport * from './repeat-infringer'\n// `addBusinessDays` briefly existed TWICE — once here in './support-tiers'\n// and once in './dmca-counter-notice' — and two `export *` made the name\n// ambiguous, TS2308'ing this barrel and every tsconfig that reads it. The\n// interleave was fixed twice in parallel: once by naming a winner here, and\n// once by deleting the second definition so './dmca-counter-notice' imports\n// this one. Only the deletion survives, so the disambiguating re-export that\n// stood on this line is gone with it — `export *` is unambiguous again.\n//\n// The concern that argued for keeping two copies is worth answering rather\n// than dropping: a later tweak to the SUPPORT SLA window must never silently\n// move the §512(g)(2)(C) put-back deadline. It cannot. This function embeds\n// no window — it is \"add N business days\", and N is the argument. The two\n// windows live in their own constants (`SUPPORT_*` there,\n// `COUNTER_NOTICE_*_BUSINESS_DAYS` in the DMCA module) and never meet. What\n// SHOULD stay shared is the day arithmetic itself: two copies of a weekend\n// rule are two chances to disagree about which day a deadline falls on.\nexport * from './org-override-reason'\nexport * from './host-tokens'\nexport * from './variables'\nexport * from './workflows'\nexport * from './datasets'\nexport * from './expand-repeatables'\nexport * from './org-roles'\nexport * from './markdown-lite'\nexport * from './notifications'\nexport * from './definition-canvas-tree'\nexport * from './ensure-canvas-root'\nexport * from './repair-canvas-nodes'\nexport * from './detect-template-placeholders'\nexport * from './guarded-version-save'\nexport * from './local-storage-budget'\nexport * from './measure-node-map'\nexport * from './resolve-named-tokens'\nexport * from './screen-route'\nexport * from './host-naming'\nexport * from './marketplace-verification'\nexport * from './name-search'\nexport * from './name-match'\nexport * from './api-plugins'\nexport * from './plugin-api-rate-limit'\n// The same-origin gate on visitor-facing plugin writes (AGL-1880). After\n// `plugin-api-rate-limit`, whose `isMachinePluginApiPath` it reuses so the\n// two gates exempt exactly the same machine surfaces.\nexport * from './plugin-api-cross-origin'\nexport * from './actions'\nexport * from './element-animation'\nexport * from './attribution-guard'\nexport * from './node-interactions'\nexport * from './element-ui'\nexport * from './image-upload-types'\nexport * from './sanitize-svg'\nexport * from './media-folders'\nexport * from './media-metadata'\nexport * from './media-ref'\n// After `media-ref`, whose reference grammar it reads stored URLs with.\nexport * from './paid-media-source'\nexport * from './author-css'\n// The isomorphic HTML rule (AGL-1901), after the CSS one it depends on.\nexport * from './author-html'\nexport * from './dataset-models'\nexport * from './dataset-csv'\nexport * from './marketplace-provenance'\nexport * from './marketplace-update-state'\nexport * from './dataset-query'\nexport * from './plugin-manifest'\n// After `plugin-manifest`, whose revocation predicates it asks the kill\n// question with, and after `media-ref`, whose grammar decides what counts as a\n// first-party image.\nexport * from './email-starter-policy'\nexport * from './safe-json-ld'\n// Agent readiness (AGL-2716): content negotiation, the Markdown rendering of a\n// page, `/llms.txt` and the per-site OpenAPI document. All pure, all server-safe.\nexport * from './accept-negotiation'\nexport * from './agent-api-catalog'\nexport * from './agent-openapi'\nexport * from './author-html-markdown'\nexport * from './llms-txt'\nexport * from './page-markdown'\nexport * from './request-geo'\nexport * from './request-ip'\nexport * from './search-indexing'\nexport * from './seo-title'\nexport * from './sitemap'\nexport * from './visitor-consent'\nexport * from './social-image'\nexport * from './scope-tokens'\nexport * from './org-billing-doc'\nexport * from './stripe-deployment-mode'\nexport * from './deferred-image'\n"],"names":["csvCell","csvDocument","customImportTarget","customImportTargetKey"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/server.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2022 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 * Server-safe app-utils: every app-util EXCEPT the client-only React\n * contexts (see ./contexts). Nothing here calls `createContext` at module\n * scope, so this barrel — re-exported by `@aglyn/aglyn/server` — is safe to\n * import from tenant Server Components (AGL-405). The full `./index` barrel\n * re-adds the contexts for client consumers.\n */\nexport * from './binding-token-catalog'\nexport * from './binding-tokens'\nexport * from './breadcrumb-json-ld'\n// What a search listing holds and how long each field may be (AGL-2910):\n// the SEO editors and anything that proposes a value read one catalog.\nexport * from './seo-listing-fields'\n// `VideoObject` for the Video elements a page actually ships (AGL-2747).\n// Beside the other structured-data builders, and server-only like them: only\n// the route emits JSON-LD, and a crawler-facing block has no client caller.\nexport * from './video-object'\nexport * from './collection-delete'\nexport * from './collection-entries'\nexport * from './collection-kind'\nexport * from './collection-slug'\nexport * from './content-authors'\nexport * from './content-schema-type'\nexport * from './content-author-profile'\nexport * from './url-slug'\nexport * from './child-contract'\nexport * from './child-contract-compose'\n// The one reading of `restrictChildren`/`restrictParent`, shared by the\n// besigner's drop check and the AI plugin's node-tree validator (AGL-2905).\nexport * from './lineal-order'\n// What a node tree must satisfy before it lands on a canvas that did not\n// author it (AGL-2939): the marketplace's install sanitizer and the AI\n// plugin's node-tree validator both pass through it.\nexport * from './node-definition-sanitizer'\nexport * from './console-routes'\nexport * from './console-record-links'\n// What a stored screen-link value means, with no React attached — the\n// where-used scan reads these on the server (AGL-703).\nexport * from './screen-link-value'\n// Which entries a page's links name (AGL-3118). The tenant render reads\n// exactly those entry documents, so the walk runs on the server.\nexport * from './link-references'\nexport * from './analytics-path-key'\nexport * from './contacts'\n// The records that sit beside a contact — companies, pipelines, deals, tasks,\n// activities, field definitions (AGL-2595). Pure like `contacts`, and beside\n// it because `ContactFacet` names its lifecycle stage and custom-value types;\n// the scope stamp every CRM creator writes lives here too.\nexport * from './crm'\n// Email templates, snippets and the merge-field resolver (AGL-2658): the\n// letter a rep keeps under a name, and the one grammar the send route and\n// the dialog fill it in by. Pure like `crm`, and beside it because a\n// template is scoped the way a task is.\nexport * from './crm-email-templates'\n// The booking door's shared vocabulary (AGL-2660): the query keys a booking\n// link carries, the record reference inside it, and the wording and due\n// date of what a booking files back on the record.\nexport * from './crm-booking'\n// Two contact documents folded into one (AGL-2625): the plan the console\n// previews and the server writes, reading the facet shape from `contacts`\n// and the company mirror from `crm`.\nexport * from './contact-merge'\n// A person's privacy erasure from one workspace (AGL-2623): the request's\n// shape and id, the marker a record carries while it waits, and the lists\n// the dialog and the docs share. Pure like `crm`; the sweep is server-side.\nexport * from './person-erasure'\n// What the CRM's reports compute from what they read — periods, weekly\n// buckets, the lifecycle funnel, pipeline totals (AGL-2604). Pure like `crm`,\n// and beside it because it reads the stage list and the deal weighting from\n// there rather than restating either.\nexport * from './crm-reports'\n// Every CRM CSV, written once (AGL-2662): the column lists and the cells\n// each section's Export button writes, and the server's whole-collection\n// export streams — one implementation, because the console app may not\n// import the plugin whose sections used to hold it.\nexport * from './crm-csv'\n// Which holder a cross-site reader sees one contact through (AGL-2630),\n// beside the files that write it: the org-level list and the server's\n// export both flatten a contact this way.\nexport * from './contact-holder'\n// What one member is owed this morning — the day's window in a named zone,\n// the task and lead bucketing, and the words the notification and the mail\n// say (AGL-2619). Pure like `crm-reports`, read by the scheduled route.\nexport * from './crm-digest'\n// A task's reminder at its own time (AGL-2659): which reminder a save\n// leaves, whether one is owed, and the words the notification and the mail\n// say. Pure like `crm-digest`, read by the hourly route and by every\n// writer of the field.\nexport * from './crm-task-reminders'\n// Email capture (AGL-2657): the address's shape and token, which of a\n// message's addresses is the correspondent, the excerpt, and the row a\n// captured message becomes. Pure like `crm-digest`; the webhook route and\n// the address route are the readers with Firestore.\nexport * from './crm-inbound'\n// A member's own addresses in a workspace (AGL-2975): the ones they have\n// confirmed count as theirs wherever the roster is asked who wrote a\n// message. Pure; the store and the confirmation link are server-side.\nexport * from './member-email-aliases'\n// The next activity a record carries (AGL-2661): what `nextTaskAtMs` IS given\n// a record's open tasks, the view clause a list filters on, the report figure.\n// Pure like `crm`; the admin library's `recomputeCrmNextTaskAt` is the writer.\nexport * from './crm-next-activity'\n// The CSV cell grammar the exports write with (AGL-2621), and the target a\n// mapped column names for a custom field — named rather than starred, because\n// an importer built on this file exports the shared ceilings under its own\n// names.\nexport {\n csvCell,\n csvDocument,\n customImportTarget,\n customImportTargetKey,\n} from './csv-import'\nexport type {\n ImportChunkResult,\n ImportDroppedValue,\n ImportSkippedRow,\n} from './csv-import'\n// What a VALUE under a custom contact field may be, and the coercion every\n// door applies to one (AGL-2601): a mapped form field, an API `custom` body,\n// and the carry-over that keeps a mapping across a publish. Pure like `crm`.\nexport * from './contact-custom-fields'\n// The consent JOIN (`docs/specs/email-overhaul.md` §3f). Pure, and it composes\n// `contacts` for the normalizer, so it sits directly beside it. No Node\n// builtin, which is what keeps it out of the `/server`-only group `person-key`\n// belongs to.\nexport * from './consent-groups'\nexport * from './marketing-consent'\n// The ENROLLMENT-time half of the same question, beside its reader for the\n// same reason: `marketing-consent` decides whether a recorded basis lets us\n// mail somebody, and this decides what basis putting them on a list may\n// record. Two enrollment surfaces import it — the Inbox assignment route and\n// the Emails console's audience card — and neither could import the other.\nexport * from './list-assignment-policy'\n// Reading the FILE a merchant arrives with (`docs/specs/email-competitive-gaps.md`\n// G5/P4), directly after the policy it hands its addresses to: parsing and\n// mechanical screening only, so that an import asks the enrollment question\n// through the same module the one-address add path asks it through rather\n// than answering it a second way.\nexport * from './list-import'\n// The dynamic-list rule (§3b/§3c), beside it for the same reasons: pure, and\n// it composes `contacts` for the segment vocabulary rather than restating it.\nexport * from './dynamic-list-rule'\n// The subscribable streams a recipient can leave one at a time\n// (`docs/specs/email-competitive-gaps.md` §1f). Pure, and read from all three\n// sides of the feature: the composer picks one, the send path signs it into\n// the unsubscribe link, and the unauthenticated preference page renders the\n// catalog. No Node builtin, so it stays out of the `/server`-only group.\nexport * from './email-topics'\nexport * from './compose-layout-nodes'\n// Layout properties applied through the chain (AGL-2893).\nexport * from './compose-layout-props'\nexport * from './document-landmark'\nexport * from './functions'\nexport * from './compose-reusable-components'\nexport * from './compress'\nexport * from './merge-node-sx'\nexport * from './palette-sx'\nexport * from './scheme-sx'\nexport * from './create-resource-uid'\nexport * from './decompress'\nexport * from './stored-nodes'\nexport * from './strip-undefined'\nexport * from './organizations'\nexport * from './org-permissions'\n// The AI verdict on either membership axis (AGL-2927). After both modules it\n// composes: the org catalog for org-wide members, the host role for site\n// collaborators.\nexport * from './host-permissions'\nexport * from './password-policy'\nexport * from './idp-profile'\nexport * from './onboarding-deep-link'\n// Where an account came from (AGL-1731). Beside the plan intent because\n// they are the same hop — the marketing CTA's query string — and both are\n// remembered on `users/{uid}` across the verification wall.\nexport * from './campaign-attribution'\n// The edge between a campaign and the forms, screens and contacts a push is\n// coordinated across. Beside the attribution above because the two answer\n// opposite questions about the same word: attribution records where somebody\n// CAME from, this records what a merchant DECLARED belongs together.\nexport * from './campaign-membership'\nexport * from './deployment-shape'\n// Which browser origins may complete a signed direct-to-GCS upload (AGL-1452).\n// GCS matches the origin list EXACTLY, so every serving console name needs its\n// own entry — the rule nobody could be expected to remember at attach time.\nexport * from './upload-cors'\n// The docs-help subset the first-party plugin consoles read (AGL-2213) — the\n// console's own registry lives in apps/console/constants and a lib cannot\n// import an app.\nexport * from './docs-help'\nexport * from './platform-brand'\nexport * from './plan-entitlements'\n// The free plan's bandwidth hard cap (AGL-1967/2070/2155). After\n// `plan-entitlements`, which owns the predicate it keys off.\nexport * from './bandwidth-cap'\nexport * from './form-abuse-ceiling'\nexport * from './forms'\n// What a form's DESIGN must still satisfy for its submissions to arrive.\n// After `forms`, whose field walk it reads the drawn fields with.\nexport * from './form-contract'\nexport * from './visitor-record-ceiling'\nexport * from './health-report'\n// Did a webhook delivery actually DO anything (AGL-1954)? After\n// `health-report`, whose billing verdict consumes the counts this produces.\nexport * from './webhook-delivery'\nexport * from './support-tiers'\nexport * from './release-flags'\n// Who runs THIS deployment, and where its notices go (AGL-2016). Ordered\n// before the four surfaces that print it, all of which used to declare their\n// own `support@aglyn.com` literal.\nexport * from './operator-identity'\nexport * from './lockdown'\nexport * from './media-quarantine'\nexport * from './media-takedown-reach'\nexport * from './upload-inspection'\nexport * from './abuse-report'\n// The other three quarters of §512 (AGL-1983): the put-back procedure that\n// answers a notice, and the strike ledger that conditions the safe harbour.\nexport * from './dmca-counter-notice'\nexport * from './repeat-infringer'\n// `addBusinessDays` briefly existed TWICE — once here in './support-tiers'\n// and once in './dmca-counter-notice' — and two `export *` made the name\n// ambiguous, TS2308'ing this barrel and every tsconfig that reads it. The\n// interleave was fixed twice in parallel: once by naming a winner here, and\n// once by deleting the second definition so './dmca-counter-notice' imports\n// this one. Only the deletion survives, so the disambiguating re-export that\n// stood on this line is gone with it — `export *` is unambiguous again.\n//\n// The concern that argued for keeping two copies is worth answering rather\n// than dropping: a later tweak to the SUPPORT SLA window must never silently\n// move the §512(g)(2)(C) put-back deadline. It cannot. This function embeds\n// no window — it is \"add N business days\", and N is the argument. The two\n// windows live in their own constants (`SUPPORT_*` there,\n// `COUNTER_NOTICE_*_BUSINESS_DAYS` in the DMCA module) and never meet. What\n// SHOULD stay shared is the day arithmetic itself: two copies of a weekend\n// rule are two chances to disagree about which day a deadline falls on.\nexport * from './org-override-reason'\nexport * from './host-tokens'\nexport * from './variables'\nexport * from './workflows'\nexport * from './datasets'\nexport * from './expand-repeatables'\nexport * from './org-roles'\nexport * from './markdown-lite'\nexport * from './notifications'\nexport * from './definition-canvas-tree'\nexport * from './ensure-canvas-root'\nexport * from './repair-canvas-nodes'\nexport * from './detect-template-placeholders'\nexport * from './guarded-version-save'\nexport * from './local-storage-budget'\nexport * from './measure-node-map'\nexport * from './resolve-named-tokens'\nexport * from './screen-route'\nexport * from './host-naming'\nexport * from './name-search'\nexport * from './name-match'\nexport * from './api-plugins'\nexport * from './plugin-api-rate-limit'\n// The same-origin gate on visitor-facing plugin writes (AGL-1880). After\n// `plugin-api-rate-limit`, whose `isMachinePluginApiPath` it reuses so the\n// two gates exempt exactly the same machine surfaces.\nexport * from './plugin-api-cross-origin'\nexport * from './actions'\nexport * from './element-animation'\nexport * from './attribution-guard'\nexport * from './node-interactions'\nexport * from './element-ui'\nexport * from './image-upload-types'\nexport * from './sanitize-svg'\nexport * from './media-folders'\nexport * from './media-metadata'\nexport * from './media-ref'\n// After `media-ref`, whose reference grammar it reads stored URLs with.\nexport * from './paid-media-source'\nexport * from './author-css'\n// The isomorphic HTML rule (AGL-1901), after the CSS one it depends on.\nexport * from './author-html'\nexport * from './dataset-models'\nexport * from './dataset-csv'\nexport * from './marketplace-provenance'\nexport * from './marketplace-update-state'\nexport * from './dataset-query'\nexport * from './plugin-manifest'\n// After `plugin-manifest`, whose revocation predicates it asks the kill\n// question with, and after `media-ref`, whose grammar decides what counts as a\n// first-party image.\nexport * from './email-starter-policy'\nexport * from './safe-json-ld'\n// Agent readiness (AGL-2716): content negotiation, the Markdown rendering of a\n// page, `/llms.txt` and the per-site OpenAPI document. All pure, all server-safe.\nexport * from './accept-negotiation'\nexport * from './agent-api-catalog'\nexport * from './agent-openapi'\nexport * from './author-html-markdown'\nexport * from './llms-txt'\nexport * from './page-markdown'\nexport * from './request-geo'\nexport * from './request-ip'\nexport * from './search-indexing'\nexport * from './seo-title'\nexport * from './sitemap'\nexport * from './visitor-consent'\nexport * from './social-image'\nexport * from './scope-tokens'\nexport * from './org-billing-doc'\nexport * from './stripe-deployment-mode'\nexport * from './deferred-image'\n"],"names":["csvCell","csvDocument","customImportTarget","customImportTargetKey"],"mappings":"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"}
@@ -412,6 +412,7 @@ export const PUBLISHED_SITE_IMPACT = {
412
412
  "collection": "datasets",
413
413
  "addonKind": "datasets",
414
414
  "includedEntitlement": "datasetsPerOrg",
415
+ "purchaseCeilingEntitlement": "maxDatasetsPerOrg",
415
416
  "nouns": {
416
417
  "one": "dataset",
417
418
  "many": "datasets",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/first-party-plugins.generated.ts"],"sourcesContent":["/**\n * GENERATED FILE — do not edit. Regenerate with:\n * node tools/scripts/generate-plugin-manifests.mjs\n *\n * The switchboard catalog (AGL-3080): one row per plugin and capability, each\n * declared by its own `catalog` block in plugins.config.json. The core holds\n * the types and the resolvers in `enabled-plugins.ts`; it holds no row.\n */\n\nimport type { FirstPartyPlugin, PluginEditBarLink, PublishedSiteImpact } from './enabled-plugins'\nimport type { ResolvedPluginHostCollection } from './plugin-host-collections'\nimport type { ResolvedPluginOrgCapacity } from './plugin-org-capacity'\n\nexport const FIRST_PARTY_PLUGINS: readonly FirstPartyPlugin[] = [\n {\n \"id\": \"mui\",\n \"label\": \"Components\",\n \"alwaysOn\": true,\n \"description\": \"The base component and theme library every site builds on.\"\n },\n {\n \"id\": \"forms\",\n \"label\": \"Forms\",\n \"alwaysOnForWorkspace\": true,\n \"description\": \"Forms on the site and the catalog that owns them.\",\n \"siteOff\": {\n \"stops\": \"Switching Forms off for this site stops forms rendering on its published pages, refuses every submission sent to it, and blocks publishing a form, or a page that carries one, until Forms is back on.\",\n \"keeps\": \"Submissions already received, the workspace’s form catalog and the CRM leads its forms created are kept, and forms keep working on the workspace’s other sites.\",\n \"confirm\": true,\n \"pages\": {\n \"heading\": \"These published pages carry a form. Their forms stop rendering and stop accepting submissions:\",\n \"none\": \"No published page on this site carries a form.\"\n }\n }\n },\n {\n \"id\": \"ai\",\n \"label\": \"AI\",\n \"alwaysOnForWorkspace\": true,\n \"description\": \"The assistant, generative building and automation, and the AI add-on.\",\n \"siteOff\": {\n \"stops\": \"Switching AI off for this site hides the assistant, Describe it, the AI cards and the editor’s AI controls on this site, refuses every AI request made for it, and stops its queued AI jobs without spending credits.\",\n \"keeps\": \"It does not stop the workspace’s AI add-on, credits, allotments or overage billing, and AI keeps working on the workspace’s other sites.\"\n }\n },\n {\n \"id\": \"accounts\",\n \"label\": \"User Accounts\",\n \"description\": \"Visitor accounts on the site: the /signin, /signup and /recover pages, and the Members blocks. Off for a site until you turn it on.\",\n \"releaseFlag\": \"release_member_accounts\",\n \"defaultOffPerSite\": true,\n \"requires\": [\n \"commerce\"\n ]\n },\n {\n \"id\": \"bookings\",\n \"label\": \"Bookings\",\n \"description\": \"Services, open slots, and paid bookings.\",\n \"releaseFlag\": \"release_bookings\"\n },\n {\n \"id\": \"commerce\",\n \"label\": \"Commerce\",\n \"description\": \"Products, carts, checkout, orders, POS.\",\n \"releaseFlag\": \"release_commerce_v2\"\n },\n {\n \"id\": \"marketplace\",\n \"label\": \"Marketplace\",\n \"description\": \"Marketplace listings, templates, and installs.\",\n \"releaseFlag\": \"release_marketplace\"\n },\n {\n \"id\": \"crm\",\n \"label\": \"CRM\",\n \"description\": \"Leads, contacts, companies, deals, tasks and reports.\",\n \"releaseFlag\": \"release_crm\"\n },\n {\n \"id\": \"outreach\",\n \"label\": \"Sequences\",\n \"description\": \"One-to-one email sequences sent from connected mailboxes.\",\n \"releaseFlag\": \"release_outreach\"\n },\n {\n \"id\": \"data\",\n \"label\": \"Data\",\n \"description\": \"Datasets, records, and CSV import/export.\",\n \"releaseFlag\": \"release_data_store\"\n },\n {\n \"id\": \"email\",\n \"label\": \"Email\",\n \"description\": \"Designed emails and campaign sending.\",\n \"releaseFlag\": \"release_email\"\n },\n {\n \"id\": \"events-calendar\",\n \"label\": \"Events Calendar\",\n \"description\": \"Event lists and calendars.\",\n \"releaseFlag\": \"release_events\"\n },\n {\n \"id\": \"inbox\",\n \"label\": \"Inbox\",\n \"description\": \"Form submissions and lead inbox.\",\n \"releaseFlag\": \"release_inbox\"\n },\n {\n \"id\": \"logic\",\n \"label\": \"Logic\",\n \"description\": \"Variables, functions, and reference health.\",\n \"releaseFlag\": \"release_logic\"\n },\n {\n \"id\": \"marketing\",\n \"label\": \"Marketing\",\n \"description\": \"Overlays, campaigns, and experiments.\",\n \"releaseFlag\": \"release_marketing\"\n },\n {\n \"id\": \"redirects\",\n \"label\": \"Redirects\",\n \"description\": \"URL redirect rules.\",\n \"releaseFlag\": \"release_redirects\"\n },\n {\n \"id\": \"workflows\",\n \"label\": \"Automation\",\n \"description\": \"Workflows, actions, webhooks, and run logs.\",\n \"releaseFlag\": \"release_workflows\"\n },\n]\n\nexport const PUBLISHED_SITE_IMPACT: Readonly<Record<string, PublishedSiteImpact>> = {\n \"mui\": \"elements\",\n \"forms\": \"elements\",\n \"ai\": \"console-only\",\n \"accounts\": \"routes\",\n \"bookings\": \"elements\",\n \"commerce\": \"elements\",\n \"marketplace\": \"console-only\",\n \"crm\": \"console-only\",\n \"outreach\": \"console-only\",\n \"data\": \"console-only\",\n \"email\": \"elements\",\n \"events-calendar\": \"elements\",\n \"inbox\": \"console-only\",\n \"logic\": \"console-only\",\n \"marketing\": \"elements\",\n \"redirects\": \"routes\",\n \"workflows\": \"routes\",\n}\n\n/**\n * The admin edit bar's quick links, in the order they are drawn — each\n * declared by the plugin whose console page it opens (AGL-3080).\n */\nexport const PLUGIN_EDIT_BAR_LINKS: readonly PluginEditBarLink[] = [\n {\n \"pluginId\": \"inbox\",\n \"order\": 20,\n \"label\": \"Inbox\",\n \"path\": \"/inbox\"\n },\n {\n \"pluginId\": \"commerce\",\n \"order\": 30,\n \"label\": \"Orders\",\n \"path\": \"/products/orders\"\n },\n]\n\n/**\n * Every host subcollection a first-party plugin owns, declared by that plugin\n * (AGL-3080). Core's readers ask this list; core names no collection.\n */\nexport const PLUGIN_HOST_COLLECTIONS_DECLARED: readonly ResolvedPluginHostCollection[] = [\n {\n \"pluginId\": \"forms\",\n \"name\": \"forms\",\n \"routeSlug\": \"forms\"\n },\n {\n \"pluginId\": \"bookings\",\n \"name\": \"services\",\n \"routeSlug\": \"bookings\"\n },\n {\n \"pluginId\": \"bookings\",\n \"name\": \"bookings\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Booking records — a customer, a time and a service pointer. The service holds the imagery and IS scanned; a booking is the transaction against it.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"products\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"productCategories\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"suppliers\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"locations\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"coupons\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"discounts\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"reviews\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"memberPosts\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"resources\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"settings\",\n \"label\": \"Store settings\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"siteMembers\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"orders\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Completed orders. Line items COPY a product's `imageUrl` at purchase time, so these would match — and matching would be the wrong answer: an order is an immutable record of what was sold, deleting the asset changes nothing about it, and no author can edit one. A busy store also holds more of these than the whole read budget.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"carts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Live and abandoned carts, with the same copied line-item image and the same reasoning, at higher volume — one document per shopper session.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"checkouts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"In-flight checkout sessions. Transient buyer state carrying the same line-item snapshot as `carts`.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"reservations\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"POS and booking holds. Short-lived transaction rows pointing at a resource that is itself scanned.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"stockHolds\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Inventory holds taken during checkout. Machine-written, short-lived, and a quantity rather than content.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"subscriptions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Site membership subscriptions: a plan pointer, a status and Stripe ids. Server-written from the billing webhook.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"registers\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"POS register allocations — a count against the register add-on, read by billing (AGL-1775). No content field at all.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"giftCards\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Gift card balances and redemption history. Money, not content.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"licenseKeys\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Digital-product license keys issued at fulfilment: a code, an order pointer and a revocation flag.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"inventoryAdjustments\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"The append-only stock adjustment ledger (AGL-2269). One row per manual stock edit and per cancellation release, unbounded over a store's life.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"inventoryReconciliation\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Reconciliation runs comparing counted stock against recorded stock. Machine-written totals.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"restockAlerts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Back-in-stock requests: an email address and a product pointer, written by visitors.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"stripeTaxRates\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Cached Stripe tax rate ids, written by the tax sync. Vendor ids.\"\n },\n {\n \"pluginId\": \"marketplace\",\n \"name\": \"installs\"\n },\n {\n \"pluginId\": \"crm\",\n \"name\": \"leads\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Captured leads, on the same footing as `formSubmissions`: visitor-submitted, unbounded, and never a place an author places an asset.\"\n },\n {\n \"pluginId\": \"email\",\n \"name\": \"suppressions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Unsubscribes, bounces and spam complaints. Email addresses and a reason.\"\n },\n {\n \"pluginId\": \"events-calendar\",\n \"name\": \"events\",\n \"routeSlug\": \"events\"\n },\n {\n \"pluginId\": \"inbox\",\n \"name\": \"formSubmissions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Visitor form submissions. Unbounded, PII-heavy, and a file attached to one is the visitor's upload — not a library asset an author picked, and not something deleting a library asset would break.\"\n },\n {\n \"pluginId\": \"logic\",\n \"name\": \"functions\",\n \"routeSlug\": \"logic\"\n },\n {\n \"pluginId\": \"logic\",\n \"name\": \"variables\",\n \"routeSlug\": \"logic\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"campaigns\",\n \"routeSlug\": \"marketing\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"experiments\",\n \"routeSlug\": \"marketing\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"overlays\",\n \"routeSlug\": \"marketing\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"emailCampaigns\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"The campaign CONTAINER — a name, a date window, the list ids it is aimed at and a topic. Distinct from `campaigns`, which holds the sends and IS scanned because a send carries the copy that went out. A container carries no copy and no asset reference: the design a send renders is a screen, and the screen is where the picker writes.\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"campaignAttributions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"One row per conversion — a form submission, a lead, a contact or a booking — recording which campaign the visitor arrived from. Written only by the Admin SDK, and the whole record is three sanitized UTM strings capped at a hundred characters: there is no field an asset could occupy and no surface that could pick one into it. Unbounded on the same footing as the conversions it credits.\"\n },\n {\n \"pluginId\": \"redirects\",\n \"name\": \"redirects\",\n \"routeSlug\": \"redirects\"\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"workflows\",\n \"routeSlug\": \"automation\"\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"webhooks\",\n \"routeSlug\": \"automation\"\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"actions\",\n \"routeSlug\": \"automation\"\n },\n]\n\n/**\n * Every org capacity a first-party plugin backs, declared by that plugin\n * (AGL-3080). Core owns the money; this says what is counted and what it is\n * called.\n */\nexport const PLUGIN_ORG_CAPACITIES_DECLARED: readonly ResolvedPluginOrgCapacity[] = [\n {\n \"pluginId\": \"data\",\n \"kind\": \"datasets\",\n \"order\": 30,\n \"collection\": \"datasets\",\n \"addonKind\": \"datasets\",\n \"includedEntitlement\": \"datasetsPerOrg\",\n \"nouns\": {\n \"one\": \"dataset\",\n \"many\": \"datasets\",\n \"addon\": \"extra datasets\"\n }\n },\n]\n"],"names":["FIRST_PARTY_PLUGINS","PUBLISHED_SITE_IMPACT","PLUGIN_EDIT_BAR_LINKS","PLUGIN_HOST_COLLECTIONS_DECLARED","PLUGIN_ORG_CAPACITIES_DECLARED"],"mappings":"AAAA;;;;;;;CAOC,GAMD,OAAO,MAAMA,sBAAmD;IAC9D;QACE,MAAM;QACN,SAAS;QACT,YAAY;QACZ,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,wBAAwB;QACxB,eAAe;QACf,WAAW;YACT,SAAS;YACT,SAAS;YACT,WAAW;YACX,SAAS;gBACP,WAAW;gBACX,QAAQ;YACV;QACF;IACF;IACA;QACE,MAAM;QACN,SAAS;QACT,wBAAwB;QACxB,eAAe;QACf,WAAW;YACT,SAAS;YACT,SAAS;QACX;IACF;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;QACf,qBAAqB;QACrB,YAAY;YACV;SACD;IACH;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;CACD,CAAA;AAED,OAAO,MAAMC,wBAAuE;IAClF,OAAO;IACP,SAAS;IACT,MAAM;IACN,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,eAAe;IACf,OAAO;IACP,YAAY;IACZ,QAAQ;IACR,S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"}
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/first-party-plugins.generated.ts"],"sourcesContent":["/**\n * GENERATED FILE — do not edit. Regenerate with:\n * node tools/scripts/generate-plugin-manifests.mjs\n *\n * The switchboard catalog (AGL-3080): one row per plugin and capability, each\n * declared by its own `catalog` block in plugins.config.json. The core holds\n * the types and the resolvers in `enabled-plugins.ts`; it holds no row.\n */\n\nimport type { FirstPartyPlugin, PluginEditBarLink, PublishedSiteImpact } from './enabled-plugins'\nimport type { ResolvedPluginHostCollection } from './plugin-host-collections'\nimport type { ResolvedPluginOrgCapacity } from './plugin-org-capacity'\n\nexport const FIRST_PARTY_PLUGINS: readonly FirstPartyPlugin[] = [\n {\n \"id\": \"mui\",\n \"label\": \"Components\",\n \"alwaysOn\": true,\n \"description\": \"The base component and theme library every site builds on.\"\n },\n {\n \"id\": \"forms\",\n \"label\": \"Forms\",\n \"alwaysOnForWorkspace\": true,\n \"description\": \"Forms on the site and the catalog that owns them.\",\n \"siteOff\": {\n \"stops\": \"Switching Forms off for this site stops forms rendering on its published pages, refuses every submission sent to it, and blocks publishing a form, or a page that carries one, until Forms is back on.\",\n \"keeps\": \"Submissions already received, the workspace’s form catalog and the CRM leads its forms created are kept, and forms keep working on the workspace’s other sites.\",\n \"confirm\": true,\n \"pages\": {\n \"heading\": \"These published pages carry a form. Their forms stop rendering and stop accepting submissions:\",\n \"none\": \"No published page on this site carries a form.\"\n }\n }\n },\n {\n \"id\": \"ai\",\n \"label\": \"AI\",\n \"alwaysOnForWorkspace\": true,\n \"description\": \"The assistant, generative building and automation, and the AI add-on.\",\n \"siteOff\": {\n \"stops\": \"Switching AI off for this site hides the assistant, Describe it, the AI cards and the editor’s AI controls on this site, refuses every AI request made for it, and stops its queued AI jobs without spending credits.\",\n \"keeps\": \"It does not stop the workspace’s AI add-on, credits, allotments or overage billing, and AI keeps working on the workspace’s other sites.\"\n }\n },\n {\n \"id\": \"accounts\",\n \"label\": \"User Accounts\",\n \"description\": \"Visitor accounts on the site: the /signin, /signup and /recover pages, and the Members blocks. Off for a site until you turn it on.\",\n \"releaseFlag\": \"release_member_accounts\",\n \"defaultOffPerSite\": true,\n \"requires\": [\n \"commerce\"\n ]\n },\n {\n \"id\": \"bookings\",\n \"label\": \"Bookings\",\n \"description\": \"Services, open slots, and paid bookings.\",\n \"releaseFlag\": \"release_bookings\"\n },\n {\n \"id\": \"commerce\",\n \"label\": \"Commerce\",\n \"description\": \"Products, carts, checkout, orders, POS.\",\n \"releaseFlag\": \"release_commerce_v2\"\n },\n {\n \"id\": \"marketplace\",\n \"label\": \"Marketplace\",\n \"description\": \"Marketplace listings, templates, and installs.\",\n \"releaseFlag\": \"release_marketplace\"\n },\n {\n \"id\": \"crm\",\n \"label\": \"CRM\",\n \"description\": \"Leads, contacts, companies, deals, tasks and reports.\",\n \"releaseFlag\": \"release_crm\"\n },\n {\n \"id\": \"outreach\",\n \"label\": \"Sequences\",\n \"description\": \"One-to-one email sequences sent from connected mailboxes.\",\n \"releaseFlag\": \"release_outreach\"\n },\n {\n \"id\": \"data\",\n \"label\": \"Data\",\n \"description\": \"Datasets, records, and CSV import/export.\",\n \"releaseFlag\": \"release_data_store\"\n },\n {\n \"id\": \"email\",\n \"label\": \"Email\",\n \"description\": \"Designed emails and campaign sending.\",\n \"releaseFlag\": \"release_email\"\n },\n {\n \"id\": \"events-calendar\",\n \"label\": \"Events Calendar\",\n \"description\": \"Event lists and calendars.\",\n \"releaseFlag\": \"release_events\"\n },\n {\n \"id\": \"inbox\",\n \"label\": \"Inbox\",\n \"description\": \"Form submissions and lead inbox.\",\n \"releaseFlag\": \"release_inbox\"\n },\n {\n \"id\": \"logic\",\n \"label\": \"Logic\",\n \"description\": \"Variables, functions, and reference health.\",\n \"releaseFlag\": \"release_logic\"\n },\n {\n \"id\": \"marketing\",\n \"label\": \"Marketing\",\n \"description\": \"Overlays, campaigns, and experiments.\",\n \"releaseFlag\": \"release_marketing\"\n },\n {\n \"id\": \"redirects\",\n \"label\": \"Redirects\",\n \"description\": \"URL redirect rules.\",\n \"releaseFlag\": \"release_redirects\"\n },\n {\n \"id\": \"workflows\",\n \"label\": \"Automation\",\n \"description\": \"Workflows, actions, webhooks, and run logs.\",\n \"releaseFlag\": \"release_workflows\"\n },\n]\n\nexport const PUBLISHED_SITE_IMPACT: Readonly<Record<string, PublishedSiteImpact>> = {\n \"mui\": \"elements\",\n \"forms\": \"elements\",\n \"ai\": \"console-only\",\n \"accounts\": \"routes\",\n \"bookings\": \"elements\",\n \"commerce\": \"elements\",\n \"marketplace\": \"console-only\",\n \"crm\": \"console-only\",\n \"outreach\": \"console-only\",\n \"data\": \"console-only\",\n \"email\": \"elements\",\n \"events-calendar\": \"elements\",\n \"inbox\": \"console-only\",\n \"logic\": \"console-only\",\n \"marketing\": \"elements\",\n \"redirects\": \"routes\",\n \"workflows\": \"routes\",\n}\n\n/**\n * The admin edit bar's quick links, in the order they are drawn — each\n * declared by the plugin whose console page it opens (AGL-3080).\n */\nexport const PLUGIN_EDIT_BAR_LINKS: readonly PluginEditBarLink[] = [\n {\n \"pluginId\": \"inbox\",\n \"order\": 20,\n \"label\": \"Inbox\",\n \"path\": \"/inbox\"\n },\n {\n \"pluginId\": \"commerce\",\n \"order\": 30,\n \"label\": \"Orders\",\n \"path\": \"/products/orders\"\n },\n]\n\n/**\n * Every host subcollection a first-party plugin owns, declared by that plugin\n * (AGL-3080). Core's readers ask this list; core names no collection.\n */\nexport const PLUGIN_HOST_COLLECTIONS_DECLARED: readonly ResolvedPluginHostCollection[] = [\n {\n \"pluginId\": \"forms\",\n \"name\": \"forms\",\n \"routeSlug\": \"forms\"\n },\n {\n \"pluginId\": \"bookings\",\n \"name\": \"services\",\n \"routeSlug\": \"bookings\"\n },\n {\n \"pluginId\": \"bookings\",\n \"name\": \"bookings\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Booking records — a customer, a time and a service pointer. The service holds the imagery and IS scanned; a booking is the transaction against it.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"products\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"productCategories\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"suppliers\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"locations\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"coupons\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"discounts\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"reviews\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"memberPosts\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"resources\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"settings\",\n \"label\": \"Store settings\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"siteMembers\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"orders\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Completed orders. Line items COPY a product's `imageUrl` at purchase time, so these would match — and matching would be the wrong answer: an order is an immutable record of what was sold, deleting the asset changes nothing about it, and no author can edit one. A busy store also holds more of these than the whole read budget.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"carts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Live and abandoned carts, with the same copied line-item image and the same reasoning, at higher volume — one document per shopper session.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"checkouts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"In-flight checkout sessions. Transient buyer state carrying the same line-item snapshot as `carts`.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"reservations\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"POS and booking holds. Short-lived transaction rows pointing at a resource that is itself scanned.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"stockHolds\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Inventory holds taken during checkout. Machine-written, short-lived, and a quantity rather than content.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"subscriptions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Site membership subscriptions: a plan pointer, a status and Stripe ids. Server-written from the billing webhook.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"registers\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"POS register allocations — a count against the register add-on, read by billing (AGL-1775). No content field at all.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"giftCards\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Gift card balances and redemption history. Money, not content.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"licenseKeys\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Digital-product license keys issued at fulfilment: a code, an order pointer and a revocation flag.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"inventoryAdjustments\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"The append-only stock adjustment ledger (AGL-2269). One row per manual stock edit and per cancellation release, unbounded over a store's life.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"inventoryReconciliation\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Reconciliation runs comparing counted stock against recorded stock. Machine-written totals.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"restockAlerts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Back-in-stock requests: an email address and a product pointer, written by visitors.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"stripeTaxRates\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Cached Stripe tax rate ids, written by the tax sync. Vendor ids.\"\n },\n {\n \"pluginId\": \"marketplace\",\n \"name\": \"installs\"\n },\n {\n \"pluginId\": \"crm\",\n \"name\": \"leads\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Captured leads, on the same footing as `formSubmissions`: visitor-submitted, unbounded, and never a place an author places an asset.\"\n },\n {\n \"pluginId\": \"email\",\n \"name\": \"suppressions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Unsubscribes, bounces and spam complaints. Email addresses and a reason.\"\n },\n {\n \"pluginId\": \"events-calendar\",\n \"name\": \"events\",\n \"routeSlug\": \"events\"\n },\n {\n \"pluginId\": \"inbox\",\n \"name\": \"formSubmissions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Visitor form submissions. Unbounded, PII-heavy, and a file attached to one is the visitor's upload — not a library asset an author picked, and not something deleting a library asset would break.\"\n },\n {\n \"pluginId\": \"logic\",\n \"name\": \"functions\",\n \"routeSlug\": \"logic\"\n },\n {\n \"pluginId\": \"logic\",\n \"name\": \"variables\",\n \"routeSlug\": \"logic\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"campaigns\",\n \"routeSlug\": \"marketing\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"experiments\",\n \"routeSlug\": \"marketing\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"overlays\",\n \"routeSlug\": \"marketing\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"emailCampaigns\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"The campaign CONTAINER — a name, a date window, the list ids it is aimed at and a topic. Distinct from `campaigns`, which holds the sends and IS scanned because a send carries the copy that went out. A container carries no copy and no asset reference: the design a send renders is a screen, and the screen is where the picker writes.\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"campaignAttributions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"One row per conversion — a form submission, a lead, a contact or a booking — recording which campaign the visitor arrived from. Written only by the Admin SDK, and the whole record is three sanitized UTM strings capped at a hundred characters: there is no field an asset could occupy and no surface that could pick one into it. Unbounded on the same footing as the conversions it credits.\"\n },\n {\n \"pluginId\": \"redirects\",\n \"name\": \"redirects\",\n \"routeSlug\": \"redirects\"\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"workflows\",\n \"routeSlug\": \"automation\"\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"webhooks\",\n \"routeSlug\": \"automation\"\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"actions\",\n \"routeSlug\": \"automation\"\n },\n]\n\n/**\n * Every org capacity a first-party plugin backs, declared by that plugin\n * (AGL-3080). Core owns the money; this says what is counted and what it is\n * called.\n */\nexport const PLUGIN_ORG_CAPACITIES_DECLARED: readonly ResolvedPluginOrgCapacity[] = [\n {\n \"pluginId\": \"data\",\n \"kind\": \"datasets\",\n \"order\": 30,\n \"collection\": \"datasets\",\n \"addonKind\": \"datasets\",\n \"includedEntitlement\": \"datasetsPerOrg\",\n \"purchaseCeilingEntitlement\": \"maxDatasetsPerOrg\",\n \"nouns\": {\n \"one\": \"dataset\",\n \"many\": \"datasets\",\n \"addon\": \"extra datasets\"\n }\n },\n]\n"],"names":["FIRST_PARTY_PLUGINS","PUBLISHED_SITE_IMPACT","PLUGIN_EDIT_BAR_LINKS","PLUGIN_HOST_COLLECTIONS_DECLARED","PLUGIN_ORG_CAPACITIES_DECLARED"],"mappings":"AAAA;;;;;;;CAOC,GAMD,OAAO,MAAMA,sBAAmD;IAC9D;QACE,MAAM;QACN,SAAS;QACT,YAAY;QACZ,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,wBAAwB;QACxB,eAAe;QACf,WAAW;YACT,SAAS;YACT,SAAS;YACT,WAAW;YACX,SAAS;gBACP,WAAW;gBACX,QAAQ;YACV;QACF;IACF;IACA;QACE,MAAM;QACN,SAAS;QACT,wBAAwB;QACxB,eAAe;QACf,WAAW;YACT,SAAS;YACT,SAAS;QACX;IACF;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;QACf,qBAAqB;QACrB,YAAY;YACV;SACD;IACH;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;CACD,CAAA;AAED,OAAO,MAAMC,wBAAuE;IAClF,OAAO;IACP,SAAS;IACT,MAAM;IACN,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,eAAe;IACf,OAAO;IACP,YAAY;IACZ,QAAQ;IACR,S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"}
@@ -0,0 +1,145 @@
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
+ /** A verdict written back onto a stored version by the re-verifier. */
18
+ export interface PluginArtifactVerdict {
19
+ ok: boolean;
20
+ problems: unknown[];
21
+ checks: unknown;
22
+ /** The exact bytes the verdict was computed over. */
23
+ sha256: string;
24
+ verifierVersion: number;
25
+ }
26
+ /** What keeps one object in the bucket alive. */
27
+ export interface PluginArtifactClaim {
28
+ /** The object path's first segment — the owning record's id. */
29
+ listingId: string;
30
+ /** The version string, the object path's second segment. */
31
+ version: string;
32
+ /** The exact bytes claimed, the object path's third segment. */
33
+ sha256: string;
34
+ /**
35
+ * Whether the owning record still exists.
36
+ *
37
+ * FALSE is reported and never reaped: the platform does not cascade a
38
+ * delete into subcollections and an install resolves a version by path, so
39
+ * the bytes of a hard-deleted record are still being loaded by somebody.
40
+ */
41
+ ownerLive: boolean;
42
+ }
43
+ /** A claim, plus everything the re-verifier needs to judge the bytes. */
44
+ export interface PluginArtifactVersion extends PluginArtifactClaim {
45
+ /** A name for the run's report; falls back to the id. */
46
+ ownerName: string;
47
+ /** The owner's review state as the report prints it, or `'unknown'`. */
48
+ reviewStatus: string;
49
+ /** How many installs are on this version, for the regression report. */
50
+ activeInstalls: number;
51
+ /** Where a human opens this version, or `''` when there is no page. */
52
+ reviewLink: string;
53
+ /** The cached verdict, or `undefined` when nothing has checked these bytes. */
54
+ storedVerdict?: unknown;
55
+ /** Origins the version's manifest declares it will reach. */
56
+ declaredNetwork: readonly string[];
57
+ /** What the manifest says it contributes, or `null` when it says nothing. */
58
+ declaredContributions: unknown;
59
+ /**
60
+ * Caches a fresh verdict on THIS version.
61
+ *
62
+ * A method on the row rather than a lookup on the source, because the row
63
+ * is where the plugin already holds the document it read — asking it to
64
+ * find the document again by id would be a second query per version, and
65
+ * a version's document id and its `version` field are not guaranteed to be
66
+ * the same string, so the second lookup could write to a sibling document
67
+ * that nothing reads.
68
+ *
69
+ * MAY REJECT, and the caller treats that as a cache miss. The verdict is a
70
+ * cache; the report a person reads has already been computed, and a sweep
71
+ * that stopped at the first write failure would leave the rest of the
72
+ * platform unchecked over one.
73
+ */
74
+ record(verdict: PluginArtifactVerdict): Promise<void>;
75
+ }
76
+ /**
77
+ * The shape both listings answer with: trusted rows, or a refusal.
78
+ *
79
+ * ⛔ THE DISCRIMINANT IS A STRING, AND IT HAS TO BE. This repo compiles with
80
+ * `strictNullChecks: false` (tsconfig.base.json), and TypeScript does not
81
+ * narrow a BOOLEAN-literal discriminant under it — `if (!answer.complete)`
82
+ * compiles to no narrowing at all, so `answer.reason` is an error and, worse,
83
+ * `answer.rows` stays readable on the refusal branch. That is precisely the
84
+ * misread this contract exists to make impossible, so the flag that carries
85
+ * it is a word.
86
+ */
87
+ export type PluginArtifactListing<T> = {
88
+ outcome: 'listed';
89
+ rows: readonly T[];
90
+ /** Documents read, for the run's report. */
91
+ scanned: number;
92
+ } | {
93
+ outcome: 'refused';
94
+ /** Why the answer cannot be trusted, in the words the run prints. */
95
+ reason: string;
96
+ /** How far the walk got before it stopped. */
97
+ scanned: number;
98
+ };
99
+ export interface PluginArtifactInventorySource {
100
+ /**
101
+ * Every claim on the bucket, completely or not at all.
102
+ *
103
+ * Separate from {@link listVersions} so the reaper can read the two path
104
+ * segments and the hash and leave the manifests on the server. It does not
105
+ * change what is BILLED — storage charges per document either way — but a
106
+ * version document carries its whole manifest, and a weekly sweep of every
107
+ * version on the platform should not drag all of them across the wire.
108
+ *
109
+ * `maxScanned` is the CALLER's refusal threshold, not the walk's page
110
+ * size: past it the answer must be `refused`, because a claim set this run
111
+ * could not finish reading cannot be reaped against.
112
+ */
113
+ listClaims(options: {
114
+ maxScanned: number;
115
+ }): Promise<PluginArtifactListing<PluginArtifactClaim>>;
116
+ /** Every stored version with what a re-verification needs to judge it. */
117
+ listVersions(options: {
118
+ maxScanned: number;
119
+ }): Promise<PluginArtifactListing<PluginArtifactVersion>>;
120
+ }
121
+ /**
122
+ * One implementation. Two would each answer about their own storage and the
123
+ * reaper would delete what the other one claims — the exact mistake the
124
+ * refusal shape exists to prevent, arriving by a different door.
125
+ */
126
+ export declare const PLUGIN_ARTIFACT_INVENTORY: import("./plugin-services").PluginServiceContract<PluginArtifactInventorySource>;
127
+ /** Installs the owner of the artifacts bucket's documents. */
128
+ export declare function registerPluginArtifactInventory(source: PluginArtifactInventorySource, options?: {
129
+ pluginId?: string;
130
+ }): void;
131
+ /** Whether anything owns the artifacts bucket on this deployment. */
132
+ export declare function hasPluginArtifactInventory(): boolean;
133
+ /**
134
+ * Every claim on the bucket, or why the answer cannot be trusted.
135
+ *
136
+ * NEVER THROWS and never answers an empty list that means "could not read" —
137
+ * see the module docblock for what an empty list would cost.
138
+ */
139
+ export declare function pluginArtifactClaims(options: {
140
+ maxScanned: number;
141
+ }): Promise<PluginArtifactListing<PluginArtifactClaim>>;
142
+ /** Every stored version with what a re-verification needs to judge it. */
143
+ export declare function pluginArtifactVersions(options: {
144
+ maxScanned: number;
145
+ }): Promise<PluginArtifactListing<PluginArtifactVersion>>;
@@ -0,0 +1,126 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ /**
18
+ * WHO CLAIMS THE BYTES IN THE ARTIFACTS BUCKET (AGL-3080).
19
+ *
20
+ * Two scheduled jobs sweep the plugin-artifacts bucket. The reaper deletes
21
+ * every object no stored version claims; the re-verifier re-runs the static
22
+ * checker over the bytes and writes each verdict back. Both are the
23
+ * PLATFORM's jobs — the bucket is platform infrastructure, the object path
24
+ * is the loader's convention, the verifier is the trust lint, and the cron
25
+ * that fires them is the console's. Both also had to read
26
+ * `pluginVersions` and `marketplaceListings` to do it, which is a plugin's
27
+ * storage reached around the plugin, from an `/api/admin` route.
28
+ *
29
+ * So the plugin answers WHAT IT STORES and the console decides what to do
30
+ * about it. The sibling of `core.site-cache` with the direction reversed:
31
+ * there the shell offers a capability down, here the owner of the documents
32
+ * answers a question the shell cannot answer for itself.
33
+ *
34
+ * ## ⛔ AN ABSENT OR PARTIAL INVENTORY REFUSES THE RUN
35
+ *
36
+ * Decide the failure direction first — {@link PLUGIN_ARTIFACT_INVENTORY} and
37
+ * `core.site-cache` look alike and fail opposite ways.
38
+ *
39
+ * Every object the reaper deletes is deleted precisely because nothing
40
+ * claimed it, the bucket has no object versioning, and a claim that was
41
+ * never read looks exactly like a claim that does not exist. An empty answer
42
+ * is therefore the most dangerous answer this contract can give: read as
43
+ * "nothing is claimed", it empties the bucket permanently.
44
+ *
45
+ * {@link pluginArtifactClaims} can never hand back an empty list that means
46
+ * "could not read". It answers a discriminated result — a caller reading
47
+ * `rows` on a refusal does not compile, which is the point — and nothing
48
+ * registered, a throw, and a walk that hit the caller's own ceiling all
49
+ * arrive as `outcome: 'refused'` with a sentence the run prints.
50
+ *
51
+ * ## `listingId`, and why the word is not minted fresh here
52
+ *
53
+ * The bucket's object path is `artifacts/{listingId}/{version}/{sha}.bundle`
54
+ * and both the serving route and `planArtifactReap` already read it that
55
+ * way. A second vocabulary for the same segment is the defect `e32405cb5`
56
+ * removed from the capacity gates — two names for one thing, kept agreeing
57
+ * by hand — so this contract uses the path's word. A future plugin that
58
+ * stores artifacts inherits a noun that is not about it; renaming the
59
+ * segment everywhere is the honest fix, and it is not this change.
60
+ */ import { definePluginServiceContract, registerPluginService, resolvePluginService } from "./plugin-services.js";
61
+ /**
62
+ * One implementation. Two would each answer about their own storage and the
63
+ * reaper would delete what the other one claims — the exact mistake the
64
+ * refusal shape exists to prevent, arriving by a different door.
65
+ */ export const PLUGIN_ARTIFACT_INVENTORY = definePluginServiceContract('core.plugin-artifact-inventory', {
66
+ multiple: false
67
+ });
68
+ /** Installs the owner of the artifacts bucket's documents. */ export function registerPluginArtifactInventory(source, options) {
69
+ if (typeof (source == null ? void 0 : source.listClaims) !== 'function' || typeof (source == null ? void 0 : source.listVersions) !== 'function') {
70
+ throw new Error('a plugin artifact inventory needs listClaims and listVersions ' + 'functions');
71
+ }
72
+ registerPluginService(PLUGIN_ARTIFACT_INVENTORY, source, _extends({}, (options == null ? void 0 : options.pluginId) ? {
73
+ pluginId: options.pluginId
74
+ } : {}));
75
+ }
76
+ /** Whether anything owns the artifacts bucket on this deployment. */ export function hasPluginArtifactInventory() {
77
+ return Boolean(resolvePluginService(PLUGIN_ARTIFACT_INVENTORY));
78
+ }
79
+ /** The refusal both readers answer with when nothing owns the bucket. */ function unowned() {
80
+ console.error('[artifact-inventory] nothing owns the artifacts bucket, so no run may ' + 'conclude that an object is unclaimed. The owning plugin registers ' + 'this on the consoleApi surface.');
81
+ return {
82
+ outcome: 'refused',
83
+ reason: 'No plugin owns the stored artifacts on this deployment, so nothing ' + 'can say which objects are still claimed.',
84
+ scanned: 0
85
+ };
86
+ }
87
+ /** Guards one listing's answer. Never throws; never invents rows. */ async function trustedListing(read) {
88
+ try {
89
+ const result = await read();
90
+ // A source that answered `listed` with no rows is a bug in the source,
91
+ // and reaping on it would delete every object in the bucket. Refusing
92
+ // costs a week; the alternative cannot be undone.
93
+ if (result.outcome === 'listed' && !Array.isArray(result.rows)) {
94
+ return {
95
+ outcome: 'refused',
96
+ reason: 'The artifact inventory returned no rows.',
97
+ scanned: 0
98
+ };
99
+ }
100
+ return result;
101
+ } catch (error) {
102
+ console.error('[artifact-inventory] listing failed', error);
103
+ return {
104
+ outcome: 'refused',
105
+ reason: 'The artifact inventory could not be read.',
106
+ scanned: 0
107
+ };
108
+ }
109
+ }
110
+ /**
111
+ * Every claim on the bucket, or why the answer cannot be trusted.
112
+ *
113
+ * NEVER THROWS and never answers an empty list that means "could not read" —
114
+ * see the module docblock for what an empty list would cost.
115
+ */ export async function pluginArtifactClaims(options) {
116
+ const source = resolvePluginService(PLUGIN_ARTIFACT_INVENTORY);
117
+ if (!source) return unowned();
118
+ return trustedListing(()=>source.listClaims(options));
119
+ }
120
+ /** Every stored version with what a re-verification needs to judge it. */ export async function pluginArtifactVersions(options) {
121
+ const source = resolvePluginService(PLUGIN_ARTIFACT_INVENTORY);
122
+ if (!source) return unowned();
123
+ return trustedListing(()=>source.listVersions(options));
124
+ }
125
+
126
+ //# sourceMappingURL=plugin-artifact-inventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-artifact-inventory.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 * WHO CLAIMS THE BYTES IN THE ARTIFACTS BUCKET (AGL-3080).\n *\n * Two scheduled jobs sweep the plugin-artifacts bucket. The reaper deletes\n * every object no stored version claims; the re-verifier re-runs the static\n * checker over the bytes and writes each verdict back. Both are the\n * PLATFORM's jobs — the bucket is platform infrastructure, the object path\n * is the loader's convention, the verifier is the trust lint, and the cron\n * that fires them is the console's. Both also had to read\n * `pluginVersions` and `marketplaceListings` to do it, which is a plugin's\n * storage reached around the plugin, from an `/api/admin` route.\n *\n * So the plugin answers WHAT IT STORES and the console decides what to do\n * about it. The sibling of `core.site-cache` with the direction reversed:\n * there the shell offers a capability down, here the owner of the documents\n * answers a question the shell cannot answer for itself.\n *\n * ## ⛔ AN ABSENT OR PARTIAL INVENTORY REFUSES THE RUN\n *\n * Decide the failure direction first — {@link PLUGIN_ARTIFACT_INVENTORY} and\n * `core.site-cache` look alike and fail opposite ways.\n *\n * Every object the reaper deletes is deleted precisely because nothing\n * claimed it, the bucket has no object versioning, and a claim that was\n * never read looks exactly like a claim that does not exist. An empty answer\n * is therefore the most dangerous answer this contract can give: read as\n * \"nothing is claimed\", it empties the bucket permanently.\n *\n * {@link pluginArtifactClaims} can never hand back an empty list that means\n * \"could not read\". It answers a discriminated result — a caller reading\n * `rows` on a refusal does not compile, which is the point — and nothing\n * registered, a throw, and a walk that hit the caller's own ceiling all\n * arrive as `outcome: 'refused'` with a sentence the run prints.\n *\n * ## `listingId`, and why the word is not minted fresh here\n *\n * The bucket's object path is `artifacts/{listingId}/{version}/{sha}.bundle`\n * and both the serving route and `planArtifactReap` already read it that\n * way. A second vocabulary for the same segment is the defect `e32405cb5`\n * removed from the capacity gates — two names for one thing, kept agreeing\n * by hand — so this contract uses the path's word. A future plugin that\n * stores artifacts inherits a noun that is not about it; renaming the\n * segment everywhere is the honest fix, and it is not this change.\n */\n\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginService,\n} from './plugin-services'\n\n/** A verdict written back onto a stored version by the re-verifier. */\nexport interface PluginArtifactVerdict {\n ok: boolean\n problems: unknown[]\n checks: unknown\n /** The exact bytes the verdict was computed over. */\n sha256: string\n verifierVersion: number\n}\n\n/** What keeps one object in the bucket alive. */\nexport interface PluginArtifactClaim {\n /** The object path's first segment — the owning record's id. */\n listingId: string\n /** The version string, the object path's second segment. */\n version: string\n /** The exact bytes claimed, the object path's third segment. */\n sha256: string\n /**\n * Whether the owning record still exists.\n *\n * FALSE is reported and never reaped: the platform does not cascade a\n * delete into subcollections and an install resolves a version by path, so\n * the bytes of a hard-deleted record are still being loaded by somebody.\n */\n ownerLive: boolean\n}\n\n/** A claim, plus everything the re-verifier needs to judge the bytes. */\nexport interface PluginArtifactVersion extends PluginArtifactClaim {\n /** A name for the run's report; falls back to the id. */\n ownerName: string\n /** The owner's review state as the report prints it, or `'unknown'`. */\n reviewStatus: string\n /** How many installs are on this version, for the regression report. */\n activeInstalls: number\n /** Where a human opens this version, or `''` when there is no page. */\n reviewLink: string\n /** The cached verdict, or `undefined` when nothing has checked these bytes. */\n storedVerdict?: unknown\n /** Origins the version's manifest declares it will reach. */\n declaredNetwork: readonly string[]\n /** What the manifest says it contributes, or `null` when it says nothing. */\n declaredContributions: unknown\n /**\n * Caches a fresh verdict on THIS version.\n *\n * A method on the row rather than a lookup on the source, because the row\n * is where the plugin already holds the document it read — asking it to\n * find the document again by id would be a second query per version, and\n * a version's document id and its `version` field are not guaranteed to be\n * the same string, so the second lookup could write to a sibling document\n * that nothing reads.\n *\n * MAY REJECT, and the caller treats that as a cache miss. The verdict is a\n * cache; the report a person reads has already been computed, and a sweep\n * that stopped at the first write failure would leave the rest of the\n * platform unchecked over one.\n */\n record(verdict: PluginArtifactVerdict): Promise<void>\n}\n\n/**\n * The shape both listings answer with: trusted rows, or a refusal.\n *\n * ⛔ THE DISCRIMINANT IS A STRING, AND IT HAS TO BE. This repo compiles with\n * `strictNullChecks: false` (tsconfig.base.json), and TypeScript does not\n * narrow a BOOLEAN-literal discriminant under it — `if (!answer.complete)`\n * compiles to no narrowing at all, so `answer.reason` is an error and, worse,\n * `answer.rows` stays readable on the refusal branch. That is precisely the\n * misread this contract exists to make impossible, so the flag that carries\n * it is a word.\n */\nexport type PluginArtifactListing<T> =\n | {\n outcome: 'listed'\n rows: readonly T[]\n /** Documents read, for the run's report. */\n scanned: number\n }\n | {\n outcome: 'refused'\n /** Why the answer cannot be trusted, in the words the run prints. */\n reason: string\n /** How far the walk got before it stopped. */\n scanned: number\n }\n\nexport interface PluginArtifactInventorySource {\n /**\n * Every claim on the bucket, completely or not at all.\n *\n * Separate from {@link listVersions} so the reaper can read the two path\n * segments and the hash and leave the manifests on the server. It does not\n * change what is BILLED — storage charges per document either way — but a\n * version document carries its whole manifest, and a weekly sweep of every\n * version on the platform should not drag all of them across the wire.\n *\n * `maxScanned` is the CALLER's refusal threshold, not the walk's page\n * size: past it the answer must be `refused`, because a claim set this run\n * could not finish reading cannot be reaped against.\n */\n listClaims(options: {\n maxScanned: number\n }): Promise<PluginArtifactListing<PluginArtifactClaim>>\n /** Every stored version with what a re-verification needs to judge it. */\n listVersions(options: {\n maxScanned: number\n }): Promise<PluginArtifactListing<PluginArtifactVersion>>\n}\n\n/**\n * One implementation. Two would each answer about their own storage and the\n * reaper would delete what the other one claims — the exact mistake the\n * refusal shape exists to prevent, arriving by a different door.\n */\nexport const PLUGIN_ARTIFACT_INVENTORY =\n definePluginServiceContract<PluginArtifactInventorySource>(\n 'core.plugin-artifact-inventory',\n { multiple: false },\n )\n\n/** Installs the owner of the artifacts bucket's documents. */\nexport function registerPluginArtifactInventory(\n source: PluginArtifactInventorySource,\n options?: { pluginId?: string },\n): void {\n if (\n typeof source?.listClaims !== 'function' ||\n typeof source?.listVersions !== 'function'\n ) {\n throw new Error(\n 'a plugin artifact inventory needs listClaims and listVersions ' +\n 'functions',\n )\n }\n registerPluginService(PLUGIN_ARTIFACT_INVENTORY, source, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n })\n}\n\n/** Whether anything owns the artifacts bucket on this deployment. */\nexport function hasPluginArtifactInventory(): boolean {\n return Boolean(resolvePluginService(PLUGIN_ARTIFACT_INVENTORY))\n}\n\n/** The refusal both readers answer with when nothing owns the bucket. */\nfunction unowned(): PluginArtifactListing<never> {\n console.error(\n '[artifact-inventory] nothing owns the artifacts bucket, so no run may ' +\n 'conclude that an object is unclaimed. The owning plugin registers ' +\n 'this on the consoleApi surface.',\n )\n return {\n outcome: 'refused',\n reason:\n 'No plugin owns the stored artifacts on this deployment, so nothing ' +\n 'can say which objects are still claimed.',\n scanned: 0,\n }\n}\n\n/** Guards one listing's answer. Never throws; never invents rows. */\nasync function trustedListing<T>(\n read: () => Promise<PluginArtifactListing<T>>,\n): Promise<PluginArtifactListing<T>> {\n try {\n const result = await read()\n // A source that answered `listed` with no rows is a bug in the source,\n // and reaping on it would delete every object in the bucket. Refusing\n // costs a week; the alternative cannot be undone.\n if (result.outcome === 'listed' && !Array.isArray(result.rows)) {\n return {\n outcome: 'refused',\n reason: 'The artifact inventory returned no rows.',\n scanned: 0,\n }\n }\n return result\n } catch (error) {\n console.error('[artifact-inventory] listing failed', error)\n return {\n outcome: 'refused',\n reason: 'The artifact inventory could not be read.',\n scanned: 0,\n }\n }\n}\n\n/**\n * Every claim on the bucket, or why the answer cannot be trusted.\n *\n * NEVER THROWS and never answers an empty list that means \"could not read\" —\n * see the module docblock for what an empty list would cost.\n */\nexport async function pluginArtifactClaims(options: {\n maxScanned: number\n}): Promise<PluginArtifactListing<PluginArtifactClaim>> {\n const source = resolvePluginService(PLUGIN_ARTIFACT_INVENTORY)\n if (!source) return unowned()\n return trustedListing(() => source.listClaims(options))\n}\n\n/** Every stored version with what a re-verification needs to judge it. */\nexport async function pluginArtifactVersions(options: {\n maxScanned: number\n}): Promise<PluginArtifactListing<PluginArtifactVersion>> {\n const source = resolvePluginService(PLUGIN_ARTIFACT_INVENTORY)\n if (!source) return unowned()\n return trustedListing(() => source.listVersions(options))\n}\n"],"names":["definePluginServiceContract","registerPluginService","resolvePluginService","PLUGIN_ARTIFACT_INVENTORY","multiple","registerPluginArtifactInventory","source","options","listClaims","listVersions","Error","pluginId","hasPluginArtifactInventory","Boolean","unowned","console","error","outcome","reason","scanned","trustedListing","read","result","Array","isArray","rows","pluginArtifactClaims","pluginArtifactVersions"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CC,GAED,SACEA,2BAA2B,EAC3BC,qBAAqB,EACrBC,oBAAoB,QACf,uBAAmB;AAiH1B;;;;CAIC,GACD,OAAO,MAAMC,4BACXH,4BACE,kCACA;IAAEI,UAAU;AAAM,GACnB;AAEH,4DAA4D,GAC5D,OAAO,SAASC,gCACdC,MAAqC,EACrCC,OAA+B;IAE/B,IACE,QAAOD,0BAAAA,OAAQE,UAAU,MAAK,cAC9B,QAAOF,0BAAAA,OAAQG,YAAY,MAAK,YAChC;QACA,MAAM,IAAIC,MACR,mEACE;IAEN;IACAT,sBAAsBE,2BAA2BG,QAAQ,aACnDC,CAAAA,2BAAAA,QAASI,QAAQ,IAAG;QAAEA,UAAUJ,QAAQI,QAAQ;IAAC,IAAI,CAAC;AAE9D;AAEA,mEAAmE,GACnE,OAAO,SAASC;IACd,OAAOC,QAAQX,qBAAqBC;AACtC;AAEA,uEAAuE,GACvE,SAASW;IACPC,QAAQC,KAAK,CACX,2EACE,uEACA;IAEJ,OAAO;QACLC,SAAS;QACTC,QACE,wEACA;QACFC,SAAS;IACX;AACF;AAEA,mEAAmE,GACnE,eAAeC,eACbC,IAA6C;IAE7C,IAAI;QACF,MAAMC,SAAS,MAAMD;QACrB,uEAAuE;QACvE,sEAAsE;QACtE,kDAAkD;QAClD,IAAIC,OAAOL,OAAO,KAAK,YAAY,CAACM,MAAMC,OAAO,CAACF,OAAOG,IAAI,GAAG;YAC9D,OAAO;gBACLR,SAAS;gBACTC,QAAQ;gBACRC,SAAS;YACX;QACF;QACA,OAAOG;IACT,EAAE,OAAON,OAAO;QACdD,QAAQC,KAAK,CAAC,uCAAuCA;QACrD,OAAO;YACLC,SAAS;YACTC,QAAQ;YACRC,SAAS;QACX;IACF;AACF;AAEA;;;;;CAKC,GACD,OAAO,eAAeO,qBAAqBnB,OAE1C;IACC,MAAMD,SAASJ,qBAAqBC;IACpC,IAAI,CAACG,QAAQ,OAAOQ;IACpB,OAAOM,eAAe,IAAMd,OAAOE,UAAU,CAACD;AAChD;AAEA,wEAAwE,GACxE,OAAO,eAAeoB,uBAAuBpB,OAE5C;IACC,MAAMD,SAASJ,qBAAqBC;IACpC,IAAI,CAACG,QAAQ,OAAOQ;IACpB,OAAOM,eAAe,IAAMd,OAAOG,YAAY,CAACF;AAClD"}
@@ -124,6 +124,23 @@ export interface PluginContactCaptureRequest {
124
124
  * contact form is still a customer.
125
125
  */
126
126
  lifecycleFloor?: string;
127
+ /**
128
+ * What kind of door this is, which decides WHICH RECORD the person lands
129
+ * on (AGL-3232) — the owner's rule is Salesforce's: one person is one
130
+ * record, a lead until they are qualified and a contact after.
131
+ *
132
+ * - `lead`: a lead surface — a form whose author routes it to leads, a
133
+ * booking request. The person is filed as a LEAD and nothing else,
134
+ * unless the workspace already holds them as a contact, in which case
135
+ * the capture lands on the contact and no lead is filed.
136
+ * - `relationship`: an act that makes the person a known relationship —
137
+ * a member account, a purchase. The person is filed as a CONTACT, and
138
+ * an open lead the site held for them is stamped converted onto it.
139
+ * - `touch`, the default: everything else — a form without lead routing,
140
+ * a newsletter opt-in. The capture lands on the open lead when the site
141
+ * holds one for the address, and on the contact otherwise.
142
+ */
143
+ surface?: 'lead' | 'relationship' | 'touch';
127
144
  /**
128
145
  * Profile fields the silo knows, keyed by the owner's own field names.
129
146
  * Only the keys given are written, so a silo that knows the phone number
@@ -155,10 +172,24 @@ export interface PluginContactCaptureRequest {
155
172
  * it was recording, so a throw here would cost an accepted submission or a
156
173
  * paid order for a record it could not keep.
157
174
  */
158
- export type PluginContactCaptured = {
175
+ export type PluginContactCaptured =
176
+ /** The capture landed on a contact — the record every capture used to make. */
177
+ {
159
178
  ok: true;
179
+ record: 'contact';
160
180
  contactId: string;
161
181
  created: boolean;
182
+ }
183
+ /**
184
+ * The capture landed on a LEAD (AGL-3232): a lead surface met somebody the
185
+ * workspace does not hold as a contact, or a touch reached an open lead.
186
+ * `leadId` is the person key the lead is filed under on `hostId`.
187
+ */
188
+ | {
189
+ ok: true;
190
+ record: 'lead';
191
+ leadId: string;
192
+ created: boolean;
162
193
  } | {
163
194
  ok: false;
164
195
  /**