You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
automation: a sys_connector_connection stores and uses the installer-supplied OAuth client for an authorization_code instance (#28702 B, server slice) #28866
Filing gate: ④ execution of a maintainer ruling, slice 2 of 3 (server). Ruling-ref: 6566728470 (#28702, letter B). Child of #27293 (E4). Handed to the server lane per 「按你的方案交给车道」. ⛔ Not a claim.
Ruling-ref: 6566728470
Work (this slice, after the spec slice #28864 lands)
packages/services/service-automation/src/oauth2-grant/grant-handle.ts (declaredClient at ~:135-137 builds the client from the packaged clientId today) and connector-connections.ts / sys-connector-connection.object.ts. When the instance declares an installer-supplied client, the connect door POST /api/v1/automation/connectors/:name/connection takes the client id from the administrator. The secret goes in the credential store, never in metadata. The client is kept on the connection record, the way MCP dynamic registration keeps registered_client (sys-connector-connection.object.ts:87). Authorize, token exchange and refresh then use it.
Refusals: a connect without a client on an instance that requires one is refused, naming the instance and the vendor's registration step. A tenant-visible message never carries a host path or the secret.
Tests: connect with an installer client, then refresh, then revoke; a control with a packaged client, if the spec slice keeps that form; a dogfood case over the real doors.
Reader
The server lane takes it from pm:queue once #28864 closes. The ui slice reads its door shape.
Unblocked · 2026-11-02T06:49Z. The spec slice #28864 landed as PR #28920, merge d8c611d9ef. clientSource: 'installer' is declared on the oauth2authorization_code instance, together with the ADR-0143 D2.1 amendment.
This card's surface, and what must flip with it, is in the landing note on #28864. In short: drop the [PLANNED — not enforced] describe marker and the connector/auth liveness sentence, and flip the PLANNED pin test, all in the PR that makes the service read the key. The Skills-docs follow-up (connectors.mdx, integration-recipes.md) rides with this card.
Claim: PM loop round 4 · card thread · 2026-11-02T06:56Z
Session: session_0186vfjHHMsRXC9EUT9hTFMo (the seat); the card thread is session_01FEkQ5p21mBsw5qoeMKcPA2
Account: os-project-manager (the seat's linked user; the card's assignee)
Branch: claude/project-thread-yrazza (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#2
Ruling-ref: the maintainer, 2026-11-01T03:46Z: 「server 车道现在就是你负责,任务有一大堆啊,都可以派,包括 p3」, with 2026-10-26T10:29Z 「p1 p2 处理完了,就可以处理 p3」. Executes the maintainer's ruling B (6566728470, 「同意」 2026-11-02T01:12Z): an installer-supplied OAuth client, kept per connection. The spec slice #28864 landed as PR #28920. With 2026-11-02T05:15Z 「队列进了很多任务,抓紧派发」; seat 1 confirmed seat 2 takes this card. Seat's route: follow the landed spec, nothing new in spec. The connect door takes the administrator's client for a clientSource: 'installer' instance. The secret goes only into the credential store. Authorize, exchange, refresh and revoke all use it, and a packaged-client instance is unchanged.
File surface: packages/services/service-automation/src/oauth2-grant/, connector-connections.ts, sys-connector-connection.object.ts; their tests; one dogfood case; changeset
Container & model: M, mode:thread, model: opus (--tier names no path mandate: PM's call, default), effort: medium
Clause-②: yes expected (the connect door accepts a new body shape; a narrowing beside it if a client on a packaged instance is newly refused); the dev measures and declares; CONTRACT_REVIEW_TIER review
Metadata-protocol: none (expected; the dev measures and declares)
Responsibility: the dev wires the installer client through connect and every token call, with the secret only in the credential store, red first with ablation; the seat reviews and lands
Thread-read: none
Premise: card filed by the epic seat under ruling B; blocker #28864 closed completed
Serial constraints cleared: #28864 landed (PR #28920, d8c611d); overlap re-read of open PRs on service-automation oauth2-grant and connector-connections before pr_create
Resume-from: none — fresh from origin/main
State: → pm:dispatched, assigned to os-project-manager, recorded by this claim.
Release: session_0186vfjHHMsRXC9EUT9hTFMo · cause: the maintainer's wrap-up (「进展中的开发先提交代码然后暂停,先确保已有的pr都合并」, 「草稿的也交给下一任,在座位帖写清楚」); seat 2 signs off · next: Draft PR #29097, implementation complete, verification partial (paused): red-first and ablation, full package suites, derived gates, full dogfood and the os-dev-report are owed. Then a CONTRACT_REVIEW_TIER review (spec contract members ConnectorConnectionRequest.client / ConnectorConnectionState.client, seat ruling B in the thread). Re-claim on the same branch.
Resume-from: claude/project-thread-yrazza@d42235fb45093791066fb1f28649e29d4b935884
State: pm:dispatched → pm:queue, assignee cleared, in this same relay stroke. Seat hand-off: mailbox #28284 comment 6571506250; seat post #20966.
Claim: PM loop round 1 · seat takeover · 2026-11-02T08:15Z
Session: session_01ADHkmQxwoGb5fSnrFkpxmt (the seat)
Account: os-steve (the seat's linked user; the card's assignee)
Branch: claude/project-thread-yrazza (continued from the released claim; PR #29097)
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#2
Ruling-ref: the maintainer, verbatim: 「开 server 2、3、5 号席位, 前任已经下班,接手所有开发,包括跟进之前未完成的开发落地。」 (os-steve project "objectstack spec"). Takes over the hand-back Release: 6571761848 of seat 2's previous term (session_0186vfjHHMsRXC9EUT9hTFMo).
File surface: packages/services/service-automation/src/oauth2-grant/, connector-connections.ts, sys-connector-connection.object.ts; their tests; one dogfood case; changeset (unchanged from claim 6571085790)
Container & model: M, mode:thread, model: opus (as the previous claim), effort: high
Clause-②: yes (expected; the connect door accepts a new body shape) — the dev measures and declares; CONTRACT_REVIEW_TIER review owed
Metadata-protocol: none (expected; the dev measures and declares)
Responsibility: the dev wires the installer client through connect and every token call, with the secret only in the credential store (claim 6571085790; seat ruling B carried). Owed: red-first and ablation, full package suites, derived gates, full dogfood, the os-dev-report, the Skills-docs follow-up
Thread-read: 6571761848
Premise: holds (measured by the previous term's dev; re-read on the PR head before ACCEPT)
Serial constraints cleared: none new; the PR's file list is re-read against live claims before landing
Resume-from: claude/project-thread-yrazza@d42235fb45093791066fb1f28649e29d4b935884
Status: draft PR #29097, partial; a new card thread resumes it on the same branch from the sha above.
State: pm:queue → pm:dispatched, assigned to os-steve, recorded by this claim.
{
"issue": 28866,
"status": "done",
"branch": "claude/project-thread-yrazza",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29097",
"session": "session_01ADHkmSB1MQ9Npyv1kGL3DV",
"premise_still_valid": true,
"summary": "Resumed draft PR #29097 at d42235fb, merged origin/main (a0442de6, one import conflict in grant-handle.test.ts resolved keeping both sides), and finished the owed verification. Added the ADR-0087 disposition `not-required (no-migration-prescription)` and a BREAKING paragraph naming the three newly refused call shapes. Wrote the claim's dogfood case, whose first run found a real defect in the previous implementation: the HTTP mount for /automation/connectors/:name/connection dispatched every verb with no body, so over HTTP an installer instance could never be connected; dispatcher-plugin.ts now defers the POST body to the domain (59630d94). Also taught the installer form in content/docs/automation/connectors.mdx.",
"tests": "Red first: implementation files at origin/main fea2dbb7 blobs, tests at HEAD -> service-automation 13 failed | 47 passed (60), runtime 2 failed | 33 passed (35), spec 1 failed | 29 passed (30); restore blob == HEAD, git diff HEAD empty. Ablations via ablation-replace.mjs, each red then restored blob == HEAD: A1 installer begin with no client proceeds (1 failed/30), A2 client on non-installer ignored (1 failed/30), A3 unknown begin body keys pass, runtime (1 failed/35), A4 client on read/revoke accepted (1 failed/30), A5 kept client of other kind used, grant handle (1 failed/30), A6 changed declaration at callback unchecked (1 failed/30). Dogfood through dist (rebuild + ablation-dist-preflight present, restore rebuild + --absent, tree clean): D1 mount drops body -> 2 failed | 2 passed (4); D2 = A1 -> 1 failed | 3 passed (4). New dogfood case on a12d046d before the mount fix: 2 failed | 2 passed; on 59630d94: 4 passed (4). Suites: service-automation 257 files / 3323 tests passed (52e23967); runtime 514 files / 8322 passed, 19 skipped (59630d94); spec 790 files / 23357 passed, 1 todo (52e23967; spec source unchanged since); typecheck incl. check:test-typecheck VERDICT 0 for all three on those heads; dogfood typecheck VERDICT 0 (59630d94); spec check:generated VERDICT 0.",
"gates": "Local, 59630d94: dispatch-gates --commands 109 families, all exit 0 (check-plugin-teardown-shape --self-test, check:skill-examples, check:dual-build-cjs-loads, check:type-check-debt first exit 3 PREREQUISITE NOT MET, re-run exit 0 after git fetch --unshallow and the missing builds); --ran with exit codes: 109 derived, 109 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. check-adr-0087-registration --base origin/main exit 0. eslint --no-inline-config on touched sources exit 0. CI check-runs on 59630d94: Lint & Repo Gates success, TypeScript Type Check success, Test Core success, Build Core success, Governed Surface Queue Guard success, Type Check UI success, Test UI success, Build & E2E UI success, Live E2E UI success, Lint UI skipped (selector), Check Changeset success, Dogfood Regression Gate success, no failure. The a0442de6 TypeScript Type Check red was three lanes `cancelled` by the next push, not a type error.",
"dogfood_battery": "59630d94 · os-verify-lock: VERDICT command-exit 0 · Test Files 387 passed | 3 skipped (390) · Tests 3199 passed | 28 skipped (3227) · no failure",
"mcp_calls": "0",
"api_writes": "1 — POST issues/28866/comments (this os-dev-report, via post-stamped.mjs through the fleet relay). git push x5 to claude/project-thread-yrazza (not REST).",
"files_changed": [
".changeset/28866-installer-oauth-client.md",
"content/docs/automation/connectors.mdx",
"content/docs/references/integration/connector.mdx",
"packages/qa/dogfood/test/connector-installer-oauth-client.dogfood.test.ts",
"packages/runtime/src/dispatcher-plugin.ts",
"packages/runtime/src/domains/automation-connector-connection-door.test.ts",
"packages/runtime/src/domains/automation.ts",
"packages/services/service-automation/src/connector-connection-door.test.ts",
"packages/services/service-automation/src/connector-connections.ts",
"packages/services/service-automation/src/oauth2-grant/authorization.ts",
"packages/services/service-automation/src/oauth2-grant/grant-handle.test.ts",
"packages/services/service-automation/src/oauth2-grant/grant-handle.ts",
"packages/services/service-automation/src/oauth2-grant/index.ts",
"packages/services/service-automation/src/oauth2-grant/installer-client.ts",
"packages/services/service-automation/src/plugin.ts",
"packages/services/service-automation/src/sys-connector-connection.object.ts",
"packages/spec/liveness/connector.json",
"packages/spec/src/contracts/automation-service.ts",
"packages/spec/src/integration/connector-auth-grant-kinds.test.ts",
"packages/spec/src/shared/connector-auth.zod.ts"
],
"line_budget": "20 files, +1055 / -70 = 1125 changed lines vs merge base fea2dbb7 (under the 3000 human-merge threshold); this round added +200 (dogfood case 189, mount fix 6, docs 16, changeset 4, net of merge).",
"deviations": [
"PR body not written by me: os-dev.md forbids a dev PATCH of the PR body after pr_create, and the standard order (which os-dev.md binds over) names issue_patch. The refreshed body is ready verbatim at /mnt/project-files/server-seat2/29097-pr-body-r2.md (attribution, Fixes, Clause-② / Metadata-protocol / Skills-docs / Ruling-ref lines, 维护者速读, What changes, Tests with forced edits named, Acceptance notes, Verification on 59630d94); the seat writes it.",
"File surface beyond the claim's: packages/runtime/src/dispatcher-plugin.ts (the mount fix, same defect class as the card: the installer client must reach the door) and content/docs/automation/connectors.mdx (the Skills-docs half the spec lane's landing note says rides with this card). packages/runtime and packages/spec were already in the resumed diff.",
"service-automation and spec suites were read on 52e23967; the two later commits touch only docs, the dogfood test and runtime's dispatcher-plugin.ts, whose own suites were re-run on 59630d94.",
"Did not merge origin/main again after the PR was open: no conflict, no main-caused red (AGENTS.md §10); main is ahead with service-automation runas changes that do not touch these files."
],
"open_questions": [
{ "question": "New public key names — maintainer approval needed before landing: `client` on ConnectorConnectionRequest and ConnectorConnectionState, with members `clientId`, `clientSecret` (request), `source`, `clientId`, `hasSecret` (state), and the connect body keys `clientId` / `clientSecret`.", "options": ["A approve as named (they mirror the OAuth client vocabulary and the spec's clientId)", "B rename before landing"], "recommendation": "A, because the names match RFC 6749 client_id/client_secret in camelCase and the existing clientId key on the auth shape." },
{ "question": "The Console's Setup → Integrations → Connector Connections begins a connect with no body, so it cannot connect a clientSource: 'installer' instance (it now shows the 400 naming the registration step). File a ui-lane card for a client id / secret form?", "options": ["A file a ui card (the server half and API are complete)", "B leave API-only until asked"], "recommendation": "A, because the Console is the documented way to connect and the feature is otherwise API-only." }
],
"out_of_scope_findings": [
"class: none (feature gap, not a defect) · reach: Console Setup → Integrations → Connector Connections, Connect on a clientSource installer instance answers 400 · evidence: the Console begin sends no body; the server refuses an installer begin without a client by design · dedupe words: connector connection console installer client form · carrier: seat 2 (ui lane card) · noted in the PR's Acceptance notes, not filed",
"Skills-docs follow-up owed: skills/objectstack-automation/references/integration-recipes.md (governed Tier H) · carrier: seat 2 files the card"
]
}
The card thread's report 6574284916 names two files outside the claim's surface on PR #29097. The seat accepts both:
packages/runtime/src/dispatcher-plugin.ts: the connect door's HTTP mount passed undefined as the body for all three verbs, so an installer client sent over HTTP never reached the door. The new dogfood case found it on its first run. The fix is POST through deferRequestBody; it is the same defect's last hop, so it rides this PR.
packages/runtime/src/domains/automation.ts (the connect door's closed body set) and content/docs/automation/connectors.mdx (teaches clientSource: 'installer' and the connect body) are the door and its product page.
{
"issue": 28866,
"status": "done",
"round": "contract review should-fix 1 (review record 6574689504)",
"branch": "claude/project-thread-yrazza",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29097",
"session": "session_01ADHkmSB1MQ9Npyv1kGL3DV",
"premise_still_valid": true,
"head": "2ca22f19045a28236809170971ef6968ad5f1a23",
"summary": "packages/runtime/src/route-ledger.ts: the POST /automation/connectors/:name/connection row no longer says 'No body'. It names the closed body set { clientId, clientSecret? }, says no body or {} begins with no client, and lists the three 400 VALIDATION_ERROR refusals. The GET row names the client the read answers, never its secret. Note text only; no code path changed. PR body r3 is at /mnt/project-files/server-seat2/29097-pr-body-r3.md.",
"tests": "2ca22f19: the 13 runtime test files that read the route ledger (route-ledger.conformance, http-dispatcher, automation-api-contract-mounts and 10 more): Test Files 13 passed (13), Tests 423 passed (423), os-verify-lock VERDICT command-exit 0. No ablation: a ledger note is documentation, not tested behaviour.",
"gates": "2ca22f19: dispatch-gates --commands derives 110 families (one new: pnpm check:route-ledger-census). The 37 that read route-ledger.ts, the new one included, re-run on this head: all exit 0. The other 73 do not read the changed file and carry their exit-0 readings from 59630d94. --ran with exit codes: 110 derived, 110 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. CI on 2ca22f19: not yet concluded when this was written.",
"dogfood_battery": "59630d94 (round 1) · VERDICT command-exit 0 · Test Files 387 passed | 3 skipped (390) · Tests 3199 passed | 28 skipped (3227). Not re-run: 2ca22f19 changes only two string literals in the route ledger.",
"mcp_calls": "0",
"api_writes": "1 — POST issues/28866/comments (this report). git push x1.",
"files_changed": ["packages/runtime/src/route-ledger.ts"],
"line_budget": "this round +2 / -2 in one file; PR total 21 files.",
"deviations": ["Dogfood battery not re-run on 2ca22f19 (note-text-only change); the round-1 reading on 59630d94 stands."],
"open_questions": [],
"out_of_scope_findings": []
}
A — the public key names land as filed. Connect request body client { clientId, clientSecret }; connection state client { source, clientId, hasSecret }; the secret is never read back. clientId / clientSecret are the words connector-auth.zod.ts already uses for an OAuth client, hasSecret follows the spec's has* boolean family (hasMore, hasSeedData, hasBreakingChanges), and source: 'installer' carries the definition's clientSource value.
Noted, not a change: client.source on the state and clientSource on the definition are two spellings of one concept; nested under client the state's reads coherently.
Ruling 6580268872: letter A, the maintainer's 「同意」 at 2026-11-02T14:54Z. The names land as filed, with zero rework. The seat ACCEPTs PR #29097 and enqueues it in this act, and lands it.
State: needs-user-decision → pm:dispatched, assigned to os-steve, recorded by this comment (the ruling's exit stroke).
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p2 ·
domain:server· 2026-11-02T02:57Z⛔ Not a claim.
clientIdis fixed by the package and the redirect URI is per deployment #28702 ruling: the server stores and uses the installer-supplied client. It is the runtime of spec: anoauth2authorization_codeinstance takes its OAuth client from the installer (a per-connection client record), not a packagedclientId— ADR-0143 D2.1 amendment (#28702 B) #28864's protocol addition, not a protocol addition itself, so p2.Blocked-by: #28864stands.Generated by Claude Code
fix(spec): mark `clientSource` as declared, not yet served, until the…
objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Unblocked · 2026-11-02T06:49Z. The spec slice #28864 landed as PR #28920, merge
d8c611d9ef.clientSource: 'installer'is declared on theoauth2authorization_codeinstance, together with the ADR-0143 D2.1 amendment.This card's surface, and what must flip with it, is in the landing note on #28864. In short: drop the
[PLANNED — not enforced]describe marker and theconnector/authliveness sentence, and flip the PLANNED pin test, all in the PR that makes the service read the key. The Skills-docs follow-up (connectors.mdx,integration-recipes.md) rides with this card.objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo
Claim: PM loop round 4 · card thread · 2026-11-02T06:56Z
Session:
session_0186vfjHHMsRXC9EUT9hTFMo(the seat); the card thread issession_01FEkQ5p21mBsw5qoeMKcPA2Account:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-yrazza(the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#2Ruling-ref: the maintainer, 2026-11-01T03:46Z: 「server 车道现在就是你负责,任务有一大堆啊,都可以派,包括 p3」, with 2026-10-26T10:29Z 「p1 p2 处理完了,就可以处理 p3」. Executes the maintainer's ruling B (6566728470, 「同意」 2026-11-02T01:12Z): an installer-supplied OAuth client, kept per connection. The spec slice #28864 landed as PR #28920. With 2026-11-02T05:15Z 「队列进了很多任务,抓紧派发」; seat 1 confirmed seat 2 takes this card. Seat's route: follow the landed spec, nothing new in spec. The connect door takes the administrator's client for a
clientSource: 'installer'instance. The secret goes only into the credential store. Authorize, exchange, refresh and revoke all use it, and a packaged-client instance is unchanged.File surface:
packages/services/service-automation/src/oauth2-grant/,connector-connections.ts,sys-connector-connection.object.ts; their tests; one dogfood case; changesetContainer & model:
M,mode:thread,model: opus(--tiernames no path mandate: PM's call, default),effort: mediumClause-②: yes expected (the connect door accepts a new body shape; a narrowing beside it if a client on a packaged instance is newly refused); the dev measures and declares; CONTRACT_REVIEW_TIER review
Metadata-protocol: none (expected; the dev measures and declares)
Responsibility: the dev wires the installer client through connect and every token call, with the secret only in the credential store, red first with ablation; the seat reviews and lands
Thread-read: none
Premise: card filed by the epic seat under ruling B; blocker #28864 closed completed
Serial constraints cleared: #28864 landed (PR #28920, d8c611d); overlap re-read of open PRs on service-automation oauth2-grant and connector-connections before pr_create
Resume-from: none — fresh from
origin/mainState: →
pm:dispatched, assigned toos-project-manager, recorded by this claim.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo
Release:
session_0186vfjHHMsRXC9EUT9hTFMo· cause: the maintainer's wrap-up (「进展中的开发先提交代码然后暂停,先确保已有的pr都合并」, 「草稿的也交给下一任,在座位帖写清楚」); seat 2 signs off · next: Draft PR #29097, implementation complete, verification partial (paused): red-first and ablation, full package suites, derived gates, full dogfood and the os-dev-report are owed. Then a CONTRACT_REVIEW_TIER review (spec contract membersConnectorConnectionRequest.client/ConnectorConnectionState.client, seat ruling B in the thread). Re-claim on the same branch.Resume-from:
claude/project-thread-yrazza@d42235fb45093791066fb1f28649e29d4b935884State:
pm:dispatched→pm:queue, assignee cleared, in this same relay stroke. Seat hand-off: mailbox #28284 comment 6571506250; seat post #20966.Generated by Claude Code
6 remaining items
objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt
Claim: PM loop round 1 · seat takeover · 2026-11-02T08:15Z
Session:
session_01ADHkmQxwoGb5fSnrFkpxmt(the seat)Account:
os-steve(the seat's linked user; the card's assignee)Branch:
claude/project-thread-yrazza(continued from the released claim; PR #29097)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#2Ruling-ref: the maintainer, verbatim: 「开 server 2、3、5 号席位, 前任已经下班,接手所有开发,包括跟进之前未完成的开发落地。」 (os-steve project "objectstack spec"). Takes over the hand-back
Release:6571761848 of seat 2's previous term (session_0186vfjHHMsRXC9EUT9hTFMo).File surface:
packages/services/service-automation/src/oauth2-grant/,connector-connections.ts,sys-connector-connection.object.ts; their tests; one dogfood case; changeset (unchanged from claim 6571085790)Container & model:
M,mode:thread,model: opus(as the previous claim),effort: highClause-②: yes (expected; the connect door accepts a new body shape) — the dev measures and declares; CONTRACT_REVIEW_TIER review owed
Metadata-protocol: none (expected; the dev measures and declares)
Responsibility: the dev wires the installer client through connect and every token call, with the secret only in the credential store (claim 6571085790; seat ruling B carried). Owed: red-first and ablation, full package suites, derived gates, full dogfood, the os-dev-report, the Skills-docs follow-up
Thread-read: 6571761848
Premise: holds (measured by the previous term's dev; re-read on the PR head before ACCEPT)
Serial constraints cleared: none new; the PR's file list is re-read against live claims before landing
Resume-from:
claude/project-thread-yrazza@d42235fb45093791066fb1f28649e29d4b935884Status: draft PR #29097, partial; a new card thread resumes it on the same branch from the sha above.
State:
pm:queue→pm:dispatched, assigned toos-steve, recorded by this claim.objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-steve · session_01ADHkmSB1MQ9Npyv1kGL3DV
os-dev-report
{ "issue": 28866, "status": "done", "branch": "claude/project-thread-yrazza", "pr": "https://github.com/objectstack-ai/objectstack/pull/29097", "session": "session_01ADHkmSB1MQ9Npyv1kGL3DV", "premise_still_valid": true, "summary": "Resumed draft PR #29097 at d42235fb, merged origin/main (a0442de6, one import conflict in grant-handle.test.ts resolved keeping both sides), and finished the owed verification. Added the ADR-0087 disposition `not-required (no-migration-prescription)` and a BREAKING paragraph naming the three newly refused call shapes. Wrote the claim's dogfood case, whose first run found a real defect in the previous implementation: the HTTP mount for /automation/connectors/:name/connection dispatched every verb with no body, so over HTTP an installer instance could never be connected; dispatcher-plugin.ts now defers the POST body to the domain (59630d94). Also taught the installer form in content/docs/automation/connectors.mdx.", "tests": "Red first: implementation files at origin/main fea2dbb7 blobs, tests at HEAD -> service-automation 13 failed | 47 passed (60), runtime 2 failed | 33 passed (35), spec 1 failed | 29 passed (30); restore blob == HEAD, git diff HEAD empty. Ablations via ablation-replace.mjs, each red then restored blob == HEAD: A1 installer begin with no client proceeds (1 failed/30), A2 client on non-installer ignored (1 failed/30), A3 unknown begin body keys pass, runtime (1 failed/35), A4 client on read/revoke accepted (1 failed/30), A5 kept client of other kind used, grant handle (1 failed/30), A6 changed declaration at callback unchecked (1 failed/30). Dogfood through dist (rebuild + ablation-dist-preflight present, restore rebuild + --absent, tree clean): D1 mount drops body -> 2 failed | 2 passed (4); D2 = A1 -> 1 failed | 3 passed (4). New dogfood case on a12d046d before the mount fix: 2 failed | 2 passed; on 59630d94: 4 passed (4). Suites: service-automation 257 files / 3323 tests passed (52e23967); runtime 514 files / 8322 passed, 19 skipped (59630d94); spec 790 files / 23357 passed, 1 todo (52e23967; spec source unchanged since); typecheck incl. check:test-typecheck VERDICT 0 for all three on those heads; dogfood typecheck VERDICT 0 (59630d94); spec check:generated VERDICT 0.", "gates": "Local, 59630d94: dispatch-gates --commands 109 families, all exit 0 (check-plugin-teardown-shape --self-test, check:skill-examples, check:dual-build-cjs-loads, check:type-check-debt first exit 3 PREREQUISITE NOT MET, re-run exit 0 after git fetch --unshallow and the missing builds); --ran with exit codes: 109 derived, 109 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. check-adr-0087-registration --base origin/main exit 0. eslint --no-inline-config on touched sources exit 0. CI check-runs on 59630d94: Lint & Repo Gates success, TypeScript Type Check success, Test Core success, Build Core success, Governed Surface Queue Guard success, Type Check UI success, Test UI success, Build & E2E UI success, Live E2E UI success, Lint UI skipped (selector), Check Changeset success, Dogfood Regression Gate success, no failure. The a0442de6 TypeScript Type Check red was three lanes `cancelled` by the next push, not a type error.", "dogfood_battery": "59630d94 · os-verify-lock: VERDICT command-exit 0 · Test Files 387 passed | 3 skipped (390) · Tests 3199 passed | 28 skipped (3227) · no failure", "mcp_calls": "0", "api_writes": "1 — POST issues/28866/comments (this os-dev-report, via post-stamped.mjs through the fleet relay). git push x5 to claude/project-thread-yrazza (not REST).", "files_changed": [ ".changeset/28866-installer-oauth-client.md", "content/docs/automation/connectors.mdx", "content/docs/references/integration/connector.mdx", "packages/qa/dogfood/test/connector-installer-oauth-client.dogfood.test.ts", "packages/runtime/src/dispatcher-plugin.ts", "packages/runtime/src/domains/automation-connector-connection-door.test.ts", "packages/runtime/src/domains/automation.ts", "packages/services/service-automation/src/connector-connection-door.test.ts", "packages/services/service-automation/src/connector-connections.ts", "packages/services/service-automation/src/oauth2-grant/authorization.ts", "packages/services/service-automation/src/oauth2-grant/grant-handle.test.ts", "packages/services/service-automation/src/oauth2-grant/grant-handle.ts", "packages/services/service-automation/src/oauth2-grant/index.ts", "packages/services/service-automation/src/oauth2-grant/installer-client.ts", "packages/services/service-automation/src/plugin.ts", "packages/services/service-automation/src/sys-connector-connection.object.ts", "packages/spec/liveness/connector.json", "packages/spec/src/contracts/automation-service.ts", "packages/spec/src/integration/connector-auth-grant-kinds.test.ts", "packages/spec/src/shared/connector-auth.zod.ts" ], "line_budget": "20 files, +1055 / -70 = 1125 changed lines vs merge base fea2dbb7 (under the 3000 human-merge threshold); this round added +200 (dogfood case 189, mount fix 6, docs 16, changeset 4, net of merge).", "deviations": [ "PR body not written by me: os-dev.md forbids a dev PATCH of the PR body after pr_create, and the standard order (which os-dev.md binds over) names issue_patch. The refreshed body is ready verbatim at /mnt/project-files/server-seat2/29097-pr-body-r2.md (attribution, Fixes, Clause-② / Metadata-protocol / Skills-docs / Ruling-ref lines, 维护者速读, What changes, Tests with forced edits named, Acceptance notes, Verification on 59630d94); the seat writes it.", "File surface beyond the claim's: packages/runtime/src/dispatcher-plugin.ts (the mount fix, same defect class as the card: the installer client must reach the door) and content/docs/automation/connectors.mdx (the Skills-docs half the spec lane's landing note says rides with this card). packages/runtime and packages/spec were already in the resumed diff.", "service-automation and spec suites were read on 52e23967; the two later commits touch only docs, the dogfood test and runtime's dispatcher-plugin.ts, whose own suites were re-run on 59630d94.", "Did not merge origin/main again after the PR was open: no conflict, no main-caused red (AGENTS.md §10); main is ahead with service-automation runas changes that do not touch these files." ], "open_questions": [ { "question": "New public key names — maintainer approval needed before landing: `client` on ConnectorConnectionRequest and ConnectorConnectionState, with members `clientId`, `clientSecret` (request), `source`, `clientId`, `hasSecret` (state), and the connect body keys `clientId` / `clientSecret`.", "options": ["A approve as named (they mirror the OAuth client vocabulary and the spec's clientId)", "B rename before landing"], "recommendation": "A, because the names match RFC 6749 client_id/client_secret in camelCase and the existing clientId key on the auth shape." }, { "question": "The Console's Setup → Integrations → Connector Connections begins a connect with no body, so it cannot connect a clientSource: 'installer' instance (it now shows the 400 naming the registration step). File a ui-lane card for a client id / secret form?", "options": ["A file a ui card (the server half and API are complete)", "B leave API-only until asked"], "recommendation": "A, because the Console is the documented way to connect and the feature is otherwise API-only." } ], "out_of_scope_findings": [ "class: none (feature gap, not a defect) · reach: Console Setup → Integrations → Connector Connections, Connect on a clientSource installer instance answers 400 · evidence: the Console begin sends no body; the server refuses an installer begin without a client by design · dedupe words: connector connection console installer client form · carrier: seat 2 (ui lane card) · noted in the PR's Acceptance notes, not filed", "Skills-docs follow-up owed: skills/objectstack-automation/references/integration-recipes.md (governed Tier H) · carrier: seat 2 files the card" ] }Stamped 2026-11-02T10:00Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt
Claim amendment to
6572348459· 2026-11-02T10:10Z · file surface increment, declaredThe card thread's report
6574284916names two files outside the claim's surface on PR #29097. The seat accepts both:packages/runtime/src/dispatcher-plugin.ts: the connect door's HTTP mount passedundefinedas the body for all three verbs, so an installer client sent over HTTP never reached the door. The new dogfood case found it on its first run. The fix is POST throughdeferRequestBody; it is the same defect's last hop, so it rides this PR.packages/runtime/src/domains/automation.ts(the connect door's closed body set) andcontent/docs/automation/connectors.mdx(teachesclientSource: 'installer'and the connect body) are the door and its product page.packages/runtime/src/domains/automation.tsin disjoint hunks (flow start and flow clone); none touchesdispatcher-plugin.tsat this hunk orconnectors.mdx. Whichever lands second merges main.Clause-②: yes (narrowing)is unchanged; the contract review runs on head59630d94.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-steve · session_01ADHkmSB1MQ9Npyv1kGL3DV
os-dev-report
{ "issue": 28866, "status": "done", "round": "contract review should-fix 1 (review record 6574689504)", "branch": "claude/project-thread-yrazza", "pr": "https://github.com/objectstack-ai/objectstack/pull/29097", "session": "session_01ADHkmSB1MQ9Npyv1kGL3DV", "premise_still_valid": true, "head": "2ca22f19045a28236809170971ef6968ad5f1a23", "summary": "packages/runtime/src/route-ledger.ts: the POST /automation/connectors/:name/connection row no longer says 'No body'. It names the closed body set { clientId, clientSecret? }, says no body or {} begins with no client, and lists the three 400 VALIDATION_ERROR refusals. The GET row names the client the read answers, never its secret. Note text only; no code path changed. PR body r3 is at /mnt/project-files/server-seat2/29097-pr-body-r3.md.", "tests": "2ca22f19: the 13 runtime test files that read the route ledger (route-ledger.conformance, http-dispatcher, automation-api-contract-mounts and 10 more): Test Files 13 passed (13), Tests 423 passed (423), os-verify-lock VERDICT command-exit 0. No ablation: a ledger note is documentation, not tested behaviour.", "gates": "2ca22f19: dispatch-gates --commands derives 110 families (one new: pnpm check:route-ledger-census). The 37 that read route-ledger.ts, the new one included, re-run on this head: all exit 0. The other 73 do not read the changed file and carry their exit-0 readings from 59630d94. --ran with exit codes: 110 derived, 110 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. CI on 2ca22f19: not yet concluded when this was written.", "dogfood_battery": "59630d94 (round 1) · VERDICT command-exit 0 · Test Files 387 passed | 3 skipped (390) · Tests 3199 passed | 28 skipped (3227). Not re-run: 2ca22f19 changes only two string literals in the route ledger.", "mcp_calls": "0", "api_writes": "1 — POST issues/28866/comments (this report). git push x1.", "files_changed": ["packages/runtime/src/route-ledger.ts"], "line_budget": "this round +2 / -2 in one file; PR total 21 files.", "deviations": ["Dogfood battery not re-run on 2ca22f19 (note-text-only change); the round-1 reading on 59630d94 stands."], "open_questions": [], "out_of_scope_findings": [] }Stamped 2026-11-02T10:37Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt
决策分析(席位 domain:server#2)· 2026-11-02T14:38Z
一句话问题: 开源版 OAuth 连接器由各部署管理员自带客户端(裁决 6566728470 字母 B),服务端实现 PR #29097 已就绪(复审 PASS),但它在连接请求与连接状态上新增公开键名,需维护者批准拼写。
背景: 卡 #28866 由席 2 接手,PR #29097(草稿,head
2ca22f19)交付;合约复审 PASS 6574689504,分诊增量复审 PASS 6576596413。新增公开键:连接请求体client{clientId, clientSecret};连接状态读出client{source, clientId, hasSecret},secret 永不读出。席位此前只在项目线程里放了决策卡,未在卡上落分析、未打needs-user-decision,总监收件箱因此看不到——本评论补上。Governing text: 裁决 6566728470(batch #450 item 1,字母 B):"a per-connection client record on the
authorization_codeinstance, the shape ADR-0143 D2.1 already keeps for MCP dynamic registration (registered_client)"。规格半边 #28920 已合并,用clientSource: 'installer'。新公开键名须维护者批准(PR 正文 Acceptance notes「New public key names」)。协议声明:
Clause-②: yes (narrowing)(连接请求体此前静默忽略任何键,现对未知键/错配客户端 400);Metadata-protocol: none;contracts 为内联成员类型,无导出移动(check:api-surfaceexit 0)。前提(带复查命令): PR 草稿且干净 —
gh api repos/objectstack-ai/objectstack/pulls/29097 --jq '.draft,.mergeable_state';键名只出现在本 PR —git grep -n "hasSecret" origin/main -- packages/spec/src/contracts为 0 行。业务含义: A = 与 OAuth 行业通用拼写(
client_id/client_secret的驼峰形)和规格半边clientSource一致;B = 只换拼写。四维(业务立场):
hasSecret,密钥不出库。clientId/clientSecret即对;写错键会得到响亮 400 而非静默忽略。os-decision-facets
① 项目长远合理性: A 与 OAuth 规范及规格半边拼写一致,密钥不出库。
② 实际业务拉动: 开源版每个部署接 OAuth 应用都需要,DocuSign 排其后。
③ 防 AI 犯错: A 按 OAuth 常识即对,错键响亮 400。
④ 创业阶段不扩散: 5 个键名在已裁形状内,无新配置面。
Prior rulings read: "clientSource installer", "registered_client", "hasSecret" → 1 ruling (6566728470, letter B); thread: none
推荐:A。 只看①选 A;②③④ 是否翻转:否。置信缺口:
source现只有'installer'一个值,为日后其他来源预留;未实测其他平台读面是否同样用hasSecret一词。裁后执行: A ⇒ 席 2 ACCEPT 并入队落地,落地后在 #28869 留解锁注记,#29255 / #29256 随之可派。B ⇒ 按给出拼写改名重跑门禁。
相关: PR #29097 · #28920 · #28869 · #29255 · #29256 · 席 2 项目线程决策卡(同一问题,裁决以本卡为准)。
State:
pm:dispatched→needs-user-decision, recorded by this comment.Generated by Claude Code
zhuangjianguo commentedon Nov 2, 2026
Brief-claimed-by: session_01QsR2jV5sBSzCYNEDgpYLJw · batch #458 · 2026-11-02T14:50Z
Generated by Claude Code
zhuangjianguo commentedon Nov 2, 2026
Ruling: batch #458 item 4 · letter A · maintainer 「同意」 2026-11-02T14:54Z
director#1 · zhuangjianguo · session_01QsR2jV5sBSzCYNEDgpYLJw
What the ruling binds
client { clientId, clientSecret }; connection stateclient { source, clientId, hasSecret }; the secret is never read back.clientId/clientSecretare the wordsconnector-auth.zod.tsalready uses for an OAuth client,hasSecretfollows the spec'shas*boolean family (hasMore,hasSeedData,hasBreakingChanges), andsource: 'installer'carries the definition'sclientSourcevalue.client.sourceon the state andclientSourceon the definition are two spellings of one concept; nested underclientthe state's reads coherently.Workload of the letter
2ca22f19, contract reviews PASS 6574689504 and 6576596413, 59 green, clean).Clause-②: yes (narrowing)with the BREAKING banner naming the three newly refused call shapes,Metadata-protocol: none.Execution
clientSource: 'installer'in integration-recipes.md once the server slice (#28866) lands #29255 / docs(adr-0143): append an amendment note that the installer-client server slice has landed (the "until the server slice lands … held degraded" sentence is now history) #29256 dispatchable; the skills reference page follow-up (integration-recipes.md, governed Tier H) is the seat's to file.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt
Ruling received · 2026-11-02T15:02Z
Ruling
6580268872: letter A, the maintainer's 「同意」 at 2026-11-02T14:54Z. The names land as filed, with zero rework. The seat ACCEPTs PR #29097 and enqueues it in this act, and lands it.State:
needs-user-decision→pm:dispatched, assigned toos-steve, recorded by this comment (the ruling's exit stroke).Generated by Claude Code