Skip to content

Conversation

migmartri
Copy link
Member

@migmartri migmartri commented Aug 11, 2025

Summary

This PR implements the requested feature to split organization leave vs organization deletion into separate processes with proper owner validation to prevent accidental organization loss.

Behavior Changes

Before

  • Leaving an organization would automatically delete it if you were the last member
  • Account deletion could accidentally delete organizations
  • No explicit organization deletion command

After

  • Organization Leave: Users can only leave if there's another owner remaining
  • Organization Deletion: Explicit action requiring owner permissions
  • Account Deletion: Blocked if user is sole owner of any organization

Key Features

Safe Organization Leave

  • Validates sole ownership before allowing leave
  • Clear error message: "cannot leave organization as the sole owner. Please add another owner or delete the organization instead"
  • Never automatically deletes organizations

Explicit Organization Deletion

  • New chainloop organization delete --name <org> CLI command
  • Requires organization owner permissions
  • Includes confirmation dialog for safety

Account Deletion Safety

  • Blocks user deletion if they are sole owner of any organization
  • Error message guides users: "cannot delete account: you are the sole owner of organizations (...). Please add other owners or delete the organizations first"

API Changes

  • Added: OrganizationService.Delete() RPC for explicit organization deletion
  • Updated: MembershipService.Leave() with owner validation (never auto-deletes)
  • Enhanced: UserService.DeleteUser() with ownership checks

Testing

  • Updated integration tests to use owner roles for proper validation
  • All existing functionality preserved with enhanced safety
  • New validation logic thoroughly tested

Files Changed

  • app/controlplane/api/controlplane/v1/organization.proto - New Delete RPC
  • app/controlplane/pkg/biz/membership.go - New Leave() function with validation
  • app/controlplane/pkg/biz/organization.go - DeleteByUser() with owner checks
  • app/controlplane/pkg/biz/user.go - Safe account deletion
  • app/cli/cmd/organization_delete.go - New delete command
  • Integration tests updated for new behavior

@migmartri migmartri requested review from javirln, jiparis and Piskoo and removed request for javirln August 11, 2025 14:15
This change separates organization leave and deletion into distinct operations with proper owner validation to prevent accidental organization loss.

- Users can only leave if there's another owner remaining
- Validates sole ownership before allowing leave
- Never automatically deletes organizations

- New explicit `chainloop organization delete` command
- Requires organization owner permissions
- Includes confirmation dialog for safety

- Blocks user deletion if they are sole owner of any organization
- Requires users to add other owners or delete orgs first
- Prevents accidental organization loss during account cleanup

- Added `OrganizationService.Delete()` RPC for explicit deletion
- Updated `MembershipService.Leave()` behavior with validation
- Removed automatic organization deletion from leave operations

- Clear error messages guide users on required actions
- Validation prevents unsafe operations
- Helpful suggestions for resolving ownership conflicts

Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
- Update user integration test to expect account deletion to be blocked when user is sole owner
- Update membership integration test to expect no cleanup when sole owner cannot leave
- Update copyright headers to 2024-2025 for modified test files
- Set proper owner roles in test setup to trigger validation logic

Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
- Split TestDeleteUser into two scenarios: blocked and allowed deletion
- Test validates that users can be deleted when they are not sole owners
- Ensures both the safety validation and normal deletion flow work correctly

Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
- Added TestLeaveHappyPath to demonstrate successful leave scenarios
- Test validates that owners can leave when other owners remain
- Test confirms that after successful leave, sole remaining owner cannot leave
- Provides clear documentation of both allowed and blocked leave operations

Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
- Format integration test files for proper Go style
- Format new CLI command and action files
- Ensure consistent code formatting across all new and modified files

Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
- Replace s.T().Run with s.Run to avoid unused testing.T parameter
- Fix unused parameter warnings in TestLeaveHappyPath test functions
- Address revive linter warnings for better code quality

Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
- Update role expectation from RoleViewer to RoleOwner in test assertion
- Fix 'no memberships' test case to work with sole owner validation
- Create proper test scenario where user can leave without being sole owner
- Use organization deletion for cleanup when user is sole owner

Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
- Format all Go code to ensure consistent formatting
- Fix any remaining formatting issues across the codebase

Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
Copy link
Member

@jiparis jiparis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thanks!

@migmartri migmartri merged commit 792dc69 into chainloop-dev:main Aug 12, 2025
13 checks passed
@migmartri migmartri deleted the 872-org-leave branch August 12, 2025 11:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants