Teams & Permissions
Ebla supports team-based collaboration with fine-grained access controls. Share libraries with team members while maintaining control over who can read, write, or administer content.
Teams
Creating a Team
# Create a new team
$ ebla team create "Engineering"
Team created successfully
ID: team_abc123
Name: Engineering
Owner: you@example.com
Members: 1
Libraries: 0
# With description
$ ebla team create "Engineering" --description "Core engineering team"
Team Roles
Each team member has a role that determines their permissions:
| Role | Manage Members | Manage Libraries | Write Files | Read Files |
|---|---|---|---|---|
| Owner | Yes | Yes | Yes | Yes |
| Admin | Yes | Yes | Yes | Yes |
| Member | No | Yes | Yes | Yes |
| Viewer | No | No | No | Yes |
Inviting Members
# Invite by email
$ ebla team invite team_abc123 alice@example.com
Invitation sent to alice@example.com
# Invite with specific role
$ ebla team invite team_abc123 bob@example.com --role admin
# List pending invitations
$ ebla team invitations team_abc123
EMAIL ROLE SENT EXPIRES
alice@example.com member 2 hours ago in 5 days
bob@example.com admin 5 minutes ago in 7 days
# Revoke invitation
$ ebla team revoke-invite team_abc123 alice@example.com
Accepting Invitations
# Accept via token (from email link)
$ ebla team accept abc123-invitation-token
Joined team "Engineering" as member
Managing Members
# List team members
$ ebla team members list team_abc123
USER ROLE JOINED
you@example.com owner 2026-01-01
alice@example.com member 2026-01-15
bob@example.com admin 2026-01-15
# Change member role
$ ebla team members role team_abc123 alice@example.com --role admin
# Remove member
$ ebla team members remove team_abc123 alice@example.com
Transferring Ownership
# Transfer team ownership to another member
$ ebla team transfer team_abc123 alice@example.com
Are you sure you want to transfer ownership of "Engineering" to alice@example.com?
This action cannot be undone. [y/N]: y
Ownership transferred. You are now an admin of this team.
Library Sharing
Personal vs Team Libraries
- Personal Libraries: Owned by a single user, can be shared via ACLs
- Team Libraries: Owned by a team, all members get default access based on role
Creating a Team Library
# Create library owned by team
$ ebla library create "Shared Documents" --team team_abc123
Library created successfully
ID: lib_xyz789
Name: Shared Documents
Team: Engineering
Access: All team members (based on role)
Assigning Personal Library to Team
# Move personal library to team
$ ebla library assign lib_xyz789 --team team_abc123
Library "My Documents" is now owned by team "Engineering"
Viewing Team Libraries
# List team's libraries
$ ebla team libraries team_abc123
ID NAME FILES SIZE ACCESS
lib_001 Shared Documents 1,234 5.2 GB team
lib_002 Code Repo 456 128 MB team
lib_003 Design Assets 89 2.1 GB team (read-only)
Access Control Lists (ACLs)
Permission Levels
Fine-grained control over library access:
| Level | View | Download | Sync/Write | Manage ACLs |
|---|---|---|---|---|
| Admin | Yes | Yes | Yes | Yes |
| Write | Yes | Yes | Yes | No |
| Read | Yes | Yes | No | No |
| None | No | No | No | No |
Setting ACLs via API
# Grant user access
curl -X POST http://server:6333/api/v1/libraries/lib_xyz789/acls \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"subject_type": "user",
"subject_id": "usr_alice123",
"permission": "write"
}'
# Grant role-based access (all team admins)
curl -X POST http://server:6333/api/v1/libraries/lib_xyz789/acls \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"subject_type": "role",
"subject_id": "team_abc123:admin",
"permission": "admin"
}'
Permission Precedence
When multiple rules apply, the most specific wins:
- User ACL - Direct user permission
- Role ACL - Permission based on team role
- Team Owner - Owners always have admin
- Library Owner - Original creator has admin
Permission Tracing
Understand why a user has access:
# API: Explain user's effective permission
curl "http://server:6333/admin/api/permissions/explain?library_id=lib_xyz&user_id=usr_alice" \
-H "Authorization: Bearer $TOKEN"
{
"user": "alice@example.com",
"library": "Shared Documents",
"effective_permission": "write",
"sources": [
{
"type": "role_acl",
"role": "member",
"team": "Engineering",
"permission": "write"
}
]
}
Link Sharing
Internal Share Links
Share files with other Ebla users via secure links:
# Create share link (requires login)
POST /api/v1/libraries/:id/shares
{
"path": "documents/report.pdf",
"permission": "view", // view or download
"expires_in": "7d" // 1d, 7d, 30d, or never
}
# Response
{
"token": "abc123xyz",
"url": "https://server:6333/s/abc123xyz",
"expires_at": "2026-01-22T00:00:00Z"
}
External Share Links (Enterprise)
Share with anyone, even without an account:
# Create public share link
POST /api/v1/libraries/:id/shares/external
{
"path": "documents/report.pdf",
"password": "optional-password",
"one_time": false,
"max_downloads": 10,
"expires_in": "7d",
"allowed_emails": ["client@example.com"], // optional restriction
"watermark": true // add watermark to previews
}
# Response
{
"token": "pub_xyz789",
"url": "https://server:6333/p/pub_xyz789",
"password_protected": true,
"expires_at": "2026-01-22T00:00:00Z"
}
Share Analytics
# View share analytics
GET /api/v1/shares/:token/analytics
{
"views": 15,
"downloads": 3,
"unique_visitors": 8,
"access_log": [
{
"timestamp": "2026-01-15T10:30:00Z",
"action": "view",
"ip": "203.0.113.45",
"user_agent": "Chrome/120"
}
]
}
Revoking Shares
# Revoke a share link
DELETE /api/v1/shares/:token
# Link immediately stops working
Audit Logging
What's Logged
All team actions are recorded for compliance:
- Member additions and removals
- Role changes
- Library permission changes
- Ownership transfers
- Share link creation and revocation
- File access via share links
Viewing Audit Logs
# CLI: View team audit log
$ ebla team audit team_abc123
TIMESTAMP USER ACTION DETAILS
2026-01-15 10:30 you@example.com member_added alice@example.com (member)
2026-01-15 10:35 you@example.com role_changed alice@example.com → admin
2026-01-15 11:00 alice@example.com library_created "Shared Documents"
2026-01-15 11:05 alice@example.com acl_added bob@example.com → write
# Filter by time range
$ ebla team audit team_abc123 --since 24h
$ ebla team audit team_abc123 --since 2026-01-01 --until 2026-01-15
# Filter by user
$ ebla team audit team_abc123 --user alice@example.com
Admin UI Audit Log
The admin dashboard provides a rich audit log interface:
- Time Range Filters: 1h, 24h, 7d, 30d, or custom date picker
- User Filter: Filter by specific user
- Event Type Filter: Member, library, permission events
- Severity Filter: Info, warning, critical
- IP Address Filter: Track access by IP
- Search: Full-text search across events
- Export: Download as CSV or JSON
Access at: http://your-server:6333/admin/audit
Admin UI for Permissions
ACL Editor
Manage permissions visually at /admin/permissions:
- Library Selector: Pick library with type badge (personal/team)
- Effective Access: See all users with access and their source
- Direct Access Overrides: Add/edit/remove user ACLs inline
- Role Permissions: Configure role-based access for team libraries
- Explain Modal: Click any user to see "Why does X have access?"
Add User Modal
When adding a user:
- Search for user by email
- Select permission level (3-column role cards)
- Set expiration (optional)
- Preview effective access before saving
Best Practices
Team Structure
- One team per project/department: Keeps permissions manageable
- Use roles over individual ACLs: Easier to maintain
- Limit Owners/Admins: Only trusted users should manage members
Library Organization
- Separate sensitive libraries: Don't mix public and confidential
- Use descriptive names: "2026 Q1 Reports" not "Stuff"
- Archive old libraries: Instead of deleting, restrict access
Sharing
- Set expirations: Don't create permanent share links
- Use passwords for external shares: Add a layer of protection
- Review share analytics: Monitor who's accessing shared files
- Revoke unused shares: Regularly audit and clean up