@marcos_feitoza/personal-finance-backend-shared
v1.5.4
Published
Este projeto contém código e utilitários compartilhados usados por todos os microsserviços do backend de finanças pessoais.
Readme
Biblioteca Compartilhada - Personal Finance Backend
Este projeto contém código e utilitários compartilhados usados por todos os microsserviços do backend de finanças pessoais.
Propósito
O objetivo desta biblioteca é centralizar a lógica de negócios, as definições de dados principais e as funcionalidades comuns para evitar a duplicação de código e garantir a consistência, manutenibilidade e observabilidade entre os serviços.
Conteúdo Principal
database.py: Gerenciamento de sessão e configuração de conexão com o banco de dados PostgreSQL.models.py: Definições das tabelas do banco de dados usando SQLAlchemy ORM.schemas.py: Modelos de dados Pydantic para validação de dados em requisições e respostas de API.crud.py: Funções comuns para operações de Create, Read, Update, Delete (CRUD) e lógica de cálculo de portfólio.auth_utils.py: Utilitários para hashing de senhas e manipulação de JWT (JSON Web Tokens).dependencies.py: Dependências do FastAPI para autenticação de usuário (extração decurrent_useretoken).logging_utils.py: Configuração centralizada para logging estruturado (JSON) com suporte aCorrelation ID.
Modelos de monetização AI adicionados:
users.plan(free,plus,pro)ai_usage_events(metering por request AI)ai_usage_credits(saldo de créditos de overage por usuário)ai_usage_credit_ledger(movimentações de crédito append-only)ai_notification_deliveries(estado de entrega de notificações AI por canal)admin_audit_log(trilha de ações administrativas com before/after, ip e request_id)
Campos de segurança/gestão em users:
account_status(active/suspended)suspended_reason/suspended_atforce_password_changesession_revoked_at
Como Usar (Instalação como Dependência)
Este projeto não é um serviço executável por si só. Ele é projetado para ser instalado como uma dependência local por outros serviços do backend (ex: personal-finance-backend-core, personal-finance-backend-market-data).
Para incluir esta biblioteca como uma dependência editável em outro serviço (por exemplo, no requirements.txt do personal-finance-backend-core), adicione a seguinte linha no requirements.txt do serviço consumidor:
-e ./personal-finance-backend-sharedImportante: Se o serviço consumidor for construído via dockerbuild.sh (como market-data), que copia a biblioteca compartilhada para um diretório local temporário, o requirements.txt do serviço consumidor deverá ter a linha:
-e ./shared-libraryNesses casos, certifique-se de que o dockerbuild.sh do serviço está copiando a biblioteca corretamente para o contexto de build do Docker.
Logging
Esta biblioteca contém a implementação centralizada do sistema de logging estruturado (JSON).
logging_utils.py: Este módulo fornece a funçãosetup_logging()e oREQUEST_ID_CTX(paraCorrelation ID).- Como Funciona: Todos os microsserviços do backend que utilizam esta biblioteca podem chamar
setup_logging()em seumain.pypara configurar seus loggers para emitir logs em JSON com oCorrelation IDautomaticamente incluído, permitindo rastreabilidade ponta a ponta. - Exemplo de Uso:
# No main.py de um serviço from personal_finance_shared.logging_utils import setup_logging setup_logging()
Autenticação (JWT)
Esta biblioteca contém utilitários compartilhados para autenticação via JWT:
personal_finance_shared/auth_utils.py: criação e decode de tokens (atualmente HS256 viaJWT_SECRET_KEY).personal_finance_shared/dependencies.py: dependências FastAPI para extrair e validarAuthorization: Bearer <token>e obtercurrent_user.
Refresh token (Fase 3)
Além do access token, o projeto suporta refresh token (JWT assinado com um segredo diferente) para permitir renovar o access token sem exigir relogin.
create_refresh_token(...)/decode_refresh_token(...)emauth_utils.py- Persistência stateful no Postgres via tabela
refresh_tokens(somente hash do token +jti+ expiração + revogação) hash_token(token)(SHA-256) para nunca armazenar o token bruto no banco
Variáveis de ambiente
JWT_SECRET_KEY(obrigatória): usada para assinar e validar access tokens.
Variáveis reservadas para hardening futuro (documentadas na Fase 0 do plano):
JWT_ISSUER: issuer dos tokens (ex.:personal-finance-backend-core).JWT_AUDIENCE: audience dos tokens (ex.:personal-finance-frontend).JWT_REFRESH_SECRET_KEY: reservado para refresh token.
Variáveis do refresh token:
JWT_REFRESH_SECRET_KEY(obrigatória para refresh token) — segredo separado do access token.REFRESH_TOKEN_EXPIRE_DAYS(opcional, default30) — expiração do refresh token.
Opcional (recomendado em produção):
JWT_STRICT_ISS_AUD: setrue, rejeita tokens semiss/aud(tokens legados)
Autorização (RBAC leve por role)
Além de autenticação, esta biblioteca fornece um helper simples para autorização baseada em role.
require_roles(*roles)
Arquivo: personal_finance_shared/dependencies.py
Exemplo (proteger endpoint):
from fastapi import Depends
from personal_finance_shared.dependencies import require_roles
@router.get("/admin-only", dependencies=[Depends(require_roles("admin", "support_admin"))])
def admin_only_endpoint():
return {"ok": True}Ou retornando o usuário já validado:
@router.get("/admin-only")
def admin_only_endpoint(current_user = Depends(require_roles("admin", "support_admin"))):
return {"user_id": current_user.id}Observação
Por padrão, o helper valida permissões usando current_user.role (fonte de verdade no banco), mesmo que o JWT também carregue a claim role.
Autorização por Plano (Monetização)
Além de RBAC por role, a biblioteca agora suporta controle por plano:
- campo
users.planno modelo de usuário (free,plus,pro) - helper
require_min_plan("plus" | "pro") - normalização de aliases:
bronze -> freeprata/silver -> plusgold -> pro
Exemplo:
from fastapi import Depends
from personal_finance_shared.dependencies import require_min_plan
@router.get("/investments", dependencies=[Depends(require_min_plan("plus"))])
def investments_only_plus():
return {"ok": True}Serviços internos e autenticação sem lookup de usuário
Alguns microsserviços internos (ex.: balance-service) não precisam carregar o usuário completo do banco (users) para funcionar.
Para esses casos, esta biblioteca fornece:
get_current_user_id
Arquivo: personal_finance_shared/dependencies.py
Ele valida o JWT e retorna apenas o user_id (int), sem consultar a tabela users.
Isso evita falhas de 401 em serviços que não têm o mesmo contexto de usuário (por exemplo, quando o token mudou e o serviço só precisa filtrar por user_id).
