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)
| Tabela | Para quê |
|---|---|
memberships | Pessoa × tenant: usuário, party e quem concedeu ou removeu. |
membership_access_profiles | Perfil do tenant concedido à membership para o tenant inteiro, com vigência. |
membership_brokers | Atuar como usuário de um corretor, com um perfil daquele corretor. |
teams | Time do tenant (agrupamento comercial ou organizacional). |
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). |
membership_portfolios | Carteira: um corretor atendido por uma pessoa num time, coberta por uma membership_teams da mesma pessoa, time e tenant. |
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. |
team_hierarchies | Aresta organizacional temporal entre duas participações em time (subordinado e superior), com motivo. |
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. |
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. |
invitations | Convite para um tenant: canal, destino, SHA-256 do token, estado e validade. |
invitation_grants | O que o aceite do convite vai criar: perfil do tenant, atuação em corretor, time ou carteira. |
invitation_session_contexts | Existe só quando um operador de plataforma, dentro de um session_context, emite o convite. |
invitation_deliveries | Cada tentativa de envio de um convite de tenant; reenvio é uma linha nova; exatamente um solicitante. |
invitation_delivery_events | Linha do tempo bruta do provedor de envio; webhook repetido não duplica. |
session_memberships | Em qual tenant uma sessão está atuando; fonte do contexto de tenant da transaçã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. |
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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
uid | text | não | |
tenant_id | bigint | não | |
user_id | bigint | não | |
party_id | bigint | não | |
granted_by | bigint | sim | |
granted_at | timestamptz | não | padrão clock_timestamp() |
removed_by | bigint | sim | |
removed_at | timestamptz | sim | |
origin_invitation_id | bigint | não | todo 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.idremoved_by→users.idtenant_id→tenants.iduser_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
| Tipo | Nome | Definição |
|---|---|---|
| PK | memberships_pkey | PRIMARY KEY (id) |
| UNIQUE | memberships_id_party_key | UNIQUE (id, party_id) |
| UNIQUE | memberships_id_party_tenant_key | UNIQUE (id, party_id, tenant_id) |
| UNIQUE | memberships_id_tenant_key | UNIQUE (id, tenant_id) |
| UNIQUE | memberships_id_user_tenant_key | UNIQUE (id, user_id, tenant_id) |
| UNIQUE | memberships_uid_unique | UNIQUE (uid) |
| UNIQUE parcial | memberships_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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
tenant_id | bigint | não | |
membership_id | bigint | não | |
access_profile_id | bigint | não | perfil do tenant (broker_id nulo) |
access_profile_scope | text | não | CHECK = 'tenant': só perfil do tenant |
valid_from | date | não | |
valid_until | date | sim | |
granted_by_user_id | bigint | sim | ação direta |
origin_invitation_grant_id | bigint | sim | ou: veio de convite |
created_at | timestamptz | não | padrã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.idorigin_invitation_grant_id→invitation_grants.id
Garantido pelo banco
| Tipo | Nome | Definição |
|---|---|---|
| CHECK | membership_access_profiles_scope_check | CHECK ((access_profile_scope = 'tenant')) |
| PK | membership_access_profiles_pkey | PRIMARY KEY (id) |
| UNIQUE parcial | membership_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_idouorigin_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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
tenant_id | bigint | não | |
membership_id | bigint | não | |
user_id | bigint | não | cópia de memberships.user_id, presa por FK |
broker_id | bigint | não | |
access_profile_id | bigint | não | perfil daquele corretor |
valid_from | date | não | |
valid_until | date | sim | |
granted_by_user_id | bigint | sim | ação direta |
origin_invitation_grant_id | bigint | sim | ou: veio de convite |
removed_by_user_id | bigint | sim | |
created_at | timestamptz | não | padrã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.idorigin_invitation_grant_id→invitation_grants.idremoved_by_user_id→users.id
Referenciada por: bank_user_assignments, session_membership_brokers.
Garantido pelo banco
| Tipo | Nome | Definição |
|---|---|---|
| PK | membership_brokers_pkey | PRIMARY KEY (id) |
| UNIQUE | membership_brokers_id_tenant_broker_user_key | UNIQUE (id, tenant_id, broker_id, user_id) |
| UNIQUE parcial | membership_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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
uid | text | não | |
tenant_id | bigint | não | |
tenant_account_id | bigint | sim | CNPJ de origem opcional; não restringe sozinho os contextos atendidos nem concede acesso |
name | text | não | |
description | text | sim | |
disabled_at | timestamptz | sim | |
created_by_user_id | bigint | não | |
created_at | timestamptz | não | padrão clock_timestamp() |
updated_at | timestamptz | não | padrão clock_timestamp() |
Chaves estrangeiras
(tenant_account_id, tenant_id)→tenant_accounts (id, tenant_id)(mesmo tenant)created_by_user_id→users.idtenant_id→tenants.id
Referenciada por: invitation_grants, membership_teams, team_financial_institution_accounts.
Garantido pelo banco
| Tipo | Nome | Definição |
|---|---|---|
| PK | teams_pkey | PRIMARY KEY (id) |
| UNIQUE | teams_id_tenant_key | UNIQUE (id, tenant_id) |
| UNIQUE | teams_tenant_name_key | UNIQUE (tenant_id, name) |
| UNIQUE | teams_uid_unique | UNIQUE (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).
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
tenant_id | bigint | não | |
team_id | bigint | não | |
membership_id | bigint | não | pessoa no tenant; não confundir com membership_brokers |
access_profile_id | bigint | não | o que a pessoa pode fazer no time |
access_profile_scope | text | não | CHECK = 'tenant': só perfil do tenant |
valid_from | date | não | |
valid_until | date | sim | |
added_by_user_id | bigint | sim | ação direta |
origin_invitation_grant_id | bigint | sim | ou: veio de convite |
created_at | timestamptz | não | padrã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.idorigin_invitation_grant_id→invitation_grants.id
Referenciada por: membership_portfolios, team_hierarchies.
Garantido pelo banco
| Tipo | Nome | Definição |
|---|---|---|
| CHECK | membership_team_period | CHECK (((valid_until IS NULL) OR (valid_until > valid_from))) |
| CHECK | membership_teams_scope_check | CHECK ((access_profile_scope = 'tenant')) |
| PK | membership_teams_pkey | PRIMARY KEY (id) |
| UNIQUE | membership_teams_id_tenant_key | UNIQUE (id, tenant_id) |
| UNIQUE | membership_teams_id_tenant_membership_team_key | UNIQUE (id, tenant_id, membership_id, team_id) |
| EXCLUDE | membership_team_no_overlap | EXCLUDE USING gist (team_id WITH =, membership_id WITH =, daterange(valid_from, valid_until, '[)') WITH &&) |
| UNIQUE parcial | membership_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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
tenant_id | bigint | não | |
membership_id | bigint | não | |
team_id | bigint | não | |
membership_team_id | bigint | não | |
broker_id | bigint | não | |
valid_from | date | não | |
valid_until | date | sim | |
assigned_by_user_id | bigint | sim | ação direta |
origin_invitation_grant_id | bigint | sim | ou: veio de convite |
created_at | timestamptz | não | padrã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.idorigin_invitation_grant_id→invitation_grants.id
Referenciada por: portfolio_transfer_items.
Garantido pelo banco
| Tipo | Nome | Definição |
|---|---|---|
| CHECK | membership_portfolio_period | CHECK (((valid_until IS NULL) OR (valid_until > valid_from))) |
| PK | membership_portfolios_pkey | PRIMARY KEY (id) |
| UNIQUE | membership_portfolios_id_tenant_broker_key | UNIQUE (id, tenant_id, broker_id) |
| UNIQUE parcial | membership_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_teamsnão é verificada pelo banco. - Identidades e
valid_fromimutá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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
tenant_id | bigint | não | |
team_id | bigint | não | |
financial_institution_account_id | bigint | não | |
valid_from | date | não | |
valid_until | date | sim | exclusivo; nulo = sem fim definido |
created_by_user_id | bigint | não | |
created_at | timestamptz | não | padrã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
| Tipo | Nome | Definição |
|---|---|---|
| CHECK | team_fi_service_period | CHECK (((valid_until IS NULL) OR (valid_until > valid_from))) |
| PK | team_financial_institution_accounts_pkey | PRIMARY KEY (id) |
| EXCLUDE | team_fi_service_no_overlap | EXCLUDE 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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
tenant_id | bigint | não | |
subordinate_membership_team_id | bigint | não | |
superior_membership_team_id | bigint | não | |
valid_from | date | não | |
valid_until | date | sim | exclusivo; nulo = sem fim definido |
recorded_by_user_id | bigint | não | |
reason | text | não | |
recorded_at | timestamptz | não | padrã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
| Tipo | Nome | Definição |
|---|---|---|
| CHECK | team_hierarchy_distinct_endpoints | CHECK ((subordinate_membership_team_id <> superior_membership_team_id)) |
| CHECK | team_hierarchy_period | CHECK (((valid_until IS NULL) OR (valid_until > valid_from))) |
| CHECK | team_hierarchy_reason | CHECK ((length(btrim(reason)) > 0)) |
| PK | team_hierarchies_pkey | PRIMARY KEY (id) |
| EXCLUDE | team_hierarchy_edge_no_overlap | EXCLUDE 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_teamse 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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
uid | text | não | |
tenant_id | bigint | não | |
actor_user_id | bigint | não | |
actor_membership_id | bigint | não | |
reason | text | não | |
effective_on | date | não | |
recorded_at | timestamptz | não | padrã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
| Tipo | Nome | Definição |
|---|---|---|
| CHECK | portfolio_transfer_reason | CHECK ((length(btrim(reason)) > 0)) |
| PK | portfolio_transfers_pkey | PRIMARY KEY (id) |
| UNIQUE | portfolio_transfers_id_tenant_key | UNIQUE (id, tenant_id) |
| UNIQUE | portfolio_transfers_tenant_uid_key | UNIQUE (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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
tenant_id | bigint | não | |
portfolio_transfer_id | bigint | não | |
broker_id | bigint | não | |
from_membership_portfolio_id | bigint | não | |
to_membership_portfolio_id | bigint | nã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
| Tipo | Nome | Definição |
|---|---|---|
| CHECK | portfolio_transfer_distinct_portfolios | CHECK ((from_membership_portfolio_id <> to_membership_portfolio_id)) |
| PK | portfolio_transfer_items_pkey | PRIMARY KEY (id) |
| UNIQUE | portfolio_transfer_items_from_membership_portfolio_id_unique | UNIQUE (from_membership_portfolio_id) |
| UNIQUE | portfolio_transfer_items_to_membership_portfolio_id_unique | UNIQUE (to_membership_portfolio_id) |
| UNIQUE | portfolio_transfer_items_transfer_broker_key | UNIQUE (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_teamsnã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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
uid | text | não | |
tenant_id | bigint | não | |
channel | text | não | email | phone |
destination | text | não | |
destination_normalized | text | não | |
token_sha256 | bytea | não | o link leva o token; aqui só o hash |
status | text | não | pending | accepted | revoked | expired |
expires_at | timestamptz | não | |
created_by_user_id | bigint | sim | ação humana; com tenant_id identifica a membership |
created_by_process | text | sim | broker_activation | seed | … |
accepted_at | timestamptz | sim | |
accepted_by_user_id | bigint | sim | |
revoked_at | timestamptz | sim | |
revoked_by_user_id | bigint | sim | |
created_at | timestamptz | não | padrão clock_timestamp() |
Chaves estrangeiras
accepted_by_user_id→users.idcreated_by_user_id→users.idrevoked_by_user_id→users.idtenant_id→tenants.id
Referenciada por: invitation_deliveries, invitation_grants, invitation_session_contexts, memberships.
Garantido pelo banco
| Tipo | Nome | Definição |
|---|---|---|
| CHECK | invitations_channel_check | CHECK ((channel IN ('email', 'phone'))) |
| CHECK | invitations_creator_check | CHECK ((num_nonnulls(created_by_user_id, created_by_process) = 1)) |
| CHECK | invitations_status_check | CHECK ((status IN ('pending', 'accepted', 'revoked', 'expired'))) |
| PK | invitations_pkey | PRIMARY KEY (id) |
| UNIQUE | invitations_id_tenant_key | UNIQUE (id, tenant_id) |
| UNIQUE | invitations_token_sha256_unique | UNIQUE (token_sha256) |
| UNIQUE | invitations_uid_unique | UNIQUE (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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
tenant_id | bigint | não | |
invitation_id | bigint | não | |
kind | text | não | access_profile | broker | team | portfolio |
access_profile_id | bigint | sim | |
access_profile_scope | text | sim | gerada: CASE kind WHEN 'broker' THEN 'broker' WHEN 'access_profile' THEN 'tenant' WHEN 'team' THEN 'tenant' ELSE NULL::text END |
broker_id | bigint | sim | |
team_id | bigint | sim |
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
| Tipo | Nome | Definição |
|---|---|---|
| CHECK | invitation_grants_kind_check | CHECK ((kind IN ('access_profile', 'broker', 'team', 'portfolio'))) |
| CHECK | invitation_grants_kind_columns_check | CHECK ( 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) |
| PK | invitation_grants_pkey | PRIMARY KEY (id) |
| Coluna gerada | access_profile_scope | STORED |
Fora do banco
- Para
portfolio, o aceite resolve amembership_teamsda 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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
invitation_id | bigint | não | |
tenant_id | bigint | não | |
session_context_id | bigint | não | operador 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
| Tipo | Nome | Definição |
|---|---|---|
| PK | invitation_session_contexts_pkey | PRIMARY 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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
uid | text | não | |
invitation_id | bigint | não | |
tenant_id | bigint | não | |
channel | text | não | email | sms | whatsapp |
destination_normalized | text | não | foto no envio |
provider | text | não | ses | sendgrid | twilio | zenvia … |
provider_message_id | text | sim | |
status | text | não | queued | sent | delivered | opened | clicked | bounced | failed | complained |
queued_at | timestamptz | não | padrão clock_timestamp() |
sent_at | timestamptz | sim | |
delivered_at | timestamptz | sim | |
opened_at | timestamptz | sim | |
failed_at | timestamptz | sim | |
failure_reason | text | sim | |
requested_by_user_id | bigint | sim | |
requested_by_process | text | sim |
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
| Tipo | Nome | Definição |
|---|---|---|
| CHECK | invitation_deliveries_channel_check | CHECK ((channel IN ('email', 'sms', 'whatsapp'))) |
| CHECK | invitation_deliveries_requester_check | CHECK ((num_nonnulls(requested_by_user_id, requested_by_process) = 1)) |
| CHECK | invitation_deliveries_status_check | CHECK ((status IN ('queued', 'sent', 'delivered', 'opened', 'clicked', 'bounced', 'failed', 'complained'))) |
| PK | invitation_deliveries_pkey | PRIMARY KEY (id) |
| UNIQUE | invitation_deliveries_id_tenant_key | UNIQUE (id, tenant_id) |
| UNIQUE | invitation_deliveries_provider_message_key | UNIQUE (provider, provider_message_id) |
| UNIQUE | invitation_deliveries_uid_unique | UNIQUE (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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
tenant_id | bigint | não | |
delivery_id | bigint | não | |
status | text | não | |
occurred_at | timestamptz | não | horário do provedor, em UTC |
dedup_key | text | não | id do evento no provedor, ou sha256 do payload quando não houver |
received_at | timestamptz | não | padrão clock_timestamp() |
payload | jsonb | não | padrão '{}'::jsonb; webhook como chegou, sem token |
Chaves estrangeiras
(delivery_id, tenant_id)→invitation_deliveries (id, tenant_id)(mesmo tenant)
Garantido pelo banco
| Tipo | Nome | Definição |
|---|---|---|
| CHECK | invitation_delivery_events_payload_size_check | CHECK ((pg_column_size(payload) < 64000)) |
| PK | invitation_delivery_events_pkey | PRIMARY KEY (id) |
| UNIQUE | invitation_delivery_events_dedup_key | UNIQUE (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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
id | bigint | não | identity (GENERATED ALWAYS) |
session_id | bigint | não | |
tenant_id | bigint | não | |
membership_id | bigint | não | |
user_id | bigint | não | prova que a sessão é da pessoa |
selected_at | timestamptz | não | padrão clock_timestamp() |
left_at | timestamptz | sim | troca 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
| Tipo | Nome | Definição |
|---|---|---|
| PK | session_memberships_pkey | PRIMARY KEY (id) |
| UNIQUE | session_memberships_id_tenant_user_key | UNIQUE (id, tenant_id, user_id) |
| UNIQUE parcial | session_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.
| Coluna | Tipo | Nulo | Observação |
|---|---|---|---|
session_membership_id | bigint | não | |
tenant_id | bigint | não | |
user_id | bigint | não | |
broker_id | bigint | não | |
membership_broker_id | bigint | não | corretor escolhido no login |
selected_at | timestamptz | não | padrã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
| Tipo | Nome | Definição |
|---|---|---|
| PK | session_membership_brokers_pkey | PRIMARY KEY (session_membership_id) |
Fora do banco
- Nenhuma regra registrada além das constraints acima.