Skip to content

refactor(plugin-auth): derive the SCIM connection-id cap from SCIM_SERVICE_PRINCIPAL_PREFIX - #31150

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-2aak0o
Nov 7, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-2aak0o

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Requested by 田騏 · project thread

Fixes #31033

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么: SCIM 凭证签发接口对 connectionId 的长度上限(246)原来把 svc:scim: 前缀再手写了一遍来计算,现在改为读取已导出的常量 SCIM_SERVICE_PRINCIPAL_PREFIX 的长度;本卡 changeset 另补一段 Exported,说明随 SCIM 凭证接口新增的两个公开 AuthManager 方法。
  • 为什么改: 审计里 SCIM 连接的操作者标签就是用这个常量拼出来的;如果以后前缀改了而上限没跟着改,过长的连接 id 会让该连接每次请求的审计写入失败。现在两者只有一个来源。
  • 风险与回滚: 行为不变(上限仍是 246,超长仍答 400 INVALID_REQUEST),只是 plugin-auth 的一处常量来源加一份 patch changeset;回滚即 revert。
  • 先看: packages/plugins/plugin-auth/src/scim-connection-admin.ts 的 MAX_SCIM_CONNECTION_ID;.changeset/31033-scim-connection-id-cap-from-prefix.md。
  • 两分钟验证: pnpm --filter @objectstack/plugin-auth exec vitest run src/scim-connection-admin.test.ts,预期 10 个用例全绿(含 246 可签发、247 被拒)。
  • 需要你做的: 无,席位落地。

What changes

  • packages/plugins/plugin-auth/src/scim-connection-admin.ts: MAX_SCIM_CONNECTION_ID is now MAX_TEXT - SCIM_SERVICE_PRINCIPAL_PREFIX.length instead of MAX_TEXT - 'svc:scim:'.length, importing the constant from scim-connection-service.ts (already imported from there). The doc comment says why. Value unchanged: 246.
  • .changeset/31033-scim-connection-id-cap-from-prefix.md: patch on @objectstack/plugin-auth. It also carries the card's optional item: an Exported paragraph naming the two public AuthManager methods behind the SCIM credential routes (isScimWired(), mintScimConnectionCredential(engine, input)), which the pending plugin-auth: no door mints a SCIM connection bearer (mintScimConnectionCredential has no caller and the object refuses create), so no IdP can connect #30958 release note does not name. That note itself is untouched (byte-identical to main).

Tests

  • No test edited: the existing pin in scim-connection-admin.test.ts (246 accepted, 247 refused, 9 + 246 === 255) holds unchanged.
  • One-shot reverse proof that the cap now follows the constant (not kept as a test): with SCIM_SERVICE_PRINCIPAL_PREFIX mutated to a 10-character svc:scimx: via scripts/ablation-replace.mjs, the pin turns red: the 246-character mint answers 400 with "at most 245 characters". Restored; blob hash equals HEAD (9557afe1), git status clean, file rerun 10/10 green.

Acceptance notes

  • None.

Verification

Local readings
  • Head 56589092: pnpm --filter @objectstack/plugin-auth test 234/234 files, 4168 passed / 10 skipped, lock VERDICT command-exit 0; pnpm --filter @objectstack/plugin-auth typecheck VERDICT command-exit 0.
  • eslint --no-inline-config on the touched source file: exit 0 (plugin-auth has no own lint script; repo-wide pnpm lint is CI's).
  • dispatch-gates --commands: 55 families derived (same list at 1f6f18d2, cb24c94f and 56589092). All 55 run at 1f6f18d2 (2 first exited 3 for prerequisites and were rerun after the fixture fetch and a full packages build, both exit 0); --ran reconciliation: 55 run, 0 NOT-MEASURED. After 56589092 (changeset-only commit) the changeset and text families were rerun: check-empty-changeset, check-changeset-no-major, check-adr-0087-registration (all --base origin/main), check:issue-citations, check:doc-authoring, check:nul-bytes, each exit 0.

🤖 Generated with Claude Code

…RVICE_PRINCIPAL_PREFIX

MAX_SCIM_CONNECTION_ID spelled the svc:scim: prefix a second time; it
now reads SCIM_SERVICE_PRINCIPAL_PREFIX.length, so the cap moves with
the audit actor label it protects. The cap stays 246.

The pending SCIM credential-door changeset gains an Exported line for
the two public AuthManager methods behind the routes.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2bjuYso9Pes3WcUTEb
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 7, 2026
@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see

Coarse fallback — 22 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 9f61e06e6fe4d28c0fcc6ef66b3fcfef6067e51b → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 76eac9b0be9c7207165c4a6fc9acb92e91b6e282 — the merge of head 56589092ed20f16c294e2a839b3f88d372232540 into base 9f61e06e6fe4d28c0fcc6ef66b3fcfef6067e51b, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 76eac9b0be9c7207165c4a6fc9acb92e91b6e282 && git checkout 76eac9b0be9c7207165c4a6fc9acb92e91b6e282
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 9f61e06e6fe4d28c0fcc6ef66b3fcfef6067e51b 56589092ed20f16c294e2a839b3f88d372232540 && git checkout -B drift-repro 9f61e06e6fe4d28c0fcc6ef66b3fcfef6067e51b && git merge --no-ff 56589092ed20f16c294e2a839b3f88d372232540

node scripts/docs-audit/affected-docs.mjs --json 9f61e06e6fe4d28c0fcc6ef66b3fcfef6067e51b

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

…'s own changeset

The pending SCIM credential-door changeset is restored byte-identical to
main; the Exported paragraph naming isScimWired() and
mintScimConnectionCredential() rides in this change's own patch note.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2bjuYso9Pes3WcUTEb
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#3 · marchtian · session_017ihL2dFb2QdZEHEJ83cR2B

维护者速读

  • 改了什么: SCIM 凭证签发接口对连接 id 的长度上限(246)改为读取已导出的前缀常量来计算,不再手写一遍 svc:scim:。本卡 changeset 补了一段,写明随 SCIM 凭证接口新增的两个公开方法。
  • 为什么改: 审计里的操作者标签就是用这个常量拼出来的。将来前缀一改,上限会跟着动,过长的连接 id 不会让审计写入失败。
  • 风险与回滚: 行为不变,上限仍是 246,超长仍返回 400。回滚即 revert。
  • 先看: scim-connection-admin.ts 的 MAX_SCIM_CONNECTION_ID。
  • 两分钟验证: 见 PR 正文同名行。
  • 需要你做的: 无,席位落地(非受管面)。
  • 席位意见: ACCEPT。plugin-auth: no door mints a SCIM connection bearer (mintScimConnectionCredential has no caller and the object refuses create), so no IdP can connect #30958 已发布待发的 changeset 原样未动,补充说明放在本卡自己的 changeset 里,不触发 DELIBERATE CORRECTION。

席位核对

ACCEPT · Head-sha: 56589092ed20f16c294e2a839b3f88d372232540 · 2026-11-07T15:15Z

  1. Shape: draft → main, Fixes #31033; Clause-②: no / Metadata-protocol: none match the claim 6708014021. 2 files, scim-connection-admin.ts and this card's changeset, inside the claimed surface. check-governed-merges --pr 31150: 0 of 2 paths governed, +17 / −2.
  2. Premise measured: at main the cap was MAX_TEXT - 'svc:scim:'.length beside the exported SCIM_SERVICE_PRINCIPAL_PREFIX (the actor-label source). PR feat(platform-objects): mint and revoke SCIM connection credentials from the console #31119 had touched the same file and is on main.
  3. Gates (check-runs at this head): 52 runs, 37 success, 15 skipped, 0 failure, 0 pending; Check Changeset green. Dev's local reading at this head: plugin-auth 234 files (4168 passed / 10 skipped) and typecheck exit 0; changeset gates exit 0; derived list unchanged at 55.
  4. Accepted, read in the diff: one import and one expression; value unchanged (246). The existing pin (246 accepted, 247 refused) holds unchanged. The dev showed with one ablation that the pin follows the constant: a 10-character prefix turns it red. The first round's edit to the pending plugin-auth: no door mints a SCIM connection bearer (mintScimConnectionCredential has no caller and the object refuses create), so no IdP can connect #30958 changeset was reverted at the seat's request (byte-identical to main). The Exported paragraph moved into this card's own changeset, which is the order's second option, so no DELIBERATE CORRECTION confirmation is owed.
  5. Out of scope: none. Skills-docs: n/a.
  6. Landing: seat lands it (pr_ready + automerge_enable via the relay). On MERGED it checks that plugin-auth: derive the SCIM connection-id cap from SCIM_SERVICE_PRINCIPAL_PREFIX #31033 closed and removes pm:dispatched.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 7, 2026 15:16
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 7, 2026 15:16
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 7, 2026
Merged via the queue into main with commit 6a01718 Nov 7, 2026
53 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-2aak0o branch November 7, 2026 15:58
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/s tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

plugin-auth: derive the SCIM connection-id cap from SCIM_SERVICE_PRINCIPAL_PREFIX

2 participants