# Team Management Integration — Current Implementation This document describes the current team-management integration in the live codebase. Source of truth: - `apps/api/src/modules/team/team.routes.ts` - `apps/api/src/services/teamService.ts` - `apps/dashboard/src/hooks/useTeam.ts` - `apps/dashboard/src/app/(dashboard)/team/page.tsx` - `apps/dashboard/src/app/reset-password/*` ## Current Model Team management is local to RentalDriveGo. It no longer depends on Clerk. The live flow is: 1. an owner invites a staff member from the dashboard 2. the API creates a pending `Employee` 3. the API generates a password-reset token 4. an email is sent with a reset-password link 5. the invited employee sets a password through the dashboard reset-password page 6. the employee can then sign in through the standard employee login flow There is no webhook step in the active implementation. ## Backend Integration The team router is already mounted by the main API app in `apps/api/src/app.ts` under: - `/api/v1/team` The public webhook placeholder under `/api/v1/webhooks/clerk` is intentionally disabled and should not be used for team onboarding. ### Team endpoints - `GET /api/v1/team` - `GET /api/v1/team/stats` - `POST /api/v1/team/invite` - `PATCH /api/v1/team/:id/role` - `POST /api/v1/team/:id/deactivate` - `POST /api/v1/team/:id/reactivate` - `DELETE /api/v1/team/:id` ### Auth and authorization These routes are protected by: - employee JWT auth - tenant resolution - subscription guard - role checks inside the router and service Important rules in the current implementation: - only the `OWNER` can invite, change roles, deactivate/reactivate, or remove team members - invited team members cannot be created with the `OWNER` role - the account owner cannot be deactivated or removed through team endpoints ## Invite Email Flow Invitations are generated in `apps/api/src/services/teamService.ts`. Current behavior: - a pending employee row is created - `passwordResetToken` and `passwordResetExpiresAt` are populated - the invite email links directly to the dashboard reset-password page Expected URL shape: ```text {DASHBOARD_URL}/reset-password?token=... ``` Relevant environment variables: ```env DASHBOARD_URL=https://your-host/dashboard NEXT_PUBLIC_DASHBOARD_URL=https://your-host/dashboard NEXT_PUBLIC_API_URL=https://your-host/api/v1 ``` ## Dashboard Integration The team UI lives here: - `apps/dashboard/src/app/(dashboard)/team/page.tsx` - `apps/dashboard/src/hooks/useTeam.ts` - `apps/dashboard/src/components/team/InviteModal.tsx` - `apps/dashboard/src/components/team/EditMemberModal.tsx` - `apps/dashboard/src/components/team/PermissionsMatrix.tsx` The dashboard consumes the team API directly through `apiFetch(...)`. ### Dashboard page behavior - loads members from `/team` - loads summary counts from `/team/stats` - opens invite/edit flows through local modals - updates local state after invite, role change, deactivate/reactivate, and removal ## Password Setup / Invite Acceptance The active invite-acceptance mechanism is the dashboard reset-password flow, not a Clerk callback flow. Relevant pages: - `apps/dashboard/src/app/reset-password/page.tsx` - `apps/dashboard/src/app/reset-password/ResetPasswordPageClient.tsx` This means: - there is no `__clerk_ticket` - there is no Clerk redirect callback - there is no employee activation webhook Invite completion is simply password setup using the token created by the API. ## Request Typing The request object is extended in the API so team routes can rely on: - `req.employee` - `req.company` - `req.companyId` Those values are attached by the company auth and tenant middleware before team handlers run. ## What Was Removed These older integration assumptions are no longer valid: - Clerk webhooks - Clerk invitation acceptance - Clerk `user.created` activation flow - `/webhooks/clerk` as a required part of team onboarding - `@clerk/nextjs` integration in the dashboard team flow If this functionality returns in the future, it should be documented as a new integration rather than assumed from this file.