v6.1.4: Cache events stop leaking rows, Explorer view tabs stop freezing
Cache-invalidation events no longer broadcast row data to every connected client, opening a saved view in its own tab no longer freezes Explorer, and 5.51 clients can delete records again without knowing about the new SkipRecordChanges option; plus grid export, foreign-key picker and test-harness fixes. No schema changes and no migrations.
Upgrade Notes apply: cache-invalidation events carry row data only for entities you allowlist, and harness data bridges are bounded at 1,000 rows by default.
6.1.4 is the certification candidate for the 6.1 line. It replaces 6.1.3, which carried the first two fixes below as open certification blockers.
MemberJunction 6.x is released under the Business Source License 1.1; 5.x and earlier stay ISC. What the licence grants, and what needs certification, is in the licence section of the v6 upgrade guide.
Bug Fixes
Section titled “Bug Fixes”- Cache-invalidation events no longer carry row data to every client (
@memberjunction/server,@memberjunction/core,@memberjunction/core-entities,@memberjunction/ng-core-entity-forms,@memberjunction/ng-dashboards). ThecacheInvalidationsubscription is delivered to every connected client with no per-user filter, and both publish sites attached the full saved row to every event. Row-level security and any consumer-side scoping apply on the read path, which a push bypasses, so every signed-in session received the contents of rows it had no right to read. The server now populatesrecordDataonly for entities named incacheSettings.recordDataBroadcastEntities, default empty; the entity name and primary key still broadcast, since they tell a consumer which record changed and disclose nothing it could not already derive. Consumers that needed the row, such as the conversation engine and the AI Agent Run form, now re-read that one record by primary key as the signed-in user, so the server decides what comes back, and a session that may not read the record gets nothing rather than someone else’s data. - Opening a saved view in its own tab no longer freezes Explorer (
@memberjunction/ng-explorer-core). The tab configuration stored the prefixed resource type (MJ: User Views) while the loaded view component carried the row name (User Views). The tab sync compared the two exactly, saw every configuration emission as a content change, tore the tab down and reloaded it, and the reload emitted again, so the page never yielded. The reload check now ignores case and theMJ:prefix, the same rule already used to resolve the type. Dynamic views opened from the omnibar (#Accounts,#Contacts) all share one record ID, so the check also compares the tab’s entity and the component cache keys on it: opening#Contactsinto a tab showing#Accountsreloads it instead of retitling the tab over the Accounts grid. - 5.51 clients can delete records again (
@memberjunction/server).DeleteOptionsInput.SkipRecordChangesarrived in 6.1.0 as a required GraphQL field, so every 5.51.x client that spells outoptions___on a delete mutation failed schema validation after the server upgraded, with “of required type Boolean! was not provided”. The field is optional again and defaults tofalse. The server already forced it tofalsefor any wire caller, so absent andfalsemean the same thing. - Grid exports carry the columns the grid shows (
@memberjunction/ng-entity-viewer). Export read the host-declared columns in declared order, while the grid rendered from the saved grid state, or from the live order once a column was dragged, so the file had different columns in a different order from the screen. Export now reads the rendered columns: on-screen order, visible columns only, on-screen headers. The row-number and width-filler columns are left out, and pixel widths are no longer passed through, since Excel read them as character widths. The view workspace’s toolbar Export asks the active renderer for the same list, and for view types without a column layout falls back to the view’s saved columns sorted by their saved order, headed by the user’s rename, and matched to entity fields regardless of case. - “Send Message” is offered only where it can do something (
@memberjunction/ng-entity-viewer). The overflow item appeared on every entity whenever a row was selected. It now shows only when the entity has an active Entity Communication Message Type. The grid’s entity-action auto-load also reads the action engine for the grid’s own provider rather than the global singleton, so a multi-provider client shows the right server’s actions. - A dismissed foreign-key picker stays dismissed (
@memberjunction/ng-base-forms). Escape and leaving the field closed the panel, but a lookup still in flight reopened it when its rows arrived, and a keystroke’s debounced search fired after blur. On a related entity large enough to be looked up from the database, any lookup slower than the blur grace period reopened the list with nothing focused and nothing could then close it. Every dismiss now retires the in-flight lookup and cancels the debounce, a mouse press anywhere outside the field and its panel closes it, an Escape that closes the panel no longer also closes the hosting dialog or slide panel, and destroying or rebinding the field retires its work so late rows cannot land on the next record. - Harness data bridges no longer return unbounded result sets (
@memberjunction/react-test-harness). A generated component could askRunVieworRunQueryfor every row and get it; one component’s query returned over 200,000 rows and exhausted the host process heap, since a bridge result is serialised in Node, shipped to Chromium and rehydrated there. The bridges now clampMaxRowstoComponentExecutionOptions.dataCaps, default 1,000 each, clamping downward only. Each call is recorded on the result’sdataAccesswith rows returned, total row count and whether it was capped, and a capped call raises adata-row-capwarning so a sparser render is not mistaken for a defect. The HTML truncation backstop drops from 100 MB to 25 MB. @memberjunction/ng-hierarchy-treedeclares its licence (@memberjunction/ng-hierarchy-tree). The package was added three days after the relicense to BUSL 1.1 and still carried the old ISC default in its manifest, so it shipped that way in 6.1.3. It now declaresBUSL-1.1like every other published package.
Upgrade Notes
Section titled “Upgrade Notes”- Cache-invalidation events carry row data only for allowlisted entities.
cacheSettings.recordDataBroadcastEntitiesdefaults to[];['*']restores the previous behaviour wholesale. With the default, a remote save of an engine-cachedAutoRefreshentity falls through to a full reload of each matching config rather than an in-place update, because the engine applies a remote save in place only when the row is present. Remote deletes still apply in place from the primary key. Engine-cached reference entities that every signed-in user may read are the ones worth listing. - Test-harness data bridges are bounded at 1,000 rows by default. A component that relied on an unbounded
RunVieworRunQuerythrough the harness now receives at mostdataCapsrows, with the cap reported on the result. RaisedataCapsper run if a component genuinely needs more.