Skip to content

v0.9.0

Choose a tag to compare

@github-actions github-actions released this 01 Jul 09:48
8cf7932
  • @lowdefy/modules-mongodb-plugins: ### Minor Changes

  • #82 2076040 Thanks @SamTolmay! - Feature: the action workspace now surfaces the reviewer's request-changes comment as a read-only callout while an action is in changes-required (Part 62). The callout sits in the middle column's bare-alerts slot — below the workflow_closed_banner, above the content card — as a type: warning Alert ("Changes requested" + the comment), so the reworker sees the "what to fix" brief without hunting the History timeline.

    The brief is resolved server-side in the GetWorkflowAction envelope as a new changes_requested field: a single gated read of the latest action-request_changes event (sort date desc, limit 1), projecting the calling app's {app_name}.description bucket. App-scoping is inherited from the multi-app comment-visibility model for free — an internal reviewer note resolves to null for an app that can't see it; the read is skipped (and null) in every other stage. Empty/whitespace-only HTML normalizes to null so the callout never renders blank. The Alert sanitizes the comment HTML at render (renderHtml → DOMPurify).

    The WorkflowAPI connection now declares eventsCollection (string, default "log-events"), and the request-changes comment inputs are now text-only (inline image uploads disabled), so the callout only ever renders a text brief.

    Host apps in a multi-app deployment must add a { action_ids: 1 } index to the events collection (log-events) — see the workflows Indexes reference.

  • #82 5dce3ba Thanks @SamTolmay! - Feature (Part 26): workflows declare an inline entity.data routine on the entity: block (authored exactly like a hook — { routine: [...] }) that returns host-shaped data about the entity instance. The module generates an engine-only {type}-entity-data InternalApi from the routine (makeWorkflowApis) and carries the resolved endpoint id on entity.data_endpoint (makeWorkflowsConfig, with the build-only data routine stripped from the runtime config). The single-workflow read handlers — GetWorkflowAction, GetWorkflowOverview, GetWorkflowActionGroupOverview — call the endpoint server-side via the engine's callApi (same authenticated user) through a shared resolveEntityData helper.

    The routine's reserved name key is lifted onto entity_link.name for the breadcrumb / back-link; all other keys are host-owned and merged onto the action response's entity object (consumed by the action page's DataDescriptions summary and the entity_view slot). Resolution never fails the read — a missing endpoint, a throwing routine, or a deleted entity all degrade to name: null (chrome falls back to the type label) and entity: { id }.

    This replaces the previous entity.name_field dot-path + the per-page get_entity request: the request file is deleted, all five action templates (view/review/edit/error/action) drop the get_entity request + onMount read and source the instance name from entity_link.name and entity fields from get_workflow_action.entity. The action-workspace shell stops blanking the page on the self-set entity_id — the middle/right content show content-shaped skeletons gated on the get_workflow_action request, and the entity-id mount gate is narrowed to just the actions-on-entity and History panels.

    entity.data must be an object with a routine: array; a string value (the legacy external-endpoint-id shape) hard-errors with a migration hint. The demo onboarding workflow declares an entity.data routine and its entity_view slot reads get_workflow_action.entity.*.

Patch Changes

  • #82 fb190ff Thanks @SamTolmay! - Fix block styling never reaching the app. ActionSteps, EventsTimeline, DataDescriptions and SmartDescriptions each shipped their global CSS via a style.module.css imported only for side effects (import "./style.module.css"). Vite/Rollup tree-shakes such an import — the CSS-module proxy is treated as side-effect-free because its exported class map is unused — so none of the :global(...) rules were emitted into the client bundle (badge stacking, timeline rails, dataview value styling all silently missing). Every selector in these files was already :global(...), so they were CSS modules in name only. Renamed each to a plain style.css and import it as a plain global stylesheet, which Vite always keeps.

    Also fix ActionSteps action items wrapping side-by-side: the per-group actions now render in a flex-column container so they stack regardless of stylesheet loading.

  • #82 f1be116 Thanks @SamTolmay! - Strip leftover :global(...) wrappers from the block stylesheets so their rules actually apply. When ActionSteps, EventsTimeline, DataDescriptions and SmartDescriptions were converted from style.module.css to a plain style.css, the rename kept the file content byte-for-byte — including the :global(...) wrapper around every selector. :global() is a CSS Modules construct, not valid CSS; in a plain stylesheet (processed with modules: false) css-loader passes it through verbatim, the browser sees an unknown pseudo-class, treats the whole selector as invalid, and drops the rule. So even though the side-effect import now reaches the production bundle, every styled rule was silently a no-op (badge layout, timeline rails, dataview value/link/tag/array styling).

    Removed the :global(...) wrapper from each rule, leaving the inner selector. These classes (action-steps-*, dataview-*, events-timeline-compact) are already namespaced, so there is no module scope to escape in a plain stylesheet. No other blocks are affected: ContactSelector and FileManager ship no stylesheet, and there are no remaining .module.css files in the package.

  • #82 e0f646a Thanks @SamTolmay! - Restore the DataDescriptions block.

  • @lowdefy/modules-mongodb-activities: ### Patch Changes

  • #82 163529c Thanks @SamTolmay! - Breaking: the layout floating-actions component now lays its buttons out with direction: row + justify: flex-end + wrap: nowrap instead of direction: row-reverse. Buttons are now listed in natural left-to-right order (the last one renders rightmost), and the bar never wraps onto a second line.

    Migration: reverse the order of buttons in each floating-actions actions: array — what used to be listed first (and rendered rightmost under row-reverse) must now be listed last. Every action button must set layout: { flex: 0 1 auto } so it is content-sized rather than a full-width grid column; a button without it stretches full width and stacks onto its own line. Any spacer Box or width var previously used to coax right-alignment is no longer needed and should be removed.

    All in-repo callers (contacts, activities, companies, user-account, user-admin) have been updated to the new order. The workflows action-page templates (edit/view/review/error) and the shared check-action-surface signal bar (used by the in-context action modal and the workflow-action-* pages) now set flex: 0 1 auto on every signal button and order them so the primary action lands rightmost, fixing buttons that previously stacked onto multiple lines and left-aligned. The signal bar's justify was also corrected from the invalid flex-end token to end (Lowdefy's justify map only accepts end; flex-end silently fell back to left alignment).

  • #82 c4e1000 Thanks @SamTolmay! - The shared page title bar (modules/shared/layout/title-block.yaml, threaded through the layout page component) gains three capabilities:

    • type eyebrow — a small uppercase entity-type label rendered directly above the title (e.g. COMPANY, EDIT COMPANY, INVITE ACME USER). The title prop now holds just the entity name; pages stop hand-concatenating "{type}: {name}" into the heading. The eyebrow renders immediately and is never skeletoned.
    • status + status_enum pill — the caller passes a status slug (runtime) and a status-enum map (build-time _ref); the title block resolves the label and the three-colour contract (color→fill, borderColor→border, titleColor→text) internally and renders a chunky, vertically-centred pill. Status resolution lives in the component now, not in each caller.
    • opt-in loading skeleton — when loading is truthy, the title, subtitle, and status pill render as shimmer skeletons (via Lowdefy's native loading:/skeleton: pair). Defaults to false, so static list/index titles are untouched.

    Breaking: the raw badge_text / badge_color props are removed (replaced by status + status_enum). Any external/consumer title-bar override that passed badge_* silently loses its badge and must migrate to a status enum with the standard { color, borderColor, titleColor, title } entry shape. The wholesale title_block override path is unaffected — it replaces the block entirely and never used these props.

    All in-repo callers are migrated: workflow overview and group overview (badge → status pill), and contacts / activities / user-admin view, edit, and new pages (entity type split out of the title into the eyebrow; loading added on the request-backed view pages). A new modules/workflows/enums/action_group_statuses.yaml enum backs the group-overview rollup status (done / in-progress / blocked), preserving its previous green / blue / grey colours. The title-bar prop interface is now documented in the layout module README.

  • @lowdefy/modules-mongodb-companies: ### Patch Changes

  • #82 163529c Thanks @SamTolmay! - Breaking: the layout floating-actions component now lays its buttons out with direction: row + justify: flex-end + wrap: nowrap instead of direction: row-reverse. Buttons are now listed in natural left-to-right order (the last one renders rightmost), and the bar never wraps onto a second line.

    Migration: reverse the order of buttons in each floating-actions actions: array — what used to be listed first (and rendered rightmost under row-reverse) must now be listed last. Every action button must set layout: { flex: 0 1 auto } so it is content-sized rather than a full-width grid column; a button without it stretches full width and stacks onto its own line. Any spacer Box or width var previously used to coax right-alignment is no longer needed and should be removed.

    All in-repo callers (contacts, activities, companies, user-account, user-admin) have been updated to the new order. The workflows action-page templates (edit/view/review/error) and the shared check-action-surface signal bar (used by the in-context action modal and the workflow-action-* pages) now set flex: 0 1 auto on every signal button and order them so the primary action lands rightmost, fixing buttons that previously stacked onto multiple lines and left-aligned. The signal bar's justify was also corrected from the invalid flex-end token to end (Lowdefy's justify map only accepts end; flex-end silently fell back to left alignment).

  • #82 3dbbbdf Thanks @SamTolmay! - Follow-on to the title-block eyebrow/status-pill work: wire two modules the first pass missed, fix a title-bar layout bug, and relocate the user record stamp.

    • layout — the title bar's change-stamp subtitle now wraps instead of being a single nowrap/ellipsis line. The previous styling gave the title column a min-content width equal to the full subtitle, which on narrower bars pushed the page actions (e.g. the Edit button) onto a new row. The title column is now flex: 1 1 0 and the page-actions block flex: 0 0 auto, so the actions always hold the right edge and the subtitle wraps within the remaining width. (Verified in a headless-browser render of the exact DOM.)
    • user-admin gains a status pill on the view and edit pages. A new modules/user-admin/enums/user_statuses.yaml enum (active / open invite / disabled) backs it, and get_user now emits a status slug derived the same way as the list table's active column (disabled > open invite > active). The enum uses the antd preset green / blue / red colour families so the title pill matches the existing AgGrid Tag in the list — the table tag mechanism is unchanged. The view page no longer renders the created/modified stamp as a title subtitle; that audit info moves into the Access sidebar card (next to "Signed up"), and the Access card's status Tag is removed since the title pill now shows status.
    • companies view / edit / new pages are migrated to the eyebrow + title shape (entity type moved out of the hand-concatenated "{label}: {name}" heading into the type eyebrow; loading added on the request-backed view page). These pages used the title bar before the redesign but were not migrated with the other modules.
  • @lowdefy/modules-mongodb-contacts: ### Patch Changes

  • #82 163529c Thanks @SamTolmay! - Breaking: the layout floating-actions component now lays its buttons out with direction: row + justify: flex-end + wrap: nowrap instead of direction: row-reverse. Buttons are now listed in natural left-to-right order (the last one renders rightmost), and the bar never wraps onto a second line.

    Migration: reverse the order of buttons in each floating-actions actions: array — what used to be listed first (and rendered rightmost under row-reverse) must now be listed last. Every action button must set layout: { flex: 0 1 auto } so it is content-sized rather than a full-width grid column; a button without it stretches full width and stacks onto its own line. Any spacer Box or width var previously used to coax right-alignment is no longer needed and should be removed.

    All in-repo callers (contacts, activities, companies, user-account, user-admin) have been updated to the new order. The workflows action-page templates (edit/view/review/error) and the shared check-action-surface signal bar (used by the in-context action modal and the workflow-action-* pages) now set flex: 0 1 auto on every signal button and order them so the primary action lands rightmost, fixing buttons that previously stacked onto multiple lines and left-aligned. The signal bar's justify was also corrected from the invalid flex-end token to end (Lowdefy's justify map only accepts end; flex-end silently fell back to left alignment).

  • #82 c4e1000 Thanks @SamTolmay! - The shared page title bar (modules/shared/layout/title-block.yaml, threaded through the layout page component) gains three capabilities:

    • type eyebrow — a small uppercase entity-type label rendered directly above the title (e.g. COMPANY, EDIT COMPANY, INVITE ACME USER). The title prop now holds just the entity name; pages stop hand-concatenating "{type}: {name}" into the heading. The eyebrow renders immediately and is never skeletoned.
    • status + status_enum pill — the caller passes a status slug (runtime) and a status-enum map (build-time _ref); the title block resolves the label and the three-colour contract (color→fill, borderColor→border, titleColor→text) internally and renders a chunky, vertically-centred pill. Status resolution lives in the component now, not in each caller.
    • opt-in loading skeleton — when loading is truthy, the title, subtitle, and status pill render as shimmer skeletons (via Lowdefy's native loading:/skeleton: pair). Defaults to false, so static list/index titles are untouched.

    Breaking: the raw badge_text / badge_color props are removed (replaced by status + status_enum). Any external/consumer title-bar override that passed badge_* silently loses its badge and must migrate to a status enum with the standard { color, borderColor, titleColor, title } entry shape. The wholesale title_block override path is unaffected — it replaces the block entirely and never used these props.

    All in-repo callers are migrated: workflow overview and group overview (badge → status pill), and contacts / activities / user-admin view, edit, and new pages (entity type split out of the title into the eyebrow; loading added on the request-backed view pages). A new modules/workflows/enums/action_group_statuses.yaml enum backs the group-overview rollup status (done / in-progress / blocked), preserving its previous green / blue / grey colours. The title-bar prop interface is now documented in the layout module README.

  • @lowdefy/modules-mongodb-layout: ### Minor Changes

  • #82 163529c Thanks @SamTolmay! - Breaking: the layout floating-actions component now lays its buttons out with direction: row + justify: flex-end + wrap: nowrap instead of direction: row-reverse. Buttons are now listed in natural left-to-right order (the last one renders rightmost), and the bar never wraps onto a second line.

    Migration: reverse the order of buttons in each floating-actions actions: array — what used to be listed first (and rendered rightmost under row-reverse) must now be listed last. Every action button must set layout: { flex: 0 1 auto } so it is content-sized rather than a full-width grid column; a button without it stretches full width and stacks onto its own line. Any spacer Box or width var previously used to coax right-alignment is no longer needed and should be removed.

    All in-repo callers (contacts, activities, companies, user-account, user-admin) have been updated to the new order. The workflows action-page templates (edit/view/review/error) and the shared check-action-surface signal bar (used by the in-context action modal and the workflow-action-* pages) now set flex: 0 1 auto on every signal button and order them so the primary action lands rightmost, fixing buttons that previously stacked onto multiple lines and left-aligned. The signal bar's justify was also corrected from the invalid flex-end token to end (Lowdefy's justify map only accepts end; flex-end silently fell back to left alignment).

  • #82 c4e1000 Thanks @SamTolmay! - The shared page title bar (modules/shared/layout/title-block.yaml, threaded through the layout page component) gains three capabilities:

    • type eyebrow — a small uppercase entity-type label rendered directly above the title (e.g. COMPANY, EDIT COMPANY, INVITE ACME USER). The title prop now holds just the entity name; pages stop hand-concatenating "{type}: {name}" into the heading. The eyebrow renders immediately and is never skeletoned.
    • status + status_enum pill — the caller passes a status slug (runtime) and a status-enum map (build-time _ref); the title block resolves the label and the three-colour contract (color→fill, borderColor→border, titleColor→text) internally and renders a chunky, vertically-centred pill. Status resolution lives in the component now, not in each caller.
    • opt-in loading skeleton — when loading is truthy, the title, subtitle, and status pill render as shimmer skeletons (via Lowdefy's native loading:/skeleton: pair). Defaults to false, so static list/index titles are untouched.

    Breaking: the raw badge_text / badge_color props are removed (replaced by status + status_enum). Any external/consumer title-bar override that passed badge_* silently loses its badge and must migrate to a status enum with the standard { color, borderColor, titleColor, title } entry shape. The wholesale title_block override path is unaffected — it replaces the block entirely and never used these props.

    All in-repo callers are migrated: workflow overview and group overview (badge → status pill), and contacts / activities / user-admin view, edit, and new pages (entity type split out of the title into the eyebrow; loading added on the request-backed view pages). A new modules/workflows/enums/action_group_statuses.yaml enum backs the group-overview rollup status (done / in-progress / blocked), preserving its previous green / blue / grey colours. The title-bar prop interface is now documented in the layout module README.

Patch Changes

  • #82 3dbbbdf Thanks @SamTolmay! - Follow-on to the title-block eyebrow/status-pill work: wire two modules the first pass missed, fix a title-bar layout bug, and relocate the user record stamp.

    • layout — the title bar's change-stamp subtitle now wraps instead of being a single nowrap/ellipsis line. The previous styling gave the title column a min-content width equal to the full subtitle, which on narrower bars pushed the page actions (e.g. the Edit button) onto a new row. The title column is now flex: 1 1 0 and the page-actions block flex: 0 0 auto, so the actions always hold the right edge and the subtitle wraps within the remaining width. (Verified in a headless-browser render of the exact DOM.)
    • user-admin gains a status pill on the view and edit pages. A new modules/user-admin/enums/user_statuses.yaml enum (active / open invite / disabled) backs it, and get_user now emits a status slug derived the same way as the list table's active column (disabled > open invite > active). The enum uses the antd preset green / blue / red colour families so the title pill matches the existing AgGrid Tag in the list — the table tag mechanism is unchanged. The view page no longer renders the created/modified stamp as a title subtitle; that audit info moves into the Access sidebar card (next to "Signed up"), and the Access card's status Tag is removed since the title pill now shows status.
    • companies view / edit / new pages are migrated to the eyebrow + title shape (entity type moved out of the hand-concatenated "{label}: {name}" heading into the type eyebrow; loading added on the request-backed view page). These pages used the title bar before the redesign but were not migrated with the other modules.
  • @lowdefy/modules-mongodb-user-account: ### Patch Changes

  • #82 163529c Thanks @SamTolmay! - Breaking: the layout floating-actions component now lays its buttons out with direction: row + justify: flex-end + wrap: nowrap instead of direction: row-reverse. Buttons are now listed in natural left-to-right order (the last one renders rightmost), and the bar never wraps onto a second line.

    Migration: reverse the order of buttons in each floating-actions actions: array — what used to be listed first (and rendered rightmost under row-reverse) must now be listed last. Every action button must set layout: { flex: 0 1 auto } so it is content-sized rather than a full-width grid column; a button without it stretches full width and stacks onto its own line. Any spacer Box or width var previously used to coax right-alignment is no longer needed and should be removed.

    All in-repo callers (contacts, activities, companies, user-account, user-admin) have been updated to the new order. The workflows action-page templates (edit/view/review/error) and the shared check-action-surface signal bar (used by the in-context action modal and the workflow-action-* pages) now set flex: 0 1 auto on every signal button and order them so the primary action lands rightmost, fixing buttons that previously stacked onto multiple lines and left-aligned. The signal bar's justify was also corrected from the invalid flex-end token to end (Lowdefy's justify map only accepts end; flex-end silently fell back to left alignment).

  • #82 14d3861 Thanks @SamTolmay! - Fix the user-selector / user-multi-selector options request returning no users. The request scoped the dropdown to apps.{app_name}.is_user using _module.var: app_name, but these components are only ever consumed through a cross-module _ref and _module.var resolved to null in that scope — so the query matched apps.null.is_user and returned nothing. It now reads the app slug via _app: slug, which resolves from the app root independently of module-entry-var resolution. Consuming apps must declare slug: on their lowdefy.yaml (kebab-case).

  • @lowdefy/modules-mongodb-user-admin: ### Patch Changes

  • #82 163529c Thanks @SamTolmay! - Breaking: the layout floating-actions component now lays its buttons out with direction: row + justify: flex-end + wrap: nowrap instead of direction: row-reverse. Buttons are now listed in natural left-to-right order (the last one renders rightmost), and the bar never wraps onto a second line.

    Migration: reverse the order of buttons in each floating-actions actions: array — what used to be listed first (and rendered rightmost under row-reverse) must now be listed last. Every action button must set layout: { flex: 0 1 auto } so it is content-sized rather than a full-width grid column; a button without it stretches full width and stacks onto its own line. Any spacer Box or width var previously used to coax right-alignment is no longer needed and should be removed.

    All in-repo callers (contacts, activities, companies, user-account, user-admin) have been updated to the new order. The workflows action-page templates (edit/view/review/error) and the shared check-action-surface signal bar (used by the in-context action modal and the workflow-action-* pages) now set flex: 0 1 auto on every signal button and order them so the primary action lands rightmost, fixing buttons that previously stacked onto multiple lines and left-aligned. The signal bar's justify was also corrected from the invalid flex-end token to end (Lowdefy's justify map only accepts end; flex-end silently fell back to left alignment).

  • #82 c4e1000 Thanks @SamTolmay! - The shared page title bar (modules/shared/layout/title-block.yaml, threaded through the layout page component) gains three capabilities:

    • type eyebrow — a small uppercase entity-type label rendered directly above the title (e.g. COMPANY, EDIT COMPANY, INVITE ACME USER). The title prop now holds just the entity name; pages stop hand-concatenating "{type}: {name}" into the heading. The eyebrow renders immediately and is never skeletoned.
    • status + status_enum pill — the caller passes a status slug (runtime) and a status-enum map (build-time _ref); the title block resolves the label and the three-colour contract (color→fill, borderColor→border, titleColor→text) internally and renders a chunky, vertically-centred pill. Status resolution lives in the component now, not in each caller.
    • opt-in loading skeleton — when loading is truthy, the title, subtitle, and status pill render as shimmer skeletons (via Lowdefy's native loading:/skeleton: pair). Defaults to false, so static list/index titles are untouched.

    Breaking: the raw badge_text / badge_color props are removed (replaced by status + status_enum). Any external/consumer title-bar override that passed badge_* silently loses its badge and must migrate to a status enum with the standard { color, borderColor, titleColor, title } entry shape. The wholesale title_block override path is unaffected — it replaces the block entirely and never used these props.

    All in-repo callers are migrated: workflow overview and group overview (badge → status pill), and contacts / activities / user-admin view, edit, and new pages (entity type split out of the title into the eyebrow; loading added on the request-backed view pages). A new modules/workflows/enums/action_group_statuses.yaml enum backs the group-overview rollup status (done / in-progress / blocked), preserving its previous green / blue / grey colours. The title-bar prop interface is now documented in the layout module README.

  • #82 3dbbbdf Thanks @SamTolmay! - Follow-on to the title-block eyebrow/status-pill work: wire two modules the first pass missed, fix a title-bar layout bug, and relocate the user record stamp.

    • layout — the title bar's change-stamp subtitle now wraps instead of being a single nowrap/ellipsis line. The previous styling gave the title column a min-content width equal to the full subtitle, which on narrower bars pushed the page actions (e.g. the Edit button) onto a new row. The title column is now flex: 1 1 0 and the page-actions block flex: 0 0 auto, so the actions always hold the right edge and the subtitle wraps within the remaining width. (Verified in a headless-browser render of the exact DOM.)
    • user-admin gains a status pill on the view and edit pages. A new modules/user-admin/enums/user_statuses.yaml enum (active / open invite / disabled) backs it, and get_user now emits a status slug derived the same way as the list table's active column (disabled > open invite > active). The enum uses the antd preset green / blue / red colour families so the title pill matches the existing AgGrid Tag in the list — the table tag mechanism is unchanged. The view page no longer renders the created/modified stamp as a title subtitle; that audit info moves into the Access sidebar card (next to "Signed up"), and the Access card's status Tag is removed since the title pill now shows status.
    • companies view / edit / new pages are migrated to the eyebrow + title shape (entity type moved out of the hand-concatenated "{label}: {name}" heading into the type eyebrow; loading added on the request-backed view page). These pages used the title bar before the redesign but were not migrated with the other modules.
  • @lowdefy/modules-mongodb-workflows: ### Minor Changes

  • #82 bf0015f Thanks @SamTolmay! - Initial release of the workflows module — a multi-workflow engine for entity-scoped business processes (sales pipelines, onboarding checklists, compliance reviews, service orders, and any entity with a structured, role-gated lifecycle).

    Apps declare workflow YAML (workflows_config, one entry per workflow type); the engine renders entity-scoped action lists and submits lifecycle transitions through engine-managed handlers. Highlights:

    • Signal-driven FSM — a submission carries a signal that the engine resolves against a per-kind finite-state machine, so authors never hand-write status transitions.
    • Resolver-emitted surface — two static overview pages, six operational APIs, and a dynamic surface derived from the app's config: a per-verb page set per form action, one {workflow_type}-action page per workflow, and one submit endpoint per form/check action. Every action page renders in the same three-tier workspace.
    • Authoring grammar — action kinds, role-gated access (multi-app scoped via app_name), inline hooks and trackers, action groups with blocking, and an inline entity.data routine that returns host-shaped data about the entity instance.
    • Built-in form components and a universal-fields surface wrapping the contact, user, file, and event components from sibling modules.

    Depends on the layout, events, notifications, contacts, and user-account modules, and on the @lowdefy/modules-mongodb-plugins WorkflowAPI connection.

    Full documentation lives under docs/workflows/ — start with the module index and the mental-model concept, then the authoring grammar, FSM-and-signals, and required-indexes references.