Connector Runtime
A Connector package implements an external protocol. Each configured integration becomes a Source with its own identity and lifecycle.
Package installation and Source creation are separate operations. Installing code creates zero Sources; a user or Host explicitly configures each Source instance.
Package
connectors/
└── oura/
├── connector.yaml
├── events.json
└── index.mjs
The installed entry is a JavaScript ESM module. Authors may use TypeScript during development, but the package must expose built ESM at the manifest's entry path.
Connector code is a trusted extension, not an App workload. Before import, the Host accepts either an official signature/hash or a human approval bound to the current package hash. Modifying package material invalidates a prior custom approval.
The child-process runner isolates lifecycle and mediates durable capabilities, but it is not the App sandbox. Only install Connector code you trust to run locally.
Manifest
manifestVersion: 1
id: oura
name: Oura
description: Imports sleep, readiness, activity, heart-rate, and related health records from Oura.
eventCatalog: ./events.json
entry: ./index.mjs
runtime:
mode: poll
defaultSchedule: "0 */6 * * *"
integrations:
mode: multiple
platforms:
darwin: {}
linux: {}
windows: {}
cloud: {}
auth:
type: managedProvider
providerId: oura
config:
lookback-days:
type: number
label: Lookback days
default: 3
| Field | Contract |
|---|---|
description | Required natural-language explanation of what the Connector captures. |
eventCatalog | Required package-relative JSON file declaring event types, descriptions, and payload JSON Schemas. |
entry | Built ESM entry relative to the package root. |
runtime.mode | Exactly watch, poll, or manual. |
defaultSchedule | Valid only for poll. Copied into a new Source; later schedule edits live in system state. |
integrations.mode | Required singleton or multiple; declares Source identity cardinality. |
platforms | Alternative supported placements, not simultaneous collection lanes. |
auth | none, apiKey, oauth2-public, or managedProvider. |
config | User-facing typed fields and author defaults. Tokens, checkpoints, and pause state never belong here. |
The event catalog is strict catalogVersion: 1 data with a non-empty eventTypes map. Every event type declares a natural-language description and a standard JSON Schema payloadSchema. Core validates and trust-hashes the file with the package; it does not infer output semantics from Connector source code.
Manifest material is static. Per-Source configuration, schedule, credential reference, checkpoint, warnings, and status live in .lamarck/system.db.
Source identity and lifecycle
A Source is one configured integration instance owned by its Connector package.
# singleton
connector:app-commits
# multiple; integration key is stable and user-selected
connector:google-calendar:work
connector:google-calendar:personal
| Operation | Effect |
|---|---|
| Install Connector | Add package code, manifest, and event catalog. Create zero Sources. |
| Add Source | Create integration identity, apply config defaults, attach auth, and initialize Source-owned state. |
| Pause Source | Stop automatic execution while preserving config, credentials, checkpoint, and schedule. |
| Resume Source | Return automatic execution policy to active; readiness is evaluated separately. |
| Remove Source | Stop it and remove its control-plane record. Previously appended D0 Events remain. |
| Remove Connector | Stop its runners and remove all owned Sources. Historical D0 Events remain. |
Active means automatic execution is allowed; it does not mean ready or currently running. Setup readiness, trust, platform requirements, observed run status, error, and pause policy are independent state.
Runtime modes
| Mode | Invocation | Examples |
|---|---|---|
watch | Long-lived, self-driven process emits as data arrives. The Host supervises it. | Mac AX, Telegram getUpdates, filesystem watch. |
poll | Scheduler invokes one bounded pass according to Source-owned cron state. | Oura, GitHub, Calendar synchronization. |
manual | Explicit bounded invocation with no automatic schedule. | Exports, imports, and on-demand capture. |
push is reserved for a future inbound delivery path and is not a v1 runtime mode.
Runner and capability broker
Host trust gate
↓
spawned Node child → import connector entry → run(context)
│
└─ IPC capability broker
├─ Guard writes + Host-injected source
├─ integration-scoped state
├─ integration-scoped warnings
├─ credential token access / refresh
└─ cancellation + run status
The child receives no SQLite handle, Guard internals, scheduler internals, or raw credential record. auth.getToken() asks the Host broker for the current token. state and warnings are automatically scoped to the active Source.
Operational warnings belong in system.db, not in D0. D0 records observations and meaningful product activity; it is not a connector log sink.
Code contract
export default defineConnector({
async run({ guard, auth, state, warnings, config, host, signal }) {
const cursor = await state.get();
const token = await auth.getToken();
// Fetch, redact, and normalize external data.
await guard.writeEvent({
type: "source.event",
externalId: "upstream-id",
startedAt: Date.now(),
payload: { cursor }
});
await state.set({ cursor: "next" });
await warnings.clear("backfill");
}
});
Do not pass source. The bound Guard derives it from the integration the Host invoked. externalId should be stable within that Source so the D0 uniqueness constraint makes retries idempotent.