Repository navigation
BeechCMS v0.6.1 — Release Notes #192
fdemusso
announced in
Announcements
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.
Released: July 10, 2026
Type: Patch — Bug Fixes & Security Hardening
Repository: fdemusso/BeechCMS
Closes: #184, #183, #182, #178, #139, #166, #162, #159, #136, #137, #134, #140, #158
Overview
v0.6.1is a focused patch release that consolidates bug fixes and security hardening across the validation engine, authentication handlers, Kanban move operations, CORS configuration, rate-limiting, and query filters. It introduces depth and size bounds forjson/tagsbranches, fixes the handling of explicitnullvalues, restores correct top-levelORlogic in engine query filters, and addresses all seven open findings from the security and validation audit tracked in 184.All changes are non-breaking: no HTTP routes, public API payloads, or
@beechcms/corebarrel exports were modified. The full monorepo build and test suites (pnpm build && pnpm test) pass with zero TypeScript errors.Bug Fixes
Validation Engine
Explicit
nullrejection whenallowNull: false—withEmptyPreprocessingpreviously passed explicitnullthrough unchecked when the field'sallowNulloption wasfalse. The value is now correctly rejected. (182)JSON and tags depth/size bounds —
jsonOrTagsSchemaaccepted arbitrarily deep/large payloads with no cap, unlike the richtext branch. The schema is now split intojsonSchema(fail-fast size check + depth-guarded control-char stripping walk) andtagsSchema(z.array(z.string())with a 100-item cap and per-tagcleanString/length checks). This prevents recursion errors and potential DoS on pathological inputs and also fixes thekanban-move.tscast crash caused by non-string tag values. (183)Relation seed schema cached per
idGeneratorinstance —compileSeedSchemaalways recompiled the full Zod tree for seeds with relation branches because the closure overidGeneratorwas skipping the cache entirely. The cache is now partitioned byidGeneratoridentity viaWeakMap, and the singlebuildCacheKey()call is reused on cache miss. (178)isPlainObjectrejects class instances —Date,Map,Set, and other class instances were accepted where a plain object was required. The proto-chain check now rejects anything whose prototype is notObject.prototypeornull. (audit finding Devs #4, 184)isEffectivelyEmptyscoped torichtextbranch only — A JSON field shaped as{ type: 'doc', … }was misclassified as empty because the doc-root check was not gated on the actual branch type. (audit finding docs: aggiorna README e commento sicurezza login #3, 184)sanitizeRichtextJsonwrapsJSON.stringifyintry/catch— Honors the documented "never throws" contract for the sanitizer. (audit finding Dashboard #7, 184)Depth guard added to
gatherRichtextText— ARICHTEXT_MAX_DEPTHconstant now preventsRangeErroron pathological structures. (audit finding Dashboard #8, 184)Repeater sub-field
requiredflag respectsenforceRequiredFields— Sub-fields inside a repeater incorrectly ignored theenforceRequiredFieldsoption. (audit finding Dashboard #5, 184)collectAssetListItemsbounded to 100 items —MAX_ASSET_LIST_ITEMS = 100cap prevents unbounded array processing. (audit finding Feature Request Algolia #10, 184)Clarified "no valid fields" error message — The error returned when a seed payload contains no recognized fields is now unambiguous. (audit finding Aggiornamento di Devs #1, 184)
API Query Filters
OR-group support in engine filter query —logic: 'OR'was accepted and validated by the public API but every condition got mapped into its ownFilterGroup; the engine always joined groups withAND, soORsilently returned narrower results.buildSelectQuerynow honors a newfilterLogicoption to join top-level filter groups withORwhile keeping conditions within a groupAND-ed.status/searchstayAND-ed regardless. (137)Authentication
Email lowercased on login to match signup normalization — Signup stored emails in lowercase, but login lookup was case-sensitive, permanently locking out users who typed their original casing. (158)
(Note: this fix was tracked as auth: case-sensitive email lookup at login vs lowercase normalization at signup — user lockout #158 in the commit history and is included in this release.)
Login
min-lengthcheck aligned withsetup/resetvalidation —validateLoginInputcalledtrim()before the length check, rejecting passwords with trailing whitespace thatsetupandresetalready accepted, permanently locking those users out. (159)Kanban & Content
Duplicate tags on Kanban move prevented — The server-side atomic swap in
kanban-move.tsappendednewValuewithout checking ifwithoutOldalready contained it, causing duplicate tags on retried or cross-source moves. (140)Deleted card evicted from cache on 404 move — A stale cache entry for a deleted card was not cleared when a move operation returned 404, causing subsequent reads to serve ghost data. (139)
findByIdwrapped intry/catchinkanbanPositionHandler— Unhandled exceptions fromfindByIdno longer crash the handler on invalid IDs. (136)Relation label read from flat row, not
item.data—repository.findManyreturns flat rows viarowToData— there is no.dataproperty, soitem.data[labelAlias]threw and was swallowed by the surroundingcatch, leaving the relations map empty. (134)CORS & Rate Limiting
PATCHadded toallowMethods;Idempotency-Keyadded toallowHeaders— Several endpoints (bulk, kanban-move, rename/retype, automation toggle, notifications read/unread) usePATCH, and the public API expectsIdempotency-Keycross-origin. Both were missing from the CORS config, causing preflight failures for cross-origin clients. (166)Public rate-limit key now includes seed from request path — The key generator was not incorporating the request path, causing unrelated routes to share the same rate-limit bucket. (162)
Regression Tests Added
All seven audit findings from 184 are covered by new regression tests co-located with their respective source files (
<filename>.test.ts). Additionally:logic: 'OR'filter group behavior verified end-to-end.nullrejection withallowNull: falseacross all branch types.json/tagsdepth and size cap boundary cases.Closed Issues
nullnot rejected whenallowNull: falseidGeneratorPATCHmethod andIdempotency-Keyheaderlogic: 'OR'silently returns AND resultsfindByIdnot guarded inkanbanPositionHandleritem.datapropertyUpgrade Notes
No migration steps are required. This release contains no schema changes, no new environment variables, and no breaking changes to the HTTP API or SDK surface.
Run the standard update procedure:
This discussion was created from the release BeechCMS v0.6.1 — Release Notes.
All reactions