#Organizations
The organization is the primary resource context. Servers, members, roles, providers and the audit log all belong to one organization. Backend Phase 4 "Organization & Members" is now complete (2026-10-03, by Pair 1) V8 requirement, so this module finally has rules: see FE: Organization & Members screens for the screen spec. The old gap D-25 is closed.
The V7 detail below stays as background for the parts Phase 4 doesn't spell out.
UserMember of Organization (with roles)Organization resources: servers, providers, members, roles, audit log
#V7 data model (reference)
| Table | Key fields | Notes |
|---|---|---|
organizations | user_id (creator/owner), name, description, logo, key, main, soft delete | Each organization gets its own SSH key pair in V7 (used by the V7 agent; not needed for OSS) |
organization_members | organization_id, user_id (null while invited), server_id (set = shared-server member), email, designation, invitation_token | One row per person per organization |
organization_roles | organization_id, role | owner and admin created with every organization |
member_role | member_id, role_id | A member can hold several roles |
organization_metas | name/value | e.g. onboarding_skipped |
#Operations
| Operation | V7 behaviour | V8 status |
|---|---|---|
| List my organizations | Organizations where I'm a member, with members and their roles. Also GET /auth/user/organizations | Missing |
| Create | name (required, validated), description, logo (jpeg/png, otherwise a generated avatar). Creates owner + admin roles with default permissions and adds the creator as Owner. The first organization gets main = 1. Audit "Organization Create" | Missing |
| Rename / settings | name, description, logo. Owner only ("You don't authorize…") | Missing |
| Delete | Refused when: it's the main organization; it's the user's only organization; it still has servers ("Please delete servers before deleting organization"). Members are removed, the organization soft-deleted, audit written | Missing |
| Onboarding | essential-point checklist and onboarding-skip | Missing Open question keep? |
| My permissions | GET /organizations/{org}/my-permissions/{level} returns the permission list for the current user (owner, member, plan-gated) | Missing |
#Switching organization
V7 puts the organization in the URL of every API call (/organizations/{organization}/servers…), and the frontend keeps the current one. V8 should keep that: it's explicit, cacheable and safe. V7 only Assumption
What happens on switch:
Pick organization in switcherSave as current (per user)Cancel in-flight requests of old orgClear org-scoped cachesReload: permissions, subscription + usage, sidebar countsStay on same section if allowed, else Dashboard
- The switcher (top bar) lists organizations from the session payload, with the user's role in each.
- The frontend stores the choice (cookie, so server components can read it) and cancels pending requests for the old organization.
- Every organization-scoped resource reloads: servers, providers, members, roles, blueprints (if organization-scoped), audit log, dashboard, subscription and usage, permission map.
- The user stays on the same section (e.g. Servers) of the new organization. Detail pages (
/servers/:id) go back to the list, because that ID belongs to the old organization. - The backend never trusts the stored choice: every request is checked for membership of the organization in the URL → 403/404 otherwise.
#Organization settings page
| Field | Rule | Source |
|---|---|---|
| Name | Required, unique per owner (V7 CheckNameValidation) | V7 only |
| Description | Optional text | V7 only |
| Logo | jpeg/png upload. Generated avatar otherwise | V7 only |
| Danger zone | Delete, with the V7 refusal rules above, plus delete protection (V8 3.6: checked before any delete) | V7 only V8 requirement |
#Organization-scoped vs user-scoped
| Organization-scoped | User-scoped |
|---|---|
| Servers, server links | Profile, password, 2FA, IP whitelist, sessions |
Providers (V7 cloud_server_providers.organization_id) | Notification channels (V7 notification_channels.user_id) |
| Members, invitations, roles | Wallet credits, cards, transactions (V7 user-level) |
| Audit log | Subscription (V7), see the conflict above |
Invoices (V7 invoices.organization_id, nullable) | Blueprints (V7 wordpress_blueprints.user_id) Open question |
#Edge cases
| Case | Expected behaviour |
|---|---|
| User has no organization | Only "Create organization" (and account pages) are reachable |
| Current organization deleted by its owner | Next request → 404/403 → frontend clears it, picks the main/first organization, toast "That organization is no longer available" |
| Member removed while working | Same as above. In-flight actions fail with 403 |
| Two tabs on different organizations | URLs carry the organization, so each tab stays consistent. "Current" is the last switched |
| Organization with servers, delete clicked | Refused, with a link to the server list |