docs: define organization account model

This commit is contained in:
2026-05-04 15:45:12 -04:00
parent 9bdef978bd
commit cd6f402d9e
15 changed files with 555 additions and 21 deletions

View File

@@ -70,6 +70,7 @@ Update OpenAPI:
## Current Domain Modules
- `Identity`: authentication, refresh tokens, email verification, password reset, social login.
- `Organizations`: SaaS account ownership, billing/subscription boundary, organization membership, connectors, data mappings, and owned workspaces.
- `Workspaces`: workspace membership, workspace settings, access scoping.
- `Clients`: client records and primary contacts tied to workspaces.
- `Projects`: project pipeline and client/project relationships.

View File

@@ -1,6 +1,6 @@
# Socialize
Socialize is a workspace-based workflow application for social media content review, revision, approval, and publication readiness.
Socialize is an organization-owned, workspace-based workflow application for social media content review, revision, approval, and publication readiness.
It is not a public social network. The product is for internal teams, providers, and client approvers coordinating content work before publication.

View File

@@ -31,7 +31,7 @@ Composition registers:
- web services and auth in `DependencyInjection.cs`
- infrastructure in `Infrastructure/DependencyInjection.cs`
- domain modules for Identity, Workspaces, Clients, Campaigns, ContentItems, Assets, Comments, Approvals, Notifications, and Feedback
- domain modules for Identity, Organizations, Workspaces, Clients, Campaigns, ContentItems, Assets, Comments, Approvals, Notifications, and Feedback
## Data Ownership
@@ -43,6 +43,10 @@ backend/src/Socialize.Api/Data/AppDbContext.cs
Workflow data is organized by module folders. Do not couple unrelated modules through ad hoc service calls; keep ownership boundaries explicit.
`Organization` is the SaaS account boundary for billing, subscription limits, organization-level users, connectors, data mappings, and workspace ownership.
`Workspace` is the brand/client workflow boundary. Each workspace belongs to exactly one organization and owns workspace-scoped workflow data such as channels, content items, assets, comments, approvals, and notifications.
## Frontend
```txt

View File

@@ -0,0 +1,195 @@
# Feature: Organizations
## Status
Draft
## Goal
Define the SaaS account boundary above workspaces.
An `Organization` owns billing, subscriptions, usage limits, organization-level users, connectors, data mappings, and the workspaces used for brand/client workflow.
## User Stories
- As an agency owner, I want my company to own multiple brand workspaces so that billing and administration happen once.
- As an in-house brand team, I want my company to own its workspaces so that billing, users, and connectors are controlled centrally.
- As a professional user, I want one login that can access multiple organizations so that I can work for my employer and freelance clients from the same account.
- As an organization admin, I want to manage organization members so that company-level access can grant inherited workspace access.
- As an organization admin, I want external clients and collaborators to remain visible in workspace members without making them organization members.
- As a billing manager, I want to manage subscription and billing for the organization.
- As an organization admin, I want to configure connectors such as Google Drive once for the organization.
- As a workspace user, I want the existing workspace selector to stay central while still letting me switch organizations.
## Domain Model
### Organization
`Organization` is the SaaS account boundary.
An organization owns:
- billing profile
- subscription plan
- subscription limits
- organization-level users and roles
- workspaces
- connectors and integration credentials
- data mapping rules for connected systems
An organization can own many workspaces.
### Workspace
`Workspace` is the brand/client workflow boundary.
Each workspace:
- belongs to exactly one organization
- is not shared between organizations
- owns brand/client content workflow data
- owns configured social channels
- uses organization-level connectors
### Channel
`Channel` is a configured social destination inside a workspace, such as a Twitter/X account, YouTube channel, Facebook page, Instagram account, or newsletter destination.
Connector credentials for external systems are configured at the organization level in v1.
### User
`User` is a global login identity.
A user can have access relationships with multiple organizations and direct access to multiple workspaces. A user account is not owned by a single organization.
Example:
```txt
alex@example.com
-> Organization access: PepsiCo, Content Manager
-> Organization access: Alex Freelance LLC, Owner and Billing Manager
-> Workspace access: Client review workspace, External Reviewer
```
## Membership And Access
### Organization Membership
Organization membership grants organization-level permissions and inherited workspace permissions across all workspaces owned by the organization.
Organization-level permissions include:
- organization settings
- organization member management
- workspace creation and administration
- billing and subscription management
- connector and data mapping management
Only users with a billing manager permission can view or edit billing and subscription information.
### Workspace Membership
Workspace membership grants access to one workspace.
Workspace participants have a relationship category relative to the organization that owns the workspace:
- `Organization Member`
- `External Collaborator`
`Organization Member` means the user is part of the owning organization. The user may have access through organization membership, direct workspace membership, or both.
`External Collaborator` means the user is not part of the owning organization but has direct workspace access. This includes subcontractors, providers, clients, and external reviewers.
External collaborators can be invited directly to a workspace without becoming organization members.
Organization admins should still be able to see external collaborators when reviewing who has access to organization-owned data.
Workspace membership can override applicable inherited workspace permissions. Organization-only permissions such as billing are not overridden at the workspace level.
## Permission Rules
- Organization permissions are inherited by all owned workspaces when they apply to workspace behavior.
- Workspace-level overrides can reduce or expand workspace-specific permissions where that makes sense.
- Billing and subscription permissions live only at the organization level.
- Connector management lives only at the organization level in v1.
- External collaborators cannot access organization billing, subscription, or connector settings unless they are separately granted organization membership with those permissions.
## Connectors And Data Mappings
Connectors are configured only at the organization level in v1.
Examples:
- Google Drive connection
- connector credentials
- default Drive folder mapping rules
- organization-wide data import or linkage rules
Workspaces use organization-level connectors and mappings. Workspace-specific connector credentials are out of scope for v1.
## Subscription And Limits
Subscription plans and usage limits belong to the organization.
Potential limits include:
- number of workspaces
- number of organization members
- number of external collaborators
- channels per workspace or per organization
- storage or asset limits
- access to advanced workflow features
Exact plan limits are a billing/product task and are not defined here.
## Frontend Surface
The existing workspace selector remains the primary navigation context.
Add an organization switcher at the bottom of the workspace selector.
Organization settings use one explicit organization route:
```txt
/app/organizations/:organizationId/settings
```
The settings page should contain sections for:
- profile/settings
- members
- billing
- connections
- workspaces
Workspace-level screens remain centered on the selected workspace.
## Backend Expectations
- Backend feature code should follow existing module patterns under `backend/src/Socialize.Api/Modules`.
- Workspaces must require an owning organization.
- Organization APIs should return only organizations the current user can access.
- Workspace APIs must preserve workspace scoping and account for inherited organization permissions.
- New backend contracts require OpenAPI regeneration while the backend is running.
## Out Of Scope For Initial Implementation
- Preserving existing local data through migration. Development data can be wiped.
- Workspace sharing across organizations.
- Workspace-level connector credentials.
- Full billing provider integration.
- Final subscription packaging and pricing.
- Cross-organization workspace access inheritance.
## Done When
- [ ] Organization is documented as the SaaS account boundary.
- [ ] Workspace is documented as the brand/client workflow boundary.
- [ ] Workspaces belong to exactly one organization.
- [ ] Organization membership can grant inherited workspace access.
- [ ] Workspace membership supports direct access and overrides.
- [ ] External collaborators do not require organization membership.
- [ ] Billing permissions live at the organization level.
- [ ] Connectors and data mappings live at the organization level.
- [ ] The workspace selector includes an organization switcher.

View File

@@ -18,7 +18,9 @@ Allow workspace managers to invite teammates, clients, and providers into a work
## Domain Rules
- Workspace invites grant access to one workspace owned by one organization.
- Workspace invites belong to exactly one workspace.
- Invite acceptance does not automatically create organization membership.
- Invite email matching should use normalized email addresses.
- Pending invite tokens must be single-use and should expire.
- Accepted invites must grant the invited role and a workspace scope claim for the invite workspace.
@@ -28,6 +30,7 @@ Allow workspace managers to invite teammates, clients, and providers into a work
- Managers can create, list, cancel, and resend invites only for workspaces they can manage.
- Managers must not be able to create duplicate pending invites for the same normalized email in the same workspace.
- Invite acceptance must be auditable through stored status and timestamp changes.
- External collaborator invitees should remain visible in workspace members and organization-level access review views without receiving organization-level billing, connector, or subscription permissions.
## Proposed Statuses

View File

@@ -2,7 +2,7 @@
Socialize is a workflow application for social media content review, revision, approval, and publication readiness.
It is not a public social network. It is a workspace-based coordination tool for internal teams, providers, and client approvers.
It is not a public social network. It is an organization-owned, workspace-based coordination tool for internal teams, providers, and client approvers.
## Primary Users
@@ -16,8 +16,12 @@ It is not a public social network. It is a workspace-based coordination tool for
## Core Product Shape
- workspace-based account boundary
- agencies able to manage multiple workspaces
- organizations as the SaaS account, billing, subscription, and connector boundary
- workspaces as brand/client workflow boundaries owned by one organization
- agencies, in-house teams, and professional businesses able to manage multiple workspaces
- organization members able to inherit access across owned workspaces
- external collaborators able to access specific workspaces without organization membership
- channels configured inside brand/client workspaces
- content items as the main reviewable unit
- assets and revisions tracked against content items
- comments and approvals attached to the work itself
@@ -38,10 +42,11 @@ It is not a public social network. It is a workspace-based coordination tool for
- full direct publishing engine
- full DAM platform
- analytics suite
- billing or subscription flows
- full billing provider integration and pricing/package automation
## Current Sources
- `docs/product/vision.md`
- `docs/product/glossary.md`
- `docs/constraints.md`
- `docs/FEATURES/organizations.md`

View File

@@ -25,6 +25,7 @@ This folder contains the project documentation used to guide product, implementa
- [product/vision.md](/home/jbourdon/repos/social-media/docs/product/vision.md): product intent, users, scope, and priorities.
- [product/glossary.md](/home/jbourdon/repos/social-media/docs/product/glossary.md): canonical domain vocabulary.
- [constraints.md](/home/jbourdon/repos/social-media/docs/constraints.md): business and technical invariants.
- [FEATURES/organizations.md](/home/jbourdon/repos/social-media/docs/FEATURES/organizations.md): organization account boundary, membership, billing, connectors, and workspace ownership.
- [BACKLOG.md](/home/jbourdon/repos/social-media/docs/BACKLOG.md): deferred technical and product work.
## Archived

View File

@@ -0,0 +1,27 @@
# Task: Extract content detail approval stepper
## Feature
`docs/FEATURES/approval-workflow.md`
## Goal
Move the approval area in `ContentItemDetailView` into a small feature-owned component that can show approval requests and multi-level workflow steps as a vertical stepper.
## Scope
- Extract the approval panel from `frontend/src/features/content/views/ContentItemDetailView.vue`.
- Render approval requests or workflow steps as circles in a vertical column connected by a dashed line.
- Show approval state, expected approver, due date, and recorded decisions in a hover/focus popup.
- Remove manual approval request creation from the content detail UI and backend API.
- Record the single documented v1 approval decision directly as `Approved`; approval discussion belongs in the content comments thread.
- Align the backend submit-decision request so approval comments are not accepted on new decisions.
- Remove temporary test text from content views.
## Validation Commands
```bash
dotnet build backend/Socialize.slnx
dotnet test backend/Socialize.slnx
cd frontend && npm run build
```

View File

@@ -0,0 +1,65 @@
# 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 name, slug/display identity, timestamps, and basic audit fields matching local conventions.
- Require every workspace to belong to exactly one organization.
- Update workspace create/list/detail APIs to include organization ownership.
- Add APIs for current user organization list and organization detail.
- 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.
- 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.
- Existing development data may be wiped; do not spend scope on compatibility migration behavior.
## 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
- [ ] 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
```bash
dotnet build backend/Socialize.slnx
dotnet test backend/Socialize.slnx
./scripts/update-openapi.sh
```

View File

@@ -0,0 +1,62 @@
# Task: Organization membership and inherited permissions
## Feature
`docs/FEATURES/organizations.md`
## Goal
Model organization-level memberships and inherited workspace permissions with workspace-level overrides.
## Context
Users have global accounts. A user can have rights in multiple organizations and direct access to individual workspaces. Organization membership grants company-level access and inherited workspace permissions. Workspace membership can grant direct access or override workspace-specific inherited permissions.
## Scope
- Add organization membership persistence.
- Add organization-level roles or permissions for:
- organization owner/admin
- organization member management
- workspace creation/administration
- billing manager
- connector manager
- Define how organization permissions map to inherited workspace permissions.
- Preserve workspace participant relationship categories: `Organization Member` and `External Collaborator`.
- Allow workspace memberships to override applicable inherited workspace permissions.
- Ensure billing and connector permissions remain organization-level only.
- Update access checks used by workspace APIs to consider inherited organization permissions.
- Add tests for inherited access, direct workspace access, external collaborator access, and override behavior.
## Constraints
- Do not implement billing pages or billing provider integration in this task.
- Do not implement connector APIs in this task.
- Do not remove direct workspace membership support.
- External collaborators must not become organization members automatically.
- Keep permission names explicit; avoid magic strings where local patterns provide constants.
## Likely Files
- `backend/src/Socialize.Api/Modules/Organizations/**`
- `backend/src/Socialize.Api/Modules/Workspaces/**`
- `backend/src/Socialize.Api/Modules/Identity/**`
- `backend/src/Socialize.Api/Data/AppDbContext.cs`
- `backend/tests/Socialize.Tests/**`
## Done When
- [ ] Organization memberships are persisted.
- [ ] Organization roles/permissions include billing manager.
- [ ] Organization-level access can grant inherited access to owned workspaces.
- [ ] Direct workspace-only external collaborators remain supported.
- [ ] Workspace-level overrides apply to workspace-specific permissions.
- [ ] Billing and connector permissions cannot be granted through workspace overrides.
- [ ] Backend tests cover inherited, direct, external collaborator, and override access paths.
## Validation Commands
```bash
dotnet build backend/Socialize.slnx
dotnet test backend/Socialize.slnx
```

View File

@@ -0,0 +1,65 @@
# Task: Organization settings UI shell
## Feature
`docs/FEATURES/organizations.md`
## Goal
Add an organization-level settings page with sections for profile, members, billing access, connections, and owned workspaces.
## Context
Workspace screens remain the primary working context. Organization SaaS account administration lives under one explicit settings route: `/app/organizations/:organizationId/settings`.
## Scope
- Add the organization settings route:
- `/app/organizations/:organizationId/settings`
- Add feature-owned frontend code under `frontend/src/features/organizations/`.
- Load organization details from the backend.
- Show a settings page with sections for:
- profile/settings
- members and their roles/permissions
- billing
- connections
- owned workspaces
- Show the billing section only to users with billing manager permission.
- Show the connections section only to users with connector manager permission.
- Show the owned workspaces section to users with organization workspace administration access.
- Add English and French locale strings.
## Constraints
- Do not implement billing provider integration in this task.
- Do not implement real connection authorization flows in this task.
- Do not replace the existing workspace selector in this task.
- Frontend runtime config must flow through `frontend/src/config.js` if new runtime config is needed.
- Use the shared Axios API client in `frontend/src/plugins/api.js`.
## Likely Files
- `frontend/src/router/router.js`
- `frontend/src/features/organizations/**`
- `frontend/src/layouts/main/**`
- `frontend/src/locales/en.json`
- `frontend/src/locales/fr.json`
## Done When
- [ ] Organization settings route exists.
- [ ] Organization details load for accessible organizations.
- [ ] Organization settings page has sections for profile, members, billing, connections, and workspaces.
- [ ] Organization members are visible to permitted users.
- [ ] Billing section is permission-gated to billing managers.
- [ ] Connections section is permission-gated to connector managers.
- [ ] Owned workspaces section is visible to permitted organization users.
- [ ] UI strings exist in English and French.
- [ ] Frontend build passes.
## Validation Commands
```bash
cd frontend
npm run build
```

View File

@@ -0,0 +1,57 @@
# Task: Workspace selector organization switcher
## Feature
`docs/FEATURES/organizations.md`
## Goal
Keep the existing workspace selector as the primary context selector and add an organization switcher at the bottom.
## Context
The current workspace selector UX is good. The missing concept is that workspaces belong to organizations. Users may have access to multiple organizations and different workspaces under each one.
## Scope
- Load the current user's accessible organizations.
- Show the current organization at the bottom of the existing workspace selector.
- Allow users to switch organizations.
- Scope or group listed workspaces by the selected organization.
- Preserve current workspace selection behavior where possible.
- When switching organizations, select a sensible workspace for that organization or route to an organization/workspace selection state.
- Provide links from the organization switcher to organization settings routes when the user has access.
- Add English and French locale strings.
## Constraints
- Do not redesign the authenticated app shell.
- Do not turn the selector into a marketing or onboarding page.
- Preserve workspace as the primary day-to-day app context.
- Preserve route-level auth and role checks.
## Likely Files
- `frontend/src/layouts/main/**`
- `frontend/src/features/workspaces/**`
- `frontend/src/features/organizations/**`
- `frontend/src/stores/**`
- `frontend/src/locales/en.json`
- `frontend/src/locales/fr.json`
## Done When
- [ ] Workspace selector shows the active organization.
- [ ] Users can switch organizations from the selector.
- [ ] Workspace list reflects the selected organization.
- [ ] Organization settings links appear only when permitted.
- [ ] Existing workspace switching behavior remains usable.
- [ ] UI strings exist in English and French.
- [ ] Frontend build passes.
## Validation Commands
```bash
cd frontend
npm run build
```

View File

@@ -11,9 +11,14 @@ These are cross-cutting rules for the current product and codebase. They are int
## Domain Constraints
- `Workspace` is the top-level scoping boundary.
- An agency may manage multiple workspaces.
- `Organization` is the SaaS account, billing, subscription, connector, and workspace ownership boundary.
- `Workspace` is the brand/client workflow boundary.
- A workspace belongs to exactly one organization and is not shared between organizations.
- `ContentItem` belongs to a workspace scope.
- Channels are configured inside a workspace.
- Organization-level membership can grant inherited access to all workspaces owned by the organization.
- Workspace-level membership can grant direct workspace access and override applicable inherited workspace permissions.
- `External Collaborator` workspace participants can have workspace access without organization membership.
- Comments, approvals, assets, and notifications must remain traceable to the underlying workflow entity they relate to.
## Backend Constraints

View File

@@ -2,28 +2,67 @@
Use these terms consistently in product docs, specs, UI copy, and code discussions.
## Workspace
## Organization
Top-level working container for a client account.
SaaS account boundary that owns billing, subscription, limits, organization-level users, connectors, data mappings, and workspaces.
An agency may manage multiple workspaces.
An organization may be an agency, an in-house brand company, or a professional's business account.
Use:
- ownership boundary
- membership boundary
- scoping boundary for content items, assets, comments, approvals, and notifications
- billing and subscription boundary
- ownership boundary for workspaces
- connector and integration configuration boundary
- organization-level membership and permission boundary
Do not use as:
- synonym for a brand workspace
- synonym for a single human user account
- synonym for an external reviewer
## Workspace
Brand, client, or operating workspace where content workflow happens.
Each workspace belongs to exactly one organization and is not shared between organizations.
Use:
- brand/client workflow boundary
- scoping boundary for content items, assets, comments, approvals, and notifications
- channel configuration boundary
Do not use as:
- top-level SaaS account boundary
- billing or subscription boundary
- synonym for internal role
- synonym for team member role
## Organization Member
User access relationship at the organization level.
Organization membership can grant organization-level permissions and inherited access to all workspaces owned by that organization.
## Workspace Member
User access relationship at the workspace level.
Workspace membership grants direct access to one workspace and can classify the user's relationship to the owning organization as `Organization Member` or `External Collaborator`.
An `Organization Member` is part of the organization that owns the workspace. They may have access through organization membership, direct workspace membership, or both.
An `External Collaborator` is not part of the owning organization but has direct workspace access. This includes subcontractors, providers, clients, and external reviewers.
Workspace membership can override applicable inherited workspace permissions.
## Agency
Operating organization managing one or more workspaces.
Type of organization that manages one or more brand/client workspaces for customers.
An agency is above the workspace level in the business model.
Use `Organization` for the product model unless specifically describing an agency customer.
## Client
@@ -106,6 +145,8 @@ Examples:
Specific destination, account, handle, page, or feed within a network.
Channels are configured inside a workspace. The connector or integration credentials used to access external systems are owned by the organization.
Examples:
- `@MyBrand` on Instagram

View File

@@ -8,7 +8,7 @@ Active
`Socialize` is a workflow application for social media content review, revision, approval, and publication readiness.
It is not a public social network. It is a workspace-based coordination tool for internal teams, providers, and client approvers.
It is not a public social network. It is an organization-owned, workspace-based coordination tool for internal teams, providers, and client approvers.
## Problem
@@ -38,8 +38,11 @@ Provide one system of workflow for drafting, revising, reviewing, approving, and
## Core Product Shape
- workspace-based account boundary
- agencies able to manage multiple workspaces
- organizations as the SaaS account, billing, subscription, and connector boundary
- workspaces as brand/client workflow boundaries owned by one organization
- agencies, in-house teams, and professional businesses able to manage multiple workspaces
- organization members able to inherit access across owned workspaces
- external collaborators able to access specific workspaces without organization membership
- content items as the main reviewable unit
- assets and revisions tracked against content items
- comments and approvals attached to the work itself
@@ -60,7 +63,7 @@ Provide one system of workflow for drafting, revising, reviewing, approving, and
- not a full publishing engine in version 1
- not a full DAM platform in version 1
- not a full analytics product in version 1
- not a billing/subscription product in version 1
- not a full billing provider or pricing/package automation product in version 1
## MVP Scope
@@ -86,7 +89,7 @@ Version 1 should focus on approval workflow rather than direct publishing.
- direct social publishing
- advanced third-party synchronization
- analytics suite
- customer billing flows
- full customer billing provider integration and pricing/package automation
## Current Strategic Assumptions