.agents/features/ee-projects.md
The EE Projects module adds team collaboration, role-based access control (RBAC), git-based environment sync, and per-project piece filtering on top of the base project entity. It introduces project membership (invitations, roles), custom project roles with fine-grained permissions, project releases for deploying flows between environments, and a git sync mechanism for version-controlling flow definitions in an external repository.
packages/server/api/src/app/ee/projects/ — platform project service, RBAC enforcementpackages/server/api/src/app/ee/project-members/ — member CRUD, role lookuppackages/server/api/src/app/ee/project-role/ — default and custom role managementpackages/server/api/src/app/ee/project-release/ — release creation, diff, applypackages/server/api/src/app/ee/git-sync/ — SSH repo push/pullpackages/shared/src/lib/ee/project-members/project-member.ts — ProjectMember typepackages/shared/src/lib/ee/project-members/project-member-request.ts — list/update request DTOspackages/shared/src/lib/automation/project-release/project-release.ts — ProjectRelease typepackages/shared/src/lib/automation/project-release/project-release.request.ts — release request DTOspackages/shared/src/lib/automation/project-release/project-state.ts — ProjectSyncPlanpackages/web/src/features/members/api/project-members-api.ts — projectMembersApipackages/web/src/features/members/hooks/project-members-hooks.ts — projectMembersHookspackages/web/src/features/members/hooks/user-invitations-hooks.ts — userInvitationsHookspackages/web/src/features/members/components/ — InviteUserDialog, EditRoleDialog, ProjectMemberCard, InvitationCardpackages/web/src/features/project-releases/api/project-release-api.ts — projectReleaseApipackages/web/src/features/project-releases/api/git-sync-api.ts — gitSyncApipackages/web/src/features/project-releases/hooks/project-release-hooks.ts — projectReleaseQueriespackages/web/src/features/project-releases/hooks/git-sync-hooks.ts — gitSyncHookspackages/web/src/app/components/project-settings/members/index.tsx — MembersSettings componentpackages/web/src/app/routes/project-release/index.tsx — ProjectReleasesPageprojectRolesEnabled and environmentsEnabled plan flags.customRolesEnabled. Git sync and releases behind environmentsEnabled.READ_FLOW, WRITE_CONNECTION).rbacService.assertPrincipalAccessToProject().Entity: id, projectId, userId, projectRoleId, platformId. Unique on (projectId, userId, platformId).
Service methods:
upsert({ userId, projectId, projectRoleName }) — create/update member with role lookuplist({ platformId, projectId?, projectRoleId? }) — paginated with user detailsgetRole({ userId, projectId }) — returns role (ADMIN if owner/platform admin)update({ id, projectId, platformId, role }) — change member's roledelete(projectId, memberId) — remove from projectgetIdsOfProjects({ userId, platformId }) — all project IDs user belongs toFrontend: projectMembersApi.list/update/delete backed by projectMembersHooks.useProjectMembers(). MembersSettings component shows combined table of active members, platform admins/operators, and pending invitations.
Entity: id, name, permissions[] (string array), platformId (nullable), type (DEFAULT/CUSTOM).
Default roles (type=DEFAULT, platformId=null):
Custom roles: Platform-scoped, created by platform admins with any combination of 26 permissions.
rbacService.assertPrincipalAccessToProject() routes by principal type:
principal.projectId === requestedProjectIdproject.platformId === principal.platform.idEntity: id, projectId, name, description, importedBy (FK user), fileId (FK), type (GIT_BRANCH/MANUAL/ROLLBACK).
Release workflow:
releasePlan() — compute diff (what flows/tables/connections would change)create() — apply diffs, serialize project state to File, record releaseFrontend: projectReleaseApi.diff() previews changes before commit. ApplyButton triggers create. ProjectReleasesPage lists history with rollback action per row.
Git sync (git-sync/):
Entity: id, projectId (one-to-one), name, pieces[] (string array), piecesFilterType (NONE/ALLOWED), locked (boolean).
NONE: All pieces availableALLOWED: Only pieces in pieces[] array visibleFilteredPieceBehavior.ALLOWED/BLOCKED) applied first, then project-levelplatformProjectService.getForPlatform() — lists projects with access control: