Adicionando Features

Sistemas reais em produção precisam de mais do que endpoints CRUD gerados. Eles precisam de segurança, permissões, processamento assíncrono, jobs operacionais, publicação de eventos e, em cenários SaaS, isolamento por tenant.


O Lino adiciona essas capacidades como features padronizadas. Cada feature atualiza metadados do projeto, gera código-fonte, adiciona configuração e mantém backend, frontend, mensageria e persistência alinhados com a mesma arquitetura.

Autenticação e autorização

A feature de autenticação adiciona a base de segurança usada por projetos Lino para proteger APIs, identificar usuários, controlar acesso a operações e integrar as mesmas permissões com Blazor Web Apps. Ela é instalada com o comando:

lino feature auth add --service <ServiceName> --module <ModuleName>

O comando também pode ser executado de forma interativa com lino feature auth add. O branch canônico é feature auth; o CLI também expõe aliases como feature security e feature identity.

Na arquitetura atual do Lino, autenticação e autorização dependem de mensageria assíncrona. O motivo é operacional: permissões de serviços e módulos são sincronizadas por eventos de integração, então o projeto precisa ter mensageria habilitada antes de adicionar segurança.

O que o assistente solicita

O CLI valida o projeto atual, verifica se a feature ainda não foi instalada, pergunta onde o módulo de segurança deve ser criado e solicita as principais configurações de token.

  • Serviço: serviço que hospedará os recursos de segurança.
  • Módulo: módulo de destino quando o serviço selecionado é modular.
  • Lifetime do access token: tempo de vida, em minutos, dos tokens de acesso emitidos.
  • Lifetime do refresh token: tempo de vida dos tokens usados para renovar sessões.
  • Tipo de identificador do usuário: tipo de dado usado como identificador do usuário, como int, long ou Guid.

Modelo de segurança gerado

Após a confirmação, o Lino atualiza os metadados do projeto, cria valores de configuração de segurança, gera arquivos de código-fonte e executa os comandos necessários. O modelo gerado inclui as entidades centrais de segurança:

  • User armazena identidades e dados de perfil.
  • Role e associações de roles para agrupar regras de acesso.
  • Permission e relações entre roles e permissões para autorização granular.
  • UserToken para controle de refresh tokens e ciclo de vida de tokens.

A feature também cria as informações necessárias para configuração de segurança, como o segredo para assinatura de tokens e os tempos de vida do access token e do refresh token. Valores sensíveis são emitidos como comandos para user secrets do AppHost, em vez de serem gravados diretamente em arquivos versionados.

Comportamento em runtime

A API usa autenticação JWT Bearer. O usuário realiza login, recebe um access token e um refresh token, e passa a enviar requisições para a API com o header Authorization: Bearer <token>. O backend valida o token, carrega o contexto do usuário e aplica as regras de autorização nos endpoints.

O fluxo típico continua sendo simples: login por endpoint ou página dedicada, emissão de JWT com claims de identidade, roles e permissões, envio do token em cada requisição e validação de assinatura e expiração pelo middleware de autenticação.

O Lino utiliza políticas e permissões para implementar autorização granular. Cada ação pode exigir uma permissão específica, como People.Read ou People.Create; policies podem ser configuradas via AddAuthorization; e endpoints podem ser protegidos declarando .RequireAuthorization.

Endpoints e páginas gerados usam permissões de forma consistente. Operações no backend podem exigir permissões, enquanto a UI Blazor gerada pode carregar permissões, proteger páginas, ocultar ações indisponíveis e expor telas para usuários, roles, permissões e autorizações quando há uma Web App no projeto.

Quando background jobs já estão habilitados, o Lino também adiciona jobs relacionados a tokens de usuário, como rotinas de manutenção para tokens desabilitados ou expirados.

Processamento em segundo plano e Outbox

Background processing trata trabalhos que não devem bloquear o fluxo principal de requisição e resposta: publicação de eventos de integração, limpeza de registros antigos, remoção de tokens expirados, envio de notificações, geração de relatórios, sincronização com sistemas externos ou execução de tarefas agendadas. O Lino adiciona essa capacidade por meio da feature de background job:

lino feature background-job add --service <ServiceName>

O comando também pode ser executado como lino feature background-job add e concluído de forma interativa. O CLI expõe aliases como job-scheduler e worker.

Essa feature requer mensageria habilitada no projeto, porque sua principal responsabilidade é publicar com segurança mensagens registradas pelo padrão Transactional Outbox.

O que o assistente solicita

  • Serviço: serviço no qual a infraestrutura de background jobs será instalada.
  • Biblioteca de background job: implementação usada para execução e agendamento de jobs. A infraestrutura gerada atualmente usa Hangfire.
  • Processamento de Outbox: define se o serviço registrará eventos para serem processados pelo scheduler.
  • Agendamento da Outbox: intervalo ou expressão de agenda usada para verificar novas mensagens Outbox.
  • Tamanho do lote da Outbox: quantidade de registros Outbox recuperados e processados por ciclo, controlando carga, paralelismo e consumo de recursos.

Infraestrutura Hangfire

O Lino gera a infraestrutura necessária para registrar o Hangfire, configurar sua persistência, expor o dashboard e agendar os jobs usados pelo serviço. A configuração gerada inclui as informações necessárias para agendar jobs, processar mensagens da Outbox e proteger o acesso ao dashboard do scheduler.

Em soluções geradas, o schema e as tabelas do Hangfire fazem parte da configuração do banco de dados da aplicação. O dashboard ajuda a inspecionar jobs concluídos, falhos, agendados e recorrentes durante desenvolvimento e operação.

Os benefícios práticos incluem execução confiável de tarefas assíncronas, painel de monitoramento embutido, suporte a jobs recorrentes ou agendados e persistência dos jobs no banco de dados.

Processamento com Transactional Outbox

Para garantir consistência em integrações assíncronas, o Lino usa o padrão Transactional Outbox. Um caso de uso de negócio persiste mudanças de domínio e registra um evento de integração na tabela Outbox dentro da mesma transação. Depois, o background job lê a tabela Outbox e publica o evento por meio do barramento de mensagens configurado, como RabbitMQ com MassTransit quando essas opções foram selecionadas para o projeto.

  1. Um comando altera o estado do domínio e salva essa alteração em uma transação.
  2. Um handler registra um evento de integração na Outbox, por exemplo um evento relacionado à criação de um pedido.
  3. O job do Hangfire bloqueia um lote de mensagens não processadas e marca essas mensagens como em processamento.
  4. Cada mensagem é desserializada e publicada pelo event bus.
  5. Mensagens bem-sucedidas são marcadas como processadas; mensagens com falha preservam informações de erro para análise posterior ou estratégia de retry.

O resultado é atomicidade entre banco de dados e eventos registrados, confiabilidade para que eventos não sejam perdidos em caso de falha e escalabilidade para que múltiplos consumidores processem mensagens publicadas.

O job gerado também inclui rotinas para remover mensagens Outbox antigas já processadas com sucesso e liberar mensagens que ficaram presas em processamento, reduzindo o risco de locks permanentes após falhas da aplicação.

Quando autenticação está instalada, a feature de background job também pode hospedar jobs de manutenção de tokens, mantendo os dados de segurança limpos ao longo do tempo.

Com esses recursos adicionais, o Lino oferece segurança robusta, controle granular de acesso e processamento assíncrono confiável para requisitos críticos de aplicações modernas em produção.

Multi-tenancy

Multi-tenancy é a feature usada quando a mesma aplicação precisa atender múltiplos clientes, organizações ou ambientes mantendo dados, permissões e configurações de cada tenant isolados. No Lino, o suporte a tenants é adicionado com:

lino feature tenant add --service <ServiceName> --module <ModuleName>

O comando também pode ser executado de forma interativa com lino feature tenant add. O branch do CLI também expõe aliases como tenancy.

Pré-requisitos

O suporte a tenant depende de duas capacidades arquiteturais:

  • Autenticação e autorização, porque acesso de usuários, roles, permissões e tokens precisam ser tenant-aware.
  • Mensageria, porque informações de tenants e usuários podem ser propagadas para outros módulos por eventos de integração.

Se esses pré-requisitos estiverem ausentes, o comando é rejeitado. A feature também só pode ser instalada uma vez por projeto.

O que é gerado

O Lino cria o modelo de tenancy, configuração, eventos, integração com API e recursos de frontend necessários para gerenciar tenants de forma consistente.

  • Tenant armazena identidade, nome, slug, status, modo de isolamento e referência de connection string do tenant.
  • TenantBranding armazena dados de branding para comportamento visual específico por tenant.
  • TenantDomain mapeia hosts ou domínios para tenants.
  • TenantStatus e IsolationMode definem ciclo de vida do tenant e opções de isolamento de dados.
  • A configuração gerada dá suporte à resolução de tenants e ao isolamento de dados do projeto.

Segurança tenant-aware

Tenancy muda a forma como autenticação e autorização são interpretadas. Um token e uma permissão válidos são avaliados dentro do contexto do tenant atual; um usuário com acesso em um tenant não recebe automaticamente acesso a outro tenant. Por isso o suporte a tenant atualiza fluxos de autenticação, comportamento de refresh tokens, permissões e referências geradas para a UI.

Em aplicações Blazor geradas, telas tenant-aware podem ser adicionadas para gerenciamento de tenants e fluxos de autorização. No backend, endpoints gerados podem resolver o contexto do tenant a partir de host, slug ou comportamento de rota configurado, e então aplicar o identificador do tenant em decisões de dados e autorização.

Isolamento de dados e propagação

O Lino dá suporte a modelagem de domínio tenant-aware permitindo que entidades declarem propriedade por tenant. Em cenários SaaS, isso permite que tabelas de negócio armazenem dados específicos por tenant enquanto módulos compartilhados continuam recebendo as informações de tenant e usuário de que precisam.

A arquitetura gerada usa eventos e o padrão Outbox para propagar dados selecionados de tenants ou usuários entre módulos sem acoplar todos os módulos diretamente às tabelas originais de Identity ou Tenancy. Isso mantém os limites dos módulos claros, enquanto telas, APIs, permissões e consultas continuam operando com contexto de tenant.

Após adicionar tenancy, crie e aplique migrations para o serviço afetado, revise secrets e API keys gerados, execute o AppHost e valide com pelo menos dois tenants para garantir que dados, usuários, roles, permissões e registros de negócio permaneçam isolados.

  • Valide isolamento: crie testes tentando acessar dados de outro tenant.
  • Revise permissões: um usuário pode ter papéis diferentes em tenants diferentes.
  • Evite confiar no cliente: tenant informado por rota, host, slug ou header precisa ser compatível com o usuário autenticado.
Ocorreu um erro não tratado. Recarregar 🗙