fix(platform-objects): hide org/membership surfaces in single-org mode#2348
Merged
Conversation
Apply the platform's existing multi-org gating convention consistently across the org/membership surface, which had only been wired in a handful of spots: - nav entries -> requiresService: 'org-scoping' - object actions -> visible: 'features.multiOrgEnabled != false' Nav (P1): - account.app "My Organizations" (sys_member/mine): was gated on requiresObject: 'sys_member', which never fires (system object always registered) and left the always-empty view visible in single-org. Re-gated on requiresService: 'org-scoping'. - setup-nav "Teams" (sys_team): had no gate while sibling Organizations/ Invitations were service-gated. Added requiresService: 'org-scoping'. Actions (P0) — gated on features.multiOrgEnabled != false: - sys_user.invite_user (most exposed: Users list always reachable) - sys_member add_member/update_member_role/remove_member + transfer_ownership - sys_team create_team/update_team/remove_team - sys_team_member add_team_member/remove_team_member - sys_invitation invite_user/resend_invitation/cancel_invitation Recipient-side invitation accept/reject stay record-gated (unreachable in single-org anyway). No behavior change in multi-org. Metadata-only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Gate the remaining sys_organization admin actions (update/delete/
set_active/leave/change_slug) on features.multiOrgEnabled != false, so
every org action matches the already-gated create_organization.
- Stop rendering a null organization in titleFormat:
- sys_member: '{user_id} in {organization_id}' -> '{user_id} ({role})'
- sys_invitation: 'Invitation to {organization_id}' -> 'Invitation for {email}'
organization_id is null in single-org mode, so the old formats read
"... null"; the new fields identify the record in both modes.
sys_team's by_org view was left as-is: the teams list is empty in single-org
(create is gated) so the grouping never degenerates in practice, and the nav
entry is hidden anyway.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 3 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The platform gates multi-org features two ways — nav entries on
requiresService: 'org-scoping'(e.g. setup-nav Organizations/Invitations) and object actions onvisible: 'features.multiOrgEnabled != false'(e.g.sys_organization.create_organization). That convention had only been wired in a handful of spots, so a wide band of org/membership surface leaked into single-org deployments (OS_MULTI_ORG_ENABLEDunset/false) where it is pure UX noise or a broken affordance.Triggering example:
…/_console/apps/com.objectstack.account/sys_member/view/mine("My Organizations") shows even in single-org, where there are nosys_organizationrows and no auto-stamped memberships — so the view is always empty for every user.Changes (metadata-only)
Nav (P1)
nav_account_memberships(sys_member/mine): was gated onrequiresObject: 'sys_member', which never fires (system object is always registered). Re-gated onrequiresService: 'org-scoping'.nav_teams(sys_team): had no gate while sibling Organizations/Invitations were service-gated. AddedrequiresService: 'org-scoping'.Actions — gated on
features.multiOrgEnabled != false(P0)sys_user.invite_user(most exposed — the Users list is always reachable in single-org)sys_member:add_member/update_member_role/remove_member, andtransfer_ownership(combined with its existingrecord.role != 'owner'condition)sys_team:create_team/update_team/remove_teamsys_team_member:add_team_member/remove_team_membersys_invitation:invite_user/resend_invitation/cancel_invitation(recipient-side accept/reject stay record-gated — unreachable in single-org anyway)Remaining rough edges (P2)
sys_organizationadmin actions (update/delete/set_active/leave/change_slug) now all gated too — previously onlycreate_organizationwas.titleFormatno longer renders a null organization:sys_member→{user_id} ({role}),sys_invitation→Invitation for {email}(org_id is null in single-org → old formats read "… null").sys_team'sby_orgview left as-is: the teams list is empty in single-org (create is gated) so the grouping never degenerates in practice, and the nav entry is hidden anyway.Scope / safety
No behavior change in multi-org deployments (
OS_MULTI_ORG_ENABLED=true):features.multiOrgEnabledis true and theorg-scopingservice is present, so every gate evaluates to visible exactly as before. No schema, API, or runtime changes.Not in scope (follow-up): single-sourcing the multi-org flag resolution (
driver-sqlreads the env var directly instead of the resolved flag; ~8 scattered detection sites) and a regression gate asserting org-scoped surfaces are hidden in single-org.Verification
@objectstack/platform-objectsbuild + DTS succeed🤖 Generated with Claude Code