Expand description
§meradomo-engine — the reusable launcher for a shared Meradomo engine
An embedding app uses this crate to serve its local app through Meradomo without a second download. It handles the whole shared-engine dance:
- discover a Meradomo engine already running on this machine
(
discover) and decide whether to attach to it or start its own (decide_start_action); - spawn the bundled engine (
EngineConfig::spawn) or attach to a running one (spawn_or_attach); - register itself as a live consumer so the engine’s reference-counted
lifecycle keeps serving while the app is open (
register,heartbeat,deregister); - publish its local app to a public address (
publish,unpublish,status).
It is Tauri-agnostic: it takes plain config and returns
std::process::Child / typed results, so any host — a Tauri app, a CLI, a
service — can drive it. The transport is HTTP over loopback to the engine’s
management endpoint (default http://127.0.0.1:8765).
§The raw wire protocol (for non-Rust hosts)
All calls are plain HTTP to the management base URL; no auth for the engine surface (loopback + same-user is the trust boundary). JSON bodies use camelCase keys.
| Method & path | Body | Purpose |
|---|---|---|
GET /engine/info | — | discovery: {engineVersion, protocol, pid, mode, connected, host, name, firstPartyApp, registrants} |
POST /engine/register | {appId, pid} | attach as a live consumer |
POST /engine/heartbeat | {appId, pid} | stay attached (idempotently registers) |
POST /engine/deregister | {appId} | detach (last one out stops the engine) |
POST /publish | {name, label, localPort, appId?} | request a public address (first-party appId auto-approves) |
GET /publish/:name | — | poll publish status |
DELETE /publish/:name | — | unpublish (keeps approval) |
GET /status | — | connection state + published apps |
A host attaches to an incumbent only when its protocol matches
ENGINE_PROTOCOL; a different number means “incompatible — start your own”.
§Managing people (owner tier)
These change who may reach the computer, so unlike the surface above they are
guarded. POST /engine/register replies with a capability; send it as
x-engine-capability on every call below. It is minted per engine run and
lives only in memory, so one from a previous run is worthless.
| Method & path | Body | Purpose |
|---|---|---|
GET /people | — | {name, members: [{email, accountId, role, status, apps}], publishedApps} |
POST /people/invite | {email, apps?} | invite by email, handing over apps in the same step |
POST /people/grant | {accountId, app, granted} | give or withdraw one app |
POST /people/revoke | {accountId} | remove somebody |
Every rule lives in the control plane, including the rate limit on
invitations, and its status and message are passed back untouched — a 429
here means a 429 there.
Structs§
- Billing
Info - The account’s billing standing (P2.4), surfaced so an embed can show a clear “renew to keep serving” state instead of a silent route-down.
- Connect
Request - What one app needs to go from a cold machine to a live public address.
- Connected
- The result of a successful
connect. - Device
Code POST /device/coderesult: the one-time code and the URL the person approves at in a browser.- Engine
Config - Everything needed to launch a bundled engine. The host resolves the paths (from its Tauri resources / sidecars) and the credential, then hands them off.
- Engine
Info - The
GET /engine/infodiscovery shape. - Exchange
GET /device/exchangeresult.- People
- The people surface: everyone with access, plus the apps that can be granted.
- Person
- One person with access, as the engine reports them.
- Publish
Result - The
POST /publish/GET /publish/:nameresult.
Enums§
- Connect
Error - Errors from the connect orchestration.
- People
Error - What went wrong managing people. Carries the engine’s own message where there is one, because those messages come from the control plane and are written to be shown to a person (“that does not look like an email address”).
- Start
Action - What a launching app should do when it finds the port already held.
- Start
Outcome - The result of
spawn_or_attach.
Constants§
- DEFAULT_
MGMT_ BASE - The engine’s default management base URL (loopback only).
- ENGINE_
PROTOCOL - Wire protocol version this crate speaks. Must match
ENGINE_PROTOCOLin the agent (agent/src/engine-registry.js). Bump together on any breaking change.
Functions§
- connect
- The whole Model-A onboarding in one call: request a code, send the person to the browser to sign in / claim their address / start the trial, wait for the credential, persist it, start (or attach to) the engine, and publish this app. Side-effects are injected so any host — and the tests — can drive it:
- decide_
start_ action - Decide attach-vs-takeover from a discovery result. Mirrors the agent’s
decideStartAction: a compatible engine → attach; anything else → takeover. - deregister
- Detach this app. When it was the last registrant the engine stops serving after its grace window. Best-effort — the engine also reaps a dead pid.
- discover
- Probe for a Meradomo engine on
mgmt_base. ReturnsNoneif nothing answers, the answer is not an engine, or the request fails. - grant
- Give or withdraw one app for one person.
- heartbeat
- Keep this app’s registration fresh (idempotently registers if unknown). Best-effort: a failure (engine still coming up) is silently ignored.
- invite
- Invite somebody by email, handing them the named apps in the same step.
- people
- Everyone who may reach this computer, and the apps that can be shared.
- poll_
exchange - Poll
GET /device/exchangeuntil the person finishes approving in the browser (sign-in → name-claim → trial), or the window elapses. - publish
- Request a public address for a local app. When
app_idmatches the engine’s configured first-party app the route goes live immediately; otherwise it ispendinguntil the owner approves it. - publish_
status - Poll the current publish status of a named app.
- register
- Attach this app to the engine so its lifecycle counts us as alive.
- request_
device_ code - Ask the control plane for a device code and the browser approval URL.
- revoke
- Remove somebody. Their access stops within one of the engine’s poll cycles.
- spawn_
or_ attach - Discover a running engine and either attach to it (registering
app_id) or spawn a new one fromcfg. This is the one call an embedding app makes to guarantee exactly one engine is serving on this machine. - status
- The engine’s
GET /status(connection state + published apps). - unpublish
- Remove a live route but keep the owner’s approval on record.
- wait_
engine - Poll
GET /engine/infountil the engine answers or the deadline passes — a freshly spawned engine needs a moment to bind its management port and learn its identity before it can accept a publish.