Receba novidades do Hedhog no seu e-mail
Novos lançamentos, receitas e breaking changes — sem spam.
Submódulo inbox
accounts
Gerencia as caixas de correio do inbox (inbox_account) às quais threads, mensagens, rascunhos e labels pertencem, incluindo a propriedade da conta e o acesso de membros compartilhados.
Caminho de origem: libraries/inbox/src/account
Arquivo do módulo: account.module.ts
Introdução
O submódulo Accounts é dono de `inbox_account`, a entidade raiz da qual todas as outras tabelas do Inbox dependem por meio de `account_id`. Cada conta representa uma única caixa de correio no provedor Resend (a coluna `provider` é um enum atualmente fixado no único valor `RESEND`), identificada por um `email` único e normalizado para minúsculas e por um `display_name` legível. Os campos opcionais `provider_domain_id` / `provider_region` permitem que a conta referencie um domínio de envio verificado específico quando a plataforma gerencia múltiplos domínios Resend, e `signature_html` armazena a assinatura HTML anexada ao compor a partir daquela conta.
O acesso à conta não é exclusivamente de proprietário único: `inbox_account_user` é uma tabela de junção com um `role` de `owner` ou `member`, então uma caixa de correio pode ser compartilhada com vários usuários. `AccountService.create` sempre faz upsert do usuário criador como `owner` e depois faz upsert de quaisquer `users` adicionais passados no corpo da requisição (deduplicados por `userId`) com o papel solicitado, tendo `member` como padrão. `AccountService.update` trata o array `users` como autoritativo quando presente: ele exclui todas as linhas de membership existentes da conta e as recria do zero, sempre mantendo o chamador como `owner` independentemente do que foi passado, o que impede que um membro remova acidentalmente o próprio acesso por meio de uma atualização parcial.
Apenas uma conta por usuário pode ser a padrão por vez. Definir `isDefault: true` na criação ou atualização executa dentro de uma transação que primeiro coloca `is_default` como `false` em todas as outras contas pertencentes àquele `user_id` e então aplica a nova padrão — trata-se de uma restrição por proprietário (espelhada pelo índice parcial único `user_id, is_default` em `inbox_account.yaml`), não global, de modo que dois usuários diferentes podem ter cada um a sua própria conta padrão. A exclusão de uma conta é um soft delete: `deleted_at` é carimbado, e `is_active`/`is_default` são ambos forçados para `false`, de modo que uma caixa de correio removida sai imediatamente da resolução de conta padrão e dos filtros de contas ativas sem precisar de uma segunda escrita.
O controle de acesso aqui é intencionalmente diferente do restante do módulo. `InboxAccessService.assertAccountAccess` (usado por update/delete) verifica se o chamador é o criador original da conta, uma linha em `inbox_account_user` ou detentor do papel `admin`/`admin-inbox` — mas `AccountService.list` não realiza nenhuma filtragem por usuário: ele retorna todas as contas não excluídas que correspondem ao termo de busca, apoiando-se inteiramente no gate de papel em nível de rota (`admin`, `admin-inbox` ou `inbox-owner`) para restringir quem pode chamar o endpoint. Em outras palavras, qualquer usuário que detenha um desses três papéis vê o diretório completo de contas, não apenas as contas às quais pertence — diferentemente de Threads, Messages, Drafts e Labels, que restringem suas consultas por meio de `InboxAccessService.listAccessibleAccountIds(userId)` e só retornam registros que o chamador pode ver. A verificação de e-mail duplicado ao criar e atualizar uma conta (`ConflictException` em caso de colisão) também é executada de forma case-insensitive após o trim, de modo que `[email protected]` e `[email protected]` são tratados como a mesma caixa de correio.
Endpoints HTTP
4 endpoints
Lista paginada de contas de inbox (ordenadas com a padrão primeiro, depois as mais recentes), com os membros compartilhados de cada conta (id, role, name, photoId). Não é restrita ao chamador — qualquer usuário com um dos três papéis permitidos vê todas as contas não excluídas.
- Query
- page, pageSize, search
Cria uma nova conta de inbox (caixa de correio). O provider é fixado em RESEND.
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| string (email, max 255) | yes | Normalized to lowercase; must be globally unique among active accounts | |
| displayName | string (max 180) | yes | — |
| providerDomainId | string (max 255) | no | — |
| providerRegion | string (max 127) | no | — |
| isDefault | boolean | no | Unsets is_default on the caller's other accounts when true |
| isActive | boolean | no | Default: true |
| signatureHtml | string | no | — |
| users | AccountMemberDto[] ({ userId, role? }) | no | Additional shared members; creator is always upserted as owner |
Atualiza uma conta de inbox (atualização parcial, com os mesmos campos da criação). Se "users" for informado, ele substitui integralmente a lista de membros da conta (o chamador é sempre mantido como owner).
- Params
- id (int)
Faz soft delete de uma conta de inbox (define deleted_at, is_active: false, is_default: false). Não exclui em cascata as threads/mensagens.
- Params
- id (int)