From 8164655d653263902ff5fe56a012b585938a5b37 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 23 Sep 2026 15:03:38 +0000 Subject: [PATCH 1/2] fix(platform-objects): sys_user.role help text names the route that works on every tenancy posture The role field's description prescribed an unscoped admin_full_access assignment as the way to grant platform-admin standing. Under a walled posture (group / isolated) that row no longer confers standing, so the help text now names OS_PLATFORM_OWNER_EMAIL (every posture) and keeps the unscoped grant clause single-only. The existing pin on the description also requires both. Claude-Session: https://claude.ai/code/session_01TEhopqrWQYBycZzyJHpAZr Co-authored-by: Claude --- .changeset/sys-user-role-help-posture-split.md | 18 ++++++++++++++++++ .../src/identity/sys-user.object.ts | 2 +- .../src/platform-objects.test.ts | 7 +++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 .changeset/sys-user-role-help-posture-split.md diff --git a/.changeset/sys-user-role-help-posture-split.md b/.changeset/sys-user-role-help-posture-split.md new file mode 100644 index 00000000000..382107a4bec --- /dev/null +++ b/.changeset/sys-user-role-help-posture-split.md @@ -0,0 +1,18 @@ +--- +"@objectstack/platform-objects": patch +--- + +fix(platform-objects): `sys_user.role`'s help text names the platform-admin route that works on every tenancy posture, and keeps the unscoped grant `single`-only (#19875) + +The `role` field's `description` is authored metadata: it ships in the published bundle, is extracted into the `en` i18n bundle, and is the help text an administrator reads on the field in Setup. It said: + +> Legacy better-auth role scalar (admin, user, …). ObjectStack no longer writes it (ADR-0068 D2) — grant platform-admin standing with an unscoped `admin_full_access` assignment in `sys_user_permission_set`. + +On a walled deployment (`OS_TENANCY_POSTURE` `group` or `isolated`) that remedy does nothing: since the walled legacy-anchor retirement, an unscoped `admin_full_access` row no longer confers platform-admin standing there. The only route there is the deployment's configured administrator list. The help text now reads: + +> Legacy better-auth role scalar (admin, user, …). ObjectStack no longer writes it (ADR-0068 D2). To grant platform-admin standing, list the user's verified email in `OS_PLATFORM_OWNER_EMAIL`; under the `single` tenancy posture an unscoped `admin_full_access` assignment in `sys_user_permission_set` also confers it. + +This describes both anchors as they work today. The configured, email-verified address confers standing on every posture. The unscoped grant row still confers it under `single`, and nowhere else. No behaviour changes: this is a text correction only. + +- **`en.objects.generated.ts`** follows by regeneration (`pnpm i18n:extract`), not by hand. +- **The existing pin** on this description (`platform-objects.test.ts`) now also requires the text to name `OS_PLATFORM_OWNER_EMAIL` and to qualify the grant with `single`. Without that, restoring the unqualified sentence would pass every test. diff --git a/packages/platform-objects/src/identity/sys-user.object.ts b/packages/platform-objects/src/identity/sys-user.object.ts index 7f8718e29df..ca076aa169e 100644 --- a/packages/platform-objects/src/identity/sys-user.object.ts +++ b/packages/platform-objects/src/identity/sys-user.object.ts @@ -701,7 +701,7 @@ export const SysUser = ObjectSchema.create({ maxLength: 64, group: 'Admin', description: - 'Legacy better-auth role scalar (admin, user, …). ObjectStack no longer writes it (ADR-0068 D2) — grant platform-admin standing with an unscoped `admin_full_access` assignment in `sys_user_permission_set`.', + 'Legacy better-auth role scalar (admin, user, …). ObjectStack no longer writes it (ADR-0068 D2). To grant platform-admin standing, list the user\'s verified email in `OS_PLATFORM_OWNER_EMAIL`; under the `single` tenancy posture an unscoped `admin_full_access` assignment in `sys_user_permission_set` also confers it.', }), banned: Field.boolean({ diff --git a/packages/platform-objects/src/platform-objects.test.ts b/packages/platform-objects/src/platform-objects.test.ts index ccaa6d83f9a..72709ae37dc 100644 --- a/packages/platform-objects/src/platform-objects.test.ts +++ b/packages/platform-objects/src/platform-objects.test.ts @@ -318,6 +318,13 @@ describe('@objectstack/platform-objects', () => { expect(role.description).not.toContain('Set Platform Role'); expect(role.description).toContain('sys_user_permission_set'); expect(role.description).toContain('admin_full_access'); + // #19875 — which route exists depends on the tenancy posture. Under a + // walled posture (`group` / `isolated`) the unscoped grant confers no + // platform-admin standing (#11663 L5), so the text must name the anchor + // that confers on EVERY posture and keep the grant clause `single`-only; + // an unqualified grant prescription silently does nothing on a walled rig. + expect(role.description).toContain('OS_PLATFORM_OWNER_EMAIL'); + expect(role.description).toContain('`single`'); }); }); From 2007d3e6c5fde9052291bdad28cf05108b4f2102 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 23 Sep 2026 15:06:53 +0000 Subject: [PATCH 2/2] chore(platform-objects): regenerate the en objects bundle for the sys_user.role help text Produced by pnpm i18n:extract; translated-locale leaves and source-hash tables are byte-unchanged. Claude-Session: https://claude.ai/code/session_01TEhopqrWQYBycZzyJHpAZr Co-authored-by: Claude --- .../src/apps/translations/en.objects.generated.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/platform-objects/src/apps/translations/en.objects.generated.ts b/packages/platform-objects/src/apps/translations/en.objects.generated.ts index 2424c705bc4..e5ef3ada4fb 100644 --- a/packages/platform-objects/src/apps/translations/en.objects.generated.ts +++ b/packages/platform-objects/src/apps/translations/en.objects.generated.ts @@ -35,7 +35,7 @@ export const enObjects: NonNullable = { }, role: { label: "Platform Role", - help: "Legacy better-auth role scalar (admin, user, …). ObjectStack no longer writes it (ADR-0068 D2) — grant platform-admin standing with an unscoped `admin_full_access` assignment in `sys_user_permission_set`." + help: "Legacy better-auth role scalar (admin, user, …). ObjectStack no longer writes it (ADR-0068 D2). To grant platform-admin standing, list the user's verified email in `OS_PLATFORM_OWNER_EMAIL`; under the `single` tenancy posture an unscoped `admin_full_access` assignment in `sys_user_permission_set` also confers it." }, banned: { label: "Banned",