Reorient @alkdev/storage around a single SQLite database host with Honker
for pub/sub, event streams, and task queues. PostgreSQL is removed as a
target (ADR-038), eliminating dual schema maintenance and infrastructure
complexity. Honker provides DB + pubsub + queues in one .db file (ADR-039).
Add system/tenant DB model (ADR-040): identity tables in system.db, all
graph data in tenant-{orgId}.db files. Identity tables move from the hub
into storage (ADR-041). Scoping columns (ownerId, projectId) added to
graphs table (ADR-042). Graph types get scope (system/tenant/user) to
protect infrastructure schemas (ADR-043).
Define Drizzle-Honker session adapter (ADR-044): ~100-line adapter enabling
Drizzle typed queries and Honker pubsub/queue on a single connection with
transactional consistency.
Resolve OQ-03, OQ-04, OQ-19, OQ-21, OQ-22, OQ-23, OQ-24. Add new
open questions OQ-26 through OQ-29 for Honker integration specifics.
New docs: honker-integration.md (adapter, event patterns, migration).
Scrub all PG/jsonb/libsql references from existing spec docs.
42 lines
1.9 KiB
Markdown
42 lines
1.9 KiB
Markdown
# ADR-045: Organization Members as Authoritative SQL Table, BelongsToEdge as Derived
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Context
|
|
|
|
OQ-23 asked whether `BelongsToEdge` in the ACL graph should be derived (materialized from `organization_members`) or primary (ACL graph is the source of truth).
|
|
|
|
The ACL graph needs `BelongsToEdge` for traversal-based permission evaluation (ADR-034). The hub needs `organization_members` for fast SQL lookups ("list all members of org X", FK constraints on cascading behavior).
|
|
|
|
Two sources of truth for the same data creates a consistency risk.
|
|
|
|
## Decision
|
|
|
|
`organization_members` is the authoritative SQL table. `BelongsToEdge` in the ACL graph is derived.
|
|
|
|
When org membership changes, the consumer (hub) writes to `organization_members` first, then creates or removes the corresponding `BelongsToEdge` in the ACL graph instance. The ACL edge mirrors the SQL table; it does not define it.
|
|
|
|
If the two fall out of sync, the SQL table is the source of truth. An audit/reconciliation process can re-derive ACL edges from the SQL table.
|
|
|
|
## Consequences
|
|
|
|
**Positive:**
|
|
|
|
- Clear authority — one write path for membership, one derived read path for ACL traversal
|
|
- FK constraints on `organization_members` work (cascade delete when org or account is removed)
|
|
- Fast indexed lookups for membership lists — no graph traversal needed
|
|
- ACL evaluator can still traverse `BelongsToEdge` for permission resolution
|
|
- Reconciliation is straightforward — scan `organization_members`, compare against ACL edges, fix discrepancies
|
|
|
|
**Negative:**
|
|
|
|
- Dual-write contract — the consumer must write both places. If the ACL edge write fails after the SQL write, they're out of sync.
|
|
- The ACL graph is not self-contained for org membership — it depends on an external table
|
|
|
|
## References
|
|
|
|
- ADR-034: ACL as metagraph
|
|
- ADR-041: Identity tables in storage package
|
|
- OQ-23: BelongsToEdge derivation (now resolved) |