Workspaces (multi-tenant)
Workspace je top-level kontejner pro projekty + tým, který se chová jako „mini-organizace" uvnitř tvého účtu. Pomáhá oddělit dokumenty jednoho klienta od druhého, nebo různá oddělení v jedné firmě.
Kdy použít
- Konzultant / design studio s víc klienty
- Firma s odděleními (Engineering / Purchasing / Management)
- Multi-tenant SaaS (každý zákazník = workspace)
WorkspaceSwitcher

V horním navbaru vedle ourCAD loga je dropdown s ikonou budovy. Zobrazuje název aktivního workspace nebo „Osobní" (legacy single-org pohled).
Co dropdown nabízí
| Položka | Akce |
|---|---|
| Osobní | Vrátí pohled na klasické dokumenty bez workspace scope. Vždy první, vždy dostupné. |
| Seznam tvých workspaces | Každý řádek: ikona + název + role badge (★ owner / ◆ admin / nic = member). Klik → přepnutí. |
| + Nový workspace | Inline formulář (jméno → Vytvořit). Caller se stane automaticky owner. |
| Nastavení workspace… | Otevře plnou správu na /workspaces. |
Klik na workspace uloží volbu do localStorage.ourcad_active_workspace_id a provede hard reload stránky, aby všechny routes (Dashboard, Dokumenty, …) refetchly data s novým scope.
Stránka /workspaces (správa)

Tabulka všech workspaces, jichž jsi členem:
| Sloupec | Popis |
|---|---|
| Název | Klikem se rozbalí řádek s detailem členů |
| Plán | personal (vyhrazeno pro budoucí billing tiery) |
| Owner | Email vlastníka |
| Členů | Počet |
| Tvoje role | owner / admin / member |
| Vytvořeno | Timestamp |
| Akce | Přepnout · Smazat (jen owner) |
Operace
- + Nový workspace — pouze platform admin (běžný user tlačítko nevidí; backend vrátí 403 pokud někdo zavolá API přímo). Inline form, admin se automaticky stane ownerem nového workspace. Po vytvoření může owner přidat libovolného člena, povýšit ho na ownera a sám se případně z workspace odejít.
- Smazat workspace (✕ jen owner) — confirmation prompt. Po smazání: dokumenty / složky / týmy s tímto
workspace_idse přepnou na NULL = „Osobní". Workspace_members se kaskádově odstraní. Ochrana: poslední owner nelze odebrat. - Přidat člena (owner/admin) — email + role (member/admin/owner). Email se identifikuje sám sebou — nemusí mít OurPortal účet předem, ale pak nemůže nic dělat dokud se nepřihlásí.
- Odebrat člena (owner/admin, ✕ vedle členu).
- Přejmenovat workspace (owner/admin).
- Přepnout se do workspace (Přepnout šipka v řádku) — analogie kliknutí v switcheru.
Kdo může vytvářet workspaces
Pouze platform admin (uživatel s globální rolí ROLE_ADMIN přidělenou v OurPortalu). Důvod:
- Anti-spam — bez gatingu by si každý uživatel mohl vytvořit libovolný počet workspaces, což fragmentuje data a zatěžuje databázi.
- Multi-tenant kontrola — workspace má charakter „malé organizace". O tom, kdo ho založí, rozhoduje provozovatel (organizace majitele instance ourCAD).
Když chce běžný uživatel nový workspace, požádá administrátora. Admin workspace vytvoří + přidá uživatele jako ownera → další správu (přidávání členů, přejmenování, smazání) už zvládá nově nominovaný owner sám bez admin role.
Backend vrací 403 WORKSPACE_CREATE_FORBIDDEN pro non-admin POST /api/v1/workspaces. UI tlačítko „+ Nový workspace" ve WorkspaceSwitcheru i na stránce /workspaces se non-adminům nezobrazí.
Role uvnitř workspace
| Role | Co může |
|---|---|
| owner | Full control. CRUD workspace, add/remove/promote/demote members. Nelze odebrat pokud je poslední. |
| admin | Member management + přejmenování workspace. Nemůže smazat workspace ani odebrat jiného ownera. |
| member | Read access — vidí dokumenty workspace, ale nemůže měnit členství. |
Vztah k per-document RBAC
Role uvnitř workspace nepřepisuje permission tier konkrétního dokumentu. I když jsi owner workspace, dokumenty mají vlastní tier (view / comment / edit / admin). Workspace member = „smí vidět seznam dokumentů ve workspace"; co konkrétně s nimi může je dáno per-doc grantem.
Use cases
Konzultant / design studio
alice@studio.cz vidí v switcheru:
├── Osobní (její soukromé experimenty)
├── Klient A (owner) — projekty pro klienta A
├── Klient B (owner) — projekty pro klienta B
└── InternalDS (admin) — sdílené šablony studiaKlikne Klient A → vidí jen jeho dokumenty. Vytvoří nový dokument → automaticky se otaguje workspace_id = klient_a_uuid.
Firma s odděleními
bob@firma.cz:
├── Engineering (admin) — sdílené CAD modely
├── Purchasing (member) — vidí released revize
└── Management (member) — vidí dashboardyEngineering tým spolupracuje na CAD modelech; Purchasing vidí jen „released" verze přes PDM workflow status.
Kam patří nový dokument + přesun
Dokument vytvořený s aktivním workspace (přepínač vlevo nahoře) do něj automaticky patří — a to i při importu (STEP/IGES, .ourcad) a při Vytvořit součást/podsestavu (díl dědí workspace rodičovské sestavy). Dokument bez workspace je osobní: vidíte ho jen vy a lidé s explicitním sdílením.
Přesun existujícího dokumentu: v seznamu dokumentů pravý klik → Přesunout do workspace… — vyberete cílový workspace nebo „Osobní". Funguje i pro vícenásobný výběr; přesouvat může jen vlastník dokumentu. Členové workspace dokument uvidí okamžitě.
Co se přepne při switch
| Sféra | V1 stav | Poznámka |
|---|---|---|
| Dokumenty | ✓ scoped | Dashboard + DocumentsRoute filtrují přes X-Workspace-ID header |
| Složky | ⚠ soft | folders.workspace_id existuje, ale list endpoint nefiltruje |
| Týmy | ⚠ soft | teams.workspace_id existuje, filtrace deferred |
| Materiály | ✗ global | Sdílené napříč všemi workspaces |
| Šablony / Title-blocks | ✗ global | Sdílené |
| Custom roles | ✗ global | Sdílené |
| Default access policy | ✗ global | Sdílené |
| Guest invites | per-doc | Nezávislé na workspace |
Persistence + API hlavičky
- localStorage klíč
ourcad_active_workspace_id— string s UUID workspace nebo prázdná hodnota = „Osobní". - Přežije reload, je sdílená napříč taby.
- Změna vyšle window event
ourcad-workspace-changed(komponenty se mohou reaktivně refetchnout; v aktuální verzi se primárně dělá hard reload). - Backend identifikuje workspace přes header
X-Workspace-ID: {uuid}(nebo query?workspace={uuid}).authHeaders()ho přidává automaticky.
Edge cases
| Situace | Chování |
|---|---|
| 0 workspaces | Vidíš jen „Osobní" + inline „+ Nový". Po loginu jsi defaultně v „Osobní" (žádný auto-workspace bootstrap). |
| Uživatel odebrán zvenčí | localStorage zůstane nastaven; další API call vrátí 403. UX: vrátit se ručně do „Osobní". |
| Přesun dokumentu | Vyžaduje: jsi owner dokumentu a zároveň member cílového workspace. |
| Smazání workspace | Documents/folders/teams se NULL-ují (vrátí se do „Osobní"); workspace_members se kaskádově smaže. Dokumenty zůstanou v systému. |
| Posun do „Osobní" | POST /api/v1/workspaces/{id}/documents/{docId} s wsID = "" vrátí dokument bez workspace scope. |
Datový model
workspaces:
id (UUID PK), name, slug, owner_email, plan ('personal'),
created_at, updated_at
workspace_members:
workspace_id (FK), user_email, role (owner/admin/member),
added_at
PRIMARY KEY (workspace_id, user_email)
-- atributy na existujících tabulkách (NULLABLE)
documents.workspace_id UUID NULL
folders.workspace_id UUID NULL
teams.workspace_id UUID NULLKlíčové vlastnosti:
workspace_idje nullable — všechna stará data zůstávají sNULLa fungují jako „Osobní" view (backward-compat).- Slug se autogeneruje z jména (lowercase +
-). Při kolizi se přidá 4-char UUID suffix. - Mazání workspace cascade-uje
workspace_members; documents/folders/teams se NULL-ují.
API endpointy
| Metoda | URL | Co dělá |
|---|---|---|
GET | /api/v1/workspaces | List všech tvých workspaces |
POST | /api/v1/workspaces | Vytvořit (jen platform admin — ROLE_ADMIN; caller se stane ownerem) |
GET | /api/v1/workspaces/{id} | Detail + členové |
PATCH | /api/v1/workspaces/{id} | Přejmenovat / změnit plán (owner/admin) |
DELETE | /api/v1/workspaces/{id} | Smazat (owner) |
GET | /api/v1/workspaces/{id}/members | List členů |
POST | /api/v1/workspaces/{id}/members | Přidat člena (owner/admin) |
DELETE | /api/v1/workspaces/{id}/members | Odebrat člena (owner/admin) |
POST | /api/v1/workspaces/{id}/documents/{docId} | Přesunout dokument do workspace |
GET | /api/v1/workspaces/{id}/documents | List dokumentů ve workspace |
Příklady curl
# Vytvořit workspace (jen platform admin, jinak 403)
curl -X POST https://ourcad.cloud/api/v1/workspaces \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Project XYZ"}'
# Přidat člena
curl -X POST https://ourcad.cloud/api/v1/workspaces/$WS_ID/members \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"email": "bob@example.com", "role": "member"}'
# List dokumentů ve workspace (přes header)
curl -X GET https://ourcad.cloud/api/v1/documents \
-H "Authorization: Bearer $TOKEN" \
-H "X-Workspace-ID: $WS_ID"Funkce workspace se průběžně rozšiřují — novinky najdeš v „Co je nového" přímo v aplikaci.
Co dál
- Sdílení & spolupráce — RBAC, magic-link host invites, audit log
- Git workflow — branches, commits, merges (per-document, neovlivněné workspace)
- Nastavení & jazyk — per-user preferences (independent na workspace volbě)