Skip to main content

Overview

O Invite é o mecanismo de token para três fluxos:
  • type=MEMBER -> adiciona um usuário ao BackOffice ou a uma organização via Membership.
  • type=DRIVER -> vincula um usuário como motorista de uma empresa via DriverCompany.
  • type=ACCOUNT_ACTIVATION -> ativa uma conta criada sem senha.
A entidade, o token, o lifecycle e as validações de estado são compartilhados. O que muda é o efeito do aceite e os dados exigidos por cada tipo.

Tipos e escopos

TipoorganizationIdroleIdEfeito do aceite
MEMBER internonullRole INTERNALCria Membership interna ACTIVE; Profile deriva access:bko
MEMBER de organizaçãopreenchidoRole ENVIRONMENT ou ORGANIZATIONCria Membership ACTIVE na organização; Profile deriva access:ops
DRIVERpreenchidonullAtiva vínculo DriverCompany; Profile deriva access:driver
ACCOUNT_ACTIVATIONnullnullDefine senha e ativa a conta referenciada

Origens do Invite

OrigemTipoQuem dispara
BackOffice cria OrganizationMEMBER (owner, organizationId = nova org)Operador BackOffice
BackOffice convida membro internoMEMBEROperador BackOffice
OPS convida colegaMEMBERMembro OPS com create:member
OPS convida motoristaDRIVERMembro OPS com create:driver
Conta criada sem senhaACCOUNT_ACTIVATIONFluxo que originou a conta
O Invite carrega dois vínculos com User:
  • invitedByUserId — identifica o emissor ou responsável pelo token.
  • invitedUserId — identifica o usuário convidado ou ativado. Em MEMBER e DRIVER, pode ser resolvido no aceite. Em ACCOUNT_ACTIVATION, já aponta para a conta pendente.

Lifecycle

O Invite não possui campo status. O estado é derivado: acceptedAt -> accepted, rejectedAt -> rejected, revokedAt -> revoked, expiresAt no passado -> expired, senão -> pending. A expiração padrão é de 7 dias.

Capacidades por superfície

As ações de preview, accept e reject são públicas e operam sobre o token. Resend e revoke exigem autenticação; em OPS, também exigem escopo de organização.
AçãoOPSBackOfficeDriverAccount Activation
PreviewSimSimSimSim
AcceptSimSimSimSim
RejectSimSimSimSim
ResendSimSimSim
RevokeSimSimSim
Cada ação valida se o convite pertence ao tipo esperado e se o token ainda pode ser usado.

Dados do aceite

TipoDados
MEMBER{ name, password }
DRIVER{ name, password, licenseNumber, licenseCategory, licenseExpiresAt }
ACCOUNT_ACTIVATION{ password }
name e password são obrigatórios em MEMBER e DRIVER, mas name é ignorado quando o User já existe. Para DRIVER, os campos de habilitação são ignorados quando o User já possui um Driver.

Polymorphic Accept

O aceite tem fases compartilhadas seguidas de um branch por type: Quando o Invite tem email, o aceite também marca o email do User como verificado.

Invite Preview

Antes de aceitar, o cliente exibe informações contextuais sobre o Invite. O preview é público e valida se o token ainda pode ser usado antes de retornar dados enriquecidos conforme o tipo. MEMBER:
{
  "email": "convidado@email.com",
  "phoneIso": "BR",
  "phoneDdi": "55",
  "phoneNumber": "11999998888",
  "organization": { "name": "Transportes XYZ" },
  "role": { "name": "Operador", "description": "Acesso operacional" }
}
DRIVER:
{
  "email": "motorista@email.com",
  "phoneIso": "BR",
  "phoneDdi": "55",
  "phoneNumber": "11999998888",
  "organization": { "name": "Transportes XYZ" },
  "requiresLicense": true
}
ACCOUNT_ACTIVATION:
{
  "email": "passageiro@email.com",
  "phoneIso": "BR",
  "phoneDdi": "55",
  "phoneNumber": "11999998888",
  "name": "Maria Silva"
}
requiresLicense indica se o User já possui um Driver. Quando false, o cliente não precisa solicitar dados de habilitação no aceite.

Flow — BackOffice creates Organization (MEMBER)

Flow — OPS invites colleague (MEMBER)

Flow — Driver invite (DRIVER)

Flow — Account activation (ACCOUNT_ACTIVATION)

Reject vs. Revoke

AçãoQuemEfeitoPré-condição
RejectConvidadoPreenche rejectedAtNão aceito, não rejeitado, não revogado
RevokeEmissor ou responsável autorizadoPreenche revokedAtNão aceito, não revogado
Rejeitar e revogar não emitem eventos — apenas marcam o timestamp correspondente.

Resend

Um Invite pendente pode ser reenviado. O reenvio regenera o token e recalcula expiresAt para mais 7 dias — o link anterior passa a ser inválido — e emite invite.resent. Invites já aceitos ou revogados não podem ser reenviados.

Events

EventoQuando
invite.createdNa criação do Invite
invite.resentNo reenvio do Invite
invite.acceptedNo aceite do Invite
invite.created e invite.resent disparam notificações com o link por WhatsApp e também por email quando email está preenchido.

Validations

On Creation — comum

ValidaçãoErro
Emissor ou responsável existeuser.not_found
Organization existe (se organizationId informado)organization.not_found
Invite pendente para mesmo telefone + org + typeinvite.already_pending

On Creation — type=MEMBER

ValidaçãoErro
roleId informadoinvite.missing_role
Role atribuível ao escopo do conviterole.organization_mismatch
Usuário ainda não possui essa role no escopo do conviteinvite.user_already_member

On Creation — type=DRIVER

ValidaçãoErro
Organization possui Companyorganization.invalid_type
User existente sem vínculo DriverCompany ativo nesta companydriver.vinculum_already_exists

On Creation — type=ACCOUNT_ACTIVATION

ValidaçãoErro
invitedUserId informadouser.not_found
User está pendente de ativaçãouser.invalid_status
User ainda não possui senhauser.password_already_defined

On Acceptance

ValidaçãoErro
Token existeinvite.not_found
Não expiradoinvite.expired
Não revogadoinvite.revoked
Não rejeitadoinvite.rejected
Não aceitoinvite.already_accepted
type corresponde à açãoinvite.invalid_type
type=MEMBER: convite possui roleIdinvite.missing_role
type=DRIVER: licença/habilitação vencidadriver.expired_license

Effects of Accept

type=MEMBER -> Membership

CampoDescrição
userIdUsuário que aceitou
organizationIdOrganização do convite; null apenas em convite interno
roleIdRole atribuída
Membership interna ACTIVE faz o Profile derivar access:bko. Membership ACTIVE em organização faz o Profile derivar access:ops. Um usuário pode acumular múltiplas Memberships na mesma organização, mas vínculos REVOKED não concedem acesso.

type=DRIVER -> Driver (se novo) + DriverCompany

EntidadeQuandoCampos
DriverApenas se o User ainda não tinha DriveruserId, licenseNumber, licenseCategory, licenseExpiresAt
DriverCompanySempredriverId, companyId (derivado de Organization -> Company)
Vínculo ativo de motorista faz o Profile derivar access:driver. Driver não cria Membership — motorista é pessoal operacional, não membro administrativo da organização.

type=ACCOUNT_ACTIVATION -> conta ativa

CampoDescrição
passwordSenha definida pelo usuário
statusConta passa a ACTIVE
emailVerifiedMarcado quando o Invite possui email
Passageiros podem entrar por auto-cadastro ou por ativação de conta via Invite, quando a conta foi criada sem senha.