Estimate: 70m · Depends on: 6.10.3
Build the org service layer + the ACCESS GATING that makes the org tier real: org membership gates workspace access, and the org owner/admin role extends (sits above) the 6.4 workspace role model. This is the business logic the org admin API/UI (6.10.5) and the platform stories later sit on.
organizationsService (business logic + transactions — 4-layer):
OrganizationRole, remove, change role), and "list members ACROSS the org’s workspaces" (the cross-workspace roster — PAGINATED, never load-all, the at-scale rule). Each write-flow is ONE prisma.$transaction; returns DTOs via lib/mappers/* (never raw Prisma); throws typed errors from lib/organizations/errors.ts the route maps to HTTP.OrganizationMembership — NO workspace membership (org-only members in zero workspaces are valid; a plain org member reaches only workspaces they’re explicitly added to). Conversely the add-to-WORKSPACE flow (extending the existing WorkspaceMembership create) MUST auto-create the user’s OrganizationMembership (role member) in that workspace’s org if absent — the UPWARD invariant (you cannot be in a workspace without being in its org), in the SAME transaction. Removing from the org cascades loss of workspace access (gate); removing from a workspace leaves the org membership intact.provisionForNewUser-style flow that creates an org + a default workspace + the owner memberships for a brand-new account, in ONE transaction, wired into the existing signup/onboarding path — so every account is an org of one (OPC) from day one and there is never a tier-less user. Mirror the shape of the 6.10.3 backfill (which does the same for pre-existing workspaces); the org name defaults from the user/company and is renameable.The access gate (the load-bearing change). Extend the existing workspace access check so that reaching a workspace requires the session user to be a member of the workspace’s ORG (org membership gates workspace access — 6.10.2). Compose the roles per 6.10.2’s precedence: an org OWNER/ADMIN is granted admin-equivalent access to EVERY workspace under the org (extending the 6.4 MemberRole); an org MEMBER falls back to their per-workspace MemberRole. Preserve the 404-not-403 cross-tenant posture (a non-member of the org sees the workspace as not-found, not forbidden — the standing guard).
Where it threads. The gate is a single authorization helper the existing workspace-scoped services/route guards call (do NOT scatter org checks across N routes); the 6.4 permission helper is extended, not duplicated. Reads that guard a write take tx + SELECT FOR UPDATE where a concurrent membership change could race (the lock-before-read-derived-update rule).
organizationsService owns org CRUD + membership management + the cross-workspace member listing (paginated), each write-flow in ONE transaction, returning DTOs (never raw Prisma), throwing typed errors; routes (added in 6.10.5) call exactly one service method.MemberRole); an org member falls back to their per-workspace role.tx on writes).organizationRepository / organizationMembershipRepository + the schema this orchestrates.motir-core/lib/services/ — the workspace + membership services + the 6.4 permission/role helper the gate EXTENDS (mirror its shape).motir-core/CLAUDE.md § 4-layer + the lock-before-read-derived-update rule + the 404-not-403 cross-tenant guard.