Link two apps on one machine
List the apps on a machine, let two sealed apps prove who they are, call an action one exposes, and ask a neighbour for status or relief.
Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.
Stability The promise an interface ships with.
- Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
- Beta Usable in production; may change before it becomes stable.
- Experimental May change or go away; needs an explicit opt-in in main.yaml.
You will see the apps on your machine, link two of them, call an exposed action from one to the other, and ask a neighbour for its status. It takes about 25 minutes.
You need
- Two MainSDK apps on one machine, run as the same user, each with a seal (see seal).
- An identity key for each: an ed25519 key pair. The public half goes in
apps.identityand the private half in the secretMAINSDK_APP_KEY.
1. See the apps on the machine
npx mainsdk appsYou get one line per app with its owner, version and seal state, and any flags: a broken seal, a stale record, a duplicate project id.
2. Declare each other
apps:
link: on
identity: "ed25519:MCowBQYDK2VwAyEA…"
peers: [prj_01JD8X]
expose: [orders.status]
access:
roles:
app: [orders.status]apps:
link: on
identity: "ed25519:MCowBQYDK2VwAyEA…"
peers: [prj_01JC8Q]Both sides must list each other, or a call fails with MAIN-APPS-0006.
3. Call an exposed action
import { action, apps } from "mainsdk";
import { s } from "mainsdk/schema";
const ordersStatus = action({
name: "orders.status",
intent: "Read an order's status",
input: s.object({ id: s.number() }),
risk: "read",
run: async ({ input }) => ({ id: input.id, status: "shipped" }),
});
apps.provide([ordersStatus]);import { apps } from "mainsdk";
const order = await apps.call("prj_01JC8Q", "orders.status", { input: { id: 1 } });The orders app runs the action as a service named app:prj_01JD8X with the role app, so you grant it only what you mean to under access.roles.
4. Ask a neighbour
neighbours:
host: on
asks: { accept: [status, load.shed] }import { neighbours } from "mainsdk";
const s = await neighbours.ask("prj_01JC8Q", "status");
await neighbours.ask("prj_01JC8Q", "load.shed", { for: "10m", reason: "report run" });The neighbour runs its slimming steps for at most asks.max-for and rolls them back by itself.
Check it
mainsdk check flags code that reads the registry folder by path (MAIN-APPS-0004) and files that mix peer data with an outbound call (MAIN-APPS-0005). In a test, createSim({ host: "sockets", apps: { a: { yaml, link: true } } }) runs the same wiring on the fake network.
Related: app registry and link, neighbours, respond to an attack.
Was this page helpful?