MIR participation
Turn your Volt app into a Memory Infrastructure Registry partner. Your app becomes a market; its users become participants whose actions build a portable, cross-partner reputation. You record what users do, and you can resolve a participant's neutral signals (tier, history, claim status) — reputation that follows them across every MIR partner, not just your site.
Enable it in the wizard (npm run dev -- --edit → Features → mir), or add mir to VOLT_ADDONS.
The onboarding flow
MIR only meters events for a public, domain-verified partner, so the config only offers MIR once SITE_URL is a real routable domain — a localhost install can never pass domain verification, so it isn't offered the option. Onboarding is three steps:
- Register — in the config's MIR participation section, click Register with MIR. You get a sandbox partner, an API key, and a domain-challenge token, written to
.envon Apply. - Deploy — ship your site. The add-on serves the challenge token at
/.well-known/mir-challenge, so MIR can confirm you control the domain. - Promote — back in the config, click Promote to production. MIR fetches your challenge, verifies the domain, and swaps your sandbox key for a production key.
Sandbox history doesn't carry over — real participation starts at zero on promote. In sandbox, submit → resolve is immediate; in production, a resolve is provisional until the participant links their own MIR account.
Recording participation
The add-on exposes a client on app.locals.mir (reach it in any route via req.app.locals.mir):
// record an event — eventType is a locked dotted enum (e.g. "transaction.completed")
await req.app.locals.mir.submitEvent(user.id, "transaction.completed");
// resolve a participant's neutral signals
const r = await req.app.locals.mir.resolveUser(user.id);
if (r.found) { /* r.signals — tier, event counts, recency, claim status */ }
else if (r.provisional) { /* production: events exist, user hasn't linked MIR yet */ }
else if (r.unknown) { /* no events for this user */ }
userExternalId (the first argument) is your app's user id — MIR maps it to a participant under your partner. weight defaults to 1 (use claims for negative signals). Events carry only four fields (userExternalId, eventType, weight, occurredAt) — no PII, by design.
Emission is opt-in
Being a registered partner does not mean events flow. Sending data about your users to an external registry is a deliberate choice, so submitEvent is a no-op until you opt in — tick Emit participation events in the config (MIR_EMIT=on). Off, submitEvent returns { skipped: true } and nothing leaves your app; resolveUser (a read) still works. This separates becoming a partner from contributing events — flip emission on only when you're ready.
Environment
| Var | What |
|---|---|
MIR_API_KEY |
Your partner key (mir_sandbox_…, or production mir_…). |
MIR_CHALLENGE |
The domain-verification token, served at /.well-known/mir-challenge. |
MIR_EMAIL |
Partner contact email (required to register). |
MIR_PARTNER_ID / MIR_ENV |
Your partner id + sandbox/production. |
MIR_BASE_URL |
Override the API base (default https://mirregistry.org/v1). |
The wizard writes all of these for you — you rarely touch them by hand.