Filed unassigned by the #13878 dev seat (session session_0112hMx9hjJ9BgB28X97DS68) under the dispatch's "measure, fix what is in scope, file the rest" clause. Recording + measurement only — no severity asserted; routing and grading are triage's. Generic types are written in SQUARE brackets (the body sanitizer eats the angle-bracket spelling).
What is published
packages/drivers/driver-memory/dist/index.d.ts, built from the tree that PR #14434 ships (source at 2584285bc):
find(object: string, query: DriverQuery, options?: DriverOptions): Promise[any[]];
findOne(object: string, query: DriverQuery, options?: DriverOptions): Promise[any];
create(object: string, data: Record[string, any], options?: DriverOptions): Promise[Record[string, any]];
update(...): Promise[Record[string, unknown] | null]; // un-masked by #14434
upsert(...): Promise[Record[string, unknown]]; // un-masked by #14434
IDataDriver declares find(): Promise[Record[string, unknown][]], findOne(): Promise[Record[string, unknown] | null], create(): Promise[Record[string, unknown]]. The three remaining doors publish any (or Record[string, any]), so a consumer of @objectstack/driver-memory that reads findOne()'s result is never asked to narrow the null arm the contract declares — the same class of silent runtime hazard #13878 closed on update().
Why the doors are any — the channel, measured
private db: Record[string, any[]] (memory-driver.ts) → getTable(): any[] → every row read is any → object spreads and toStoredRecord's T infer any → every inferred return type collapses. toStoredRecord already carries an explicit return type; the any arrives through its type parameter. #13878's PR repairs update / upsert by giving those two doors explicit return types (the minimal honest change), ⛔ not by re-typing the store — because re-typing the store was measured and cascades:
private db: Record[string, Record[string, unknown][]] → 19 errors in the package's tsc program: 4 sites assign mingo results (unknown[]) back into typed rows (lines ~567 / 748 / 814 / 1100 at 79b6a22a5), find() readers in memory-datetime-storage.test.ts lose their field reads, and the write doors infer a too-narrow literal { id: unknown; created_at: unknown; updated_at: string } — the spread { ...row, ...data, id, created_at, updated_at } drops the index signature at the final object literal — which is a second lie, not an honest type.
So the honest repair for the remaining doors is either (a) explicit contract-typed return annotations on find / findOne / create (the shape #14434 used — one line each, no cascade; create already has a comment at memory-driver.ts ~640 saying its annotation was added for exactly this reason, yet it still emits Record[string, any] because its input is Record[string, any]), or (b) a typed store (StoredRow) with the four mingo seams and the spread sites rewritten to keep an index signature — a larger, package-internal refactor. Which one is a triage call; (a) is the one #14434's measurement supports.
What this does NOT claim
Dedup
MCP search_issues, one targeted query (driver-memory InMemoryDriver find findOne create published d.ts resolve to any inferred through backing store any rows type mask) → 12 results, none on this: #13878 (the parent — update() only), #14082 (execute() answers without running), #14121 (database-loader capability predicate), the rest closed and unrelated. Same-session control for the channel: the #13878-title query returned #13878 first.
Related
#13878 (ruling A; PR #14434 un-masks update / upsert) · #14428 (the fabricating drivers, item 5 of the same ruling)
Generated by Claude Code
Filed unassigned by the #13878 dev seat (session
session_0112hMx9hjJ9BgB28X97DS68) under the dispatch's "measure, fix what is in scope, file the rest" clause. Recording + measurement only — no severity asserted; routing and grading are triage's. Generic types are written in SQUARE brackets (the body sanitizer eats the angle-bracket spelling).What is published
packages/drivers/driver-memory/dist/index.d.ts, built from the tree that PR #14434 ships (source at2584285bc):IDataDriverdeclaresfind(): Promise[Record[string, unknown][]],findOne(): Promise[Record[string, unknown] | null],create(): Promise[Record[string, unknown]]. The three remaining doors publishany(orRecord[string, any]), so a consumer of@objectstack/driver-memorythat readsfindOne()'s result is never asked to narrow thenullarm the contract declares — the same class of silent runtime hazard #13878 closed onupdate().Why the doors are
any— the channel, measuredprivate db: Record[string, any[]](memory-driver.ts) →getTable(): any[]→ every row read isany→ object spreads andtoStoredRecord'sTinferany→ every inferred return type collapses.toStoredRecordalready carries an explicit return type; theanyarrives through its type parameter. #13878's PR repairsupdate/upsertby giving those two doors explicit return types (the minimal honest change), ⛔ not by re-typing the store — because re-typing the store was measured and cascades:private db: Record[string, Record[string, unknown][]]→ 19 errors in the package's tsc program: 4 sites assign mingo results (unknown[]) back into typed rows (lines ~567 / 748 / 814 / 1100 at79b6a22a5),find()readers inmemory-datetime-storage.test.tslose their field reads, and the write doors infer a too-narrow literal{ id: unknown; created_at: unknown; updated_at: string }— the spread{ ...row, ...data, id, created_at, updated_at }drops the index signature at the final object literal — which is a second lie, not an honest type.So the honest repair for the remaining doors is either (a) explicit contract-typed return annotations on
find/findOne/create(the shape #14434 used — one line each, no cascade;createalready has a comment at memory-driver.ts ~640 saying its annotation was added for exactly this reason, yet it still emitsRecord[string, any]because its input isRecord[string, any]), or (b) a typed store (StoredRow) with the four mingo seams and the spread sites rewritten to keep an index signature — a larger, package-internal refactor. Which one is a triage call; (a) is the one #14434's measurement supports.What this does NOT claim
anyhides exactly that, which is the finding.InMemoryDriver.update()returnsnullfor a missing id, whichIDataDriver.update()'s declared return type forbids — hidden for the life of the code by an inferredany#13878 ruling named (comment 5494524403 item 2)..d.ts(SqlDriver.updatecarries an explicitPromise[any]atsql-driver.ts:6820— reported in [finding]InMemoryDriver.update()returnsnullfor a missing id, whichIDataDriver.update()'s declared return type forbids — hidden for the life of the code by an inferredany#13878's report, coupled to driver-sql:bulkUpdateis a sequential per-row loop with no transaction — a mid-batch refusal leaves earlier rows committed (driver-turso inherits it viasuper.) #13854).Dedup
MCP
search_issues, one targeted query (driver-memory InMemoryDriver find findOne create published d.ts resolve to any inferred through backing store any rows type mask) → 12 results, none on this: #13878 (the parent —update()only), #14082 (execute()answers without running), #14121 (database-loader capability predicate), the rest closed and unrelated. Same-session control for the channel: the #13878-title query returned #13878 first.Related
#13878 (ruling A; PR #14434 un-masks
update/upsert) · #14428 (the fabricating drivers, item 5 of the same ruling)Generated by Claude Code