Documentation / Exploitation / Référence / Instance manifest

Instance manifest

The instance manifest is the concrete configuration of one Meridian deployment. Plugins declare capabilities (named adapters, value sets, declared events, event sources and bindings); the instance decides delegation — which adapter serves each port, with what concrete configuration, which plugins are required, and which event bindings its connections enable. The manifest declares no contributions of its own (no value sets, no adapters, no bindings are defined here).

The schema is a Zod object defined in libs/shared/src/plugin/instance.ts and exported as InstanceManifest. This page documents that schema exactly.

For task-oriented instructions, see Create your first instance, Configure ports and adapters, Declare and install plugins, Connect an event source, and Configure terminology.

Loading

The manifest is loaded by loadInstance() in apps/api/src/instance.ts:

Step Behavior
Source path INSTANCE_CONFIG (a path) if set, otherwise instance.yaml at the repository root.
Relative paths Resolved against the repository root, not the current working directory.
Format YAML, parsed then validated with InstanceManifest.parse.
Missing file (INSTANCE_CONFIG set) Fails loudly: INSTANCE_CONFIG introuvable.
Missing file (no INSTANCE_CONFIG) Falls back to EMPTY_INSTANCE — a manifest with only apiVersion, i.e. all defaults (dev default: everything internal / in-memory).
Invalid manifest Fails loudly. A schema violation stops boot.
Unknown key Dropped by the schema, logged at warn by the instance component: clé inconnue du manifeste d'instance, ignorée, with path (the manifest file) and key (the key's path, such as ports.patient.confg). Boot goes on. The values the schema keeps whole (an adapter's config, a sources entry) are open.

See Environment variables for INSTANCE_CONFIG, MERIDIAN_REGISTRY, MERIDIAN_PLUGIN_CACHE, and PLUGINS_PATH.

Top-level fields

Field Type Required Default
apiVersion "meridian/instance-v1" (literal) yes —
name string no undefined
locale string no "fr"
timezone string no "Europe/Paris"
registry string no undefined (falls back to MERIDIAN_REGISTRY)
plugins Record<string, PluginRequirement> no {}
seed string[] no []
connections Record<string, InstanceConnection> no {}
connectionDefaults Record<string, string> no {}
ports Record<string, PortBinding> no {}
terminology Record<string, PortBinding> no {}
sources (deprecated) Record<string, Record<string, unknown>> no {}
eventBindings (deprecated) string[] no undefined

apiVersion

z.literal("meridian/instance-v1"). Required. Any other value fails validation. Identifies the schema version of the manifest.

name

Optional free-form string. Used only as a label: loadInstance() logs parsed.name ?? path when the manifest is loaded. It has no functional effect.

locale

Optional string, default "fr". The language of persisted content — record notifications, validation titles, and anything the workflow engine writes to the patient record. An instance is monolingual. Behaviors receive it through ctx.locale / ctx.t. This is distinct from the UI language, which follows the individual user. See Set the instance locale and Instance locale vs UI locale.

timezone

Optional IANA identifier, default "Europe/Paris". The clock of the instance: it resolves the schedule rules of a trigger.schedule workflow whenever the trigger doesn't set its own timezone. Same reasoning as locale — a facility has one clock, the one where care is delivered, so "07:30" in a schedule means 07:30 locally, daylight-saving transitions included.

registry

Optional string. The plugin registry used to resolve required plugins declared by version. Two accepted forms:

  • gs://bucket[/prefix] — a Google Cloud Storage bucket (ADC auth).
  • a local directory path.

If omitted, the registry falls back to the MERIDIAN_REGISTRY environment variable (apps/api/src/registry.ts). In apps/api/src/registry.ts, a value starting with gs:// or file:// is used verbatim; any other value is resolved as a path relative to the repository root. Plugins are laid out in the registry under @publisher/name/version/…. See Set up a plugin registry.

plugins

Optional map, default {}. Keys are plugin package names (e.g. @posos/demo); values are PluginRequirement (see below). These are the plugins required by the instance. At boot, ensureInstancePlugins() (apps/api/src/registry.ts) resolves each one before loadPlugins():

  • Missing versions are downloaded into the local cache (MERIDIAN_PLUGIN_CACHE, default <repo>/.data/plugins).
  • Each resolved directory becomes an additional discovery root for loadPlugins(), alongside the roots on PLUGINS_PATH.
  • A listed plugin that cannot be resolved (invalid instance range, no registry configured, no published version satisfying the range, or no combination compatible with the host and the local plugins) fails boot loudly — it is treated as a configuration error. A path that does not exist is not checked here: loadPlugins() warns that the root is missing (« racine de plugins introuvable — ignorée ») and boots without it.
  • A listed plugin that is also found locally (under a PLUGINS_PATH root or a path entry) is not resolved on the registry: the local copy loads first and hides the registry one. Its version is checked against the instance range; outside it, the boot logs « « @s/x » : copie locale 1.0.0 chargée, hors de la plage de l'instance « ^2.0.0 ». Retirer la copie locale ou modifier la plage. » and goes on. The plugins that depend on it are resolved against the local copy.

The plugins resolved on the registry are chosen together (resolveRequiredPlugins, libs/plugin-cli/src/registry/resolve.ts). Each gets a published version that:

  1. satisfies the instance range;
  2. accepts, through its own dependsOn ranges, the versions of the local and required plugins it cites;
  3. is accepted by the dependsOn ranges of the local plugins the host loads and of the required plugins that cite it;
  4. admits, through its sdk range, the host's plugin contract (PLUGIN_CONTRACT_VERSION); the host would refuse the version otherwise. The sdk range is read before the manifest schema, so a version of a newer contract is set aside for its contract even when this schema cannot read it;
  5. does not cite itself in dependsOn, which the host refuses too.

The local plugins are the manifests of the PLUGINS_PATH roots and of the path entries, the first copy of a name only. A local plugin the host will refuse whatever the registry holds (for its contract, for citing itself, or for a dependsOn range on another local plugin) still counts by its version: the host judges the ranges that cite it against that version, so a required plugin whose range excludes it is set aside. Its own ranges constrain nothing. A dependency that is neither local nor required does not constrain the choice; the host reports it as absent when it loads the plugin.

The search groups the required plugins by cycle (the strongly connected components of their dependencies, read from the dependsOn of the highest version of each range) and takes the groups from the dependents to their dependencies, the group of the smallest name first on a tie, and the plugins of a cycle by name; a plugin therefore comes before the required plugins it depends on, except within a cycle. Versions go from the highest down. The ranges of the local plugins and of the required plugins already chosen are checked on the version number before the version's manifest is read. When no version of a plugin fits, the search goes back to the closest required plugin whose chosen version ruled one out, and tries its next version; when only the host and the local plugins rule the versions out, no other choice would help and the resolution fails. The combination found is the highest in that order, and the same registry with the same local plugins gives it to every process that boots, the engine endpoint and the proxy alike. Each version examined is read at most once, from the local cache when it is there (published versions are immutable), from the registry otherwise; the lists of versions and the highest version of each range are read in parallel. The search stops after 10 000 versions examined.

When a higher version is set aside, the boot logs « plugin requis : versions plus hautes écartées » with the versions and their reasons: « @posos/clinical » 0.2.4 hors de « ^0.3.0 » (a local plugin outside the version's range), « @l/future » 1.0.0 (refusé) hors de « ^2.0.0 » (a local plugin the host refuses, outside the version's range), « @posos/geriatrie » 0.1.1 (requis) exige « ^0.2.0 » (a range of another required plugin; « (requis) » marks a version the resolver chose, not a loaded plugin), « @t/a » se cite dans dependsOn, plage « latest » de « @posos/clinical » invalide, contrat plugin 0.1.4 hors de la plage sdk « ^0.2.0 », manifeste illisible. When the resolution fails, the versions set aside are logged the same way first, then the boot fails with a message that ends with what to do:

[registry] @posos/demo@« ^0.2.0 » : aucune version publiée compatible avec l'hôte et les plugins locaux (0.2.3 : « @posos/clinical » 0.2.4 hors de « ^0.3.0 »). Publier une version compatible ou modifier la plage de l'instance.
[registry] @posos/geriatrie@« ^0.1.0 » : aucune version publiée compatible avec les autres plugins requis ; plugins en cause : @posos/demo@« ^0.2.0 » (0.2.2 : « @posos/geriatrie » 0.1.2 (requis) exige « ^0.3.0 »). Publier des versions compatibles ou modifier une plage de l'instance.
[registry] @posos/demo@« ^0.9.0 » : introuvable sur gs://meridian-plugins (versions publiées : 0.2.2, 0.2.3). Publier une version dans « ^0.9.0 » ou modifier la plage de l'instance.
[registry] plage « latest » de l'instance invalide pour « @posos/demo ». Déclarer une plage semver.
[registry] résolution des plugins requis arrêtée après 10000 versions examinées, sans combinaison compatible trouvée. Épingler une version ou resserrer une plage de l'instance.

The first message names a required plugin whose every version is ruled out whatever the other plugins choose: by the host, the local plugins or its own manifest. The second names first the plugin left without a version, then the required plugins whose chosen versions ruled its versions out. Each plugin cites three versions at most, then « … N autres, voir le journal »: the full list is in the logged versions set aside. Ranges use the npm semver package (validRange, satisfies, valid); a prerelease is selected only by a range that names one, and only valid semver versions count as published. The host checks the dependsOn ranges again when it loads the plugins. See Declare and install plugins and the plugin package format in Plugin manifest.

PluginRequirement

PluginRequirement is a union with a short string form and a long object form. Each entry declares exactly one of version (resolved on the registry) or path (local override).

Form Example Meaning
Short string "@posos/demo": "^0.1.0" Equivalent to { version: "^0.1.0" }. The string is a semver range resolved on the registry.
Object, version { version: "0.1.0" } npm semver range (*, 1.2.3, ^, ~, 1.2.x, >= <, …) resolved on the registry.
Object, path { path: ../vitals/dist } Local path to the plugin's compiled dist/ directory. Short-circuits the registry entirely (dev, hotfix).

Rules:

  • The object form is validated by .refine((v) => !!v.version !== !!v.path): it must declare version or path, not both and not neither. Violations produce the message "un plugin requis déclare version (registre) OU path (local), pas les deux".
  • The short string form is transformed to { version, path: undefined }.
  • A path is resolved relative to the repository root (unless absolute) and read directly; no registry access occurs for that plugin.

seed

Optional string[], default []. Extra directories of workflow/agent definitions to seed into the definition store at boot, in addition to the host's own SYSTEM definitions (DEFINITION_SEED_DIR, default apps/api — which carries only agent-invoke.workflow.yaml). Relative paths resolve against the repository root. This is how content shipped with a deployment (demos, business workflows) stays instance data rather than host code: the clinical demo workflows and the chat-clinique agent live in content/clinical-demo/{workflows,agents} and are seeded by seed: [content/clinical-demo] (as in instance.dev.yaml and instance.example.yaml). Seeding is non-destructive: it populates the store, which then owns the definitions (draft → publish → rollback). See Manage workflow storage.

connections

Optional map, default {}. Connections to external systems declared by the instance: keys are connection identifiers (^[a-z][a-z0-9-]{0,63}$), values are instances of a connection type contributed by a loaded plugin (contributes.connectionTypes, for example fhir-r4 of @posos/fhir or posos-api of @posos/posos). The console lists them read-only, next to the connections created in the console; both share one identifier space. See Manage connections.

Field Type Required Meaning
type string yes Connection type contributed by a plugin.
label string no Label shown in the console; defaults to the identifier.
baseUrl string yes http(s) URL of the system. A relative request path is appended to it; an absolute URL must share its origin.
timeoutMs integer no Time limit of each request, default 30000, at most 600000.
headers Record<string,string> no Extra request headers, not secret; authorization, proxy-authorization and cookie are refused.
auth object no { scheme, …fields }, default { scheme: none }. The scheme must be one the type accepts; the fields are those of the credential kind of the scheme (below). A secret field is written env:NAME, never in clear; a non-secret field is written in clear or env:NAME.
any other key string, number or boolean depends on the type A parameter declared by the type (params), e.g. audience and region for posos-api.
auth.scheme Fields (secret in bold) Request
none — no authentication
basic username, password Authorization: Basic …
header header, value the named header
bearer token Authorization: Bearer <token>
oauth2-client-credentials tokenUrl, clientId, clientSecret, scope (optional) token obtained from tokenUrl (client authenticated with Basic), kept until 60 s before it expires, renewed once on a 401
ambient — none from the host: the plugin's client uses the process identity (Application Default Credentials)

The connections are checked when the instance loads, against the loaded types: unknown type, parameter missing or mistyped, scheme not accepted, literal secret, env: variable absent. An unusable connection does not stop the boot; the proxy logs the warning connexion « <id> » du manifeste inutilisable : <issues>, the console shows the issues, and resolving it fails with Connexion « <id> » inutilisable : <issues>.

A connection of the manifest never references a credential of the store. The variables it names must be set in the environment of every process that uses it: the proxy for event sources, both the proxy and the endpoint for terminology, the endpoint for ports and nodes.

Inbound connections

An entry with format is an inbound connection: its type is a transport (http or directory from the host, or an inbound type contributed by a plugin, such as mllp of @posos/hl7) and format the protocol it receives (receive.protocol, such as hl7v2). An entry whose type is the name of an event source is an inbound connection too, without format (see Pulled inbound connections). The console lists them read-only in Connexions → Connexions entrantes.

Field Type Required Meaning
type string yes Inbound connection type (transport).
format string yes Protocol received; the transport must carry it.
label string no Name shown in the console and the traffic history; defaults to the identifier.
enabled boolean no Reception active, default true.
bindings, bindingOptions list, map no Message bindings of the format to enable, and their options.
validationProfile string no Validation profile of the format.
auth object no Caller check: { scheme: basic, username, password: env:NAME } or { scheme: header, header, value: env:NAME }; required by http.
any other key string, number or boolean depends on the type Parameters of the transport (port, host, encoding, directory…).
connections:
  bus-chu:
    type: mllp
    format: hl7v2
    label: Bus MLLP du CHU
    host: 0.0.0.0
    port: 2575
    bindings: [hl7v2-adt-admission]
  depot-pn13:
    type: http
    format: pn13
    auth: { scheme: header, header: X-Api-Key, value: env:PN13_INGRESS_KEY }

The checks are those of a connection created in the console (type carrying the format, parameters, bindings, profile) plus the inline auth (secret env:NAME, variable set on the proxy). An unusable connection is logged at boot (connexion entrante « <id> » du manifeste inutilisable : …) and shown with status error. A manifest connection has no row in the database; the messages it receives reference it by its identifier, and its traffic history shows its label. It cannot be modified, archived or deleted through the API (409). An identifier present in the manifest and in the database stops the proxy at boot.

Pulled inbound connections

An entry whose type is the name of an event source (contributes.eventSources, such as fhir-poll of @posos/fhir) is a pulled inbound connection: the source polls an external system with the connection's parameters, and each record it emits goes through the reception inbox before the binding of its feed projects it. See Connect an event source.

Field Type Required Meaning
type string yes Name of the event source.
label string no Name shown in the console and the traffic history; defaults to the identifier.
enabled boolean no Reception active, default true.
bindings string[] no Event bindings of the source to enable, each one a feed of the source; absent: every binding of the source.
auth object no { scheme: none } only (the default); another scheme makes the connection unusable: auth « <scheme> » : une source tirée ne reçoit pas d'appel à vérifier.
connection string no For a source that requires a connection (connection: { type } in its plugin manifest): the outbound connection it reads; absent, the default connection of that type.
any other key string, number or boolean depends on the source A parameter declared by the source (params). Checked like the parameters of a connection type, defaults applied; a source that declares none receives its parameters unchecked.

A pulled connection has no format. The source's factory receives the parameters, declared defaults applied and without connection, as config; the connection named by connection (else the default of its type) as connection; and one feed per enabled binding. The id of each event it produces is <connection id>:<feed>:<recordId>.

connections:
  entrepot:
    type: fhir-r4
    baseUrl: https://fhir.chu.example/r4
  fhir-poll:
    type: fhir-poll
    label: Interrogation de l'entrepôt
    connection: entrepot          # absent: default connection of type fhir-r4
    intervalSeconds: 15
    bindings: [fhir-creatinine, fhir-validation-decided]   # absent: all bindings of the source

The checks are those of the other inbound connections: an unusable connection is logged at boot (connexion entrante « <id> » du manifeste inutilisable : …), shown with status error, and its source does not start. An outbound connection named by the connection parameter of a pulled connection of the manifest cannot be deleted from the console.

fhir-poll parameters

The parameters declared by the fhir-poll source of @posos/fhir (external-plugins/fhir/plugin.yaml, read by external-plugins/fhir/sources/poll.ts):

Parameter Type Default Meaning
connection string default connection of type fhir-r4 Connection to the FHIR R4 server.
intervalSeconds number ≥ 1 15 Delay between two polls of all feeds.
count integer ≥ 1 50 Page size (_count) of each feed query.
maxPages integer ≥ 1 10 Pages read at most per feed and poll. A poll that reaches it logs limite de <maxPages> pages atteinte, and the next poll starts right away, without waiting intervalSeconds, from the page where it stopped.
startOverlapSeconds number ≥ 0 600 Overlap window re-read at startup. The initial cursor of each feed is the start time minus this value, except for feeds whose binding sets since: epoch, which start at the epoch. 0 starts at the start time.
requestTimeoutSeconds number ≥ 1 30 Time limit of each request to the server. A request past it stops the poll of its feed (délai de <n> s dépassé), and the other feeds are polled.

A value of another type (a numeric string included) or out of bounds makes the connection unusable.

Each poll searches the resources updated since the cursor of the feed, oldest first, and follows the next links of the result on the connection's base URL; the cursor moves with each record stored and loses no record sharing a lastUpdated second with another. See Pages and cursor of a feed.

Records re-read in the overlap window are already in the connection's inbox, and their events would carry the same eventId as before the restart: they start nothing, and a workflow published after the event's first reception does not receive it. See Connect an event source.

connectionDefaults

Optional map, default {}. Default connection of each type (type → identifier), used by an adapter, a source or a node that requires a connection of that type and designates none. A default set here is read-only in the console. Without a default, resolving fails with Aucune connexion par défaut pour le type « <type> ». Désigner une connexion par défaut en console ou dans le manifeste d'instance.

An identifier defined both here (connections) and in the store, or a type whose default is set both here and in the store, stops the proxy at boot: Connexions en conflit : connexion « <id> » définie dans le manifeste d'instance et en base. Renommer la connexion du manifeste ou supprimer celle de la base.

ports

Optional map, default {}. Adapter selection for single-implementation hexagonal ports. Keys are port names; values are PortBinding (see below). The set of ports is open: every port is keyed by name, and its contract is carried by the plugin that owns it (patient/prescription by @posos/clinical, notification by @posos/notify, decision by @posos/decision; the SDK types only agent and terminology).

Resolution happens in buildPorts() (apps/api/src/instance.ts):

Port Requirement
patient Optional at boot. Without it, workflows touching the record fail at execution (Port « patient » non branché) and GET /api/records/patient/:id answers 404.
prescription Optional at boot. Same failure mode: order.* nodes throw Port « prescription » non branché.
agent Optional (pick, may be undefined). Its config accepts maxIters and providers — see LLM providers.
decision Optional. Needed by the Décision intelligente nodes (@posos/decision); adapter typesafe (@posos/typesafe), on a connection of type typesafe-systemone (connection, else the default connection of the type) — see Configure ports and adapters.
any other port Optional. Every additional key in ports is bound dynamically by its name; its TypeScript contract is carried by the contributing plugin.

For each port, the selected adapter's factory is called with the binding's config and, when the adapter requires a connection, with access to the connection named by connection (else the default connection of the type), resolved at each call. If the named adapter is not found among loaded plugins, the port falls back to the provided fallback (or is left unresolved for optional ports) and a warning is logged. See Configure ports and adapters, Connect a FHIR warehouse, and Port contracts.

PortBinding

PortBinding is a Zod object with three fields:

Field Type Required Default Meaning
adapter string yes — Name of the adapter contributed by a plugin (the selected capability).
config Record<string, unknown> no {} Concrete configuration passed to the adapter's factory.
connection string no default connection of the type Connection used by an adapter that requires one (connection in its plugin manifest), manifest or store.

LLM providers (ports.agent.config.providers)

Optional map, read by the @posos/llm runner. Without it, provider on an agent must be one of the names built into @meridian/llm-client (anthropic, openai, gemini, mistral, azure-openai, local), each with one default base URL and one environment variable for its key — so an instance can reach at most one endpoint per name.

Declaring providers here gives one name per endpoint, which is what lets several models of the same protocol coexist: an in-house model beside a public vendor, a sandbox beside a production gateway. An agent's provider selects the entry by name.

Field Type Meaning
kind "anthropic" | "openai" Wire protocol (/v1/messages or /chat/completions). Defaults to the built-in name's protocol, else openai.
baseUrl string Endpoint root. Defaults to the built-in name's URL.
apiKeyEnv string Name of the environment variable holding the key — never the key itself. Defaults to the built-in name's variable.
headers Record<string,string> Extra headers, merged last — so a declared authorization overrides the one built from the key (the header name must match its lowercase form exactly). Values are not a place for secrets: they sit in versioned configuration, unlike apiKeyEnv.
timeoutMs number Per-provider network timeout.
maxTokensField "max_tokens" | "max_completion_tokens" Field carrying the output limit of a /chat/completions call made by the workflow assistant. Defaults to max_completion_tokens for openai and azure-openai, max_tokens otherwise.

A partial declaration completes the built-in default of the same name rather than replacing it: declaring anthropic: { headers: … } keeps its URL and key variable.

Secrets stay out of this file, which is versioned configuration — hence apiKeyEnv rather than a literal. It is also the only option available to the Restate endpoint, which executes agents and never reaches the credential store (it reads nothing but its journal).

An entry the host cannot read is skipped, never guessed (parseProviderDecls, shared by the proxy and the @posos/llm runner so both hold the same list): a non-object declaration, an unknown kind, a mistyped baseUrl/apiKeyEnv/timeoutMs, a maxTokensField other than the two names above, or non-string header values are logged with the reason and drop out of the provider list. One bad entry does not take down the others.

A provider naming neither a declared entry nor a built-in is refused when the agent is saved, and logged at boot for agents already stored or contributed by a plugin (validateAgent, warnInvalidAgents) — instead of surfacing on the first run. The same list reaches the engine (makeCatalog({providers})), which is what an agent.inline node's provider is checked against — that node has no schema of its own. GET /api/catalog serves the list as llmProviders, which is what the console's provider selector offers.

Two operational notes. Authentication is expected to carry a key: a gateway that authenticates through headers alone still needs an apiKeyEnv (both callers refuse a provider with no key). And the variable named by apiKeyEnv must exist in both deployments' environments — the Restate endpoint executes agents, the proxy runs the workflow assistant; docker-compose.yml forwards only ANTHROPIC_API_KEY and OPENAI_API_KEY, so a house variable has to be added there for the containerized stack.

terminology

Optional map, default {}. Same PortBinding value type as ports, but keyed by code system: multiple terminology resolvers are active at once, routed by the system of the code being resolved.

buildTerminology() (apps/api/src/instance.ts) builds a RoutingTerminology from these entries. For each [system, binding] pair it resolves binding.adapter in the terminology port namespace and registers the adapter under that system, with access to the connection named by connection (else the default connection of the type) when the adapter requires one, as hermes does (type hermes). A binding whose adapter is not found is skipped with a warning. Systems not listed fall through to internal resolution. See Configure terminology.

sources

Deprecated: declare a pulled inbound connection instead. Optional map, default {}; keys are event-source names, values their parameters.

Still read at boot: each sources.<name> that names a loaded source with at least one binding left by eventBindings becomes the read-only inbound connection <name> of type <name>, with the entry as its parameters and, as its bindings, the eventBindings list restricted to the source (absent: every binding of the source). The identifier <name> keeps the event ids <name>:<feed>:<recordId>. An entry with the identifier of a connection declared under connections is not read. The proxy logs the warning clés sources et eventBindings du manifeste d'instance dépréciées : déclarer une connexion du type de la source sous connections, avec ses bindings.

The parameters are checked like those of a pulled connection. sources.<name>.baseUrl is no longer read: the connection gets the issue sources.<name>.baseUrl n'est plus lu : désigner une connexion par le paramètre connection. (… : clé réservée aux connexions sortantes. for a source without an outbound connection) and does not start.

# Deprecated form
sources:
  fhir-poll: { connection: entrepot, intervalSeconds: 15 }
eventBindings: [fhir-creatinine]
# Equivalent connection
connections:
  fhir-poll:
    type: fhir-poll
    connection: entrepot
    intervalSeconds: 15
    bindings: [fhir-creatinine]

eventBindings

Deprecated: list the bindings under bindings of each pulled connection. Optional string[]; when omitted the field is undefined. It applies only to the connections derived from sources.

Value Effect
omitted / undefined Each connection derived from sources enables every binding of its source.
array of names Each connection derived from sources enables the listed bindings of its source; a source with none listed produces no connection.

Binding names are defined by plugins; see Plugin manifest.

A binding that produces a declared event is checked against the event's contract when the plugins load, whether or not a connection enables it. A mismatch logs the warning « binding hors contrat » and the binding stays available; see Observability signals.

Complete example

apiVersion: meridian/instance-v1
name: exemple-chu
locale: fr
timezone: Europe/Paris                # horloge des workflows planifiés

# Required plugins, resolved on the registry (or overridden by a local path).
registry: gs://meridian-plugins       # or a local directory
plugins:
  "@posos/demo": "^0.1.0"             # short form ≡ { version: "^0.1.0" }
  "@posos/geriatrie": { version: "0.1.0" }
  "@acme/vitals": { path: ../vitals/dist }   # local override, no registry access

# Shipped content seeded into the definition store, on top of the host's
# system definitions.
seed: [content/clinical-demo]

# Connections to external systems; secrets as env:NAME.
connections:
  entrepot:
    type: fhir-r4
    baseUrl: https://fhir.chu.example/r4
    auth: { scheme: oauth2-client-credentials, tokenUrl: https://sso.chu.example/token, clientId: meridian, clientSecret: env:FHIR_CLIENT_SECRET }
  # Pulled inbound connection: the fhir-poll source and the bindings it enables.
  fhir-poll:
    type: fhir-poll
    intervalSeconds: 15
    startOverlapSeconds: 600
    bindings: [fhir-creatinine]       # absent: every binding of the source
  hermes-fr:
    type: hermes
    baseUrl: http://hermes.internal:8080
    languageRefsetId: "10031000315102"  # parameter of the hermes type
connectionDefaults:
  fhir-r4: entrepot
  hermes: hermes-fr

# Port delegation: which adapter serves each port + its concrete config.
ports:
  patient:      { adapter: fhir }          # default connection of type fhir-r4
  prescription: { adapter: fhir, connection: entrepot }
  agent:        { adapter: llm }
  notification: { adapter: console }
  decision:     { adapter: typesafe }

# Terminology routing, keyed by code system.
terminology:
  snomed-ct: { adapter: hermes }           # default connection of type hermes

The empty manifest (dev default) is valid with only apiVersion:

apiVersion: meridian/instance-v1
  • Environment variables — INSTANCE_CONFIG, MERIDIAN_REGISTRY, MERIDIAN_PLUGIN_CACHE, PLUGINS_PATH.
  • Topology — where the manifest sits in the deployment.
  • Plugin manifest — the plugin side: adapters, event sources, connection types, and bindings the instance selects.
  • Manage connections — connections of the manifest and of the console, defaults, secrets.
  • Bundled plugins — adapters and sources shipped in-repo.
97 documents17 sectionssource : /docs · généré au build