feat: POST /auth/workspaces — create an additional collective from an existing account
Until now collectives only existed at registration; an account with a personal workspace had no path to start one. The creator becomes Owner and gets a session scoped to the new workspace.
This commit is contained in:
parent
177ca6eb2b
commit
cbdb8c0f81
18 changed files with 2584 additions and 8 deletions
31
apps/api/migrations/036_branding.sql
Normal file
31
apps/api/migrations/036_branding.sql
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
-- 036: per-collective branding — logo, tagline, background, accent.
|
||||
--
|
||||
-- Owner need: the ACTIVE COLLECTIVE must be unmistakable in the shell, and
|
||||
-- pages/screenshots must look different per workspace. That is presentation
|
||||
-- state of the TENANT itself, so it lives on `workspaces` — not a new table,
|
||||
-- not instance_settings (028 is the deployment's legal posture, one per
|
||||
-- instance; branding is per collective).
|
||||
--
|
||||
-- One nullable jsonb column, nothing else:
|
||||
-- * logoAssetKey text — storage key (sha256/…) of the collective's mark
|
||||
-- * tagline text — one-line subtitle under the name
|
||||
-- * backgroundKey text — storage key of the shell background image
|
||||
-- * accent text — CSS hex color overriding the palette accent
|
||||
-- * NULL / missing key ⇒ the Hub default for that field
|
||||
--
|
||||
-- NULL (the default) means "no branding": every existing workspace keeps the
|
||||
-- stock look. The key set is validated at the API seam (branding.service.ts)
|
||||
-- because the values are cross-cutting (storage keys must match real objects,
|
||||
-- accent must be a safe CSS color); the DB only guarantees "object or absent"
|
||||
-- so an undecodable row degrades to defaults instead of failing the shell.
|
||||
--
|
||||
-- `workspaces` is deliberately NOT under RLS (001): it holds no tenant rows,
|
||||
-- it IS the tenant spine. Reads/writes stay behind the RbacGuard + service
|
||||
-- seam exactly as before this migration.
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE workspaces ADD COLUMN branding jsonb
|
||||
CHECK (branding IS NULL OR jsonb_typeof(branding) = 'object');
|
||||
|
||||
COMMIT;
|
||||
Loading…
Add table
Add a link
Reference in a new issue