Connectors
Connectors are how a solution reaches the outside world — Shopify, payment gateways, property management systems, legacy POS APIs. A solution never talks to them directly: it declares dependencies, and the platform resolves, provisions and mediates every call.
For solution-owned application documents (reservations, menus, drafts),
implement tools in your install’s SDK and persist with
ctx.storage — no pool connector
required. [email protected] ships with connectors: [] and
hosting: managed.
Do not call platform storage/* from workflows or UI sources. That model
is superseded by ADR-003.
Reserved names
These roots are platform SDK namespaces and cannot be declared as
connectors: storage, vector, object, cache, queue, secret,
state. Manifest validation rejects them.
Two declaration layers
1. Manifest dependencies
manifest.yaml lists the connectors the solution requires, with optional
semver constraints:
connectors:
- name: shopify
version: ">=1.0.0"
At install time the registry resolves each dependency against published connector versions. An unsatisfiable constraint fails the installation before anything is activated.
2. The connectors/ directory
The package's connectors/ directory documents the connector contracts
the solution relies on — the operations each source and workflow step
uses:
name: shopify
operations:
- orders.list
- products.list
auth:
type: oauth2
These declarations are validated against the published connector's tool
list at publish time: referencing an operation the connector does not
expose is rejected. This keeps sources.yaml and workflows/ honest
before a tenant ever installs the solution.
Omit connectors/ entirely when the solution uses only its own SDK tools
(and runtime sources) — no external pool dependencies.
Resolution and provisioning
The shared pool invariant: connector containers serve all tenants and
are named qefro-connector-{name}-{version}-{id} — never per-tenant.
Connectors are stateless; tenant state lives in the platform, and every
routed call carries the tenant context. See
Connectors concept.
Calling connectors: the bridge
Data sources and workflow tool steps reach connectors only through the connector bridge:
Checks on every routed call:
- The solution holds
connector.invoke(UI sources) or the workflow was registered by the same installation (tool steps). - The connector is declared in the manifest.
- Tenant context is attached; credentials are fetched from the secret manager, never stored in the package.
There is no direct network access from a solution — the bridge is the only path. See Sources.
Credentials
Connector credentials are tenant data:
- Collected at install time for connectors that declare
auth. - Stored AES-256-GCM encrypted by the secret manager; cache keys are tenant-prefixed; plaintext is never logged.
- Injected into pool calls by the platform — packages and workflows never see them.
See Secrets.
Restaurant Pro
From 1.7.0, restaurant-pro declares connectors: [] and ships a
required /qefro SDK app. Application state uses
managed storage via ctx.storage.
UI/workflows call restaurant-pro/restaurant.* tools. Older packages that
depended on restaurant-pos or called storage/* from YAML are superseded.
Guidelines
- Prefer an SDK app + managed storage for solution-owned documents; add pool connectors only for external systems of record.
- Prefer one well-chosen connector over several overlapping ones; every connector adds an install-time credential for the tenant.
- Constrain versions (
>=1.0.0) when your sources depend on specific operation payloads; leave unconstrained for stable, widely deployed connectors. - Publish the connector first — a solution that references an unpublished connector cannot install. See the connector reference.
- Never name a connector after a reserved SDK namespace (
storage, …).
Related topics
- Managed storage
- Sources — capability-gated reads
- Capabilities
- Workflows — connector / storage tool steps
- Installation — resolution + credentials
- restaurant-pro example
- Connectors concept