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

53 lines
3.5 KiB
Markdown

# 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](../forward-look.md) — Repository Layer Strategy section (full analysis)
- [overview.md](../overview.md) — Repository Layer Bridging Pattern
- [sqlite-host.md](../sqlite-host.md) — JSON text for schema columns (ADR-019)
- ADR-018: dbtype integration is post-v1
- ADR-005: Drizzle + TypeBox via drizzlebox