ZSL
Terraform for enterprise applications. Declarative, plannable, deployable.
ZSL is the declarative language for defining a DOSS application: its tables, views, workflows, permissions, and UI. The `zsl` CLI reconciles a desired state in a git repo against a live environment via plan-and-apply — identical in spirit to Terraform, but operating on business application primitives instead of cloud infrastructure. Everything downstream (ZebraDB tables, ZFlow workflows, Vapor-generated UI) is compiled from ZSL source.
Four layers, strictly dependent
- 01
Layer 0 — Schema
Business Objects. Tables, columns, types, lookups, formulas. The data substrate every other layer builds on.
- 02
Layer 1 — Projections
Views, joins, and queries over the Schema. Compiled with strongly-typed refs to Layer 0 so changes propagate at plan time.
- 03
Layer 2 — Workflows
Business logic, automations, and triggers. Consumes Projections and Schemas; emits into ZFlow as durable functions.
- 04
Layer 3 — Interfaces
UI components and layouts. Consumes Projections; triggers Workflows. Vapor takes over from here to generate the actual applet.
Declaring a table
Plain TypeScript using the `T` helper. No DSL, no YAML — just typed objects.
import { T } from "../types";
import { Users } from "./users";
export const Vendors = {
slug: "vendors",
displayName: "Vendors",
columns: {
company: T.string({ required: true, description: "Legal company name" }),
isActive: T.boolean({ nullable: false, description: "Is vendor active?" }),
primaryContact: T.lookup({
target: () => Users,
description: "The primary contact for this vendor",
}),
statusLabel: T.formula({
formula: (refs) => `IF(${refs.isActive}, "Active", "Inactive")`,
description: "A computed label for the status.",
}),
},
};plan → apply → pull
- 01
zsl plan
Loads `.zsl-state/state.json`, compiles desired state from source, reconciles UUIDs, diffs against live, writes `plan.json`.
- 02
zsl apply
Reads `plan.json`, asks for confirmation, executes CREATE/UPDATE/DELETE against the live DOSS environment, then auto-pulls to refresh state.
- 03
zsl pull
Fetches the live configuration back into `.zsl-state/state.json` so every teammate plans against the same reality.
Why TypeScript, not YAML
Agents read TypeScript natively
Every frontier model already writes fluent TypeScript. A YAML DSL would force agents to context-shift into a language they weren't trained on.
Type-checker catches broken refs
Rename a column and every lookup, projection, and formula that referenced it lights up red at compile time — before any plan is written.
LSP, REPL, git-native
Everything you expect from a real toolchain. Not a config surface — a programming language for business applications.