@ebitex/content-mcp 0.5.111 → 0.5.114

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.
@@ -31,12 +31,12 @@ export const HELP_TOPICS = [
31
31
  {
32
32
  "slug": "content-composer",
33
33
  "title": "Building your site in Composer",
34
- "body": "# Building your site in Composer\n\nComposer is where content becomes a website. A **site** is a named tree of\n**pages**; each page's slug (and its ancestors' slugs) form its **path** —\nthe URL it will eventually be served at. A page can be pure structure (a\n**Folder**, with no page of its own, just a place to organize its\nchildren), or it can carry a payload: either a **Presentation** (content\nshown at that path) or a **Redirect** (send visitors somewhere else).\nContracts, Components, and Templates (see\n[Modeling content with Contracts](contracts.md),\n[Authoring Components](components.md), and\n[Presenting content with Templates](templates.md)) define *what* content\nis and *how* it's presented; Composer decides *where* it lives. Nothing\nbuilt here is publicly visible yet — publishing is a later phase.\n\nComposer is the suite's *top-down* authoring surface — site, then tree,\nthen page. [Content](content-authoring.md) is its *bottom-up* counterpart:\nthe Component library, edited independently of any one page. Both appear\nas their own item in the sidebar.\n\n## Choosing a site\n\nComposer's header has a site switcher — select it to see every site in\nthis organization and pick one, or select **Manage sites →** to create,\nrename, or delete a site. Composer's tree always shows exactly one site's\npages at a time; switching sites swaps the whole tree beneath it.\n\nSites themselves are managed from **Settings > Sites**: create a new one\nby name, rename an existing one, or delete one (deleting a site deletes\nits entire page tree, including every page's payload — typing the site's\nname confirms you mean it).\n\n## Building the tree\n\nA large tree can be searched by category — see \"Filtering by category\" in\n[Taxonomy](content-taxonomy.md) for how the tree's own **Filter by\ncategory** control auto-expands to reveal matches without hiding anything\nelse.\n\nTo add a page:\n\n1. Select the parent page (the site's own root, shown at the top of the\n tree, or any page under it), then select **+ Add page** at the top of\n the tree panel.\n2. Pick a type — **Presentation**, **Redirect**, or **Folder** —\n Presentation is pre-selected, since it's what most new pages are for.\n You can change a page's type at any time later, from its own\n Experience tab.\n3. Enter a **Name** — the path preview beneath it fills in from it\n automatically (`/campaigns-launch`, for example). You can give the page\n a different slug later, from its **Configuration** tab.\n4. Select **Create**.\n\nEvery page shows its computed **path** at the top of the detail panel —\nthe site root's own path is always `/`.\n\n### Localized slugs\n\nA page's slug can have a different value per locale, just like other\nlocalizable content — select the translate icon beside **Slug** (in the\n**Configuration** tab) to add per-locale overrides. Two sibling pages can\nnever resolve to the same slug in the same locale, whether that's their\nshared default or one sibling's override colliding with another's\ndefault; you'll see exactly which locale and which sibling conflicts if\nthat happens.\n\n### Moving and reordering pages\n\nThe tree supports two different drags, depending on where you drop:\n\n- Drop a page **onto** another page to reparent it there — the dropped\n page becomes that page's child.\n- Drop a page **between** two sibling rows to reorder it among its\n current siblings, without changing its parent.\n\nEither kind of drag can also be done without a mouse: select **Move…** in\na page's **Configuration** tab and pick a target the same way dragging\nwould. You can't move a page into itself or one of its own descendants,\nand a site's root can't be moved or reordered at all — it has no grip\nhandle to drag by, and its Configuration tab shows no **Move…** button.\n\nIf someone else changes the tree while you're mid-drag, Composer notices,\nrefreshes the sibling list automatically, and asks you to try again rather\nthan silently applying a stale order.\n\nDeleting a page requires it to have no children first; a page that's the\ntarget of a **Redirect** elsewhere in the tree can't be deleted until that\nredirect is removed or repointed. A site's root can't be deleted from\nComposer at all — that's a **Settings > Sites** action, since it deletes\nthe whole tree beneath it.\n\n## The Experience tab\n\nA page's **Experience** tab is where you choose its type and, for a\nPresentation page, what actually renders:\n\n- **Template** shows which Template is bound and the Contract it\n requires.\n- **Satisfied by** shows the actual chain that fills that requirement —\n either a Component directly, or one or more Adapters translating a\n Component's content into what the Template expects (see\n [Adapters](content-adapters.md) if that's new to you). This is a live\n view of the binding actually in effect, not just two separate names, and\n it's also where you do the actual work: the innermost box in the chain\n is where you pick a Template, bind a Component (or create one on the\n spot), and fine-tune it through the **Contextual values** and\n **Settings** panels described in\n [Presenting content with Templates](templates.md). If the Template\n declares a settings field that's both mandatory and Contextual, it must\n be filled in here — a page is the last stop for that value, so there's\n nowhere further downstream to inherit it from. **Quick edit** opens the\n bound Component itself in a layer over the tree — and the same layer\n opens *this* page from any Link or Experience-reference field elsewhere\n that points at it; see\n [Editing something from where it's used](content-authoring.md#editing-something-from-where-its-used).\n\nSwitching a page's type here always lands you on that type's own normal\nstarting point (no Template chosen yet, no redirect target chosen yet) —\nit never carries over or invents a binding from whatever the page was\nbefore.\n\nFor a **Redirect** page, select **Pick a target page…** and browse to it.\nA page can't redirect to itself. A **Folder** page has no payload of its\nown — it exists only to organize the pages beneath it.\n\n## The Configuration tab\n\nEverything about a page other than what it renders lives in\n**Configuration**: its name and slug, its location in the tree (parent,\nMove…), access rules and workflow assignment, classification tags, and —\nfor a non-root page — the option to delete it.\n\nPublish status and the page's actions — **Preview…**, **Promote…**, and a\n**Publish…**/**Republish…** button (once published, its own chevron opens\n**Unpublish**) — sit together in a row above the page name, visible no\nmatter which tab is open, since they matter regardless of what you're\ncurrently editing. A small workflow chip appears there too, once a page\nhas an editorial workflow assigned — select it to jump straight to the\nfull workflow panel in Configuration.\n\n## Live preview\n\nClick **Preview…** on any page to open live preview: your site, rendered\nright there in Composer, showing your unsaved draft — not what's actually\npublished. Nothing you do here goes live until you choose to publish it.\n\nThe page renders with numbered pins over anything you can edit. Shape\ntells you what a pin is, so it reads even in black and white:\n\n- A **magenta circle** is a single field — a headline, a paragraph, a date.\n- A **solid blue rounded rectangle** is a whole Component — either the\n Presentation bound at that spot, or something rendered outside the page\n itself (see \"Also on this page\" below).\n- A **dashed blue rounded rectangle** is content produced by an Adapter —\n mapped in from somewhere else, with no field of its own on this page.\n- A **red rectangle** marks something that couldn't be resolved.\n\nEvery pinned part of the page also gets a light outline in its pin's own\ncolor the whole time you're in Edit mode, not just on hover — so you can\nsee everything on the page that's editable at a glance, before you click\nanything. Hovering or selecting a pin (from the page or from its row in\nthe panel on the right) strengthens that outline and shows a tag naming\nwhat it is.\n\nWhat clicking a pin does depends on its shape:\n\n- A **field** pin opens a small **docked editor** right at the top of the\n panel — no matter how deep inside the page's content that field actually\n lives — with its name, its type, and a magenta **Own save** badge, above\n the rest of the page summary (dimmed while you're editing). Deep inside\n something (a section, a card, a list item), the docked editor also shows\n a breadcrumb (\"Referenced by *the page* → *Section 4* *Statement* →\n `actions`\") so you know exactly where you are. What docks depends on the\n field:\n - A **Component**, **Reference**, or **Presentation** field — the kind\n that points at other content — gets a compact list: one row per item,\n with a label, where it links to (if anywhere), a drag handle to\n reorder, an edit button, a remove button, and an **Add item** row at\n the bottom. Click a row's edit button to open that item — an item\n authored right here opens its own full editor; an item that's really a\n separate, shared Component re-targets this same panel to that\n Component instead of opening a second one.\n - Every other field (Rich text, a plain text field, a date, and so on)\n gets its own usual editor, docked as a single row.\n Type, then **Save** or **Cancel** — or **Open full editor** if you'd\n rather see the whole Component or page it belongs to.\n A pin whose field can't be matched this way falls back to opening the\n whole Component or page in full, with that field already focused.\n- A **Component** pin (solid rectangle) opens that Component for editing\n in full, the same as clicking **Quick edit** next to it — a magenta\n **Own save** badge marks it while you're in it.\n- An **Adapter-mapped** pin (dashed rectangle) never opens an editor\n directly — there's no field of yours behind it. Instead it explains\n where the content comes from: which Adapter produced it, and a look at\n the actual source underneath. From there, **Edit source field** jumps\n straight to the one field that's a direct, one-to-one copy (when there\n is one), and **Edit mapping…** opens the mapping itself for a deeper\n change.\n- A **red (unresolved)** pin opens on whatever it belongs to, so you can\n see and fix why it isn't resolving.\n\nType in a docked or full editor, and the page updates within a second or\nso either way.\n\nA **Browse** toggle switches off the pins so you can click around the page\nthe way a visitor would — following links to see other pages of the same\nsite, still against your unsaved drafts.\n\n**Also on this page** lists anything the site renders that isn't part of\nthe page itself — a shared header or footer, for instance. These are\nedited and saved the same way as anything else with a pin: click **Quick\nedit** next to it, make your change, and save. Because a shared header or\nfooter isn't part of any one page, saving it doesn't publish it along with\nthe page — after saving, use the **Publish…** button that appears right\nthere to make the change live. If a site is set up to show something\nthat doesn't exist in the environment you're working in, it's listed as\n**not in this environment** — nothing to worry about, and never something\nthat stops the rest of the page from previewing normally.\n\n### Previewing a site that renders on its server\n\nSome sites build every page on their own server and send finished pages to\nthe browser, with nothing re-drawn in the browser afterwards. Live preview\ncan't hand those sites your draft directly, so it works a little\ndifferently there.\n\nYour developer sets it up once:\n\n- Under **Settings › Sites**, open the site and set its host's **Live\n preview** to **Server**.\n- Under **API Keys**, the site's key needs **Allow draft preview** turned\n on. Only a server-side key can have it.\n\nAfter that, live preview on that host behaves like this:\n\n- Composer starts a private preview session for you. Your draft, unsaved\n edits included, goes to that session, and the site's server reads it from\n there.\n- Each time you pause typing, the page reloads with your latest edits. That\n takes a moment longer than on other sites.\n- There are no pins and no **Browse** toggle, because the site has nothing\n running in the browser to draw them. Use the panel on the right to edit\n the page and the Component it shows.\n- Only the page you're previewing shows your draft. Follow a link and the\n other page shows what's published.\n- If the preview says **The site loaded, but it did not read the draft**,\n what you're looking at isn't your draft. Usually the site isn't set up for\n server previews yet, its key doesn't allow draft preview, or your browser\n blocked the site's cookie inside Composer. **Open the site in a new tab**\n gets around that last one.\n- Closing live preview ends the session straight away. Nobody can use it\n afterwards.\n\n## Opening a page from the site itself\n\nWhen you're signed in to Content and browsing one of your own published sites, a small **Click to\nedit** button appears in the corner of the page. It takes you straight to that page in Composer, with\nlive preview already open.\n\nIf the page belongs to a **different organization** than the one you're currently working in, Content\nswitches for you and shows a notice saying so, with a **Switch back** button. That switch applies to\nyour whole ebitex session — Hub and Forms in other tabs will show the new organization the next time\nyou navigate in them — so the notice stays until you dismiss it.\n\nA few cases where the link won't open a page, and what each means:\n\n- **\"This page no longer exists, or belongs to an organization you are not currently signed in to.\"**\n Either the page was deleted, or it belongs to an organization you're not a member of. If a\n colleague sent you the link, ask them to add you to that organization.\n- **Nothing switches and the page doesn't load.** The site's hostname isn't mapped to a site in any\n organization you belong to. Check **Settings > Delivery** for that organization's host mappings.\n- **Two organizations claim the same hostname.** Content won't guess which one you meant. Fix the\n duplicate mapping in **Settings > Delivery**, then follow the link again.\n\n## Restricting what can go where\n\nTwo governance controls apply to a branch of the tree, the same way they\napply to Component folders (see \"Folders and access rules\" in\n[Authoring Components](components.md)) — both live in the **Configuration**\ntab's \"Access & workflow\" section:\n\n- **Access rules** grant specific roles view/edit/delete/publish on a\n branch — no rules anywhere on the branch means it's open to everyone; a\n rule anywhere on a root even restricts an entire site. A role needs view\n to see a branch at all; edit, delete, and publish are each independent\n beyond that.\n- **Allowed Templates** restricts which Templates a Presentation payload\n can use anywhere at or beneath a page — useful for keeping, say, a\n campaigns section limited to a handful of approved layouts. Leaving it\n empty allows any Template. Tightening this later never breaks a payload\n already in place; it's only checked when a payload is assigned or\n changed.\n\nBoth panels are only editable by someone with elevated access-management\npermission; everyone else sees a read-only summary of what they\npersonally can do on that branch.\n"
34
+ "body": "# Building your site in Composer\n\nComposer is where content becomes a website. A **site** is a named tree of\n**pages**; each page's slug (and its ancestors' slugs) form its **path** —\nthe URL it will eventually be served at. A page can be pure structure (a\n**Folder**, with no page of its own, just a place to organize its\nchildren), or it can carry a payload: either a **Presentation** (content\nshown at that path) or a **Redirect** (send visitors somewhere else).\nContracts, Components, and Templates (see\n[Modeling content with Contracts](contracts.md),\n[Authoring Components](components.md), and\n[Presenting content with Templates](templates.md)) define *what* content\nis and *how* it's presented; Composer decides *where* it lives. Nothing\nbuilt here is publicly visible yet — publishing is a later phase.\n\nComposer is the suite's *top-down* authoring surface — site, then tree,\nthen page. [Content](content-authoring.md) is its *bottom-up* counterpart:\nthe Component library, edited independently of any one page. Both appear\nas their own item in the sidebar.\n\n## Choosing a site\n\nComposer's header has a site switcher — select it to see every site in\nthis organization and pick one, or select **Manage sites →** to create,\nrename, or delete a site. Composer's tree always shows exactly one site's\npages at a time; switching sites swaps the whole tree beneath it.\n\nSites themselves are managed from **Settings > Sites**: create a new one\nby name, rename an existing one, or delete one (deleting a site deletes\nits entire page tree, including every page's payload — typing the site's\nname confirms you mean it).\n\n## Building the tree\n\nA large tree can be searched by category — see \"Filtering by category\" in\n[Taxonomy](content-taxonomy.md) for how the tree's own **Filter by\ncategory** control auto-expands to reveal matches without hiding anything\nelse.\n\nTo add a page:\n\n1. Select the parent page (the site's own root, shown at the top of the\n tree, or any page under it), then select **+ Add page** at the top of\n the tree panel.\n2. Pick a type — **Presentation**, **Redirect**, or **Folder** —\n Presentation is pre-selected, since it's what most new pages are for.\n You can change a page's type at any time later, from its own\n Experience tab.\n3. Enter a **Name** — the path preview beneath it fills in from it\n automatically (`/campaigns-launch`, for example). You can give the page\n a different slug later, from its **Configuration** tab.\n4. Select **Create**.\n\nEvery page shows its computed **path** at the top of the detail panel —\nthe site root's own path is always `/`.\n\n### Localized slugs\n\nA page's slug can have a different value per locale, just like other\nlocalizable content — select the translate icon beside **Slug** (in the\n**Configuration** tab) to add per-locale overrides. Two sibling pages can\nnever resolve to the same slug in the same locale, whether that's their\nshared default or one sibling's override colliding with another's\ndefault; you'll see exactly which locale and which sibling conflicts if\nthat happens.\n\n### Moving and reordering pages\n\nThe tree supports two different drags, depending on where you drop:\n\n- Drop a page **onto** another page to reparent it there — the dropped\n page becomes that page's child.\n- Drop a page **between** two sibling rows to reorder it among its\n current siblings, without changing its parent.\n\nEither kind of drag can also be done without a mouse: select **Move…** in\na page's **Configuration** tab and pick a target the same way dragging\nwould. You can't move a page into itself or one of its own descendants,\nand a site's root can't be moved or reordered at all — it has no grip\nhandle to drag by, and its Configuration tab shows no **Move…** button.\n\nIf someone else changes the tree while you're mid-drag, Composer notices,\nrefreshes the sibling list automatically, and asks you to try again rather\nthan silently applying a stale order.\n\nDeleting a page requires it to have no children first; a page that's the\ntarget of a **Redirect** elsewhere in the tree can't be deleted until that\nredirect is removed or repointed. A site's root can't be deleted from\nComposer at all — that's a **Settings > Sites** action, since it deletes\nthe whole tree beneath it.\n\n## The Experience tab\n\nA page's **Experience** tab is where you choose its type and, for a\nPresentation page, what actually renders:\n\n- **Template** shows which Template is bound and the Contract it\n requires.\n- **Satisfied by** shows the actual chain that fills that requirement —\n either a Component directly, or one or more Adapters translating a\n Component's content into what the Template expects (see\n [Adapters](content-adapters.md) if that's new to you). This is a live\n view of the binding actually in effect, not just two separate names, and\n it's also where you do the actual work: the innermost box in the chain\n is where you pick a Template, bind a Component (or create one on the\n spot), and fine-tune it through the **Contextual values** and\n **Settings** panels described in\n [Presenting content with Templates](templates.md). If the Template\n declares a settings field that's both mandatory and Contextual, it must\n be filled in here — a page is the last stop for that value, so there's\n nowhere further downstream to inherit it from. **Quick edit** opens the\n bound Component itself in a layer over the tree — and the same layer\n opens *this* page from any Link or Experience-reference field elsewhere\n that points at it; see\n [Editing something from where it's used](content-authoring.md#editing-something-from-where-its-used).\n\nSwitching a page's type here always lands you on that type's own normal\nstarting point (no Template chosen yet, no redirect target chosen yet) —\nit never carries over or invents a binding from whatever the page was\nbefore.\n\nFor a **Redirect** page, select **Pick a target page…** and browse to it.\nA page can't redirect to itself. A **Folder** page has no payload of its\nown — it exists only to organize the pages beneath it.\n\n## The Configuration tab\n\nEverything about a page other than what it renders lives in\n**Configuration**: its name and slug, its location in the tree (parent,\nMove…), access rules and workflow assignment, classification tags, and —\nfor a non-root page — the option to delete it.\n\nPublish status and the page's actions — **Preview…**, **Promote…**, and a\n**Publish…**/**Republish…** button (once published, its own chevron opens\n**Unpublish**) — sit together in a row above the page name, visible no\nmatter which tab is open, since they matter regardless of what you're\ncurrently editing. A small workflow chip appears there too, once a page\nhas an editorial workflow assigned — select it to jump straight to the\nfull workflow panel in Configuration.\n\n## Live preview\n\nClick **Preview…** on any page to open live preview: your site, rendered\nright there in Composer, showing your unsaved draft — not what's actually\npublished. Nothing you do here goes live until you choose to publish it.\n\nThe page renders with numbered pins over anything you can edit. Shape\ntells you what a pin is, so it reads even in black and white:\n\n- A **magenta circle** is a single field — a headline, a paragraph, a date.\n- A **solid blue rounded rectangle** is a whole Component — either the\n Presentation bound at that spot, or something rendered outside the page\n itself (see \"Also on this page\" below).\n- A **dashed blue rounded rectangle** is content produced by an Adapter —\n mapped in from somewhere else, with no field of its own on this page.\n- A **red rectangle** marks something that couldn't be resolved.\n\nEvery pinned part of the page also gets a light outline in its pin's own\ncolor the whole time you're in Edit mode, not just on hover — so you can\nsee everything on the page that's editable at a glance, before you click\nanything. Hovering or selecting a pin (from the page or from its row in\nthe panel on the right) strengthens that outline and shows a tag naming\nwhat it is.\n\nWhat clicking a pin does depends on its shape:\n\n- A **field** pin opens a small **docked editor** right at the top of the\n panel — no matter how deep inside the page's content that field actually\n lives — with its name, its type, and a magenta **Own save** badge, above\n the rest of the page summary (dimmed while you're editing). Deep inside\n something (a section, a card, a list item), the docked editor also shows\n a breadcrumb (\"Referenced by *the page* → *Section 4* *Statement* →\n `actions`\") so you know exactly where you are. What docks depends on the\n field:\n - A **Component**, **Reference**, or **Presentation** field — the kind\n that points at other content — gets a compact list: one row per item,\n with a label, where it links to (if anywhere), a drag handle to\n reorder, an edit button, a remove button, and an **Add item** row at\n the bottom. Click a row's edit button to open that item — an item\n authored right here opens its own full editor; an item that's really a\n separate, shared Component re-targets this same panel to that\n Component instead of opening a second one.\n - Every other field (Rich text, a plain text field, a date, and so on)\n gets its own usual editor, docked as a single row.\n Type, then **Save** or **Cancel** — or **Open full editor** if you'd\n rather see the whole Component or page it belongs to.\n A pin whose field can't be matched this way falls back to opening the\n whole Component or page in full, with that field already focused.\n- A **Component** pin (solid rectangle) opens that Component for editing\n in full, the same as clicking **Quick edit** next to it — a magenta\n **Own save** badge marks it while you're in it.\n- An **Adapter-mapped** pin (dashed rectangle) never opens an editor\n directly — there's no field of yours behind it. Instead it explains\n where the content comes from: which Adapter produced it, and a look at\n the actual source underneath. From there, **Edit source field** jumps\n straight to the one field that's a direct, one-to-one copy (when there\n is one), and **Edit mapping…** opens the mapping itself for a deeper\n change.\n- A **red (unresolved)** pin opens on whatever it belongs to, so you can\n see and fix why it isn't resolving.\n\nType in a docked or full editor, and the page updates within a second or\nso either way.\n\nA **Browse** toggle switches off the pins so you can click around the page\nthe way a visitor would — following links to see other pages of the same\nsite, still against your unsaved drafts.\n\n**Also on this page** lists anything the site renders that isn't part of\nthe page itself — a shared header or footer, for instance. These are\nedited and saved the same way as anything else with a pin: click **Quick\nedit** next to it, make your change, and save. Because a shared header or\nfooter isn't part of any one page, saving it doesn't publish it along with\nthe page — after saving, use the **Publish…** button that appears right\nthere to make the change live. If a site is set up to show something\nthat doesn't exist in the environment you're working in, it's listed as\n**not in this environment** — nothing to worry about, and never something\nthat stops the rest of the page from previewing normally.\n\n### Previewing a site that renders on its server\n\nSome sites build every page on their own server and send finished pages to\nthe browser, with nothing re-drawn in the browser afterwards. Live preview\ncan't hand those sites your draft directly, so it works a little\ndifferently there.\n\nYour developer sets it up once:\n\n- Under **Settings › Sites**, open the site and set its host's **Live\n preview** to **Server**.\n- Under **API Keys**, the site's key needs **Allow draft preview** turned\n on. Only a server-side key can have it.\n\nAfter that, live preview on that host behaves like this:\n\n- Composer starts a private preview session for you. Your draft, unsaved\n edits included, goes to that session, and the site's server reads it from\n there.\n- Each time you pause typing, the page reloads with your latest edits. That\n takes a moment longer than on other sites.\n- **Pins work if the site adds one script.** Out of the box a\n server-rendered site has nothing running in the browser to draw pins, and\n the panel says so — use it to edit the page and the Component it shows.\n If your developer adds ebitex's preview script to the site (a single\n `<script>` tag, and marks which part of the page shows which field), you\n get the same numbered pins and click-to-edit as any other site. Nothing\n changes for visitors: the script does nothing unless Composer is framing\n the page. Ask them for \"the ebitex preview script\" and point them at\n developers.ebitex.io.\n- Only the page you're previewing shows your draft. Follow a link and the\n other page shows what's published — and if the site runs the script,\n Composer follows you there and starts previewing that page instead.\n- If the preview says **The site loaded, but it did not read the draft**,\n what you're looking at isn't your draft. Usually the site isn't set up for\n server previews yet, its key doesn't allow draft preview, or your browser\n blocked the site's cookie inside Composer. **Open the site in a new tab**\n gets around that last one.\n- Closing live preview ends the session straight away. Nobody can use it\n afterwards.\n\n## Opening a page from the site itself\n\nWhen you're signed in to Content and browsing one of your own published sites, a small **Click to\nedit** button appears in the corner of the page. It takes you straight to that page in Composer, with\nlive preview already open.\n\nIf the page belongs to a **different organization** than the one you're currently working in, Content\nswitches for you and shows a notice saying so, with a **Switch back** button. That switch applies to\nyour whole ebitex session — Hub and Forms in other tabs will show the new organization the next time\nyou navigate in them — so the notice stays until you dismiss it.\n\nA few cases where the link won't open a page, and what each means:\n\n- **\"This page no longer exists, or belongs to an organization you are not currently signed in to.\"**\n Either the page was deleted, or it belongs to an organization you're not a member of. If a\n colleague sent you the link, ask them to add you to that organization.\n- **Nothing switches and the page doesn't load.** The site's hostname isn't mapped to a site in any\n organization you belong to. Check **Settings > Delivery** for that organization's host mappings.\n- **Two organizations claim the same hostname.** Content won't guess which one you meant. Fix the\n duplicate mapping in **Settings > Delivery**, then follow the link again.\n\n## Restricting what can go where\n\nTwo governance controls apply to a branch of the tree, the same way they\napply to Component folders (see \"Folders and access rules\" in\n[Authoring Components](components.md)) — both live in the **Configuration**\ntab's \"Access & workflow\" section:\n\n- **Access rules** grant specific roles view/edit/delete/publish on a\n branch — no rules anywhere on the branch means it's open to everyone; a\n rule anywhere on a root even restricts an entire site. A role needs view\n to see a branch at all; edit, delete, and publish are each independent\n beyond that.\n- **Allowed Templates** restricts which Templates a Presentation payload\n can use anywhere at or beneath a page — useful for keeping, say, a\n campaigns section limited to a handful of approved layouts. Leaving it\n empty allows any Template. Tightening this later never breaks a payload\n already in place; it's only checked when a payload is assigned or\n changed.\n\nBoth panels are only editable by someone with elevated access-management\npermission; everyone else sees a read-only summary of what they\npersonally can do on that branch.\n"
35
35
  },
36
36
  {
37
37
  "slug": "content-environments",
38
38
  "title": "Content environments",
39
- "body": "# Content environments\n\nBy default, your organization has one authoring space and one place published content goes live —\nyou'll never need this page if that's all you use. If you want separate spaces to draft in (a\nStaging environment you can experiment in before anything reaches Production, say), this is where\nthat's configured.\n\n## What's an environment?\n\nThere are two kinds:\n\n- **Authoring environments** are separate drafting spaces. Contracts, Templates, folders,\n Components, the Experience tree, and Audiences are all specific to whichever authoring\n environment you're currently working in — content in one is completely invisible from another,\n as if they were separate organizations.\n- **Delivery environments** are separate published targets — what the Content Delivery API actually\n serves to the outside world, and what a delivery key reads from.\n\nEvery organization starts with one of each, marked **Default**. The default is where publishing,\nnew delivery keys, and the environment switcher land when nothing more specific is chosen — you can\nchange which environment holds that role at any time (see **Managing environments** below).\n\n## Switching environments\n\nIf more than one authoring environment exists, a switcher appears in the header next to your\naccount. Pick one to start working there — every page reloads to show that environment's own\ncontent. Your choice is remembered per-organization, so it's still selected next time you sign in.\n\n## Managing environments\n\nOpen **Environments** under **Settings** in the app navigation (requires the \"Manage Environments\"\npermission — ask an Owner or administrator if it's not available to you).\n\n- **Create** a new authoring or delivery environment, give it a name. Your plan may limit how many\n environments you can have in total. A newly created environment is added to the end of its\n list.\n- **Reorder** the authoring or delivery list to whatever arrangement makes sense to your team —\n drag a row to where you want it, or use the ▲/▼ buttons on each row. While dragging, the row\n shows as a placeholder that moves to preview exactly where it'll land if you release. This sets\n the order these lists and the environment switcher use, and where a not-yet-arranged box is\n placed on the topology canvas below; once you've dragged a box on the canvas, the canvas keeps\n where you put it. (A list with only one environment has nothing to reorder against, so dragging\n is unavailable there.)\n- **Rename** any environment at any time — nothing else changes.\n- **Set as default**: on any non-default environment's row, this moves the Default badge to it and\n clears it from wherever it was. Publishing, new delivery keys, and the environment switcher's own\n default all follow immediately.\n- **Delete** any environment except the last remaining one of its kind. This is permanent and\n immediate: everything authored (or, for a delivery environment, everything published) there is\n gone, with no recovery. You'll be asked to type the environment's name to confirm. If the\n environment currently publishes to a delivery target, promotes into another environment, or is\n itself a promotion target, the confirmation names those connections — deleting still removes them\n along with everything else. The current default can't be deleted directly while another\n environment of its kind exists — set a different one as default first, then delete it.\n- **Refresh from…**: replace this environment's content wholesale from another authoring\n environment — the routine \"copy Production down into Staging\" move. See\n [environment-refresh.md](environment-refresh.md) for the full workflow, including how to rescue\n work that would otherwise be lost.\n\n### The topology canvas\n\nOne canvas shows every way your environments connect to each other. Each environment is a box with\nfour small circles — **connectors** — one on each side. Each connection is a labelled line drawn\nbetween two boxes, and every line points the same way: **content can move along the arrow**.\n\nThere are three kinds, and the legend under the canvas names all three:\n\n- **publishes to** — an authoring environment publishes to a delivery environment.\n- **promotes into** — an authoring environment can promote content into another authoring\n environment.\n- **inherited by** — an authoring environment's library is available, read-only, in another one.\n The arrow runs from the parent to the child, the same direction the content travels.\n\nAll three are routing, not content. Changing one redirects where the next publish, promote or sync\nlands; it does not move anything by itself.\n\n**Drawing a connection.** Select a connector on the environment you want to connect *from*, then a\nconnector on the one you want to connect *to*. It works the same with a mouse (click one then the\nother, or drag between them) and with the keyboard alone (<kbd>Tab</kbd> to a connector,\n<kbd>Enter</kbd>, <kbd>Tab</kbd> to another, <kbd>Enter</kbd>). <kbd>Escape</kbd> cancels at any\npoint.\n\n**The connectors you choose are the ones the line uses**, and they stay that way — moving a box\nre-routes the line between the same two connectors rather than picking different ones. Pick whichever\nsides make your topology read best; if you want a line to come in from below, connect to the bottom\nconnector and that is where it will arrive, for everyone, after every reload.\n\nConnecting two *authoring* environments is the one case the canvas can't work out on its own, since\nthere are two relationships it could mean, so it asks: **Promote {A} into {B}** or **{B} inherits\nfrom {A}**. Everything else is decided by what you connected.\n\n**A delivery environment only receives.** Its box is marked *Receives only*, and its connectors\ncan't start a connection at all — there's nothing to click or drag from. That's not a rule you'll\ndiscover by being told off after the fact; the canvas simply can't draw the line.\n\n**When something isn't allowed**, a short message appears where you dropped the connection and\nnothing is saved:\n\n- *That would create a cycle in the promotion pipeline* / *…an inheritance cycle* — content can't\n flow in a circle, directly or through a chain of other environments.\n- *Already connected* — that exact connection is already there.\n\n**A delivery environment can be published from only one authoring environment at a time.** Connect\none that's already claimed and you'll be asked to confirm reassigning it, naming the environment\nthat holds it now; confirming removes the other mapping. An authoring environment can promote into\nany number of others, and any number can promote into the same target — promotion has no such\nexclusivity. Each environment has at most one parent, so drawing an inheritance line into one that\nalready has a parent asks you to confirm replacing it — naming the parent it has **right now**,\nwhich is not always the one your page was showing if a colleague changed it while you had this open.\n\n**Removing a connection.** Select the **×** on the line's label, or **Remove** on the matching row\nin the Connections list below. Publishing and promotion lines go immediately — they're routing, and\nremoving one destroys nothing.\n\n**Removing a publishing line does not take your live site down.** Anything already published stays\npublished and keeps being served exactly as before: a published page is a finished copy held by the\ndelivery environment, not a view onto the authoring one. What stops is publishing itself — until you\ndraw the line again, you can't publish anything new to that environment or unpublish anything from\nit, and you'll be told so if you try. A delivery box in that state says *Still serving content\npublished from …* so it's clear the site is up even though nothing is connected to it.\n\nRemoving an inheritance line asks first, and explains that the content already inherited simply\nbecomes ordinary local content the child can edit: nothing is deleted.\n\n**Arranging the canvas.** Drag any box to where you want it. The arrangement is saved for your whole\norganization, so everyone sees the topology laid out the way you left it. Pan by dragging the\nbackground, zoom with the scroll wheel or the +/− buttons, and use the ⤢ button to fill the screen\n(<kbd>Escape</kbd> leaves full screen). An environment nobody has arranged yet is placed\nautomatically — authoring on the left, delivery on the right, in list order.\n\n**The Connections list** below the canvas says the same thing in words — *Live publishes to\nProduction* — grouped by the environment each connection starts from, with its own Remove on every\nrow. Use whichever you prefer; they're the same connections and the same actions.\n\nWithout the \"Manage Environments\" permission the canvas is read-only: you can pan, zoom, go full\nscreen and read the Connections list, but nothing offers to change anything.\n\n## Limiting who can use an environment\n\nBy default every member of your organization can open every authoring environment, with the role\nthey hold in the organization. That's usually what you want. When it isn't — an agency working on\none client's site, a contractor who should only see a Staging environment — you can limit a member\nto specific environments, and give them a different role in each.\n\nOpen **Environment access** at the bottom of the Environments page. Pick an environment, then choose\na member and the role they should have *in that environment*, and select **Bind member**. You can\nchange a bound member's role there at any time, or **Remove** them.\n\nThis needs the \"Assign member roles\" permission — the same one Hub uses to change a member's role —\nbecause giving someone a role in an environment is giving them that role. You also need \"View roles\",\nso the section can list the roles to choose from; if you have only one of the two, the section says\nwhich is missing.\n\n**What changes for a bound member:**\n\n- They can open **only** the environments they're bound to. The environment switcher shows just\n those, and anything that names another environment is refused.\n- In each one they have the role you chose there, not their organization role — so someone can be\n an editor in one environment and read-only in another.\n- The topology canvas is hidden from them, because it would show connections to environments they\n can't see.\n\n**Owners are never limited.** They always reach every environment with full access, so they don't\nappear in the member list and the Owner role can't be chosen.\n\n**Removing a member's last binding gives them back access to every environment** with their\norganization role — it doesn't lock them out. Having no bindings at all is the normal, unrestricted\nstate. To take someone out of Content entirely, change their role in Hub instead.\n\n**Uploaded files follow the same boundary.** Someone limited to certain environments can open an\nimage or file that's used by content in one of those environments, or that they uploaded there\nthemselves. Anything else reports as not found, exactly as a file that doesn't exist would — so they\ncan't tell what exists elsewhere. Nobody unrestricted, and no Owner, is affected.\n\n**Setting up an outside collaborator.** Give them a minimal organization role in Hub, then bind their\nreal role per environment here — **Content Author** is usually the one you want. Their organization\nrole is what applies everywhere outside Content, and the bound role is what applies inside it. See\n**Working with someone outside your team** in the Hub organizations guide for the Hub half, and\n**What roles can do in an environment** below if they should write content but not publish it.\n\n## What roles can do in an environment\n\nBeing able to open an environment isn't the same as being able to do everything in it. **What roles\ncan do here**, below Environment access on the Environments page, sets what each role may do\nthroughout one authoring environment.\n\nTick a role for **Edit**, **Delete** or **Publish**. Viewing is included automatically with any of\nthem, so there's no separate tick for it.\n\nThe part that reads backwards, so it's worth saying plainly: **an action with no ticks at all is\nunrestricted.** Anyone who can open the environment can do it. Ticking roles is what restricts an\naction to those roles, and removing the last tick for an action makes it unrestricted again — so\nclearing ticks *widens* access rather than removing it. An environment where you've never set\nanything up behaves exactly as it always has.\n\nThis is the only place that can restrict content filed outside any folder. Rules you set on a\nfolder or a page still win for that branch, so the usual shape is: restrict publishing across the\nenvironment here, then grant it back on the one section a team owns.\n\nA typical setup for a writer who shouldn't publish:\n\n1. Tick **Edit** for Content Author, so editing is restricted to roles you name — including them.\n2. Leave **Publish** ticked only for the roles that should publish. Content Author isn't one.\n3. They can now write and change content anywhere in the environment, and publish nothing.\n\nAnyone holding the \"Manage access\" permission is unaffected by these rules, so an environment can\nnever be configured into a state nobody can fix.\n\n## Promoting content\n\nPromoting copies a Component or Experience node — and everything it needs (its Contract, Template,\nany Audiences its variants reference, referenced Components, ancestor folders) — from the\nenvironment you're in into another one, ready to be worked on or published there. This is different\nfrom publishing: promoting moves *draft* content between authoring spaces; publishing takes draft\ncontent live to visitors.\n\nSelect **Promote…** on a Component or Experience node — a target is already picked for you (the\nfirst one configured, changeable from the dropdown if more than one exists), so you'll usually go\nstraight to reviewing the plan below rather than choosing first. If your current environment has no\npromotion target configured at all, **Promote…** is disabled with an explanation — set one up under\n[Managing environments](#managing-environments) first. Once a target is resolved, you'll see\neverything about to move, each marked:\n\n- **New** — doesn't exist in the target yet.\n- **Update** — already exists there, unchanged since it was last promoted; safe to overwrite.\n- **Diverged** — already exists there, but has been edited directly in the target (or promoted from\n somewhere else) since the last time this same source promoted it. You'll need to explicitly\n confirm overwriting it — nothing diverged is ever silently replaced. Whatever was there before\n stays recoverable in its own version history.\n\nContracts, Templates, Audiences, and ancestor folders/nodes always move along with the item you're\npromoting — there's no separate choice for those. Referenced Components can be unchecked\nindividually if you don't want them to move yet; a skipped reference is simply left as-is in the\ntarget, pointing at whatever (if anything) is already there. If the item you're skipping doesn't\nexist in the target at all yet, a note appears explaining that this leaves a dangling reference\nthere until it's promoted — see [Unresolved references](#unresolved-references-component-sync)\nbelow for how to find and fix one later.\n\nPromoting requires the same **Publish** permission the item's own branch requires; promoting a\nContract, Template, or Audience along with it additionally requires the permission to manage that\nkind of thing directly.\n\n### Promoting a Contract, Template, or Audience on its own\n\nA schema-only change — a field added to a Contract, an adjusted Template, a fixed Audience\ncondition — can be promoted by itself, without touching any Component that happens to use it.\nSelect **Promote…** directly from the Contract builder, the Template builder, or next to an\nAudience on the Audiences settings page. The same **New**/**Update**/**Diverged** states and\noverwrite confirmation apply; a Template's own settings Contract and a provider-contributed\nContract can't be promoted this way (promote the Template instead, or refresh/manage the provider\nregistration). This needs the permission to manage that kind of thing directly — there's no\n**Publish** branch involved, since Contracts/Templates/Audiences aren't organized into branches.\n\n## Unresolved references (Component Sync)\n\nSkipping a referenced Component during promotion (above) — or publishing a Component whose\nreference was already skipped in an earlier promotion — leaves that reference pointing at\nsomething that doesn't exist in this environment. This is allowed on purpose: it never blocks a\npromotion or a publish, and delivery itself handles it gracefully (the missing reference is simply\nomitted from what's served). But nothing else ever tells you it happened unless you go looking, so\n**Component Sync**, under **Settings** in the app navigation, lists every one currently in your\nenvironment: which Component or Experience node has the broken reference, which field it's in, and\n— where this environment has a direct upstream promotion source that still has the missing item —\nwhich environment that is.\n\nYou'll also see it called out in two other places, right where it matters: opening a Component\nwhose reference is broken shows an **Unresolved** badge in place of the usual resolved name, with a\nlink straight to its Component Sync entry; and publishing a closure that contains one shows a\nnon-blocking banner naming the affected item (publishing still proceeds — this is a heads-up, not a\nnew restriction).\n\n**To fix one:** promote the missing item forward from the environment Component Sync names — but\nthat step alone isn't enough on its own, because promoting the missing item doesn't touch the\nComponent that references it. Once the missing item exists here, **re-promote the referencing\nComponent too** (from wherever you originally promoted it), so its reference is re-checked against\nwhat's now available. After that second promotion, the entry disappears from Component Sync, the\nbadge on the Component resolves back to a normal name, and any publish banner clears.\n\n## Sharing content across environments (inheritance)\n\nPromoting is a deliberate, one-time push — good for moving a specific change from Staging to\nProduction. If instead you have content a *whole family* of environments should all draw from —\nshared design-system blocks, legal boilerplate, a common set of media Contracts — set up\ninheritance instead: link a \"Shared\" environment as the **parent** of each sibling that should\nreceive its content, and every relevant item in Shared shows up as a read-only copy in each child,\nkept up to date with a button press rather than a promotion per environment per change.\n\n**To link a parent:** draw an inheritance line on the topology canvas, from the parent to the\nchild, and choose **{child} inherits from {parent}** when the canvas asks which relationship you\nmeant. Removing that line unlinks them. The child's row also shows its current parent, as text —\nthe canvas is where you change it, so the two can never disagree. An environment can have at most\none parent, and a chain is fine (Shared → Region → Brand), but a loop is rejected.\n\n**To bring the parent's content in:** select **Sync now** on the child's row. This copies the\nparent's Contracts, Templates, Audiences, taxonomy, folders, and Components into the child,\nmarked as inherited. Running it again later picks up anything the parent has changed since —\nnew items appear, changed ones update, and anything the parent no longer has disappears from the\nchild too (unless something local in the child still depends on it, in which case the sync stops\nand tells you what's blocking it, so you can resolve that first). Nothing is ever half-applied — a\nsync either finishes completely or leaves the child exactly as it was.\n\n**Inherited items are read-only** in the child — you'll see an \"Inherited\" label on them, and any\nattempt to edit, rename, move, or delete one is refused with an explanation pointing you back to\nthe parent (or the Environments page, to unlink). You can still **publish** or **promote** an\ninherited Component from the child normally — it publishes as the child's own copy, just like\nanything else there.\n\n**Unlinking** a parent (or switching to a different one) doesn't delete anything — the child's\ncopies simply become ordinary local content you can edit freely from then on. If you relink the\nsame parent later and it now has a different version of something the child already has, syncing\nwill flag it and ask you to confirm before overwriting — your child's edit is version-recorded\nfirst, so nothing is lost even then.\n\nDeleting a parent environment automatically unlinks every child that pointed to it, the same way —\ntheir copies stay in place and become editable, nothing is deleted along with the parent.\n\n## How this affects everything else\n\nIf you never create a second environment, nothing here changes anything: the switcher never\nappears, publishing and delivery keys keep using your one delivery environment automatically, and\nthere's no promotion to do. See [publishing.md](publishing.md) for the publish lifecycle,\n[content-personalization.md](content-personalization.md) for Audiences (which, like everything else\nyou author, belong to one environment), and [content-providers.md](content-providers.md) for\ncopying a registered content provider between environments.\n"
39
+ "body": "# Content environments\n\nBy default, your organization has one authoring space and one place published content goes live —\nyou'll never need this page if that's all you use. If you want separate spaces to draft in (a\nStaging environment you can experiment in before anything reaches Production, say), this is where\nthat's configured.\n\n## What's an environment?\n\nThere are two kinds:\n\n- **Authoring environments** are separate drafting spaces. Contracts, Templates, folders,\n Components, the Experience tree, and Audiences are all specific to whichever authoring\n environment you're currently working in — content in one is completely invisible from another,\n as if they were separate organizations.\n- **Delivery environments** are separate published targets — what the Content Delivery API actually\n serves to the outside world, and what a delivery key reads from.\n\nEvery organization starts with one of each, marked **Default**. The default is where publishing,\nnew delivery keys, and the environment switcher land when nothing more specific is chosen — you can\nchange which environment holds that role at any time (see **Managing environments** below).\n\n## Switching environments\n\nIf more than one authoring environment exists, a switcher appears in the header next to your\naccount. Pick one to start working there — every page reloads to show that environment's own\ncontent. Your choice is remembered per-organization, so it's still selected next time you sign in.\n\n## Managing environments\n\nOpen **Environments** under **Settings** in the app navigation (requires the \"Manage Environments\"\npermission — ask an Owner or administrator if it's not available to you).\n\n- **Create** a new authoring or delivery environment, give it a name. Your plan limits authoring\n and delivery environments **separately**, not as one combined total — Subscriptions & Billing\n shows both, with how many you're using. A newly created environment is added to the end of its\n list.\n- **Reorder** the authoring or delivery list to whatever arrangement makes sense to your team —\n drag a row to where you want it, or use the ▲/▼ buttons on each row. While dragging, the row\n shows as a placeholder that moves to preview exactly where it'll land if you release. This sets\n the order these lists and the environment switcher use, and where a not-yet-arranged box is\n placed on the topology canvas below; once you've dragged a box on the canvas, the canvas keeps\n where you put it. (A list with only one environment has nothing to reorder against, so dragging\n is unavailable there.)\n- **Rename** any environment at any time — nothing else changes.\n- **Set as default**: on any non-default environment's row, this moves the Default badge to it and\n clears it from wherever it was. Publishing, new delivery keys, and the environment switcher's own\n default all follow immediately.\n- **Delete** any environment except the last remaining one of its kind. This is permanent and\n immediate: everything authored (or, for a delivery environment, everything published) there is\n gone, with no recovery. You'll be asked to type the environment's name to confirm. If the\n environment currently publishes to a delivery target, promotes into another environment, or is\n itself a promotion target, the confirmation names those connections — deleting still removes them\n along with everything else. The current default can't be deleted directly while another\n environment of its kind exists — set a different one as default first, then delete it.\n- **Refresh from…**: replace this environment's content wholesale from another authoring\n environment — the routine \"copy Production down into Staging\" move. See\n [environment-refresh.md](environment-refresh.md) for the full workflow, including how to rescue\n work that would otherwise be lost.\n\n### The topology canvas\n\nOne canvas shows every way your environments connect to each other. Each environment is a box with\nfour small circles — **connectors** — one on each side. Each connection is a labelled line drawn\nbetween two boxes, and every line points the same way: **content can move along the arrow**.\n\nThere are three kinds, and the legend under the canvas names all three:\n\n- **publishes to** — an authoring environment publishes to a delivery environment.\n- **promotes into** — an authoring environment can promote content into another authoring\n environment.\n- **inherited by** — an authoring environment's library is available, read-only, in another one.\n The arrow runs from the parent to the child, the same direction the content travels.\n\nAll three are routing, not content. Changing one redirects where the next publish, promote or sync\nlands; it does not move anything by itself.\n\n**Drawing a connection.** Select a connector on the environment you want to connect *from*, then a\nconnector on the one you want to connect *to*. It works the same with a mouse (click one then the\nother, or drag between them) and with the keyboard alone (<kbd>Tab</kbd> to a connector,\n<kbd>Enter</kbd>, <kbd>Tab</kbd> to another, <kbd>Enter</kbd>). <kbd>Escape</kbd> cancels at any\npoint.\n\n**The connectors you choose are the ones the line uses**, and they stay that way — moving a box\nre-routes the line between the same two connectors rather than picking different ones. Pick whichever\nsides make your topology read best; if you want a line to come in from below, connect to the bottom\nconnector and that is where it will arrive, for everyone, after every reload.\n\nConnecting two *authoring* environments is the one case the canvas can't work out on its own, since\nthere are two relationships it could mean, so it asks: **Promote {A} into {B}** or **{B} inherits\nfrom {A}**. Everything else is decided by what you connected.\n\n**A delivery environment only receives.** Its box is marked *Receives only*, and its connectors\ncan't start a connection at all — there's nothing to click or drag from. That's not a rule you'll\ndiscover by being told off after the fact; the canvas simply can't draw the line.\n\n**When something isn't allowed**, a short message appears where you dropped the connection and\nnothing is saved:\n\n- *That would create a cycle in the promotion pipeline* / *…an inheritance cycle* — content can't\n flow in a circle, directly or through a chain of other environments.\n- *Already connected* — that exact connection is already there.\n\n**A delivery environment can be published from only one authoring environment at a time.** Connect\none that's already claimed and you'll be asked to confirm reassigning it, naming the environment\nthat holds it now; confirming removes the other mapping. An authoring environment can promote into\nany number of others, and any number can promote into the same target — promotion has no such\nexclusivity. Each environment has at most one parent, so drawing an inheritance line into one that\nalready has a parent asks you to confirm replacing it — naming the parent it has **right now**,\nwhich is not always the one your page was showing if a colleague changed it while you had this open.\n\n**Removing a connection.** Select the **×** on the line's label, or **Remove** on the matching row\nin the Connections list below. Publishing and promotion lines go immediately — they're routing, and\nremoving one destroys nothing.\n\n**Removing a publishing line does not take your live site down.** Anything already published stays\npublished and keeps being served exactly as before: a published page is a finished copy held by the\ndelivery environment, not a view onto the authoring one. What stops is publishing itself — until you\ndraw the line again, you can't publish anything new to that environment or unpublish anything from\nit, and you'll be told so if you try. A delivery box in that state says *Still serving content\npublished from …* so it's clear the site is up even though nothing is connected to it.\n\nRemoving an inheritance line asks first, and explains that the content already inherited simply\nbecomes ordinary local content the child can edit: nothing is deleted.\n\n**Arranging the canvas.** Drag any box to where you want it. The arrangement is saved for your whole\norganization, so everyone sees the topology laid out the way you left it. Pan by dragging the\nbackground, zoom with the scroll wheel or the +/− buttons, and use the ⤢ button to fill the screen\n(<kbd>Escape</kbd> leaves full screen). An environment nobody has arranged yet is placed\nautomatically — authoring on the left, delivery on the right, in list order.\n\n**The Connections list** below the canvas says the same thing in words — *Live publishes to\nProduction* — grouped by the environment each connection starts from, with its own Remove on every\nrow. Use whichever you prefer; they're the same connections and the same actions.\n\nWithout the \"Manage Environments\" permission the canvas is read-only: you can pan, zoom, go full\nscreen and read the Connections list, but nothing offers to change anything.\n\n## Limiting who can use an environment\n\nBy default every member of your organization can open every authoring environment, with the role\nthey hold in the organization. That's usually what you want. When it isn't — an agency working on\none client's site, a contractor who should only see a Staging environment — you can limit a member\nto specific environments, and give them a different role in each.\n\nOpen **Environment access** at the bottom of the Environments page. Pick an environment, then choose\na member and the role they should have *in that environment*, and select **Bind member**. You can\nchange a bound member's role there at any time, or **Remove** them.\n\nThis needs the \"Assign member roles\" permission — the same one Hub uses to change a member's role —\nbecause giving someone a role in an environment is giving them that role. You also need \"View roles\",\nso the section can list the roles to choose from; if you have only one of the two, the section says\nwhich is missing.\n\n**What changes for a bound member:**\n\n- They can open **only** the environments they're bound to. The environment switcher shows just\n those, and anything that names another environment is refused.\n- In each one they have the role you chose there, not their organization role — so someone can be\n an editor in one environment and read-only in another.\n- The topology canvas is hidden from them, because it would show connections to environments they\n can't see.\n\n**Owners are never limited.** They always reach every environment with full access, so they don't\nappear in the member list and the Owner role can't be chosen.\n\n**Removing a member's last binding gives them back access to every environment** with their\norganization role — it doesn't lock them out. Having no bindings at all is the normal, unrestricted\nstate. To take someone out of Content entirely, change their role in Hub instead.\n\n**Uploaded files follow the same boundary.** Someone limited to certain environments can open an\nimage or file that's used by content in one of those environments, or that they uploaded there\nthemselves. Anything else reports as not found, exactly as a file that doesn't exist would — so they\ncan't tell what exists elsewhere. Nobody unrestricted, and no Owner, is affected.\n\n**Setting up an outside collaborator.** Give them a minimal organization role in Hub, then bind their\nreal role per environment here — **Content Author** is usually the one you want. Their organization\nrole is what applies everywhere outside Content, and the bound role is what applies inside it. See\n**Working with someone outside your team** in the Hub organizations guide for the Hub half, and\n**What roles can do in an environment** below if they should write content but not publish it.\n\n## What roles can do in an environment\n\nBeing able to open an environment isn't the same as being able to do everything in it. **What roles\ncan do here**, below Environment access on the Environments page, sets what each role may do\nthroughout one authoring environment.\n\nTick a role for **Edit**, **Delete** or **Publish**. Viewing is included automatically with any of\nthem, so there's no separate tick for it.\n\nThe part that reads backwards, so it's worth saying plainly: **an action with no ticks at all is\nunrestricted.** Anyone who can open the environment can do it. Ticking roles is what restricts an\naction to those roles, and removing the last tick for an action makes it unrestricted again — so\nclearing ticks *widens* access rather than removing it. An environment where you've never set\nanything up behaves exactly as it always has.\n\nThis is the only place that can restrict content filed outside any folder. Rules you set on a\nfolder or a page still win for that branch, so the usual shape is: restrict publishing across the\nenvironment here, then grant it back on the one section a team owns.\n\nA typical setup for a writer who shouldn't publish:\n\n1. Tick **Edit** for Content Author, so editing is restricted to roles you name — including them.\n2. Leave **Publish** ticked only for the roles that should publish. Content Author isn't one.\n3. They can now write and change content anywhere in the environment, and publish nothing.\n\nAnyone holding the \"Manage access\" permission is unaffected by these rules, so an environment can\nnever be configured into a state nobody can fix.\n\n## Promoting content\n\nPromoting copies a Component or Experience node — and everything it needs (its Contract, Template,\nany Audiences its variants reference, referenced Components, ancestor folders) — from the\nenvironment you're in into another one, ready to be worked on or published there. This is different\nfrom publishing: promoting moves *draft* content between authoring spaces; publishing takes draft\ncontent live to visitors.\n\nSelect **Promote…** on a Component or Experience node — a target is already picked for you (the\nfirst one configured, changeable from the dropdown if more than one exists), so you'll usually go\nstraight to reviewing the plan below rather than choosing first. If your current environment has no\npromotion target configured at all, **Promote…** is disabled with an explanation — set one up under\n[Managing environments](#managing-environments) first. Once a target is resolved, you'll see\neverything about to move, each marked:\n\n- **New** — doesn't exist in the target yet.\n- **Update** — already exists there, unchanged since it was last promoted; safe to overwrite.\n- **Diverged** — already exists there, but has been edited directly in the target (or promoted from\n somewhere else) since the last time this same source promoted it. You'll need to explicitly\n confirm overwriting it — nothing diverged is ever silently replaced. Whatever was there before\n stays recoverable in its own version history.\n\nContracts, Templates, Audiences, and ancestor folders/nodes always move along with the item you're\npromoting — there's no separate choice for those. Referenced Components can be unchecked\nindividually if you don't want them to move yet; a skipped reference is simply left as-is in the\ntarget, pointing at whatever (if anything) is already there. If the item you're skipping doesn't\nexist in the target at all yet, a note appears explaining that this leaves a dangling reference\nthere until it's promoted — see [Unresolved references](#unresolved-references-component-sync)\nbelow for how to find and fix one later.\n\nPromoting requires the same **Publish** permission the item's own branch requires; promoting a\nContract, Template, or Audience along with it additionally requires the permission to manage that\nkind of thing directly.\n\n### Promoting a Contract, Template, or Audience on its own\n\nA schema-only change — a field added to a Contract, an adjusted Template, a fixed Audience\ncondition — can be promoted by itself, without touching any Component that happens to use it.\nSelect **Promote…** directly from the Contract builder, the Template builder, or next to an\nAudience on the Audiences settings page. The same **New**/**Update**/**Diverged** states and\noverwrite confirmation apply; a Template's own settings Contract and a provider-contributed\nContract can't be promoted this way (promote the Template instead, or refresh/manage the provider\nregistration). This needs the permission to manage that kind of thing directly — there's no\n**Publish** branch involved, since Contracts/Templates/Audiences aren't organized into branches.\n\n## Unresolved references (Component Sync)\n\nSkipping a referenced Component during promotion (above) — or publishing a Component whose\nreference was already skipped in an earlier promotion — leaves that reference pointing at\nsomething that doesn't exist in this environment. This is allowed on purpose: it never blocks a\npromotion or a publish, and delivery itself handles it gracefully (the missing reference is simply\nomitted from what's served). But nothing else ever tells you it happened unless you go looking, so\n**Component Sync**, under **Settings** in the app navigation, lists every one currently in your\nenvironment: which Component or Experience node has the broken reference, which field it's in, and\n— where this environment has a direct upstream promotion source that still has the missing item —\nwhich environment that is.\n\nYou'll also see it called out in two other places, right where it matters: opening a Component\nwhose reference is broken shows an **Unresolved** badge in place of the usual resolved name, with a\nlink straight to its Component Sync entry; and publishing a closure that contains one shows a\nnon-blocking banner naming the affected item (publishing still proceeds — this is a heads-up, not a\nnew restriction).\n\n**To fix one:** promote the missing item forward from the environment Component Sync names — but\nthat step alone isn't enough on its own, because promoting the missing item doesn't touch the\nComponent that references it. Once the missing item exists here, **re-promote the referencing\nComponent too** (from wherever you originally promoted it), so its reference is re-checked against\nwhat's now available. After that second promotion, the entry disappears from Component Sync, the\nbadge on the Component resolves back to a normal name, and any publish banner clears.\n\n## Sharing content across environments (inheritance)\n\nPromoting is a deliberate, one-time push — good for moving a specific change from Staging to\nProduction. If instead you have content a *whole family* of environments should all draw from —\nshared design-system blocks, legal boilerplate, a common set of media Contracts — set up\ninheritance instead: link a \"Shared\" environment as the **parent** of each sibling that should\nreceive its content, and every relevant item in Shared shows up as a read-only copy in each child,\nkept up to date with a button press rather than a promotion per environment per change.\n\n**To link a parent:** draw an inheritance line on the topology canvas, from the parent to the\nchild, and choose **{child} inherits from {parent}** when the canvas asks which relationship you\nmeant. Removing that line unlinks them. The child's row also shows its current parent, as text —\nthe canvas is where you change it, so the two can never disagree. An environment can have at most\none parent, and a chain is fine (Shared → Region → Brand), but a loop is rejected.\n\n**To bring the parent's content in:** select **Sync now** on the child's row. This copies the\nparent's Contracts, Templates, Audiences, taxonomy, folders, and Components into the child,\nmarked as inherited. Running it again later picks up anything the parent has changed since —\nnew items appear, changed ones update, and anything the parent no longer has disappears from the\nchild too (unless something local in the child still depends on it, in which case the sync stops\nand tells you what's blocking it, so you can resolve that first). Nothing is ever half-applied — a\nsync either finishes completely or leaves the child exactly as it was.\n\n**Inherited items are read-only** in the child — you'll see an \"Inherited\" label on them, and any\nattempt to edit, rename, move, or delete one is refused with an explanation pointing you back to\nthe parent (or the Environments page, to unlink). You can still **publish** or **promote** an\ninherited Component from the child normally — it publishes as the child's own copy, just like\nanything else there.\n\n**Unlinking** a parent (or switching to a different one) doesn't delete anything — the child's\ncopies simply become ordinary local content you can edit freely from then on. If you relink the\nsame parent later and it now has a different version of something the child already has, syncing\nwill flag it and ask you to confirm before overwriting — your child's edit is version-recorded\nfirst, so nothing is lost even then.\n\nDeleting a parent environment automatically unlinks every child that pointed to it, the same way —\ntheir copies stay in place and become editable, nothing is deleted along with the parent.\n\n## How this affects everything else\n\nIf you never create a second environment, nothing here changes anything: the switcher never\nappears, publishing and delivery keys keep using your one delivery environment automatically, and\nthere's no promotion to do. See [publishing.md](publishing.md) for the publish lifecycle,\n[content-personalization.md](content-personalization.md) for Audiences (which, like everything else\nyou author, belong to one environment), and [content-providers.md](content-providers.md) for\ncopying a registered content provider between environments.\n"
40
40
  },
41
41
  {
42
42
  "slug": "content-links",
@@ -66,7 +66,7 @@ export const HELP_TOPICS = [
66
66
  {
67
67
  "slug": "content-workflow",
68
68
  "title": "Editorial workflow",
69
- "body": "# Editorial workflow\n\nA workflow adds a review step in front of publishing: assign one to a folder or a section of your\nExperience tree, and content there can't go live until someone carries it through the review states\nyou've defined. Nothing changes anywhere you haven't assigned a workflow — publishing works exactly\nas it always has.\n\n## Creating a workflow\n\nOpen **Workflow** under **Configure** in the app navigation and choose **New workflow**. First pick\nthe workflow's **kind** — what this workflow governs. It can't be changed after creation:\n\n- **Publishing workflow** — governs a Component or page: Draft → your review steps → Approved,\n where Approved is the only state publishing is allowed from.\n- **Translation workflow** — governs a translation job's proposed values before they're written\n into the Component. See [Translation jobs](translation-jobs.md) for how to kick one off and\n review its results.\n- **Proposal review** — governs content offered from outside your organization, by a form or by\n another system, before any of it becomes a Component. See [Proposals](proposals.md).\n\nA workflow's states come from its kind, and each state's meaning is fixed — shown on the node as\nbadges and a one-line description, never as switches you configure:\n\n- **Anchor states** (marked STATE · ANCHOR) are placed for you and can't be deleted or renamed —\n for a publishing workflow, **Draft** (where authors work freely) and **Approved** (locked, and\n the one publishable state).\n- **Step templates** are the states you add yourself, as many as you need: a **Review step**\n (content is locked while the reviewer decides) or a **Rework step** (back with the author,\n editable again). The name is yours — add two Review steps called \"Editorial review\" and \"Legal\n review\" for a two-stage approval, each with its own approver role on its transition.\n\nGive the workflow a name, then wire the graph:\n\n- **Add a step**: **+ Add node**, pick a step template, and type its name on the node.\n- **Connect two states into a transition**: every state has a small connector on each of its four\n sides — click one, then click a connector on the state you want to connect it to (or drag from\n one to the other). Click the new transition's label to name it and, optionally, restrict who may\n fire it to specific role ids (find a role's id on Hub's Roles page) — leave it blank to let any\n organization member fire it. A state without any wiring simply never occurs — there's no way to\n reach it. A state whose outcome ends the flow — a translation workflow's **Approved** and\n **Rejected** — still shows all four of its connectors, but only to receive an *incoming*\n transition: there's nothing to drag or click to start one from it, since it can never be the\n source of an outgoing transition. (A publishing workflow has no such state — even **Approved**\n can have an outgoing transition, such as a \"Revert to draft\" step, if you wire one.)\n- Every state shows how many items are **currently sitting in it** — a live count that updates as\n people submit, approve, and reject.\n\nOpen an existing workflow from the list to edit its graph the same way. A structural change (adding\nor removing states or transitions) is blocked while any item has an active review in progress — the\nerror explains this; renaming the workflow and editing attached actions (below) are always allowed\nregardless.\n\n## Attaching a Notify or Webhook to a state or transition\n\nBeyond states and transitions, the canvas offers two action node kinds via the same **+ Add node**\nmenu:\n\n- **Notify** — pick a channel (email or in-app) and one or more recipients. **This doesn't send\n anything yet** — no notification channel is configured for this organization. The attempt is still\n recorded (see Activity Log below), so you can see exactly when it *would* have fired once sending\n is available.\n- **Webhook** — a URL your own system controls. This one is real: it actually `POST`s the transition\n details to that URL. A URL that resolves to a private or internal address is rejected when you try\n to save it.\n\nAttach either one to a **state** (fires the moment an item enters that state — click one of the\naction's own connectors, then one of the state's) or to a **transition** (fires the moment that\ntransition is used — click the action's connector, then the transition's own label). An action must\nbe attached to something before you can save. A Notify or Webhook never blocks the review itself —\neven if a webhook fails, the transition still goes through; the failure is just recorded.\n\n\"Enters that state\" means however it got there, including when nobody was involved. A review that\nstarts on its own — a translation job finishing, or a proposal arriving from a form or another\nsystem — fires whatever is attached to the state it starts in, and anything attached to a step the\nworkflow takes automatically after that. That is usually the point of attaching one: nobody is\nwatching when a proposal arrives, which is exactly why you want to be told. A Webhook fired this way\nsays so in its payload (`\"runStarted\": true`), since there was no transition and no previous state\nto name.\n\n## Assigning a workflow to a branch\n\nOpen a folder's (or an Experience node's) **governance panel** — the same place you manage access\nrules — and find the **Editorial workflow** section. Choose a workflow from the dropdown, or:\n\n- **Inherit from ancestor** — use whatever the nearest parent branch has assigned (or nothing, if\n none does). This is the default for every branch.\n- **None (explicit)** — opt this branch and everything beneath it out of review, even if a parent\n branch has a workflow assigned. Useful for a sub-folder that should publish freely while the rest\n of the section stays gated.\n\n### One assignment per kind\n\nA branch carries a separate assignment for each kind, so a folder can be gated for publishing,\ngated for proposals, and ungoverned for translation all at once. Each has its own picker, and each\ninherits down the tree independently:\n\n- **Editorial workflow** — on folders and on Experience nodes.\n- **Proposal review** and **Translation review** — on folders only, since both are resolved from\n the folder an item lives in and neither has anything to do with a page's address.\n\nA kind's picker only appears once you have at least one workflow of that kind, which is why a folder\nyou have never used proposals on shows just the one section.\n\n**What \"none\" means differs by kind**, and each picker says which:\n\n| Kind | With no workflow assigned |\n|---|---|\n| Editorial workflow | Content publishes without review |\n| Proposal review | Offers to that folder are **refused** — there would be nobody to review them |\n| Translation review | Translation jobs apply their translations without review |\n\n## Submitting and reviewing\n\nOpen a Component (under its **Settings** tab) or an Experience node under a governed branch and\nyou'll see a workflow panel showing its current state. If it's still in a non-publishable state,\nthe **Publish** button — always visible in the Component editor's header, regardless of which tab\nyou're on — is disabled and explains why.\n\nSelect an available transition (e.g. **Submit for review**), optionally add a comment, and confirm.\nWhile an item sits in a **Review step** or in **Approved**, its content is locked — what was\nreviewed is exactly what publishes. If a reviewer sends it to a **Rework step**, it's editable\nagain while the review stays open; the review tracks the version you submitted, and if you edit\nduring rework, the panel tells you the item has moved past the reviewed version.\n\nOnce it reaches a publishable state, **Publish** works as normal — it publishes the reviewed\nversion and marks the review complete. If someone edited the item after submission, it will show as\n\"Modified since publish\" immediately, since the head and the published version now differ — that's\nexpected, not an error.\n\nA reviewer sees the same panel with **Approve**/**Reject** buttons (only the transitions their role\nis allowed to perform are enabled). Rejecting sends it back to the start with the reviewer's comment\nattached, and it can be resubmitted. Resubmitting while a review is already in progress starts a\nfresh one, pinned to your latest version.\n\nYou (or anyone with access-management permission) can cancel an in-progress review from the same\npanel.\n\n## Permissions\n\nCreating, renaming, and deleting workflow definitions requires its own \"Manage Content workflows\"\npermission. Assigning a workflow to a branch is governed by the same permission as access rules\n(\"Manage access\"), since it's branch governance, not workflow authoring. Submitting for review\nrequires edit access on the branch; approving/rejecting is limited to whichever role(s) the\ntransition names (or anyone, if none are named) — an access-management holder can always advance a\nstuck review.\n\n## Activity Log\n\nEvery submission, approval, rejection, and cancellation appears in Hub's Activity Log with the\nactor and any comment attached — the review trail is part of your organization's audit history.\nAttached Notify and Webhook actions appear there too, one entry per attempt: a Webhook shows the URL\nand the response it got back (or that it failed); a Notify always shows \"not delivered (no\nnotification channel configured)\" — the reminder that it's recorded, not sent, until this\norganization has a notification channel set up.\n"
69
+ "body": "# Editorial workflow\n\nA workflow adds a review step in front of publishing: assign one to a folder or a section of your\nExperience tree, and content there can't go live until someone carries it through the review states\nyou've defined. Nothing changes anywhere you haven't assigned a workflow — publishing works exactly\nas it always has.\n\n## Creating a workflow\n\nOpen **Workflow** under **Configure** in the app navigation and choose **New workflow**. First pick\nthe workflow's **kind** — what this workflow governs. It can't be changed after creation:\n\n- **Publishing workflow** — governs a Component or page: Draft → your review steps → Approved,\n where Approved is the only state publishing is allowed from.\n- **Translation workflow** — governs a translation job's proposed values before they're written\n into the Component. See [Translation jobs](translation-jobs.md) for how to kick one off and\n review its results.\n- **Proposal review** — governs content offered from outside your organization, by a form or by\n another system, before any of it becomes a Component. See [Proposals](proposals.md).\n\nA workflow's states come from its kind, and each state's meaning is fixed — shown on the node as\nbadges and a one-line description, never as switches you configure:\n\n- **Anchor states** (marked STATE · ANCHOR) are placed for you and can't be deleted or renamed —\n for a publishing workflow, **Draft** (where authors work freely) and **Approved** (locked, and\n the one publishable state).\n- **Step templates** are the states you add yourself, as many as you need: a **Review step**\n (content is locked while the reviewer decides) or a **Rework step** (back with the author,\n editable again). The name is yours — add two Review steps called \"Editorial review\" and \"Legal\n review\" for a two-stage approval, each with its own approver role on its transition.\n\nGive the workflow a name, then wire the graph:\n\n- **Add a step**: **+ Add node**, pick a step template, and type its name on the node.\n- **Connect two states into a transition**: every state has a small connector on each of its four\n sides — click one, then click a connector on the state you want to connect it to (or drag from\n one to the other). Click the new transition's label to name it and, optionally, restrict who may\n fire it to specific role ids (find a role's id on Hub's Roles page) — leave it blank to let any\n organization member fire it. A state without any wiring simply never occurs — there's no way to\n reach it. A state whose outcome ends the flow — a translation workflow's **Approved** and\n **Rejected** — still shows all four of its connectors, but only to receive an *incoming*\n transition: there's nothing to drag or click to start one from it, since it can never be the\n source of an outgoing transition. (A publishing workflow has no such state — even **Approved**\n can have an outgoing transition, such as a \"Revert to draft\" step, if you wire one.)\n- Every state shows how many items are **currently sitting in it** — a live count that updates as\n people submit, approve, and reject.\n\nOpen an existing workflow from the list to edit its graph the same way. A structural change (adding\nor removing states or transitions) is blocked while any item has an active review in progress — the\nerror explains this; renaming the workflow and editing attached actions (below) are always allowed\nregardless.\n\n## Attaching a Notify or Webhook to a state or transition\n\nBeyond states and transitions, the canvas offers two action node kinds via the same **+ Add node**\nmenu:\n\n- **Notify** — pick a channel (email or in-app) and one or more recipients. **This doesn't send\n anything yet** — no notification channel is configured for this organization. The attempt is still\n recorded (see Activity Log below), so you can see exactly when it *would* have fired once sending\n is available.\n- **Webhook** — a URL your own system controls. This one is real: it actually `POST`s the transition\n details to that URL. A URL that resolves to a private or internal address is rejected when you try\n to save it. You can also set a **signing secret**, so the system receiving the request can prove it\n came from us — see **Making sure a webhook really came from us**, below.\n\nAttach either one to a **state** (fires the moment an item enters that state — click one of the\naction's own connectors, then one of the state's) or to a **transition** (fires the moment that\ntransition is used — click the action's connector, then the transition's own label). An action must\nbe attached to something before you can save. A Notify or Webhook never blocks the review itself —\neven if a webhook fails, the transition still goes through; the failure is just recorded.\n\n\"Enters that state\" means however it got there, including when nobody was involved. A review that\nstarts on its own — a translation job finishing, or a proposal arriving from a form or another\nsystem — fires whatever is attached to the state it starts in, and anything attached to a step the\nworkflow takes automatically after that. That is usually the point of attaching one: nobody is\nwatching when a proposal arrives, which is exactly why you want to be told. A Webhook fired this way\nsays so in two places: its event type is `content.workflow.runStarted` rather than\n`content.workflow.transitioned`, and `\"runStarted\": true` appears in the payload — because there was\nno transition and no previous state to name.\n\n## Making sure a webhook really came from us\n\nA webhook is an ordinary `POST` to a URL you chose, so anyone who learns that URL could send one.\nSetting a **signing secret** on the Webhook node closes that: we sign every request with it, and your\nsystem can check the signature before trusting anything in the body.\n\nLeave the secret blank and requests are sent unsigned, exactly as before — nothing you have already\nset up changes.\n\nThe secret is write-only. Once saved, the node shows **Configured** rather than the value, and we\nnever send it back to your browser. To change it, select **Replace** and enter a new one; to stop\nsigning, select **Replace** and save with the field empty. Editing anything else about the workflow\nleaves the secret alone.\n\nChanging the destination URL does **not** carry the secret over, deliberately — a different URL is a\ndifferent system, and it should get its own secret rather than inheriting one silently.\n\nEvery request carries two headers:\n\n```\nX-Ebitex-Signature: v1,t=1790000591,s=<signature>\nX-Ebitex-Delivery: whd_0123456789abcdef0123456789abcdef\n```\n\nYour system should recompute the signature over the exact bytes it received and compare. The full\nrecipe, with worked examples in several languages, is on our developer site — see\n[developers.ebitex.io](https://developers.ebitex.io). Two things that catch people out: sign the raw\nbody you received rather than re-encoding it first, and compare using a constant-time comparison\nrather than `==`.\n\n`X-Ebitex-Delivery` identifies one delivery. If we retry after a failure, the retry carries the same\nid, so your system can recognise it as a repeat rather than a second event. Use it to ignore\nduplicates.\n\n## Assigning a workflow to a branch\n\nOpen a folder's (or an Experience node's) **governance panel** — the same place you manage access\nrules — and find the **Editorial workflow** section. Choose a workflow from the dropdown, or:\n\n- **Inherit from ancestor** — use whatever the nearest parent branch has assigned (or nothing, if\n none does). This is the default for every branch.\n- **None (explicit)** — opt this branch and everything beneath it out of review, even if a parent\n branch has a workflow assigned. Useful for a sub-folder that should publish freely while the rest\n of the section stays gated.\n\n### One assignment per kind\n\nA branch carries a separate assignment for each kind, so a folder can be gated for publishing,\ngated for proposals, and ungoverned for translation all at once. Each has its own picker, and each\ninherits down the tree independently:\n\n- **Editorial workflow** — on folders and on Experience nodes.\n- **Proposal review** and **Translation review** — on folders only, since both are resolved from\n the folder an item lives in and neither has anything to do with a page's address.\n\nA kind's picker only appears once you have at least one workflow of that kind, which is why a folder\nyou have never used proposals on shows just the one section.\n\n**What \"none\" means differs by kind**, and each picker says which:\n\n| Kind | With no workflow assigned |\n|---|---|\n| Editorial workflow | Content publishes without review |\n| Proposal review | Offers to that folder are **refused** — there would be nobody to review them |\n| Translation review | Translation jobs apply their translations without review |\n\n## Submitting and reviewing\n\nOpen a Component (under its **Settings** tab) or an Experience node under a governed branch and\nyou'll see a workflow panel showing its current state. If it's still in a non-publishable state,\nthe **Publish** button — always visible in the Component editor's header, regardless of which tab\nyou're on — is disabled and explains why.\n\nSelect an available transition (e.g. **Submit for review**), optionally add a comment, and confirm.\nWhile an item sits in a **Review step** or in **Approved**, its content is locked — what was\nreviewed is exactly what publishes. If a reviewer sends it to a **Rework step**, it's editable\nagain while the review stays open; the review tracks the version you submitted, and if you edit\nduring rework, the panel tells you the item has moved past the reviewed version.\n\nOnce it reaches a publishable state, **Publish** works as normal — it publishes the reviewed\nversion and marks the review complete. If someone edited the item after submission, it will show as\n\"Modified since publish\" immediately, since the head and the published version now differ — that's\nexpected, not an error.\n\nA reviewer sees the same panel with **Approve**/**Reject** buttons (only the transitions their role\nis allowed to perform are enabled). Rejecting sends it back to the start with the reviewer's comment\nattached, and it can be resubmitted. Resubmitting while a review is already in progress starts a\nfresh one, pinned to your latest version.\n\nYou (or anyone with access-management permission) can cancel an in-progress review from the same\npanel.\n\n## Permissions\n\nCreating, renaming, and deleting workflow definitions requires its own \"Manage Content workflows\"\npermission. Assigning a workflow to a branch is governed by the same permission as access rules\n(\"Manage access\"), since it's branch governance, not workflow authoring. Submitting for review\nrequires edit access on the branch; approving/rejecting is limited to whichever role(s) the\ntransition names (or anyone, if none are named) — an access-management holder can always advance a\nstuck review.\n\n## Activity Log\n\nEvery submission, approval, rejection, and cancellation appears in Hub's Activity Log with the\nactor and any comment attached — the review trail is part of your organization's audit history.\nAttached Notify and Webhook actions appear there too, one entry per attempt: a Webhook shows the URL\nand the response it got back (or that it failed); a Notify always shows \"not delivered (no\nnotification channel configured)\" — the reminder that it's recorded, not sent, until this\norganization has a notification channel set up.\n"
70
70
  },
71
71
  {
72
72
  "slug": "contracts",
@@ -81,7 +81,7 @@ export const HELP_TOPICS = [
81
81
  {
82
82
  "slug": "export-import",
83
83
  "title": "Export and import",
84
- "body": "# Export and import\n\nPromotion (see [Content environments](content-environments.md)) moves content one direction along\na configured pipeline. Export and import is the general-purpose alternative: take a portable copy\nof something and bring it into any authoring environment — the same organization or a different\none, with or without a promotion pipeline set up between them.\n\nUse this for:\n\n- **Moving content backward** (\"demote\") — content edited in a downstream environment, brought\n back to where it came from.\n- **Copying between environments with no pipeline configured**, or **between organizations**.\n- **Backing up** a Contract, Template, page, or Component, or **seeding** a fresh environment with\n a starting set of content.\n\n## Exporting\n\nOn a Contract, Template, page, Component, Audience, or Adapter's own editor, look for the\n**Export…** button (next to Promote, where that's also available).\n\nExporting shows you everything that will be included — the item itself plus everything it depends\non (its Contract, any Templates it uses, referenced Audiences, and so on) — before you commit to\nanything. Check **Portable** if you're exporting to a different organization and the content\nincludes images or other files; this packages those files' bytes along with the content so they\ndon't arrive broken. Leave it unchecked for a same-organization export — the files are already\nvisible everywhere in your organization regardless of environment.\n\nClick **Export** to produce a bundle file, then **Download bundle file** to save it.\n\n## Importing\n\nOpen **Transfer** under **Tools** in the app navigation, then **Upload bundle file…** to stage a\nbundle you've downloaded (or received from someone else). Once staged, click **Import…** next to\nit.\n\nYou'll be asked to choose:\n\n- **Preserve identity** — items keep the same identity they had when exported. Use this for a\n same-organization import; it's also what makes a \"demote\" work cleanly, since the item you bring\n back is recognized as the same one you'll later send forward again.\n- **Fresh identity** — every item gets a brand-new identity, guaranteed not to collide with\n anything. Required when importing into a different organization than the one the bundle came\n from.\n\nThe import plan then shows each item's state:\n\n- **New** — doesn't exist here yet, will be created.\n- **Identical** — already here, exactly matching — nothing changes.\n- **Conflict** — already exists here with *different* content. You'll need to check a box\n confirming you want the bundle's version to replace what's here. (The version being replaced is\n saved first, so it isn't lost — see the item's own version history afterward if you need it\n back.)\n\nA bundle imports as a whole — you can't pick and choose individual items partway through (do that\nat export time instead, by choosing a narrower starting point). Click **Import** to apply it.\n\nA large bundle can take a while, and the button counts items off as they're applied. The import runs\non the server rather than in this browser tab, so it keeps going if you close the dialog or reload\nthe page — reopening it picks the same import back up and carries on showing progress. If something\ndoes go wrong, nothing is left half-applied: the whole import is undone, and the reason appears next\nto the **Import** button.\n\n### Plan limits\n\nYour plan limits how many components, pages and categories your organization can have, counted\nacross all of its authoring environments. An import that would take you past one of those limits is\nrefused before anything is written, and the message says which limit and by how much. The import\nplan warns you about this before you click **Import**.\n\nOnly the items an import *creates* count. Importing a bundle that only updates content you already\nhave is never refused for this, even if you are over a limit.\n\nPromoting content, syncing an environment from its parent, and refreshing an environment are never\nrefused for this reason either. They copy content your organization already has, and being unable to\npromote to production would be worse than going over. If one of them takes you over a limit, you can\nkeep editing, but you can't create more of that kind of item until you upgrade or remove some.\n\n## Staged bundles\n\nThe Transfer page lists every bundle you've exported or uploaded. From there you can download a\nbundle again, re-run its import, or delete it once you're done with it. An ordinary export expires\nautomatically after 30 days; delete it sooner if you're finished with it.\n\n## What travels in a bundle, and what doesn't\n\nA bundle carries the *current* state of what you selected — the live content, not its full edit\nhistory. It does **not** carry: published copies (the destination publishes on its own schedule),\nin-progress workflow reviews, delivery keys or host mappings (those belong to the environment\nitself, not its content), or activity history.\n"
84
+ "body": "# Export and import\n\nPromotion (see [Content environments](content-environments.md)) moves content one direction along\na configured pipeline. Export and import is the general-purpose alternative: take a portable copy\nof something and bring it into any authoring environment — the same organization or a different\none, with or without a promotion pipeline set up between them.\n\nUse this for:\n\n- **Moving content backward** (\"demote\") — content edited in a downstream environment, brought\n back to where it came from.\n- **Copying between environments with no pipeline configured**, or **between organizations**.\n- **Backing up** a Contract, Template, page, or Component, or **seeding** a fresh environment with\n a starting set of content.\n\n## Exporting\n\nOn a Contract, Template, page, Component, Audience, or Adapter's own editor, look for the\n**Export…** button (next to Promote, where that's also available).\n\nExporting shows you everything that will be included — the item itself plus everything it depends\non (its Contract, any Templates it uses, referenced Audiences, and so on) — before you commit to\nanything. Check **Portable** if you're exporting to a different organization and the content\nincludes images or other files; this packages those files' bytes along with the content so they\ndon't arrive broken. Leave it unchecked for a same-organization export — the files are already\nvisible everywhere in your organization regardless of environment.\n\nClick **Export** to produce a bundle file, then **Download bundle file** to save it.\n\n## Importing\n\nOpen **Transfer** under **Tools** in the app navigation, then **Upload bundle file…** to stage a\nbundle you've downloaded (or received from someone else). Once staged, click **Import…** next to\nit.\n\nYou'll be asked to choose:\n\n- **Preserve identity** — items keep the same identity they had when exported. Use this for a\n same-organization import; it's also what makes a \"demote\" work cleanly, since the item you bring\n back is recognized as the same one you'll later send forward again.\n- **Fresh identity** — every item gets a brand-new identity, guaranteed not to collide with\n anything. Required when importing into a different organization than the one the bundle came\n from.\n\nThe import plan then shows each item's state:\n\n- **New** — doesn't exist here yet, will be created.\n- **Identical** — already here, exactly matching — nothing changes.\n- **Conflict** — already exists here with *different* content. You'll need to check a box\n confirming you want the bundle's version to replace what's here. (The version being replaced is\n saved first, so it isn't lost — see the item's own version history afterward if you need it\n back.)\n\nA bundle imports as a whole — you can't pick and choose individual items partway through (do that\nat export time instead, by choosing a narrower starting point). Click **Import** to apply it.\n\nA large bundle can take a while, and the button counts items off as they're applied. The import runs\non the server rather than in this browser tab, so it keeps going if you close the dialog or reload\nthe page — reopening it picks the same import back up and carries on showing progress. If something\ndoes go wrong, nothing is left half-applied: the whole import is undone, and the reason appears next\nto the **Import** button.\n\n### Plan limits\n\nYour plan limits how many components, pages and categories your organization can have, counted\nacross all of its authoring environments. **Organizations > Subscriptions & Billing** shows each\nlimit and how much of it you're using. An import that would take you past one of those limits is\nrefused before anything is written, and the message says which limit and by how much. The import\nplan warns you about this before you click **Import**.\n\nOnly the items an import *creates* count. Importing a bundle that only updates content you already\nhave is never refused for this, even if you are over a limit.\n\nPromoting content, syncing an environment from its parent, and refreshing an environment are never\nrefused for this reason either. They copy content your organization already has, and being unable to\npromote to production would be worse than going over. If one of them takes you over a limit, you can\nkeep editing, but you can't create more of that kind of item until you upgrade or remove some.\n\n## Staged bundles\n\nThe Transfer page lists every bundle you've exported or uploaded. From there you can download a\nbundle again, re-run its import, or delete it once you're done with it. An ordinary export expires\nautomatically after 30 days; delete it sooner if you're finished with it.\n\n## What travels in a bundle, and what doesn't\n\nA bundle carries the *current* state of what you selected — the live content, not its full edit\nhistory. It does **not** carry: published copies (the destination publishes on its own schedule),\nin-progress workflow reviews, delivery keys or host mappings (those belong to the environment\nitself, not its content), or activity history.\n"
85
85
  },
86
86
  {
87
87
  "slug": "locale-addressing",
@@ -1 +1 @@
1
- {"version":3,"file":"helpCorpus.generated.js","sourceRoot":"","sources":["../../src/resources/helpCorpus.generated.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,kGAAkG;AAClG,oGAAoG;AAIpG,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,0CAA0C;QACnD,MAAM,EAAE,knWAAknW;KAC3nW;IACD;QACE,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,wnGAAwnG;KACjoG;IACD;QACE,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EAAE,igVAAigV;KAC1gV;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,kCAAkC;QAC3C,MAAM,EAAE,6okBAA6okB;KACtpkB;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,0BAA0B;QACnC,MAAM,EAAE,6oLAA6oL;KACtpL;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,gCAAgC;QACzC,MAAM,EAAE,sxeAAsxe;KAC/xe;IACD;QACE,MAAM,EAAE,sBAAsB;QAC9B,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EAAE,mxqBAAmxqB;KAC5xqB;IACD;QACE,MAAM,EAAE,eAAe;QACvB,OAAO,EAAE,qCAAqC;QAC9C,MAAM,EAAE,q3FAAq3F;KAC93F;IACD;QACE,MAAM,EAAE,yBAAyB;QACjC,OAAO,EAAE,4BAA4B;QACrC,MAAM,EAAE,2jRAA2jR;KACpkR;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,6/HAA6/H;KACtgI;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,4CAA4C;QACrD,MAAM,EAAE,22GAA22G;KACp3G;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,UAAU;QACnB,MAAM,EAAE,wvJAAwvJ;KACjwJ;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,oBAAoB;QAC7B,MAAM,EAAE,85SAA85S;KACv6S;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,iCAAiC;QAC1C,MAAM,EAAE,s2XAAs2X;KAC/2X;IACD;QACE,MAAM,EAAE,qBAAqB;QAC7B,OAAO,EAAE,qBAAqB;QAC9B,MAAM,EAAE,+iFAA+iF;KACxjF;IACD;QACE,MAAM,EAAE,eAAe;QACvB,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,w5JAAw5J;KACj6J;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,upIAAupI;KAChqI;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,iBAAiB;QAC1B,MAAM,EAAE,qmMAAqmM;KAC9mM;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,m7KAAm7K;KAC57K;IACD;QACE,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,oBAAoB;QAC7B,MAAM,EAAE,2hVAA2hV;KACpiV;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,+BAA+B;QACxC,MAAM,EAAE,g2EAAg2E;KACz2E;IACD;QACE,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,i7FAAi7F;KAC17F;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,mCAAmC;QAC5C,MAAM,EAAE,8vKAA8vK;KACvwK;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,kBAAkB;QAC3B,MAAM,EAAE,6hJAA6hJ;KACtiJ;CACF,CAAA"}
1
+ {"version":3,"file":"helpCorpus.generated.js","sourceRoot":"","sources":["../../src/resources/helpCorpus.generated.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,kGAAkG;AAClG,oGAAoG;AAIpG,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,0CAA0C;QACnD,MAAM,EAAE,knWAAknW;KAC3nW;IACD;QACE,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,wnGAAwnG;KACjoG;IACD;QACE,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EAAE,igVAAigV;KAC1gV;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,kCAAkC;QAC3C,MAAM,EAAE,6okBAA6okB;KACtpkB;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,0BAA0B;QACnC,MAAM,EAAE,6oLAA6oL;KACtpL;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,gCAAgC;QACzC,MAAM,EAAE,qyfAAqyf;KAC9yf;IACD;QACE,MAAM,EAAE,sBAAsB;QAC9B,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EAAE,s3qBAAs3qB;KAC/3qB;IACD;QACE,MAAM,EAAE,eAAe;QACvB,OAAO,EAAE,qCAAqC;QAC9C,MAAM,EAAE,q3FAAq3F;KAC93F;IACD;QACE,MAAM,EAAE,yBAAyB;QACjC,OAAO,EAAE,4BAA4B;QACrC,MAAM,EAAE,2jRAA2jR;KACpkR;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,6/HAA6/H;KACtgI;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,4CAA4C;QACrD,MAAM,EAAE,22GAA22G;KACp3G;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,UAAU;QACnB,MAAM,EAAE,wvJAAwvJ;KACjwJ;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,oBAAoB;QAC7B,MAAM,EAAE,k4WAAk4W;KAC34W;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,iCAAiC;QAC1C,MAAM,EAAE,s2XAAs2X;KAC/2X;IACD;QACE,MAAM,EAAE,qBAAqB;QAC7B,OAAO,EAAE,qBAAqB;QAC9B,MAAM,EAAE,+iFAA+iF;KACxjF;IACD;QACE,MAAM,EAAE,eAAe;QACvB,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,u/JAAu/J;KAChgK;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,upIAAupI;KAChqI;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,iBAAiB;QAC1B,MAAM,EAAE,qmMAAqmM;KAC9mM;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,m7KAAm7K;KAC57K;IACD;QACE,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,oBAAoB;QAC7B,MAAM,EAAE,2hVAA2hV;KACpiV;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,+BAA+B;QACxC,MAAM,EAAE,g2EAAg2E;KACz2E;IACD;QACE,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,i7FAAi7F;KAC17F;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,mCAAmC;QAC5C,MAAM,EAAE,8vKAA8vK;KACvwK;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,kBAAkB;QAC3B,MAAM,EAAE,6hJAA6hJ;KACtiJ;CACF,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ebitex/content-mcp",
3
- "version": "0.5.111",
3
+ "version": "0.5.114",
4
4
  "description": "An MCP server for ebitex Content: build and publish a content model from an AI agent.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://developers.ebitex.io/getting-started/content-as-code/",