Skip to content

[Decision] Ontology over external systems: an API-backed external datasource authenticates through a connector instance's credential (one Connect per vendor for actions and records), its own auth block, or static credentialsRef only (epic #27261) #27298

Closed

Description

@objectstack-fleet

director#1 · os-bill · session_01Utp6CbQLcy8yg6vhJVXXi8

Ruled: 6486136301 · letter A · 2026-10-29T02:25Z

Filing gate ② (a decision only the maintainer can make), filed on the maintainer's instruction in this session, 2026-10-28, verbatim: 「你说的问题立决策卡,挂在专题下面」. It follows the re-assessment of #27261 against #26702 / ADR-0143.

Placement. Epic: #27261 (parent; pm:epic subtree). Filed by session_01J8VVAmeQhJepVXSad145da. ⛔ Not a claim. No domain:* label: triage sets it, and domain:spec is expected because the answer is a key on the datasource contract.

维护者速读

Background

Governing text

Protocol statement. A is Metadata-protocol: added: one optional key on the datasource external block that names a connector instance, refused at build unless that instance is declared. B is added too: an auth block on the datasource with the ADR-0143 variants, plus the connection record binding a datasource. C adds nothing. A or B amends the standing rule "credentials only through credentialsRef" for API-backed datasources. That amendment is the point of this card.

Premises (read at origin/main e9c88f7c)

  1. Datasource secrets are sys_secret: references. Re-check: git grep -n "REF_PREFIX = 'sys_secret:'" origin/main -- packages/services/service-datasource/src/datasource-secret-binder.ts.
  2. The connector resolver seam is separate. Re-check: git grep -n "defaultEnvCredentialResolver" origin/main -- packages/services/service-automation/src/credential-resolver.ts.
  3. The two spellings differ across the two surfaces: credentialsRef in 39 non-test source files, credentialRef in 19. Re-check: git grep -lw credentialsRef origin/main -- 'packages/**/src/**' | grep -v -e test -e pin | wc -l (same for credentialRef). Not decided here; under A the divergence does not grow, because a connector-backed datasource names no secret itself.

Options

Option What it does What the customer sees Effort
A reference a connector instance The datasource's external block names a declared connector instance. The driver asks the automation service's resolver for a live credential per request (ADR-0143 D4). Static, OAuth, app-credential and signed kinds are all reused. "Connect HubSpot" once. Flows and HubSpot-backed objects both work. Reconnect fixes both. domain:spec 1 PR (S) + domain:server 1 PR (S–M), with P2 · no UI · no precedent
B own auth block Datasources gain the ADR-0143 variants. The connection record also binds (organization, datasource). A second Connect flow is added on the datasource page. Two "Connect HubSpot" entries, one for actions and one for data, each expiring on its own. spec M + server M + ui M · no precedent
C static only Datasources keep credentialsRef. OAuth sources are reachable only through a Tier A plugin driver written in code. No-code binding works only for key-based APIs. Everything else needs a developer. 0 now

In business terms. A: one key ring per vendor, used for both doing things and reading things. B: two key rings for the same vendor. C: the no-code door opens only for vendors that still accept a static key.

四维分析(业务立场)

  • 项目长远合理性(领起)。 两年后的样子:一个供应商连一次,平台既能对它执行动作,也能把它的数据当对象来读,换授权只换一处。主流平台就是这么建模的:Dataverse 的 virtual connector provider 建虚拟表时,直接用连接器的 connection reference 鉴权;Salesforce 的 Named Credential 是一个独立凭证对象,callout 和外部数据源都引用它的名字。A 正是这个终态。B 让同一个供应商的授权一分为二,过期、撤销、审计都要做两遍。C 把声明式档对 OAuth 系统关死,等于 P2 的主要目标客户用不了。
  • 实际业务拉动。 今天零拉动:object-gantt can no longer write back to a same-origin endpoint after #23082 — a measured producer of the retired view-level api source (read + write) #27130 走代码档,P2 要等第二个客户。所以只裁方向,实施随 P2 立卡,现在不派码。
  • 防 AI 犯错。 A 下 AI 作者只写一个实例名,build 时实例不存在就响亮拒收,凭据形状只有一处定义。B 下同一个供应商要在两处各写一遍鉴权,两处漂移时一边能用、一边失败,看起来像供应商故障。C 下 AI 会给 OAuth 系统写一个静态密钥,运行时 401。
  • 创业阶段不扩散。 A 只加一个可选键,不新增连接形态,不新增 UI。B 复制一整套鉴权契约。C 最省,但代价是 P2 的价值。

os-decision-facets

Prior rulings read: "external datasource authenticate connector connection OAuth credentialsRef" → 2 hits (#26702 open: connector-side only; #27230 closed, ruled A: connector static secrets, says nothing on datasources); ADR-0143 Q1 A / Q2 B / D3 / D4; ADR-0015 §10; #27261 ruling 6471382887 D1, D2; thread: none.

Recommendation

After the ruling

Related

#27261 (epic) · #26702 · #26768 / ADR-0143 · #27230 · #27130 · ADR-0015 · and the sibling decision card on Tier B's dialect, filed alongside this one.


Generated by Claude Code

Activity

  1. added
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    pm:epicReserved by a dedicated epic PM, parent or sub-issue; other PMs never take it; never with pm:queue
    on Oct 28, 2026
  2. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV

    A Tier A reading that bears on this decision, carried here, not filed (from the #27278 dev report 6485876530; seam-level probe at origin/main 6d7634a, not measured at a public door):

    • For a datasource whose driver a plugin already registered (driver.<name> service), DatasourceConnectionService returns already-registered before credential resolution: external.credentialsRef is not resolved, not handed to the driver, and does not fail the boot when no secret store is configured (0 resolver calls, with and without a secret store). A driver that is not pre-registered resolves it (1 resolver call).
    • So today a plugin driver gets its credential from the options the host passes to the plugin, and the "credentials only through credentialsRef" rule of ruling 6471382887 is not what Tier A does. The guide (PR docs(data-modeling): virtual objects — rows from your server, shown in any view (plugin-driver recipe) #27349, content/docs/data-modeling/virtual-objects.mdx § Credentials) states this behaviour as it is.
    • The dev's options: (A) the platform hands the resolved credentialsRef to a plugin driver; (B) bless host-composed plugin options as the Tier A channel and amend the rule; (C) refuse at boot a credentialsRef on a plugin-registered driver's datasource, so it is never silently ignored. Whatever this card rules for API-backed datasources should settle the plugin-driver case in the same ruling.
  3. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    director#1 · os-bill · session_01Utp6CbQLcy8yg6vhJVXXi8

    Brief-claimed-by: session_01Utp6CbQLcy8yg6vhJVXXi8 · batch #426 · 2026-10-29T02:14Z

    Director seat, summon #54 (ledger objectstack#12708, opening mark 6485456694). Presented to the maintainer in batch #426 as item 1 of 3, together with its sibling #27299 and #27302 (one family: epics #27261 / #27293).

    Seat increment (re-read at origin/main 73725c20, 2026-10-29T02:14Z):

    Prior rulings read: datasource, connector, credential, OAuth, credentialsRef → ADR-0143 D1 / D3 / D4 / Q1 / Q2, ADR-0015 §10; thread: 6471382887 (#27261), #27230 A; repo: objectstack-ai/objectstack

  4. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    director#1 · os-bill · session_01Utp6CbQLcy8yg6vhJVXXi8

    Ruling: batch #426 item 1 · letter A · maintainer 「同意」 2026-10-29T02:22Z

    Director seat, summon #54 (ledger objectstack#12708, opening mark 6485456694, brief 6486018608). The maintainer answered batch #426 in the summon chat with one word, verbatim: 「同意」 — the seat's letter on each of the three cards; for this card A.

    What the ruling binds (letter A): an API-backed external datasource authenticates by naming a declared connector instance in its external block and borrowing that instance's credential — static, oauth2, app-credential and signed kinds alike — through ADR-0143 D4's per-dispatch resolver. One Connect per vendor serves both actions (flows) and records (virtual objects); a reconnect fixes both. The key is one optional member of the datasource external block, refused at build when the named instance is not declared (Metadata-protocol: added, filed with P2). Execution identity is not reopened: ADR-0143 Q1 = A (organization-shared) applies to the virtual-object read as to the flow dispatch; object permissions and RLS stay the only gate on what a user sees (#27261 §5.9). Amendment recorded: #27261 ruling 6471382887's standing rule "credentials only through credentialsRef" and the epic body's §4 item 8 now read: through credentialsRef, or through a declared connector instance for an API-backed datasource. Not taken: B (a second grant per vendor, a second Connect flow, drift between two auth blocks), C (a static key for OAuth sources, runtime 401).

    Governing text: ADR-0143 D3 / D4 / Q1 A / Q2 B; ADR-0015 §10; ruling 6471382887 D1 / D2 on #27261; #27230 ruled A (connector static secrets). Premises re-read at origin/main 73725c20 (brief 6486018608).

    Workload of the letter: domain:spec 1 PR (S: the key plus an ADR-0015 amendment note, Tier H) + domain:server 1 PR (S–M: the shared resolver seam) · no UI · filed with P2 on the second customer pull (D1), not now · no precedent. Open readings for P2's spec child: whether the objectql-side driver reaches the automation service's resolver without a new dependency direction; whether the (organization, connector instance) binding fits an environment-level datasource (#27230 S1).

    Execution: nothing is dispatched. The epic PM of #27261 records this as D7 in the epic body and corrects §4 item 8; this card closes completed in this act (the ruling is its content; P2's children cite this comment on a Ruling-ref: line when filed).

    os-decision-facets
    ① 长远:一个供应商一份授权,动作与读数共用,与 Dataverse connection reference / Salesforce Named Credential 同形
    ② 拉动:今天零(#27130 走代码档,P2 等第二个客户);只定方向,实施随 P2
    ③ 防错:只写一个实例名,build 时实例不存在即响亮拒收;B 两处鉴权会漂移,C 诱导静态密钥
    ④ 不扩散:一个可选键,不新增连接形态与 UI

  5. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    director#1 · os-bill · session_01Utp6CbQLcy8yg6vhJVXXi8

    Closed completed · 2026-10-29T02:32Z · ruling 6486136301 (batch #426 item 1, letter A: an API-backed datasource borrows a declared connector instance's credential; execution identity stays ADR-0143 Q1 A). The epic PM records it as D7 on #27261 (pointer left there); P2's spec and server children cite the ruling when filed on the second pull. needs-user-decision leaves with the close; pm:epic stays — the card remains a ruled member of the subtree.

  6. removed
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    on Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    pm:epicReserved by a dedicated epic PM, parent or sub-issue; other PMs never take it; never with pm:queue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions