Skip to content

Changelog

Changes that need action in apps built on Coworkee. Newest first.

0.0.1.33 (2026-10-17)

Breaking changes

  • Migration needed: a filtered unique index IX_Themes_Name on cw.Themes (built-in themes, TenantId null) and the column cw.ChatAttachments.ThumbnailKey. The index keeps two app instances from seeding the built-in themes twice on SQL Server and SQLite (Postgres already refused it); the seed no longer cleans up such duplicates. If the migration reports a duplicate key, delete the extra built-in row first.
  • History restore checks its preview: EntityHistoryPreviewDto.Version and EntityHistoryRestoreRequest.Version are new; POST /api/v1/history/{set}/{id}/restore answers 409 when the version is missing or the record changed since the preview. The history dialog, the audit log undo and the AirWorks record window preview again. Own IEntityHistoryApi implementations and direct API calls pass the version; regenerate OpenAPI snapshots and SDKs. See Auditing.
  • Coworkee.Chat depends on Coworkee.BackgroundJobs and brings SkiaSharp (MIT) with its native Linux assets for the thumbnails.

New

  • coworkee update inserts single lines itself (rule kind insertions in upgrade-rules.json: after the first line matching a pattern, with its indentation, skipped where the line is already there; --dry-run only lists them). The step of 0.0.1.32 (builder.ConfigureContainer(new DefaultServiceProviderFactory()); in src/*.Migrations/Program.cs) is applied automatically now.
  • New apps have an AGENTS.md with the rules for coding agents (layout, required patterns, pitfalls, migrations, tests, CLI and MCP) and a CLAUDE.md that imports it. Existing apps can copy them from a new app of the same options.
  • AirWorks: the theme and mail template editors of the administration are the pages of the web app in a window when the BFF knows the web app (embedOr), the TypeScript editors stay the fallback; Workflow designer opens Elsa Studio in a browser tab (Workflows.Elsa.Manage); the record window has Open in the web app (the page of the record's global search hit). New text key Open in the web app.
  • Coworkee:Auth:FrameAncestors: origins that may frame the account pages of the auth server (default none), so an AirWorks window can show the sign-in page of an embedded web page. Same site only; see AirWorks.
  • app.UseCoworkeeSecurityHeaders() (Coworkee.Bff) sends a Content-Security-Policy for the Blazor WebAssembly client (frame-ancestors from Coworkee:Bff:FrameAncestors, MudEx file previews from blob and data URLs, hot reload in Development), nosniff and a Referrer-Policy; extra sources per directive or an own policy through Coworkee:Bff:SecurityHeaders. The template's web host uses it; existing apps add it before UseStaticFiles and drop a hand-written policy. Apps with the cloud pickers of the Files module add their hosts. See Security headers of the web app.
  • Coworkee:Bff:MaxRequestBodySize caps what the web host forwards to the API; by default its forwarded routes have no limit and the API checks its own. A hand-written ConfigureKestrel(k => k.Limits.MaxRequestBodySize = ...) in the web or AirWorks host is not needed and can go.
  • builder.AddCoworkeeMigrations<TDbContext>(...) and host.RunCoworkeeMigrationsAsync() (Coworkee.Identity.Setup) are the migrations host: migrate with retries (Migrations:Attempts), seed the development users or the first administrator of a deployment, keep the development users in step, reconcile Keycloak, and the container fix of 0.0.1.32. The template uses it; existing apps replace their hand-written src/*.Migrations/Program.cs with it, so later fixes come with the package (coworkee update points at it). See Migrations and seeding.
  • Chat pictures get a small WebP the server makes (at most 480 px, turned upright, GET /api/v1/chat/attachments/{id}/thumbnail, ChatAttachmentDto.HasThumbnail); the message list shows it, a click opens the full file.
  • Every chat file opens in the MudEx file viewer (MudExFileDisplay), also an upload before it is sent. The rule for own pages is on Files.
  • The policy of UseCoworkeeSecurityHeaders allows the CDNs the file viewer loads its viewers from (Coworkee:Bff:SecurityHeaders:FileViewerCdns: jsDelivr, esm.sh, unpkg) in script-src, style-src and connect-src, so Word, Excel, maps and the other viewers work out of the box; clear the list for a policy without third-party script. See Security headers of the web app.
  • Files uploaded to a chat but never sent are deleted after Coworkee:Chat:UnsentAttachmentLifetime (default 24 hours, an hourly job).

Fixes

  • The SDKs page described an sdk/openapi.json with a snapshot test and an sdk/typescript client that the template never had; it now shows them as a recipe for apps that need them.
  • npm run build of @coworkee/client and @coworkee/airworks empties dist first, so packs no longer carry files of removed sources.
  • The built-in themes Coworkee, Forest and Sunset meet WCAG AA on button text in light mode (slightly darker primary or secondary color); the contrast test covers every built-in theme.
  • The file viewer never hands a private file to the online Office viewer of Microsoft.
  • Files forwarded by the web host keep their own sandbox policy: UseCoworkeeSecurityHeaders adds the app policy only to answers without one (before, forwarded files carried both).
  • The content endpoints of files, public files, chat files and thumbnails answer HEAD, which the image viewer sends first (it got 405).

0.0.1.32 (2026-10-17)

Fixes

  • The migrations of a local run crashed at start since 0.0.1.31: they run as Development, whose service validation fails on the MVC services of OData in a host without a web environment. The template builds the container of the migrations with the production defaults; existing apps add builder.ConfigureContainer(new DefaultServiceProviderFactory()); after Host.CreateApplicationBuilder(args) in src/*.Migrations/Program.cs (coworkee update points at it).

0.0.1.31 (2026-10-17)

Breaking changes

  • Migration needed (apps with Chat): direct and group chats bring the tables cw.ChatConversations, cw.ChatMembers, cw.ChatReactions, cw.ChatAttachments and new columns of cw.ChatMessages. Earlier direct messages move into conversations at the next start; what was read stays read.
  • Coworkee.Chat depends on Coworkee.Storage (attachments) and references Coworkee.Notifications (mention notifications when that module is there).
  • Chat contracts: ChatMessageDto.ToUserId is nullable (empty in groups) and the DTO has new properties (ConversationId, Html, Source, EditedAt, Deleted, ReplyTo, Reactions, Attachments, HasEntityMentions); ChatReadDto has ConversationId. IChatApi gained the conversation members; own implementations add them. New endpoints under /api/v1/chat/chats, /messages and /attachments: regenerate OpenAPI snapshots and SDKs. The plain text endpoints by person stay.
  • UserAvatar opens a menu with Chat and Profile for other people when the user may chat (OfferChat, default true); set OfferChat="false" where the avatar sits in something that reacts to clicks. New library page person at /people/{id}.

New

  • Eight more built-in themes, each with light and dark palettes, own fonts, radius and options: Octo, Code, Arctic, Vampire, Solar, Atom, Paper and Aubergine (CLI/spec theme, template, Studio gallery). Their text meets WCAG AA contrast. See Theming.
  • The setup token is easy to find in a local run: the app host gives every service one token and, while the system is not set up, prints it on its console (coworkee run), in the api's log and in the Aspire dashboard (Setup link with the token on the web resource, Setup token property on the api). Coworkee Studio shows it with a copy button on the run card and under My apps; coworkee deploy names <APP>_SETUP_TOKEN when no administrator is set. /setup?token=... fills the token in. See Setup wizard or seed.
  • @coworkee/airworks: Inbox (coworkee.inbox, approvals and notifications) replaces notificationsApp; Records with a record window (coworkee.record: fields, history with undo and restore, workflow); the profile is the first tab of Settings (profileApp is gone, renderProfile stays); the API documentation moved into the administration (Monitoring). Apps that registered notificationsApp, profileApp or apiDocsApp by name take defaultApps or the new names.
  • Pages of the web app in AirWorks windows: embedApp, openWebPage; CoworkeeLayout shows only the page with ?embed=1. BffOptions.WebAppUrl (reported as appUrl of /bff/user) and BffOptions.FrameAncestors (lets those origins frame the pages; antiforgery's X-Frame-Options is suppressed then); AddAirWorks sets both under Aspire.
  • Badges on the inbox and chat tiles with AirWorks' setBadge (AirWorks 0.5; older versions just show none).
  • Chat: group chats (name, add and remove people, leave), formatted messages with the rich text editor (Enter sends), @ mentions of people (link to the person, notification for members of the chat) and # mentions of records from the global search (shown only to readers whose search finds them, otherwise restricted), replies, emoji reactions, editing and deleting own messages, files and pictures by button, drag and drop or paste with upload progress (members only, setting Chat.MaxAttachmentMb, hook IChatAttachmentScanner), read marks per reader, typing indicator and search in a chat. The server sanitizes every message. See Chat.
  • Mini chats: a dock at the bottom right with up to three collapsible chat windows (unread count when minimized, Open in the chat, kept per user across reloads, full screen on phones). They open from the chat page, the command palette (Chat with…, @name), any avatar, the person page, the snackbar of a new message and mention notifications. ChatDock opens them from own components.
  • RichTextEditor takes Tools (toolbar) and Placeholder.

Fixes

  • A new app run locally showed its setup page instead of signing in with the development users: the migrations project has no launch profile and ran as Production, so DemoSeed was skipped. AddMigrations passes the app host's environment (DOTNET_ENVIRONMENT) to the migrations of a local run.
  • The setup page of a system that is already set up goes to the app; a setup tab left open leaves for the app when it gets the focus again or another tab finishes the setup.
  • Built-in themes were listed twice when requests seeded them at the same moment (SQL Server and SQLite let the unique index repeat null tenants). Seeding runs once at a time per process and removes such copies (the one an organisation uses stays).

0.0.1.30 (2026-10-16)

New

  • The audit log undoes changes of entity sets registered with AddEntityHistory: per entry Undo this change, Restore the state before this change, Restore record (soft delete) and Open record history, through the history preview and restore. EntityHistoryRestoreRequest has a Mode (After, Before, Undo), the preview marks fields a later entry changed (ChangedLater), and GET /api/v1/history lists the readable sets. IEntityHistoryApi has GetSetsAsync (own implementations add it).

0.0.1.29 (2026-10-16)

New

  • Workflow state as a server-side filter: every OData set whose entity has a workflow gets the virtual properties WorkflowState and WorkflowAwaitsMe for $filter and $orderby (a tenant-filtered subquery, or the MirrorTo column) and a facet WorkflowState with the states of the definition and Awaiting my approval; both need Workflows.View. CoworkeeWorkflowColumn for CoworkeeDataTable filters, sorts and groups by it; WorkflowState<T>.WithColor(...) colors a state. Replace TemplateColumn + CoworkeeWorkflowActions with <CoworkeeWorkflowColumn T="..." EntityType="..." />.
  • OData sets can carry computed properties of other modules (IODataComputedPropertySource, ODataComputedProperty): bound into $filter/$orderby, never serialized, optional facet. The library configures the OData route itself now instead of Nextended's AddODataAuto.

Fixes

  • SyncDevelopmentUsersAsync() runs for the migrations of a local Aspire run: the migrations project has no launch profile and ran as Production, so the sync never happened there. AddMigrations sets Coworkee:Identity:SyncDevelopmentUsers in local development runs; the sync runs in Development or with that setting.
  • SyncDevelopmentUsersAsync() also gives seed users the roles and seeded roles the permissions added to the seed since (Development only, nothing is removed), so a database set up earlier picks up e.g. a new role of a demo user and new workflow permissions of a demo role.

0.0.1.28 (2026-10-16)

Breaking changes

  • Migration needed (apps with Reporting): new table cw.DashboardReports.
  • IReportsApi gained GetDashboardAsync and SetDashboardAsync; own implementations add them. New endpoints under /api/v1/reports/dashboard: regenerate OpenAPI snapshots and SDKs.
  • AddCommandPaletteEntitySet and CommandPaletteEntitySet<T> are removed: the command palette finds records through the new global search of the server. Register the set next to its OData set, e.g. services.AddGlobalSearch<Product>(s => s.Fields(p => p.Name, p => p.Barcode).Page("/catalog/products")) (coworkee update points at the old calls).
  • New endpoints /api/v1/search, /api/v1/search/stream and /api/v1/search/providers: regenerate OpenAPI snapshots and SDKs.
  • ICoworkeeApi gained GetMailTemplateHistoryAsync; own implementations add it.
  • MudBlazor.Extensions 9.11.4 and MudExRichTextEditor 9.5.5: apps that pin MudBlazor.Extensions themselves move to 9.11.4.

New

  • A report as dashboard: every user can make a report their dashboard, holders of the new permission Reports.Dashboard the organisation's default; the user's choice wins. ReportDashboard shows it live and falls back to the app's own dashboard. The template's dashboard page uses it, lists Dashboard before Reports and the sample setup makes Catalog overview the organisation's dashboard. See A report as dashboard.
  • Global search: one search over users, roles, groups, files, reports, chats and the app's own sets (AddGlobalSearch<T> for OData sets, IGlobalSearchProvider for anything else, AddGlobalSearchIndex for an Elasticsearch alias). Prefix before part, "exact", users:max type filters and ids; scores comparable across providers, a timeout per provider, the same permissions, organisation and row rules as the OData lists. The command palette shows the hits group by group as they arrive, /search?q= lists all with a filter per type, GET /api/v1/search/stream streams JSON lines through the BFF, and the MCP tool global_search hands them to AI clients. See Global search.
  • The files page opens the preview of ?file={id}.
  • Template samples: brands, products and documents are in the global search.
  • coworkee module add and coworkee entity add register generated entities with text properties in the global search (AddGlobalSearch<T> with those fields and the list page).
  • Rich text editor setting: Editors.RichTextEditor (TipTap, the default, or Quill) picks the engine of every rich text editor of the library; RichTextEditor brings the same choice to own pages. Mail placeholders work as mentions in both. See Mailing.
  • Mail template editor: the editor fills the window, a preview sheet follows every change (desktop or phone width, light or dark mail client, inbox line), version history with a line diff and restore (GET /api/v1/mail/templates/{name}/{culture}/history), a guard against leaving unsaved changes, language chips next to the title and a searchable placeholder list.
  • Workflow designer: Coworkee.Workflows.Elsa.Studio hosts Elsa Studio as an app of its own that signs in at the auth server (permission Workflows.Elsa.Manage) and works with the Elsa API of the api; app.AddElsaStudio<T>() (or AddProjects() for *_ElsaStudio) wires the client, the API address and the designer link, coworkee deploy --without elsastudio leaves it out. Template option elsaStudio (--elsa-studio). See Elsa Studio.

Fixes

  • Dialogs and side sheets of the library (import wizard, campaign wizard, theme, logo, code editor, API key, workflow comment) carry the initial class of MudBlazor.Extensions, so they show up only at their final position instead of flashing in the middle first. Own dialogs opened with ShowExAsync or ShowSideSheetAsync set Class="@MudExCss.Classes.Dialog.Initial" on their MudDialog.
  • The approvals inbox shows title, details and deadline of an approval on lines of their own.
  • Apps with Coworkee.Workflows.Elsa keep the property names of their validation errors (Brand.Name); the Elsa API (FastEndpoints) had switched FluentValidation to camelCase for every validator (brand.Name).
  • Elsa's endpoints (/api/elsa/...) no longer land in the app's OpenAPI document: regenerate OpenAPI snapshots and SDKs of apps with Coworkee.Workflows.Elsa.

0.0.1.27 (2026-10-16)

Fixes

  • Links to addresses of the server (e.g. Sign in at the end of the setup, /bff/login) load from the server again; since the library pages have a catch-all route, the app showed Not found. for them. Nothing to change in apps.

0.0.1.26 (2026-10-16)

Breaking changes

  • ICoworkeeApi gained GetSystemStatusAsync; own implementations add it.
  • Library pages under their own prefix: admin pages of the library moved from /admin/... to /cw/admin/... (CoworkeeClientOptions.PagePrefix, "" keeps the old addresses); old addresses go on to the new ones. The library pages have no @page routes any more, one catch-all page (/{*Path}) renders them: an app with its own catch-all page gets an ambiguous route. Apps can replace or turn off pages by key (options.Pages), see Replacing components.
  • Deployments take the app host's tools along: a published app host now deploys Keycloak, Grafana, WebDataStudio, LibreTranslate and AspireUI too. Apps from an older template copy three things from a new one: in Migrations/Program.cs the seed of InitialAdmin.From(configuration) (with DemoSeed.ConfigureDeployment) and ReconcileKeycloakRealmAsync(), in ServiceDefaults/Extensions.cs the Grafana exporter per signal with GRAFANA_OTLP_PROTOCOL, and in AppHost.cs app.Deploys(...) for Ollama and aspireUi.WithCoworkee(app) for AspireUI. KeycloakRealm moved to Coworkee.Contracts.Identity.
  • Migration needed: new tables cw.PushSubscriptions (Notifications), cw.DataTransferJobs and cw.ImportProfiles (OData, so every app). Workflows and Webhooks bring their own tables when an app adds them.
  • ICoworkeeApi gained AddMailTemplateLanguageAsync, GetPushSettingsAsync, SavePushSubscriptionAsync and DeletePushSubscriptionAsync; own implementations add them.
  • Notification derives from AggregateRoot now (it raises NotificationCreated while push is configured). No schema change from that.
  • IODataClient.ExportAsync and ImportAsync removed: use IDataTransferApi (export of the current view in three formats, the import wizard). Own IODataClient fakes drop the two methods.
  • ODataImportRegistration has Create, Update and Delete instead of Send; AddODataImport takes (Guid? id, row) => command and an optional delete command for updates and undo.
  • CoworkeeODataModule depends on CoworkeeBackgroundJobsModule: imports and large exports run as jobs. Apps from the template have it already (mailing); test hosts set Coworkee:Jobs:ConnectionStringName and create their tables before UseCoworkee().
  • The Import button of CoworkeeDataTable opens the import wizard instead of uploading an Excel file at once; Excel, CSV and JSON exports of OData sets come from the server with the visible columns.
  • Phone layout: apps add viewport-fit=cover to the viewport tag of App.razor (coworkee update does it).
  • New endpoints (push, mail template languages, import and export, record history, workflows, webhooks): regenerate OpenAPI snapshots and SDKs.

coworkee update knows all of these (upgrade rules of 0.0.1.26).

New

  • Template samples: the command palette offers New product (opens the dialog through /catalog/products?new=true) and finds products by name or barcode.
  • Webhooks: rotate secret: a new secret shown once, the old one signs next to it for Coworkee:Webhooks:SecretGracePeriod (24 h), see Webhooks. Two new columns on cw.WebhookSubscriptions (apps with webhooks need a migration).
  • Workflow chips in tables load the states of a page in one request (POST /api/v1/workflows/{entityType}/states, IWorkflowApi.GetStatesAsync) instead of one per row; own IWorkflowApi implementations add the method.
  • Range sliders in column filters: between on number and date columns slides between the smallest and largest value the server reports; a column with a date or number range facet (e.g. the demo's order date) shows that facet's histogram and slider instead of a check box per bucket.
  • System status page for the system organisation (/cw/admin/system-status): versions, database and pending migrations, outbox, background jobs with the last failures, mail, realtime, Redis, files, translation and AI; modules and apps add cards with ISystemStatusContributor, see Admin UI.
  • Workflows and approvals (Coworkee.Workflows, optional): states and guarded transitions per entity type, approvals by roles or users with deadline, reminder and escalation, a history, the components CoworkeeWorkflow, CoworkeeWorkflowActions and CoworkeeWorkflowTimeline and the page Approvals, see Workflows and approvals.
  • Elsa workflows (Coworkee.Workflows.Elsa, optional): Elsa Workflows 3 in the API with Coworkee activities and triggers, see Elsa workflows.
  • Webhooks (Coworkee.Webhooks, optional): endpoints per organisation get signed events (Standard Webhooks style) about changes of opted-in entity sets, workflow transitions and the app's own events, shaped by what the endpoint's owner may read; retries with backoff, switch-off after repeated failures, delivery log, test events and redelivery on /admin/webhooks, SSRF protection. See Webhooks.
  • Import wizard per entity set: CSV, Excel and JSON, detected encoding, separator and header, column mapping with suggestions and saved mappings, conversion with the file's language, preview with the validation of the commands, add, update by key or both, dry run, background job with live progress, file of the failed rows and undo of the last import, see Import and export. Admin page Import and export (/admin/data-transfer, permission DataTransfer.Use; grant it to the roles that should see it). Exports of the current view as Excel, CSV or JSON (format, columns); more than Coworkee:OData:BackgroundExportRows rows (10 000) run as a job with a download notice.
  • Record history and restore (AddEntityHistory, History="true" on CoworkeeDataTable, CoworkeeEntityHistory): timeline with word diff, restore of a state or a single field with preview, deleted records of ISoftDelete sets come back, see Auditing.
  • Command palette (Ctrl+K): pages, records, actions and the assistant as fallback, extensible with AddCommandPaletteProvider, see Command palette.
  • Phone layout of the Blazor shell and the sign-in pages: overflow menu in the app bar, navigation as overlay, full-screen edit sheets, facet menus as bottom sheets, sticky row actions, 44 px touch targets and safe areas, see Phones, installable app and push.
  • Installable app: <Coworkee.Bff.Pwa.CoworkeePwa /> in the head of App.razor links the web manifest in the theme's colours; Coworkee.Bff serves manifest, service worker (it keeps only the offline page), icon and offline page; update and install prompts in the app.
  • Web Push for the notifications: options.UsePush() in Aspire, or Coworkee:Notifications:Push:PublicKey/PrivateKey; users switch it on per device on the notifications page.
  • Languages of mail templates: Add language on Administration > Mail templates adds a variant for a language switched on later, copied or machine translated (texts only, tags and placeholders kept), and removes it again, see Mailing. A mail in a language without a variant uses the default language (organisation, system, Languages page) before English (IDefaultLanguage); machine translation is available to other modules as IMachineTranslator.
  • Deployment: the app host publishes for Docker Compose, Azure Container Apps or Kubernetes (public addresses, token certificates, setup token, the first administrator and the mail server as parameters, stable volumes, fixed ports); the tools of the app host (Keycloak with its realm, Grafana with the app's dashboards, WebDataStudio, LibreTranslate, Ollama, AspireUI) go along with volumes and public addresses, each one can be left out (DeployTool, coworkee deploy --without), Mailpit only with --with mailpit; coworkee deploy compose|azure|k8s asks for the administrator and the mail server and lists every address and the sign-in at the end; Coworkee Studio offers Deploy after creating an app; token certificates can come as Base64 from a secret. Only services that process jobs create the Hangfire schema. See Deployment.
  • CLI: coworkee add/remove turn template options on or off in an existing app (merged into your files, conflicts as .rej, options kept in .coworkee/app.json), coworkee update applies the upgrade rules of the versions in between, coworkee db reset|seed|backup|restore, coworkee entity import --from db|openapi|csv, six starter specs (coworkee specs list|show, coworkee new --template-spec), options --workflows, --elsa, --webhooks and --pwa (on by default). MCP tools add_option and import_entities. See CLI and Starter specs.
  • Studio: open an existing app and change it, My apps (start, stop, links), Start from a template, entity diagram (drag, draw references, auto layout, PNG export) and entity import with a preview.
  • Template: sample products are soft deleted and, with auditing, show their history and come back; the dashboard works on SQLite (it returned 500 there); demo users are seeded only in Development, migrations wait for the database.
  • coworkee doctor compares versions inside an app: dotnet-ef with EF Core, Aspire CLI with the app host's Aspire SDK, coworkee with CoworkeeVersion, and finds ports of the launch profiles in use, each with a fix.
  • Development users stay in step: SyncDevelopmentUsersAsync() (Development only) adds seed users and roles a database set up earlier lacks and gives seed users their seeded password again; the template's migrations host calls it after SeedCoworkeeIdentityAsync(), so changes to DemoUsers.cs reach an existing database.

0.0.1.25 (2026-10-15)

Fixes only: the loading screen script is its own file, so a strict CSP runs it, and app pages are sent with Cache-Control: no-cache, no-store. Nothing to change in apps.

0.0.1.24 (2026-10-15)

Breaking changes

  • ClientEntityIndicator removed: every data table of a mirrored set shows the ClientEntitySwitch in its tool bar (added by AddCoworkeeClientEntities). Delete the <ClientEntityIndicator> lines and an own Compare button from your pages.
  • ODataPicker.Margin (and OptionalODataPicker.Margin) is Margin? now: unset, the picker follows the density of the theme. Code that reads the value as Margin adds ?? Margin.Dense.
  • CliOption (Coworkee.Cli.Spec) gained the constructor parameter DependsOn, OptionDependency gained Or: source compatible, binary incompatible for tools compiled against an older Coworkee.Cli.Spec.
  • LoadingScreenDto gained the positional parameter SignedIn; regenerate OpenAPI snapshots and SDKs.
  • Enums in every MudExObjectEdit render with the EnumEditor (localized labels from EnumLabels, [Flags] as multi select of the single-bit members) and nullable enums with the clearable NullableEnumEditor. A meta's RenderWith still wins.
  • --sign-in-media with the layout Card is ignored (not passed, not copied) unless --loading-screen SignInMedia shows it behind the loading screen.

New

  • Loading screen in the theme's colours with the real download progress, a friendly error state when the start fails, and the user's colour mode, theme and language, see Theming. Every app adds one line as the first line of <body> in MyApp.Web/App.razor: <Coworkee.Bff.CoworkeeLoadingScreen Logo="coworkee-icon.svg" />. Its background (Animated, SignInMedia, Plain) is set on the Sign-in page card, with options.SignIn.LoadingScreen in Aspire or --loading-screen in the CLI. The page is now sent with Cache-Control: no-cache, no-store; the logo comes from /bff/loading-screen/logo, the script from /bff/loading-screen/script.js (no inline script, so apps with a strict Content-Security-Policy keep working).
  • Public files: managers make a file public (PUT /api/v1/files/{id}/public, file manager bar, preview); anyone loads it from GET /api/v1/files/public/{id}/{name}, e.g. as sign-in or loading screen media, picked with Choose from files. The model gained StoredFile.IsPublic: apps with the Files module add a migration.
  • Page mode of data tables: CoworkeeDataTable.PageMode (Pager, EndlessScroll) and the setting DataTable.DefaultPageMode (global and per user), see Data table.
  • Client entity switch in the tool bar of mirrored tables: search in the browser or on the server, sync state as a ring, Compare and choose the faster picks the faster side; the choice is kept per user.
  • ImageDataUrlEdit uploads with MudExUploadEdit; enums get the EnumEditor everywhere (see Breaking changes).
  • The texts of the MudBlazor.Extensions components the library shows (upload field, style and cron editors, file manager, file preview) ship in all languages; their stored machine translations are replaced at the next start.
  • CLI and Studio: options that need another one (--airworks-packages without --airworks, --ai-provider, --ai-model and --ai-endpoint without --ai, --backup off Postgres, --sign-in-media with the layout Card unless the loading screen shows it, --sign-in-media-side without a media) are no longer passed to the template; the CLI warns (coworkee spec validate too) and the Studio hides their cards. Sign-in media of a Card layout is therefore not copied into the app any more. New coworkee spec show and a spec from the Studio that lists every library module with true/false; coworkee options prints Needs: and the websites of the products an option brings, the Studio cards show icons and open buttons, see CLI.

0.0.1.23 and earlier

Breaking changes

  • IMailSender: the interface now requires the six-parameter QueueAsync(to, template, model, culture, campaignId, cancellationToken). The five-parameter overload is a default method that passes null as the campaign. Own implementations (test doubles, wrappers) implement the six-parameter method; callers are unchanged.
  • IMailTemplateRenderer: gained RenderContentAsync(content, layout, model, cancellationToken), which renders with an already resolved layout (the campaign job uses it to resolve template and layout once per run). Own implementations add the method; callers are unchanged.
  • Positional records gained parameters: MailTemplateSummaryDto (IsCustom, Description), MailTemplateDto (IsCustom) and OutgoingMailDto (CampaignId). Code that constructs or deconstructs them positionally, and generated clients, need the new parameters. Regenerate OpenAPI snapshots and SDKs.
  • Removed with the MudEx 9.11.3 adoption: ChipListEditor, CronEditor, CronSchedule and SettingsFormRules.WrapInColumns. Lists of strings render as MudExTagField<string> and [Cron] renders MudExCronEdit; use those directly.

New

  • AirWorks client: chat, reports with their designer, assistant, the administration apps (adminApps) and realtime, see AirWorks client. Generated apps take @coworkee/client and @coworkee/airworks from the tarballs inside the template; every release also publishes them to npm (--airworks-packages npm). coworkee new --template-source adds the local package folder to the app's nuget.config. Apps made with the first AirWorks version: add ...adminApps to ClientApp/src/main.ts and, for the file preview, the MudEx hosting of the template (mudex-webcomponents, vite.config.ts, .dat content type in Program.cs).
  • Mail campaigns with recipient presets, saved queries and manual selection, scheduled sending and an unsubscribe confirmation page, see Mailing.
  • Own mail templates with a visual and a source editor, and a Monaco based CodeEditor component.
  • Entity model changes for campaigns, recipient lists and own templates: add a migration to your app.