Skip to main content
Your app runs on somebody’s computer and Meradomo gives it an address. This is the next question they ask: can my partner use it too? An app that bundles the engine can answer yes without sending anyone to a browser, and without either person installing anything of ours. You call four endpoints; Meradomo sends the invitation, signs the person in, and enforces the access.
Needs the embedded engine. An app taking the detect-the-app path has no engine of its own, and the running Meradomo app’s credential is not yours to borrow — its owner shares from the menu bar instead. See Embed the engine.

What it looks like to the person invited

  1. They get an email: owner@example.com shared Music with you”, naming your app and its own address — not a generic front page.
  2. They click once. That signs them in and accepts.
  3. They land in your app, already able to use it. Nothing refuses them on arrival, because the access was granted when the invitation was sent.
If the owner has a custom domain, the invitation names that.

The two limits, stated plainly

Worth knowing before you design a screen around this:
  • An invitation grants the apps you name and nothing else. Somebody invited to your app cannot reach anything else on that computer.
  • Only the owner can invite. Somebody they shared with cannot invite anyone. There is no “share onward”.

Getting the key

These routes change who can reach a person’s computer, so unlike the rest of the local API they are guarded. Registering is what earns the key:
Send it as x-engine-capability on every call below.
The capability is minted per engine run and held only in memory. One from a previous run is worthless, so re-register after an engine restarts rather than caching it forever. register is idempotent — calling it before each request is fine, and is what the Rust crate does.
This is also why an app that attached to an engine somebody else started can manage people: the key comes from registering, not from having spawned the engine.

The four calls

The engine lifecycle that earns the capability is documented too: discover, attach, stay attached, detach.

Reading the list

Filter it to your own app. The list describes the whole computer, and somebody shared a different app has no more access to yours than a stranger — showing them would tell the owner otherwise:
Drop revoked entirely. The row survives upstream so the owner can see the removal happened; in your app the question is only “who can open this”.

Inviting

The label in apps must be one this computer actually serves (publishedApps above), and it is the app’s display label — the same one you passed as label when you published, not the address label. Anything else is refused rather than quietly dropped, so the owner is never told they shared something they did not.

Removing

Two different things, and picking the wrong one is a real mistake: From inside your app, prefer the first. They may have been shared something else, and taking that away is not your app’s decision to make.
Always confirm before removing. It ends access and cannot be undone without a fresh invitation, and a row in a list is exactly where a stray tap lands.

Telling your owner apart from your visitors

Every forwarded request carries the visitor’s verified identity, so your app can show the owner controls a visitor must not see:
Do not decide this from the connection address. The engine proxies to 127.0.0.1, so every visitor arrives from loopback — a phone on the other side of the world included. Trusting loopback here hands your owner’s controls to everybody. Use X-Meradomo-Role.Any copy of these headers the visitor sent is stripped before the real ones are written, which is what makes them trustworthy. See the security model.
Key per-person data on X-Meradomo-User, not the email — that is what lets somebody change address without losing everything they had.

Refusals are written to be read

Meradomo decides what counts as an address, which apps may be granted, and how often invitations may be sent — the same rate limit that guards sign-in links. Its refusals come back in words meant for a person:
Show them. Replacing them with wording of your own loses the part that says what to do next. A 429 means the invitation budget is spent; say so and let them try later.

In Rust

The meradomo-engine crate wraps all of this:
register (or spawn_or_attach) collects the capability for you; the calls return PeopleError::NotAttached until it has. PeopleError::Refused carries the message above verbatim. Every method talks over the network with a blocking client — call them off your async runtime (tokio::task::spawn_blocking or equivalent), or you will stall the thread serving your app.