Connectors
Author custom low-code connectors as code, versioned alongside your
connections/ and cubes/. When the source you need isn't in the built-in
catalog, write it locally, test it, and register it with revos apply — after
which it behaves like any other source type: create a
Source against it (with
real credentials) and reference that Source from a
Connection.
Project layout
Each connector lives in its own directory under connectors/:
connectors/
my-source/
connector.yaml # RevOS resource wrapper (kind: Connector)
manifest.yaml # the low-code connector manifest
secrets/
config.json # the connector's config values (gitignored)
integration_tests/
configured_catalog.json
# connectors/my-source/connector.yaml
apiVersion: revos/v1
kind: Connector
metadata:
name: my-source # local slug identity (folder + address); id is written back on apply
spec:
name: My Source # the registered name (shown in the UI); free-form
type: declarative
There are two names, with two jobs (the same split a Connection uses):
metadata.nameis the local slug identity — the directory name and the address other resources reference it by. It is never sent upstream. Rename it (and the folder) for a local-only move;metadata.idkeeps the rename from orphaning, and the engine re-matches by that id, so nothing changes for the registered connector.spec.nameis the connector's registered name (what the UI shows). Edit it and re-apply to rename the connector — an ordinary spec change.
This keeps pull → diff clean for free-form names: pull writes the
registered name verbatim into spec.name, so My Source never drifts against
the my-source slug. The manifest lives in the sibling manifest.yaml, not in
connector.yaml.
Workflow
revos connectors new my-source # scaffold a runnable hello-world
revos connectors check my-source # run it locally (also: spec/discover/read)
revos apply # register with RevOS (picks up connectors/*)
| Command | Behavior |
|---|---|
revos connectors new <name> | Scaffold a runnable hello-world connector against a public API, plus a gitignored secrets/config.json for its config values. |
revos connectors spec <name> | Show the connector's config schema, read from its manifest. Pure-local. |
revos connectors check <name> | Run the connector locally and test the connection (SUCCEEDED / FAILED). Reads secrets/config.json (or --config). |
revos connectors discover <name> | Run the connector locally and list the streams it exposes. |
revos connectors read <name> | Run the connector locally and stream sample records. Add --catalog / --state. |
revos apply [connectors/<name>] | Register (or update) the manifest(s) with RevOS — the whole project, or one connector by path. Idempotent; bumps the version on change; writes the id back. The payload contains no credentials. |
revos connectors delete <name> | Unpublish the connector from the workspace (by its recorded id) and clear that id locally, keeping the files. Add --purge to also delete the local directory, --yes to skip the confirmation. |
check, discover, and read require the connector test runtime on PATH
(pre-installed in the RevOS Dev Container). new, spec, apply, and delete
do not. Outside the Dev Container, if the runtime is missing these commands stop
with the exact one-line install command to run — install it once and they work.
Run locally
Each operation is its own command, run against your manifest without leaving your machine:
spec— the connector's configuration schema (local; no config needed)check— verify the supplied config can connect (SUCCEEDED/FAILED)discover— the streams the connector exposesread— stream records (needs--catalog, defaulting tointegration_tests/configured_catalog.json)
revos connectors spec my-source
revos connectors check my-source
revos connectors discover my-source
revos connectors read my-source
Apply and use
revos apply registers the manifest with RevOS and writes the assigned id back
into connector.yaml's metadata.id. It picks up every connector under
connectors/; pass a path (revos apply connectors/my-source) to scope it to
one. Re-running is idempotent; changing the manifest bumps the version, and
editing spec.name renames the connector (renaming metadata.name + the folder
is a local-only move). Once applied it appears as a
selectable source type: create a Source against it through the usual flow and
reference that Source from a Connection — no special syntax.
Delete
revos connectors delete <name> removes a connector. By default it unpublishes
the connector from the workspace (using the id recorded in connector.yaml) and
clears that id locally, keeping the files — so a later revos apply
recreates it. Pass --purge to also delete the local connectors/<name>/
directory, and --yes to skip the confirmation prompt.
revos connectors delete my-source # unpublish, keep the local files
revos connectors delete my-source --purge # unpublish and remove the directory
A connector that was never applied has no recorded id, so there is nothing to
unpublish — --purge just removes its local files.
Credentials stay in secrets/, never committed
A connector's config values for the local test loop live in
secrets/config.json:
{ "api_key": "your-key-here" }
secrets/ is gitignored, so real credentials you put there are never committed.
check/discover/read read this file (override with --config <path>, e.g.
CI secrets); spec needs none. The connector runs entirely on your machine —
nothing is uploaded.
Real per-tenant credentials are entered later, server-side, exactly as they are
for built-in sources — they are never written to the project tree and never
uploaded by revos apply. The scaffolded .gitignore excludes
connectors/**/secrets/, connectors/**/config.json, connectors/**/*.env,
and connectors/**/.env*.