# Feature: Workspace Invites

## Status

Draft

## Goal

Allow workspace managers to invite teammates, clients, and providers into a workspace and allow invited people to accept access with the correct role and workspace scope.

## User Stories

- As a workspace manager, I want to invite a person by email and role so that they can access the right workspace.
- As an invited person, I want to accept an invite from a link so that I can join the workspace without administrator help.
- As an invited person without an account, I want to create my account as part of accepting the invite.
- As an invited person with an account, I want the accepted workspace to appear after sign-in.
- As a workspace manager, I want to see pending, accepted, cancelled, and expired invites so that I understand who has access or still needs follow-up.

## Domain Rules

- Workspace invites grant access to one workspace owned by one organization.
- Workspace invites belong to exactly one workspace.
- Invite acceptance does not automatically create organization membership.
- Invite email matching should use normalized email addresses.
- Pending invite tokens must be single-use and should expire.
- Accepted invites must grant the invited role and a workspace scope claim for the invite workspace.
- Signed-in users may accept invites only when their account email matches the invite email.
- New users may create an account during invite acceptance, then receive the invited role and workspace scope.
- Accepted, cancelled, and expired invites must not be accepted again.
- Managers can create, list, cancel, and resend invites only for workspaces they can manage.
- Managers must not be able to create duplicate pending invites for the same normalized email in the same workspace.
- Invite acceptance must be auditable through stored status and timestamp changes.
- External collaborator invitees should remain visible in workspace members and organization-level access review views without receiving organization-level billing, connector, or subscription permissions.

## Proposed Statuses

- `Pending`
- `Accepted`
- `Cancelled`
- `Expired`

## Backend Surface

- `POST /api/workspaces/{workspaceId:guid}/invites`
- `GET /api/workspaces/{workspaceId:guid}/invites`
- `POST /api/workspace-invites/{inviteId:guid}/resend`
- `POST /api/workspace-invites/{inviteId:guid}/cancel`
- `GET /api/workspace-invites/accept/{token}`
- `POST /api/workspace-invites/accept`

## Frontend Surface

- Workspace settings members tab for invite creation and invite management.
- Public invite acceptance route.
- Authenticated invite acceptance route for signed-in users.
- Registration/sign-in handoff for invited users without a usable session.

## Done When

- [ ] Invite creation sends an email with an acceptance link.
- [ ] Acceptance link validates a pending, unexpired, single-use token.
- [ ] Signed-in users can accept matching-email invites.
- [ ] New users can register through the invite path.
- [ ] Accepted invites grant role and workspace scope.
- [ ] Accepted users see the workspace after token refresh or sign-in.
- [ ] Managers can cancel and resend pending invites.
- [ ] Invite statuses are represented without magic strings.
- [ ] Backend tests cover create, duplicate, accept, expired, cancelled, and email mismatch cases.
- [ ] OpenAPI and frontend API usage are updated after contract changes.
