Accepted (STA-1280). Records the owner’s standing vendor rule (2026-10-26, round 2, R2-4) and the
integration architecture and vendor-code placement (round 3, R3-7 and R3-8). It amends
0236 decision 4,
0376
decisions 5 and 8, and
0379
decisions 3 and 4, each by an amendment on that page. It reads with
0308
(Integrations and Connections),
0355
(one app market) and 0155 (the MCP
gateway).
Context
Three different things were all called “integrations”: Figentra calling a vendor (a payment gateway, an SMS provider), a third party calling Figentra (a partner app reading orders), and partner UI or AI tools running next to ours. They need different security models, and the board mixed them. At the same time wave 12 shipped 16 vendor Integration classes in@stackra/payments, 8 in @stackra/notifications and one (Chatwoot) in @stackra/integrations, while
0236 decision 4 and the owner’s rule R2-4 say a vendor is a connector
delivered through the OS integrations service (capability map M10). The owner settled both on 2026-10-26: three
mechanisms in one marketplace (R3-7), and every vendor integration in the OS integrations service with Stackra keeping
only ports and shared machinery (R3-8). The alternative of keeping vendor Integrations in Stackra as SDK-free provider
descriptions (capability map Q5, option a) was weighed and not chosen.
Decision
The vendor rule (R2-4).- A port in Stackra, each vendor a connector. Every capability that reaches an outside vendor does so through a
port owned by the Stackra package for that capability (payments, notifications, pricing tax, identity verification,
media OCR, documents e-signature, i18n translation, money FX, shipping, peripherals, integrations for the rest). Each
vendor is a connector listed in the OS marketplace. The tenant picks the vendor and the mode,
ownormanaged(0376 decision 5). Where an open-source or self-hosted product is good enough, Figentra runs it as the managed default (Documenso, PaddleOCR or Surya, Nominatim and Photon, LibreTranslate, Chatwoot, on one tools stack per region, R3-5), and it is reached through the same port as amanagedConnection.
- Connectors: Figentra calls the vendor. Figentra is the OAuth client of the vendor, or holds the vendor’s API key.
The Connection stores the credential in the integrations vault; records keep only a
CredentialRef(0376 decision 6). The vendor driver sits behind the Stackra port and is chosen per call byProviderResolver(0376 decision 1; payments byPaymentGateways). Nothing outside the driver knows the vendor’s name. - Apps: third parties call Figentra. Figentra is the OAuth2 authorization server (OS identity, on the provider of 0206). An app has a client ID and secret, declares the scopes it needs in its listing, and is installed only after a tenant admin consents to those scopes. Its tokens are scoped to that tenant and to the consented scopes, and a scope maps to permissions the ordinary permission check enforces. An app receives events through webhook subscriptions to the events in the registry’s webhook event catalogue, signed by the shared webhook signer. A major version or a new scope waits for consent again (0355 decision 9).
- Extensions: partner UI and AI tools next to ours. A partner UI is a sandboxed bundle that fills a slot a shell declares (the slot model of ADR 0438, the extension model on the app-shells branch). It runs isolated from the shell and its own code, and reaches data only through the API with an app token under decision 3. MCP runs both ways: Tamo uses external MCP servers, each one a connector whose Connection holds Figentra’s token for that server; and Figentra exposes its own API as an MCP server through the one gateway of 0155 decision 4, under the same scopes as apps.
- Partner code never runs in our services. A connector driver is Figentra’s code. An app runs on the partner’s infrastructure. An extension bundle runs in the viewer’s sandbox. No partner-supplied code is loaded into a Figentra service process or a shell bundle.
- One marketplace, three shelves. The one app market of 0355 decision 7 lists
connectors,appsandai-toolswith one install flow, one bill and one consent screen. The shelf, category and modes offered per market are catalogue data (provider-category:<category>, market packs), never code.
- Every vendor Integration lives in the OS integrations service. A class that names a vendor (its description,
Connection shape, API client, webhook verifier and
ManagedProvisioningimplementation) is OS code. This includes the payments, messaging, mail, push, tax, verification, OCR, e-signature, geocoding, translation, FX, carrier, accounting and voice vendors. - Stackra keeps the ports and the shared machinery, and nothing vendor-specific. It keeps the capability ports
and the provider description types (
@stackra/integrationsbases,Connection,ConnectionStore,WebhookEvent), the OAuth client, the token vault and refresh, webhook signing and verification, theManagedProvisioningport and its runner contracts,ProviderDefaults,MarketContextandProviderResolver, and the testing kit (fake Integration API, memory drivers). A test fake or memory driver that names no vendor stays. - The move is not a breaking change for port callers. Callers that use a port (charge, send, quote tax) keep working; the Connection now resolves to a driver registered by the OS integrations service. A caller that imported a vendor class by name imports it from OS integrations instead, and each package records the move in its changeset.
- Values. Catalogue data: shelves,
provider-category:<category>modes and fees, listings, app scopes. Pack data: which vendors and modes a market offers and the managed default per category. Seed data: the regional tools stack endpoints as platformmanagedConnections. Settings: none. Code: ports, shared machinery and the OS drivers.
Consequences
- A new vendor is an OS integrations change and a catalogue entry, never a Stackra release.
- Stackra packages carry no vendor SDK and no vendor name, so a product built on Stackra alone runs on the memory drivers and its own Connections.
- The OS integrations service grows by every vendor driver that wave 12 built in Stackra (stackra-150, os-104).
- Apps and MCP share one scope model, so a tenant admin consents once per app and sees the same scopes for an AI tool.
- The OAuth2 authorization server, consent screens, app registration and webhook subscriptions are OS identity, OS registry and OS integrations items; Stackra supplies the scope and webhook contracts.
Enforcement
planned — the boundaries rule fails a file underpackages/**/src/core/providers/ that extends Integration and
names a vendor (an allow-list holds memory and fake drivers); the OS gen pass lists every vendor Integration under the
integrations service. Until then the rule is a comment.
Supersedes and sources
Supersedes: none. Amends 0236 decision 4, 0376 decisions 5 and 8, and 0379 decisions 3 and 4. Sources:notes/handover/owner-decisions-2026-10-26-round-2.md (R2-4);
notes/handover/owner-decisions-2026-10-26-round-3.md (R3-3, R3-5, R3-7, R3-8);
notes/handover/capability-map-2026-10-26.md (tiers T3 to T5, M4, M10, Q3, Q5).