Skip to content

connectors: outbound OAuth in the open tier — connection-scoped authorization-code / client-credentials / app-credential tokens, refreshed per dispatch, for the openapi, mcp and rest providers #26702

Open

Description

@objectstack-fleet

Unblocked (triage, 2026-10-30): ADR-0143 is Accepted on main (PR #27231); #26768's only open item is the cloud mirror record (objectstack-ai/cloud#3350), which gates no code in this repo.
Filing-gate category: ③ maintainer-directed task.

Maintainer ruling (verbatim, not translated)

OAuth 放开源层,先起草 ADR 修订

平台基于 better-auth ,怎么会有没有 oauth

创建issue 就行

The first line moves the boundary. The third replaces the ADR draft with this card. The ADR revision is still owed and is listed under "Work" below.

Business reason

Who benefits: app builders whose flows and agents must act in the SaaS their customers already run. That means Salesforce, Slack, HubSpot, Jira/Confluence, Notion, Asana and Stripe abroad, and Feishu, DingTalk and WeCom at home.

Scenario: an AI-authored app declares a connector instance as metadata. An admin clicks "Connect" once. A flow's connector_action step then calls the vendor on every run without anyone pasting tokens into env vars.

Without it: the connector layer reaches only APIs that accept a static key. A survey of the vendors' own channels found that the common products now ship their integrations as hosted MCP servers that require OAuth. The same survey found the Chinese suites issue short-lived tokens from app credentials. Neither shape is reachable today, so the "integration-heavy enterprise core system" the platform targets stops at the long tail.

Product Vendor channel found Auth it requires
Salesforce, Slack, HubSpot, Atlassian, Notion, Asana official hosted MCP server OAuth (HubSpot: OAuth 2.1 + PKCE)
Stripe stripe/openapi (MIT, OpenAPI 3) + hosted MCP static key for the spec path; OAuth for MCP
Feishu official lark-openapi-mcp (MIT, beta) App ID/Secret → tenant_access_token (~2 h)
DingTalk official open-dingtalk/dingtalk-mcp + MCP square AppKey/Secret → access token

The bulk-catalog alternatives were measured and rejected for this goal; the numbers are in the session analysis. For example, microsoft/PowerPlatformConnectors has 1187 definitions, and 766 of them convert with createOpenApiConnector. None of the mainstream products above is among them: those connectors are closed-source, and the ones present are in the OAuth tier.

Current state (read at 71a4b4ea)

Inbound OAuth exists; outbound connector OAuth does not. better-auth already gives the platform three things:

  • sign-in OAuth (socialProviders, packages/plugins/plugin-auth/src/auth-plugin.ts);
  • an authorization server for MCP clients (@better-auth/oauth-provider, mapped in auth-schema-config.ts);
  • a user account table that stores access_token / refresh_token / access_token_expires_at.

Nothing on the connector side uses any of it:

  • ConnectorInstanceAuthSchema (packages/spec/src/shared/connector-auth.zod.ts) is none | bearer | api-key | basic. Its header says "OAuth2 is intentionally absent (enterprise tier, ADR-0015)".
  • ConnectorOAuth2Schema exists as a runtime shape, but no provider consumes it.
  • credentialRef is resolved once, at materialization (ADR-0097 §3; defaultEnvCredentialResolver reads env vars). A token that expires has no refresh point.
  • The connector-mcp http transport sends only static headers (mcp-provider.ts, applyAuthToHeaders). It cannot perform the MCP authorization flow: protected-resource discovery, dynamic client registration and PKCE.
  • connector-openapi maps only static schemes. An oauth2 securitySchemes entry is dropped.

Work (each item is a slice; the ADR comes first)

  1. Governance. Write a successor ADR in this repo that moves outbound connector OAuth into the open tier. Amend the status lines of ADR-0015, ADR-0022, ADR-0023, ADR-0024 and ADR-0097 where they place OAuth2 in the enterprise tier. Per AGENTS.md Prime Directive 13, the boundary half also needs a cloud ADR-NNNN record with a ## Provenance pointer from here. Both are Tier H governed surfaces, so the maintainer lands them.
  2. Connection record. Store per-connection grants with tokens encrypted at rest, never in metadata. Org-scoped by default; the ADR decides whether per-user connections exist. Design fork for the ADR: reuse better-auth's account storage and refresh, or keep a separate connection object. A linked account is also a sign-in method, which an integration grant must not become.
  3. Grant types.
    • authorization_code + PKCE + refresh;
    • client_credentials;
    • vendor app-credential exchange (Feishu / DingTalk / WeCom), non-interactive.
  4. Resolve per dispatch, not at boot. The CredentialResolver seam answers with a live access token, refreshing on expiry or on a 401 once. This is a change to the ADR-0097 contract.
  5. Authoring contract (packages/spec). ConnectorInstanceAuthSchema gains an oauth2 variant: endpoints, clientId, credentialRef for the client secret, scopes and grant type, and a reference to the connection. Inline tokens or secrets are refused at publish, as today.
  6. Providers.
    • mcp: the MCP authorization flow on the http transport.
    • openapi: map oauth2 securitySchemes.
    • rest: accept the oauth2 variant.
  7. Console. Add a "Connect / Reconnect" flow and a connection status view, so a degraded instance (ADR-0097, upstream-unavailable) names an expired or revoked grant. This is a ui/ follow-up.

Decisions the successor ADR must put to the maintainer

  • Connection ownership and execution identity. Org-shared connection vs per-user connection, and whose grant a flow run uses (ADR-0073).
  • Storage. Reuse better-auth account storage, or a dedicated connection object.
  • First products. Which products the first acceptance targets.

Acceptance (to be pinned by the ADR)

  • A declarative provider: 'mcp' instance pointing at an OAuth-protected vendor MCP server is authorized once from the Console. A flow connector_action dispatches end to end. After the access token expires, the next dispatch refreshes it with no operator action.
  • A Feishu (or DingTalk) instance declared with app credentials dispatches through the openapi or rest provider. Its token renews without restart.
  • No token or client secret appears in sys_metadata, in GET /api/v1/automation/connectors, or in logs.

Out of scope

  • Curating which actions each product exposes. That is a separate catalog card once auth lands.
  • Bulk import of third-party catalogs.

Who acts

  1. The domain:skills seat drafts the successor ADR, which the maintainer lands (Tier H).
  2. The domain:server seat then takes packages/connectors/*, packages/services/service-automation and packages/plugins/plugin-auth. The packages/spec auth variant is a Seam: for the domain:spec seat. The Console flow goes to domain:ui.

Triage assigns the final lanes.

Duplicate check

Semantic issue search on objectstack-ai/objectstack, open and closed:

Query Hits Relevant
"connector OAuth2 authorization code refresh token connection credential" 0 —
"credentialRef vault CredentialResolver token exchange client credentials Feishu DingTalk" 0 —
"connector oauth" 4 none — all inbound MCP-server OAuth (25118, 24166, 24137, 21885)
"MCP connector remote server OAuth client authentication" 12 (10 returned and read) none — all inbound: our MCP server and better-auth as authorization server, e.g. 20791, 25118, 24137

No card covers outbound connector OAuth.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — enhancement · security · priority:p1 · domain:server · area:api · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-27T14:12Z

    ⛔ Not a claim, ⛔ not a dispatch.


    Generated by Claude Code

  2. added
    area:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobs
    domain:serverDomain lane — seat card indexed by label:pm:seat
    enhancementNew feature or request
    priority:p1High: required for production / M2
    and removed on Oct 27, 2026
  3. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    pm:queue → pm:blocked · domain:server seat 3 · session_01QSeKYmQXM3rHJcPnrEPk4B · 2026-10-27T15:09Z

    Blocked-by: #26768

  4. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Part of #27293 (E1 platform prerequisites) · 2026-10-28T14:59Z

    Epic link on the maintainer's ruling 「是否建议立专题卡统一处理。」→「同意」 (2026-10-28, session_01J8VVAjRKqdoEYQ4hXxtBuf). Role in the chain: the outbound OAuth variant that admits the OAuth-protected half of E4 (Microsoft Graph, Notion, Atlassian, Google, DocuSign); its successor ADR also carries #26710's signing decision. Lane claims and dispatch proceed as triage set them; the epic PM seat (epic:#27293) tracks this card and reserves only what it drives in order. ⛔ Not a claim.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U

    Reserved for the epic subtree · 2026-10-28T15:12Z — pm:epic added; pm:blocked (Blocked-by: #26768) unchanged.

    The maintainer in session_017xRBcVBKAFk1ntXSjvPt7U, 2026-10-28, verbatim: 「有很多子卡,这是没有挂到子任务,你应该处理。」 This card is attached under #27293 and now carries pm:epic: other seats' candidate reads skip it; the epic PM claims it with the full claim protocol when it dispatches. ⛔ Not a claim, ⛔ not a dispatch.

  6. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: 可对外的 API | none | P②

    Triage: unblocked · p1 kept · domain:server · 2026-10-29T04:01Z

    ⛔ Not a claim.


    Generated by Claude Code

  7. 28 remaining items

  8. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibwa6RkD7A2gK6rYRNT
    os-dev-report

    {
     "issue": 26702,
     "status": "needs_decision",
     "branch": "claude/project-thread-8z6igj",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/28399",
     "session": "session_01L9qibwa6RkD7A2gK6rYRNT",
     "slice": "S2 (providers), first half by provider: rest + openapi + the D2.2 app-credential transport. The mcp half is a second PR on the same branch after this one lands.",
     "premise_still_valid": true,
     "summary": "The rest and openapi plugins register with { credentialHandle: true }; with a handle every request goes through callWithBorrowedCredential for the run's organization (401 refresh once + retry once, second 401 = 503), transport errors are scrubbed of the credential, and a handle beside a static credential or signer is refused. openapi reads security: an operation with security [] is anonymous, and a required apiKey scheme's parameter is platform-filled and leaves the input schema. service-automation gains oauth2-grant/app-credential.ts: Feishu, DingTalk (v1.0) and WeCom exchanges per vendor docs, a memory-only handle with skew margin and single flight, no redirect, refusals naming only the vendor code; WeCom's in-body early invalidation (40014/42001) refreshes once and repeats once. The materializer serves app-credential on opted-in providers and holds it degraded otherwise. needs_decision is for the mcp discovery-organization point only; PR 28399 itself is complete for review.",
     "tests": "connector-rest vitest: 5 files, 43 passed (new rest-provider-credential-handle.test.ts 10, incl. WeCom end to end through AutomationServicePlugin + ConnectorRestPlugin). connector-openapi: 7 files, 89 passed (new 7). service-automation full suite 243 files / 3084 passed on 1838861a; app-credential.test.ts 19/19 on be639274; connector-materialization app-credential cases 3. Ablations via scripts/ablation-replace.mjs, 16, each red then restored with git diff HEAD empty: rest get-only call, rest exclusivity, rest scrub, openapi anonymous, openapi scheme-filled exclusion, openapi exclusivity, openapi get-only call, rest plugin opt-in, openapi plugin opt-in, no-answer refusal carrying the transport error, redirect: 'error' removed, WeCom first-answer passthrough, WeCom second-answer passthrough, handle single flight, plugin guard on a non-opted provider, and the WeCom wrap removed in plugin.ts with service-automation dist rebuilt (ablation-dist-preflight --absent exit 0; restore, rebuild, preflight present exit 0, test green).",
     "gates": "head be639274 (gates swept on 84f40d95; the last commit only types two test reads). dispatch-gates --commands: 73 families. First sweep: check:test-source-alias exit 1 (new @objectstack/types import unaliased in connector-rest/openapi) fixed by anchored aliases; check:plugin-teardown-shape --self-test exit 3 cleared by fetching its pinned commit; check:dual-build-cjs-loads exit 3 cleared by a whole-tree turbo build (77 tasks). Re-runs exit 0; check-console-intercept-disarm exit 0 for the new rest vitest config. --ran: 73 derived, 73 run, 0 NOT-MEASURED, 0 unrun. pnpm --filter <pkg> run typecheck exit 0 for connector-rest, connector-openapi, service-automation. eslint scoped to the touched packages exit 0. CI on the PR: pending at report time.",
     "line_budget": {
      "additions": 1352,
      "deletions": 108,
      "files": 21
     },
     "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
     "declarations": "Clause-②: yes (widening). Metadata-protocol: semantic (app-credential and oauth2 on rest/openapi now dispatch instead of holding degraded; openapi security [] now means anonymous). Skills-docs: follow-up owed — content/docs/automation/connectors.mdx and skills/objectstack-automation/references/integration-recipes.md still say app-credential and the built-in providers are not served; both are outside this card's file surface.",
     "mcp_calls": "reads only: issue_read (#26702 body and comments), pull_request_read get #28317; 0 writes",
     "api_writes": "relay only: pr_create objectstack-ai/objectstack#28399 (run 41195973877, 12248 bytes identical on read-back); this report via post-stamped",
     "open_questions": [
      {
       "question": "Which connection's token does an oauth2 mcp instance's tool discovery use? Measured: the mcp provider runs connect + tools/list once, inside the factory at materialization (mcp-provider.ts createMcpConnector), outside any run, so there is no run organization. S1's handle answers a no-organization ask from the only connection and refuses 422 when there are several (grant-handle.ts). S1 re-materializes only on any-connection <-> none, so the first connect lists with exactly one connection, but a boot or reload with two or more connected organizations has no rule. ADR-0143 D4's no-organization rule is written for a run; it does not say what materialization uses.",
       "options": [
        "A D4-literal: discovery asks with no organization. One connection lists; with several, the instance is held degraded naming the ambiguity until one remains. Cost: an instance two organizations connected stops working after a restart. Small.",
        "B One deterministic connection for tools/list only: the earliest connected_at (ties by organization id), re-listed on connect/revoke; every dispatch still uses its own run's organization's token. Cost: the vendor sees that organization's token on a catalogue read no run made; the tool list reflects that organization's grant. Small to medium.",
        "C Per-organization listing: materialize from a declared providerConfig.include (required for oauth2 mcp), and list per organization lazily on its first dispatch. Cost: a new authoring requirement and per-organization defs. Large."
       ],
       "recommendation": "B, because it keeps every dispatch on its own organization's token (D4 for runs holds), never degrades a working multi-organization instance on restart, and stays small; the one cross-organization use is a catalogue read with no record data."
      }
     ],
     "out_of_scope_findings": [
      "class: b · reach: named producer · the mcp half needs two edits outside the claimed surface: a registered_client secret column on sys_connector_connection (S1's object) and the DCR/discovery step in service-automation's connect flow (plugin.ts begin/completeConnectorConnection, not the materializer guard). The seat to widen the surface for PR 2, or rule it out.",
      "class: b · reach: docs · content/docs/automation/connectors.mdx (grant-bearing section and failure-modes row) and skills/objectstack-automation/references/integration-recipes.md go stale with PR 28399; declared Skills-docs follow-up owed; this thread can carry them in PR 28399 if the seat widens the surface."
     ]
    }
  9. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    Claim amendment to 6541963747 (slice S2) · 2026-10-31T11:17Z · File surface increment, declared

    S2 is split by provider (dev report 6542669233): PR #28399 carries rest + openapi + the D2.2 app-credential transport; the mcp half follows as a second PR on the same branch after #28399 lands.

  10. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    Landing record · #26702 S2 (providers) · PR #28399

    domain:server seat 1 · session_01L9qibz3ZUbZ8Qcn1rDw9yc · 2026-10-31T12:23Z

    Reading Probe Result
    Merged GET pulls/28399 merged, 7e9f8143
    Ancestry git merge-base --is-ancestor 7e9f8143 origin/main yes
    Content git grep -l credential handle on origin/main in connector-rest / connector-openapi rest-provider-credential-handle.test.ts, openapi-provider-credential-handle.test.ts and the provider sources
    • Landed (Part of): the rest and openapi providers read the connection's credential handle, and feishu/dingtalk/wecom take an app credential.
    • Card stays claimed: the mcp half (the registered_client column on sys_connector_connection plus DCR/discovery in the plugin.ts connect flow, claim amendment 6542689344) follows on the same branch claude/project-thread-8z6igj. It is waiting on Tesla's ruling about which organization runs discovery.
    • Docs/skills follow-up: content/docs/automation/connectors.mdx and skills/objectstack-automation/references/integration-recipes.md were not carried here (skills/** is Tier H). The seat files them as a separate card.

    State: pm:dispatched kept, assignee os-tesla, claim 6541963747 stands.

  11. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    Claim amendment to 6541963747 (slice S2) · 2026-10-31T12:25Z · File surface increment, declared

    PR #28399 merged at 7e9f8143. content/docs/automation/connectors.mdx now says two things that are false on main, in the paragraph that begins "What is not served yet is held degraded":

  12. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibwa6RkD7A2gK6rYRNT
    os-dev-report

    {
     "issue": 26702,
     "status": "done",
     "branch": "claude/project-thread-8z6igj",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/28419",
     "head": "18e9b3f050ea98a65f4802c5ed55398f32cf10ae",
     "session": "session_01L9qibwa6RkD7A2gK6rYRNT",
     "slice": "S2 docs-only follow-up of PR 28399 (surface amendment 6543339271): content/docs/automation/connectors.mdx.",
     "premise_still_valid": true,
     "summary": "The 'held degraded' paragraph no longer lists app-credential or the rest/openapi providers; it keeps mcp (and plugin providers registered without credentialHandle) as not served. 'How the server serves them' gains the credential handle rest/openapi ask, the openapi security rules for a handle (security [] anonymous; apiKey parameter platform-filled), and an app-credential paragraph plus a per-vendor table (Feishu, DingTalk v1.0, WeCom: token request and where the token rides), memory-only token with the 30 s skew, refresh once on 401, single flight, WeCom 40014/42001 refresh-once and repeat-once, no redirect, and the failure split. The failure-modes row is narrowed to 'a provider that does not ask the credential handle (the built-in mcp provider, for now)'. Facts read from merged code (app-credential.ts, plugin.ts, openapi-connector.ts, connector-credential-source.ts). The line-404 hunk that draft 28346 edits and every skills/** file are untouched.",
     "tests": "none: docs-only.",
     "gates": "dispatch-gates --commands: 43 families for the one path, all exit 0. check:docs exit 1 and check:skill-examples exit 3 on the first run were a stale packages/spec/json-schema in this worktree (a build prerequisite, not a finding); after pnpm --filter @objectstack/spec build both exit 0. --ran: 43 derived, 43 run, 0 NOT-MEASURED, 0 unrun. CI on the PR: pending at report time.",
     "line_budget": { "additions": 40, "deletions": 7, "files": 1 },
     "dogfood_battery": "n/a: docs-only",
     "declarations": "Clause-②: no. Metadata-protocol: none. Skills-docs: the skills half is #28299 (skills lane); no skills/** file touched. No changeset: the PR was created with the skip-changeset label.",
     "mcp_calls": "reads only: pull_request_read get #28399; 0 writes",
     "api_writes": "relay only: pr_create objectstack-ai/objectstack#28419 (run 41202335114, 5561 bytes identical on read-back, label skip-changeset); this report via post-stamped",
     "open_questions": [],
     "out_of_scope_findings": []
    }
  13. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    Landing record · #26702 S2 docs · PR #28419

    domain:server seat 1 · session_01L9qibz3ZUbZ8Qcn1rDw9yc · 2026-10-31T13:16Z

    Reading Probe Result
    Merged GET pulls/28419 merged, 380a1078
    Ancestry git merge-base --is-ancestor 380a1078 origin/main yes
    Content git grep -c x-acs-dingtalk-access-token in content/docs/automation/connectors.mdx on origin/main 1
  14. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    Ruled: B, for which organization's connection an mcp instance's tool discovery uses (dev report 6542669233, options A/B/C) · 2026-10-31T15:12Z

    Maintainer, verbatim, in the project thread at 2026-10-31T15:10Z: 「同意」. The answer was to the decisions list decisions/2026-10-31-director-rulings.md, whose item 5 recommends B ("全部按推荐可以只回…"). So it is B.

    • B: tools/list at materialization uses the connection with the earliest connected_at. Each dispatch still uses the token of its own run's organization.
    • Not chosen: A, D4 literally (no organization, so the instance is degraded while several connections exist). C, discovery per organization with providerConfig.include required.
    • Rollback: B is one connection-selection rule and can be turned back to A.

    Execution: the held mcp half of S2 (branch claude/project-thread-8z6igj, rebased on 380a1078) finishes on B and opens as its own PR, Part of #26702, with the surface from claim amendment 6542689344. The same PR updates the connectors.mdx "not served yet" paragraph for mcp. The claim 6541963747 stands.

  15. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibwa6RkD7A2gK6rYRNT
    os-dev-report

    {
     "issue": 26702,
     "status": "done",
     "branch": "claude/project-thread-8z6igj",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/28437",
     "head": "5021bd3d43732515fde6944baedd8fc9d84d9d5f",
     "session": "session_01L9qibwa6RkD7A2gK6rYRNT",
     "slice": "S2 (providers), second half: the mcp provider and the MCP authorization flow (surface amendment 6542689344), discovery organization per ruling 6545215904 (B), plus the mcp lines of connectors.mdx.",
     "premise_still_valid": true,
     "summary": "connector-mcp registers with { credentialHandle: true }; over http every MCP request asks the handle (401 refresh once + retry once, second 401 = 503), one session per organization, failed sessions not kept, stdio or static beside a handle refused. service-automation runs the MCP authorization flow at connect for an authorization_code mcp instance over http that leaves endpoints/client undeclared: RFC 9728 PRM (resource check), RFC 8414/OIDC AS metadata (issuer equality, S256), RFC 7591 public-client DCR or the declared clientId, RFC 8707 resource on every request, RFC 9207 iss check, https-only, no redirects, refusals naming no server text. The discovered client is kept in the new encrypted sys_connector_connection.registered_client; refreshes and reconnects use it. Ruling B: while an authorization_code mcp instance materializes, a no-organization ask is answered as the earliest-connected organization (connected_at, ties by organization id); afterwards such an ask follows D4 (only connection or 422). The discovery organization joins the mcp signature, so revoking/refusing/reconnecting it re-materializes and re-lists. connectors.mdx: mcp leaves the not-served paragraph and the failure row; the mcp paragraph, the discovery rule and the authorization flow are described.",
     "tests": "service-automation full suite 246 files / 3131 passed; connector-mcp 6 / 64; connector-rest 5 / 43; connector-openapi 7 / 89 (pre-rebase onto 630b4078, comment-only upstream changes in touched files); after the rebase typecheck x2, door + oauth2-grant suites and the connector-mcp suite re-run green. New: door test 14 (incl. ruling B end to end with three organizations), mcp-authorization unit 8, grant-handle kept-client 4, mcp provider over a real Streamable-HTTP server 8. Ablations 25 via scripts/ablation-replace.mjs, each red then restored with git diff HEAD empty: 14 flow (iss, S256, issuer, resource, server https, guard https, AS https, redirect, registration text, no-answer, declared secret, reconnect reuse, kept-client refresh, log leak), 7 provider (per-org session, refresh-once, stdio, exclusivity, failed session, close, opt-in), 4 ruling B (pass-through while materializing, never settle, no discovery in signature, latest instead of earliest).",
     "gates": "dispatch-gates --commands: 104 families, all exit 0 after pnpm install + turbo build of ./packages/**; --ran: 104 derived, 104 run, 0 NOT-MEASURED, 0 unrun. pnpm --filter <pkg> run typecheck exit 0 for connector-mcp and service-automation (one test-only fix: Array.prototype.at is outside the test lib). eslint on touched sources exit 0. After the rebase: check:doc-authoring, check:doc-anchors, check:docs-transcript-drift, check:doc-security-posture exit 0. CI on the PR: pending at report time.",
     "line_budget": { "additions": 1935, "deletions": 79, "files": 21 },
     "dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm",
     "declarations": "Clause-②: yes (widening). Metadata-protocol: semantic (oauth2/app-credential on mcp now dispatch instead of holding degraded; an mcp authorization_code instance may leave endpoints/client to discovery). Skills-docs: skills half is #28299; connectors.mdx carried here per the seat.",
     "contract_review": "owed: Clause-② yes (widening), and sys_connector_connection gains a column (registered_client, Field.secret). packages/spec not touched.",
     "mcp_calls": "reads only: pull_request_read (#28399, #28419 check runs), issue_read (#26702 comments); 0 writes",
     "api_writes": "relay only: pr_create objectstack-ai/objectstack#28437 (run 41217718378, 13165 bytes identical on read-back); this report via post-stamped",
     "open_questions": [],
     "out_of_scope_findings": [
      "class: b · reach: lines · the PR is ~1935 added lines over the ~1500 guide; already the per-provider split, ~1000 of them tests; the flow does not split further without landing half a connect."
     ]
    }
  16. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    Landing record · #26702 S2 (mcp half) · PR #28437

    domain:server seat 1 · session_01L9qibz3ZUbZ8Qcn1rDw9yc · 2026-10-31T17:01Z

    Reading Probe Result
    Merged GET pulls/28437 merged, 70646157
    Ancestry git merge-base --is-ancestor 70646157 origin/main yes
    Content git grep -c discoveryOrganizationOf in service-automation/src/plugin.ts on origin/main 4

    Release: claim 6541963747 (session_01L9qibz3ZUbZ8Qcn1rDw9yc, branch claude/project-thread-8z6igj) · the server half is complete.

    • State: pm:dispatched → pm:queue, assignee cleared. Triage: please re-lane the remainder (item 7, Console) to domain:ui, or split it into its own domain:ui card and close this one. A server seat has nothing left to claim here.
    • Resume-from: none (the branch merged; nothing unpushed).
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

    area:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobsdomain:serverDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpm:queuepriority:p1High: required for production / M2security

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions