- Rust 97.7%
- Nix 2.2%
- PLpgSQL 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
mir_client carried its own hand-written copy of every request and response shape. mir-api now has them all, so the client can depend on it instead: sessions (login/logout/password), users and tokens, admin reload, barcode and location detail, lots, instance history (Transition), shopping list, condition warnings, order/arrival, lend/return, transit, damage/repair, retire/lost/found, unexpire, split/merge, correct/revert, flow runs with notes, demand by id, and price/usage/spend statistics. Model types are PartialEq, and responses Serialize, so a UI can use them as props and cache them. Role is ordered (an unknown role sorts lowest), State predicts the state machine (checked against the server's table), and an API error displays as Mir's own message; status() and is_unauthorized() / is_forbidden() expose the rest. A client without a token sends no credentials, which is what login needs. every_client_call_speaks_the_servers_language runs each new call against the real router. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
| .moira/envs | ||
| crates | ||
| deploy/kubernetes | ||
| docs | ||
| example | ||
| migrations | ||
| operators/flow-gap | ||
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| devenv.lock | ||
| devenv.nix | ||
| devenv.yaml | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
| renovate.json | ||
| zensical.toml | ||
Mir
Mir is a primitive ledger of the material economy. It tracks the flow of things — what exists, where it is, where it came from, where it went.
What does Mir mean? In Russian, мир is the village commune. It is also the world, and peace. Rust people will tell you it's an IR, and they're right too: Mir is the Material Intermediate Representation — the form the real economy takes between what exists and what operators do with it. And in German, mir means to me — as in "das gehört mir", that belongs to me — which is the whole point of a self-hosted ledger. All of them are right.
What it is
- Small. Five primitives — items, states, transactions, locations, flows — that compose into whatever inventory situation you have.
- Scale-invariant. One person's pantry, a shared household, a maker space, a community.
- API-first. Mir is infrastructure. Automation and integrations live outside as operators and talk to it over HTTP. The API describes itself:
GET /api/openapi.jsonis a generated OpenAPI 3.1 document covering every endpoint, so clients are generated rather than guessed. - Yours. Self-hosted, no cloud, no analytics. The data about what you own and consume belongs to you.
- Federated (eventually). Sovereign instances exchanging items and demand signals, peer to peer.
Operators in Rust get a head start from crates/mir-operator — a typed client plus a reconcile loop — and operators/flow-gap, a reference operator that turns planned flow runs into demand.
The full documentation lives in docs/ — concepts, architecture, data model.
Running
Mir is a single binary plus PostgreSQL. An instance is configured by a config.toml and a set of definition directories (itemdb sources, locations, flows) — see Storage. Users and tokens live in the database, not in files.
Development
devenv up # starts postgres (and provides nightly rust)
cargo run -- example/config.toml # migrate + serve on 127.0.0.1:8080
Create the first admin (also works as lockout recovery):
cargo run -- example/config.toml bootstrap <name>
Log in with the printed one-time password via POST /auth/login, then manage users and operator tokens through the API — see Users.
The API lives under /api — the rest of the domain is left to the UI, mir_client. The full surface is at GET /api/openapi.json; GET /api/health is liveness and GET /api/ready also checks the database.
Deployment
The container image is built with nix — no Dockerfile:
nix build .#containerImage
skopeo copy docker-archive:result docker://registry.example.com/mir:latest
deploy/kubernetes/ is a deployment template, one manifest per resource (apply with kubectl apply -f deploy/kubernetes/): itemdb sources are cloned by git init containers (fetching and pinning repos is the deployment's job — core only reads directories), config lives in a Secret, and a minimal postgres is included for small instances.