Skip to content

Tenant-Defined Schemas

Parts of some connectors’ shapes are configured by the account holder rather than by the vendor: custom CRM properties, the columns of a spreadsheet, the fields of a form. A published manifest cannot declare these fields, because they differ per account. The manifest declares where such fields appear. A schema overlay declares, per connection, what they are.

Extension points. A manifest’s schemas section holds named schemas, referenced with $ref. An entry marked defined_by: connection is an extension point:

schemas:
contact_properties:
defined_by: connection # tenant-defined; base type map[string, json]
actions:
update_contact:
input:
id: { type: "string", required: true }
fields: { $ref: "#/schemas/contact_properties" }
output:
id: { type: "string" }
properties: { $ref: "#/schemas/contact_properties" }

An extension point’s base type is map[string, json]. connection is the only defined value of defined_by. A value whose schema is an extension point is an extension region. A trigger output MAY reference an extension point, as a spreadsheet’s row_added payload does. A vendor manifest MUST NOT declare a tenant-configured field as an ordinary typed field, because a type in a published manifest is a promise for every tenant.

Without an overlay. An extension region behaves as its base type. A field is reached by indexing, which yields null for an absent key and composes with default:

{{ contact.properties['deal_size'] | default(0) }}

Member access into an extension region requires an overlay that declares the field, and implementations MUST reject member access into an unrefined region. Indexing is a dynamic lookup that yields null for an absent key; member access is a checked reference to a declared field.

Overlays. A schema overlay declares the fields of one connection’s tenant-defined schemas:

overlay: 1
connector: hubspot
connection: acme-hubspot
schemas:
contact_properties:
deal_size: { type: "float" }
lead_source: { type: "enum[web, referral, event]" }

An overlay’s entries are field declarations. At most one overlay applies per connector and connection. An overlay MUST NOT declare an extension point of its own. It MUST NOT refine a schema that the manifest does not mark defined_by: connection. Implementations MUST reject an overlay that violates either rule.

Refinement. With an overlay resolved:

  • Member access is statically checked. A path that names a field the overlay does not declare is a validation error. Indexing keeps its dynamic, null-on-absent behavior.
  • Inputs check closed. Implementations MUST reject an argument field inside an extension region that the overlay does not declare.
  • Outputs check open. On an action marked validated_output, implementations MUST validate the region’s declared fields against their overlay types before binding. A key that the overlay does not declare binds as a json value and is not validated, which tolerates a field added upstream between overlay refreshes.
  • An overlay field with an enum type has a declared domain. A route over it is exhaustively checkable under the same condition as any other enum: the producing action declares validated_output.

Scope. An overlay belongs to one connection. A binding’s shape follows the connection of the step or trigger that produced it: the environment’s default, or the step’s connection override. Static checks on a path into an extension region use the overlay of that producing connection. Two steps on different connections can therefore check against different overlays.

Resolution and drift. Implementations MUST resolve overlays when a run starts, and MUST record them by content hash. A schema edit upstream never alters a run in progress. Drift surfaces explicitly:

  • A field added upstream appears in outputs as an undeclared key. It is reachable by indexing, and invisible to static checks, until the overlay is refreshed.
  • A new member of an enum-typed field fails output validation on the step that observes it, classified by the manifest’s errors table. A checked route is never handed a value outside its domain.
  • A field deleted upstream is caught at the next overlay refresh. Every member access that names it becomes a validation error before any run starts.

Portability. A Workfile that references only base manifests validates against the published catalog alone, and is portable across every connection of its connectors. Member access into an extension region binds the file to a connection’s overlay, and validating such a file requires the overlay for the target connection.

schema-overlays is a capability.