Context
Realtime stores can receive unsolicited server pushes through the existing Neo.data.Pipeline -> Neo.data.Store path. Today that path is useful for record updates that are already present in the store, but it cannot surface a server-created record in a bound view unless application code reloads or patches the store separately.
The current implementation is intentionally conservative, and the source already marks the missing insert behavior as a future enhancement:
if (record) {
record.set(data)
} else {
}Live source check: src/data/Store.mjs:1131 currently looks up the pushed key and only calls record.set(data) when the record already exists. src/data/Pipeline.mjs:211 processes unsolicited connection pushes through the parser/normalizer path and forwards the shaped data as a push event. learn/guides/datahandling/DataPipelines.md:192 documents websocket push reactivity for existing records, but does not define safe insert or upsert semantics for unknown keys.
The Problem
Neo.data.Store#onPipelinePush() drops keyed pushes whose id is not already present in the store. That default is safe, but it leaves a framework gap for realtime CRUD stores: a server-pushed create event cannot appear in the bound grid/table through the standard pipeline path.
Application code can work around this with custom listeners, explicit reloads, or request/response patching, but the framework primitive should be available at the store level so applications can opt into well-defined behavior for newly-created records.
The Architectural Reality
Neo.data.Pipeline#onConnectionPush() receives unsolicited connection push data, optionally runs parser and normalizer steps, then fires push with the shaped payload.
Neo.data.Store#afterSetPipeline() subscribes the store to pipeline push events.
Neo.data.Store#onPipelinePush() extracts data[me.getKeyProperty()], calls me.get(id), and updates only existing records.
- Unknown keyed pushes are currently ignored.
Store already has local and remote projection controls that affect safe insertion semantics: filters, sorters, remoteFilter, remoteSort, currentPage, and pageSize.
- Existing unit coverage includes
test/playwright/unit/data/PipelinePush.spec.mjs for pipeline push forwarding and test/playwright/unit/data/StorePush.spec.mjs for updating existing records through record.set().
The Fix
Add an explicit store-level opt-in for unknown keyed push records.
One possible API shape:
pushInsertStrategy: false | 'insert' | 'upsert' | 'reload' | 'reloadWhenUncertain'
A smaller first pass is also acceptable:
autoInsertPushes: false
The implementation must keep the default behavior unchanged. When opt-in behavior is enabled, unknown keyed pushes may be inserted/upserted only under documented, fail-safe projection rules.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
Neo.data.Store#onPipelinePush() |
src/data/Store.mjs:1131 |
Continue updating known ids; support opted-in handling for unknown keyed pushes. |
Default remains ignore unknown ids. |
learn/guides/datahandling/DataPipelines.md |
Unit tests for known update, default ignore, and opt-in handling. |
| Store opt-in config |
New src/data/Store.mjs config |
Let applications choose insert/upsert/reload semantics for unknown pushes. |
false / disabled. |
Store config docs and DataPipelines guide. |
Unit tests covering local and uncertain remote projections. |
| Local projection handling |
Store filters / sorters behavior |
Respect local filters and local sorting when inserting/upserting from push data. |
Do not make filtered-out records visible. |
DataPipelines guide caveats. |
Unit test with a filtered-out pushed record. |
| Remote projection handling |
Store remoteFilter, remoteSort, currentPage, pageSize configs |
Avoid silently corrupting remote-filtered, remote-sorted, or paginated visible projections when membership/order cannot be proven. |
Reload or mark invalid/uncertain according to the selected strategy. |
DataPipelines guide caveats. |
Unit tests for remote-filter or pagination uncertainty. |
Decision Record Impact
none
Acceptance Criteria
Out of Scope
- Designing a full server mutation-event protocol for every CRUD operation.
- Making blind insertion the default behavior for all stores.
- Replacing the existing request/response RPC flow.
- Solving authorization or transport-level event validation.
Avoided Traps
- Do not auto-add every unknown id. Filtered stores, remotely sorted stores, paginated stores, and incomplete payloads make blind insertion incorrect.
- Do not treat delete or invalidate payloads as full records.
- Do not hide uncertainty behind a successful local insert when the server owns the projection.
Creation Checks
- Live latest-open sweep: checked the latest 20 open GitHub issues at 2026-07-01T13:12:44Z; no equivalent issue found.
- Live issue search: searched for
onPipelinePush autoInsertPushes pipeline push Store; no equivalent issue found.
- Local content sweep: searched committed issue/discussion snapshots for
onPipelinePush, autoInsertPushes, pushInsertStrategy, unknown keyed push, unknown id, and pipeline push; no equivalent issue found.
- Knowledge Base sweep: found closed related pipeline-update context (
#9564, #9449), but no equivalent unknown-id insert/upsert issue.
- A2A in-flight sweep: checked recent messages for overlapping lane claims immediately before creation; no competing claim found.
Related
src/data/Store.mjs
src/data/Pipeline.mjs
learn/guides/datahandling/DataPipelines.md
test/playwright/unit/data/StorePush.spec.mjs
test/playwright/unit/data/PipelinePush.spec.mjs
Handoff Retrieval Hint: "Store onPipelinePush unknown keyed websocket push insert upsert projection"
Context
Realtime stores can receive unsolicited server pushes through the existing
Neo.data.Pipeline->Neo.data.Storepath. Today that path is useful for record updates that are already present in the store, but it cannot surface a server-created record in a bound view unless application code reloads or patches the store separately.The current implementation is intentionally conservative, and the source already marks the missing insert behavior as a future enhancement:
if (record) { record.set(data) } else { // Future enhancement: handle inserts based on a config (e.g. autoInsertPushes) // me.add(data); }Live source check:
src/data/Store.mjs:1131currently looks up the pushed key and only callsrecord.set(data)when the record already exists.src/data/Pipeline.mjs:211processes unsolicited connection pushes through the parser/normalizer path and forwards the shaped data as apushevent.learn/guides/datahandling/DataPipelines.md:192documents websocket push reactivity for existing records, but does not define safe insert or upsert semantics for unknown keys.The Problem
Neo.data.Store#onPipelinePush()drops keyed pushes whose id is not already present in the store. That default is safe, but it leaves a framework gap for realtime CRUD stores: a server-pushed create event cannot appear in the bound grid/table through the standard pipeline path.Application code can work around this with custom listeners, explicit reloads, or request/response patching, but the framework primitive should be available at the store level so applications can opt into well-defined behavior for newly-created records.
The Architectural Reality
Neo.data.Pipeline#onConnectionPush()receives unsolicited connection push data, optionally runs parser and normalizer steps, then firespushwith the shaped payload.Neo.data.Store#afterSetPipeline()subscribes the store to pipelinepushevents.Neo.data.Store#onPipelinePush()extractsdata[me.getKeyProperty()], callsme.get(id), and updates only existing records.Storealready has local and remote projection controls that affect safe insertion semantics:filters,sorters,remoteFilter,remoteSort,currentPage, andpageSize.test/playwright/unit/data/PipelinePush.spec.mjsfor pipeline push forwarding andtest/playwright/unit/data/StorePush.spec.mjsfor updating existing records throughrecord.set().The Fix
Add an explicit store-level opt-in for unknown keyed push records.
One possible API shape:
pushInsertStrategy: false | 'insert' | 'upsert' | 'reload' | 'reloadWhenUncertain'A smaller first pass is also acceptable:
autoInsertPushes: falseThe implementation must keep the default behavior unchanged. When opt-in behavior is enabled, unknown keyed pushes may be inserted/upserted only under documented, fail-safe projection rules.
Contract Ledger
Neo.data.Store#onPipelinePush()src/data/Store.mjs:1131learn/guides/datahandling/DataPipelines.mdsrc/data/Store.mjsconfigfalse/ disabled.filters/sortersbehaviorremoteFilter,remoteSort,currentPage,pageSizeconfigsDecision Record Impact
none
Acceptance Criteria
onPipelinePush()update behavior for known ids remains unchanged by default.learn/guides/datahandling/DataPipelines.mddocuments websocket push insert/upsert semantics, defaults, and caveats.Out of Scope
Avoided Traps
Creation Checks
onPipelinePush autoInsertPushes pipeline push Store; no equivalent issue found.onPipelinePush,autoInsertPushes,pushInsertStrategy,unknown keyed push,unknown id, andpipeline push; no equivalent issue found.#9564,#9449), but no equivalent unknown-id insert/upsert issue.Related
src/data/Store.mjssrc/data/Pipeline.mjslearn/guides/datahandling/DataPipelines.mdtest/playwright/unit/data/StorePush.spec.mjstest/playwright/unit/data/PipelinePush.spec.mjsHandoff Retrieval Hint: "Store onPipelinePush unknown keyed websocket push insert upsert projection"