# Task: Organization domain foundation ## Feature `docs/FEATURES/organizations.md` ## Goal Add the backend foundation for organizations as the SaaS account boundary and make workspaces belong to an organization. ## Context Current docs and code treat `Workspace` as the top-level boundary. The product model now requires `Organization` above workspace for billing, subscriptions, connectors, limits, and workspace ownership. Existing local data does not need to be preserved. ## Scope - Add an `Organizations` backend module or follow the existing ownership pattern if organization code belongs with `Workspaces`. - Add an organization persistence model with `Id`, `Name`, `Slug`, `OwnerUserId`, and `CreatedAt`, matching local conventions. - Require every workspace to belong to exactly one organization. - Update workspace create/list/detail APIs to include organization ownership. - Add current-user organization read APIs: - `GET /api/organizations` - `GET /api/organizations/{organizationId}` - Add backend validation that users cannot access organizations they have no relationship with. - Seed or development bootstrap data should create at least one organization and owned workspace when local development data is empty. - Update OpenAPI after backend contracts change. ## Constraints - Keep backend code under `backend/src/Socialize.Api`. - Preserve FastEndpoints module structure. - Do not implement billing provider integration in this task. - Do not implement connector storage in this task. - Do not implement full organization membership override behavior in this task. - Do not implement organization settings UI in this task. - Existing development data may be wiped; do not spend scope on compatibility migration behavior. ## Implementation Notes - Place organization-owned backend code under `backend/src/Socialize.Api/Modules/Organizations`. - Add `DbSet` and `ConfigureOrganizationsModule()` to `AppDbContext`. - Keep `Workspace.OwnerUserId` for the existing creator/owner convention unless a later task explicitly replaces it. - Add a required `Workspace.OrganizationId` property and database index. - The first implementation may grant organization access through `Organization.OwnerUserId == currentUserId` and existing manager/administrator access. Full organization membership belongs to task 002. - `CreateWorkspaceRequest` should require `OrganizationId`; reject creation when the user cannot manage that organization. - `WorkspaceDto` should include `OrganizationId`. - Slugs should keep the existing lowercase kebab-case validation used for workspaces. - Use tests for unauthorized organization detail access and workspace creation under an inaccessible organization. ## Likely Files - `backend/src/Socialize.Api/Data/AppDbContext.cs` - `backend/src/Socialize.Api/Modules/Organizations/**` - `backend/src/Socialize.Api/Modules/Workspaces/**` - `backend/src/Socialize.Api/Migrations/**` - `backend/tests/Socialize.Tests/**` - `shared/openapi/openapi.json` - `frontend/src/api/schema.d.ts` ## Done When - [x] Organization entity is persisted. - [x] Workspace requires `OrganizationId`. - [x] Workspace APIs expose organization ownership. - [x] Current user can list accessible organizations. - [x] Current user can get accessible organization details. - [x] Unauthorized organization access is rejected. - [x] Development seed data creates an organization with owned workspaces. - [x] Backend build and tests pass. - [x] OpenAPI and generated frontend schema are updated. ## Validation Commands ```bash dotnet build backend/Socialize.slnx dotnet test backend/Socialize.slnx ./scripts/update-openapi.sh ```