Monalisa
Modelo de dados

Workforce

Memberships (pessoa × tenant) e as ligações que dão poder e contexto: perfis, corretores, times, carteiras, convites e seleção de sessão.

memberships é só pessoa × tenant: uma membership ativa por usuário em cada tenant. Tudo que dá poder ou contexto é uma ligação com membership_id, com tenant_id, vigência e autor:

  • membership_access_profiles: perfil do tenant inteiro;
  • membership_brokers: atuar como usuário de um corretor, com um perfil daquele corretor;
  • membership_teams: participar de um time, com um perfil do tenant;
  • membership_portfolios: carteira de um comercial (corretor + pessoa + time).

A mesma pessoa pode acumular várias ligações; a permissão efetiva é a união das ligações ativas. Tudo tem origem: uma membership nasce de um convite (origin_invitation_id), e as ligações vêm de um grant de convite ou de uma ação direta registrada.

Tabelas (17)

TabelaPara quê
membershipsPessoa × tenant: usuário, party e quem concedeu ou removeu.
membership_access_profilesPerfil do tenant concedido à membership para o tenant inteiro, com vigência.
membership_brokersAtuar como usuário de um corretor, com um perfil daquele corretor.
teamsTime do tenant (agrupamento comercial ou organizacional).
membership_teamsPessoa no time, com um perfil do tenant e vigência [valid_from, valid_until) sem sobreposição para o mesmo par (time, membership).
membership_portfoliosCarteira: um corretor atendido por uma pessoa num time, coberta por uma membership_teams da mesma pessoa, time e tenant.
team_financial_institution_accountsContextos que um time atende: time → vínculo CNPJ × IF existente, com vigência sem sobreposição para o mesmo par.
team_hierarchiesAresta organizacional temporal entre duas participações em time (subordinado e superior), com motivo.
portfolio_transfersCabeçalho imutável de uma transferência manual de carteiras, com ator, motivo e data efetiva; uid identifica a operação idempotente.
portfolio_transfer_itemsCada corretor transferido: carteira de origem e de destino do mesmo corretor e tenant; uma carteira só aparece uma vez como origem e uma vez como destino.
invitationsConvite para um tenant: canal, destino, SHA-256 do token, estado e validade.
invitation_grantsO que o aceite do convite vai criar: perfil do tenant, atuação em corretor, time ou carteira.
invitation_session_contextsExiste só quando um operador de plataforma, dentro de um session_context, emite o convite.
invitation_deliveriesCada tentativa de envio de um convite de tenant; reenvio é uma linha nova; exatamente um solicitante.
invitation_delivery_eventsLinha do tempo bruta do provedor de envio; webhook repetido não duplica.
session_membershipsEm qual tenant uma sessão está atuando; fonte do contexto de tenant da transação.
session_membership_brokersExiste só quando a sessão atua como usuário de um corretor; trocar de corretor abre uma nova session_memberships.

Referência

memberships

Pessoa × tenant: usuário, party e quem concedeu ou removeu. Uma ativa por (tenant, usuário); quem foi removido pode voltar. Nasce sempre de um convite.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
uidtextnão
tenant_idbigintnão
user_idbigintnão
party_idbigintnão
granted_bybigintsim
granted_attimestamptznãopadrão clock_timestamp()
removed_bybigintsim
removed_attimestamptzsim
origin_invitation_idbigintnãotodo vínculo nasce de um convite

Chaves estrangeiras

  • (origin_invitation_id, tenant_id) → invitations (id, tenant_id) (mesmo tenant)
  • (user_id, party_id) → users (id, party_id)
  • granted_by → users.id
  • removed_by → users.id
  • tenant_id → tenants.id
  • user_id → users.id

Referenciada por: bank_user_transfers, broker_prospects, membership_access_profiles, membership_brokers, membership_portfolios, membership_teams, party_contacts, portfolio_transfers, session_memberships, task_run_user_actors.

Garantido pelo banco

TipoNomeDefinição
PKmemberships_pkeyPRIMARY KEY (id)
UNIQUEmemberships_id_party_keyUNIQUE (id, party_id)
UNIQUEmemberships_id_party_tenant_keyUNIQUE (id, party_id, tenant_id)
UNIQUEmemberships_id_tenant_keyUNIQUE (id, tenant_id)
UNIQUEmemberships_id_user_tenant_keyUNIQUE (id, user_id, tenant_id)
UNIQUEmemberships_uid_uniqueUNIQUE (uid)
UNIQUE parcialmemberships_live_key(tenant_id, user_id) WHERE (removed_at IS NULL)

Fora do banco

  • Nenhuma regra registrada além das constraints acima.

membership_access_profiles

Perfil do tenant concedido à membership para o tenant inteiro, com vigência.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
tenant_idbigintnão
membership_idbigintnão
access_profile_idbigintnãoperfil do tenant (broker_id nulo)
access_profile_scopetextnãoCHECK = 'tenant': só perfil do tenant
valid_fromdatenão
valid_untildatesim
granted_by_user_idbigintsimação direta
origin_invitation_grant_idbigintsimou: veio de convite
created_attimestamptznãopadrão clock_timestamp()

Chaves estrangeiras

  • (access_profile_id, tenant_id, access_profile_scope) → access_profiles (id, tenant_id, scope) (mesmo tenant)
  • (membership_id, tenant_id) → memberships (id, tenant_id) (mesmo tenant)
  • granted_by_user_id → users.id
  • origin_invitation_grant_id → invitation_grants.id

Garantido pelo banco

TipoNomeDefinição
CHECKmembership_access_profiles_scope_checkCHECK ((access_profile_scope = 'tenant'))
PKmembership_access_profiles_pkeyPRIMARY KEY (id)
UNIQUE parcialmembership_access_profiles_live_key(membership_id, access_profile_id) WHERE (valid_until IS NULL)

Fora do banco

  • Não há CHECK de ordem do período nem EXCLUDE de sobreposição; só a unicidade da ligação aberta é garantida.
  • Ter ao menos uma origem (granted_by_user_id ou origin_invitation_grant_id) não tem CHECK.

membership_brokers

Atuar como usuário de um corretor, com um perfil daquele corretor. É o vínculo sob o qual a ação do usuário de corretor é auditada. user_id é cópia de memberships.user_id, presa por FK.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
tenant_idbigintnão
membership_idbigintnão
user_idbigintnãocópia de memberships.user_id, presa por FK
broker_idbigintnão
access_profile_idbigintnãoperfil daquele corretor
valid_fromdatenão
valid_untildatesim
granted_by_user_idbigintsimação direta
origin_invitation_grant_idbigintsimou: veio de convite
removed_by_user_idbigintsim
created_attimestamptznãopadrão clock_timestamp()

Chaves estrangeiras

  • (access_profile_id, tenant_id, broker_id) → access_profiles (id, tenant_id, broker_id) (mesmo tenant)
  • (membership_id, tenant_id) → memberships (id, tenant_id) (mesmo tenant)
  • (membership_id, user_id, tenant_id) → memberships (id, user_id, tenant_id) (mesmo tenant)
  • (tenant_id, broker_id) → tenant_brokers (tenant_id, broker_id) (mesmo tenant)
  • granted_by_user_id → users.id
  • origin_invitation_grant_id → invitation_grants.id
  • removed_by_user_id → users.id

Referenciada por: bank_user_assignments, session_membership_brokers.

Garantido pelo banco

TipoNomeDefinição
PKmembership_brokers_pkeyPRIMARY KEY (id)
UNIQUEmembership_brokers_id_tenant_broker_user_keyUNIQUE (id, tenant_id, broker_id, user_id)
UNIQUE parcialmembership_brokers_live_key(membership_id, broker_id) WHERE (valid_until IS NULL)

Fora do banco

  • Não há CHECK de ordem do período nem EXCLUDE de sobreposição; só uma ligação aberta por (membership, corretor) é garantida.
  • Ter ao menos uma origem não tem CHECK.

teams

Time do tenant (agrupamento comercial ou organizacional). O CNPJ de origem é opcional e não concede acesso nem isola dados.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
uidtextnão
tenant_idbigintnão
tenant_account_idbigintsimCNPJ de origem opcional; não restringe sozinho os contextos atendidos nem concede acesso
nametextnão
descriptiontextsim
disabled_attimestamptzsim
created_by_user_idbigintnão
created_attimestamptznãopadrão clock_timestamp()
updated_attimestamptznãopadrão clock_timestamp()

Chaves estrangeiras

  • (tenant_account_id, tenant_id) → tenant_accounts (id, tenant_id) (mesmo tenant)
  • created_by_user_id → users.id
  • tenant_id → tenants.id

Referenciada por: invitation_grants, membership_teams, team_financial_institution_accounts.

Garantido pelo banco

TipoNomeDefinição
PKteams_pkeyPRIMARY KEY (id)
UNIQUEteams_id_tenant_keyUNIQUE (id, tenant_id)
UNIQUEteams_tenant_name_keyUNIQUE (tenant_id, name)
UNIQUEteams_uid_uniqueUNIQUE (uid)

Fora do banco

  • Nenhuma regra registrada além das constraints acima.

membership_teams

Pessoa no time, com um perfil do tenant e vigência [valid_from, valid_until) sem sobreposição para o mesmo par (time, membership).

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
tenant_idbigintnão
team_idbigintnão
membership_idbigintnãopessoa no tenant; não confundir com membership_brokers
access_profile_idbigintnãoo que a pessoa pode fazer no time
access_profile_scopetextnãoCHECK = 'tenant': só perfil do tenant
valid_fromdatenão
valid_untildatesim
added_by_user_idbigintsimação direta
origin_invitation_grant_idbigintsimou: veio de convite
created_attimestamptznãopadrão clock_timestamp()

Chaves estrangeiras

  • (access_profile_id, tenant_id, access_profile_scope) → access_profiles (id, tenant_id, scope) (mesmo tenant)
  • (membership_id, tenant_id) → memberships (id, tenant_id) (mesmo tenant)
  • (team_id, tenant_id) → teams (id, tenant_id) (mesmo tenant)
  • added_by_user_id → users.id
  • origin_invitation_grant_id → invitation_grants.id

Referenciada por: membership_portfolios, team_hierarchies.

Garantido pelo banco

TipoNomeDefinição
CHECKmembership_team_periodCHECK (((valid_until IS NULL) OR (valid_until > valid_from)))
CHECKmembership_teams_scope_checkCHECK ((access_profile_scope = 'tenant'))
PKmembership_teams_pkeyPRIMARY KEY (id)
UNIQUEmembership_teams_id_tenant_keyUNIQUE (id, tenant_id)
UNIQUEmembership_teams_id_tenant_membership_team_keyUNIQUE (id, tenant_id, membership_id, team_id)
EXCLUDEmembership_team_no_overlapEXCLUDE USING gist (team_id WITH =, membership_id WITH =, daterange(valid_from, valid_until, '[)') WITH &&)
UNIQUE parcialmembership_teams_live_key(team_id, membership_id) WHERE (valid_until IS NULL)

Fora do banco

  • Encerrar a participação exige tratar na mesma transação as carteiras e arestas de hierarquia que dependem dela.

membership_portfolios

Carteira: um corretor atendido por uma pessoa num time, coberta por uma membership_teams da mesma pessoa, time e tenant. Um corretor tem no máximo uma carteira aberta por tenant.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
tenant_idbigintnão
membership_idbigintnão
team_idbigintnão
membership_team_idbigintnão
broker_idbigintnão
valid_fromdatenão
valid_untildatesim
assigned_by_user_idbigintsimação direta
origin_invitation_grant_idbigintsimou: veio de convite
created_attimestamptznãopadrão clock_timestamp()

Chaves estrangeiras

  • (membership_id, tenant_id) → memberships (id, tenant_id) (mesmo tenant)
  • (membership_team_id, tenant_id, membership_id, team_id) → membership_teams (id, tenant_id, membership_id, team_id) (mesmo tenant)
  • (tenant_id, broker_id) → tenant_brokers (tenant_id, broker_id) (mesmo tenant)
  • assigned_by_user_id → users.id
  • origin_invitation_grant_id → invitation_grants.id

Referenciada por: portfolio_transfer_items.

Garantido pelo banco

TipoNomeDefinição
CHECKmembership_portfolio_periodCHECK (((valid_until IS NULL) OR (valid_until > valid_from)))
PKmembership_portfolios_pkeyPRIMARY KEY (id)
UNIQUEmembership_portfolios_id_tenant_broker_keyUNIQUE (id, tenant_id, broker_id)
UNIQUE parcialmembership_portfolios_live_key(tenant_id, broker_id) WHERE (valid_until IS NULL)

Fora do banco

  • A vigência da carteira caber na vigência de membership_teams não é verificada pelo banco.
  • Identidades e valid_from imutáveis após a atribuição são regra da aplicação.

team_financial_institution_accounts

Contextos que um time atende: time → vínculo CNPJ × IF existente, com vigência sem sobreposição para o mesmo par. Não é propriedade da conta nem concede leitura da produção de outros corretores.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
tenant_idbigintnão
team_idbigintnão
financial_institution_account_idbigintnão
valid_fromdatenão
valid_untildatesimexclusivo; nulo = sem fim definido
created_by_user_idbigintnão
created_attimestamptznãopadrão clock_timestamp()

Chaves estrangeiras

  • (financial_institution_account_id, tenant_id) → financial_institution_accounts (id, tenant_id) (mesmo tenant)
  • (team_id, tenant_id) → teams (id, tenant_id) (mesmo tenant)
  • created_by_user_id → users.id

Garantido pelo banco

TipoNomeDefinição
CHECKteam_fi_service_periodCHECK (((valid_until IS NULL) OR (valid_until > valid_from)))
PKteam_financial_institution_accounts_pkeyPRIMARY KEY (id)
EXCLUDEteam_fi_service_no_overlapEXCLUDE USING gist (team_id WITH =, financial_institution_account_id WITH =, daterange(valid_from, valid_until, '[)') WITH &&)

Fora do banco

  • Nenhuma regra registrada além das constraints acima.

team_hierarchies

Aresta organizacional temporal entre duas participações em time (subordinado e superior), com motivo. A hierarquia é configurável e não concede permissão.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
tenant_idbigintnão
subordinate_membership_team_idbigintnão
superior_membership_team_idbigintnão
valid_fromdatenão
valid_untildatesimexclusivo; nulo = sem fim definido
recorded_by_user_idbigintnão
reasontextnão
recorded_attimestamptznãopadrão clock_timestamp()

Chaves estrangeiras

  • (subordinate_membership_team_id, tenant_id) → membership_teams (id, tenant_id) (mesmo tenant)
  • (superior_membership_team_id, tenant_id) → membership_teams (id, tenant_id) (mesmo tenant)
  • recorded_by_user_id → users.id

Garantido pelo banco

TipoNomeDefinição
CHECKteam_hierarchy_distinct_endpointsCHECK ((subordinate_membership_team_id <> superior_membership_team_id))
CHECKteam_hierarchy_periodCHECK (((valid_until IS NULL) OR (valid_until > valid_from)))
CHECKteam_hierarchy_reasonCHECK ((length(btrim(reason)) > 0))
PKteam_hierarchies_pkeyPRIMARY KEY (id)
EXCLUDEteam_hierarchy_edge_no_overlapEXCLUDE USING gist (subordinate_membership_team_id WITH =, superior_membership_team_id WITH =, daterange(valid_from, valid_until, '[)') WITH &&)

Fora do banco

  • Ausência de ciclos, cobertura da vigência pelas duas membership_teams e inserções concorrentes ainda não são garantidas: exigem constraint trigger ou protocolo transacional. O EXCLUDE só impede a mesma aresta sobreposta no tempo.

portfolio_transfers

Cabeçalho imutável de uma transferência manual de carteiras, com ator, motivo e data efetiva; uid identifica a operação idempotente.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
uidtextnão
tenant_idbigintnão
actor_user_idbigintnão
actor_membership_idbigintnão
reasontextnão
effective_ondatenão
recorded_attimestamptznãopadrão clock_timestamp()

Chaves estrangeiras

  • (actor_membership_id, actor_user_id, tenant_id) → memberships (id, user_id, tenant_id) (mesmo tenant)

Referenciada por: portfolio_transfer_items.

Garantido pelo banco

TipoNomeDefinição
CHECKportfolio_transfer_reasonCHECK ((length(btrim(reason)) > 0))
PKportfolio_transfers_pkeyPRIMARY KEY (id)
UNIQUEportfolio_transfers_id_tenant_keyUNIQUE (id, tenant_id)
UNIQUEportfolio_transfers_tenant_uid_keyUNIQUE (tenant_id, uid)

Fora do banco

  • Conter ao menos um item e gravar cabeçalho, itens, fechamento das origens e abertura dos destinos numa única transação são regras da aplicação.

portfolio_transfer_items

Cada corretor transferido: carteira de origem e de destino do mesmo corretor e tenant; uma carteira só aparece uma vez como origem e uma vez como destino.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
tenant_idbigintnão
portfolio_transfer_idbigintnão
broker_idbigintnão
from_membership_portfolio_idbigintnão
to_membership_portfolio_idbigintnão

Chaves estrangeiras

  • (from_membership_portfolio_id, tenant_id, broker_id) → membership_portfolios (id, tenant_id, broker_id) (mesmo tenant)
  • (portfolio_transfer_id, tenant_id) → portfolio_transfers (id, tenant_id) (mesmo tenant)
  • (to_membership_portfolio_id, tenant_id, broker_id) → membership_portfolios (id, tenant_id, broker_id) (mesmo tenant)

Garantido pelo banco

TipoNomeDefinição
CHECKportfolio_transfer_distinct_portfoliosCHECK ((from_membership_portfolio_id <> to_membership_portfolio_id))
PKportfolio_transfer_items_pkeyPRIMARY KEY (id)
UNIQUEportfolio_transfer_items_from_membership_portfolio_id_uniqueUNIQUE (from_membership_portfolio_id)
UNIQUEportfolio_transfer_items_to_membership_portfolio_id_uniqueUNIQUE (to_membership_portfolio_id)
UNIQUEportfolio_transfer_items_transfer_broker_keyUNIQUE (portfolio_transfer_id, broker_id)

Fora do banco

  • Destino com a mesma pessoa e o mesmo time da origem é recusado na aplicação.
  • A vigência do destino caber em membership_teams não é verificada pelo banco.

invitations

Convite para um tenant: canal, destino, SHA-256 do token, estado e validade. Não cria nada sozinho: conta e vínculos nascem no aceite.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
uidtextnão
tenant_idbigintnão
channeltextnãoemail | phone
destinationtextnão
destination_normalizedtextnão
token_sha256byteanãoo link leva o token; aqui só o hash
statustextnãopending | accepted | revoked | expired
expires_attimestamptznão
created_by_user_idbigintsimação humana; com tenant_id identifica a membership
created_by_processtextsimbroker_activation | seed | …
accepted_attimestamptzsim
accepted_by_user_idbigintsim
revoked_attimestamptzsim
revoked_by_user_idbigintsim
created_attimestamptznãopadrão clock_timestamp()

Chaves estrangeiras

  • accepted_by_user_id → users.id
  • created_by_user_id → users.id
  • revoked_by_user_id → users.id
  • tenant_id → tenants.id

Referenciada por: invitation_deliveries, invitation_grants, invitation_session_contexts, memberships.

Garantido pelo banco

TipoNomeDefinição
CHECKinvitations_channel_checkCHECK ((channel IN ('email', 'phone')))
CHECKinvitations_creator_checkCHECK ((num_nonnulls(created_by_user_id, created_by_process) = 1))
CHECKinvitations_status_checkCHECK ((status IN ('pending', 'accepted', 'revoked', 'expired')))
PKinvitations_pkeyPRIMARY KEY (id)
UNIQUEinvitations_id_tenant_keyUNIQUE (id, tenant_id)
UNIQUEinvitations_token_sha256_uniqueUNIQUE (token_sha256)
UNIQUEinvitations_uid_uniqueUNIQUE (uid)

Fora do banco

  • O teto de concessão é conferido na criação e no aceite, pela aplicação.

invitation_grants

O que o aceite do convite vai criar: perfil do tenant, atuação em corretor, time ou carteira. access_profile_scope é gerada a partir de kind.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
tenant_idbigintnão
invitation_idbigintnão
kindtextnãoaccess_profile | broker | team | portfolio
access_profile_idbigintsim
access_profile_scopetextsimgerada: CASE kind WHEN 'broker' THEN 'broker' WHEN 'access_profile' THEN 'tenant' WHEN 'team' THEN 'tenant' ELSE NULL::text END
broker_idbigintsim
team_idbigintsim

Chaves estrangeiras

  • (access_profile_id, tenant_id, access_profile_scope) → access_profiles (id, tenant_id, scope) (mesmo tenant)
  • (invitation_id, tenant_id) → invitations (id, tenant_id) (mesmo tenant)
  • (team_id, tenant_id) → teams (id, tenant_id) (mesmo tenant)
  • (tenant_id, broker_id) → tenant_brokers (tenant_id, broker_id) (mesmo tenant)

Referenciada por: membership_access_profiles, membership_brokers, membership_portfolios, membership_teams.

Garantido pelo banco

TipoNomeDefinição
CHECKinvitation_grants_kind_checkCHECK ((kind IN ('access_profile', 'broker', 'team', 'portfolio')))
CHECKinvitation_grants_kind_columns_checkCHECK ( CASE kind WHEN 'access_profile' THEN ((access_profile_id IS NOT NULL) AND (broker_id IS NULL) AND (team_id IS NULL)) WHEN 'broker' THEN ((access_profile_id IS NOT NULL) AND (broker_id IS NOT NULL) AND (team_id IS NULL)) WHEN 'team' THEN ((access_profile_id IS NOT NULL) AND (broker_id IS NULL) AND (team_id IS NOT NULL)) WHEN 'portfolio' THEN ((access_profile_id IS NULL) AND (broker_id IS NOT NULL) AND (team_id IS NOT NULL)) ELSE false END)
PKinvitation_grants_pkeyPRIMARY KEY (id)
Coluna geradaaccess_profile_scopeSTORED

Fora do banco

  • Para portfolio, o aceite resolve a membership_teams da pessoa no time; ausência, ambiguidade ou vigência incompatível recusam a concessão inteira.

invitation_session_contexts

Existe só quando um operador de plataforma, dentro de um session_context, emite o convite.

ColunaTipoNuloObservação
invitation_idbigintnão
tenant_idbigintnão
session_context_idbigintnãooperador de plataforma que emitiu o convite

Chaves estrangeiras

  • (invitation_id, tenant_id) → invitations (id, tenant_id) (mesmo tenant)
  • (session_context_id, tenant_id) → session_contexts (id, tenant_id) (mesmo tenant)

Garantido pelo banco

TipoNomeDefinição
PKinvitation_session_contexts_pkeyPRIMARY KEY (invitation_id)

Fora do banco

  • Nenhuma regra registrada além das constraints acima.

invitation_deliveries

Cada tentativa de envio de um convite de tenant; reenvio é uma linha nova; exatamente um solicitante.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
uidtextnão
invitation_idbigintnão
tenant_idbigintnão
channeltextnãoemail | sms | whatsapp
destination_normalizedtextnãofoto no envio
providertextnãoses | sendgrid | twilio | zenvia …
provider_message_idtextsim
statustextnãoqueued | sent | delivered | opened | clicked | bounced | failed | complained
queued_attimestamptznãopadrão clock_timestamp()
sent_attimestamptzsim
delivered_attimestamptzsim
opened_attimestamptzsim
failed_attimestamptzsim
failure_reasontextsim
requested_by_user_idbigintsim
requested_by_processtextsim

Chaves estrangeiras

  • (invitation_id, tenant_id) → invitations (id, tenant_id) (mesmo tenant)
  • requested_by_user_id → users.id

Referenciada por: invitation_delivery_events.

Garantido pelo banco

TipoNomeDefinição
CHECKinvitation_deliveries_channel_checkCHECK ((channel IN ('email', 'sms', 'whatsapp')))
CHECKinvitation_deliveries_requester_checkCHECK ((num_nonnulls(requested_by_user_id, requested_by_process) = 1))
CHECKinvitation_deliveries_status_checkCHECK ((status IN ('queued', 'sent', 'delivered', 'opened', 'clicked', 'bounced', 'failed', 'complained')))
PKinvitation_deliveries_pkeyPRIMARY KEY (id)
UNIQUEinvitation_deliveries_id_tenant_keyUNIQUE (id, tenant_id)
UNIQUEinvitation_deliveries_provider_message_keyUNIQUE (provider, provider_message_id)
UNIQUEinvitation_deliveries_uid_uniqueUNIQUE (uid)

Fora do banco

  • Nenhuma regra registrada além das constraints acima.

invitation_delivery_events

Linha do tempo bruta do provedor de envio; webhook repetido não duplica.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
tenant_idbigintnão
delivery_idbigintnão
statustextnão
occurred_attimestamptznãohorário do provedor, em UTC
dedup_keytextnãoid do evento no provedor, ou sha256 do payload quando não houver
received_attimestamptznãopadrão clock_timestamp()
payloadjsonbnãopadrão '{}'::jsonb; webhook como chegou, sem token

Chaves estrangeiras

  • (delivery_id, tenant_id) → invitation_deliveries (id, tenant_id) (mesmo tenant)

Garantido pelo banco

TipoNomeDefinição
CHECKinvitation_delivery_events_payload_size_checkCHECK ((pg_column_size(payload) < 64000))
PKinvitation_delivery_events_pkeyPRIMARY KEY (id)
UNIQUEinvitation_delivery_events_dedup_keyUNIQUE (delivery_id, dedup_key)

Fora do banco

  • Nenhuma regra registrada além das constraints acima.

session_memberships

Em qual tenant uma sessão está atuando; fonte do contexto de tenant da transação. Trocar de tenant fecha a linha.

ColunaTipoNuloObservação
idbigintnãoidentity (GENERATED ALWAYS)
session_idbigintnão
tenant_idbigintnão
membership_idbigintnão
user_idbigintnãoprova que a sessão é da pessoa
selected_attimestamptznãopadrão clock_timestamp()
left_attimestamptzsimtroca de tenant fecha a linha

Chaves estrangeiras

  • (membership_id, user_id, tenant_id) → memberships (id, user_id, tenant_id) (mesmo tenant)
  • (session_id, user_id) → sessions (id, user_id)

Referenciada por: session_membership_brokers.

Garantido pelo banco

TipoNomeDefinição
PKsession_memberships_pkeyPRIMARY KEY (id)
UNIQUEsession_memberships_id_tenant_user_keyUNIQUE (id, tenant_id, user_id)
UNIQUE parcialsession_memberships_live_key(session_id) WHERE (left_at IS NULL)

Fora do banco

  • Sem sessões criadas hoje (autenticação em reconstrução).

session_membership_brokers

Existe só quando a sessão atua como usuário de um corretor; trocar de corretor abre uma nova session_memberships.

ColunaTipoNuloObservação
session_membership_idbigintnão
tenant_idbigintnão
user_idbigintnão
broker_idbigintnão
membership_broker_idbigintnãocorretor escolhido no login
selected_attimestamptznãopadrão clock_timestamp()

Chaves estrangeiras

  • (membership_broker_id, tenant_id, broker_id, user_id) → membership_brokers (id, tenant_id, broker_id, user_id) (mesmo tenant)
  • (session_membership_id, tenant_id, user_id) → session_memberships (id, tenant_id, user_id) (mesmo tenant)

Garantido pelo banco

TipoNomeDefinição
PKsession_membership_brokers_pkeyPRIMARY KEY (session_membership_id)

Fora do banco

  • Nenhuma regra registrada além das constraints acima.

Nesta página