SysMARA ORM — AI-First Database Layer for TypeScript
A database layer designed for machine-readable operations, capability-scoped queries, and impact-aware migrations.
Philosophy
Traditional ORMs — Prisma, Drizzle, TypeORM — were designed for human developers. They hide SQL behind abstraction layers, provide convenient query builders, and let you write any query your code can express. This is powerful for humans, but opaque for AI agents. An agent reading Prisma client calls cannot determine which operations are authorized, which invariants should hold, or what the blast radius of a schema change would be.
SysMARA ORM inverts this design. Every aspect of the database layer is explicit, bounded, and machine-readable.
Schema IS the System Graph
There is no separate ORM schema to maintain. SysMARA ORM reads your entity specs from SystemSpecs — the same specs that define your system graph — and generates SQL directly. When you change an entity in your YAML specs, the database schema changes. One source of truth.
Every Query is a Capability
You cannot make arbitrary database queries. Every operation must be scoped to a declared capability. If a capability create_user declares access to the user entity, you can only query user through that capability. This means AI agents cannot accidentally make unauthorized queries — the ORM refuses operations that are not declared in the system specs.
Invariants = DB Constraints
Invariants declared in your specs are not just runtime checks. The schema generator converts them into actual database constraints — UNIQUE, CHECK, NOT NULL, and foreign key constraints. The database enforces your business rules even if application code has a bug.
Machine-Readable Operation Log
Every database operation is recorded as a structured JSON entry in the operation log. AI agents can read this log to understand exactly what the system has done: which capability triggered the operation, which entity was affected, which invariants were checked, how long it took, and how many rows were affected.
Impact-Aware Migrations
Before applying any schema change, the migration engine diffs the previous and current specs, identifies every affected capability and invariant, computes a risk level, and determines whether human review is required. No blind ALTER TABLE statements.
Getting Started
Configure SysMARA ORM in your sysmara.config.yaml:
database:
adapter: sysmara-orm
provider: postgresql
connectionString: env(DATABASE_URL) Usage
Initialize the ORM
import { SysmaraORM } from 'sysmara/database/adapters/sysmara-orm/orm';
const orm = new SysmaraORM(
{ adapter: 'sysmara-orm', provider: 'postgresql' },
specs // your parsed SystemSpecs
); Execute a capability
The capability() method resolves a capability from the system specs, validates the input against the capability's contract, and routes to the appropriate entity operation. Every call is logged.
// Execute a capability as a database operation
const result = await orm.capability('create_user', {
email: 'alice@example.com',
role: 'admin',
});
// The ORM validates that 'create_user' exists in specs,
// that 'email' and 'role' are declared inputs,
// and logs the operation with invariant tracking. Use typed repositories
Repositories are scoped to a single entity within a capability's boundaries. All operations through the repository are validated against the capability contract and logged to the operation log.
// Get a typed repository scoped to a capability
const repo = orm.repository<User>('user', 'create_user');
// Standard CRUD operations — all capability-scoped and logged
const user = await repo.findOne({ email: 'alice@example.com' });
const newUser = await repo.create({ email: 'bob@example.com', role: 'member' });
const updated = await repo.update('abc-123', { role: 'admin' });
await repo.delete('abc-123');
// Without explicit capability — uses first capability that declares the entity
const repo2 = orm.repository<User>('user'); If you try to create a repository for an entity that no capability declares access to, the ORM throws an error. There are no backdoor queries.
Generate SQL schema
const sql = orm.generateSchema();
// Returns complete CREATE TABLE statements with:
// - Provider-specific types (PostgreSQL, MySQL, SQLite)
// - NOT NULL, UNIQUE, CHECK constraints from entity field constraints
// - Foreign keys detected from *_id field naming
// - UUID primary keys with provider-appropriate defaults Example output for PostgreSQL:
-- GENERATED BY SYSMARA ORM
-- Provider: postgresql
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
CREATE TABLE IF NOT EXISTS "user" (
"id" UUID DEFAULT gen_random_uuid() PRIMARY KEY,
"email" VARCHAR(255) NOT NULL UNIQUE,
"role" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMPTZ DEFAULT NOW() NOT NULL,
CONSTRAINT chk_user_role_enum CHECK ("role" IN ('admin', 'member', 'viewer'))
); Operation Log
The operation log is what makes SysMARA ORM AI-first. Every database operation — whether executed through orm.capability() or a repository method — is recorded as a structured JSON entry. AI agents can read this log to audit system behavior, debug issues, and reason about what happened.
Log entry structure
{
"id": "op_1_1710410400000",
"capability": "create_user",
"entity": "user",
"operation": "insert",
"invariants_checked": ["email_must_be_unique"],
"affected_fields": ["email", "role"],
"timestamp": "2026-03-14T12:00:00.000Z",
"duration_ms": 12,
"affected_rows": 1,
"sql_template": "INSERT INTO \"user\" (\"email\", \"role\") VALUES ($1, $2)"
} | Field | Description |
|---|---|
id | Unique identifier for this log entry. |
capability | The capability that authorized this operation. |
entity | The entity (table) this operation targets. |
operation | SQL operation type: select, insert, update, or delete. |
invariants_checked | Invariant names that were validated before execution. |
affected_fields | Field names read or written by the operation. |
timestamp | ISO 8601 timestamp of when the operation was executed. |
duration_ms | Execution duration in milliseconds. |
affected_rows | Number of database rows affected. |
sql_template | Parameterized SQL template (never raw values). |
Querying the log
// Get all operations
const allOps = orm.getOperationLog();
// The OperationLog instance supports filtered queries
const log = orm.getOperationLogInstance();
const userOps = log.getByEntity('user');
const inserts = log.getByOperation('insert');
const capOps = log.getByCapability('create_user');
const count = log.size(); Migration Engine
The migration engine diffs two versions of your SystemSpecs and produces an impact-aware migration plan. Unlike traditional migration tools that only generate SQL, SysMARA's migration engine knows the system graph — it tracks which capabilities, invariants, modules, policies, and flows are affected by every schema change.
Generating a migration plan
const plan = orm.planMigration(previousSpecs);
// plan contains:
// {
// steps: [...],
// affectedCapabilities: ['create_user', 'update_user'],
// affectedInvariants: ['email_must_be_unique'],
// riskLevel: 'low',
// requiresReview: false
// } Migration step types
| Action | Description | Risk |
|---|---|---|
create_table | New entity added to specs | Low |
add_column | New field added to an entity | Low |
alter_column | Field type or nullability changed | Medium |
drop_column | Field removed from an entity | High |
drop_table | Entity removed from specs | Critical |
rename_table | Entity renamed | Medium |
rename_column | Field renamed | Medium |
Risk classification
The migration engine computes a risk level based on the most destructive operation in the plan:
- Low: Only additive changes (new tables, new columns).
- Medium: Column type or nullability changes.
- High: Column drops — data will be lost.
- Critical: Table drops — entire entity data will be lost.
Migrations classified as high or critical automatically set requiresReview: true.
Example migration plan output
{
"steps": [
{
"action": "add_column",
"entity": "user",
"field": "phone",
"details": "Add column \"phone\" (string) to \"user\"",
"sql": "ALTER TABLE \"user\" ADD COLUMN \"phone\" VARCHAR(255);"
},
{
"action": "create_table",
"entity": "notification_preference",
"details": "Create new table \"notification_preference\"",
"sql": "-- See full schema for complete DDL"
}
],
"affectedCapabilities": ["create_user", "update_user", "get_user_profile"],
"affectedInvariants": ["email_must_be_unique"],
"riskLevel": "low",
"requiresReview": false
} Impact analysis
The migration engine can also produce a full impact surface for a migration plan, identifying affected modules, policies, flows, tests, and generated artifacts:
const engine = orm.getMigrationEngine();
const impact = engine.analyzeImpact(plan, specs);
// impact.affectedModules → ['users']
// impact.affectedPolicies → ['admin_full_access']
// impact.affectedFlows → ['user_onboarding']
// impact.affectedTests → ['tests/create_user.test.ts']
// impact.generatedArtifacts → ['routes/create_user.ts', 'sysmara-orm/schema/user.sql'] SQL generation
const sql = engine.generateSQL(plan);
// Produces a complete migration script:
// - Header with risk level, affected capabilities, and invariants
// - Wrapped in BEGIN/COMMIT transaction
// - Each step as a commented SQL statement Why AI-First Matters
The difference between SysMARA ORM and traditional ORMs is not about features — it is about who the ORM is designed for.
Traditional ORMs hide complexity from humans
Prisma's prisma.user.create() and Drizzle's db.insert(users).values() hide SQL behind convenient APIs. This is great for human developers who understand the system. But when an AI agent calls prisma.user.create(), there is no record of why that query ran, which capability authorized it, or which invariants should have been checked.
SysMARA ORM makes everything transparent
| Aspect | Traditional ORM | SysMARA ORM |
|---|---|---|
| Schema source | Separate schema file maintained by developers | Generated from entity specs (single source of truth) |
| Query authorization | Any code can query any table | Queries scoped to declared capabilities |
| Invariant enforcement | Application-level validation only | Database-level constraints from spec invariants |
| Operation audit | Manual logging or middleware | Automatic structured JSON log for every operation |
| Migration safety | SQL diff with no architectural context | Impact-aware migrations with risk classification |
| AI agent readability | Agent must parse ORM API calls and guess intent | Agent reads operation log, capability contracts, and system graph |
Bounded queries prevent AI mistakes
When an AI agent works with a traditional ORM, it can generate any query the ORM supports. There is no guardrail preventing the agent from querying tables it should not access or modifying data in ways that violate business rules.
SysMARA ORM enforces capability boundaries at the ORM level. If the create_user capability declares access to the user entity, a repository scoped to that capability can only operate on user. The agent cannot accidentally query billing data through a user capability.
The operation log enables AI reasoning
Because every operation is logged with its capability, entity, invariants, and SQL template, an AI agent can:
- Audit what the system has done without parsing application logs.
- Detect anomalies by comparing operations against capability contracts.
- Debug issues by tracing operations back to the capability that triggered them.
- Optimize by analyzing query patterns and durations.
- Verify invariant enforcement by checking that expected invariants were validated.
Related Concepts
- Database Adapters — the pluggable adapter system SysMARA ORM is part of
- Entities — the specs that SysMARA ORM generates schema from
- Capabilities — every ORM query is scoped to a capability
- Invariants — become database constraints in SysMARA ORM
- CLI Reference —
sysmara dbcommands for schema and migrations