Agent-ready Rust business systems.
Lenso is a Rust-first modular app framework for composing real product shapes, verifying every change, and evolving stable boundaries into services. Start with a runnable host, services, modules, local processes, contracts, migrations, and Console already connected instead of assembling the surrounding system one library at a time.
Humans and coding agents work from the same explicit model: one exact App Composition, Module and Service manifests, generated contracts, checks, and runtime state.
Build modular first. Keep one deployable app while boundaries are changing, then move selected capabilities into independently delivered services when those boundaries are ready.
Read the documentation · Follow the quickstart · Explore the examples
Install the CLI, compose a support application, and start the exact App Composition:
npm install -g @lenso/cli
lenso app compose ./acme-support \
--blueprint support-desk \
--apply
lenso system dev --system-file ./acme-support/lenso.app.jsonUse cargo install lenso-cli instead when you prefer the Rust distribution of
the same CLI.
- Compose.
lenso app compose --applymaterializes the exactlenso.app.json: one revisioned App Composition and lock with immutable Module release digests, implementation bindings, and dependency selections. - Run locally.
lenso system dev --system-file <app>/lenso.app.jsonstarts the composed System through its public Workload entrypoints and a Local Control Adapter. The App Composition contains identities and bindings, not copied process commands or credentials. - Connect. Start the separately installed Console Service and submit that exact composition through its authenticated Connect System API. Connecting records topology and the Management Binding; it does not require an environment or deployment API.
- Status. Inspect the connected System, Services, Modules, Surfaces, and
Workloads in Console. Every object reports
connected,unavailable,incompatible, orunmanagedwith a direct reason, and an unavailable adapter leaves operational state unknown and rejects mutation.
Console does not release or deploy the application. Production release and deployment remain repository- and operator-owned activities outside the Console authority boundary.
- Provider —
lenso.service.v1: Rust and TypeScript Services can provide Modules while a Host owns authentication, queues, retries, and runtime coordination. - Autonomous Service —
lenso.service.v2: Rust only. The Service owns its runtime and storage and uses direct HTTP, direct gRPC, Event Contracts, Durable Workflows, Workload Identity, and Delegated Actor Context.
The TypeScript Service Kit implements the Provider tier; it does not claim Autonomous Service parity. See the authoritative Service Capability Tiers.
Axum remains the HTTP layer. Lenso adds the business-system lifecycle around it:
- a runnable Host with API, Worker, migrations, Postgres, and a separate Console connection;
- manifests for routes, data, actions, events, lifecycle, dependencies, and operator surfaces;
- product blueprints, capability packs, and one revisioned App Composition;
- Runtime Stories that correlate requests, functions, events, outbox work, and service activity;
- generated contracts, manifest lints, architecture checks, smoke checks, and release gates;
- linked modules today and service-backed modules when a boundary is ready to leave the host.
Lenso Console is the separately installed operator service for one Lenso System. It projects managed-Service state through the System Plane so humans and coding agents can review the same system without putting Console code in a business Host.
System Connection shows the exact composed Services and Modules with a direct state and reason for every object.
Runtime Stories follows one business flow across requests, functions, events, and services without losing its correlation.
Runtime Overview brings queue pressure, active work, recent activity, failures, and dead letters into one operator workspace.
These screenshots use the seeded demo dataset so the workflows are reproducible. Read the Console System Plane architecture for service boundaries, access controls, operation records, and Module UI isolation.
The public acceptance is intentionally concrete:
Build a support ticket module for a Lenso app.
The result should be a bounded change with generated code, passing checks, a working Business API, and visible state in Console, not just a scaffold that compiles. The working loop is:
product brief -> Compose -> Run locally -> Connect -> Status
Install the public skill pack directly from this repository:
npx skills add LioRael/lensoThe pack covers business planning, app composition, host setup, linked Module
authoring, Service authoring, Console Surface authoring, API clients,
Autonomous Services, Contract evolution, Durable Workflows, Module extraction,
incident recovery, and reviewed releases. lenso-start is the human-invoked
router; the other skills have narrow task descriptions so agents can discover
the right workflow without loading unrelated instructions.
See the public skill catalog. Manifests, contracts, current CLI help, repository checks, and Console state remain the inspectable source of truth for each workflow.
See the agent-ready module demo. Runnable
support-ticket and account-profile examples are guarded in
LioRael/lenso-examples by module
smoke checks and real host API smokes.
| Surface | Role |
|---|---|
lenso |
Public Rust facade for module declarations, manifest lints, and the narrow host boot API. |
@lenso/cli / lenso-cli |
Compose apps, manage generated state, author capabilities, run local systems, and operate modules and services. |
LioRael/lenso |
This repository: backend platform crates, built-in Modules, System Plane contracts, framework SDKs, migrations, and architecture checks. |
LioRael/lenso-console |
Independent Console Service, web shell, composition Store, and reviewed same-realm ESM Module UI host. |
LioRael/lenso-examples |
Runnable product, module, service, and integration examples. |
lenso.dev |
Product documentation, guides, API reference, and agent-readable docs. |
Add the Rust authoring surface directly when building a module or custom host:
cargo add lensoGenerated hosts enable the crate's host feature. Lenso Console is installed
and operated as a separate Service; managed hosts never serve Console assets.
Keep lenso, lenso-cli, and lenso-console checked out as siblings
when changing behavior across backend, CLI, and Console boundaries. Repository
operations notes live in
docs/repository-operations.md.
- Modular monolith first: linked modules run in-process and can later be extracted behind independently running services over HTTP, gRPC, or event boundaries (guide).
- App Composition:
lenso.app.jsonis the exact revisioned application and lock; blueprints and addons are authoring inputs, not competing runtime state. - Services: Provider
lenso.service.v1is Host-managed and available in Rust and TypeScript; Autonomous Servicelenso.service.v2is Rust-only and owns its runtime and Store. - Modules: business capabilities use exactly Linked or Service delivery and carry immutable release and Surface bindings in the App Composition.
- Local System:
lenso system devrealizes the App Composition through public Workload entrypoints and a typed Local Control Adapter. - Rust first: API, worker, migrations, platform crates, modules, contract generators, and architecture checks are Rust workspace members.
- Explicit SQL and Postgres: no custom ORM, no hidden database magic.
- Transactional outbox: module writes and emitted events commit atomically.
- In-process outbox relay: worker claims outbox rows, dispatches registered handlers, and marks delivery state.
- Contract layer: Rust-authored OpenAPI and JSON Schema artifacts are committed.
More detail lives in docs/architecture/overview.md. Hard rules live in docs/architecture/rules.md.
lenso module install is the primary business-capability entrypoint. It may
enable linked code or resolve a lenso.module-release.json to a provider
service. lenso service install remains the lower-level provider/process
operation for operators who want to connect a service before enabling one of
its modules.
The Support Desk example is the product-level acceptance. It composes an exact
App, runs the local System, connects Console, loads receipt-bound Support Ticket
and Story console_ui_esm Surfaces, exercises the real ticket Business API,
and completes one typed local Workload control round trip.
First-time local setup lives in docs/getting-started.md.
crates/lenso-contracts: shared declaration contracts re-exported bylensoand consumed by platform crates.lenso: public Rust facade crate for serializable module-authoring declarations and manifest lints.lenso-api: Axum HTTP API app.lenso-api-contracts: owner-local contract generator and architecture checks.lenso-worker: background worker and outbox relay app.lenso-migrate: deterministic migration runner.lenso-bootstrap: composition root listing the concrete modules; bothlenso-apiandlenso-workerwire their module set from here.platform-core: config, errors, context, DB, migrations, events, outbox, health, telemetry primitives.platform-http: Axum adapters, request context middleware, JSON extractor, error responses, health routes, and theOpenApiRouterre-exports for single-source OpenAPI.platform-runtime: embedded runtime primitives for functions, triggers, queues, flows, retries, and store traits.platform-module: behavior seams and compatibility re-exports for Module loading and Linked bindings.platform-system-plane: capability-neutral managed-Service management kernel mounted only on the dedicated System Plane listener.platform-testing: shared test database helpers.
modules/auth: host-owned authentication anchor and development session routes. Session resolution defaults to Postgres and can opt into Redis by enabling the auth module'sredisfeature, settingREDIS_URL, and setting runtime configauth.session_cache=redis.auth-oauth: reusable OAuth client flow substrate for authentication adapters.auth-anonymous: first-party anonymous provider for guest sessions.auth-password: first-party password provider for the auth anchor.auth-phone: first-party phone OTP and phone password provider for the auth anchor.auth-github: first-party GitHub OAuth provider built onauth-oauth.auth-google: first-party Google OAuth/OIDC provider built onauth-oauth.
fixtures/provider: internal provider fixture for integration and protocol checks.
contracts/- Generated and curated OpenAPI, JSON Schema, and error contracts.
infrastructure/local/- Local Postgres and optional OpenTelemetry collector config.
Lenso Console source, its deployable Service backend, and the Runtime Stories
Console module live in the sibling ../lenso-console repository. This framework
repository owns public contracts, Module release declarations, and System Plane
capability contracts consumed by the Console.
Prerequisites:
- Rust toolchain compatible with the workspace (
rust-version = 1.94). - Cargo and Docker Compose for development commands.
- Docker if you want local Postgres.
- The sibling
../lenso-consolecheckout if you want to work on the Console.
Create local environment config:
cp .env.example .envModule-local config belongs in env/static host config, not runtime-config DB
overrides. Use LENSO_MODULE_<MODULE>__<KEY>=<json-or-string> for local values;
for example LENSO_MODULE_AUTH_PASSWORD__JWT_ISSUER=acme is available to linked
module code through ctx.config.module_local_config("auth-password"). Module
load toggles remain LENSO_MODULE_<MODULE>_ENABLED=false and are also surfaced
as restart-only runtime config for operator overrides.
auth-phone also keeps OTP secrets in module-local config. Set
LENSO_MODULE_AUTH_PHONE__OTP_SECRET=<secret> outside local development; the
secret is intentionally not exposed as editable runtime config.
REDIS_URL is optional for the platform itself. The first-party auth module uses
Redis only when its dependency is built with the redis feature and runtime
config sets auth.session_cache=redis; otherwise session resolution reads
Postgres directly.
Generated hosts can install that auth profile with:
lenso module install auth --profile redis-session-cacheThe CLI applies the module descriptor profile, enabling the auth dependency's
redis Cargo feature, writing REDIS_URL=redis://localhost:6379/0 to .env,
and recording the runtime default auth.session_cache=redis in
.lenso/runtime-config-defaults.json. Provide a Redis service separately; the
starter Docker Compose file only starts Postgres by default.
Typical loop:
docker compose -f infrastructure/local/docker-compose.yml up -d postgres
cargo run --locked -p lenso-migrate
cargo run --locked -p lenso-apiWorker:
cargo run --locked -p lenso-workerConsole Service and CLI development shortcuts:
# Run the complete local Console Service from its own repository.
cd ../lenso-console
pnpm run service:serve
# Serve a generated host through the local lenso-cli checkout.
cargo run --locked --manifest-path ../lenso-cli/Cargo.toml -- serve --repo-root <host-root>Use an absolute or relative path for <host-root>; it does not need to be a
sibling directory. Managed Services never host Console web assets.
Production Console access must use real auth, not development bearer tokens.
With APP_ENV=production, dev-user:* and dev-service:* tokens are ignored.
Browser users should sign in through password auth or OIDC, then receive
the Console Service's own operator grant through lenso console operator bootstrap.
OpenTelemetry collector for local span export:
docker compose -f infrastructure/local/docker-compose.yml --profile observability up --pull missing --wait --wait-timeout 45 postgres otel-collector
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 cargo run --locked -p lenso-api
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 cargo run --locked -p lenso-workerThe local collector receives OTLP over gRPC on localhost:4317 and OTLP over
HTTP on localhost:4318. The Rust exporter is configured for gRPC, so use:
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317To verify the local loop without starting the API and worker, run:
docker compose -f infrastructure/local/docker-compose.yml --profile observability up --pull missing --wait --wait-timeout 45 otel-collector
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 cargo run --locked -p lenso-platform-core --example otelUser-facing examples live in LioRael/lenso-examples.
The platform example emits one outbox-style span and one function-style span.
Inspect collector debug logs for
lenso.correlation_id, lenso.story_id, lenso.execution.kind,
lenso.outbox_event_id, and lenso.function_run_id.
Common local collector failures:
- Docker is not running: the observability Compose command fails during the Docker daemon preflight.
- The observability profile is not selected: start the collector through
the observability Compose command or use
docker compose -f infrastructure/local/docker-compose.yml --profile observability .... - Ports
4317or4318are already occupied: stop the conflicting process or update both the compose ports andOTEL_EXPORTER_OTLP_ENDPOINT. - The collector config path is wrong: the observability Compose command validates
infrastructure/local/docker-compose.ymlbefore startup; the expected mount isinfrastructure/local/otel-collector.yamlto/etc/otelcol/config.yaml. - First startup needs an image pull: the recipe uses visible Compose output and a 45 second service wait timeout so failures are easier to see.
Regenerate contracts after changing Rust/OpenAPI sources:
cargo run --locked -p lenso-api-contracts --bin generate-contractscargo fmt --all -- --check: check Rust formatting.cargo test --locked --workspace: run Rust workspace tests.cargo check --locked --workspace --all-targets: compile the whole workspace.cargo test --locked -p lenso-api-contracts --test architecture: run architecture guardrails.cargo test --locked -p lenso-api-contracts --test generated_artifacts: verify committed contract bytes.cargo run --locked -p lenso-api-contracts --bin generate-contracts: generate OpenAPI and JSON Schema artifacts..github/workflows/ci.yml: the explicit CI quality gate.
The CI quality gate runs:
- Check Rust formatting, compile every Rust workspace target, and run Rust tests.
- Regenerate contracts, then fail if committed artifacts changed.
- Run architecture guardrails.
The owner integration tests also fail on:
- A root
tools/,scripts/, or task-runner file. - DDD/Clean Architecture folders inside modules:
api,application,domain,infrastructure. - Cross-module imports inside module source code.
- OpenAPI route invariants in the API owner test.
- Stale contract artifacts in the generated-artifact test.
- Missing event payload contracts for current events.
Generated files are source-controlled artifacts, but they are not hand-edited. Update Rust/OpenAPI sources, then regenerate.
Run the explicit quality commands from .github/workflows/ci.yml before a
Release-plz or Changesets release pull request. Cargo and npm publish
independently from this repository; Console checks live in the sibling
lenso-console repository.
Release packaging and tagging steps live in docs/release-process.md.


