Team Member Capabilities System
Version: 1.0
Last Updated: 2026-01-21
Purpose: Enterprise-ready role-based access control with granular capabilities
Overview
Vellocity uses a role + capability permission model for team members:
- Roles (5 total): Simple, human-understandable levels
- Capabilities (30+): Granular permissions for code/features
- Plan gating: Some capabilities require higher subscription tiers
This design provides enterprise-grade security while keeping the UX simple.
Architecture
┌─────────────────────────────────────────────────────────────────────────────┐
│ CAPABILITY RESOLUTION FLOW │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ User Request │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Super Admin? │──── Yes ────► ALLOW (bypass all checks) │
│ └───────┬───────┘ │
│ │ No │
│ ▼ │
│ ┌───────────────┐ │
│ │ Team Owner? │──── Yes ────► ALLOW (owns team = all capabilities) │
│ └───────┬───────┘ │
│ │ No │
│ ▼ │
│ ┌───────────────────┐ │
│ │ Explicitly Denied?│──── Yes ────► DENY │
│ │ (denied_capabilities) │
│ └───────┬───────────┘ │
│ │ No │
│ ▼ │
│ ┌───────────────────┐ │
│ │ Explicitly Granted│ │
│ │ OR Role Default? │──── No ────► DENY │
│ └───────┬───────────┘ │
│ │ Yes │
│ ▼ │
│ ┌───────────────────┐ │
│ │ Plan Allows │ │
│ │ Capability? │──── No ────► DENY (upgrade required) │
│ └───────┬───────────┘ │
│ │ Yes │
│ ▼ │
│ ALLOW │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Team Member Roles
| Role |
Hierarchy |
Console Access |
Default Permissions |
owner |
100 |
Yes |
All capabilities |
admin |
80 |
Yes |
All except billing management |
member |
50 |
Yes |
View all + manage content/listings/SEO |
viewer |
20 |
Yes |
View only (read-only) |
api_service |
10 |
No |
API access only |
Role Details
Owner
- Full control over team, billing, deletion
- Cannot be removed from team
- Automatically assigned to team creator
- Can assign any role to others
Admin
- Manage team members (invite, edit, remove)
- All features except billing management
- Can assign member/viewer roles
Member
- Standard work access
- Create/edit content, listings, companies
- Use AI features per plan
- No team management
Viewer
- Read-only access
- View all team resources
- Cannot create or modify anything
- Ideal for stakeholders, executives
API Service
- Programmatic access only
- No console (web UI) login
- For CI/CD, integrations, data pipelines
- Audit-friendly (named service accounts)
Capabilities Reference
Billing & Finance
| Capability |
Description |
Default Roles |
Min Plan |
manage_billing |
Change plan, payment method |
owner |
All |
view_billing |
View invoices, usage |
owner, admin, member |
All |
approve_usage |
Approve overages, PO workflow |
owner |
All |
Partner & Co-Sell
| Capability |
Description |
Default Roles |
Min Plan |
invite_partners |
Send partnership invitations |
owner, admin |
Accelerate |
manage_partners |
Manage partner relationships |
owner, admin |
Accelerate |
view_partners |
View partner data (read-only) |
owner, admin, member |
All |
manage_cosell_plans |
Create/edit co-sell plans |
owner, admin |
Accelerate |
Marketing & GTM
| Capability |
Description |
Default Roles |
Min Plan |
manage_seo |
SEO intelligence, LLM seeding |
owner, admin, member |
Accelerate |
manage_content |
AI content generation |
owner, admin, member |
All |
manage_campaigns |
Email sequences, campaigns |
owner, admin |
Accelerate |
view_marketing_analytics |
Marketing reports |
owner, admin, member |
All |
Marketplace & Listings
| Capability |
Description |
Default Roles |
Min Plan |
manage_listings |
Create/edit listings |
owner, admin, member |
All |
publish_listings |
Publish to marketplaces |
owner, admin |
All |
view_listings |
View listing data |
All roles |
All |
Integrations & Connections
| Capability |
Description |
Default Roles |
Min Plan |
manage_cloud_connections |
AWS marketplace IAM setup |
owner |
Command+ |
manage_integrations |
Slack, HubSpot, etc. |
owner, admin |
All |
view_integrations |
View integration status |
owner, admin, member |
All |
Security & Compliance
| Capability |
Description |
Default Roles |
Min Plan |
view_audit_log |
Access logs, security events |
owner, admin |
Command+ |
manage_security_settings |
Data privacy, compliance |
owner, admin |
All |
manage_sso |
SSO/SAML configuration |
owner |
Command+ |
API Access
| Capability |
Description |
Default Roles |
Min Plan |
api_access |
Use API programmatically |
owner, admin, api_service |
Accelerate |
api_admin |
Manage API keys |
owner |
Command+ |
Team Management
| Capability |
Description |
Default Roles |
Min Plan |
invite_members |
Invite new members |
owner, admin |
All |
manage_members |
Edit/remove members |
owner, admin |
All |
view_members |
View member list |
All roles |
All |
Companies & Analytics
| Capability |
Description |
Default Roles |
Min Plan |
manage_companies |
Create/edit companies |
owner, admin, member |
All |
view_companies |
View company profiles |
All roles |
All |
view_analytics |
View dashboards/reports |
owner, admin, member |
All |
export_data |
Export data/reports |
owner, admin |
Command+ |
Usage Examples
In Routes (Middleware)
// Single capability required
Route::get('/partners/invite', [PartnerController::class, 'invite'])
->middleware('capability:invite_partners');
// Any of multiple capabilities (OR)
Route::get('/billing', [BillingController::class, 'index'])
->middleware('capability:manage_billing,view_billing');
// All capabilities required (AND) - chain middleware
Route::post('/billing/upgrade', [BillingController::class, 'upgrade'])
->middleware(['capability:manage_billing', 'capability:approve_usage']);
In Controllers
use App\Enums\Team\TeamMemberCapability;
class PartnerController extends Controller
{
public function invite()
{
// Using User helper
if (!auth()->user()->hasTeamCapability(TeamMemberCapability::INVITE_PARTNERS)) {
abort(403, 'You do not have permission to invite partners');
}
// ... invite logic
}
public function bulkActions()
{
// Check multiple capabilities
if (!auth()->user()->hasAnyTeamCapability([
TeamMemberCapability::MANAGE_PARTNERS,
TeamMemberCapability::INVITE_PARTNERS,
])) {
abort(403);
}
}
}
In Blade Templates
@php
use App\Enums\Team\TeamMemberCapability;
@endphp
@if(auth()->user()->hasTeamCapability(TeamMemberCapability::INVITE_PARTNERS))
<button>Invite Partner</button>
@endif
@if(auth()->user()->hasTeamCapability(TeamMemberCapability::MANAGE_BILLING))
<a href="{{ route('billing') }}">Manage Billing</a>
@endif
In Livewire Components
use App\Enums\Team\TeamMemberCapability;
class PartnerList extends Component
{
public function mount()
{
// Ensure user can view partners
abort_unless(
auth()->user()->hasTeamCapability(TeamMemberCapability::VIEW_PARTNERS),
403
);
}
public function canInvite(): bool
{
return auth()->user()->hasTeamCapability(TeamMemberCapability::INVITE_PARTNERS);
}
}
Managing Capabilities Programmatically
use App\Enums\Team\TeamMemberCapability;
use App\Enums\Team\TeamMemberRole;
use App\Models\Team\TeamMember;
// Grant specific capability to a member
$member = TeamMember::find($id);
$member->grantCapability(TeamMemberCapability::MANAGE_SEO)->save();
// Deny a capability (even if role would allow it)
$member->denyCapability(TeamMemberCapability::PUBLISH_LISTINGS)->save();
// Reset to role defaults
$member->resetCapabilitiesToDefaults()->save();
// Check effective capabilities
$capabilities = $member->getEffectiveCapabilities();
// Create a service account
$serviceAccount = TeamMember::createServiceAccount(
team: $team,
name: 'CI/CD Pipeline',
capabilities: [
TeamMemberCapability::API_ACCESS,
TeamMemberCapability::VIEW_LISTINGS,
TeamMemberCapability::MANAGE_CONTENT,
]
);
Database Schema
team_members table additions
ALTER TABLE team_members ADD COLUMN capabilities JSON NULL
COMMENT 'Explicitly granted capabilities beyond role defaults';
ALTER TABLE team_members ADD COLUMN denied_capabilities JSON NULL
COMMENT 'Explicitly denied capabilities that override role defaults';
ALTER TABLE team_members ADD COLUMN api_only BOOLEAN DEFAULT FALSE
COMMENT 'If true, member can only access via API, no console login';
ALTER TABLE team_members ADD COLUMN service_account_name VARCHAR(255) NULL
COMMENT 'Human-readable name for service accounts';
ALTER TABLE team_members ADD COLUMN last_console_access_at TIMESTAMP NULL;
ALTER TABLE team_members ADD COLUMN last_api_access_at TIMESTAMP NULL;
Plan-Based Capability Gating
Capabilities can require a minimum subscription plan:
| Plan |
Level |
Available Capabilities |
| Starter |
1 |
Core features (content, listings, basic team) |
| Accelerate |
2 |
+ SEO, partners, campaigns, API access |
| Command+ |
3 |
+ Cloud connections, audit logs, SSO, exports |
| Enterprise |
4 |
All capabilities |
Example: A member with the admin role normally has manage_seo, but if the team is on the Starter plan, manage_seo will return false because it requires Accelerate or higher.
Migration Guide
For Existing Code
- Replace role string checks with capability checks:
// Before
if ($member->role === 'admin' || $member->role === 'owner') {
// allow action
}
// After
if ($member->hasCapability(TeamMemberCapability::MANAGE_MEMBERS)) {
// allow action
}
- Use middleware instead of manual checks:
// Before
Route::get('/partners', function () {
if (auth()->user()->teamMember->role !== 'admin') {
abort(403);
}
});
// After
Route::get('/partners', ...)->middleware('capability:manage_partners');
- Use User helpers for simpler checks:
// Direct membership check (more verbose)
$member = auth()->user()->activeTeamMembership();
if ($member && $member->hasCapability(...)) { }
// User helper (recommended)
if (auth()->user()->hasTeamCapability(...)) { }
Security Considerations
- Super admins bypass all checks - Use sparingly
- Team owners have all capabilities - By design
- Explicit denials take precedence - Use for specific restrictions
- Plan gating is enforced - Cannot bypass via explicit grants
- Service accounts should have minimal capabilities - Principle of least privilege
- Audit logs track console/API access times - For security reviews
| File |
Purpose |
app/Enums/Team/TeamMemberRole.php |
Role enum definition |
app/Enums/Team/TeamMemberCapability.php |
Capability enum definition |
app/Models/Team/TeamMember.php |
Model with capability methods |
app/Models/User.php |
User capability helpers |
app/Http/Middleware/CheckTeamCapability.php |
Route middleware |
database/migrations/2026_01_21_*_add_capabilities_*.php |
Migration |
Document generated: 2026-01-21