Skip to content

Commit 6a01718

Browse files
refactor(plugin-auth): derive the SCIM connection-id cap from SCIM_SERVICE_PRINCIPAL_PREFIX (#31150)
<!-- claude-projects-attribution: {"github_login":"marchtian"} --> _Requested by **田騏** · [project thread](https://claude.ai/code/project/chan_01VmuUhXU9SSUzqJYyXSmYSi?thread=cmsg_01VmuUhXU9SSUzqJYyXSmYSi9Hju7DThD7eoLKoJU9hnHj)_ 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 #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 <details><summary>Local readings</summary> - 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. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- signed: domain:server#3 · marchtian · session_017ihL2bjuYso9Pes3WcUTEb --> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8ef4d30 commit 6a01718

2 files changed

Lines changed: 17 additions & 2 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@objectstack/plugin-auth': patch
3+
---
4+
5+
refactor(plugin-auth): the SCIM connection-id cap is derived from the exported service-principal prefix
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
`POST /api/v1/auth/admin/scim/mint-credential` refuses a `connectionId` longer than 246 characters so the connection's audit actor `svc:scim:CONNECTION_ID` fits the 255 characters of `sys_audit_log.actor`. That cap was computed from the prefix spelled out a second time; it now reads the length of `SCIM_SERVICE_PRINCIPAL_PREFIX`, the constant the actor label itself is built from, so the two can no longer drift apart. Nothing a caller sees changes: the cap is still 246, and the refusal is still `400 INVALID_REQUEST`.
11+
12+
Exported (completing the record of the SCIM credential routes, whose release note names the routes only): two public `AuthManager` methods back them. `isScimWired()` answers whether the SCIM service provider is mounted on this deployment (the same decision that mounts `/scim/v2`), and `mintScimConnectionCredential(engine, input)` mints a connection bearer with the deployment's auth secret, the key the mounted SCIM verifier digests with.

‎packages/plugins/plugin-auth/src/scim-connection-admin.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ import type { PlatformAdminActor } from './platform-admin-gate.js';
6767
import { readJsonRequestBody } from './request-json-body.js';
6868
import {
6969
SCIM_CREDENTIAL_OBJECT,
70+
SCIM_SERVICE_PRINCIPAL_PREFIX,
7071
revokeScimConnectionCredential,
7172
type MintScimConnectionCredentialInput,
7273
type MintedScimConnectionCredential,
@@ -84,9 +85,11 @@ const MAX_TEXT = 255;
8485
* A write made by a SCIM connection is audited with the service actor
8586
* `svc:scim:<connectionId>` (#30960), and `sys_audit_log.actor` holds 255
8687
* characters, so a longer id would make that audit insert fail for every
87-
* request the connection makes. 255 minus the 9-character prefix.
88+
* request the connection makes. 255 minus the 9-character prefix, read from
89+
* {@link SCIM_SERVICE_PRINCIPAL_PREFIX} (the one spelling the actor label is
90+
* built from) so the cap moves with the label it protects.
8891
*/
89-
const MAX_SCIM_CONNECTION_ID = MAX_TEXT - 'svc:scim:'.length;
92+
const MAX_SCIM_CONNECTION_ID = MAX_TEXT - SCIM_SERVICE_PRINCIPAL_PREFIX.length;
9093

9194
/** Execution context for the store reads and the audit write. */
9295
const SYSTEM_CTX = { isSystem: true } as const;

0 commit comments

Comments
 (0)