Runtime diagnostic logs redact payload values by default, before delivery to file, console, buffers, or custom logging sinks. Selecting a diagnostic sink alone does not authorize plaintext. For controlled troubleshooting only:
export TEAQL_ALLOW_SENSITIVE_PLAINTEXT_LOGS=I_UNDERSTAND_SENSITIVE_DATA_MAY_BE_WRITTEN_TO_DISKOnly this exact value enables plaintext permission; empty values, true, and
whitespace variants do not. Enabling it emits a warning. Credential-classified
fields remain redacted. The flag does not force every sink to expose values.
SQL without reliable field/literal provenance may be suppressed and marked
NOT REPLAYABLE. Execution parameters and persisted business data are unchanged.
Do not put sensitive data in free-text comments or purpose declarations. TeaQL cannot govern arbitrary application prints or independent driver loggers; configure those separately. This setting does not erase older plaintext files. Restrict access and retention when using plaintext diagnostics, then unset the variable and restart processes when troubleshooting is complete.
TeaQL is an AI-native runtime designed for Coding Agents and modern application development.
While traditional frameworks assume a human is writing every line of code, TeaQL provides a strict, typed, and auditable Capability Sandbox tailored specifically for autonomous AI Agents (and humans) to execute code securely.
When building database-backed applications with the TeaQL Rust runtime, we recommend using it together with the TeaQL Agent Kit. The Agent Kit is TeaQL's continuously evolving Harness Engineering method. It gives coding agents a model-mediated, executable workflow for domain modeling, deterministic evaluation and repair, code generation, implementation, and evidence-based verification as the generator and runtimes evolve.
To ensure absolute safety and governance when AI Agents interact with production systems, the TeaQL runtime enforces the following five safeguards:
- Mandatory Identity (UserContext): Every operation must pass through a runtime
UserContext. The system explicitly records whether the action was performed by a human or an AI Agent. - Intent Auditing (Typestate/Builder): Agents cannot simply call
.execute(). They are forced by the compiler to declare their intent using.purpose()(for reads) or.audit_as()(for writes) before the execution terminal is unlocked. - Capability Sandbox (SPI/Features): Dangerous operations (HTTP, File IO, Message Queues) are physically isolated. Unless explicitly granted in the project dependencies (via Cargo features), the Agent is structurally blocked from accessing them.
- Graph Mutability Control: Agents do not manually assemble SQL
UPDATEs or relationship loops. They operate on typed Entity Graphs (save_graph), reducing hallucination-induced data corruption. - Universal Error Translation: The runtime intercepts infrastructure errors and translates them into semantic business codes, preventing the Agent from getting stuck in stack trace loops.
TeaQL is a DDD-oriented data runtime for applications that want generated, typed domain APIs instead of hand-written repository boilerplate.
The Rust workspace provides the runtime pieces: entity metadata, a query AST,
SQL compilation, relation enhancement, graph writes, checkers, mutation events,
and PostgreSQL, MySQL, and SQLite executors. The sibling teaql-code-gen
project can turn a compact domain model into a typed Rust service crate with
entity structs, Q::merchants()-style query builders, behavior/checker hooks,
and audited graph-save entrypoints.
TeaQL is not trying to be a general replacement for Diesel, SeaORM, or direct
sqlx use:
- use TeaQL when the domain model is central, relation graphs matter, and you want generated high-level APIs that resemble the Java TeaQL style;
- use Diesel or SeaORM when you want a conventional Rust ORM with a broad ecosystem;
- use
sqlxdirectly when explicit SQL is the right abstraction and generated domain APIs would get in the way.
The Rust rewrite keeps the scope deliberately narrow:
- PostgreSQL, MySQL, and SQLite database providers
- Rust-native metadata and query AST
- SQL compiler and runtime separated from optional web and cache integrations
- compatibility with every Java implementation detail is not a goal, but the high-level TeaQL programming model is being carried over where it is useful
For the latest published Rust runtime package, see
teaql-runtime on crates.io.
The main branch can contain changes that have not yet been packaged; use a
specific released version when validating a downloaded artifact.
For release provenance, run ./scripts/verify-release-provenance.sh <version>
from a checkout with the relevant tags and signing public key. It compares the
archives for every crate in the retained public-release contract with crates.io
checksums, requires one VCS source commit, and verifies that v<version> is
signed and points to that commit. Run the script with --list-crates to inspect
the exact current package boundary instead of relying on a duplicated count in
documentation.
This is a provenance gate, not a functional database-conformance test.
For a new release, first push the signed v<version> tag on the exact
origin/main commit, then run ./publish.sh <version> --check-only. A green
preflight permits ./publish.sh <version> to publish the retained ten-crate
boundary in dependency order with Cargo verification enabled. The publisher is
resume-safe only when an existing archive has the expected checksum and clean
VCS source; it finishes by running the provenance gate above. It intentionally
refuses dirty trees, unsigned or unpushed tags, non-main source, and manifest
version drift.
The framework-independent teaql-tfp-endpoint crate is part of that public
boundary. It carries the trusted TFP request policy, wire metadata, alias
normalization, and collision/unknown-field diagnostics; it is not an internal
detail of the optional Axum integration.
For the frozen 5.0.1 release, run the retained
release-fixtures/tfp-wire-profile consumer locally before merging the
hardening PR. Once published-tfp-wire-replay.yml is on the default branch,
dispatch it with each exact later version. The replay rejects path, Git,
mixed-version, checksum-free, dirty, and wrong-VCS-source resolution before
executing the wire-alias, canonical Checker path, submitted-source path,
collision, and unknown-field assertions.
TeaQL Rust is a server-side security reference runtime. Ordinary Query and Mutation logging is default-on and value-free: it retains declared intent, trace, parameterized SQL, timing, and outcome. Copy/paste SQL or bound values require an explicit sensitive diagnostic level. The framework-independent TFP endpoint applies trusted request policy, bounded query rules, tenant scope, writable-field policy, and optimistic version at the provider boundary.
Boundary-facing entity references are issued and consumed through
UserContext, not by serializing raw internal IDs or by treating decryption as
authorization:
use std::{sync::Arc, time::Duration};
use teaql_runtime::{
ContextBoundReferenceRuntime, DeploymentProfile, ReferenceDocumentScope,
ReferenceIdentity, ReferenceKey, StaticReferenceKeyProvider,
TrustedReferencePrincipal, UserContext,
};
let keys = Arc::new(StaticReferenceKeyProvider::new(
"k3",
[ReferenceKey::new("k3", active_master_key_bytes)?],
)?);
let runtime = Arc::new(ContextBoundReferenceRuntime::from_process_environment(
DeploymentProfile::Production,
"order-service",
"production",
keys,
current_authorization_policy,
)?);
let context = UserContext::new()
.with_round_trip_reference_runtime(runtime)
.with_trusted_reference_principal(TrustedReferencePrincipal::new(
"oidc", "alice", "Platform", 1,
)?);
let document = ReferenceDocumentScope::new(
"order-edit-1001", "edit-order", "Order", 1001, 7,
)?;
let reference = context.reference_for(
ReferenceIdentity::new("OrderItem", 42, 3)?,
&document,
Duration::from_secs(900),
)?;
let wire_value = context.serialize_reference(&reference)?;
let returned = context.deserialize_reference(&wire_value)?;
let resolved = context.resolve_reference(&returned, "OrderItem", &document)?;The tqr1 AES-256-GCM envelope uses HKDF-SHA-256 and random 96-bit nonces. It
binds a reference to service, environment, Domain Root, stable Actor identity,
document/purpose, Aggregate identity/revision, entity type/identity/version,
and lifetime. The key-provider SPI supports one current encryption key plus
decode-only previous keys. Current authorization is checked both when a
reference is issued and when it returns.
For aggregate editing, the Rust runtime also provides the first bounded
tqd1 document-snapshot POC. A generated or application-owned
ContextBoundDocumentService loads and projects the aggregate, while the
runtime authenticates the document-local row map, loaded/writable surface,
relation completeness, allowed mutations and optimistic versions. Application
code enters through UserContext::open_document and
UserContext::accept_document; it never receives decoded persistence IDs as a
general utility. Run the retained proof with:
cargo test -p teaql-examples --test context_bound_order_documentThis is a single-backend POC, not yet a seven-runtime portability claim or a public generated API guarantee.
Local debugging can expose the original ID/version only when the process starts in a development or test profile with the exact acknowledgement below:
TEAQL_UNSAFE_EXPOSE_RAW_ENTITY_IDS=I_UNDERSTAND_THIS_EXPOSES_INTERNAL_ENTITY_IDS_FOR_LOCAL_DEBUGGING_ONLY
Near matches leave governed mode enabled. The same setting in production fails
startup. Raw mode emits an ERROR-level downgrade notice and does not bypass
authorization, type/version checks, projection, Checker/Fix, audit, or Mutation
Ledger rules. See cargo run -p teaql-examples --bin round_trip_references and
the canonical context-bound round-trip reference design.
TeaQL provides cloud-native crates for embedding Rust services into Java (Spring Cloud) microservice architectures:
use teaql_cloud_starter::CloudApp;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
CloudApp::new()
.nacos("127.0.0.1:8848")
.namespace("production")
.service_name("order-service-rust")
.port(8080)
.routes(my_business_routes())
.start()
.await?;
Ok(())
}| Crate | Purpose |
|---|---|
teaql-cloud-core |
Backend-agnostic traits (ServiceRegistry, ServiceDiscovery, ConfigSource, HealthIndicator, MetricsCollector) |
teaql-cloud-actuator |
Spring Boot Actuator-compatible endpoints (health, info, metrics) |
teaql-cloud-nacos |
Nacos v2 gRPC implementation |
teaql-cloud-starter |
One-line bootstrap — connects Nacos, registers service, starts HTTP, graceful shutdown |
See design document for details.
To build TeaQL from source:
git clone https://github.com/teaql/teaql-rs.git
cd teaql-rs
cargo build --workspace --all-targets --exclude teaql-provider-linuxOn Linux, include the /proc data provider with cargo build --all-targets.
To use TeaQL in your project, add the relevant crates to your Cargo.toml:
[dependencies]
teaql-core = "4.2.2"
# Add other providers as neededThe quickest demo uses SQLite in memory and needs no database server:
cargo run -p teaql-examples --bin sqlite_relations_graphIt bootstraps the schema, submits an Order graph containing OrderLine and
Product objects, fetches the order again, and prints the typed result.
For a smaller schema/bootstrap and CRUD path:
cargo run -p teaql-examples --bin sqlite_schema_crudFor generated-service style APIs, use teaql-code-gen to generate a service
crate and write application code against Q:
use crm_erp_service::Q;
let platforms = Q::platforms()
.select_merchant_list_with(
Q::merchants()
.select_name()
.with_name_containing("TeaQL"),
)
.comment("Load platforms with filtered merchant names")
.purpose("Displaying platform-merchant overview for dashboard")
.execute_for_list(&ctx)
.await?;teaql-core: metadata, entity traits, base entity data, values, filters, ordering, aggregates, query model, andSmartList<T>teaql-sql: SQL dialect trait, compiled query types, DDL helpers, and AST-to-SQL compilerteaql-runtime: minimal runtime mechanism,UserContext, metadata lookup, repository boundary, repository registry, behavior registry, checker registry, entity event sink, id generation,RuntimeModule, and in-memory executionteaql-provider-postgres: PostgreSQL native adapter (deadpool-postgres), schema bootstrap, transaction wrapper, row decoding, and ID-space generatorteaql-provider-sqlite: SQLite native adapter (rusqlite), schema bootstrap, transaction wrapper, row decoding, and ID-space generatorteaql-provider-mysql: MySQL native adapter (mysql_async), schema bootstrap, transaction wrapper, row decoding, and ID-space generatorteaql-data-service: database-neutral query and mutation service contractsteaql-web-integration-axum: Axum integration for TeaQL web responses and request contextsteaql-cache-integration-redis: Redis-backed runtime cache and ownership-safe Remote Lock integrationteaql-provider-meilisearch: Meilisearch query providerteaql-provider-linux: Linux/procdata providerteaql-macros:TeaqlEntityderive macro plus attribute parsing and record/entity mapping generation
The Rust implementation currently covers the core TeaQL runtime:
- Typed domain model — Entity and relation metadata,
TeaqlEntityderive support, typed entity mapping, andSmartList<T>. - Queries and aggregates — Filters, projections, sorting, pagination,
subqueries, relation loading, grouped aggregates, and
HAVING. - Audited persistence — Create, update, soft delete, recover, optimistic locking, transactions, and audited entity-graph saves.
- Runtime governance —
UserContext, repository behavior hooks, checkers, translated validation messages, mutation events, and ID generation. - Relation graphs — Typed nested relation enhancement, aggregate relations, graph planning, references, removal, and missing-child handling.
- Providers and integrations — PostgreSQL, MySQL, SQLite, in-memory,
Meilisearch, Linux
/proc, Axum, Redis, and cloud integration crates.
See Workspace layout for crate responsibilities, Typed entities, and Typed relation enhancement for examples.
TeaqlEntity derive now generates both metadata and typed Entity mapping.
Entity data-service APIs can return either raw Record rows or typed
SmartList<T> collections.
use teaql_core::{Expr, SelectQuery, SmartList, TeaqlEntity};
use teaql_macros::TeaqlEntity;
use teaql_runtime::PurposedSelectQuery;
#[derive(Clone, Debug, Default, TeaqlEntity)]
#[teaql(entity = "CatalogProduct", table = "catalog_product_data")]
struct CatalogProductRow {
#[teaql(id, column = "id")]
id: u64,
#[teaql(version, column = "version")]
version: i64,
#[teaql(column = "name")]
name: String,
}
let query = PurposedSelectQuery::new(
SelectQuery::new("CatalogProduct")
.filter(Expr::eq("name", "desk"))
.comment("Load catalog products named desk"),
"Display matching catalog products",
);
let products: SmartList<CatalogProductRow> =
data_service.fetch_entities::<CatalogProductRow>(&query).await?;SmartList<T> keeps TeaQL-style list metadata alongside the typed rows:
datatotal_countaggregationssummary
When the entity defines #[teaql(id)] or #[teaql(version)], SmartList<T> also exposes:
ids()versions()into_records()
fetch_enhanced_entities::<T>() runs record-based relation enhancement first, then converts the
result into typed nested entities.
use teaql_core::{SelectQuery, SmartList, TeaqlEntity};
use teaql_macros::TeaqlEntity;
use teaql_runtime::PurposedSelectQuery;
#[derive(Clone, Debug, Default, TeaqlEntity)]
#[teaql(entity = "Product", table = "product_data")]
struct ProductRow {
#[teaql(id, column = "id")]
id: u64,
#[teaql(version, column = "version")]
version: i64,
#[teaql(column = "name")]
name: String,
}
#[derive(Clone, Debug, Default, TeaqlEntity)]
#[teaql(entity = "OrderLine", table = "order_line_data")]
struct OrderLineRow {
#[teaql(id, column = "id")]
id: u64,
#[teaql(version, column = "version")]
version: i64,
#[teaql(column = "order_id")]
order_id: u64,
#[teaql(column = "product_id")]
product_id: u64,
#[teaql(
relation(
target = "Product",
local_key = "product_id",
foreign_key = "id"
)
)]
product: Option<ProductRow>,
}
#[derive(Clone, Debug, Default, TeaqlEntity)]
#[teaql(entity = "Order", table = "order_data")]
struct OrderRow {
#[teaql(id, column = "id")]
id: u64,
#[teaql(version, column = "version")]
version: i64,
#[teaql(
relation(
target = "OrderLine",
local_key = "id",
foreign_key = "order_id",
many
)
)]
lines: SmartList<OrderLineRow>,
}
let query = PurposedSelectQuery::new(
SelectQuery::new("Order").comment("Load orders and configured relations"),
"Display orders and configured relations",
);
let orders: SmartList<OrderRow> =
data_service.fetch_enhanced_entities::<OrderRow>(&query).await?;For nested enhancement, register relation paths from repository behavior, for example:
lineslines.product
Schema setup is implemented by the selected database provider, but exposed through the database-neutral runtime entry point:
ctx.ensure_schema().await?;Each database provider exposes a registration helper that installs its dialect,
executor, and schema provider into UserContext.
PostgreSQL:
use teaql_provider_postgres::{
PgMutationExecutor, PostgresProviderExt,
};
ctx.use_postgres_provider(PgMutationExecutor::new(pg_pool));
ctx.ensure_schema().await?;SQLite:
use rusqlite::Connection;
use teaql_provider_sqlite::{SqliteMutationExecutor, SqliteProviderExt};
let executor = SqliteMutationExecutor::from_connection(Connection::open("app.db")?);
ctx.use_sqlite_provider(executor);
ctx.ensure_schema().await?;MySQL:
use teaql_provider_mysql::{
MysqlMutationExecutor, MysqlProviderExt,
};
ctx.use_mysql_provider(MysqlMutationExecutor::new(mysql_pool));
ctx.ensure_schema().await?;Current ensure_schema scope:
- create missing tables
- add missing columns to existing tables
- do not attempt destructive migrations such as drop column, type rewrite, or primary-key rebuild
Runnable examples live in the teaql-examples workspace package:
cargo run -p teaql-examples --bin sqlite_schema_crud
cargo run -p teaql-examples --bin sqlite_relations_graph
cargo run -p teaql-examples --bin school_example
cargo run -p teaql-examples --bin test_default_logCurrent examples cover:
- SQLite schema bootstrap, audited create/update/delete, and typed entity fetch
- SQLite entity graph writes and typed relation enhancement
- audited graph saves through
entity.audit_as("why").save(&ctx) - default SQL trace-log output
Ledger-backed save(&ctx) reads the authoritative persisted root row on the
write transaction before committing. The returned typed entity therefore uses
database-generated IDs, defaults and actual versions from that transaction,
including an existing soft-delete tombstone. If the readback fails, the write
transaction rolls back and the mutation ledger remains retryable. An executor
already bound to an outer transaction uses that same executor and leaves commit
or rollback to its owner. See issue #127
for the retained concurrency and rollback regression.
The PostgreSQL and MySQL provider tests contain real-database cases that return
early when their URL is absent. A green plain cargo test result therefore does
not by itself prove those cases executed. Use the retained gate instead:
TEAQL_TEST_POSTGRES_URL='postgresql://<user>:<password>@<host>/<dedicated-db>' \
TEAQL_TEST_MYSQL_URL='mysql://<user>:<password>@<host>/<dedicated-db>' \
scripts/verify-live-sql-providers.shCreate a disposable database named teaql_rust_provider_* on each engine first.
The script rejects missing URLs and other database names, then runs the complete
SQLite, PostgreSQL and MySQL provider suites. It does not create or drop the
databases; the caller must verify and clean up those exact test databases after
the run. The provider tests create and remove fixed-name fixture tables within
them, so never point this gate at a shared or production database.
TeaQL supports the following environment variables for configuration and debugging:
TEAQL_LOG_ENDPOINT: Sends internal execution logs tostdoutor appends them to the specified file path.TEAQL_LOG_FORMAT: Controls the format of the output log specified byTEAQL_LOG_ENDPOINT. Can be set tojson(ordebug) for structured JSON logging, orhuman(default) for human-readable output.TEAQL_DOMAIN: Sets the default log filename to<domain>.logwhenTEAQL_LOG_ENDPOINTis not set.
If you find a bug, please create an issue on GitHub Issues. Please include as much detail as possible, such as TeaQL version, Rust version, database type, and steps to reproduce. For security vulnerabilities, please see our Security Policy.
- Expand
MemoryRepositorytoward relation enhancement and richer parity with the SQL-backed path. - Add typed checker generation and richer Java-style validation semantics.
- Keep expanding value coverage beyond the current JSON/date/timestamp/Decimal set, especially
Uuidand bytes. - Decide whether a Rust-native service layer is needed above repository/runtime APIs.