Skip to main content

ProjectMember Model Documentation

Overview​

The ProjectMember model manages team membership and permissions within projects in CODITECT. It defines role-based access control at the project level, tracking who belongs to each project, their roles, and their specific permissions. This model enables fine-grained access control while maintaining a clear audit trail of membership changes.

Model Structure​

Core Fields​

FieldTypeDescriptionConstraints
tenant_idUUIDAssociated tenantForeign key to Tenant
project_idUUIDProject identifierForeign key to Project
member_idUUIDTeam memberForeign key to Member
roleProjectRole (Enum)Member's project roleRequired
joined_atDateTimeWhen member joinedAuto-set to current time
permissionsVecGranted permissionsAuto-set based on role
added_byUUIDWho added this memberForeign key to User

ProjectRole Enum​

enum ProjectRole {
Owner, // Full control, can delete project
Admin, // Manage project and members
Developer, // Create and manage tasks
Viewer, // Read-only access
Tester, // QA and testing role
Designer // Design team member
}

Permission Enum​

enum Permission {
// Task permissions
CreateTask, // Create new tasks
UpdateTask, // Modify existing tasks
DeleteTask, // Remove tasks
AssignTask, // Assign tasks to members

// Project permissions
UpdateProject, // Modify project settings
DeleteProject, // Delete entire project
AddMembers, // Invite new members
RemoveMembers, // Remove members

// View permissions
ViewTasks, // See all tasks
ViewMembers, // See team roster
ViewReports // Access analytics
}

Role-Based Permissions​

Permission Matrix​

RoleCreate TaskUpdate TaskDelete TaskAssign TaskUpdate ProjectDelete ProjectAdd MembersRemove MembersView All
Owner✓✓✓✓✓✓✓✓✓
Admin✓✓✓✓✓✗✓✓✓
Developer✓✓✗✓✗✗✗✗✓
Tester✓✓✗✗✗✗✗✗✓
Designer✓✓✗✗✗✗✗✗✓
Viewer✗✗✗✗✗✗✗✗✓

Default Permissions by Role​

Owner (11 permissions)​

All permissions - complete project control

Admin (10 permissions)​

All permissions except DeleteProject

Developer (6 permissions)​

  • CreateTask, UpdateTask, AssignTask
  • ViewTasks, ViewMembers, ViewReports

Tester/Designer (5 permissions)​

  • CreateTask, UpdateTask
  • ViewTasks, ViewMembers, ViewReports

Viewer (3 permissions)​

  • ViewTasks, ViewMembers, ViewReports

Example Records​

Project Owner​

{
"tenant_id": "123e4567-e89b-12d3-a456-426614174000",
"project_id": "456e7890-e89b-12d3-a456-426614174000",
"member_id": "789e0123-e89b-12d3-a456-426614174000",
"role": "Owner",
"joined_at": "2025-01-15T10:00:00Z",
"permissions": [
"CreateTask", "UpdateTask", "DeleteTask", "AssignTask",
"UpdateProject", "DeleteProject", "AddMembers", "RemoveMembers",
"ViewTasks", "ViewMembers", "ViewReports"
],
"added_by": "789e0123-e89b-12d3-a456-426614174000"
}

Team Developer​

{
"tenant_id": "123e4567-e89b-12d3-a456-426614174000",
"project_id": "456e7890-e89b-12d3-a456-426614174000",
"member_id": "890e1234-e89b-12d3-a456-426614174000",
"role": "Developer",
"joined_at": "2025-03-01T14:30:00Z",
"permissions": [
"CreateTask", "UpdateTask", "AssignTask",
"ViewTasks", "ViewMembers", "ViewReports"
],
"added_by": "789e0123-e89b-12d3-a456-426614174000"
}

External Reviewer​

{
"tenant_id": "123e4567-e89b-12d3-a456-426614174000",
"project_id": "456e7890-e89b-12d3-a456-426614174000",
"member_id": "901e2345-e89b-12d3-a456-426614174000",
"role": "Viewer",
"joined_at": "2025-08-15T09:00:00Z",
"permissions": ["ViewTasks", "ViewMembers", "ViewReports"],
"added_by": "890e1234-e89b-12d3-a456-426614174000"
}

Database Schema​

Primary Storage Pattern​

Key: /{tenant_id}/project_members/{project_id}/{member_id}
Value: JSON serialized ProjectMember object

Secondary Indexes​

# Members by project
/{tenant_id}/members_by_project/{project_id} -> [member_ids]

# Projects by member
/{tenant_id}/projects_by_member/{member_id} -> [project_ids]

# Members by role
/{tenant_id}/project_members_by_role/{project_id}/{role} -> [member_ids]

# Recent additions
/{tenant_id}/recent_project_members/{YYYY-MM-DD} -> [(project_id, member_id)]

Source Files​

  • Model: /src/models/project_member.rs
  • Repository: /src/db/repositories/project_member_repository.rs
  • Service: /src/services/project_membership_service.rs
  • API Handler: /src/api/handlers/project_member_handlers.rs
  • Tests: /src/models/tests/project_member_tests.rs

Key Methods​

impl ProjectMember {
fn new(
tenant_id: Uuid,
project_id: Uuid,
member_id: Uuid,
role: ProjectRole,
added_by: Uuid
) -> Self

fn permissions_for_role(role: &ProjectRole) -> Vec<Permission>
fn has_permission(&self, permission: &Permission) -> bool
fn can_assign_tasks(&self) -> bool
fn can_manage_members(&self) -> bool
}

impl ProjectMemberRepository {
async fn add_member(&self, member: &ProjectMember) -> Result<()>
async fn remove_member(&self, tenant_id: &Uuid, project_id: &Uuid, member_id: &Uuid) -> Result<()>
async fn update_role(&self, tenant_id: &Uuid, project_id: &Uuid, member_id: &Uuid, role: ProjectRole) -> Result<()>
async fn get_project_members(&self, tenant_id: &Uuid, project_id: &Uuid) -> Result<Vec<ProjectMember>>
async fn get_member_projects(&self, tenant_id: &Uuid, member_id: &Uuid) -> Result<Vec<ProjectMember>>
}

API Endpoints​

Member Management​

  • POST /api/projects/{project_id}/members - Add member
  • GET /api/projects/{project_id}/members - List members
  • PUT /api/projects/{project_id}/members/{member_id} - Update role
  • DELETE /api/projects/{project_id}/members/{member_id} - Remove member

Member Queries​

  • GET /api/members/{member_id}/projects - Member's projects
  • GET /api/projects/{project_id}/members/by-role/{role} - Members by role
  • GET /api/projects/{project_id}/members/{member_id}/permissions - Check permissions

Bulk Operations​

  • POST /api/projects/{project_id}/members/bulk-add - Add multiple members
  • POST /api/projects/{project_id}/members/bulk-update - Update multiple roles

Business Rules​

Membership Rules​

  1. One Owner Required: Every project must have at least one owner
  2. Owner Transfer: Last owner cannot leave without transferring ownership
  3. Unique Membership: One member can have only one role per project
  4. Self-Service: Members cannot change their own role (except owners)
  5. Cascade Delete: Deleting member removes from all projects

Permission Hierarchy​

  1. Role-Based: Permissions derived from role
  2. No Override: Cannot grant permissions beyond role
  3. Immediate Effect: Permission changes apply immediately
  4. No Inheritance: Parent project permissions don't cascade

Access Control​

// Only admins and owners can manage members
async fn can_manage_members(
actor_id: Uuid,
project_id: Uuid
) -> Result<bool> {
let membership = get_project_member(project_id, actor_id).await?;
Ok(membership.can_manage_members())
}

// Members can only update tasks they created or are assigned
async fn can_update_task(
member_id: Uuid,
task: &Task
) -> Result<bool> {
let membership = get_project_member(task.project_id, member_id).await?;

if !membership.has_permission(&Permission::UpdateTask) {
return Ok(false);
}

// Additional business logic
Ok(task.creator_id == member_id || task.assignee_id == Some(member_id))
}

Use Cases​

Project Creation​

// Creator automatically becomes owner
let owner_membership = ProjectMember::new(
tenant_id,
new_project_id,
creator_id,
ProjectRole::Owner,
creator_id // self-added
);

Team Onboarding​

// Batch add new team members
let new_members = vec![
(dev1_id, ProjectRole::Developer),
(dev2_id, ProjectRole::Developer),
(qa_id, ProjectRole::Tester),
(designer_id, ProjectRole::Designer),
];

for (member_id, role) in new_members {
let membership = ProjectMember::new(
tenant_id,
project_id,
member_id,
role,
admin_id
);
member_service.add_member(membership).await?;
}

Role Promotion​

// Promote developer to admin
member_service
.update_member_role(
project_id,
developer_id,
ProjectRole::Admin,
promoted_by_id
)
.await?;

Integration Points​

With Member Model​

  • Member availability affects assignment
  • Member skills influence role assignment
  • Member status affects project access

With Project Model​

  • Project status affects member operations
  • Project deletion removes all memberships
  • Project visibility based on membership

With Task Model​

  • Task assignment limited to project members
  • Task visibility based on membership
  • Task permissions derived from project role

Workflows​

Adding Members​

1. Check actor has AddMembers permission
2. Verify member exists and is active
3. Check member not already in project
4. Create ProjectMember record
5. Send notification to new member
6. Log addition in audit trail

Changing Roles​

1. Verify actor can manage members
2. Check target member exists in project
3. Validate new role assignment
4. Update member record
5. Refresh member's permissions
6. Notify member of change

Removing Members​

1. Check actor has RemoveMembers permission
2. Verify not removing last owner
3. Reassign member's tasks (optional)
4. Remove member record
5. Revoke project access
6. Log removal event

Security Considerations​

Permission Checks​

  • Always verify membership before granting access
  • Check specific permissions, not just role
  • Cache permissions for performance
  • Invalidate cache on role change

Audit Requirements​

  • Log all membership changes
  • Track who added/removed members
  • Record permission usage
  • Monitor unusual access patterns

Data Protection​

  • Members see only assigned tasks by default
  • Sensitive project data requires explicit permission
  • Personal member data protected
  • Cross-project isolation enforced

Performance Optimization​

Caching Strategy​

struct MembershipCache {
// Cache member's project list
member_projects: HashMap<Uuid, Vec<ProjectSummary>>,

// Cache project's member list
project_members: HashMap<Uuid, Vec<MemberSummary>>,

// Cache permission lookups
permission_cache: HashMap<(Uuid, Uuid), Vec<Permission>>,

// TTL: 5 minutes
ttl: Duration
}

Query Patterns​

  • Batch load project members
  • Denormalize member count on project
  • Index frequently queried combinations
  • Preload permissions for requests

Best Practices​

Role Assignment​

  1. Start with least privilege (Viewer)
  2. Promote based on demonstrated need
  3. Regular role reviews
  4. Document role changes
  5. Automate common patterns

Team Management​

  1. Onboard teams in batches
  2. Use templates for standard teams
  3. Regular membership audits
  4. Clear ownership succession
  5. Archive inactive memberships

Future Enhancements​

Advanced Features​

  1. Custom Roles: Project-specific role definitions
  2. Permission Sets: Reusable permission groups
  3. Temporary Access: Time-bound memberships
  4. Role Templates: Standard team structures

Automation​

  1. Auto-assignment: Based on skills/availability
  2. Role Suggestions: ML-based recommendations
  3. Access Reviews: Periodic membership audits
  4. Succession Planning: Automatic owner transfer

Integration Features​

  1. Team Sync: Import from HR systems
  2. SSO Groups: Map external groups to roles
  3. Approval Workflows: Multi-step member addition
  4. Cross-Project Teams: Shared team definitions

Analytics​

  1. Team Velocity: Performance by role mix
  2. Permission Usage: Actual vs granted
  3. Collaboration Patterns: Member interactions
  4. Optimal Team Size: Data-driven recommendations

Last Updated: 2025-08-29 Version: 1.0