Skip to main content

Crate meradomo_engine

Crate meradomo_engine 

Source
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:

  1. discover a Meradomo engine already running on this machine (discover) and decide whether to attach to it or start its own (decide_start_action);
  2. spawn the bundled engine (EngineConfig::spawn) or attach to a running one (spawn_or_attach);
  3. register itself as a live consumer so the engine’s reference-counted lifecycle keeps serving while the app is open (register, heartbeat, deregister);
  4. 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 & pathBodyPurpose
GET /engine/infodiscovery: {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/:namepoll publish status
DELETE /publish/:nameunpublish (keeps approval)
GET /statusconnection 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 & pathBodyPurpose
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§

BillingInfo
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.
ConnectRequest
What one app needs to go from a cold machine to a live public address.
Connected
The result of a successful connect.
DeviceCode
POST /device/code result: the one-time code and the URL the person approves at in a browser.
EngineConfig
Everything needed to launch a bundled engine. The host resolves the paths (from its Tauri resources / sidecars) and the credential, then hands them off.
EngineInfo
The GET /engine/info discovery shape.
Exchange
GET /device/exchange result.
People
The people surface: everyone with access, plus the apps that can be granted.
Person
One person with access, as the engine reports them.
PublishResult
The POST /publish / GET /publish/:name result.

Enums§

ConnectError
Errors from the connect orchestration.
PeopleError
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”).
StartAction
What a launching app should do when it finds the port already held.
StartOutcome
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_PROTOCOL in 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. Returns None if 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/exchange until 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_id matches the engine’s configured first-party app the route goes live immediately; otherwise it is pending until 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 from cfg. 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/info until 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.