3.5 KiB
3.5 KiB
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
Organizationsbackend module or follow the existing ownership pattern if organization code belongs withWorkspaces. - Add an organization persistence model with
Id,Name,OwnerUserId, andCreatedAt, 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/organizationsGET /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<Organization>andConfigureOrganizationsModule()toAppDbContext. - Keep
Workspace.OwnerUserIdfor the existing creator/owner convention unless a later task explicitly replaces it. - Add a required
Workspace.OrganizationIdproperty and database index. - The first implementation may grant organization access through
Organization.OwnerUserId == currentUserIdand existing manager/administrator access. Full organization membership belongs to task 002. CreateWorkspaceRequestshould requireOrganizationId; reject creation when the user cannot manage that organization.WorkspaceDtoshould includeOrganizationId.- Use tests for unauthorized organization detail access and workspace creation under an inaccessible organization.
Likely Files
backend/src/Socialize.Api/Data/AppDbContext.csbackend/src/Socialize.Api/Modules/Organizations/**backend/src/Socialize.Api/Modules/Workspaces/**backend/src/Socialize.Api/Migrations/**backend/tests/Socialize.Tests/**shared/openapi/openapi.jsonfrontend/src/api/schema.d.ts
Done When
- Organization entity is persisted.
- Workspace requires
OrganizationId. - Workspace APIs expose organization ownership.
- Current user can list accessible organizations.
- Current user can get accessible organization details.
- Unauthorized organization access is rejected.
- Development seed data creates an organization with owned workspaces.
- Backend build and tests pass.
- OpenAPI and generated frontend schema are updated.
Validation Commands
dotnet build backend/Socialize.slnx
dotnet test backend/Socialize.slnx
./scripts/update-openapi.sh