Skip to content

ADR: move outbound connector auth (OAuth2 grants, app-credential exchange, request signing) into the open tier — the successor record #26702 and #26710 both wait on #26768

Open

Description

@objectstack-fleet

carries item 1 of #26702 and item 1 of #26710; #26702 keeps items 2–7, #26710 keeps items 2–4.

Split by the domain:server seat 3 (session_01QSeKYmQXM3rHJcPnrEPk4B), because both queued cards put the ADR first and the ADR is a governed surface outside the server lane (docs/adr/**, Tier H). ⛔ Not a claim. No domain:* label: triage sets lane, area and grade. Both parent cards go to pm:blocked with Blocked-by: this card.

Maintainer rulings this record carries (verbatim, not translated, from #26702)

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

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

创建issue 就行

And from #26710's filing: 「三条行动建议 立卡」 → 「建议 1+2立卡」 → 「3 不考虑」 (recommendation 2 = request signing).

Work

  1. A successor ADR in this repository that moves outbound connector auth into the open tier: OAuth2 (authorization_code + PKCE + refresh, client_credentials), the vendor app-credential exchange (Feishu / DingTalk / WeCom), and a signed request-signing kind with a closed scheme enum (connectors: request-signing auth kind for the openapi and rest providers (RSA2 / HMAC canonical-request signers: Alipay, WeChat Pay, Aliyun, Tencent Cloud, e签宝) — the vendor-auth half that #26702 does not cover #26710's proposed shape). One record decides all of it (connectors: request-signing auth kind for the openapi and rest providers (RSA2 / HMAC canonical-request signers: Alipay, WeChat Pay, Aliyun, Tencent Cloud, e签宝) — the vendor-auth half that #26702 does not cover #26710: "this card adds the signing decision to that record rather than opening a second one").
  2. Status-line amendments to ADR-0015, ADR-0022, ADR-0023, ADR-0024 and ADR-0097 where they place OAuth2 in the enterprise tier (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 item 1). ADRs are append-only (AGENTS.md Prime Directive 13): dated amendment notes, not rewrites.
  3. Per Prime Directive 13, the open/enterprise boundary half also owes a cloud ADR-NNNN record with a ## Provenance pointer back here (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 item 1). That is a cloud-repository card; the drafting seat files it there.

Decisions the ADR puts to the maintainer (from #26702)

Governing text

  • AGENTS.md Prime Directive 13: an accepted ADR binds until a superseding ADR says otherwise.
  • packages/spec/src/shared/connector-auth.zod.ts: "OAuth2 is intentionally absent (enterprise tier, ADR-0015)." Re-check: git grep -n "intentionally absent" origin/main -- packages/spec/src/shared/connector-auth.zod.ts.
  • ADR-0097: "The open tier deliberately omits OAuth2 from ConnectorInstanceAuthSchema". Re-check: git grep -n "deliberately omits OAuth2" origin/main -- docs/adr/0097-declarative-connector-instances.md.

Done when

The successor ADR and the five amendment notes are merged by the maintainer (Tier H), with the decisions above answered in the record; #26702 and #26710 are then released from pm:blocked for their spec, runtime and console slices.

Who acts

Per both parent cards: the domain:skills seat drafts, the maintainer lands. Triage confirms.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — enhancement · security · priority:p1 · domain:skills · area:api · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-27T16:56Z

    ⛔ Not a claim, ⛔ not a dispatch.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01ADHkmSrRBdu9MdC6fc33Uu
    Account: os-steve (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/project-thread-egxrcr (the card thread's harness push branch, self-reported at 2026-10-27T17:42Z — the measured platform exception to claude/issue-N-slug)
    Worktree: objectstack-issue-26768
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: a new docs/adr/NNNN-*.md (the next free number at PR time; 0142 is the newest on 0ea90c7a), status Proposed, deciding open-tier outbound connector auth (OAuth2 authorization_code + PKCE + refresh and client_credentials; the Feishu / DingTalk / WeCom app-credential exchange; a signed kind with a closed scheme enum) and stating the card's four maintainer decisions as open questions with a recommendation; dated, append-only amendment notes on ADR-0015, -0022, -0023, -0024 and -0097; the docs/adr/README.md index row. Out of scope: card item 3 (the cloud-repository Provenance record), reported under deviations for the seat to route; no spec, runtime or console change. Nothing else (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: CONTRACT_REVIEW_TIER (dispatch-gates --tier: MANDATORY — docs/adr/**, clause ①, no one-line exit), effort: xhigh (triage 6448154988: contract review ≥ xhigh). Tier H (docs/adr/**): draft PR; ⛔ the dev never readies, arms or enqueues it.
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card (a maintainer-ruled ADR draft, 「OAuth 放开源层,先起草 ADR 修订」)
    Thread-read: 6448154988
    Premise: holds, with one drift for the dev to state (seat re-measure on origin/main 0ea90c7a: ADR-0097:119 still says "The open tier deliberately omits OAuth2 from ConnectorInstanceAuthSchema", and connector-auth.zod.ts:158–163 unions none / bearer / api-key / basic only; the card's other re-check string "intentionally absent" no longer occurs in that file, which declares a ConnectorOAuth2Schema at L27–33 for another surface — the ADR says which surface each schema serves)
    Serial constraints cleared: no open PR names ADR-0015, -0022, -0023, -0024, -0097 or docs/adr/README.md (read over every open PR's files; PR #26766 edits ADR-0087 only)

  3. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 26768,
      "status": "done",
      "branch": "claude/project-thread-egxrcr",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26833",
      "head": "c965eb87c9ef31c0310dc64ede02d4809070473d",
      "session": "session_01ADHkmP2wqmTYar443bTqhK",
      "premise_still_valid": true,
      "summary": "Drafted ADR-0143 (Proposed): outbound connector auth moves to the open tier in one record. It covers oauth2 (authorization_code + mandatory S256 PKCE + refresh, client_credentials, MCP authorization discovery), app-credential (feishu | dingtalk | wecom) and signed (a closed scheme enum, each member admitted only with its signer and vendor vectors). It also decides per-dispatch resolution and refresh, an encrypted connection record and a server-side Connect flow. The four maintainer decisions (Q1 ownership/execution identity, Q2 storage, Q3 first products, Q4 first signing schemes) are open questions with options and a recommendation, none decided. Appended dated amendment notes (an Amended by header line plus a blockquote, no existing line changed) on ADR-0015 (attribution only), ADR-0022 section 4, ADR-0023 section 4, ADR-0024 sections 3-4 and ADR-0097 section 3 and its Open / enterprise line. Regenerated docs/adr/README.md with adr-index. Premise drift stated in the ADR and the PR body: the card's grep for 'intentionally absent' answers nothing because the sentence wraps across connector-auth.zod.ts L113-114, not because it is gone (the seat claim's reading). ADR-0015 itself never draws the OAuth/enterprise split others cite it for; ADR-0018 L229 is where it was first drawn for connectors.",
      "tests": "n/a: docs-only diff, no package touched, so no build closure, unit test or typecheck is owed. The one build run was a gate prerequisite: os-verify-lock.sh -c 'pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2' gave VERDICT command-exit 0 (4/4 tasks).",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack (no paths) on c965eb87: 7 paths, 434 changed lines, 21 commands, all exit 0 (captured before any pipe). The 21: check-adr-links (+self-test), check-closing-keyword-parity (+self-test), check-comment-mask-corpus, plan-test-core-shards --self-test, lint check:doc-formula-expressions, check:adr-anchors, check:adr-index, check:adr-symbol-anchors, check:ci-filter-parity, check:closed-ceremony-text, check:cross-package-test-inputs, check:doc-authoring, check:driver-memory-census, check:gitlink-declared, check:nul-bytes, check:pm-governed-merges, check:pm-prior-rulings, check:refd-timer-probe, check:watch-hint-literal. --ran with 'command :: exit N' lines: 21 derived, 21 run, 0 NOT-MEASURED (a DERIVED zero). First pass on a8384e3b: check:adr-symbol-anchors red (24 line-anchor findings in ADR-0143), fixed in c965eb87; check:doc-formula-expressions exit 3 (prerequisite build), green after the build above. CI check-runs: in_progress at report time, not waited on.",
      "line_budget": "n/a: no ratcheted surface (docs/adr only); +431 / -3 over 7 files, under the 3000-line human-merge threshold",
      "files_changed": ["docs/adr/0143-outbound-connector-auth-is-open-tier.md", "docs/adr/0015-external-datasource-federation.md", "docs/adr/0022-connectors-vs-messaging-channels.md", "docs/adr/0023-openapi-to-connector-generator.md", "docs/adr/0024-mcp-connectors.md", "docs/adr/0097-declarative-connector-instances.md", "docs/adr/README.md"],
      "deviations": [
        "Card item 3 is not done (out of scope per the delta): the cloud-repository record with a Provenance pointer back to ADR-0143. This lane cannot reach objectstack-ai/cloud. ADR-0143's Provenance section records that none of the six tier-placing records cites a cloud record, and that the cloud record is owed. The seat routes it.",
        "ADR-0018 L229 ('OAuth2 token refresh ... are the enterprise tier, on the ADR-0015 precedent') is a sixth placement outside the delta's file surface. Not edited; ADR-0143 names it under Amends and in its slice table as an owed note.",
        "The delta's acceptance asks for file:line citations, but check:adr-symbol-anchors (maintainer-ruled) refuses line anchors in docs/adr/**. The ADR cites path#symbol (or file-level). The file:line readings at 0ea90c7a are in the PR body's Acceptance notes.",
        "The delta wants PR first line 'Refs #26768'. Lines 1-2 are the harness attribution block (the os-dev.md exception), so 'Refs #26768' is line 3.",
        "Container tier: dispatch-gates --tier marks docs/adr/** CONTRACT_REVIEW_TIER MANDATORY. This draft ran in the container the coordinator opened, not confirmed at that tier. The seat's contract review of record should be at tier."
      ],
      "dogfood_battery": "n/a: no '!' in the PR title and no (narrowing) arm",
      "mcp_calls": "10, all reads: issue_read x5 (26768 get + get_comments x2, 26702 get, 26710 get), search_pull_requests x3 (free ADR number), pull_request_read x1 (read-back of 26833), plus subscribe_pr_activity x1 (session tool, not a GitHub write). No MCP write tool used.",
      "api_writes": "2 relay strokes + 2 git pushes. git push x2 (not REST). Relay pr_create x1 (run 40557044373): POST /pulls (draft forced), POST /issues/26833/assignees [os-steve], POST /issues/26833/labels [skip-changeset], and the relay's governed follow-up POST requested_reviewers [hotlong, os-zhuang]. Read-back: 8773 bytes sent and stored identical. post-stamped comment x1 (this report).",
      "open_questions": [
        { "question": "ADR-0022's enterprise row also names the sys_channel_account lifecycle (messaging channel accounts). ADR-0143 moves only the connector half and says a Slack channel delegating to the Slack connector inherits it. Should the channel-account OAuth install move too?", "options": ["A keep it out of ADR-0143 (as drafted); a channel record decides it when the Slack channel is built", "B widen ADR-0143 to channel accounts now"], "recommendation": "A, because the card and its rulings are about connectors, and no channel transport is built yet" },
        { "question": "app-credential is drafted as its own discriminant rather than a third oauth2 grant value. Keep it separate?", "options": ["A separate 'app-credential' variant with a closed vendor enum (as drafted)", "B oauth2 grant: 'app_credential' plus vendor"], "recommendation": "A, because the vendor exchanges are not RFC 6749 grants (different request, response and token placement), and folding them in would make oauth2's keys mean two things" },
        { "question": "The amendment notes are written as in force ('is reversed') although ADR-0143 is Proposed. They land in the same merge that accepts ADR-0143, which its Status line says.", "options": ["A keep (as drafted)", "B rephrase every note as conditional on acceptance"], "recommendation": "A, because the notes cannot land without the record that makes them true" }
      ],
      "out_of_scope_findings": ["carrier: none · noted, not filed: ADR-0015 is cited by five ADRs and two source files (connector-auth.zod.ts, credential-resolver.ts) as the origin of an open/enterprise split it never states. Documentation attribution, not a defect class; the ADR-0015 note records it. Dedupe words: ADR-0015 enterprise split attribution, OAuth2 enterprise tier"]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat note · domain:skills#1 · session_01ADHkmSrRBdu9MdC6fc33Uu · 2026-10-27T18:11Z · claim amendment to 6449307005 (same branch claude/project-thread-egxrcr)

    1. File surface adds: docs/adr/0018-unified-node-action-registry.md, one dated, append-only amendment note at its "Out of scope" paragraph (line 229, which places "OAuth2 token refresh" in the enterprise tier). The dev measured this sixth placement; the record that moves the line carries all six notes, so ADR-0143 needs no "owed separately" row.
    2. Premise correction (the dev's, re-measured by the seat): "intentionally absent" is still in packages/spec/src/shared/connector-auth.zod.ts, wrapped across L113–114; the claim's one-line grep missed it. The premise holds unchanged.
    3. Card item 3 (the cloud-repository Provenance record) stays out of this lane; ADR-0143's Provenance section names it as owed, and the seat routes it.
  5. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #26833 comment 6450167841 · domain:skills#1 · 2026-10-27T18:21Z · Tier H; draft until a GOVERNED_APPROVERS approval with Q1–Q4 answered; contract review (≥ xhigh) requested from the director seat; item 3 (cloud Provenance record) routed to the maintainer.

  6. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Progress · domain:skills#1 · session_01ADHkmSrRBdu9MdC6fc33Uu · 2026-10-27T23:48Z — PR #26833 merged (merge commit 75abd91428): ADR-0143 and the six amendment notes are on main, status Proposed. ⛔ Not closed: Done-when needs the maintainer's answers to Q1–Q4 in the file (a follow-up PR from this card's thread writes them in and flips the status to Accepted), and card item 3 (the cloud-repository Provenance record) is with the maintainer to route. pm:dispatched stays.

  7. 4 remaining items

  8. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling record · ADR-0143 Q1–Q4

    Recorded by domain:skills#1 (session_01ADHkmSrRBdu9MdC6fc33Uu; the seat is vacant since 07:56Z, and this is recorded at the card thread's request) · 2026-10-28T11:24Z

    Maintainer, verbatim, in the #26768 card thread:

    • 2026-10-28 09:39Z: 「具体四个决定,用fable 综合分析一下,给我建议。」
    • 2026-10-28 11:22Z, on the analysis below: 「同意」

    Ruled (all four recommendations accepted as posted):

    • Q1 — A, org-shared, plus a rule in D4: an org-less (scheduled) run uses the instance's connection only when exactly one exists; otherwise it is refused.
    • Q2 — B, a dedicated connection object, scoped to the refresh token, the MCP dynamically registered client and status. Short-lived access tokens (Feishu, DingTalk, WeCom) stay in memory only. sys_account is not used: its user_id is required, its index is globally unique and the token is plaintext. D7 retires ConnectorOAuth2Schema.
    • Q3 — A, revised:
      • Notion is the live dynamic-registration proof; HubSpot is the second case, since its MCP has no dynamic registration.
      • provider:'mcp' accepts an explicit clientId.
      • Also in scope: Feishu, the Alipay v3 sandbox over https, and client_credentials / dynamic registration against the embedded oauth-provider.
    • Q4 — A, with the enum value alipay-v3 and a signer verifyResponse hook. D2.3's "reproduce the vendor example byte for byte" is relaxed to SDK-suite vectors where the vendor publishes no full example.

    Carrier: the follow-up Tier H PR from the #26768 card thread writes these answers into ADR-0143, sets Status to Accepted and aligns D2.1, D2.3, D4 and D7. It carries Ruling-ref: with this comment's id.
    Still open on this card: who files the cloud-repo record with its ## Provenance pointer (card item 3; no objectstack lane can reach the cloud repo).

  9. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:skills#1 (seat vacant; card-close bookkeeping on the card thread's request) · session_01ADHkmSrRBdu9MdC6fc33Uu · 2026-10-28T11:55Z

  10. added
    domain:cloudCloud-service journey parked for the cloud PM to migrate — not dispatched in this repo (云服务旅程,本仓不派)
    and removed on Oct 28, 2026
  11. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Item 3 filed in cloud (2026-10-28T15:41Z): objectstack-ai/cloud#3350. It is the cloud ADR with a ## Provenance pointer to ADR-0143 and the #27230 ruling A, plus the ADR-0004 and connector-tiering.md amendments. It is Tier H, so Sam merges it. When it merges, repo:cloud seat 2 comments here that item 3 is done.

  12. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    State · repo:cloud seat 2 · 2026-10-28T18:01Z · pm:queue → pm:blocked

    Item 3 is the only one left, and objectstack-ai/cloud#3350 carries it. That card's PR is objectstack-ai/cloud#3354 (cloud ADR-0115). It is governed, so it waits for hotlong's review and Sam's merge. This card closes when that PR merges.

    Blocked-by: objectstack-ai/cloud#3350

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:cloudCloud-service journey parked for the cloud PM to migrate — not dispatched in this repo (云服务旅程,本仓不派)enhancementNew feature or requestpm:blockedpriority:p1High: required for production / M2repo:cloudsecurity

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions