# Jetstream Teams (platform)

## Purpose

Multi-team accounts, memberships, invitations, and related auth/profile flows provided by Laravel Jetstream. This is **platform**, not a removable product domain.

## Boundaries

- **Owns:** `User`, `Team`, memberships, invitations, Fortify/Jetstream actions, profile/API token UI scaffolding
- **Does not own:** Product CRM/scheduling features
- **Location:** Default Laravel/Jetstream paths under `laravel/app/`, `laravel/resources/js/`, `laravel/tests/Feature/`
- **Removable?** No — product domains may depend on this layer

## Models

| Model | Table | Notes |
|-------|-------|-------|
| `App\Models\User` | `users` | Jetstream user |
| `App\Models\Team` | `teams` | Team account |
| `App\Models\Membership` | `team_user` | Pivot membership |
| `App\Models\TeamInvitation` | `team_invitations` | Invitations |

## Routes

Managed by Jetstream/Fortify (web). Sanctum supports API token auth for mobile clients. See [Web and API](../architecture/web-and-api.md).

## Permissions

Jetstream team roles/abilities via `TeamPolicy` and related Jetstream configuration.

| Role key | Label | Abilities |
|----------|-------|-----------|
| `admin` | Administrator | `create`, `read`, `update`, `delete` |
| `editor` | Editor | `read`, `create`, `update` |
| `staff` | Staff | `read` |
| `customer` | Customer | `read`, `create`, `update` |
| `provider` | Provider | `read` |

Team **owners** retain full team-management gates (`addTeamMember`, etc.) regardless of role.

The `customer` role is for CRM portal logins linked via `customer_portal_users` (see [Customers](customers.md) and [Jobs](jobs.md)). Portal users do not manage company settings or the customers CRM.

The `provider` role is for third-party portal logins linked via `provider_portal_users` (see [Providers](providers.md) and [Jobs](jobs.md)). Providers see only appointments assigned to them (limited fields) and cannot access providers CRM or payments.

### Create member with password (no invite)

Owners can create a user and attach them to the team without sending an invitation:

- Web: `POST /teams/{team}/members/create` (`team-members.create`) — flashes one-time `generated_password`
- API: `POST /api/teams/{team}/members` (`api.team-members.store`) — JSON includes one-time `password`

Existing invite flow (`POST /teams/{team}/members`) is unchanged.

## Tests

Existing Jetstream Feature tests under `laravel/tests/Feature/` (registration, teams, API tokens, profile, etc.), plus `CreateTeamMemberWithPasswordTest`.

## Notes for agents

- Do not move this into `app/Domains/`.
- Product features reference `User` / `Team` as platform dependencies and document that on their feature pages.
