@aglyn/aglyn 1.0.0-beta.288 → 1.0.0-beta.290

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 (37) hide show
  1. package/package.json +11 -11
  2. package/src/lib/app-utils/docs-help-sections.generated.js +5 -0
  3. package/src/lib/app-utils/docs-help-sections.generated.js.map +1 -1
  4. package/src/lib/app-utils/docs-help.generated.d.ts +7 -1
  5. package/src/lib/app-utils/docs-help.generated.js +29 -0
  6. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  7. package/src/lib/app-utils/docs-index.generated.js +131 -12
  8. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  9. package/src/lib/app-utils/element-motion.js +1 -0
  10. package/src/lib/app-utils/element-motion.js.map +1 -1
  11. package/src/lib/app-utils/host-status.d.ts +2 -1
  12. package/src/lib/app-utils/host-status.js +10 -0
  13. package/src/lib/app-utils/host-status.js.map +1 -1
  14. package/src/lib/app-utils/screen-slug.d.ts +5 -5
  15. package/src/lib/app-utils/screen-slug.js +5 -5
  16. package/src/lib/app-utils/screen-slug.js.map +1 -1
  17. package/src/lib/app-utils/search-indexing.d.ts +18 -0
  18. package/src/lib/app-utils/search-indexing.js +16 -2
  19. package/src/lib/app-utils/search-indexing.js.map +1 -1
  20. package/src/lib/app-utils/server.d.ts +1 -0
  21. package/src/lib/app-utils/server.js +2 -0
  22. package/src/lib/app-utils/server.js.map +1 -1
  23. package/src/lib/app-utils/site-preview.d.ts +153 -0
  24. package/src/lib/app-utils/site-preview.js +167 -0
  25. package/src/lib/app-utils/site-preview.js.map +1 -0
  26. package/src/lib/app-utils/upload-inspection.js +36 -0
  27. package/src/lib/app-utils/upload-inspection.js.map +1 -1
  28. package/src/lib/app-utils/visitor-upload-client.d.ts +47 -0
  29. package/src/lib/app-utils/visitor-upload-client.js +63 -0
  30. package/src/lib/app-utils/visitor-upload-client.js.map +1 -0
  31. package/src/lib/app-utils/visitor-upload.d.ts +140 -0
  32. package/src/lib/app-utils/visitor-upload.js +312 -0
  33. package/src/lib/app-utils/visitor-upload.js.map +1 -0
  34. package/src/lib/foundation/definitions/platform.types.d.ts +27 -0
  35. package/src/lib/foundation/definitions/platform.types.js.map +1 -1
  36. package/src/lib/plugin-manager/feature-plugins.d.ts +17 -1
  37. package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
@@ -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'\n// `FAQPage` for the FAQ section a page draws (AGL-3574): the same input, the\n// same reason, and server-only for the same one — only the route emits it.\nexport * from './faq-page'\nexport * from './collection-delete'\nexport * from './collection-entries'\nexport * from './collection-kind'\nexport * from './collection-slug'\nexport * from './content-authors'\n// NOT re-exported: `./local-business` and `./site-entity-json-ld` (AGL-3383).\n// This barrel is the whole namespace a realm bundle is handed and part of the\n// runtime a published page loads (`check:tenant-wire-weight`); the site\n// entity's JSON-LD and the LocalBusiness allow-list are read only by the\n// tenant page's server render and the console's Setup → SEO card, which import\n// them by path (`@aglyn/aglyn/app-utils/...`).\nexport * from './content-query-fields'\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 portable node tree must satisfy before it lands on a canvas that did\n// not author it (AGL-2939): a tree installed from another workspace and a tree\n// a model generated both pass through it.\nexport * from './node-definition-sanitizer'\nexport * from './console-routes'\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// A lead's or a contact's email state (AGL-3245): the last verdict on its\n// address, in words a person can act on, mirrored from the senders' lists.\nexport * from './email-state'\n// A field whose choices an admin keeps (AGL-3510): standard values built in,\n// the organization's own beside them, and the judge every write asks. Pure,\n// and named for no plugin — a plugin's registry of picklists sits on top.\nexport * from './picklists'\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// 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// 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`, read by the hourly route and by every writer of the\n// field.\n// Reading a received email (AGL-2657): the address in a header, the thread\n// a subject belongs to, the reply above the quoted history — and the domain\n// the platform receives mail on. Pure; every surface that reads mail it was\n// sent reads it this way.\nexport * from './email-text'\nexport * from './inbound-mail-domain'\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 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 importNoMailServerSentence,\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// A refusal kept after the record it was written on is deleted (AGL-3338),\n// read back through the same parser as the record's own.\nexport * from './retained-refusals'\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 './enrollment-basis'\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.\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 './subscription-topics'\nexport * from './compose-layout-nodes'\n// Layout properties applied through the chain (AGL-2893).\nexport * from './compose-layout-props'\n// A screen's per-page restyling of its layout's elements (AGL-3286).\nexport * from './layout-style-overrides'\nexport * from './document-landmark'\nexport * from './functions'\nexport * from './compose-reusable-components'\n// Where a reusable component is placed — pages or emails (AGL-3287).\nexport * from './reusable-component-kind'\nexport * from './compress'\nexport * from './merge-node-sx'\nexport * from './palette-sx'\nexport * from './scheme-sx'\n// An element pinned to one color scheme (AGL-3284).\nexport * from './element-color-scheme'\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// The platform team's ask that a workspace buy a plan (AGL-3466), beside the\n// plan intent its button carries into Billing.\nexport * from './upgrade-proposal'\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 './utm-attribution'\n// What a record is filed under: the edge between a container a plugin keeps\n// (a campaign) and the forms, screens and contacts it gathers. Beside the\n// attribution above because the two answer opposite questions: attribution\n// records where somebody CAME from, this records what a merchant DECLARED\n// belongs together.\nexport * from './container-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'\n// Video and file delivery as bandwidth (AGL-3474), in the band's own units.\nexport * from './media-bandwidth'\n// The month every monthly counter is keyed by, and the boundary it lifts on.\nexport * from './utc-month'\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'\n// Site Care requests (AGL-3959): the arithmetic, and the two modules any\n// staff-recorded, approval-gated charge reuses (AGL-3970).\nexport * from './site-care'\nexport * from './owner-approval-record'\nexport * from './append-only-history'\n// Site Care projects (AGL-3970): the flat quote, its split and its record.\nexport * from './site-care-project'\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'\n// What happened on a site that an automation can start on: the platform's\n// own event and the ones plugins declare (AGL-3080).\nexport * from './host-events'\nexport * from './expand-repeatables'\nexport * from './org-roles'\nexport * from './markdown-lite'\nexport * from './notifications'\n// The operator alert registry (AGL-3377); OPERATOR_ALERT_NOTIFICATION_TYPES\n// lives here now, derived from it.\nexport * from './operator-alerts'\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 './artifact-list-keys'\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'\n// What a published page does when a visitor does something (AGL-3080): the\n// platform's interaction vocabulary, which the workflows plugin builds its\n// automations on.\nexport * from './site-interactions'\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'\nexport * from './rendered-widths'\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 './csv'\nexport * from './csv-upload'\nexport * from './artifact-provenance'\nexport * from './repeat-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","importNoMailServerSentence"],"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'\n// `FAQPage` for the FAQ section a page draws (AGL-3574): the same input, the\n// same reason, and server-only for the same one — only the route emits it.\nexport * from './faq-page'\nexport * from './collection-delete'\nexport * from './collection-entries'\nexport * from './collection-kind'\nexport * from './collection-slug'\nexport * from './content-authors'\n// NOT re-exported: `./local-business` and `./site-entity-json-ld` (AGL-3383).\n// This barrel is the whole namespace a realm bundle is handed and part of the\n// runtime a published page loads (`check:tenant-wire-weight`); the site\n// entity's JSON-LD and the LocalBusiness allow-list are read only by the\n// tenant page's server render and the console's Setup → SEO card, which import\n// them by path (`@aglyn/aglyn/app-utils/...`).\nexport * from './content-query-fields'\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 portable node tree must satisfy before it lands on a canvas that did\n// not author it (AGL-2939): a tree installed from another workspace and a tree\n// a model generated both pass through it.\nexport * from './node-definition-sanitizer'\nexport * from './console-routes'\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// A lead's or a contact's email state (AGL-3245): the last verdict on its\n// address, in words a person can act on, mirrored from the senders' lists.\nexport * from './email-state'\n// A field whose choices an admin keeps (AGL-3510): standard values built in,\n// the organization's own beside them, and the judge every write asks. Pure,\n// and named for no plugin — a plugin's registry of picklists sits on top.\nexport * from './picklists'\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// 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// 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`, read by the hourly route and by every writer of the\n// field.\n// Reading a received email (AGL-2657): the address in a header, the thread\n// a subject belongs to, the reply above the quoted history — and the domain\n// the platform receives mail on. Pure; every surface that reads mail it was\n// sent reads it this way.\nexport * from './email-text'\nexport * from './inbound-mail-domain'\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 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 importNoMailServerSentence,\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// A refusal kept after the record it was written on is deleted (AGL-3338),\n// read back through the same parser as the record's own.\nexport * from './retained-refusals'\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 './enrollment-basis'\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.\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 './subscription-topics'\nexport * from './compose-layout-nodes'\n// Layout properties applied through the chain (AGL-2893).\nexport * from './compose-layout-props'\n// A screen's per-page restyling of its layout's elements (AGL-3286).\nexport * from './layout-style-overrides'\nexport * from './document-landmark'\nexport * from './functions'\nexport * from './compose-reusable-components'\n// Where a reusable component is placed — pages or emails (AGL-3287).\nexport * from './reusable-component-kind'\nexport * from './compress'\nexport * from './merge-node-sx'\nexport * from './palette-sx'\nexport * from './scheme-sx'\n// An element pinned to one color scheme (AGL-3284).\nexport * from './element-color-scheme'\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// The platform team's ask that a workspace buy a plan (AGL-3466), beside the\n// plan intent its button carries into Billing.\nexport * from './upgrade-proposal'\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 './utm-attribution'\n// What a record is filed under: the edge between a container a plugin keeps\n// (a campaign) and the forms, screens and contacts it gathers. Beside the\n// attribution above because the two answer opposite questions: attribution\n// records where somebody CAME from, this records what a merchant DECLARED\n// belongs together.\nexport * from './container-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'\n// Video and file delivery as bandwidth (AGL-3474), in the band's own units.\nexport * from './media-bandwidth'\n// The month every monthly counter is keyed by, and the boundary it lifts on.\nexport * from './utc-month'\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'\n// Site Care requests (AGL-3959): the arithmetic, and the two modules any\n// staff-recorded, approval-gated charge reuses (AGL-3970).\nexport * from './site-care'\nexport * from './owner-approval-record'\nexport * from './append-only-history'\n// Site Care projects (AGL-3970): the flat quote, its split and its record.\nexport * from './site-care-project'\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'\n// What happened on a site that an automation can start on: the platform's\n// own event and the ones plugins declare (AGL-3080).\nexport * from './host-events'\nexport * from './expand-repeatables'\nexport * from './org-roles'\nexport * from './markdown-lite'\nexport * from './notifications'\n// The operator alert registry (AGL-3377); OPERATOR_ALERT_NOTIFICATION_TYPES\n// lives here now, derived from it.\nexport * from './operator-alerts'\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 './artifact-list-keys'\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'\n// What a published page does when a visitor does something (AGL-3080): the\n// platform's interaction vocabulary, which the workflows plugin builds its\n// automations on.\nexport * from './site-interactions'\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'\nexport * from './rendered-widths'\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 './csv'\nexport * from './csv-upload'\nexport * from './artifact-provenance'\nexport * from './repeat-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'\n// Preview: a site or page only its team can see (AGL-4086).\nexport * from './site-preview'\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","importNoMailServerSentence"],"mappings":"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"}
@@ -0,0 +1,153 @@
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
+ /**
18
+ * Preview: a site, or one page of it, that only its team can see (AGL-4086).
19
+ *
20
+ * The public gets the site's 503 page, or a "Coming soon" notice, at every
21
+ * address of a site in preview, and the site's 404 at a page in preview. The
22
+ * site's team, and Aglyn staff, get the whole site. Flipping the switch makes
23
+ * it public to everyone.
24
+ *
25
+ * DEPENDENCY-FREE ON PURPOSE. The tenant middleware runs on the edge and reads
26
+ * the cookie name and the enter path from here; it deep-imports its helpers so
27
+ * the edge bundle does not drag a barrel, and this module imports nothing, as
28
+ * `entry-preview-link.ts` does not.
29
+ *
30
+ * ## The two fields
31
+ *
32
+ * - `host.preview: true` puts the WHOLE SITE in preview. Absent is public: a
33
+ * missing field must never read as "hide this site", or a schema slip would
34
+ * take every customer off the air.
35
+ * - `host.previewScreens: { [screenId]: true }` puts ONE PAGE in preview, on a
36
+ * site that is otherwise public. It lives on the host document rather than
37
+ * on the screen for one reason: the tenant middleware has to know, before
38
+ * any cached HTML answers, which addresses a team member must be routed
39
+ * around the cache for, and the verdict route it asks holds the host
40
+ * document and nothing else.
41
+ *
42
+ * `host.publicSinceMs` records that the site has been public at least once,
43
+ * so the switch that makes it public reports `site_published` only for a site
44
+ * that never was.
45
+ */
46
+ /** A host document, as far as preview reads it. */
47
+ export interface SitePreviewHost {
48
+ preview?: boolean | null;
49
+ previewScreens?: Record<string, unknown> | null;
50
+ publicSinceMs?: number | null;
51
+ /** The routing map: screen id → routing-map path (`about`, `/`). */
52
+ screens?: Record<string, unknown> | null;
53
+ }
54
+ /**
55
+ * The cookie a console-minted enter link plants on the site's own host. It
56
+ * holds a signed token bound to one site, verified on every request by the
57
+ * tenant; the edge only checks that it is present.
58
+ */
59
+ export declare const SITE_PREVIEW_COOKIE = "aglyn_site_preview";
60
+ /**
61
+ * The console sign-in's hint cookie on the tenant apex (`Domain=.aglyn.app`),
62
+ * planted by `/api/edit-hint/set`. Named here as well so the edge reads one
63
+ * dependency-free module; the server side keeps its own constant beside the
64
+ * signer.
65
+ */
66
+ export declare const SITE_PREVIEW_EDIT_HINT_COOKIE = "aglyn_edit_hint";
67
+ /** The tenant route a console-minted enter link lands on. */
68
+ export declare const SITE_PREVIEW_ENTER_PATH = "/api/site-preview/enter";
69
+ /** How long a planted preview cookie lasts: 12 hours. */
70
+ export declare const SITE_PREVIEW_COOKIE_TTL_MS: number;
71
+ /**
72
+ * How long an enter link's blob lasts: two minutes. It rides a URL, which is
73
+ * logged and can be shared, so it lives only as long as one click takes.
74
+ */
75
+ export declare const SITE_PREVIEW_ENTER_TTL_MS: number;
76
+ /** Whether the whole site is in preview. Only an explicit `true` is. */
77
+ export declare function isHostInPreview(host: Pick<SitePreviewHost, 'preview'> | null | undefined): boolean;
78
+ /** Whether one page of the site is in preview. */
79
+ export declare function isScreenInPreview(host: Pick<SitePreviewHost, 'previewScreens'> | null | undefined, screenId: string | null | undefined): boolean;
80
+ /** The ids of the pages in preview, in a stable order. */
81
+ export declare function previewScreenIds(host: Pick<SitePreviewHost, 'previewScreens'> | null | undefined): string[];
82
+ /**
83
+ * The request paths of the published pages in preview, for the middleware.
84
+ * A page in preview that is not published has no address, so it has none.
85
+ */
86
+ export declare function sitePreviewPaths(host: Pick<SitePreviewHost, 'previewScreens' | 'screens'> | null | undefined): string[];
87
+ /**
88
+ * Whether a request path is one the team must be routed around the public
89
+ * cache for: every path while the site is in preview, or the address of a
90
+ * page in preview. Trailing slashes are ignored, as Next ignores them.
91
+ */
92
+ export declare function isSitePreviewRequest(verdict: {
93
+ preview?: boolean;
94
+ previewPaths?: readonly string[];
95
+ } | null | undefined, pathname: string): boolean;
96
+ /**
97
+ * Where a create flow starts by default: in preview for a site brought in
98
+ * from somewhere else, public for everything else. A site that already exists
99
+ * elsewhere should not be public before its owner has looked at it; a new
100
+ * site is the launch its owner asked for.
101
+ */
102
+ export type SitePreviewStart = 'import' | 'ai' | 'starter' | 'blank';
103
+ export declare function sitePreviewStartsOn(start: string | null | undefined): boolean;
104
+ /**
105
+ * What a create request asks for: an explicit `preview` boolean wins, and
106
+ * without one the start decides ({@link sitePreviewStartsOn}).
107
+ */
108
+ export declare function sitePreviewForCreate(body: {
109
+ preview?: unknown;
110
+ start?: unknown;
111
+ } | null | undefined): boolean;
112
+ /**
113
+ * What flipping the site's switch writes, and whether it is the site's first
114
+ * time in public.
115
+ *
116
+ * - Turning preview ON for a site that is public now stamps `publicSinceMs`
117
+ * when it is absent: the site WAS public, and the stamp is what keeps a
118
+ * later "make it public" from reporting a first publish it is not.
119
+ * - Turning it OFF clears `preview`, and stamps `publicSinceMs` when the site
120
+ * has never been public. That is the moment `site_published` is reported,
121
+ * once, for a site that has pages to show.
122
+ */
123
+ export interface SitePreviewSwitchPlan {
124
+ /** `preview` after the write: true, or the field removed. */
125
+ preview: boolean;
126
+ /** Stamp `publicSinceMs` with the write's time. */
127
+ stampPublicSince: boolean;
128
+ /** Report `site_published` (first publish) for this flip. */
129
+ firstPublic: boolean;
130
+ /** Nothing would change; the caller writes nothing. */
131
+ unchanged: boolean;
132
+ }
133
+ export declare function sitePreviewSwitchPlan(host: SitePreviewHost | null | undefined, enabled: boolean): SitePreviewSwitchPlan;
134
+ /**
135
+ * A return path an enter link may send the browser to: a path on the site's
136
+ * own origin, and nothing else. Anything that could leave the origin — a
137
+ * scheme, `//host`, a backslash the browser would read as a slash, a control
138
+ * character — answers `/`.
139
+ */
140
+ export declare function sitePreviewReturnPath(raw: string | null | undefined): string;
141
+ /**
142
+ * What the public sees at a site in preview when no 503 page is assigned:
143
+ * the holding page's words, because to a visitor the two are the same thing,
144
+ * a site on its way.
145
+ */
146
+ export declare function sitePreviewNotice(siteName: string | null | undefined): {
147
+ title: string;
148
+ body: string;
149
+ };
150
+ /** The fixed line the team reads on every page of a site in preview. */
151
+ export declare const SITE_PREVIEW_BANNER_TEXT = "Preview \u2014 only your team can see this site. Make it public in Admin \u2192 Error pages.";
152
+ /** The same line for one page in preview on a public site. */
153
+ export declare const PAGE_PREVIEW_BANNER_TEXT = "Preview \u2014 only your team can see this page. Make it public in its Page Access card.";
@@ -0,0 +1,167 @@
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
+ * Preview: a site, or one page of it, that only its team can see (AGL-4086).
18
+ *
19
+ * The public gets the site's 503 page, or a "Coming soon" notice, at every
20
+ * address of a site in preview, and the site's 404 at a page in preview. The
21
+ * site's team, and Aglyn staff, get the whole site. Flipping the switch makes
22
+ * it public to everyone.
23
+ *
24
+ * DEPENDENCY-FREE ON PURPOSE. The tenant middleware runs on the edge and reads
25
+ * the cookie name and the enter path from here; it deep-imports its helpers so
26
+ * the edge bundle does not drag a barrel, and this module imports nothing, as
27
+ * `entry-preview-link.ts` does not.
28
+ *
29
+ * ## The two fields
30
+ *
31
+ * - `host.preview: true` puts the WHOLE SITE in preview. Absent is public: a
32
+ * missing field must never read as "hide this site", or a schema slip would
33
+ * take every customer off the air.
34
+ * - `host.previewScreens: { [screenId]: true }` puts ONE PAGE in preview, on a
35
+ * site that is otherwise public. It lives on the host document rather than
36
+ * on the screen for one reason: the tenant middleware has to know, before
37
+ * any cached HTML answers, which addresses a team member must be routed
38
+ * around the cache for, and the verdict route it asks holds the host
39
+ * document and nothing else.
40
+ *
41
+ * `host.publicSinceMs` records that the site has been public at least once,
42
+ * so the switch that makes it public reports `site_published` only for a site
43
+ * that never was.
44
+ */ /** A host document, as far as preview reads it. */ /**
45
+ * The cookie a console-minted enter link plants on the site's own host. It
46
+ * holds a signed token bound to one site, verified on every request by the
47
+ * tenant; the edge only checks that it is present.
48
+ */ export const SITE_PREVIEW_COOKIE = 'aglyn_site_preview';
49
+ /**
50
+ * The console sign-in's hint cookie on the tenant apex (`Domain=.aglyn.app`),
51
+ * planted by `/api/edit-hint/set`. Named here as well so the edge reads one
52
+ * dependency-free module; the server side keeps its own constant beside the
53
+ * signer.
54
+ */ export const SITE_PREVIEW_EDIT_HINT_COOKIE = 'aglyn_edit_hint';
55
+ /** The tenant route a console-minted enter link lands on. */ export const SITE_PREVIEW_ENTER_PATH = '/api/site-preview/enter';
56
+ /** How long a planted preview cookie lasts: 12 hours. */ export const SITE_PREVIEW_COOKIE_TTL_MS = 12 * 60 * 60 * 1000;
57
+ /**
58
+ * How long an enter link's blob lasts: two minutes. It rides a URL, which is
59
+ * logged and can be shared, so it lives only as long as one click takes.
60
+ */ export const SITE_PREVIEW_ENTER_TTL_MS = 2 * 60 * 1000;
61
+ /** Whether the whole site is in preview. Only an explicit `true` is. */ export function isHostInPreview(host) {
62
+ return (host == null ? void 0 : host.preview) === true;
63
+ }
64
+ /** Whether one page of the site is in preview. */ export function isScreenInPreview(host, screenId) {
65
+ if (!screenId) return false;
66
+ const map = host == null ? void 0 : host.previewScreens;
67
+ if (!map || typeof map !== 'object') return false;
68
+ return map[screenId] === true;
69
+ }
70
+ /** The ids of the pages in preview, in a stable order. */ export function previewScreenIds(host) {
71
+ const map = host == null ? void 0 : host.previewScreens;
72
+ if (!map || typeof map !== 'object') return [];
73
+ return Object.keys(map).filter((id)=>map[id] === true).sort();
74
+ }
75
+ /** A routing-map path (`about`, `services/roofing`, `/`) as a request path. */ function routingPathToRequestPath(path) {
76
+ const trimmed = path.trim().replace(/^\/+|\/+$/g, '');
77
+ return trimmed ? `/${trimmed}` : '/';
78
+ }
79
+ /**
80
+ * The request paths of the published pages in preview, for the middleware.
81
+ * A page in preview that is not published has no address, so it has none.
82
+ */ export function sitePreviewPaths(host) {
83
+ const routing = host == null ? void 0 : host.screens;
84
+ if (!routing || typeof routing !== 'object') return [];
85
+ const paths = new Set();
86
+ for (const screenId of previewScreenIds(host)){
87
+ const path = routing[screenId];
88
+ if (typeof path === 'string') paths.add(routingPathToRequestPath(path));
89
+ }
90
+ return [
91
+ ...paths
92
+ ].sort();
93
+ }
94
+ /**
95
+ * Whether a request path is one the team must be routed around the public
96
+ * cache for: every path while the site is in preview, or the address of a
97
+ * page in preview. Trailing slashes are ignored, as Next ignores them.
98
+ */ export function isSitePreviewRequest(verdict, pathname) {
99
+ if (!verdict) return false;
100
+ if (verdict.preview === true) return true;
101
+ const paths = verdict.previewPaths;
102
+ if (!paths || !paths.length) return false;
103
+ const normalized = routingPathToRequestPath(pathname);
104
+ return paths.includes(normalized);
105
+ }
106
+ export function sitePreviewStartsOn(start) {
107
+ return start === 'import';
108
+ }
109
+ /**
110
+ * What a create request asks for: an explicit `preview` boolean wins, and
111
+ * without one the start decides ({@link sitePreviewStartsOn}).
112
+ */ export function sitePreviewForCreate(body) {
113
+ if (typeof (body == null ? void 0 : body.preview) === 'boolean') return body.preview;
114
+ return sitePreviewStartsOn(typeof (body == null ? void 0 : body.start) === 'string' ? body.start : null);
115
+ }
116
+ export function sitePreviewSwitchPlan(host, enabled) {
117
+ var _ref;
118
+ const inPreview = isHostInPreview(host);
119
+ const everPublic = typeof (host == null ? void 0 : host.publicSinceMs) === 'number';
120
+ if (enabled) {
121
+ return {
122
+ preview: true,
123
+ stampPublicSince: !inPreview && !everPublic,
124
+ firstPublic: false,
125
+ unchanged: inPreview
126
+ };
127
+ }
128
+ const hasPages = Object.keys((_ref = host == null ? void 0 : host.screens) != null ? _ref : {}).length > 0;
129
+ return {
130
+ preview: false,
131
+ stampPublicSince: inPreview && !everPublic,
132
+ firstPublic: inPreview && !everPublic && hasPages,
133
+ unchanged: !inPreview
134
+ };
135
+ }
136
+ /**
137
+ * A return path an enter link may send the browser to: a path on the site's
138
+ * own origin, and nothing else. Anything that could leave the origin — a
139
+ * scheme, `//host`, a backslash the browser would read as a slash, a control
140
+ * character — answers `/`.
141
+ */ export function sitePreviewReturnPath(raw) {
142
+ if (typeof raw !== 'string' || !raw) return '/';
143
+ if (raw.length > 2048) return '/';
144
+ if (!raw.startsWith('/')) return '/';
145
+ if (raw.startsWith('//')) return '/';
146
+ // eslint-disable-next-line no-control-regex
147
+ if (/[\\\u0000-\u001f\u007f]/.test(raw)) return '/';
148
+ return raw;
149
+ }
150
+ /**
151
+ * What the public sees at a site in preview when no 503 page is assigned:
152
+ * the holding page's words, because to a visitor the two are the same thing,
153
+ * a site on its way.
154
+ */ export function sitePreviewNotice(siteName) {
155
+ const name = String(siteName != null ? siteName : '').trim();
156
+ return name ? {
157
+ title: name,
158
+ body: 'This site is coming soon. Check back shortly.'
159
+ } : {
160
+ title: 'Coming soon',
161
+ body: 'This site is on its way. Check back shortly.'
162
+ };
163
+ }
164
+ /** The fixed line the team reads on every page of a site in preview. */ export const SITE_PREVIEW_BANNER_TEXT = 'Preview — only your team can see this site. Make it public in Admin → Error pages.';
165
+ /** The same line for one page in preview on a public site. */ export const PAGE_PREVIEW_BANNER_TEXT = 'Preview — only your team can see this page. Make it public in its Page Access card.';
166
+
167
+ //# sourceMappingURL=site-preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/site-preview.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 * Preview: a site, or one page of it, that only its team can see (AGL-4086).\n *\n * The public gets the site's 503 page, or a \"Coming soon\" notice, at every\n * address of a site in preview, and the site's 404 at a page in preview. The\n * site's team, and Aglyn staff, get the whole site. Flipping the switch makes\n * it public to everyone.\n *\n * DEPENDENCY-FREE ON PURPOSE. The tenant middleware runs on the edge and reads\n * the cookie name and the enter path from here; it deep-imports its helpers so\n * the edge bundle does not drag a barrel, and this module imports nothing, as\n * `entry-preview-link.ts` does not.\n *\n * ## The two fields\n *\n * - `host.preview: true` puts the WHOLE SITE in preview. Absent is public: a\n * missing field must never read as \"hide this site\", or a schema slip would\n * take every customer off the air.\n * - `host.previewScreens: { [screenId]: true }` puts ONE PAGE in preview, on a\n * site that is otherwise public. It lives on the host document rather than\n * on the screen for one reason: the tenant middleware has to know, before\n * any cached HTML answers, which addresses a team member must be routed\n * around the cache for, and the verdict route it asks holds the host\n * document and nothing else.\n *\n * `host.publicSinceMs` records that the site has been public at least once,\n * so the switch that makes it public reports `site_published` only for a site\n * that never was.\n */\n\n/** A host document, as far as preview reads it. */\nexport interface SitePreviewHost {\n preview?: boolean | null\n previewScreens?: Record<string, unknown> | null\n publicSinceMs?: number | null\n /** The routing map: screen id → routing-map path (`about`, `/`). */\n screens?: Record<string, unknown> | null\n}\n\n/**\n * The cookie a console-minted enter link plants on the site's own host. It\n * holds a signed token bound to one site, verified on every request by the\n * tenant; the edge only checks that it is present.\n */\nexport const SITE_PREVIEW_COOKIE = 'aglyn_site_preview'\n\n/**\n * The console sign-in's hint cookie on the tenant apex (`Domain=.aglyn.app`),\n * planted by `/api/edit-hint/set`. Named here as well so the edge reads one\n * dependency-free module; the server side keeps its own constant beside the\n * signer.\n */\nexport const SITE_PREVIEW_EDIT_HINT_COOKIE = 'aglyn_edit_hint'\n\n/** The tenant route a console-minted enter link lands on. */\nexport const SITE_PREVIEW_ENTER_PATH = '/api/site-preview/enter'\n\n/** How long a planted preview cookie lasts: 12 hours. */\nexport const SITE_PREVIEW_COOKIE_TTL_MS = 12 * 60 * 60 * 1000\n\n/**\n * How long an enter link's blob lasts: two minutes. It rides a URL, which is\n * logged and can be shared, so it lives only as long as one click takes.\n */\nexport const SITE_PREVIEW_ENTER_TTL_MS = 2 * 60 * 1000\n\n/** Whether the whole site is in preview. Only an explicit `true` is. */\nexport function isHostInPreview(\n host: Pick<SitePreviewHost, 'preview'> | null | undefined,\n): boolean {\n return host?.preview === true\n}\n\n/** Whether one page of the site is in preview. */\nexport function isScreenInPreview(\n host: Pick<SitePreviewHost, 'previewScreens'> | null | undefined,\n screenId: string | null | undefined,\n): boolean {\n if (!screenId) return false\n const map = host?.previewScreens\n if (!map || typeof map !== 'object') return false\n return (map as Record<string, unknown>)[screenId] === true\n}\n\n/** The ids of the pages in preview, in a stable order. */\nexport function previewScreenIds(\n host: Pick<SitePreviewHost, 'previewScreens'> | null | undefined,\n): string[] {\n const map = host?.previewScreens\n if (!map || typeof map !== 'object') return []\n return Object.keys(map)\n .filter((id) => (map as Record<string, unknown>)[id] === true)\n .sort()\n}\n\n/** A routing-map path (`about`, `services/roofing`, `/`) as a request path. */\nfunction routingPathToRequestPath(path: string): string {\n const trimmed = path.trim().replace(/^\\/+|\\/+$/g, '')\n return trimmed ? `/${trimmed}` : '/'\n}\n\n/**\n * The request paths of the published pages in preview, for the middleware.\n * A page in preview that is not published has no address, so it has none.\n */\nexport function sitePreviewPaths(\n host: Pick<SitePreviewHost, 'previewScreens' | 'screens'> | null | undefined,\n): string[] {\n const routing = host?.screens\n if (!routing || typeof routing !== 'object') return []\n const paths = new Set<string>()\n for (const screenId of previewScreenIds(host)) {\n const path = (routing as Record<string, unknown>)[screenId]\n if (typeof path === 'string') paths.add(routingPathToRequestPath(path))\n }\n return [...paths].sort()\n}\n\n/**\n * Whether a request path is one the team must be routed around the public\n * cache for: every path while the site is in preview, or the address of a\n * page in preview. Trailing slashes are ignored, as Next ignores them.\n */\nexport function isSitePreviewRequest(\n verdict: { preview?: boolean; previewPaths?: readonly string[] } | null | undefined,\n pathname: string,\n): boolean {\n if (!verdict) return false\n if (verdict.preview === true) return true\n const paths = verdict.previewPaths\n if (!paths || !paths.length) return false\n const normalized = routingPathToRequestPath(pathname)\n return paths.includes(normalized)\n}\n\n/**\n * Where a create flow starts by default: in preview for a site brought in\n * from somewhere else, public for everything else. A site that already exists\n * elsewhere should not be public before its owner has looked at it; a new\n * site is the launch its owner asked for.\n */\nexport type SitePreviewStart = 'import' | 'ai' | 'starter' | 'blank'\n\nexport function sitePreviewStartsOn(start: string | null | undefined): boolean {\n return start === 'import'\n}\n\n/**\n * What a create request asks for: an explicit `preview` boolean wins, and\n * without one the start decides ({@link sitePreviewStartsOn}).\n */\nexport function sitePreviewForCreate(body: {\n preview?: unknown\n start?: unknown\n} | null | undefined): boolean {\n if (typeof body?.preview === 'boolean') return body.preview\n return sitePreviewStartsOn(typeof body?.start === 'string' ? body.start : null)\n}\n\n/**\n * What flipping the site's switch writes, and whether it is the site's first\n * time in public.\n *\n * - Turning preview ON for a site that is public now stamps `publicSinceMs`\n * when it is absent: the site WAS public, and the stamp is what keeps a\n * later \"make it public\" from reporting a first publish it is not.\n * - Turning it OFF clears `preview`, and stamps `publicSinceMs` when the site\n * has never been public. That is the moment `site_published` is reported,\n * once, for a site that has pages to show.\n */\nexport interface SitePreviewSwitchPlan {\n /** `preview` after the write: true, or the field removed. */\n preview: boolean\n /** Stamp `publicSinceMs` with the write's time. */\n stampPublicSince: boolean\n /** Report `site_published` (first publish) for this flip. */\n firstPublic: boolean\n /** Nothing would change; the caller writes nothing. */\n unchanged: boolean\n}\n\nexport function sitePreviewSwitchPlan(\n host: SitePreviewHost | null | undefined,\n enabled: boolean,\n): SitePreviewSwitchPlan {\n const inPreview = isHostInPreview(host)\n const everPublic = typeof host?.publicSinceMs === 'number'\n if (enabled) {\n return {\n preview: true,\n stampPublicSince: !inPreview && !everPublic,\n firstPublic: false,\n unchanged: inPreview,\n }\n }\n const hasPages = Object.keys(host?.screens ?? {}).length > 0\n return {\n preview: false,\n stampPublicSince: inPreview && !everPublic,\n firstPublic: inPreview && !everPublic && hasPages,\n unchanged: !inPreview,\n }\n}\n\n/**\n * A return path an enter link may send the browser to: a path on the site's\n * own origin, and nothing else. Anything that could leave the origin — a\n * scheme, `//host`, a backslash the browser would read as a slash, a control\n * character — answers `/`.\n */\nexport function sitePreviewReturnPath(raw: string | null | undefined): string {\n if (typeof raw !== 'string' || !raw) return '/'\n if (raw.length > 2048) return '/'\n if (!raw.startsWith('/')) return '/'\n if (raw.startsWith('//')) return '/'\n // eslint-disable-next-line no-control-regex\n if (/[\\\\\\u0000-\\u001f\\u007f]/.test(raw)) return '/'\n return raw\n}\n\n/**\n * What the public sees at a site in preview when no 503 page is assigned:\n * the holding page's words, because to a visitor the two are the same thing,\n * a site on its way.\n */\nexport function sitePreviewNotice(siteName: string | null | undefined): {\n title: string\n body: string\n} {\n const name = String(siteName ?? '').trim()\n return name\n ? { title: name, body: 'This site is coming soon. Check back shortly.' }\n : { title: 'Coming soon', body: 'This site is on its way. Check back shortly.' }\n}\n\n/** The fixed line the team reads on every page of a site in preview. */\nexport const SITE_PREVIEW_BANNER_TEXT =\n 'Preview — only your team can see this site. Make it public in Admin → Error pages.'\n\n/** The same line for one page in preview on a public site. */\nexport const PAGE_PREVIEW_BANNER_TEXT =\n 'Preview — only your team can see this page. Make it public in its Page Access card.'\n"],"names":["SITE_PREVIEW_COOKIE","SITE_PREVIEW_EDIT_HINT_COOKIE","SITE_PREVIEW_ENTER_PATH","SITE_PREVIEW_COOKIE_TTL_MS","SITE_PREVIEW_ENTER_TTL_MS","isHostInPreview","host","preview","isScreenInPreview","screenId","map","previewScreens","previewScreenIds","Object","keys","filter","id","sort","routingPathToRequestPath","path","trimmed","trim","replace","sitePreviewPaths","routing","screens","paths","Set","add","isSitePreviewRequest","verdict","pathname","previewPaths","length","normalized","includes","sitePreviewStartsOn","start","sitePreviewForCreate","body","sitePreviewSwitchPlan","enabled","inPreview","everPublic","publicSinceMs","stampPublicSince","firstPublic","unchanged","hasPages","sitePreviewReturnPath","raw","startsWith","test","sitePreviewNotice","siteName","name","String","title","SITE_PREVIEW_BANNER_TEXT","PAGE_PREVIEW_BANNER_TEXT"],"mappings":"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"}
@@ -512,6 +512,42 @@ const ascii = (text)=>Array.from(text, (character)=>character.charCodeAt(0));
512
512
  magic: ascii('wOF2'),
513
513
  label: 'WOFF2'
514
514
  }
515
+ ],
516
+ // Design files a business and its customer trade as proofs and artwork
517
+ // (AGL-4096, `visitor-upload.ts`). Illustrator saves a PDF-compatible file
518
+ // by default and plain PostScript when that option is off; an EPS is
519
+ // PostScript, or PostScript inside the DOS EPS binary header; a Photoshop
520
+ // document opens `8BPS`.
521
+ 'application/illustrator': [
522
+ {
523
+ magic: ascii('%PDF-'),
524
+ label: 'Illustrator'
525
+ },
526
+ {
527
+ magic: ascii('%!PS'),
528
+ label: 'Illustrator'
529
+ }
530
+ ],
531
+ 'application/postscript': [
532
+ {
533
+ magic: ascii('%!PS'),
534
+ label: 'PostScript'
535
+ },
536
+ {
537
+ magic: [
538
+ 0xc5,
539
+ 0xd0,
540
+ 0xd3,
541
+ 0xc6
542
+ ],
543
+ label: 'PostScript'
544
+ }
545
+ ],
546
+ 'image/vnd.adobe.photoshop': [
547
+ {
548
+ magic: ascii('8BPS'),
549
+ label: 'Photoshop'
550
+ }
515
551
  ]
516
552
  };
517
553
  /** The OOXML document types whose archive is scanned for a macro project. */ const OOXML_DOCUMENT_TYPES = new Set([