Skip to content
Concept

Choose a cross-App integration

Select references, events, projections or host contracts for the actual task.

Choose a cross-App integration

Choose the path from the requirement, then follow its implementation guide. Before coding, identify the owner App, actor authority and behavior when that App is unavailable.

You need toUseContinue
Select or read another App's current recordAuthorized Resource ReferenceResource References
React to a committed factPublic Event and idempotent consumerHandle events and jobs
Display several independent App metricsApp-owned Dashboard widgetsAdd a Dashboard Widget
Combine a bounded compatible Resource graphCore Resource CompositionAdd a Dashboard Widget
Maintain a combined metric over factsConsumer-owned event projectionHandle events and jobs
Request Electronic Approval or Business ProcessDedicated Core runtime contractElectronic Approval, Business Process
Require another App to be operationalManifest prerequisites, plus a separate data pathApp manifest

An App never imports another App's package, queries its table, adds a foreign key into its data or shares its transaction. If one invariant needs atomic writes in both Apps, reconsider which App owns it.

Verify

The chosen owner and data path are explicit. Test unavailable owners, denied references, repeated events and stale projections for the selected mechanism.

Select a record or retain evidence

Store the canonical reference identity {app_key, resource_key, resource_id} using the owner’s public identifier. The owner resolves a safe current view under the current actor, scope, time and purpose. A display fallback is not current truth. Never query the owner table to distinguish missing from denied.

When the workflow must preserve what was accepted at a cutoff, retain the authorized snapshot with its as_of, revision and content hash. Label it as evidence and resolve again for current state. Protected fields stay out of snapshots, search and debug output.

Handle available, absent, disabled, failed, stale and unauthorized deliberately. Only absent permits an absence fallback; do not turn a denied or failed lookup into guessed data.

For a person field, use directory.party with the required selection profile. An optional membership eligibility narrows candidates but does not grant authority. An exact employment binding may belong to the owning domain; the Resource References covers that choice.

Ask for work and wait for a result

An event handoff is asynchronous. Publish a request fact and accept a separately correlated result. Validate producer, schema, tenant, scope and public identities before changing local state. Use stable idempotency keys and define the behavior for rejection, retries, timeout and a late result. HandoffResultState supplies the shared result vocabulary; each App still owns its business state.

A projection is eventually consistent. Give it a replay or reconciliation path and make staleness visible when it affects decisions. Do not present copied owner fields as a second source of truth.

Compose a Dashboard

Independent widgets each use their owning App's authorized query. For a single table over related Resources, Core accepts only a bounded graph of catalog-proven relationships with source aliases and independent authorization. No raw SQL, arbitrary joins or automatic relationship search is admitted. Other aggregates need a projection or a suitable host contract.

Share a host capability only when it belongs to the platform

Use an existing SDK capability first. A new surface must express a durable, App-neutral host responsibility and still make sense if any one App is absent or replaced. A DTO for one fixed App pairing does not belong in the SDK merely because two consumers use it. Keep domain rules in their owner and let Core restore tenant and actor context for host execution.

Test absent and disabled owners, denied references, duplicate/late results and reconciliation in Test an App. A successful installation prerequisite check proves lifecycle ordering, not any data flow or authorization.

Source of truth: docs/developers/content/en/building-apps/choose-cross-app-integration.md