feat(8.0): reserved-field enforcement — reservedFieldPolicy defaults to throw
An untyped (JS) caller that smuggles a Brainy-reserved field (confidence, weight, subtype, visibility, service, createdBy, noun/verb, data, createdAt, updatedAt, _rev) inside a write-path metadata bag previously got a silent remap-or-drop — a class of bug where confidence-evolution writes no-oped for weeks before being caught on read-back. 8.0 closes this with no silent failures. - New BrainyConfig.reservedFieldPolicy: 'throw' | 'warn' | 'remap' (default 'throw'). 'throw' rejects the write naming every offending key + its correct write path; 'warn' remaps with a one-shot per-key warning; 'remap' is the legacy silent path. - Central enforceReservedPolicy gate wired into all four remap methods (add, update, relate, updateRelation) so live calls AND their transact()/with() mirrors honor it. Single-source reservedWritePath guidance shared by throw+warn. - 'warn' now warns for EVERY reserved key (closes the gap where only system-managed fields warned). Dead warnDropped* helpers removed. - Import pipeline migrated to route reserved values (confidence/weight/subtype) through dedicated params and strip reserved keys from extractor/customMetadata bags via the canonical split*MetadataRecord helpers — imports no longer trip the default throw. - Tests: new reservedFieldPolicy matrix (throw/warn/remap across every write path + transact); remap-correctness suite reframed as opt-in 'remap'; shared test-factory no longer emits reserved keys in custom metadata.
This commit is contained in:
parent
ae3fe82fd9
commit
54c7c39669
12 changed files with 605 additions and 190 deletions
|
|
@ -1496,6 +1496,33 @@ export interface BrainyConfig {
|
|||
* (PID liveness + heartbeat) cannot prove it. Logs a warning regardless.
|
||||
*/
|
||||
force?: boolean
|
||||
|
||||
/**
|
||||
* How write paths react when an untyped (JavaScript) caller smuggles a
|
||||
* Brainy-reserved field (`RESERVED_ENTITY_FIELDS` / `RESERVED_RELATION_FIELDS`
|
||||
* — `confidence`, `weight`, `subtype`, `visibility`, `service`, `createdBy`,
|
||||
* `noun`/`verb`, `data`, `createdAt`, `updatedAt`, `_rev`) **inside the
|
||||
* `metadata` bag** of `add()` / `update()` / `relate()` / `updateRelation()`
|
||||
* (and their `transact()` / `with()` mirrors). TypeScript callers can't write
|
||||
* these shapes at all — the compile-time guard on the metadata param types
|
||||
* (`NoReservedEntityKeys` / `NoReservedRelationKeys`) rejects a literal
|
||||
* reserved key — so this policy only governs untyped callers that slip one
|
||||
* past the compiler.
|
||||
*
|
||||
* - `'throw'` (**default, 8.0**): a reserved key in the bag throws a clear
|
||||
* `Error` naming the offending key(s) and the correct write path. No silent
|
||||
* remap, no data loss, no surprise. This is the 8.0 "no silent failures"
|
||||
* contract.
|
||||
* - `'warn'`: legacy remapping with a loud, one-shot (per key, per process)
|
||||
* warning for EVERY reserved key found — user-mutable fields are remapped to
|
||||
* their dedicated top-level param (top-level wins when both are supplied),
|
||||
* system-managed fields are dropped. Use while migrating untyped call sites.
|
||||
* - `'remap'`: the pre-8.0 silent remapping, no warning. Last-resort
|
||||
* compatibility hatch for code that intentionally relies on the bag path.
|
||||
*
|
||||
* @default 'throw'
|
||||
*/
|
||||
reservedFieldPolicy?: 'throw' | 'warn' | 'remap'
|
||||
}
|
||||
|
||||
// ============= Neural API Types =============
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue