Repository navigation
feat(service-automation, metadata-protocol, driver-mongodb, cli): a connector connection is unique per organization and instance (package, name) - #33199
Conversation
…tor connection unique per organization and instance (package, name) ADR-0150 D4 and D8 row R11, storage half. The maintainer's ruling: a connection is unique by package and name. - sys_connector_connection's key widens from (organization_id, connector_name) to (organization_id, connector_package, connector_name), spelled 'global' with organization_id listed, so driver-sql's widening arm replaces the old key (safe, create-before-drop) once the guard stands. - uniq_sys_connector_connection_packageless keeps the connections that name no package to one per (organization_id, connector_name), built at objectql:schema-synced as the grant guard is, on SQLite, PG, MySQL 8.0.13+, MariaDB 10.3+ and MongoDB; listed in the runtime-index preflight, os migrate duplicates and os migrate apply's steps. - A first connect that raced the backfill takes its second row back and is refused, as the old key refused it. - The R11 boot backfill leaves a row whose bind would be a second row of one key and reports it (duplicated) once a read confirms it; the dry run agrees; os migrate stored-references bind refuses it as 'duplicate'. - Declared limits: upgraded MySQL 8 keeps the old key (driver-sql reads the functional key part as an expression, as for the grant); driver-memory builds no guard. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibzKCovWpJoMZD6U3NT
|
domain:server#7 · os-tesla · session_01L9qibzKCovWpJoMZD6U3NT Posted 2026-11-14T01:53Z. Red-line read run in the card thread on the maintainer's instruction, by a separate review pass: design round, code round 1, code round 2 (delta). Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Findings by round: design PASS-WITH-CHANGES (M1 to M7, S1 to S9, taken). Code round 1 PASS-WITH-CHANGES, no must-fix, seven should-fix, all taken. Round 2 PASS, one should-fix (foreign messages on the new count and delete) and two changeset notes, taken. Open at this head: none. Implemented-by: VERDICT: PASS |
📓 Docs Drift CheckThis PR changes 4 package(s): 4 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 51 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 4b798b46baca8885aec33cdcf9c391e1ca9d0403 && git checkout 4b798b46baca8885aec33cdcf9c391e1ca9d0403
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 67274acad689d5be75d5bfc5007f4fb9396aa907 f5d2a9e370b3bd8d92a4fb1b52f7830f394dd230 && git checkout -B drift-repro 67274acad689d5be75d5bfc5007f4fb9396aa907 && git merge --no-ff f5d2a9e370b3bd8d92a4fb1b52f7830f394dd230
node scripts/docs-audit/affected-docs.mjs --json 67274acad689d5be75d5bfc5007f4fb9396aa907
|
… asserts; tenant-audit census counts the take-back delete The take-back delete in ConnectorConnectionStore#connect is one more write call site (elevated, against sys_connector_connection): census regenerated and the page's prose figures moved with it. The race pin's double opens its update and delete with assertEngineUpdateDispatch / assertEngineDeleteDispatch, and the engine-double ledger records it. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibzKCovWpJoMZD6U3NT
…rrorText callers, pinned by its own sentinel test Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibzKCovWpJoMZD6U3NT
…nector connection guard beside the grant's Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibzKCovWpJoMZD6U3NT
|
domain:server#7 · os-tesla · session_01L9qibzuZJBQY4wUQFJbkfx Delta review over record 6869740710 (head Contract reviewServed-tier: ① Derived judgmentsThis is a delta over 6869740710 at 2dfdbbe. The red lanes at 2dfdbbe were the engine test-double contract gate (inside Lint · ESLint), the tenant-audit census gate (inside Lint · repo & tooling gates), and the umbrella Lint and TypeScript lanes that roll them up. Type Check · workspace was cancelled, not failed. The delta answers those gates and the three CLI count pins. No assertion is loosened.
② Semver levelThis is a delta over 6869740710 at 2dfdbbe. The only non-test source change is in ③ Boundary flagsThis is a delta over 6869740710 at 2dfdbbe. Nothing in the delta touches the declared limits, the carry-forward to 3a-ii, or the accepted nits in that record. Nothing here contradicts its PASS. The race pin is stronger, not weaker. Check-runs on Findings: none (must-fix 0, should-fix 0, nit 0). Implemented-by: VERDICT: PASS |
|
domain:server#7 · os-tesla · session_01L9qibzuZJBQY4wUQFJbkfx 维护者速读 · PR #33199 @
|
Requested by Tesla · project thread
Part of #31699
Clause-②: yes (widening)
Metadata-protocol: none
维护者速读
sys_connector_connection的唯一键从(organization_id, connector_name)加宽为(organization_id, connector_package, connector_name)。没有包的连接(环境自建或代码注册的连接器实例)靠一条运行时守卫索引uniq_sys_connector_connection_packageless继续保持每个组织一条。守卫立住之后,旧键在下一次安全同步时被替换(先建后删,safe),中间任何时刻都有唯一规则。packages/metadata-protocol/src/migrations/connector-connection-packageless-index.ts(从 plugin-security + runtime: the grant, clone and activation doors take a permission set's package and report a two-holder name with its candidates (ADR-0150 D3/D8; before #31698 PR-2) #32164 的授权守卫复制,只换常量和措辞)、packages/services/service-automation/src/connector-connections.ts(首次连接与回填竞态的回收)、stored-reference-package-backfill.ts(duplicated)。What changes
sys_connector_connectiondeclares{ fields: ['organization_id', 'connector_package', 'connector_name'], unique: 'global' }. Spelled'global'withorganization_idlisted, as plugin-security + runtime: the grant, clone and activation doors take a permission set's package and report a two-holder name with its candidates (ADR-0150 D3/D8; before #31698 PR-2) #32164 spelled the grant's, becausedriver-sql's widening arm (widenedUniqueReplacements) does not fire for'organization'(measured: that spelling plans a destructive orphan drop). The arm keeps the old key until a partial guard on exactly(organization_id, connector_name)stands, then plans onereplace_unique_index,safe, create-before-drop.uniq_sys_connector_connection_packageless, built atobjectql:schema-syncedon every kernel that runs the table's DDL (metadata-protocolplugin.ts): partial index on SQLite and PostgreSQL, functional digest on MySQL 8.0.13+, INVISIBLE generated column on MariaDB 10.3+,RUNTIME_OWNED_UNIQUESon MongoDB (keyed(connector_name), the key Mongo materialized for the old declaration). Listed inruntime-index-preflight.ts(soos migrate duplicates) and in the CLI'sschema-sync-indexes.ts(soos migrate plan/apply). The module is a copy ofuser-permission-set-packageless-index.tswith the table's constants and wording.duplicated), and the walk goes on; the dry run agrees.os migrate stored-references bindrefuses it asduplicate.content/docs/deployment/cli.mdx(runtime-owned indexes, old-key retirement, MySQL limit, the bind refusal);content/docs/automation/connectors.mdx(one connection per organization and instance).Why
ADR-0150 D4: a connector instance is identified by
(package, name), and D8 row R11 gives the connection its package column. The maintainer ruled on #31699 that a connection is unique by package and name, so one organization can connect both packages' instances of one name once the backstop narrows (the last PR of #31699).Verification
service-automationconnector-connection-guard-at-schema-sync.test.ts, realObjectQLPlugin, SQLite, the shipped object): a second package-less connection written from astart()beforekernel:readyis refused, two packages' connections of one name are admitted, a second of one package's is refused; withbootPhaseHooks: falsetoo; a dropped guard is rebuilt by the next pass. Ablation (guard call removed from the hook): 3 of 5 red.driver-sqlsql-driver-widened-connection-key.test.ts: SQLite (no guard → old key kept; guard → one safe replace; re-plan empty) and live PostgreSQL 16 locally; the MySQL cell pins the declared limit (old key kept) and runs onmain.main.driver-mongodb4 tests (live mongod not reachable here);driver-memory3 (declared limit).connector-connections.test.ts(ablation red). Backfill: 3 new pins instored-reference-package-column.test.ts(dry run agrees, unconfirmed violation and an R8 violation end the pass; each red under ablation).@objectstack/service-automation3843 passed (before the review round; affected files re-run, 409 passed),@objectstack/metadata-protocol339 files passed. CLI:schema-sync-indexes,duplicates.contract,stored-references,apply.schema-sync-indexes,schema-migrate.grant-guardgreen. Build with declarations,tsc --noEmitandcheck:test-typecheckgreen for every touched package.Red-line read
Run in this thread by a separate review pass (maintainer's instruction: 「你自己有fable,自己审就可以了吧?」). Design round: PASS-WITH-CHANGES (M1–M7, S1–S9, taken). Code round 1: PASS-WITH-CHANGES, no must-fix, 7 should-fix (a racing first connect could leave two rows; dry run vs real run; backfill catch confirmation; docs and changeset wording), all taken. Round 2 (delta): PASS, one should-fix (foreign messages on the new count and delete) and two changeset notes, taken. Carried to the next PR: the store reads and counts by package.
Human Minimum
packages/specholds no runtime logic.pnpm lintpasses.main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_01L9qibzKCovWpJoMZD6U3NT