28 de jul. de 2025·8 min de leitura

Esquema de banco de dados para organizações e equipes B2B que permanece organizado

Esquema de banco de dados para organizações e equipes B2B: um padrão relacional prático para convites, estados de membership, herança de roles e mudanças prontas para auditoria.

Esquema de banco de dados para organizações e equipes B2B que permanece organizado

Que problema esse padrão de esquema resolve

A maioria das apps B2B não é realmente uma app de “contas de usuário”. São espaços de trabalho compartilhados onde pessoas pertencem a uma organização, divididas em equipes, e recebem permissões diferentes dependendo do cargo. Vendas, suporte, finanças e admins precisam de acessos distintos, e esse acesso muda com o tempo.

Um modelo simples demais quebra rápido. Se você mantiver uma única tabela users com uma coluna role, não consegue expressar “a mesma pessoa é Admin em uma org, mas Viewer em outra.” Também não consegue lidar bem com casos comuns como contratados que devem ver apenas uma equipe, ou um funcionário que sai de um projeto mas ainda pertence à empresa.

Convites são outra fonte frequente de bugs. Se um convite é apenas uma linha de email, fica ambíguo se a pessoa já está “dentro” da org, a qual equipe deveria se juntar e o que acontece se ela se cadastrar com outro email. Pequenas inconsistências aqui tendem a virar problemas de segurança.

Este padrão busca quatro objetivos:

  • Segurança: permissões vêm de membership explícito, não de suposições.
  • Clareza: orgs, equipes e roles têm cada uma sua fonte da verdade.
  • Consistência: convites e memberships seguem um ciclo de vida previsível.
  • Histórico: você pode explicar quem concedeu acesso, alterou roles ou removeu alguém.

A promessa é um modelo relacional único que permanece compreensível conforme os recursos crescem: múltiplas orgs por usuário, múltiplas equipes por org, herança de roles previsível e mudanças fáceis de auditar. É uma estrutura que você pode implementar hoje e estender depois sem reescrever tudo.

Termos chave: orgs, equipes, usuários e memberships

Se você quer um esquema que continue legível depois de seis meses, comece concordando em algumas palavras. A maioria das confusões vem de misturar “quem alguém é” com “o que ele pode fazer”.

Uma Organização (org) é a fronteira de tenant principal. Representa o cliente ou conta empresarial que possui os dados. Se dois usuários estão em orgs diferentes, eles não devem ver os dados um do outro por padrão. Essa única regra evita muitos acessos acidentais entre tenants.

Uma Equipe é um grupo menor dentro de uma org. Equipes modelam unidades de trabalho reais: Vendas, Suporte, Finanças ou “Projeto A”. Equipes não substituem a fronteira da org; vivem abaixo dela.

Um Usuário é uma identidade. É o login e o perfil da pessoa: email, nome, senha ou ID de SSO, e talvez configurações de MFA. Um usuário pode existir sem ter acesso a nada ainda.

Uma Membership é o registro de acesso. Responde: “Este usuário pertence a esta org (e opcionalmente a esta equipe) com este status e estes roles.” Manter identidade (User) separada de acesso (Membership) facilita modelar contratados, offboarding e acessos multi-org.

Significados práticos que você pode usar no código e na UI:

  • Membro: um usuário com uma membership ativa em uma org ou equipe.
  • Role: um conjunto nomeado de permissões (por exemplo, Org Admin, Team Manager).
  • Permissão: uma ação permitida única (por exemplo, “ver faturas”).
  • Fronteira de tenant: a regra que delimita os dados a uma org.

Trate membership como uma pequena máquina de estados, não um booleano. Estados típicos são invited, active, suspended e removed. Isso mantém convites, aprovações e offboarding consistentes e auditáveis.

O modelo relacional único: tabelas centrais e relacionamentos

Um bom esquema multi-tenant começa com uma ideia: armazene “quem pertence aonde” em um lugar só, e mantenha todo o resto como tabelas de suporte. Assim você pode responder perguntas básicas (quem está na org, quem está em uma equipe, o que podem fazer) sem saltar por modelos desconexos.

Tabelas centrais que você normalmente vai precisar:

  • organizations: uma linha por conta de cliente (tenant). Contém nome, status, campos de cobrança e um id imutável.
  • teams: grupos dentro de uma organização (Support, Sales, Admin). Sempre pertence a uma organização.
  • users: uma linha por pessoa. Isso é global, não por organização.
  • memberships: a ponte que diz “este usuário pertence a esta organização” e opcionalmente “também a esta equipe”.
  • role_grants (ou role_assignments): que roles uma membership tem, ao nível da org, da equipe ou ambos.

Mantenha chaves e constraints rígidas. Use chaves primárias substitutas (UUIDs ou bigints) para cada tabela. Adicione foreign keys como teams.organization_id -> organizations.id e memberships.user_id -> users.id. Depois adicione algumas unique constraints para evitar duplicações antes que apareçam em produção.

Regras que pegam a maior parte dos dados ruins cedo:

  • Um slug ou chave externa por org: unique(organizations.slug)
  • Nomes de equipe por org: unique(teams.organization_id, teams.name)
  • Sem membership duplicada por org: unique(memberships.organization_id, memberships.user_id)
  • Sem membership duplicada de equipe (só se você modelar membership de equipe separadamente): unique(team_memberships.team_id, team_memberships.user_id)

Decida o que é append-only versus atualizável. Organizations, teams e users são atualizáveis. Memberships costumam ser atualizáveis para o estado corrente (active, suspended), mas mudanças também devem gravar num log de acesso append-only para que auditorias sejam simples depois.

Convites e estados de membership que permanecem consistentes

A maneira mais fácil de manter o acesso limpo é tratar um convite como seu próprio registro, não uma membership meio feita. Uma membership significa “este usuário atualmente pertence”. Um convite significa “oferecemos acesso, mas ainda não é real.” Mantê-los separados evita membros-fantasma, permissões meio-criadas e mistérios como “quem convidou essa pessoa?”.

Um modelo de estado simples e confiável

Para memberships, use um pequeno conjunto de estados que você consiga explicar a qualquer pessoa:

  • active: o usuário pode acessar a org (e quaisquer equipes das quais é membro)
  • suspended: bloqueado temporariamente, mas o histórico permanece intacto
  • removed: não é mais membro, guardado para auditoria e relatórios

Muitas equipes evitam um estado de membership “invited” e mantêm “invited” estritamente na tabela de invitations. Isso tende a ser mais limpo: linhas de membership existem apenas para usuários que realmente têm acesso (active), ou que já tiveram (suspended/removed).

Convites por email antes de existir uma conta

Apps B2B frequentemente convidam por email quando ainda não existe uma conta de usuário. Armazene o email no registro de invitation, junto com onde o convite se aplica (org ou team), a role pretendida e quem o enviou. Se a pessoa mais tarde se cadastrar com aquele email, você pode casar os convites pendentes e permitir que ela aceite.

Quando um convite é aceito, trate isso em uma única transação: marque o invitation como accepted, crie a membership e escreva uma entrada de auditoria (quem aceitou, quando e qual email foi usado).

Defina estados finais claros para invitations:

  • expired: passou do prazo e não pode ser aceito
  • revoked: cancelado por um admin e não pode ser aceito
  • accepted: convertido em membership

Previna convites duplicados impondo “apenas um invite pendente por org ou equipe por email”. Se você suporta re-invites, ou estenda o expiry no convite pendente existente ou revogue o antigo e emita um novo token.

Roles e herança sem tornar o acesso confuso

Implemente sua app B2B do seu jeito
Faça o deploy no AppMaster Cloud ou na sua própria nuvem quando estiver pronto para ir ao ar.
Experimentar AppMaster

A maioria das apps B2B precisa de dois níveis de acesso: o que alguém pode fazer na organização como um todo, e o que pode fazer dentro de uma equipe específica. Misturar isso em um único campo role é onde as apps começam a ficar inconsistentes.

Roles ao nível da org respondem se a pessoa pode gerenciar billing, convidar pessoas ou ver todas as equipes. Roles ao nível da equipe respondem se pode editar itens na Equipe A, aprovar pedidos na Equipe B ou apenas visualizar.

A herança de roles é mais fácil de conviver quando segue uma regra: uma role de org se aplica em todos os lugares, a menos que uma equipe diga explicitamente o contrário. Isso mantém o comportamento previsível e reduz dados duplicados.

Uma forma limpa de modelar isso é armazenar assignments de role com um escopo:

  • role_assignments: user_id, org_id, team_id opcional (NULL significa abrangência org-wide), role_id, created_at, created_by

Se você quiser “uma role por escopo”, adicione uma unique constraint em (user_id, org_id, team_id).

Então o acesso efetivo para uma equipe se torna:

  1. Procure um assignment específico da equipe (team_id = X). Se existir, use-o.

  2. Caso contrário, recorra ao assignment org-wide (team_id IS NULL).

Para padrões de princípio de privilégio mínimo, escolha uma role org mínima (frequentemente “Member”) e não lhe dê poderes administrativos ocultos. Novos usuários não deveriam ganhar acesso implícito a equipes a menos que seu produto realmente precise disso. Se você fegar acesso automaticamente, faça isso criando memberships explícitas de equipe, não alargando silenciosamente a role da org.

Overrides devem ser raros e óbvios. Exemplo: Maria é “Manager” de org (pode convidar, ver relatórios), mas na equipe Finance ela deve ser “Viewer”. Você armazena um assignment org-wide para Maria, mais um override com escopo de equipe para Finance. Nada de copiar permissões, e a exceção fica visível.

Nomes de roles funcionam bem para padrões comuns. Use permissões explícitas apenas quando tiver casos únicos reais (como “pode exportar mas não editar”), ou quando compliance exigir uma lista clara de ações permitidas. Mesmo assim, mantenha a ideia de escopo para que o modelo mental continue consistente.

Mudanças amigáveis à auditoria: rastreando quem alterou acessos

Se sua app guarda apenas a role atual numa linha de membership, você perde a história. Quando alguém pergunta “Quem deu acesso de admin ao Alex na terça passada?” você não tem uma resposta confiável. Você precisa de histórico de mudanças, não apenas do estado atual.

A abordagem mais simples é uma tabela de audit dedicada que registra eventos de acesso. Trate-a como um diário append-only: você nunca edita linhas antigas de auditoria; apenas adiciona novas.

Uma tabela de auditoria prática normalmente inclui:

  • actor_user_id (quem fez a mudança)
  • subject_type e subject_id (membership, team, org)
  • action (invite_sent, role_changed, membership_suspended, team_deleted)
  • occurred_at (quando aconteceu)
  • reason (texto opcional como “offboarding de contratado”)

Para capturar “antes” e “depois”, armazene um pequeno snapshot dos campos que importam. Mantenha isso limitado a dados de controle de acesso, não perfis completos de usuário. Por exemplo: before_role, after_role, before_state, after_state, before_team_id, after_team_id. Se preferir flexibilidade, use dois campos JSON (before, after), mas mantenha o payload pequeno e consistente.

Para memberships e teams, soft delete costuma ser melhor que hard delete. Ao invés de remover a linha, marque-a desativada com campos como deleted_at e deleted_by. Isso mantém foreign keys intactas e facilita explicar acessos passados. Hard delete ainda pode fazer sentido para registros realmente temporários (como invites expirados), mas só se você tiver certeza de que não vai precisar deles depois.

Com isso, você pode responder perguntas comuns de compliance rapidamente:

  • Quem concedeu ou removeu acesso, e quando?
  • O que exatamente mudou (role, equipe, estado)?
  • O acesso foi removido como parte de um offboarding normal?

Passo a passo: projetando o esquema em um banco relacional

Mantenha seu modelo de dados sadio
Use um modelo de dados que permanece legível à medida que você adiciona equipes, exceções e histórico de auditoria.
Desenhar banco de dados

Comece simples: um lugar para dizer quem pertence a quê, e por quê. Construa em pequenos passos e adicione regras ao longo do caminho para que os dados não derem “quase corretos”.

Uma ordem prática que funciona bem em PostgreSQL e outros bancos relacionais:

  1. Crie organizations e teams, cada uma com uma chave primária estável (UUID ou bigint). Adicione teams.organization_id como foreign key e decida cedo se nomes de equipe devem ser únicos dentro da org.

  2. Separe users de membership. Coloque campos de identidade em users (email, status, created_at). Coloque “pertence a org/equipe” em uma tabela memberships com user_id, organization_id, team_id opcional (se você modelar assim) e uma coluna state (active, suspended, removed).

  3. Adicione invitations como tabela própria, não uma coluna em membership. Armazene organization_id, team_id opcional, email, token, expires_at e accepted_at. Aplique unicidade para “um invite aberto por org + email + equipe” para não criar duplicados.

  4. Modele roles com tabelas explícitas. Uma abordagem simples é roles (admin, member, etc.) mais role_assignments que apontam para escopo org (sem team_id) ou escopo de equipe (team_id definido). Mantenha regras de herança consistentes e testáveis.

  5. Adicione um trilho de auditoria desde o primeiro dia. Use uma tabela access_events com actor_user_id, target_user_id (ou email para invites), action (invite_sent, role_changed, removed), scope (org/team) e created_at.

Depois que essas tabelas existirem, execute algumas queries administrativas básicas para validar a realidade: “quem tem acesso org-wide?”, “quais equipes não têm admins?” e “quais invites estão expirados mas ainda abertos?” Essas perguntas tendem a revelar constraints faltantes cedo.

Regras e constraints que evitam dados bagunçados

Construa este esquema visualmente
Modele orgs, equipes e associações no PostgreSQL com ferramentas visuais e gere código real.
Experimentar AppMaster

Um esquema permanece sadio quando o banco de dados, não apenas seu código, aplica as fronteiras de tenant. A regra mais simples é: toda tabela com escopo tenant carrega org_id, e toda busca inclui isso. Mesmo que alguém esqueça um filtro no app, o banco deve resistir a conexões entre orgs.

Guardrails que mantêm os dados limpos

Comece com foreign keys que sempre apontam “dentro da mesma org”. Por exemplo, se você armazenar membership de equipe separadamente, uma linha team_memberships deve referenciar team_id e user_id, mas também carregar org_id. Com chaves compostas, você pode garantir que a equipe referenciada pertence à mesma org.

Constraints que impedem os problemas mais comuns:

  • Uma membership ativa por usuário por org: unique em (org_id, user_id) com condição parcial para linhas ativas (onde suportado).
  • Um invite pendente por email por org ou equipe: unique em (org_id, team_id, email) onde state = 'pending'.
  • Tokens de invite globalmente únicos e nunca reutilizados: unique em invite_token.
  • Time pertence exatamente a uma org: teams.org_id NOT NULL com foreign key para orgs(id).
  • Encerre memberships ao invés de deletá-las: armazene ended_at (e opcionalmente ended_by) para proteger o histórico de auditoria.

Indexando para as consultas que você realmente faz

Indexe as queries que sua app executa sempre:

  • (org_id, user_id) para “quais orgs este usuário tem?”
  • (org_id, team_id) para “listar membros desta equipe”
  • (invite_token) para “aceitar invite”
  • (org_id, state) para “invites pendentes” e “membros ativos”

Mantenha nomes de org mutáveis. Use um orgs.id imutável em toda parte, e trate orgs.name (e qualquer slug) como campos editáveis. Renomear toca apenas uma linha.

Mover uma equipe entre orgs costuma ser uma decisão de política. A opção mais segura é proibir (ou clonar a equipe) porque memberships, roles e histórico de auditoria são org-scoped. Se precisar permitir moves, faça em uma única transação e atualize todas as linhas filhas que carregam org_id.

Para evitar registros órfãos quando usuários saem, evite deletes físicos. Desabilite o usuário, encerre suas memberships e restrinja deletes em linhas pai (ON DELETE RESTRICT) a menos que você realmente queira remoção em cascata.

Exemplo: uma org, duas equipes, alterando acesso com segurança

Imagine uma empresa chamada Northwind Co com uma org e duas equipes: Sales e Support. Eles contratam uma temporária, Mia, para ajudar nos tickets de Support por um mês. Aqui o modelo deve permanecer previsível: uma pessoa, uma membership org, memberships de equipe opcionais e estados claros.

Uma admin da org (Ava) convida Mia por email. O sistema cria uma linha de invitation ligada à org, com status pending e uma data de expiração. Nada mais muda ainda, então não existe um “meio usuário” com acesso incerto.

Quando Mia aceita, o invitation é marcado como accepted e uma linha de membership org é criada com state active. Ava define a role org de Mia para member (não admin). Em seguida Ava adiciona a membership de equipe Support e atribui uma role de equipe como support_agent.

Agora um detalhe: Ben é funcionário em tempo integral com uma role org de admin, mas não deve ver dados do Support. Você pode lidar com isso com um override a nível de equipe que downgradeia explicitamente sua role na equipe Support enquanto mantém habilidades administrativas org-wide. Tudo visível e explícito.

Uma semana depois, Mia viola a política e é suspensa. Ao invés de deletar linhas, Ava define o estado da membership org de Mia para suspended. Memberships de equipe podem permanecer, mas tornam-se inefetivas enquanto a membership org não estiver ativa.

O histórico de auditoria permanece claro porque cada mudança é um evento:

  • Ava convidou Mia (quem, o quê, quando)
  • Mia aceitou o convite
  • Ava adicionou Mia ao Support e atribuiu support_agent
  • Ava definiu o override do Support para Ben
  • Ava suspendeu Mia

Com esse modelo, a UI pode mostrar um resumo claro de acesso: estado da org (active ou suspended), role na org, lista de equipes com roles e overrides, e um feed “Mudanças recentes de acesso” que explica por que alguém pode ou não ver Sales ou Support.

Erros comuns e armadilhas para evitar

Implemente roles com escopo mais rápido
Adicione roles com escopo de org e de equipe com regras consistentes, sem codificar cada endpoint manualmente.
Criar backend

A maioria dos bugs de acesso vem de modelos “quase corretos”. O esquema parece ok no começo, depois casos de borda se acumulam: re-invites, moves de equipe, trocas de role e offboarding.

Uma armadilha comum é misturar invitations e memberships na mesma linha. Se você armazenar “invited” e “active” no mesmo registro sem significado claro, acaba com perguntas impossíveis como “esta pessoa é membro se nunca aceitou?” Mantenha invitations e memberships separados, ou torne a máquina de estados explícita e consistente.

Outro erro frequente é colocar uma coluna role na tabela users e achar que está resolvido. Roles quase sempre são escopadas (role de org, role de equipe, role de projeto). Uma role global força gambiarras como “usuário é admin para um cliente, mas somente leitura para outro”, o que quebra expectativas multi-tenant e gera dores de suporte.

Armadilhas que geralmente causam problemas depois:

  • Permitir membership cruzada entre orgs por acidente (team_id aponta para org A, membership aponta para org B).
  • Deletar memberships fisicamente e perder “quem tinha acesso semana passada?”
  • Faltar regras de unicidade e permitir que um usuário ganhe acesso duplicado por linhas idênticas.
  • Permitir que herança acumule silenciosamente (org admin + membro de equipe + override) de modo que ninguém consiga explicar por que o acesso existe.
  • Tratar “invite accepted” como evento da UI e não como fato do banco.

Um exemplo rápido: um contratado é convidado para uma org, entra na Team Sales, depois é removido e re-convidado um mês depois. Se você sobrescrever a linha antiga, perde o histórico. Se permitir duplicatas, ele pode acabar com duas memberships ativas. Estados claros, roles escopadas e constraints corretas impedem ambos.

Checagens rápidas e próximos passos para integrar ao seu app

Antes de codar, faça uma revisão rápida do seu modelo e veja se ainda faz sentido no papel. Um bom modelo de acesso multi-tenant deve parecer entediante: as mesmas regras se aplicam em todo lugar e “casos especiais” são raros.

Uma checklist rápida para pegar lacunas comuns:

  • Toda membership aponta para exatamente um usuário e uma org, com constraint única para prevenir duplicados.
  • Estados de invitation, membership e remoção são explícitos (não implícitos por nulls), e transições são limitadas (por exemplo, não se pode aceitar um invite expirado).
  • Roles são armazenadas em um lugar e o acesso efetivo é calculado de forma consistente (incluindo regras de herança, se usadas).
  • Deletar orgs/equipes/usuários não apaga o histórico (use soft delete ou campos de arquivamento onde precisar de trilha de auditoria).
  • Toda mudança de acesso emite um evento de auditoria com ator, alvo, escopo, timestamp e motivo/fonte.

Teste o desenho com perguntas reais. Se você não consegue responder estas com uma query e uma regra clara, provavelmente precisa de uma constraint ou um estado extra:

  • O que acontece se um usuário é convidado duas vezes e depois o email muda?
  • Um admin de equipe pode remover um owner da org dessa equipe?
  • Se uma role de org concede acesso a todas as equipes, uma equipe pode sobrescrever isso?
  • Se um invite é aceito depois que a role mudou, qual role se aplica?
  • Quando o suporte pergunta “quem removeu o acesso”, você consegue provar isso rapidamente?

Escreva o que admins e equipe de suporte precisam entender: estados de membership (e o que os dispara), quem pode convidar/remover, o que herança de roles significa em linguagem simples e onde olhar por eventos de auditoria durante um incidente.

Implemente constraints primeiro (uniques, foreign keys, transições permitidas), depois construa a lógica de negócio em cima delas para que o banco ajude a manter tudo honesto. Mantenha decisões de política (herança on/off, roles padrão, expiry de invites) em tabelas de configuração em vez de constantes no código.

Se você quiser montar isso sem escrever cada backend e tela administrativa manualmente, AppMaster (appmaster.io) pode ajudá-lo a modelar essas tabelas no PostgreSQL e implementar transições de invite e membership como processos de negócio explícitos, gerando ainda código-fonte real para deploy em produção.

FAQ

Por que eu não devo armazenar uma única coluna de role na tabela users?

Use um registro separado de membership para que roles e acessos estejam ligados a uma organização (e opcionalmente a uma equipe), e não à identidade global do usuário. Isso permite que a mesma pessoa seja Admin em uma organização e Viewer em outra sem gambiarras.

Um convite deve criar uma linha de membership imediatamente?

Mantenha separados: um invitation é uma oferta com email, escopo e validade, enquanto uma membership significa que o usuário realmente tem acesso. Isso evita “membros fantasmas”, status confusos e falhas de segurança quando os emails mudam.

Quais estados de membership devo usar?

Um conjunto pequeno como active, suspended e removed é suficiente para a maioria das apps B2B. Se você mantiver “invited” apenas na tabela de invitations, as memberships permanecem inequívocas: representam acessos atuais ou passados, não acessos pendentes.

Como modelo roles de org vs roles de equipe sem confusão?

Armazene roles de org e de equipe como assignments com escopo (org-wide quando team_id for null, específico de equipe quando definido). Ao checar acesso para uma equipe, prefira o assignment específico da equipe se existir; caso contrário, recorra ao assignment global da org.

Qual a regra mais simples para herança de roles?

Comece com uma regra previsível: roles de org se aplicam em todos os lugares por padrão, e roles de equipe sobrescrevem apenas quando explicitamente definidas. Mantenha overrides raros e visíveis para que as pessoas possam explicar o acesso sem adivinhar.

Como evito convites duplicados e re-invites de forma limpa?

Imponha “apenas um convite pendente por org/equipe por email” com uma constraint única e um ciclo de vida claro pending/accepted/revoked/expired. Se precisar re-enviar convites, atualize o convite pendente existente (por exemplo, estendendo o expiry) ou revogue-o antes de emitir um novo token.

Como aplico a fronteira de tenant no banco de dados?

Cada linha com escopo de tenant deve carregar org_id, e suas foreign keys/constraints devem impedir mistura de orgs (por exemplo, uma equipe referenciada por uma membership deve pertencer à mesma org). Isso reduz o alcance de filtros esquecidos no código da aplicação.

Como torno mudanças de acesso auditáveis?

Mantenha um log de eventos de acesso append-only que registre quem fez o quê, a quem, quando e em qual escopo (org ou equipe). Registre os campos-chave antes/depois (role, state, team) para que você possa responder “quem concedeu admin na última terça-feira?” de forma confiável.

Devo deletar memberships e invites fisicamente?

Evite deletes físicos para memberships e equipes; marque-as como encerradas/desabilitadas para que o histórico continue consultável e as chaves estrangeiras não quebrem. Para invites, você também pode mantê-los (mesmo expirados) se quiser um rastro completo de segurança, mas no mínimo não reutilize tokens.

Quais índices importam mais para este esquema?

Indexe seus caminhos quentes: (org_id, user_id) para checagens de membership da org, (org_id, team_id) para listas de membros da equipe, (invite_token) para aceitação de convite e (org_id, state) para telas administrativas como “membros ativos” ou “convites pendentes”. Índices devem refletir suas consultas reais, não todas as colunas.

Fácil de começar
Criar algo espantoso

Experimente o AppMaster com plano gratuito.
Quando estiver pronto, você poderá escolher a assinatura adequada.

Comece