Split out from #952 (now resolved/closed). The cache-reopen cast bridge was fixed in #993 (typed hydrateCacheStore) and the wasm-free typecheck lane landed in #1002 — but the same duck-typing pattern #952 condemned still lives in the ingest paths:
apps/viewer/src/hooks/ingest/viewerModelIngest.ts — createMinimalGlbDataStore() builds a store via a whole-object as unknown as IfcDataStore cast (plus per-field casts).
apps/viewer/src/hooks/ingest/pointCloudIngest.ts — same pattern.
These synthetic stores lack the IfcStoreBase accessors (getEntity / getEntitiesByType / getProperties / getQuantities) and never call attachDataStoreAccessors, yet they route into the live store via useIfcLoader / ViewportContainer → the query path (new EntityNode(model.ifcDataStore) → store.getProperties()).
Why it matters: same crash class as the original cache-reopen bug (#950). A future required-member addition to IfcDataStore stays silently green at these as unknown as sites and throws TypeError: store.getProperties is not a function at runtime on the GLB / point-cloud ingest flow. It also violates the AGENTS.md house rule (no as any / as unknown as escape hatches — fix the types or add a .d.ts).
Fix: replace the casts with a typed builder (analogous to hydrateCacheStore in useIfcCache.ts) that constructs an IfcStoreData and runs it through attachDataStoreAccessors, so the compiler enforces the full IfcDataStore contract for synthetic GLB/point-cloud stores too.
Context: #952, #950, #993, #1002.
Split out from #952 (now resolved/closed). The cache-reopen cast bridge was fixed in #993 (typed
hydrateCacheStore) and the wasm-free typecheck lane landed in #1002 — but the same duck-typing pattern #952 condemned still lives in the ingest paths:apps/viewer/src/hooks/ingest/viewerModelIngest.ts—createMinimalGlbDataStore()builds a store via a whole-objectas unknown as IfcDataStorecast (plus per-field casts).apps/viewer/src/hooks/ingest/pointCloudIngest.ts— same pattern.These synthetic stores lack the
IfcStoreBaseaccessors (getEntity/getEntitiesByType/getProperties/getQuantities) and never callattachDataStoreAccessors, yet they route into the live store viauseIfcLoader/ViewportContainer→ the query path (new EntityNode(model.ifcDataStore)→store.getProperties()).Why it matters: same crash class as the original cache-reopen bug (#950). A future required-member addition to
IfcDataStorestays silently green at theseas unknown assites and throwsTypeError: store.getProperties is not a functionat runtime on the GLB / point-cloud ingest flow. It also violates the AGENTS.md house rule (noas any/as unknown asescape hatches — fix the types or add a.d.ts).Fix: replace the casts with a typed builder (analogous to
hydrateCacheStoreinuseIfcCache.ts) that constructs anIfcStoreDataand runs it throughattachDataStoreAccessors, so the compiler enforces the fullIfcDataStorecontract for synthetic GLB/point-cloud stores too.Context: #952, #950, #993, #1002.