Member Junction
    Preparing search index...
    ENTITY_COMPANY_INTEGRATION_OBJECTS: "MJ: Company Integration Objects" = 'MJ: Company Integration Objects'

    The per-connection catalog: read-side types, column contract, and projection.

    Every connector and every engine read site names an IntegrationObject's properties directly — io.Name appears 241 times across the connectors repository, io.Fields 93, io.APIPath 52. A row loaded for an entity with no registered subclass is a plain BaseEntity: it carries its values in Fields and exposes them through Get(), and every one of those property reads is undefined. So the cache cannot hand connectors the entity rows themselves.

    It hands them PROJECTIONS instead — plain objects carrying exactly the property surface the read sites use. That is not a new idea here: IntegrationEngineBase.SeedForTesting already seeds the shared catalog with "plain objects shaped like the entity (property reads only)" for the same reason, and the replay tiers exercise metadata-driven connectors through them.

    Writes are the other half and do NOT come through here — they go through the store in @memberjunction/integration-engine, which holds real entity rows and uses Get()/Set() exclusively. Assigning row.Name = x on a subclass-less BaseEntity silently creates an own property, Save() sends nothing, and the write is lost with no error anywhere.