Files
2026-05-26 19:28:44 -04:00

4.0 KiB

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:

{DASHBOARD_URL}/reset-password?token=...

Relevant environment variables:

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.