Workspace.create misses workspace_members + silent General default — first-run experience broken #22
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_collab#22
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Two coupled gaps in the operator's first-run experience
After running collab end-to-end through the proxy with a fresh DB, the deployer's first 60 seconds in the UI are needlessly broken in two ways. They're independent in source but coupled in user experience — the modal needs the membership row to actually work, and the membership row without the modal still leaves the operator stuck on "default 'General' workspace I didn't pick a name for."
Half 1 —
workspace.createdoesn't add the creator toworkspace_membershandlers/workspace.rs::createdoes:workspace.create)workspacesdataJSONNo INSERT into
workspace_members. Result: the workspace exists, the creator passes the perm check, but every per-workspace operation that gates on membership fails immediately:For comparison:
channel.createandcanvas.createalready auto-add the creator to their respective scope tables (channel_memberswithrole=admin,canvas_collaboratorswithrole=owner).workspace.createwas the only one missing the equivalent INSERT.Half 2 — chat-app.js silently auto-creates a "General" workspace
pickUserhad:The operator opens the chat for the first time and a workspace named "General" appears with no choice, no naming, no awareness that this just happened. They either rename it (annoying friction) or live with it (looks like off-the-shelf product). No modern self-hosted product does this — Slack, Discord, Mattermost, Linear, Notion all ask you to name your workspace as the first onboarding step.
Plus:
init()was firing-and-forgettingworkspace.list, sopickUsercould see stalestate.workspaces=[]even when the server had workspaces — creating spurious "General" workspaces and confusing the operator.Why coupled
If we fix the membership row but keep the silent "General" auto-create, the operator never sees a setup screen and the workspace name they end up with isn't theirs. If we add a setup modal but leave the membership row missing, the modal succeeds but the chat is immediately unusable (canvas.create fails). Both halves are required for the first-run experience to actually work.
Fix shape
Server:
workspace.createauto-adds the creatorWrapped in
if let Some(caller)so dev-mode unauth (caller_id=None) silently skips. canvas.create's membership check is also dev-mode-bypassed, so no functional break in dev.Client: first-run setup modal
Replace the silent auto-create with a forced modal that asks for workspace name + first channel name. Slack-pattern onboarding.
Polish details (all in
chat-app.js::showFirstRunSetup):rgba(0,0,0,0.85)+backdrop-filter: blur(4px)so the chat layout (sidebar avatar) doesn't bleed throughvalidate_channel_slug)${user.name}'s Workspace(selected on focus so it's overwriteable)gap:14px, narrowermax-width:420pxsince it's only 2 fieldsstate.users.length > 1(dev mode); proxy mode locks the usercreateElementthroughout — only user-derived value (user.name) set viatextContent, no innerHTML on user dataAlso:
init()'s proxy-mode branch awaitsworkspace.listso the empty-check inpickUseris accurate.Behaviour after the fix
canvas.createNot a member of workspace Nworkspace.createPR
Fix in
feat/workspace-creator-membership-and-first-run-ui. ~310 LOC acrosshandlers/workspace.rs(+20 server) andchat-app.js(+290 client, mostly the polished modal). No schema change.