v0.6.0 — 2026-04-25

Changelog

Historique des versions publiées. Découvrez ce qui a été ajouté, corrigé ou modifié à chaque release.

Changelog

Todas as mudancas notaveis deste projeto serao documentadas neste arquivo.

O formato segue Keep a Changelog,

e o projeto adere ao Versionamento Semantico.


[Unreleased]

Adicionado

  • Modulo Integrations — handoff sincrono do XP Lead Engine (docs/INTEGRATIONS.md §2.4)

- POST /api/v1/integrations/lead-engine/leads (service token; tenant vem do token)

- Cria/atualiza Contact (idempotente por e-mail, update nao-destrutivo),

Account (find-or-create por nome se o lead trouxer empresa),

Opportunity (primeiro stage do pipeline default; nao duplica open existente)

e Activity nota "Vindo do XP Lead Engine" (idempotente por lead_id)

  • Migracao 038_service_tokens.sql — tabela esperada pelo ServiceTokenMiddleware

(ja referenciada pelo provisionamento Hub → CRM, mas ausente das migracoes)

  • Script scripts/create-service-token.php — gera/revoga service tokens (hash SHA-256)
  • ContactsRepository::findByEmail()

Corrigido

  • ServiceTokenMiddleware agora respeita expires_at do token

Planejado

  • Phase 2: Products, Quotations, Contracts, Email/Calendar sync
  • Rate limit + CORS (M2.5)
  • 2FA TOTP, recuperacao de senha por email, convite de usuario

[0.6.0] - 2026-04-25 — Activities + Dashboard (M6)

Adicionado

  • Modulo Activities com 7 endpoints REST (CRUD + restore + complete)

- 8 tipos suportados: call, email, meeting, task, note, sms, whatsapp, linkedin

- Vinculo polimorfico (contact OU account OU opportunity, com CHECK no DB)

- Campos prontos para sync externo: external_id, external_source

- Metadata JSONB livre por tipo (call: phone/sentiment, email: opens/clicks)

- Filtros: ?type, ?status, ?owner_id=me, ?overdue, ?due_from/to, etc.

- Endpoint atalho POST /activities/{id}/complete

  • Modulo Dashboard com 3 endpoints read-only

- GET /dashboard/summary — 12 KPIs em uma query (contatos, accounts, pipeline aberto + weighted, won_this_month, conversion_rate, avg_deal_cycle, activities_today/overdue)

- GET /dashboard/pipeline — kanban-ready, stages com open/won/lost counts e values

- GET /dashboard/activity-feed — timeline com nomes joinados (owner, contact, account, opp)

  • Migracao 017_activities_audit.sql — trigger de audit em activities

Corrigido

  • ORDER BY em activities: posicao do NULLS LAST estava antes do ASC/DESC

Documentacao

  • docs/IMPLEMENTED.md — visao geral das funcionalidades + comparativo com HubSpot, Pipedrive, Salesforce, RD Station

[0.5.0] - 2026-04-25 — Pipelines + Opportunities (M5)

Adicionado

  • Modulo Pipelines (10 endpoints)

- CRUD de pipelines + flag is_default + restore

- CRUD aninhado de stages: /pipelines/{id}/stages e /pipelines/{id}/stages/{stageId}

- Seed automatico de 6 stages padrao no POST /pipelines (Prospecting → Qualified → Proposal → Negotiation → Closed Won → Closed Lost)

- Bloqueia delete de stage com opportunities ativas (409)

  • Modulo Opportunities (8 endpoints)

- CRUD com FK validation (account, pipeline, stage no pipeline, owner)

- Endpoint especial POST /opportunities/{id}/move:

- Insere em opportunity_stage_history com duration_in_from_stage

- Atualiza stage_id, stage_entered_at, probability (default do novo stage)

- Auto-detecta is_won/is_lost do stage destino → seta status, won_at/lost_at, closed_at

- Re-abertura de stage fechado limpa timestamps e volta status='open'

- GET /opportunities/{id}/history retorna timeline

- 15+ filtros incluindo faixa de valor e datas de fechamento

  • Migracao 016_opp_stage_history_rls.sql — habilita RLS na tabela de historico (estava desprotegida)

Diferenca arquitetural

  • Services de Opportunities NAO chamam AuditService::log() manualmente — confiam na trigger de audit ja existente. Para acoes nao-default (delete/restore), usam Database::setAuditAction('delete') antes da operacao para o trigger registrar com a label correta.

Resolvido

  • Bug Ambiguous parameter no INSERT de opportunity_stage_history quando stage_entered_at era NULL (caso da insercao inicial). Refatorado para dois caminhos SQL distintos.

[0.4.0] - 2026-04-25 — Accounts + Contacts (M4)

Adicionado

  • Modulo Accounts (6 endpoints)

- 20+ campos: nome, legal_name, tax_id, industry, size, tier, website, telefone

- Hierarquia matriz/filial via parent_account_id

- Enderecos JSONB (billing + shipping), tags TEXT[], custom_fields JSONB

- Lifecycle stage (prospect/customer/churned/evangelist) + tier (A/B/C) + health_score 0-100

- Filtros: ?q, ?lifecycle_stage, ?tier, ?industry, ?owner_id, ?country

  • Modulo Contacts (6 endpoints)

- 30+ campos incluindo full_name GENERATED ALWAYS, dedupe_hash SHA-256 auto-computado

- LGPD/RGPD: consent_marketing, consent_data_processing, do_not_contact, unsubscribed_at, unsubscribe_reason

- UTM tracking completo

- Lifecycle (lead → mql → sql → opportunity → customer) + lead_status + temperatura + score

  • Migracao 015_audit_trigger_with_actor.sql — redefine audit_trigger_function():

- Le app.current_user_id da sessao para popular audit_logs.user_id

- Computa changed_fields[] automaticamente em UPDATEs (via jsonb_each)

- Suporta override de action via app.current_action (para registrar 'delete'/'restore' em vez de 'update')

  • Adicionado em Database:

- setActor(?string $userId) — chamado pelo AuthMiddleware apos identificar o user

- setAuditAction(?string $action) — usado por services para customizar a action

Resolvido

  • DNS collision no nginx interno — app:9000 resolvia para assistants-app (rede proxy compartilhada). Corrigido para xp-crm-app:9000. Documentado em memoria.

[0.3.0] - 2026-04-25 — Users (M3)

Adicionado

  • Modulo Users (7 endpoints)

- CRUD com role gating (tenant_admin / manager / sales / csm / read_only)

- Self-update com lista branca de campos (first_name, last_name, locale, timezone, phone, mobile, avatar_url)

- Self-protection: usuario nao pode deletar a si mesmo, nem alterar propria role/is_active

- Soft delete + restore

- POST /users/{id}/password — admin direto OU self com current_password obrigatorio

  • Adicionado em BaseController:

- requireRole(...$roles) — 403 se user nao tiver role permitida

- pagination() — clamping de page/per_page

Resolvido

  • Coluna deleted_by referenciada por Database::softDelete mas inexistente no schema. Removida — actor fica em audit_logs.

[0.2.0] - 2026-04-25 — Auth + Tenancy (M2)

Adicionado

  • JwtService (firebase/php-jwt HS256, access 15min + refresh 7d, claims sub/tnt/rol/typ/jti)
  • AuditService::log() — escreve em audit_logs com diff de campos
  • BaseController com helpers (currentUser, ok, fail, etc.)
  • AuthMiddleware — Bearer token, valida JWT, carrega user via RLS, anexa em request
  • TenantMiddleware — re-bind do Database::setTenant() apos auth
  • Modulo Auth (5 endpoints): register, login, refresh, logout, me

- Lockout apos 5 falhas (15 min) com flags failed_login_attempts e locked_until

- Rehash automatico em login se password_needs_rehash (atualizacao de algoritmo)

- Audit em todos os eventos: register, login, login_failed, login_locked, logout

  • Modulo Tenants (interno, sem rotas publicas) — usado pelo register
  • Migracoes:

- 011_force_rls.sqlFORCE ROW LEVEL SECURITY em 9 tabelas

- 013_app_role.sql — cria role xp_app (LOGIN, NOSUPERUSER) e GRANTs DML

- 014_audit_logs_insert_policy.sql — adiciona policy de INSERT (so SELECT existia → bloqueava o app)

  • App passa a conectar como xp_app (nao mais xp_user superuser). DB_USERNAME atualizado em .env. xp_user reservado para migrations DDL.

Resolvido (3 armadilhas RLS criticas, registradas em memoria)

1. xp_user era SUPERUSER (default da imagem pgvector/pgvector:pg16) — superusers bypassam RLS sempre. Solucao: criar xp_app separado.

2. RLS sem FORCE permite ao OWNER da tabela bypassar. Solucao: ALTER TABLE ... FORCE ROW LEVEL SECURITY.

3. audit_logs so tinha policy FOR SELECT — INSERT do app era bloqueado. Solucao: adicionar policy de INSERT explicita.


[0.1.5] - 2026-04-25 — Foundation Framework (M1)

Adicionado

  • Front controller public/index.php com inicializacao Dotenv + sessao
  • src/Core/:

- Application (singleton, kernel, pipeline de middleware, error handler)

- Container (DI com auto-wiring via reflection)

- Router (grupos, middlewares, params tipados {id:uuid}, {n:int})

- Request / Response (security headers, JSON helpers)

- Database (PDO singleton + savepoints + RLS via setTenant())

  • src/Helpers/functions.php — env(), config(), uuid(), is_valid_uuid(), e(), logger(), t()
  • routes/api.php com /api/v1/ping (liveness) e /api/v1/health (DB + Redis + Meili)
  • routes/web.php com home placeholder
  • Estrutura de modulos auto-descoberta (src/Modules/<Mod>/routes.php e auto-carregado)

Resolvido (armadilhas registradas)

  • Imagem postgres:16-alpine nao tem pgvector — migrations falhavam silenciosamente. Trocada para pgvector/pgvector:pg16.
  • Dotenv::safeLoad() nao popula $_ENV para chaves ja em getenv() (vindas do docker-compose environment). Solucao: usar sempre o helper env().
  • Permissoes de log: container www (UID 1000) nao escrevia em logs/ ownuead por deploy (UID 1002). Compose passa HOST_UID/HOST_GID como build args.

Infraestrutura

  • 5 containers Docker em producao no VPS:

- xp-crm-nginx (rede proxy + xp-crm-net)

- xp-crm-app (PHP 8.2-FPM com extensoes pdo_pgsql, redis, intl, gd, opcache)

- xp-crm-db (PostgreSQL 16 + pgvector)

- xp-crm-redis (Redis 7 com password)

- xp-crm-meili (Meilisearch 1.6)

  • Portas: 9006 (nginx publico), 5437/6382/7700 (DB/Redis/Meili em 127.0.0.1 only)
  • HTTPS publico em https://crm.xpevolution.fr via Nginx Proxy Manager + Let's Encrypt
  • Migrations 001-010 aplicadas (15 tabelas)

[0.1.0] - 2026-04-15

Adicionado

  • Estrutura inicial do projeto
  • Documentacao fundacional:

- README.md - Visao geral do produto

- CLAUDE.md - Configuracao para Claude Code

- docs/ARCHITECTURE.md - Arquitetura tecnica detalhada

- docs/SCHEMA.md - Modelo de dados completo

- docs/API.md - Especificacao REST/GraphQL

- docs/SECURITY.md - Diretrizes de seguranca (OWASP, LGPD/RGPD)

- docs/WORKPLAN.md - Plano de trabalho em sprints (18 meses)

- docs/PRODUCT_VISION.md - Visao, publico e posicionamento

- docs/ROADMAP.md - Roadmap de releases

- docs/INTEGRATIONS.md - Integracoes com ecossistema XP

- docs/EVENT_BUS.md - Especificacao do barramento de eventos

- docs/DEPLOYMENT.md - Guia de deploy

- docs/DEVELOPMENT_PITFALLS.md - Armadilhas comuns

- docs/CODING_STANDARDS.md - Padroes de codigo

  • Estrutura de pastas seguindo padrao do ecossistema XP
  • Primeiras migracoes SQL (001_init, 002_tenants, 003_users)
  • Arquivos de configuracao inicial