The repo currently implements a shared Supabase-backed data layer, but it does not have a single uniform internal model across all products. There are really two levels of internal persistence:
- Client-local persistence in Roam and Obsidian.
- Shared persisted records in Supabase.
The shared Supabase model is the closest thing to a canonical cross-product data layer. Its core persisted records are:
Space,PlatformAccount,AgentIdentifier,LocalAccess,SpaceAccessDocument,ContentConceptResourceAccess,FileReferencecontent_contributors,concept_contributorsContentEmbedding_openai_text_embedding_3_small_1536sync_info
The current system does not persist graph edges or assertions in a dedicated edge table. Instead:
- Node schemas, relation schemas, node instances, and relation instances are all stored in
public."Concept". - A relation instance is represented as a
Conceptrow whose generatedarityis greater than0. - The relation type is carried by
schema_id. - The bound participants are stored in
reference_contentas JSON role bindings, with a generatedrefs BIGINT[]index extracted from that JSON.
This means "relation as first-class object" is only partially implemented:
- Yes in the sense that relation instances are stored as rows with IDs, authorship, timestamps, and schema/type.
- No in the sense that there is no dedicated
Assertion,Edge,Statement,Occurrence, or provenance table in Supabase.
- Schema layer: the conceptual discourse vocabulary in
apps/website/public/schema/dg_base.ttlandapps/website/public/schema/dg_core.ttl, plus some legacy modeling intent inpackages/database/schema.yaml. - Data layer: the SQL schema in
packages/database/supabase/schemas/*.sql, generated types inpackages/database/src/dbTypes.ts, input composites inpackages/database/src/inputTypes.ts, and the client-local stores in Roam and Obsidian. - Transport layer: Next.js API routes under
apps/website/app/api/supabase/*, Roam JSON-LD export inapps/roam/src/utils/jsonld.ts, RID helpers inapps/obsidian/src/utils/rid.ts, and import/export flows.
Question, Claim, Evidence, and Source are not dedicated database tables. They currently exist as:
- Ontology classes in
apps/website/public/schema/dg_core.ttl - Default plugin node types in
apps/obsidian/src/constants.ts - Config-driven node definitions in Roam
So they are schema concepts and seeded configuration, not first-class DB model classes.
Obsidian and Roam do not project equally into the shared data layer:
- Obsidian sync materializes node schemas, relation type schemas, relation triple schemas, node instances, and relation instances into Supabase
Conceptrows. - Roam has local support for stored/reified relation blocks in
apps/roam/src/utils/createReifiedBlock.ts, but the current sync path inapps/roam/src/utils/syncDgNodesToSupabase.tsprimarily upserts node schemas and node instances.
The present data layer is best defined as:
- A client-local discourse model in each app.
- A shared normalized persistence model in Supabase centered on
Concept,Content, andDocument. - A set of transport/export projections that are downstream of those internal structures.
The main gap between current and intended state is that the conceptual ontology treats relation instances more like first-class statements with room for provenance and evidence metadata, while the implemented shared data layer still encodes them as generic Concept rows with JSON role bindings.