docs: restructure architecture docs to flowgraph pattern

- Create decisions/ directory with 32 numbered ADRs (ADR-001 through ADR-032)
  extracted from inline DD/SD/ED/SE decision sections
- Create open-questions.md with 16 OQs organized by theme, cross-referenced
  to ADRs, with status tracking (resolved/open)
- Create README.md as architecture index with doc table, ADR table, and
  lifecycle status definitions (draft/reviewed/stable/deprecated)
- Replace inline decision sections in all spec docs with ADR reference tables
- Replace inline open questions with OQ references to centralized tracker
- Update frontmatter: metagraph-module.md, overview.md, sqlite-host.md → reviewed;
  schema-evolution.md and encrypted-data.md remain draft
- DD1-DD10 → ADR-009 through ADR-018
- D1-D8 → ADR-001 through ADR-008
- SD1-SD5 → ADR-019 through ADR-023 (SD5 folded into ADR-006/008)
- ED1-ED5 → ADR-023 through ADR-027
- SE1-SE5 → ADR-028 through ADR-032
This commit is contained in:
2026-05-29 07:19:03 +00:00
parent 6c3ed598db
commit 67ccfbf928
39 changed files with 1117 additions and 435 deletions

View File

@@ -1,6 +1,6 @@
---
status: draft
last_updated: 2026-05-28
status: reviewed
last_updated: 2026-05-29
---
# SQLite Host
@@ -260,53 +260,16 @@ Drizzle database instance with the full schema attached. This enables:
## Design Decisions
### SD1: JSON text vs. JSONB in SQLite
All design decisions are documented as ADRs in [decisions/](decisions/).
SQLite stores JSON as `text` with `{ mode: "json" }`. PostgreSQL uses native
`jsonb`. This means:
- SQLite cannot query inside JSON columns efficiently (no GIN indexes)
- SQLite JSON validation relies on application-level checks (TypeBox schemas)
- PostgreSQL will get queryability benefits for JSON columns
The trade-off: SQLite is for spokes (local, infrequent queries), PostgreSQL is
for the hub (frequent, complex queries).
### SD2: No `nodeTypeId` on nodes
Nodes don't carry a direct FK to `node_types`. The node type is enforced at the
application layer. Reasons:
- Graph type schemas define which node types are valid. Adding a FK would
duplicate this constraint.
- Node types can evolve (schemas can change) without requiring node row updates.
- The repository layer validates node attributes against the appropriate node
type schema before insertion.
This may change if query performance requires filtering nodes by type. A
`nodeTypeId` column can be added as a denormalized index.
### SD3: Edge identity uses consumer-defined keys
Edges use `(graphId, key)` as their unique identity. The `key` is
consumer-defined, matching the metagraph model where consumers control
identifiers. For anonymous edges (common in simple graphs), `key` can be
auto-generated.
### SD4: Composite foreign keys for node references
Edges reference nodes via composite FKs:
`(graphId, sourceNodeKey) → (nodes.graphId, nodes.key)`. This ensures
referential integrity within a graph and cascades node deletions to connected
edges.
### SD5: Enum pattern — `as const` objects, not TypeScript enums
All enumerations use the `as const` object pattern (e.g.,
`GRAPH_STATUS = { Active: "active", ... } as const`) rather than TypeScript
`enum`. This matches the `ACTOR_TYPE` pattern in `common.ts` and avoids JSR
slow-type issues. The TypeBox schema is a `Type.Union` of `Type.Literal` values
derived from the object.
| ADR | Decision | Summary |
|-----|----------|---------|
| [019](decisions/019-json-text-for-schema-columns.md) | JSON text for schema columns in SQLite | SQLite uses `text` with JSON mode; application-level validation |
| [020](decisions/020-no-nodetypeid-on-nodes.md) | No nodeTypeId on nodes | Node type enforced at application layer, not via FK |
| [021](decisions/021-edge-identity-uses-consumer-keys.md) | Edge identity uses consumer-defined keys | `(graphId, key)` as unique identity within a graph |
| [022](decisions/022-composite-fks-for-node-references.md) | Composite foreign keys for node references | Edges reference `(graphId, sourceNodeKey) → (nodes.graphId, nodes.key)` |
| [006](decisions/006-enum-pattern-as-const-objects.md) | `as const` objects, not TypeScript enums | `GRAPH_STATUS`, `ACTOR_TYPE` use const objects; TypeBox uses Literal unions |
| [008](decisions/008-common-columns-pattern.md) | Common columns pattern | `id`, `metadata`, `createdAt`, `updatedAt` on every table |
## Metadata Convention