--- status: draft last_updated: 2026-06-02 --- # @alkdev/storage Architecture Typed graph storage with SQLite via Honker. Deno-first, published via JSR. ## Current State Storage has Phase 1-3 of the metagraph implementation complete: Metagraph Module, bridge functions, reference graph type Modules (CallGraph, SecretGraph), and crypto utility. Phase 4 (graphology bridge) is pending. The package is transitioning to SQLite-only with Honker integration (ADR-038, ADR-039) and adding identity tables for multi-tenant support (ADR-041). The repository/CRUD layer, Drizzle-Honker adapter, identity tables, and additional graph types remain to be implemented. ## Architecture Documents | Document | Content | Status | |----------|---------|--------| | [overview.md](overview.md) | Package purpose, exports, dependencies, database model, ecosystem integration | draft | | [metagraph-module.md](metagraph-module.md) | TypeBox Module type system, bridge functions, implementation path | reviewed | | [sqlite-host.md](sqlite-host.md) | SQLite tables (metagraph + identity), client factories, Honker adapter | draft | | [honker-integration.md](honker-integration.md) | Drizzle-Honker adapter, event patterns, system/tenant DB coordination | draft | | [schema-evolution.md](schema-evolution.md) | Value.Diff/Cast/Patch for schema migration, version strategy | reviewed | | [encrypted-data.md](encrypted-data.md) | Crypto utility, encrypted node type, key management | reviewed | | [forward-look.md](forward-look.md) | Pointers, dbtype, ujsx IR (conceptual, post-v1) | draft | | [acl.md](acl.md) | Access control graph: principal/agent framework, scoping, operations integration | draft | ### Design Decisions | ADR | Decision | Status | |-----|----------|--------| | [001](decisions/001-deno-first-jsr-publishes.md) | Deno-first, JSR publishes, npm comes free | Accepted | | [002](decisions/002-metagraph-over-domain-tables.md) | Metagraph pattern over domain-specific tables | Accepted | | [003](decisions/003-typebox-module-as-api-surface.md) | TypeBox Module as the graph type definition API surface | Accepted | | [004](decisions/004-injectable-clients-no-side-effects.md) | Injectable clients, no module-level side effects | Accepted | | [005](decisions/005-drizzle-plus-typebox-via-drizzlebox.md) | Drizzle + TypeBox via drizzlebox | Accepted | | [006](decisions/006-enum-pattern-as-const-objects.md) | `as const` objects, not TypeScript enums | Accepted | | [007](decisions/007-no-comments-in-code.md) | No comments in code | Accepted | | [008](decisions/008-common-columns-pattern.md) | Common columns pattern | Accepted | | [009](decisions/009-typebox-module-replaces-schemabuilder.md) | TypeBox Module replaces the SchemaBuilder | Accepted | | [010](decisions/010-metagraph-import-for-same-package.md) | Metagraph.Import() for same-package Modules | Accepted | | [011](decisions/011-config-as-module-entry-with-literal-values.md) | Config as Module entry with Literal values | Accepted | | [012](decisions/012-node-edge-attributes-as-module-entries.md) | Node/edge attribute schemas are Module entries | Accepted | | [013](decisions/013-storage-produces-graphology-format.md) | Storage produces graphology format, flowgraph consumes it | Accepted | | [014](decisions/014-dereferenced-entry-schemas.md) | Repository stores dereferenced entry schemas | Accepted | | [015](decisions/015-edge-constraints-as-named-entries.md) | Edge type constraints as named Module entries | Accepted | | [016](decisions/016-naming-convention-for-module-entries.md) | Naming convention for Module entries | Accepted | | [017](decisions/017-pointer-abstraction-is-forward-looking.md) | Pointer abstraction is forward-looking, not v1 | Accepted | | [018](decisions/018-dbtype-integration-is-post-v1.md) | dbtype integration is post-v1 | Accepted | | [019](decisions/019-json-text-for-schema-columns.md) | JSON text for schema columns in SQLite | Accepted | | [020](decisions/020-no-nodetypeid-on-nodes.md) | No nodeTypeId on nodes | Accepted | | [021](decisions/021-edge-identity-uses-consumer-keys.md) | Edge identity uses consumer-defined keys | Accepted | | [022](decisions/022-composite-fks-for-node-references.md) | Composite foreign keys for node references | Accepted | | [023](decisions/023-per-attribute-encryption.md) | Per-attribute encryption, not per-node | Accepted | | [024](decisions/024-encrypted-data-as-node-type.md) | Encrypted data as node type, not standalone table | Accepted | | [025](decisions/025-password-based-encryption-pbkdf2.md) | Password-based encryption via PBKDF2 | Accepted | | [026](decisions/026-application-managed-key-ring.md) | Application-managed key ring | Accepted | | [027](decisions/027-no-key-rotation-utility.md) | No key rotation utility in this package | Accepted | | [028](decisions/028-additive-only-with-cast-migration.md) | Additive-only for v1, Cast migration when needed | Accepted | | [029](decisions/029-version-as-breaking-change-signal.md) | Version as a coarse-grained breaking-change signal | Accepted | | [030](decisions/030-schema-change-detection-via-diff.md) | Schema change detection via Value.Diff | Accepted | | [031](decisions/031-moduletodbschema-for-updates.md) | moduleToDbSchema() for schema updates | Accepted | | [032](decisions/032-single-author-not-crdt.md) | Single-author model, not CRDT | Accepted | | [033](decisions/033-json-path-queries-for-v1.md) | JSON path queries and hand-written CRUD for v1 | Accepted | | [034](decisions/034-acl-as-metagraph.md) | ACL is a metagraph, not domain-specific tables | Accepted | | [035](decisions/035-actors-become-acl-nodes.md) | Actors become ACL nodes, standalone table removed | Accepted | | [036](decisions/036-principal-agent-as-delegation-edges.md) | Principal-agent as delegation edges with scope narrowing | Accepted | | [037](decisions/037-setup-vs-runtime-separation.md) | Setup-time definitions seed graph types, runtime instances are separate | Accepted | | [038](decisions/038-sqlite-first-pg-removed.md) | SQLite-first, Postgres removed | Accepted | | [039](decisions/039-honker-as-sqlite-extension.md) | Honker as SQLite extension and transport | Accepted | | [040](decisions/040-system-db-tenant-db.md) | System DB + tenant DB separation | Accepted | | [041](decisions/041-identity-tables-in-storage.md) | Identity tables in storage package | Accepted | | [042](decisions/042-scoping-columns-on-graphs.md) | Scoping columns on graph instances | Accepted | | [043](decisions/043-graph-type-scope.md) | Graph type scope — system/tenant/user | Accepted | | [044](decisions/044-drizzle-honker-adapter.md) | Drizzle-Honker session adapter | Accepted | | [045](decisions/045-org-members-authoritative-belongsto-derived.md) | organization_members authoritative, BelongsToEdge derived | Accepted | | [046](decisions/046-fold-drizzlebox-as-utils.md) | Fold @alkdev/drizzlebox as src/sqlite/utils | Accepted | | [047](decisions/047-honker-event-target.md) | HonkerEventTarget adapter for pubsub | Accepted | | [048](decisions/048-operation-specs-as-repo-surface.md) | OperationSpecs as repository surface | Accepted | | [049](decisions/049-identity-schema-restructuring.md) | Identity schema restructuring — separate credential tables, remove Gitea, data→metadata | Accepted | | [050](decisions/050-sha256-for-api-key-hashing.md) | SHA-256 for machine-generated API keys | Accepted | ### Open Questions All unresolved design questions are tracked in [open-questions.md](open-questions.md), organized by theme with cross-references between related questions. ## Document Lifecycle Architecture documents use YAML frontmatter with `status` and `last_updated` fields: ```yaml --- status: draft | reviewed | stable | deprecated last_updated: YYYY-MM-DD --- ``` | Status | Meaning | Transitions | |--------|---------|-------------| | `draft` | Under active development. Content may change significantly. Implementation should not start until the document reaches `reviewed`. | → `reviewed` when all open questions are resolved and cross-cutting issues are addressed. | | `reviewed` | Architecture is final and reviewed. Implementation may begin. API contracts are specified but not yet verified by tests. Changes require a review cycle. | → `stable` when implementation is complete and API contracts are verified by tests. → `draft` if a fundamental redesign is needed. | | `stable` | API contracts are locked and verified by tests. Changes require a review cycle and may warrant an ADR. | → `deprecated` when superseded. | | `deprecated` | Superseded by another document. Kept for reference. | Removed when no longer referenced. | ADR documents use a separate `Status` field in their body: `Proposed`, `Accepted`, `Deprecated`, or `Superseded`. ADRs never revert from `Accepted`. ## References - Source: `src/` - AGENTS.md: `/workspace/@alkdev/storage/AGENTS.md` - Honker source: `/workspace/honker/` - Flowgraph architecture: `/workspace/@alkdev/flowgraph/docs/architecture/` - ujsx architecture: `/workspace/@alkdev/ujsx/docs/architecture/` - Operations architecture: `/workspace/@alkdev/operations/docs/architecture/`