Repository navigation
Commit 744211f
feat(spec): ConnectorConnectionState declares redirectUri, the derived OAuth redirect URI (#29618)
<!-- claude-projects-attribution: {"github_login":"os-warren"} -->
_Requested by **Warren** · [project
thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ8NW1CM3VW93waPbnVevLEfG)_
Fixes #29574
Clause-②: yes (widening)
Metadata-protocol: none
## 维护者速读
- 改了什么:`ConnectorConnectionState` 新增一个可选只读键 `redirectUri`,承载本部署推导出的
OAuth 回调地址;只改 spec 契约,不改服务端。
- 为什么改:管理员要先拿这个地址去厂商处注册自己的 OAuth client(#28702 裁决 B),Console 的连接步骤需要在有
client 之前就显示它;此前没有任何回答带它。
- 风险与回滚:纯加宽,一个可选键,已有实现与调用方零改动;回滚即 revert 本 PR。服务端尚未填它(#29463),TSDoc
已写明「声明在先」。
- 先看:`packages/spec/src/contracts/automation-service.ts`(新键及
TSDoc)、`packages/spec/src/contracts/connector-connection-redirect-uri.pin.test.ts`、`.changeset/29574-connector-redirect-uri.md`。
- 两分钟验证:`pnpm --filter @objectstack/spec exec vitest run
src/contracts/connector-connection-redirect-uri.pin.test.ts`,预期 2
passed。
- 需要你做的:批准键名 `redirectUri`(或改选下方 Open questions 里的其它拼法);批准原文须引入本 PR
正文后才能入队。
## What changes
`ConnectorConnectionState` (`@objectstack/spec/contracts`,
`packages/spec/src/contracts/automation-service.ts`) declares one
optional key, `redirectUri?: string`: the absolute URL of `GET
/api/v1/automation/connectors/oauth/callback` that the administrator
registers with the vendor's OAuth client. Its TSDoc states:
- **How it is derived:** by the server, fixed per deployment, never
taken from a request: the automation plugin's
`connectorOAuthRedirectUri` option, else that path under `OS_AUTH_URL`,
else under `OS_BASE_URL` (the chain
`ServiceAutomationPlugin.connectorOAuthRedirectUri()` already
implements).
- **When it is present:** on `getConnectorConnection`'s answer whenever
the server can derive it, whatever `status` says.
- **When it is absent:** when the deployment has no base to derive it
from (a connect is then refused `503`), never guessed from the request's
origin; and for every grant other than `authorization_code`,
structurally, since only an `authorization_code` instance has a
connection (the door refuses any other `400`).
- **Read-only:** no connection request takes it.
- **Declared ahead of the service:** until the automation service sets
it (#29463, `Blocked-by` this card), no answer carries it. #29463's PR
deletes that sentence when it lands.
No server change, no docs change (the card leaves
`content/docs/automation/connectors.mdx` to #29463), no
`api/protocol.zod.ts` / `identity/protocol.ts` / metadata-protocol
`protocol.ts` edit (freeze until 2026-11-03 06:00Z). The interface has
no Zod wire mirror in `packages/spec/src/api/`, so no schema or
generated reference moves.
## Why
#28702 ruling B (6566728470) has each deployment's administrator
register their own OAuth client against this deployment's callback, and
asks the Console's Connect step (#28869) to show that exact URI with a
copy button. The server derives it but answers it nowhere a client can
read before a client exists. Split from #29463 on route ruling
6585200349; triage 6586696710 (p1).
## Open questions
- **The key name (merge gate: the maintainer approves it before the
queue).** Proposed `redirectUri`. Reasoning, by the method the `client`
ruling 6580268872 used (reuse the words the contract layer already uses
for the concept):
- It is the RFC 6749 `redirect_uri` parameter, camelCased per the
config-key rule.
- The code that derives and sends this exact value already spells it
`redirectUri`: the plugin option `connectorOAuthRedirectUri`, and the
request fields of
`services/service-automation/src/oauth2-grant/authorization.ts` and
`mcp-authorization.ts`. The vendor consoles an administrator pastes it
into call it "Redirect URI".
- Not `redirectUrl`: in the spec that word is the action handler-return
navigation convention (`{ redirectUrl, openIn? }`, `ui/action.zod.ts`),
a different concept a reader would conflate.
- Not `callbackUrl`: no precedent in the spec, and it names the route
rather than the OAuth term the vendor asks for.
- Not nested as `client.redirectUri`: `client` is absent until the
installer enters one, which is exactly when the URI is needed.
- Noted: `redirectUri` once named an inline key of the retired
`ConnectorOAuth2Schema` (`connector.authentication`, migration entry
`connector-auth-config-oauth2-retired`). That was an authorable metadata
key; this is a read-only answer field on a service contract, never
authored, so nothing collides with that retirement.
- Options: **A** `redirectUri` (recommended, for the reasons above) ·
**B** `callbackUrl` · **C** `redirectUrl`.
## Tests
- New
`packages/spec/src/contracts/connector-connection-redirect-uri.pin.test.ts`,
compiled by `check:test-typecheck` under `tsconfig.test.json`: the key
is exactly `string | undefined` and optional;
`ConnectorConnectionRequest` has no such key; every prior key of the
state keeps its type; a structured value does not compile
(`@ts-expect-error`); the TSDoc names the callback path, the derivation
chain and both absence conditions.
- Reverse check, run once: with the key mutated to `number`
(`scripts/ablation-replace.mjs`), `check:test-typecheck` went red with
"2 type error(s)" in the pin file; restored blob equals HEAD
(`31cf455e60bc`).
## Acceptance notes
- No `readonly` modifier: "read-only" here means no request carries it
(pinned); the interface's sibling keys carry none either.
- `Metadata-protocol: none`: `ConnectorConnectionState` is a service
answer, not something a metadata author writes. `Clause-②: yes
(widening)`: the published contract gains a key.
## Verification
All readings at head `555302a1f` (this branch merged with `origin/main`
at the time of the run), in `objectstack-ai/objectstack`:
- `pnpm --filter @objectstack/spec build` :: exit 0 (lock VERDICT
command-exit 0).
- `pnpm --filter @objectstack/spec check:generated` :: exit 0, "All 14
generated artifacts are up to date"; nothing regenerated, nothing
committed (the interface has no Zod mirror, and the api-surface row
`ConnectorConnectionState (interface)` names the interface, not its
members).
- `pnpm --filter @objectstack/spec test` :: exit 0, Test Files 802
passed (802), Tests 23700 passed, 1 todo.
- `pnpm --filter @objectstack/spec typecheck` :: exit 0 (includes
`check:test-typecheck`, which compiles the new pin).
- `node scripts/pm/dispatch-gates.mjs --commands`: 79 derived families;
all 79 run, each exit 0; `--ran` reconciliation: "79 derived famil(ies)
accounted for — 79 run, 0 NOT-MEASURED". Prerequisite builds: `turbo run
build --filter=@objectstack/formula --filter=@objectstack/lint
--filter=@objectstack/objectql`, and `git fetch origin 621a487` for the
teardown-shape self-test's pinned control.
- Every family CI runs beyond that local subset (repo-wide lint, Test
Core, Build Core, the type-check lanes): this PR's check-runs.
- Dogfood: not owed (no `!` in the title, no `(narrowing)` arm).
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(A contract interface with no Zod mirror, as its siblings.)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` passes. (Repo-wide lint is CI's.)
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset.
- [x] 6. `packages/spec` touched: its generated artifacts are
regenerated and committed. (`check:generated`: all 14 up to date,
nothing moved.)
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English.
- [x] The *Before Submitting* list in CONTRIBUTING.md is done.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01JQwxbXFQf118bS56KJqpQj)_
## Maintainer approval
Warren approved the key name `redirectUri` (on
`ConnectorConnectionState`, option A; `callbackUrl` and `redirectUrl`
were not taken) on 2026-11-03 at 00:08 UTC. He chose 「全部批准」 on decision
card cmsg_01U5RdnAAmkSQmZbqh6FtqZ8Rr7w8AxYJLZP6jP9v41T4n, whose question
was 「六个命名/措辞全部按推荐批准吗?」, in the project thread "Decide pending spec name
approvals". The post above that card recommended `redirectUri` as
spelled.
<!-- signed: domain:spec#5 · os-warren ·
session_01JQwxbWR3K3h7i1ytwycVg1 -->
Co-authored-by: Claude <noreply@anthropic.com>1 parent e0187d0 commit 744211f
3 files changed
Lines changed: 130 additions & 0 deletions
File tree
- .changeset
- packages/spec/src/contracts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1178 | 1178 | | |
1179 | 1179 | | |
1180 | 1180 | | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
| 1184 | + | |
| 1185 | + | |
| 1186 | + | |
| 1187 | + | |
| 1188 | + | |
| 1189 | + | |
| 1190 | + | |
| 1191 | + | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + | |
| 1195 | + | |
| 1196 | + | |
| 1197 | + | |
| 1198 | + | |
| 1199 | + | |
| 1200 | + | |
1181 | 1201 | | |
1182 | 1202 | | |
1183 | 1203 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
0 commit comments