Triplex roadmap
This document outlines strategic enhancements to make @triplex-build/triplex a world-class, open-source triple store and Datalog engine.
For the implemented surface, backend maturity, and release status, start with current-state.md. Items below are future work unless explicitly marked delivered.
The operational foundation and its ordering constraints are specified in operational-primitives.md. Atomic KV transactions, compare-and-retract conditions, causal transaction envelopes, and per-transaction change journals are implemented, including a backend-issued commit cursor and resumable transaction pages. The portable derivation candidates and their immutable, freshness-aware materialization runs are also implemented, including durable temporal wakeups for future-effective and expiring evidence. The wrapped Datalog API now has typed, scope-bound, commit-position-stable keyset cursors. Fixed attribute dependency sets now have indexed freshness positions and temporal schedules across KV, SQLite, and PostgreSQL. Graph constraints are content-addressed, produce durable queryable observations, and can be enforced atomically across their full valid-time intervals. Command receipts are atomically unique and durable consumer checkpoints are available through the operational subpath. Indexed entity transaction timelines and PostgreSQL composition over an ambient host-owned SqlClient or validated database-scoped pool are also delivered; relational host rows, Triplex facts/journal, and outbox writes can share one Effect SQL transaction.
Immediate release gate
- Delivered: a Changesets v3 GitHub workflow maintains the version PR, publishes stable releases, and can manually publish
nextsnapshots without committing snapshot versions. - Delivered: package checks install all tarballs and exercise the CLI as an external consumer.
- Delivered: the PostgreSQL multi-connection isolation and shared conformance suite run in CI.
- Delivered: Cloudflare and FoundationDB are private experimental workspace packages and cannot be included in the first release accidentally.
- Delivered: the GitHub repository cutover to
bjacobso/triplex. - Delivered: the initial version PR and the first publication of all seven public packages under
@triplex-build. - Remaining: verify trusted publishing for all seven public packages with a tokenless
nextrelease and test the registry packages in a clean external consumer.
Immediate correctness gate: backend parity
Custom runtime composition now has public adapter contracts, structured scopes, typed capability providers, and a public-only Cloudflare implementation. Before stable adoption, validate each adapter's migrations, durability, isolation, and capability behavior; the shared Triples conformance suite alone does not establish those guarantees.
The conformance corpus now runs identical typed projections, scalar joins, predicates, negation, booleans, ref joins, recursive transitive closure, grouped aggregation, bitemporal reads, and snapshot-stable pagination against KV, SQLite, and PostgreSQL. Grow it with every query-engine bug.
Datalog conjunctions are clause-order independent across engines: positive relations establish outer bindings and patterns inside negation establish local bindings before predicates run.
Runtime query shape, truly unbound variables, result/aggregate target collisions, empty disjunctions, undefined rules, unsupported recursive bodies, and wrapper projection references now fail through one backend-neutral typed preflight. Projection and joins cover all seven stored value types, and aggregate duplicate, distinct-count, and empty-input semantics are differential tested. Wrapped filters now validate operand arity and use typed projection columns so numeric, text-family, boolean, and null behavior agrees across backends. Direct ordering and keyset pagination now share a typed total order for mixed scalar families, including null placement and deterministic ties. Raw ordered predicates now accept only numeric-capable value bindings and numeric constants, rejecting backend-dependent text and identity coercions during typed preflight. Equality keeps entity, attribute, transaction, and rule identities string-typed rather than leaking SQL coercion. Group-key equality in
havinguses those same scalar families, while aggregate equality is numeric-only and optional projections are rejected before SQL compilation. Pattern constants now use the same scalar-family identity through positive patterns, negation, and disjunction, while typed refs remain exact. Pattern identity positions now reject non-string constants before backend execution. The?prefix is reserved for schema-valid variables, and constant projections retain typed primitive values through direct and wrapped execution. Continue expanding hostile schema-valid input.SQL projection now carries hidden canonical scalar-family columns through execution, so strings such as
"007", numeric-looking entity IDs and refs, datetimes, booleans, and JSON are decoded without guessing. Distinctness, grouping, counts, and page boundaries use that same flattened public identity across KV, SQLite, and PostgreSQL.Recursive SQL rule definitions, applications, optional projection attributes, and depth bounds are parameterized; validated rule names are quoted identifiers. The portable recursive shape is binary and identity-only. Same-named definitions union, repeated variables unify, and unsupported recursion fails during typed preflight.
Keep PostgreSQL labelled as a pre-1.0 production candidate while its now-required CI corpus gains operational history. Keep FoundationDB and Cloudflare private and experimental until each passes the shared conformance and differential suites.
1. Schema-Aware Constraints & Enforcement
Goal: Move from a "bag of facts" to a reliable, structured database.
- Delivered: independently content-addressed required, cardinality, uniqueness, and reference-target nodes generated by the ontology DSL.
- Delivered: bitemporal read-only evaluation and immutable first-class findings through
EntityValidation, with shared KV/SQLite/PostgreSQL conformance coverage. - Delivered: opt-in transaction enforcement that rejects new or worsened post-state violations at every valid-time boundary and serializes concurrent absence/uniqueness decisions across KV, SQLite, and PostgreSQL.
- Delivered: indexed constraint candidate loading by source entity type and referenced target type, with batched subject expansion instead of a full live-fact scan.
- Graph constraints remain separate from value-local
TypeExprdefinitions. - Next: explicitly modelled general Datalog invariants. Observation mode remains available for migrations and audit.
2. Reactive "Live" Queries (Watch API)
Goal: Power real-time, reactive user interfaces.
- Delivered foundation: dependency extraction,
SubscriptionManager.checkAffected, indexed dependency positions, an ordered transaction feed, durable consumer checkpoints, and best-effort wakeup transport. - Provide a
watchQueryfunction that emits new results when relevant facts change. - Enable incremental result updates to minimize re-computation.
- Build reliable invalidation on the ordered transaction feed;
ChangeEmitterremains a best-effort wake-up mechanism.
3. Application-level tenancy and authorization
Goal: Native, safe isolation for SaaS applications.
- Delivered foundation: explicit database scope, branded
DatabaseId, scope-bound cursors, and PostgreSQL schema-per-database isolation. SQLite hosts use one file/layer per database and KV callers use an explicitly named scope. - Keep authenticated account-to-database selection and authorization above raw
Triplesuntil there is a complete threat model and a backend-portable query/write policy contract. - Do not add an ambient
tenantIdcolumn that silently changes query semantics.
Delivered foundation: Bitemporality (Valid Time)
Goal: Distinguish between when a fact was recorded and when it became true.
- Implemented across KV, SQLite, and PostgreSQL with a shared recorded/valid basis for direct reads and Datalog.
- Differential tests cover historical corrections, future-effective facts, retractions, joins, and negation.
- Structural derivations expose the earliest recorded future
validFromorvalidToacross their dependency attributes. Immutable materialization runs persist and content-bind that schedule, including zero-candidate runs suppressed by negated evidence. A host scheduler can therefore reopen expiry-driven projections without a daily full scan. Fixed attribute sets use backend dependency indexes; dynamic-attribute definitions retain an explicit journal fallback.
4. Integrated Full-Text Search (FTS)
Goal: Seamlessly combine graph traversal with text search.
- Expose a
(fts ?entity "search term")predicate within Datalog. - Support relevance scoring and highlighting in query results.
- Leverage underlying SQL engine FTS capabilities (SQLite FTS5, Postgres GIN/GiST).
5. Performance & Query Optimization
Goal: Handle millions of triples with sub-millisecond latency.
- Cost-Based Optimizer: Reorder Datalog clauses based on attribute cardinality.
- JSON Indexing: Optimize
value_jsonlookups for complex data types. - Recursive Rule Performance: Optimize CTE generation for deep graph traversals.
- Scoped concurrency (deferred): Separate global journal ordering from entity and invariant conflict scopes only after the atomic multi-scope design in
operational-primitives.mdhas cross-backend conformance coverage.
6. Client-Side Sync & Offline-First
Goal: Enable seamless data replication to edge devices and browsers.
- Develop a sync protocol for replicating filtered triple subsets to a client.
- Provide a lightweight browser-side Hexastore for local querying.
- Implement conflict resolution strategies for offline writes.
7. Developer experience and tooling
Goal: Make the database "inspectable" and easy to use.
- Database Studio: A web-based UI for exploring entities, history, and snapshots.
- OpenTelemetry Integration: Built-in tracing for query execution and performance bottlenecks.