Organizations & Workspaces
Workspace types
AMS has two concrete workspace types, both extending the base Workspace class using JPA InheritanceType.JOINED:
| Type | Table | Who owns it | Created when |
|---|---|---|---|
OrgWorkspace | org_workspace | An Organization | Org is created (default) or manually added |
UserWorkspace | user_workspace | A User | User first signs in (auto-created) |
Never instantiate the base Workspace class. Always use OrgWorkspace or UserWorkspace. When querying workspace-subclass-specific fields in JPQL, target the subclass directly: SELECT w FROM OrgWorkspace w WHERE w.orgId = :orgId.
Organization workspace lifecycle
When an organization is created:
- A default
OrgWorkspaceis created - A default team is created in that workspace
- An
OrgPublicProfileis immediately created in synced mode (copy of private profile) - The creator is added as OWNER member of the default team
Public org profile
Every OrgWorkspace has exactly one OrgPublicProfile. This is the client-facing view of the organization.
Sync behaviour
| Mode | Behaviour |
|---|---|
synced = true (default) | Public profile mirrors private OrganizationProfile + addresses. Auto-updated whenever private profile is saved. |
synced = false | Independently managed. Private org profile changes do NOT affect the public profile. |
GraphQL mutations:
syncOrgPublicProfile(workspaceId)— copies private → public, setssynced = trueupdateOrgPublicProfile(workspaceId, input)— saves custom data, setssynced = false
OrgPublicProfileAddress records are independent copies — editing them does not touch OrganizationAddress.
There must never be an OrgWorkspace without an OrgPublicProfile. Always create one via OrgPublicProfileService.sync() immediately when creating an OrgWorkspace.
Clients
Clients are external applicants assigned directly to an organization (client.orgId FK → Organization). They are not scoped to a specific workspace.
- A
Clientlinks aUserto anOrganization - Clients are queried org-wide:
clients(orgId: ID),clientInvitations(orgId: ID) - When a client participates in an application, they appear as an
Applicantrecord on that application - Workspace-level permission checks for clients are resolved via a join:
JOIN org_workspace ow ON ow.org_id = c.org_id WHERE ow.id = :workspaceId
Teams & members
Teams are org-scoped and assigned to workspaces via TeamWorkspaceAssignment. Teams organize staff users.
- Team slug must be unique within the org
- Member links a
Userto aTeamwith aMemberRole - Creator of a team is automatically added as OWNER
Default teams
| Team | Purpose |
|---|---|
| Default team | All regular team members |
Personal workspace
Every user has exactly one UserWorkspace, created automatically on first login. It provides:
- Personal dashboard
- Personal applications list
- User settings (profile, account, appearance, notifications, addresses)
- Organizations list
URL structure
Personal workspace:
/p/$userSlug/applications/
/p/$userSlug/settings/...
Org management (not workspace-specific):
/o/$orgSlug/teams/
/o/$orgSlug/users/
/o/$orgSlug/clients/
/o/$orgSlug/partners/
/o/$orgSlug/settings/...
/o/$orgSlug/workspaces/
Workspace work (workspace-specific):
/o/$orgSlug/w/$workspaceSlug/dashboard/
/o/$orgSlug/w/$workspaceSlug/applications/
/o/$orgSlug/w/$workspaceSlug/applications/$id/
/o/$orgSlug/w/$workspaceSlug/messages/
/o/$orgSlug/w/$workspaceSlug/application-setup/documents/
/o/$orgSlug/w/$workspaceSlug/application-setup/templates/
/o/$orgSlug/w/$workspaceSlug/application-setup/permissions/
Org-management routes (/o/$orgSlug/...) handle resources that belong to the org as a whole — teams, clients, partners, settings. Workspace-specific work routes nest under /o/$orgSlug/w/$workspaceSlug/ and carry both the org and workspace context in the URL.