feat: complete Epic 1 — team management & permission system

- Story 1.1: Permission enum, config, AuthorizesPermissions & HasWorkspaceScope traits, member→worker migration
- Story 1.2: Team page with member list, invitation system with queued email
- Story 1.3: Role assignment (Manager/Worker) and member removal with activity logging
- Story 1.4: Owner-only permission toggle matrix for Managers (manage team, view logs, configure portal)
- Story 1.5: Role-based access enforcement — Workers see only assigned declarations/clients, sidebar scoping
- Story 1.6: Workspace switcher dropdown for multi-workspace users with session-based switching
- 83 new/modified files, 182 tests passing with zero regressions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-18 00:12:50 +00:00
parent 5dffd2d063
commit c89d1879bf
83 changed files with 5850 additions and 314 deletions

View File

@@ -19,6 +19,8 @@ export type Auth = {
user: User | null;
workspaces?: Workspace[];
currentWorkspace?: Workspace | null;
workspaceRole?: 'owner' | 'manager' | 'worker' | null;
workspaceSwitchUrl?: string | null;
};
export type TwoFactorConfigContent = {

View File

@@ -1,3 +1,4 @@
export * from './auth';
export * from './navigation';
export * from './team';
export * from './ui';

View File

@@ -0,0 +1,32 @@
export type TeamMember = {
id: number;
name: string;
email: string;
role: string;
joined_at: string;
status: 'active';
workspace_user_id: number;
updateRoleUrl: string;
removeUrl: string;
permissions?: Record<string, boolean>;
permissionsUrl?: string;
};
export type TeamInvitation = {
id: number;
email: string;
role: string;
invited_at: string;
status: 'pending';
};
export type TeamPageProps = {
members: TeamMember[];
pendingInvitations: TeamInvitation[];
canManageTeam: boolean;
isOwner: boolean;
availablePermissions: Record<string, string>;
authUserId: number;
inviteUrl: string;
roles: Record<string, string>;
};