You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Builds on ADR-0015 (federation). Goal: declare an external datasource → it's visible, auto-connected, validated, and queryable with zero app boilerplate, through one connection mechanism shared by code- and runtime-origin datasources, backward-compatible (existing managed apps unchanged).
D1 New DatasourceConnectionService: given a datasource def, build a driver via the injected factory, connect, and engine.registerDriver under the datasource name. One "definition → live driver" path (extract from standalone-stack.ts, call from app-plugin.ts).
D2 Opt-in-safe gating: connect only when the datasource is external, or an object/datasourceMapping routes to it, orautoConnect: true. A managed+unrouted datasource stays metadata-only. examples/app-crm and other existing apps must be byte-for-byte unchanged.
D5 Lifecycle: connect/disconnect (graceful shutdown), per-datasource pool, optional health probe in the admin list; connect before the kernel:ready validation gate; fail-fast for external + onMismatch:'fail', degrade-with-warning otherwise.
Refactor the single default-driver bootstrap onto the same service last (highest-risk; behind tests).
Acceptance: a stack that only declares an external datasource (no onEnable) can query its federated objects via REST; full dogfood gate green (every example app boots); app-crm behavior unchanged.
Phase 2 — credentials at connect (D3)
Resolve external.credentialsRef / secret config via SecretBinder over ICryptoProviderbefore building the driver; converge with the runtime-admin "Add Datasource" secret path.
Fail-closed (clear boot error, datasource left unconnected) when the host can't decrypt; open-core default InMemoryCryptoProvider.
Acceptance: a Postgres external datasource with credentialsRef connects using the decrypted secret; missing/undecryptable secret fails closed with a clear message (no silent skip).
Phase 3 — native-analytics SQL over external objects (D6)
Route the analytics native-SQL strategy's FROM/column references through the driver's physical-table/column resolution (remoteName/remoteSchema/columnMap) — reuse, don't re-implement.
Until done, analytics over external objects stays disabled rather than querying the wrong table.
Acceptance: a dashboard/report over a federated object aggregates against the correct remote table/columns.
Phase 4 — reconciliation + cleanup (D7, D8)
D7 For external objects, columnMap is authoritative; reject field.columnName on external objects at validation (no silent dual-source) until a unified column-resolution model exists. Managed field.columnName untouched.
D8 Drop the onEnable driver-registration bridge from examples/app-showcase (fixture provisioning may remain); keep onEnable + ctx.drivers.register documented as the escape hatch.
Acceptance: showcase declares its external datasource with no onEnable driver wiring and still works end-to-end.
Notes
Each phase = its own PR + changeset (published packages are in the fixed group).
Phase 1's default-driver refactor is the riskiest single step (hot boot path for all apps) — land declared-datasource auto-connect first, refactor default last, behind the dogfood gate.
Tracking/epic issue to drive ADR-0062 — External Datasource Runtime to completion.
docs/adr/0062-external-datasource-runtime.md(merged in docs(adr): ADR-0062 — External Datasource Runtime (connection, credentials, visibility, query completeness) #2162)Phase 0 — shipped ✅
remoteName/remoteSchema— fix(driver-sql,objectql): honor external.remoteName/remoteSchema in the federation read path (ADR-0015) #2138external.columnMap(remote col ≠ local field) — feat(driver-sql): honor external.columnMap on federated objects (ADR-0015) #2149objectstack verifyskip for read-only external — feat(app-showcase): add an end-to-end external datasource + federated object example (#2111) #2139/api/v1/datasources+/meta/datasource+ Setup — fix(runtime): surface code-defined datasources on the host-config boot path (ADR-0015 §18) #2157Phase 1 —
DatasourceConnectionService+ auto-connect (D1, D2, D5) — coreDatasourceConnectionService: given a datasource def, build a driver via the injected factory, connect, andengine.registerDriverunder the datasource name. One "definition → live driver" path (extract fromstandalone-stack.ts, call fromapp-plugin.ts).external, or an object/datasourceMappingroutes to it, orautoConnect: true. A managed+unrouted datasource stays metadata-only.examples/app-crmand other existing apps must be byte-for-byte unchanged.kernel:readyvalidation gate; fail-fast forexternal+onMismatch:'fail', degrade-with-warning otherwise.default-driver bootstrap onto the same service last (highest-risk; behind tests).onEnable) can query its federated objects via REST; full dogfood gate green (every example app boots); app-crm behavior unchanged.Phase 2 — credentials at connect (D3)
external.credentialsRef/secretconfig viaSecretBinderoverICryptoProviderbefore building the driver; converge with the runtime-admin "Add Datasource" secret path.InMemoryCryptoProvider.credentialsRefconnects using the decrypted secret; missing/undecryptable secret fails closed with a clear message (no silent skip).Phase 3 — native-analytics SQL over external objects (D6)
FROM/column references through the driver's physical-table/column resolution (remoteName/remoteSchema/columnMap) — reuse, don't re-implement.Phase 4 — reconciliation + cleanup (D7, D8)
columnMapis authoritative; rejectfield.columnNameon external objects at validation (no silent dual-source) until a unified column-resolution model exists. Managedfield.columnNameuntouched.onEnabledriver-registration bridge fromexamples/app-showcase(fixture provisioning may remain); keeponEnable+ctx.drivers.registerdocumented as the escape hatch.onEnabledriver wiring and still works end-to-end.Notes
default-driver refactor is the riskiest single step (hot boot path for all apps) — land declared-datasource auto-connect first, refactordefaultlast, behind the dogfood gate.References
packages/runtime/src/{standalone-stack,app-plugin}.ts,packages/objectql/src/engine.ts,packages/services/service-datasource/*,packages/plugins/driver-sql/src/sql-driver.ts