Inkress ADRsarchitecture decisions
Overview / Apps
ADR 0042

Embedded merchant apps use a two-layer framework: app-bridge (transport) and app-kit (full-stack)

AcceptedApps

Context

Merchants and partners build apps that run embedded in the Inkress dashboard (in an iframe). Each such app needs the same plumbing: bootstrap a session from the host, call the API with a real token, and handle OAuth and webhooks. Without a shared framework every app re-implements the transport and the auth handshake at the most sensitive boundary. Shopify's App Bridge / app template split is the proven model for exactly this.

Decision

Provide a two-layer embedded-app framework, modeled on Shopify's:

  • @inkress/app-bridge — the transport (framework-agnostic). It handles postMessage between the embedded iframe and the dashboard host and the 60-second session-JWT → inka_ token exchange (RFC 8693, ADR 0027), with strict origin checks. It has no UI-framework dependency, so any app can use it.
  • @inkress/app-kit — the full-stack kit (opinionated). Built on React Router v7, it wires server-side OAuth, session handling, webhook verification and a client-side provider on top of the bridge, so an app author gets a working embedded app skeleton.

This is the intended successor to an earlier vanilla-DOM apps-core, distributed by GitHub install. Adoption is still early, though: the deployed fleet (~32 of 33 apps) currently runs on apps-core, and app-kit is a young package (v0.1.0) used by only a handful of mostly-example apps. So this ADR records the adopted direction, not the current majority runtime.

Consequences

  • Positive: apps get transport + auth + OAuth/webhook plumbing for free and behave consistently at the auth boundary; the framework-agnostic bridge lets non-React apps use the transport while React apps get the full kit.
  • Neutral / to revisit: the kit ties app authors to React Router v7 (a framework bet); the bridge does not, which is the point of the split. Distribution is via GitHub install rather than npm today.
  • Current state / to revisit: the deployed apps still overwhelmingly run on the older apps-core; migrating the fleet onto app-bridge/app-kit is outstanding, so the consistency benefits above are mostly prospective until that migration happens.

Alternatives considered

  • Each app implements its own transport and token exchange: rejected — duplicated, error-prone plumbing at the auth boundary, and every app would have to get the postMessage origin checks and the token exchange right independently.
  • One monolithic SDK (no bridge/kit split): rejected — coupling the transport to a UI framework would shut out non-React embedded apps; separating the framework-agnostic bridge from the opinionated kit serves both.
← 0041 The official client is a hand-maintained TypeScript SDK with an enum-translation layer 0043 Inkress-on-Shopify is two compliance-separated apps sharing one account link →