Skip to content

docs(adr): ADR-0143 accepted — the maintainer's Q1–Q4 decisions recorded; D2.1, D2.3, D3, D4 and D7 state what they settle - #27231

Merged
os-zhuang merged 1 commit into
mainfrom
claude/project-thread-egxrcr
Oct 28, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/project-thread-egxrcr

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread
Part of #26768
Clause-②: no
Metadata-protocol: none
Ruling-ref: #26768 (comment)

维护者速读

What changes

docs/adr/0143-outbound-connector-auth-is-open-tier.md:

  • Status is now Accepted, dated 2026-10-28. Deciders quotes the ruling 「同意」, given to an independent analysis of Q1–Q4.
  • Q1–Q4. Each keeps its options as drafted and gains a **Decision (2026-10-28)** paragraph. Q3 departs from the drafted recommendation, and says so.
    • Q1: A, organization-shared.
    • Q2: B, a dedicated connection object, scoped by D3.
    • Q3: A revised. Notion's hosted MCP server is the live dynamic-registration proof, and HubSpot is the pre-registered-clientId case, live or as a contract test. Then Feishu, an Alipay v3 sandbox query over https, and client_credentials plus a registration contract test against the embedded @better-auth/oauth-provider.
    • Q4: A, with three conditions: alipay-v3 replaces alipay-rsa2; the signer seam carries response verification; the test-vector rule is relaxed.
  • D2.1. On provider: 'mcp', endpoints and clientId may also be supplied, for vendors without dynamic client registration (HubSpot).
  • D2.3. Test vectors reproduce a complete vendor example byte for byte where one is published; otherwise they come from the vendor's official SDK test suite, with SDK and version named. The signer seam gains an optional response-verification step, which alipay-v3 implements.
  • D3. Only what cannot be re-obtained unattended is persisted: the refresh token, the dynamically registered client, and status, scopes and expiry. Access tokens, including every client_credentials and app-credential token, stay in an in-process cache.
  • D4 gains the organization-less run rule. A run with no organization (a schedule) uses the instance's connection only when exactly one exists; otherwise it is refused. It never falls back to an arbitrary connection.
  • D7. ConnectorOAuth2Schema is retired through ADR-0087, not redefined.
  • Acceptance follows Q3 and Q4. That means Notion via dynamic registration with refresh-token rotation, Alipay v3 over https on alipay-v3 with response verification, and the embedded-server contract test.

docs/adr/README.md is regenerated by node scripts/adr-index.mjs: ADR-0143's row, and Accepted 125→126 / Proposed 5→4.

Forced test edits: none.

Tests

Docs-only diff with no package touched, so no build, unit test or typecheck is owed. The derived gate family ran (see Verification).

Acceptance notes

  • Vendor facts behind the Q3 / Q4 decisions (pages fetched 2026-10-28; the ADR cites the first two):
    • HubSpot remote MCP: PKCE required, no dynamic client registration; the client is pre-registered in HubSpot.
    • Notion MCP: RFC 7591 registration, S256 PKCE, refresh token rotated on every refresh.
    • Aliyun ACS3: publishes a complete worked example with its final signature.
    • Tencent TC3: its example masks the SecretKey.
    • Alipay's v3 protocol page is robots-blocked. Its openapi.yaml (alipay-sdk-java-all, v3/api/) declares no securitySchemes, and its sandbox server entry is plain http.
    • New WeChat Pay merchants verify against a fixed platform public key.
  • Code facts, re-read on origin/main at cdec7473.
    • sys-account.object.ts: (provider_id, account_id) is indexed unique: 'global'. The comment beside the token columns says they are deliberately not retyped to Field.secret() and that encryptOAuthTokens is unset.
    • runtime-identity.ts#resolveRunDataContext: a schedule resolves no user and no organization.
    • auth-manager-plugin-list.ts sets allowDynamicClientRegistration.
  • Ruling. Steve's two messages, the 09:39Z request for an independent analysis with a recommendation per question and the 11:22Z reply 「同意」, are recorded verbatim on 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 in ruling record 6467737978. The ADR quotes 「同意」 and describes the request in words.
  • Not in this PR: card item 3, the cloud-repository record with a ## Provenance pointer. It is still owed, and this lane cannot reach that repository.
  • Tier H. This PR is a draft and waits for an approval from a GOVERNED_APPROVERS account. It is not readied, armed or queued from here.

Verification

Derived gate family: 21/21 exit 0, --ran reconciles 21/21, 0 NOT-MEASURED (derived zero)

The gates ran on 97b63d2b. The pushed head 5fada82b is the same tree; only the commit message was reworded, to drop a card trailer that the pre-push check:commit-card-trailers refused.

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack listed 21 commands:

node scripts/check-adr-links.mjs :: exit 0
node scripts/check-adr-links.mjs --self-test :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
pnpm check:adr-anchors :: exit 0
pnpm check:adr-index :: exit 0
pnpm check:adr-symbol-anchors :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-prior-rulings :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:watch-hint-literal :: exit 0

--ran result: "21 derived famil(ies) accounted for — 21 run, 0 NOT-MEASURED (a DERIVED zero — all 21 recorded an exit code and none of them is 3)".


Generated by Claude Code

…ded; D2.1, D2.3, D3, D4 and D7 state what they settle

Q1 organization-shared, with an org-less-run selection rule in D4.
Q2 a dedicated connection object persisting only the refresh token, the
dynamically registered client and grant status; access tokens stay in
process. Q3 revised: Notion's MCP server is the live dynamic-registration
proof (HubSpot has none), HubSpot the pre-registered-clientId case. Q4
`alipay-v3` / ACS3 / TC3, a response-verification step on the signer seam,
and SDK-suite vectors where the vendor publishes no complete example.
D7 retires ConnectorOAuth2Schema.

Claude-Session: https://claude.ai/code/session_01ADHkmP2wqmTYar443bTqhK
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 28, 2026
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation labels Oct 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants