-- 031: personal workspaces — solo accounts (operator flow reorder, follow-up to 030). -- -- The register form no longer forces "Name your workspace": registration -- defaults to a SOLO ACCOUNT with a minimal auto-created personal workspace, and -- creating a collective becomes an explicit opt-in flag on the form. -- -- WHY A WORKSPACE AT ALL, when the user asked for none: -- The workspace is the tenancy spine of the whole Hub — memberships, -- connections, drafts, approvals, the group tree, group_rooms, chat_media_ -- archive, storage/PeerTube quotas and the audit chain are all keyed -- workspace_id, and RLS fail-closes on app.workspace_id. A user without a -- workspace would have no readable rows anywhere; giving them one keeps every -- existing machine (including the group-files and PeerTube paths) working -- unchanged, with zero new code paths to audit. -- -- The flag makes that hidden scaffolding honest: kind='personal' says "this -- tenant exists to hold ONE user's own stuff". It is deliberately NOT one of -- the groups kinds from 030: groups.kind distinguishes participation units in -- the collective tree; workspaces.kind distinguishes tenancy origins. A -- personal workspace CONTAINS no collective, so it can never appear in the -- collective tree/listing APIs (collectives are groups rows; 030 already -- filters them by kind IN ('collective','subcollective') and a personal -- workspace never creates such rows). -- -- kind is workspace-scoped metadata, not a secret: it is returned by /auth/me -- and used by the web app to pick the post-login home. Nothing authorizes on it. BEGIN; ALTER TABLE workspaces ADD COLUMN kind text NOT NULL DEFAULT 'shared' CHECK (kind IN ('shared','personal')); -- Existing workspaces were all created by the named-workspace flow => shared. -- The DEFAULT covers new rows; the explicit UPDATE is documentation, and it -- keeps the backfill honest if the default ever changes. UPDATE workspaces SET kind = 'shared' WHERE kind IS NULL; COMMIT;