V8 Central — Product & Technical Spec
  1. Docs
  2. Core platform
  3. Organizations

#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.

#V7 data model (reference)

TableKey fieldsNotes
organizationsuser_id (creator/owner), name, description, logo, key, main, soft deleteEach organization gets its own SSH key pair in V7 (used by the V7 agent; not needed for OSS)
organization_membersorganization_id, user_id (null while invited), server_id (set = shared-server member), email, designation, invitation_tokenOne row per person per organization
organization_rolesorganization_id, roleowner and admin created with every organization
member_rolemember_id, role_idA member can hold several roles
organization_metasname/valuee.g. onboarding_skipped

#Operations

OperationV7 behaviourV8 status
List my organizationsOrganizations where I'm a member, with members and their roles. Also GET /auth/user/organizationsMissing
Createname (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 / settingsname, description, logo. Owner only ("You don't authorize…")Missing
DeleteRefused 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✅ BUILT 2026-10-09 (Pair 1) V8 requirement — and it keeps V7's shape with the detail now published: owner only (an Admin gets 403), the owner types the organization name to confirm, and it is refused while the organization is the owner's default, which is what keeps the last one alive. Roles, memberships, pending invitations and the logo are removed with it. The servers check arrives in Phase 8 (422 organization_has_servers), so it is not enforced yet. V7's "only organization" rule stays implied — the default always exists (D-2)
Onboardingessential-point checklist and onboarding-skipMissing Open question keep?
My permissionsGET /organizations/{org}/my-permissions/{level} returns the permission list for the current user (owner, member, plan-gated)Missing

#Ownership transfer readiness

B4.7 built (Pair 1, 2026-10-09), including the previously pending deletion-safety extension. Current owner starts/cancels; only the chosen existing member accepts within 48 hours. Both must be active and verified and independently confirm with their own password/email code plus their configured 2FA. Cancellation needs no new credential challenge. Previous owner becomes Admin; recipient becomes Owner; both defaults stay unchanged.

A former owner cannot delete an organization after transfer completes, even from a stale dialog. A transfer completed during the former owner's account deletion preserves that organization for its new owner.

Unpaid-charge and recipient-plan checks are not enforced yet (Phases 6–7). Do not promise these blocks today. Preview email delivery is not verified. Full fields, errors and states: Ownership transfer spec.

#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:

  1. The switcher (top bar) lists organizations from the session payload, with the user's role in each.
  2. The frontend stores the choice (cookie, so server components can read it) and cancels pending requests for the old organization.
  3. Every organization-scoped resource reloads: servers, providers, members, roles, blueprints (if organization-scoped), audit log, dashboard, subscription and usage, permission map.
  4. 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.
  5. 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

FieldRuleSource
NameRequired, unique per owner (V7 CheckNameValidation)V7 only
DescriptionOptional textV7 only
Logojpeg/png upload. Generated avatar otherwiseV7 only
Danger zoneDelete, 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-scopedUser-scoped
Servers, server linksProfile, password, 2FA, IP whitelist, sessions
Providers (V7 cloud_server_providers.organization_id)Notification channels (V7 notification_channels.user_id)
Members, invitations, rolesWallet credits, cards, transactions (V7 user-level)
Audit logSubscription (V7), see the conflict above
Invoices (V7 invoices.organization_id, nullable)Blueprints (V7 wordpress_blueprints.user_id) Open question

#Edge cases

CaseExpected behaviour
User has no organizationOnly "Create organization" (and account pages) are reachable
Current organization deleted by its ownerNext request → 404/403 → frontend clears it, picks the main/first organization, toast "That organization is no longer available"
Member removed while workingSame as above. In-flight actions fail with 403
Two tabs on different organizationsURLs carry the organization, so each tab stays consistent. "Current" is the last switched
Organization with servers, delete clickedRefused, with a link to the server list

#Built list filters (B4.1, Pair1 2026-10-10)

GET /api/v1/organizations supports literal name search(max100) and type=all|mine|invited. All includes memberships plus valid pending invitations to the current verified email; Mine means current owner+membership; Invited means joined non-owned+eligible pending. Unverified users see memberships only. Sorted name/ID, one row/org, no pagination. Pending rows show basic name/public logo only and give no access; acceptance still uses the invitation email link, not a token from this list. Profile/login lists stay joined-only, so pending cards never enter the switcher. Screen states and safeguards. Pair2 now reports this update pulled through a7aefc9.

ServerAvatar V8 Central · prepared by central-app-2 (Pair 2 frontend) for Bhavik Jethwa · the frontend in this spec is not built yet; the backend started on 2026-10-08 · Built 2026-11-02 11:30 UTC