Files
storage/docs/architecture/decisions/033-json-path-queries-for-v1.md
glm-5.1 a2ee452a63 Add repository layer strategy: JSON path queries, CRUD decisions, ecosystem integration
Add three open questions (OQ-17, OQ-18, OQ-19) covering attribute query
strategy, CRUD generation approach, and storage-operations bridge placement.
Create ADR-033 recording the v1 decision: JSON path queries for attributes
with hand-written CRUD for static tables.

Expand forward-look.md with Repository Layer Strategy section analyzing
three approaches (JSON path, native columns via dbtype, hybrid) and their
implications for the metagraph pattern. Add drizzle-graphql and dbtype
from-dbtype comparison showing neither handles dynamic schema-as-data.

Update overview.md with dbtype/ujsx in the dependency diagram, expanded
ecosystem context in the bridging pattern section, and new open questions.

Align open-questions.md: resolve OQ-17 and OQ-18 for v1 (ADR-033), add
OQ-19 as open, update summary counts and ADR impact table.
2026-05-30 11:02:49 +00:00

3.5 KiB

ADR-033: JSON path queries and hand-written CRUD for v1 repository layer

Status

Accepted

Context

The repository layer is the next major feature for @alkdev/storage. It needs to provide typed CRUD operations for the 6 metagraph tables and query capability for node/edge attributes stored as JSON columns.

The metagraph pattern stores node and edge attributes as JSON (attributes text not null default '{}' with JSON mode in SQLite, jsonb in PG). This is fundamental to the design — node types are dynamic schemas defined at runtime and stored in node_types.schema, not static columns known at database definition time.

Three approaches exist for querying attributes:

  1. JSON path queries: Map filter criteria to json_extract() (SQLite) or ->> / #>> (PG). Works with current table definitions. No native index support on individual attributes.

  2. Native columns via dbtype: Render the metagraph tables via @alkdev/dbtype element trees and make attributes native columns. Conflicts with the metagraph's dynamic schema model — attributes are runtime data, not static columns.

  3. Hybrid: dbtype renders the 6 static tables. Attributes remain JSON (dynamic schema requirement). CRUD for static tables could be auto-generated. Graph-specific queries use JSON path. Virtual columns for frequently queried attributes as a later optimization.

Separately, the CRUD operations for the 6 metagraph tables (insert graph type, find node by key, etc.) could be hand-written, auto-generated from Drizzle schemas (drizzle-graphql pattern), or auto-generated from dbtype element trees (the from-dbtype adapter pattern).

Decision

For v1:

  1. Attribute queries use JSON path extraction (json_extract on SQLite, ->>/#>> on PG). This preserves the metagraph's dynamic schema model. Native column indexes on individual attributes are not available in v1.

  2. Static table CRUD operations are hand-written with explicit function signatures (findNode(graphId, key), insertNodeType(...), etc.). No auto-generation from Drizzle or dbtype.

  3. dbtype integration is deferred (per ADR-018). The hybrid approach remains viable for a future iteration but is not the v1 path.

  4. Virtual/computed columns for frequently queried attributes are a post-v1 optimization, not a v1 design concern.

The repository layer will have two parts:

  • Static table CRUD: Insert, find, update, delete for graph_types, node_types, edge_types, graphs, nodes, edges, actors.
  • Graph data queries: JSON path queries against node/edge attributes, validated by the Module schema at the application layer.

Consequences

  • v1 repository API uses JSON path for attribute queries — no native SQL indexes on attributes
  • CRUD function signatures are known and explicit — no generated code surface to learn
  • PG can add GIN indexes on jsonb columns for containment queries, but not for arbitrary key-value lookups
  • The hand-written CRUD path doesn't block any future auto-generation approach (dbtype from-dbtype, drizzle-graphql pattern, or a from-storage adapter in @alkdev/operations)
  • The metagraph's dynamic schema model is preserved — attributes are always JSON, not static columns

References

  • forward-look.md — Repository Layer Strategy section (full analysis)
  • overview.md — Repository Layer Bridging Pattern
  • sqlite-host.md — JSON text for schema columns (ADR-019)
  • ADR-018: dbtype integration is post-v1
  • ADR-005: Drizzle + TypeBox via drizzlebox