.carrier → lexer → parser → AST → semantic → IR → rust | java | node.
Carrier™ keeps a real compiler pipeline. Lex / parse / semantic / IR are shared; the codegen step splits into three peers — a Rust + Cargo binary for production, a Spring Boot service for JVM-native shops, and a Node + Fastify target for sub-second dev iteration. Same migration SQL across all three, byte-identical. 1.3.4 carries a written stability policy, a 1.x upgrade guarantee, remote SSH builds, and first-class deploy targets — Carrier Cloud, Compose, Kubernetes, edge WASM.
Stages and responsibilities
Ten crates. One job each. Three codegen targets.
The compiler workspace is a plain Cargo workspace. Reading the code is the fastest way to understand how Carrier behaves.
carrier-lexerTokenizerConverts .carrier source into tokens with spans. Handles comments, doc comments, string literals, identifiers, and attribute annotations.
carrier-parserParserProduces the AST for declarations, statements, and expressions. Preserves spans for diagnostic-quality error messages.
carrier-astAST nodesSpan-carrying syntax tree. The canonical shape every later stage consumes.
carrier-semanticSemantic analysisName resolution, type checking, CRUD and auth validation, policy checks, idempotency scope rules, workflow dependency graphs, LLM tool schema inference, role hierarchy resolution, invariant + SLA validation, built-in call signatures.
carrier-irIntermediate formLowers the semantic model into a codegen-oriented program. Decouples language surface from generation. Both Rust and Node targets read the same IR.
carrier-codegen-rustRust targetGenerates a standalone Rust service project plus OpenAPI, manifest, migration artifacts, and OTLP telemetry wiring. Tokio + Axum + sqlx. Shards generated source under .carrier/generated/src/generated/ for stable file boundaries.
carrier-codegen-javaJava / Spring Boot targetGenerates a Spring Boot 3.x service for JVM-native deployments. Java 21 source + Maven, JDBC + HikariCP, Spring Security for the JWT auth surface. Same migration SQL as the Rust target, byte-identical.
carrier-codegen-nodeNode targetGenerates a Fastify + pg dev project for fast iteration (~200ms restart). Same migration SQL as the other targets, byte-identical. Bails clearly on shapes that need significant runtime scaffolding.
carrier-runtimeRuntime helpersThe internal runtime: auth + JWT rotation + JWKS, Postgres pooling, cache, jobs, schedules, events, workflows, queues, realtime transports, LLM dispatch, idempotency advisory locks, outbound HTTP, runtime depth guards, panic capture, evidence bundles, Carrier Flight Recorder.
carriercCompiler CLIProject discovery, generation, build orchestration (local + remote SSH), dev watch, tests, evals, invariant verification, harden, tune, manifest audit, OpenAPI export, migrations, deploy compose / k8s / edge, remote (Carrier Cloud), agent docs, React Native SDK generator.
What the generated service gets for free.
Generated Rust services link against carrier-runtime. You never write against it directly — it powers the constructs you declare in .carrier source.
/health · /ready · /openapi.json · /docs.JWT_SECRET_PREVIOUS, clock-skew leeway, auth.current_user.carrier.current_roles, carrier.current_tenant, and carrier.current_user per request. Cleared on pooled connection reuse (tested).{METHOD} {PATH}:user:{id}:tenant:{t}:workspace:{w}.REDIS_URL is healthy, otherwise an in-memory fallback. Keys are tenant-scoped by the runtime.retry_compensation.watch emissions.client declarations. Spans annotated with carrier.client_name.1.3.4 is the release candidate. 1.0 is a promise, not a rewrite.
Stable surfaces are anchored by fixture-based manifest/OpenAPI drift tests in CI, a written deprecation window, and a documented 1.x upgrade path.
- Language grammar and currently implemented declarations
fail(code, message)body shape (code · message · request_id · details?)- Runtime-reserved error codes (
unauthorized,forbidden,conflict,validation_failed, …) carrier.tomlformat +.carrier/artifact layoutCurrentUsershape (id, email, name, roles, tenant_id?, workspace_id?)- System-table names and column contracts (see below)
- OpenAPI extensions:
x-carrier-ai-hint,x-carrier-idempotent,x-carrier-cache,x-carrier-telemetry,x-carrier-workflows - CLI commands and documented flags
- Stable OTLP attribute names (carrier.*)
- Generated Rust source layout under
.carrier/generated/src/ - Vendored runtime implementation under
.carrier/generated/vendor/ llm clientdeclaration grammar and built-in call surface- Manifest
llm_clientssection andx-carrier-llm-clientsOpenAPI extension - Benchmark harness internals
- Test-only helper APIs for
testblocks - Startup banner text outside documented JSON fields
carrier check → carrier migrate generate → carrier migrate up. No hand-edits to source or checked-in migrations.crates/, generated Rust internals, undocumented env vars, undocumented benchmark numbers.Durable operational state, in Postgres
Every Carrier service owns a small set of carrier_* tables. Their column contracts are part of the 0.9 stability policy.
carrier_idempotency_keysroute_scope · idempotency_key · response_body · replay_count · last_replayed_at
carrier_jobsjob_name · payload · current_user · trace_context · status · attempts · available_at · last_error
carrier_eventssequence · event_name · payload · current_user · trace_context
carrier_event_deliveriesevent_id · subscriber · attempts · delivered_at · last_error
carrier_audit_logaction · entity · entity_id · metadata · before_value · after_value · current_user
carrier_schedule_runsschedule_name · scheduled_for · created_at
carrier_workflow_stateworkflow_name · input_payload · step_results · output_payload · status · attempts · lease_expires_at · timeout_at
carrier_workflow_tasksrun_id · step_name · status · attempts · available_at · lease_expires_at · last_error
carrier_llm_conversationsclient_name · provider · wire_format · model · status · tokens · current_user
carrier_llm_messagesconversation_id · sequence · role · message · input_tokens · output_tokens
One source tree. Carrier Cloud, Compose, Kubernetes, edge WASM.
The same compiler artifacts feed Carrier Cloud's HTTPS bundle path, generated docker-compose stacks, multi-region Kubernetes manifests, and Cloudflare/Fastly edge adapters.
carrier remote login → deploy → status / logs / open. Reproducible HTTPS upload bundle, sorted by relative path, with --wait for terminal state.carrier deploy compose generates a Compose file + Dockerfile from the compiled project plus .env.example defaults.carrier deploy k8s emits ConfigMap, Secret, Deployment, Service, HPA, and PDB. --multi-region emits one api/worker pair per declared tenant residency region.carrier deploy edge --target cloudflare | fastly requires deploy { routes: edge_wasm }; outputs route manifests + adapter files..carrier/build/<svc> mcp. Actions become synchronous tools; workflow tools enqueue runs and return run_id.carrier compliance generate --standard hipaa | ferpa | pci-dss | soc2 writes evidence backed by Carrier metadata + observed audit data. Hash-chain verification via verify-audit-chain.carrier workflow promote <id> snapshots a runtime-authored workflow into a managed bundle: scaffold_only or behaviorally_complete.Every build emits the same shape
Deterministic, machine-readable outputs — not debug artifacts. Tools can treat these as the ground truth of a Carrier project.
.carrier/generated/generated Rust service project.carrier/generated/migrations/SQL migrations & schema snapshots.carrier/manifest.jsondeclarations · routes · models · policies · jobs.carrier/build/<binary>native executable
/openapi.jsonserved by the binary/docsAPI explorer UI/health · /readyliveness · readiness- JSON logs to stdoutstructured metadata for downstream collectors
Escape hatches are intentional, not afterthoughts
Carrier defines a clear sequence for how you reach for Postgres. Most code lives at the top. Escape hatches are explicit and typed.
- 1Generated CRUDstandard list · get · create · update · delete · restore
- 2Model helpersModel.get, Model.search, count_by_*, exists_by_*, get_by_*, list_by_*
- 3Vector helpersModel.similar_with_scores(...), Model.hybrid_search(...) when Vector(N) + searchable
- 4Actions + transactionsauth context, row locks via get_for_update, cache, jobs, audit
- 5Raw SQLsql.list_as, sql.one_as, sql.scalar_as, sql.exec — typed results
- 6DB functionsdb.call_as, db.fn_one_as, db.fn_scalar_as — stored functions & builtins
Current limits
Carrier ships what the compiler actually implements. These are the places where it deliberately stops short today.
src/ still compiles together — imports are not yet selective loaders..carrier/generated/migrations/.Json payload types so the job body handles an empty input.return from inside a transaction { } block is not supported yet. Do work in the block; return after.