Repository navigation
Apostrophe 4.34.0: AI usage tracking and Assembly polish #5669
BoDonkey
announced in
Release Notes
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Hello Apostrophe Community!
Apostrophe 4.34.0 is a maintenance release that builds on the AI connectors and Astro work in 4.33.0, with a focus on Assembly, our multitenant platform for delivering sites to your own customers. AI usage can now be recorded and attributed to each tenant site, and in Assembly projects using Astro, every site now serves its own
robots.txtandllms.txt. The release also brings translation and accessibility fixes in the admin UI and dependency upgrades that address several security advisories.AI Usage Tracking
The new
@apostrophecms/ai:usageevent delivers one record for each provider response, with its token counts. The newusageMetadataoption lets you attach your own attribution to each record, which can help when pricing or billing AI use for your own customers. In Assembly projects, every record automatically names the site it was spent on, or the dashboard. If you offer AI-powered features to your customers, you can see what each tenant uses and price or bill accordingly. Please note that AI providers' billing policies are subject to change. See Tracking AI usage in the documentation for details.The Anthropic, OpenAI and Google adapters also default to newer models. The Google adapter now uses the Gemini Interactions API, so earlier Gemini transcripts lose their reasoning context.
Each Assembly site serves its own
robots.txtandllms.txtAstro now routes literal content files such as
robots.txtandllms.txtto the right site in multisite projects, using the newliteralRoutesScopeoption of@apostrophecms/url. The SEO module also answers these files with a proper 404 or 500 when it has nothing to serve, rather than an empty 200.Security
This release fixes 11 responsibly disclosed security vulnerabilities in core, Import/Export and
sanitize-html. None are rated high severity, but we recommend all users upgrade promptly. This release addresses:viewPermissionfields could appear in related documents and write responses, the public API's sort and filter options could get aroundpublicApiProjection, and the slug check could reveal whether private content existssanitize-html2.18.0 when re-sanitizing certain discarded iframesFull details and reporter credits are in the changelog below and in the published GitHub security advisories.
A few of these fixes change behavior you may be relying on:
publishRole. An editor can no longer change published documents of a type whosepublishRoleisadmin, including through the REST API, without going through the normal publishing workflow.publicApiProjection. If logged-out visitors or your front end sort or filter on a field, add it to the projection. Full text search is unchanged, so mark sensitive text fieldssearchable: false.slug-takenroute now requires the ability to edit content, so guests can no longer call it.Additional Improvements
bestPage, which made the payload about a third larger. Usepageinstead. The changelog below explains how to restore it if you need to.How to Update
Update your projects with
npm updateand let us know what you think on our roadmap.The “stable” option
Everything above reflects our standard “latest” releases. Customers also have the option of following our “stable” release channel. The difference is simple: stable releases receive new features one full quarter later, but receive bug fixes and security fixes at the same time as “latest.” For this to be an effective way to increase stability, customers still need to actively evaluate “latest” so that they have a meaningful head start on what is coming in “stable.” Customers interested in following this path should reach out for complete information on how to point their dependencies to “stable.”
Everything we ship as “latest” is 100% ready for production. The “stable” series is an option for those with a large investment in training, automated testing, etc. It allows delayed implementation of new features without falling behind on fixes.
🚀 Happy coding!
Apostrophe 4.34.0
Adds
@apostrophecms/ai:usageevent: one record per provider response, with its own token counts, and the ability to add attribution via the newusageMetadataoption. This may be helpful in pricing and billing AI use by your own customers. Please note that the billing policies of AI providers are subject to change.robots.txtandllms.txtto the right site in multisite projects, using the newliteralRoutesScopeoption of@apostrophecms/url.Changes
highquality requests.bestPage, which only serves to populatepageand made the payload a third larger; usepageinstead. A project that still needs it can restore it by extending thepruneDataForExternalFront(req, template, data, moduleName)method of@apostrophecms/templateand settingdata.bestPage = req.data.bestPage.testModuleoption now run under mocha 12.Fixes
AposFieldin a widget can be edited as soon as the widget is added or saved in Astro, rather than only after the page is refreshed. Rich text fields in such a widget no longer appear as escaped markup during live preview and inline editing. Empty fields of a widget that was just saved can be selected and edited on the page right away, as they can be in a Nunjucks or JSX project.label, or from itstooltipwhen no label is set. This also covers breadcrumb operations added by project code.sanitizemethod throws aninvaliderror whosedata.errorsentries name fields bypath, the modal switches to that field's tab and displays the message beneath it. Previously the save was blocked with no feedback at all.apostrophe:imagewherever the mouse hovers in the manager modal.data-apos-test="relationship-chooser:<field label>"attribute, so end-to-end tests can find them now that the field label is no longer rendered as atitleattribute on the modal.latin1asmulterdoes by default. Thanks to yoshimasa sugawara for this fix.en.json. Thanks to Michael Lip for the contribution.{{ skipcount }},{{ ancho }},{{ format }}), so values like counts, image dimensions and file types now render in de, es, fr, it, pt-BR and sk. Removes two stale Slovak tag keys.key_1for 2–4,key_2for 0 and 5+), so counts no longer always show the singular. Fixes the German date format rendering "Uhr" as an hour.Security
csv-parseto 7.x to address a security advisory.nodemailerto 10.x to address several security advisories.publicApiProjection, thesortquery parameter and the per-field filter query parameters could operate on fields excluded by the projection, revealing the relative order of hidden values or which documents had a given hidden value. Sort keys and field filters not permitted by the projection are now ignored for these requests. In addition, the related pages embedded in anonymous page REST API responses (_ancestorsand_children) were not limited topublicApiProjectionwhen the projection includedpath; they now are. Authenticated requests and API key requests are not affected. Only sites that setpublicApiProjectionwere affected. Full text search (search,autocomplete) is unchanged: it covers every field not markedsearchable: false, exactly as the public site search does, so sensitive text fields should be markedsearchable: false(CWE-200, CWE-639, GHSA-rqgm-cfrp-4hx8). Thanks to N.HARSHA VARDHAN for reporting the vulnerability.viewPermissionare now removed from every document in every REST API response (apiRoutesandrestApiRoutesof all modules) for a user who lacks that permission, not just from the documents requested from the page and piece REST APIs. This includes documents loaded through relationships (also nested and reverse relationships, and relationships inside widgets, array fields and object fields), the related pages embedded in page responses (_ancestorsand_children), the home page response, pageautocompleteresults, areas rendered withrender-areas, and the documents returned after a write:POST,PUTandPATCH(including archiving, restoring and moving pages), publish, unpublish, revert, localize and share, as well asGET /api/v1/@apostrophecms/doc/:_idand a single document version. The document version history also no longer reveals changes to those fields: the change list of a version (GET /api/v1/@apostrophecms/document-versions/:versionId/changes) leaves them out, the change counts of the version list and of a single version no longer count them, and a version's document withannotate=1no longer highlights them as changed. Saving a document without those fields in the request body still leaves their stored values untouched, as before. Each document is filtered according to its own type's schema. Aprojectquery parameter can also no longer excludetypeormetaType, which could previously be used to keep a page's restricted fields in the response. The reported problems withGET /api/v1/@apostrophecms/page/:_id, which in 4.32.2 and earlier ignored type-levelviewRoleand did not removeviewPermissionfields, were already corrected in 4.33.0 and are now covered by additional tests. EnforcingviewRoleon that route was always the intended behavior, and the earlier behavior was a bug that should not have been relied upon. This only affects sites that useviewPermission. Anonymous visitors were affected only where apublicApiProjectionincludes a relationship to documents of a type with such fields (CWE-200, CWE-863, GHSA-vh56-5m88-39rq). Thanks to harshavardhan98899-lab for reporting the vulnerability.slug-takenroute of@apostrophecms/doctold any logged-in user, including guests who cannot edit anything, whether a slug was in use, even by documents they could not view. It now requires the ability to edit content (theview-draftpermission held by contributors, editors and admins). Because slugs are unique across all documents, users who can choose a slug still learn that it is already taken; this is inherent in globally unique slugs, and the route reveals nothing about the document beyond that (CWE-200, CWE-203, GHSA-f66c-mpj2-3r8h). Thanks to T.Jaswanth for reporting the vulnerability.publishRole. A type'spublishRolewas always meant to govern its published content, but an editor could change published documents of a type whosepublishRoleisadmin, including through the REST API and Import/Export, without publishing them through the normal workflow. That was a bug and should not have been relied upon. Types withautopublish: true, types without a draft/published distinction, and permission checks made with a type name rather than a document are unchanged (CWE-285, CWE-863, GHSA-5m22-7pfq-vp65). Thanks to Mufeed VH and Vivek R for reporting the vulnerability.styleandclassattributes without HTML attribute escaping, so a project-defined free-formstringstyle field could be used by an editor to inject additional HTML attributes into the published page. All attribute values rendered bygetWidgetAttributes()and theapos.styles.attributes()helper are now escaped. Only projects that define a free-form style field are affected, and exploitation requires permission to edit the widget (CWE-79, CWE-116, GHSA-7jg5-frgc-c67w). Thanks to Fariskhi Vidyan for reporting the vulnerability.rgb(),hsl()or similar color, so extra content before or after the color was stored as-is. When such a color is used by a widget style field rendered inline (noselector), that content reached the wrapper'sstyleattribute and could inject HTML attributes into the published page. The whole value must now be a valid color, otherwise it is discarded like any other invalid color. Legitimate values (hex, named colors,transparent,rgb()/rgba()/hsl()/hsla()notations, CSS variable names) are stored unchanged. Exploitation requires permission to edit content using a color field (CWE-20, CWE-79, GHSA-vmgj-9cwm-cf3h). Thanks to N.HARSHA VARDHAN for reporting the vulnerability.Pro Modules
@apostrophecms-pro/cypress-tools1.0.0-beta.31Automated functional browser tests are an important part of quality assurance for enterprise websites and web applications. Cypress is an industry-standard, open-source library for carrying out automated functional browser tests. This module provides a collection of conveniences for testing ApostropheCMS sites and applications within Cypress. Contact us or visit our new pricing page to learn more.
Fixes
getRelationshipPagesModalfinds the chooser by itsdata-apos-testmarker. Apostrophe no longer renders the relationship label as a title attribute on the modal, which the command relied on.@apostrophecms-pro/data-set2.1.1This module provides an easy avenue for low-code data presentation. It creates a data-set piece for the import of comma-separated values (CSV) files. A separate widget allows for the dynamic selection of columns, and display of the data as an HTML table, or in other templates provided by the developer. Contact us or visit our pricing page to learn more.
Security
csv-parseto 7.x to address a security advisory.@apostrophecms-pro/multisite4.7.0This module lets you have many ApostropheCMS websites running on a single codebase in a single Node.js process. Each has its own database, users, media uploads, etc. Sites can be created and managed via a dashboard site. Explore our documentation to discover how this extension can enhance your project. For further details or inquiries, feel free to contact us or visit our pricing page.
Adds
usageMetadataoption of@apostrophecms/ai. See "AI usage per site" in the README.Fixes
robots.txt,llms.txtand similar files.@apostrophecms-pro/multisite-dashboard1.8.1This extension creates the new default multisite dashboard with infinite scroll, search functionality, and the ability to save templates. This extension requires that the project also have the
@apostrophecms-pro/multisiteextension installed and configured. Explore our documentation to discover how this extension can enhance your project. For further details or inquiries, feel free to contact us or visit our pricing page.Fixes
site:transition-shortnametask no longer crashes when it has to fall back to the slug for a site's short name.Free Modules
@apostrophecms/ai-helper1.0.0-beta.14This module enhances Apostrophe with AI-driven helpers. Currently this module offers:
See the extension page for more info.
Fixes
@apostrophecms/apostrophe-astro1.17.0This module integrates ApostropheCMS into your Astro application.
Adds
robots.txtandllms.txtto the right site in multisite projects, using the newliteralRoutesScopeoption of@apostrophecms/url.Fixes
AposFieldin a widget can be edited as soon as the widget is added or saved in Astro, rather than only after the page is refreshed. Rich text fields in such a widget no longer appear as escaped markup during live preview and inline editing. Empty fields of a widget that was just saved can be selected and edited on the page right away, as they can be in a Nunjucks or JSX project.@apostrophecms/form1.5.6Allow ApostropheCMS editors to build their own forms. They can then place any form in one or more content areas across the website.
Fixes
key_1for 2–4,key_2for 0 and 5+), so counts no longer always show the singular. Fixes the German date format rendering "Uhr" as an hour.@apostrophecms/form-submission-google1.0.4This module adds an additional form submission option to Apostrophe Forms. It allows website managers to configure individual forms to submit to a specific Google Docs spreadsheet.
Security
googleapisto the latest version to addressnode-forgeanduuidsecurity advisories.@apostrophecms/i18n-static1.2.1This module makes it possible to edit the translations of static text strings found in templates through the ApostropheCMS admin UI.
Fixes
key_1for 2–4,key_2for 0 and 5+), so counts no longer always show the singular. Fixes the German date format rendering "Uhr" as an hour.@apostrophecms/import-export3.7.1This module enables import and export of pages and pieces, with or without related documents such as files, images and other related types.
Fixes
en.json. Thanks to Michael Lip for the contribution.{{ skipcount }},{{ ancho }},{{ format }}), so values like counts, image dimensions and file types now render in de, es, fr, it, pt-BR and sk. Removes two stale Slovak tag keys.Security
csv-parseto 7.x to address a security advisory.importLimitsoption of the module. Everything an import uploaded or extracted is removed whenever it fails. Exploiting this required a logged-in user (CWE-400, CWE-409, CWE-459, GHSA-9g7p-m758-rp72). Thanks to Mufeed VH and Vivek R for reporting the vulnerability.publishRoleisadmin. Import now refuses documents whose mode, locale and_iddisagree, and relies on the correctedpublishRolecheck in Apostrophe 4.34.0 for the rest. Exploiting this required a logged-in user allowed to import the type (CWE-285, CWE-863, GHSA-5m22-7pfq-vp65). Thanks to Mufeed VH and Vivek R for reporting the vulnerability./uploads/exports/URL until they expire, and their file names were built only from the site's short name, the exported type and a timestamp to the second, so anyone could guess the URL of a fresh export and download it without logging in. Export file names now include a random, unguessable id, and the type in the name is reduced to a slug so it can no longer place the file outside the exports folder. Exposure was limited: a privileged user had to have just run an export, and the download is removed after 10 minutes by default (CWE-200, CWE-330, GHSA-5gc8-frw3-3vqm). Thanks to tikisan_ for reporting the vulnerability.clean-exportandoverride-duplicatesroutes did not require a login. Also,clean-exportwould discard the pending files of an import started by someone else and mark any import job as completed, without checking who owned either. Both routes now require a logged-in user.clean-exportonly acts on an import uploaded by the caller, and only ends that caller's own job. Import jobs are now recorded as belonging to the user who started them. Exposure was limited because the pending import's ID is random and only shown to the user who uploaded it, so in practice an attacker could only interfere with an import they could already identify (CWE-306, CWE-862, CWE-639, GHSA-rw26-wwfc-9wvm). Thanks to Liuhuo Wan for reporting the vulnerability.@apostrophecms/seo1.7.1Comprehensive SEO module providing meta field management and Schema.org structured data generation (JSON-LD) for all pages and pieces.
Fixes
llms.txtandrobots.txtno longer answer 200 when they have nothing to serve: a disabledllms.txtanswers 404, and a failure while generating either file answers 500.Utilities
sanitize-html2.18.1This module provides a simple HTML sanitizer with a clear API.
Changes
Remove the
deepmergedependency, which was used only to combine tag-specific and*(all tags) entries inallowedClassesandallowedStyles. That is now done by a few lines of code within sanitize-html.This is not a fix for a vulnerability in sanitize-html. Security scanners such as Snyk now report CVE-2026-93753 in
deepmerge, which can affect applications that merge untrusted objects, such as parsed JSON request bodies. sanitize-html only ever merged the developer's own configuration, never anything taken from the HTML being sanitized, so it was not exploitable through sanitize-html. Since we needed only a small part of whatdeepmergedoes, we removed the dependency so that these reports no longer appear for sanitize-html users.Security
<iframe>was re-sanitized by a recursive call with no limit, one level per nested unclosed<iframe>. A few kilobytes of crafted input could throwRangeError: Maximum call stack size exceededwith the default options, and thenestingLimitoption was not enforced across the fallback because each nested call started counting from zero. The fallback of a discarded<iframe>is still sanitized and kept, but only up to eight nested<iframe>elements (deeper fallback is escaped as text, as before 2.18.0), and the current nesting depth now carries into the nested call sonestingLimitapplies to the whole output. Only 2.18.0 was affected, and the exception is thrown synchronously, so applications that catch errors fromsanitizeHtmlonly lost the affected request (CWE-674, GHSA-c9rx-x947-fp3h). Thanks to hkmj19, JohnBeckley, and amikhailovstiltsoft for reporting the vulnerability.uploadfs1.28.1uploadfscopies files to a web-accessible location and provides a consistent way to get the URLs that correspond to those files. uploadfs can also resize, crop and autorotate uploaded images. uploadfs includes S3-based, Azure-based, GCS-based and local filesystem-based backends and you may supply others.Security
@google-cloud/storagedependency to 8.x to address auuidsecurity advisory. The Google Cloud Storage backend now requires Node.js 22 or later.All reactions