Skip to content

fix(teams): personal spaces offer create-a-team instead of a doomed invite - #1032

Open
juandavidr7 wants to merge 2 commits into
mainfrom
fix/personal-space-invite-gate
Open

fix(teams): personal spaces offer create-a-team instead of a doomed invite#1032
juandavidr7 wants to merge 2 commits into
mainfrom
fix/personal-space-invite-gate

Conversation

@juandavidr7

Copy link
Copy Markdown
Collaborator

Client half of the Teams invite fix (server half: gethouston/cloud#156). Fixes the confirmed production bug where users invited teammates from their PERSONAL space, the gateway answered 403 personal_space by design, and the client showed a generic red failure toast — because the People surface only gated on multiplayer + role, and everyone owns their personal space.

What

  • Capabilities type (additive): spaceKind?: "personal" | "team" on ui/engine-client Capabilities — the gateway's server-truth signal for the ACTIVE space, refetched on space switch. Tolerant reader: absent (older gateway) keeps today's behavior byte-identical.
  • Pure gate: isPersonalSpace(caps) in app/src/lib/org-roles.ts, beside the other capability-only gates.
  • Surface: one branch at the top of the Organization → People tab. In a personal space, the add-member form, pending invites, and roster are replaced by a "create a team to invite people" CTA that reuses CreateTeamDialog; on success the app switches into the new team, capabilities refetch as team, and the real invite surface appears — the journey continues instead of dead-ending. Admin index People caption follows suit.
  • Deliberately narrow: canSeeMembers/canSeeOrganization untouched — Admin (Activity/Usage) and Permissions stay reachable in personal spaces; only the invite affordance is replaced. share-via-team-flow was already personal-aware.
  • Copy in en/es/pt (teams:people.personal.*), teams-and-inviting language only.

Decision table

capabilities.spaceKind People tab
"personal" Create-team CTA replaces invite surface
"team" Unchanged
absent (older gateway) Unchanged — no regression on stale gateways

Tests

App suite 1950/1950 (new cases for the three states in org-roles.test.ts), tsgo --noEmit clean, check-locales in sync, houston-web typecheck + shim parity OK, engine-client typecheck/tests clean, Biome clean.

Notes

  • The CTA only ever shows once cloud#156 is deployed (clients read spaceKind absent until then).
  • Follow-up (cheap, optional): extend the fake host with spaceKind to add a personal-space Playwright e2e; existing e2e exercise the absent path.

…onal spaces

Since C8, inviting from a personal space answers 403 personal_space by
design, but the client still rendered the Organization > People "Add
someone" form there: it gated only on the multiplayer capability plus
owner/admin role, and every user is owner of their personal space. Users
invited, hit the wall, and saw a generic red failure toast (8/8 production
invite failures on 2026-07-22).

Gate on the gateway's new server-truth signal instead: GET /v1/capabilities
now returns spaceKind ("personal" | "team") for the active space, refetched
on every space switch exactly like role. Additive and read tolerantly:

- spaceKind "personal": the People tab body becomes a "create a team to
  invite people" CTA that opens the existing CreateTeamDialog (which
  switches into the new team on success, so the real invite surface
  appears right after); the Admin index People row caption follows.
- spaceKind "team": unchanged (roster + add row / read-only admin notice).
- spaceKind absent (older gateway): unchanged, so hosted team users on a
  stale gateway never lose the invite surface.

Changes: additive Capabilities.spaceKind in ui/engine-client, a pure
isPersonalSpace gate in app/src/lib/org-roles.ts beside the other caps-only
role gates, the People tab branch + PeopleCreateTeamCta component, and
en/es/pt copy under teams:people.personal + org.index.rows.peoplePersonal.
The gateway stays the sole enforcer; this only stops offering a dead end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant