Skip to content
Air-Cloud docs

Workspaces

A product that serves companies can let any signed-in end user create a company of their own — a workspace — without you placing anyone: one new node of your organization tree, and a new membership for that end user homed there, as the company's admin. Their other memberships stay as they were, so a person who signed up as a customer keeps that account and gains the company beside it.

Registration does not change: end users still sign up through your product's one hosted sign-up, under the posture [authenticate] declares (Members, roles and registration). Creating a workspace is something a signed-in end user does afterwards, from your product's page.

Declaring it

[authenticate]
roles = ["staff", "customer", "company_admin", "company_member"]
registration = "open"
default_roles = ["customer"]
default_org_path = "/crm/people"
admin_org_path = "/crm"

[authenticate.workspaces]
parent = "/crm/companies"
admin_profile = "company_admin"
name = "slug"
seed = "company"
key what it says
parent the node every workspace is created under: at or below admin_org_path, not at or below default_org_path, and with room for a node below it
admin_profile a profile of config/profiles.toml the creator is granted at the new node (Profiles and grants)
name how the new node's last segment is made: slug from the name the end user types, with a suffix when it is taken (a name that yields no letters falls back to token); token an opaque value, so the name never enters the path
seed optional: a node seed template, db/seeds/<environment>/nodes/<template>/, whose records are applied at each new workspace

aircloud check names each mistake: workspaces.parent_not_below_admin, workspaces.parent_nests_default, workspaces.parent_too_deep, workspaces.profile_undeclared and workspaces.seed_undeclared. The release active in production carries the declaration, and its activation creates the parent node and the base profiles before the first workspace can be made.

The platform stores no company name: the node is a path. Keep the name in your own data at that node — the seed template is the natural place.

What the creator holds

The new membership is homed at the new node, with a grant of admin_profile there and the tenant:org scope. So the creator manages the company's members, profiles, groups and grants at or below its node, and creates and archives nodes below it (Members, roles and registration). Changing admin_profile in config/profiles.toml changes every workspace admin's roles at once.

An end user may create several workspaces; each is a sibling under parent. Every workspace is a node, so it counts against your plan's allowance of nodes, and creation is rate-limited per address.

Scope your staff routes. Your own staff hold roles at admin_org_path, and a workspace admin holds the roles of admin_profile at their company. A [[authenticate.route]] that admits a role of admin_profile must say where with at, so that a company admin does not pass your staff's route by holding the same role at their own node:

[[authenticate.route]]
prefix = "/api/accounts"
function = "accounts"
roles = ["company_member", "company_admin"]
at = "/crm/companies"

aircloud check refuses such a route without at (authenticate.route_at_required). With at, the route passes a session only when one of its roles is effective at that node or below it.

Your page

Your page posts the company's name to the platform route /_air/workspaces on your product's host, with the signed-in end user's session, as a form (display_name, and return_to for the page to come back to) or as JSON ({"display_name": "Acme"}). On success the session acts in the new workspace: a form is sent back to return_to, and JSON receives the new node's org_path, its membership_id and selected: true. Should the new membership take a moment longer to reach every part of the platform, it is not selected yet: a form is sent to the membership switcher and JSON receives selected: false. The workspace exists either way, so select it there and never send the creation again.

The name is kept as the new node's display name, whichever way its path is derived: the members page and every node listing show the company by that name, its path as a hint, and aircloud org nodes rename changes it. It has 1 to 100 characters and no line breaks or other control characters; surrounding blanks are trimmed, and any other name is refused org_node_name_invalid with nothing created.

The end user moves between their memberships — their own account and each company — at /_air/memberships, without signing in again (Members, roles and registration).

A creation is refused, with the selection unchanged, when the production release declares no workspaces (workspaces_undeclared), the end user's address is blocked (address_blocked), the new membership would sit inside one the end user already holds — your first admin's, for instance (membership_home_nested) — or the plan's node allowance is spent (org_node_quota_exceeded).

A function in an end user's session can create a workspace too, through the tree operation workspaces.create it declares (The acting node and elevation). You create client nodes yourself with aircloud org nodes create and place their admins with aircloud members invite.