fix: correct orderBy sort for timestamp fields via centralized field resolver

Muse reported that find({ orderBy: 'createdAt' }) silently returned the
wrong order: getFieldValueForEntity read noun.metadata[field] for
timestamp fields, but getNoun() destructures standard fields to the top
level, so the read always returned undefined and the sort collapsed to
insertion order.

The fix introduces a single source of truth for reading fields off an
entity. STANDARD_ENTITY_FIELDS + resolveEntityField() in coreTypes.ts
encode the "standard fields top-level, custom fields nested" contract
in one place. getFieldValueForEntity now uses the helper and routes
through a named BUCKETED_INDEX_FIELDS set instead of a hardcoded
timestamp if-chain — filtered sort on createdAt/updatedAt now works.

Unfiltered orderBy is explicitly rejected with a clear error pointing
callers at the right pattern. A scalable, unfiltered-sort-capable
time-ordered segment index is tracked as a separate follow-up.
This commit is contained in:
David Snelling 2026-04-09 16:26:38 -07:00
parent 086d90d01c
commit be6c4dc182
4 changed files with 343 additions and 29 deletions

View file

@ -2166,6 +2166,21 @@ export class Brainy<T = any> implements BrainyInterface<T> {
const limit = params.limit || 20
const offset = params.offset || 0
// orderBy without any filter is not supported — it would require
// O(N) work across every entity in storage. Consumers must supply
// a filter (`type`, `where`, or `excludeVFS: true`) so the sort
// runs over a bounded, roaring-bitmap-filtered set. The long-term
// fix is a dedicated time-ordered segment index (Track 2).
if (params.orderBy) {
throw new Error(
`find({ orderBy: '${params.orderBy}' }) requires a filter. ` +
`Add 'type', 'where', or 'excludeVFS: true' so the sort runs ` +
`over a bounded set. Unfiltered sort over all entities is not ` +
`scalable with the current index and is tracked as a dedicated ` +
`time-ordered segment index (Track 2).`
)
}
// ExcludeVFS helper - exclude VFS infrastructure entities
// VFS files/folders have vfsType set, extracted entities do NOT
let filter: any = {}