0010 — Marketplace de Consultores Credenciados + Pacotes Avulsos
Status
Accepted · 2026-04-26 · Autor: Alexandre + Claude.
Contexto
Modelo de Revenue Share (ADR 0008) precisa de marketplace pra:
- Clínicas órfãs (sem consultor) descobrirem consultores credenciados
- Consultores ganharem visibilidade pública (SEO)
- Plataforma curar quem entra (qualidade)
Sem marketplace, plataforma fica refém de “consultor que conhecemos”. Com marketplace mal-feito, vira lugar de spam onde consultores assediam clínicas.
Decisão
1. Curadoria por convite (sem auto-cadastro)
Consultor não pode “se cadastrar” na plataforma. Apenas Alexandre (platform_admin) convida.
Status do credenciamento (consultancies.credentialed_status):
pending_invitation— Alexandre cadastrou mas não enviou convite aindainvited— convite enviado por email; consultor recebeu link mas não aceitoupending_approval— consultor aceitou e completou perfil; aguarda aprovação finalcredentialed— aprovado e ativo no marketplacesuspended— temporariamente fora (dispute, não cumprimento de SLA, etc)revoked— descredenciado permanentemente
Razão: qualidade do marketplace > volume. Cliente final (clínica) confia em ClinicGestor pela curadoria.
2. Marketplace público SEO-indexed
Rota /consultores (no domínio clinicgestor.com):
- Listagem pública de todos
credentialed_status = 'credentialed' AND accepts_new_clinics = true - Filtros: especialidade, região, idiomas
- Sem autenticação (público pra SEO)
- Branding: plataforma (não consultor)
Rota /consultores/<slug>:
- Perfil individual do consultor
- Branding: do consultor (logo + 2 cores próprios)
- Mostra: bio, casos, depoimentos, pacotes avulsos oferecidos, promoção opcional (“Primeira sessão grátis”)
- CTA: “Quero ser cliente” (redireciona pra
/signupse não logado, ou direto pra “tornar X minha consultoria” se logado e órfã)
Ambas indexadas pelo Google. Captura busca SEO orgânica.
3. Princípio “no-spam B2B” (busca unidirecional)
Regra inviolável: clínica busca consultor; consultor nunca busca clínica.
- Não existe rota tipo
/consultancy/marketplace-clinicas - Não existe filtro/listing de clínicas órfãs disponível ao consultor
- RLS bloqueia:
consultancy_can_view_clinic(consultancy_id, clinic_id)retornafalsese clínica não está emcurrent_consultancy_idouattribution_consultancy_id - Lint custom
lint:no-spam-b2bproíbe rotas com pattern/consultancy/(marketplace|search|browse)-clinic*
Razão: B2B SaaS sem essa regra vira “garimpagem” — consultor caça clínicas, marketplace vira spam, plataforma perde reputação.
4. Marketplace só pra órfãs com plano ativo
Helper:
CREATE OR REPLACE FUNCTION public.clinic_can_browse_marketplace(p_clinic_id UUID)RETURNS BOOLEANLANGUAGE SQL STABLE SECURITY DEFINER SET search_path = public AS $$ SELECT EXISTS ( SELECT 1 FROM public.clinics c WHERE c.id = p_clinic_id AND c.deleted_at IS NULL AND c.current_consultancy_id IS NULL AND c.platform_subscription_state = 'active' );$$;UI esconde rota /clinic/escolher-consultor se helper retornar false. API rejeita com 403.
Razão: clínica em contrato não vê marketplace pra evitar “garimpagem inversa” (outros consultores assediarem).
5. Vitrine futura curada pela plataforma (F2+)
Pra dar visibilidade controlada aos consultores credenciados (sem permitir que eles façam outreach proativo):
- Blog
clinicgestor.com/blogcom artigos de gestão clínica (consultor pode ser convidado como autor) - Podcasts da plataforma com consultores como entrevistados
- Banner no marketplace “Consultor do Mês” (curado por Alexandre)
- Lives mensais da plataforma com 1 consultor convidado
Schema dormente em F1 (platform_blog_posts, platform_podcast_episodes, marketplace_featured_consultancies); ativação F2+.
6. Pacotes Avulsos (F1.5) — degrau 2 da escada de aquisição
Escada de aquisição:
Degrau 1: 1h GRÁTIS (promoção opcional do consultor — campo em consultancies.promotional_offer) ↓Degrau 2: PACOTE PAGO 1-10h (essa subseção — F1.5) ↓Degrau 3: CONTRATO FIXO mensal (Ideia 1 base — Revenue Share)6.1 Tabelas (F1)
-- Pacotes oferecidos pelo consultor (F1 prepara, F1.5 ativa UI)CREATE TABLE public.consultancy_session_packages ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), consultancy_id UUID NOT NULL REFERENCES public.consultancies(id), name TEXT NOT NULL, -- "Mentoria Pontual 1h" description TEXT, hours_count INT NOT NULL CHECK (hours_count > 0), price_brl_cents INT NOT NULL CHECK (price_brl_cents >= 0), validity_days INT NOT NULL DEFAULT 90, active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW());
-- Compra de pacote (F1.5)CREATE TABLE public.session_package_purchases ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), package_id UUID NOT NULL REFERENCES public.consultancy_session_packages(id), clinic_id UUID NOT NULL REFERENCES public.clinics(id), consultancy_id UUID NOT NULL REFERENCES public.consultancies(id), purchased_at TIMESTAMPTZ DEFAULT NOW(), expires_at TIMESTAMPTZ NOT NULL, hours_total INT NOT NULL, hours_used NUMERIC(5,2) DEFAULT 0, status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'consumed', 'expired', 'refunded')), asaas_payment_id TEXT, data_access_consent_until TIMESTAMPTZ NOT NULL, -- consent escopado pelo pacote refunded_at TIMESTAMPTZ, refund_reason TEXT);
-- Sessões agendadas (F1.5)CREATE TABLE public.session_appointments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), purchase_id UUID NOT NULL REFERENCES public.session_package_purchases(id), scheduled_for TIMESTAMPTZ NOT NULL, duration_minutes INT DEFAULT 60, status TEXT NOT NULL DEFAULT 'scheduled' CHECK (status IN ('scheduled', 'completed', 'cancelled', 'no_show')), consultant_notes TEXT, clinic_rating INT CHECK (clinic_rating BETWEEN 1 AND 5), clinic_feedback TEXT, meeting_url TEXT, -- preenchido manualmente pelo consultor (F1.5; integração com Cal.com em F2+) cancelled_at TIMESTAMPTZ, cancelled_by TEXT CHECK (cancelled_by IN ('clinic', 'consultancy', 'platform')), cancellation_reason TEXT);
-- Slots de disponibilidade (F1.5 simples; F2+ com Google Calendar)CREATE TABLE public.consultancy_availability_slots ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), consultancy_id UUID NOT NULL REFERENCES public.consultancies(id), start_at TIMESTAMPTZ NOT NULL, duration_minutes INT DEFAULT 60, status TEXT NOT NULL DEFAULT 'available' CHECK (status IN ('available', 'reserved', 'completed', 'cancelled')), reserved_by_appointment_id UUID REFERENCES public.session_appointments(id));6.2 Regras
- 0% comissão da plataforma — coerência com modelo “só cobramos plano”. 100% pro consultor.
- Pacote NÃO muda
current_consultancy_idda clínica (transação efêmera, sem vínculo formal) - Só pra clínica com plano ativo (regra 5.7.4)
- Consent escopado por pacote: ao comprar, clínica autoriza acesso aos dados pelo período do pacote + 30 dias após última sessão. Expira automaticamente. Helper
consultancy_has_data_access_totrata. - SLA do consultor: 7 dias pra publicar slots ou agendar 1ª sessão. Refund integral até 1ª sessão. 3 ocorrências em 90 dias = revisão de credenciamento.
6.3 Edge functions (F1.5)
purchase-session-package— clínica compra; integra Asaas do consultorschedule-session-appointment— clínica agenda dentro do pacotecomplete-session-appointment— consultor marca concluída + adiciona notasexpire-session-packages-cron— job diário detecta pacotes expirados; libera consentconsultancy-sla-monitor-cron— monitora SLA de 7 dias; alerta clínica + escala consultor
6.4 UI (F1.5)
/consultancy/configuracoes/pacotes— consultor cria/edita/consultancy/agenda— sessões agendadas + slots/consultores/<slug>(revisado) — mostra pacotes oferecidos/clinic/comprar-consultoria— clínica órfã navega + compra/clinic/agenda— clínica vê sessões compradas
7. Promoção opcional (Ideia 1.H)
Cada consultor pode publicar promoção no perfil público:
ALTER TABLE public.consultancies ADD COLUMN promotional_offer_text TEXT, ADD COLUMN promotional_offer_active BOOLEAN DEFAULT FALSE, ADD COLUMN promotional_offer_updated_at TIMESTAMPTZ;Exemplos:
- “Primeira sessão de consultoria gratuita”
- “Mentoria mensal grátis nos primeiros 90 dias”
- “Análise de fluxo de caixa sem custo”
Plataforma não monitora cumprimento (compromisso bilateral consultor↔clínica). Mas vira diferencial comercial.
Consequências
Positivas
- Marketplace orgânico atrai clínicas órfãs via SEO
- Curadoria por convite mantém qualidade
- No-spam B2B protege experiência de consultor (não é assediado) e clínica (não tem consultor caça-níqueis)
- Pacotes Avulsos criam degrau de baixa fricção — clínica experimenta antes de fechar contrato
- Promoção opcional dá flexibilidade comercial pro consultor
Negativas
- Curadoria escala lentamente — Alexandre precisa convidar consultor a consultor
- Marketplace começa vazio — 1 consultor (Karla) na F1 não enche
Riscos
- Marketplace fraco em F1 afeta atração de clínicas órfãs
- Mitigação: foco em F1 é canal direto (lead via consultor existente). Marketplace vira diferencial em F1.5+ quando 5+ consultores credenciados
- Pacote sem cumprimento vira disputa
- Mitigação: SLA de 7 dias + auditoria via tickets; refund automático se SLA falha
Alternativas consideradas
1. Auto-cadastro de consultor
- Prós: escala mais rápido
- Contras: qualidade impossível de garantir; vai gerar reputação ruim. Rejeitado.
2. Marketplace mostra clínicas órfãs pra consultor escolher
- Prós: aceleração de match
- Contras: viola “no-spam B2B”; gera assédio. Rejeitado.
3. Pacotes Avulsos sem consent escopado (consultor vê dados sempre)
- Prós: simplicidade
- Contras: viola LGPD (consultor que só fez 1 sessão tem acesso pra sempre)
- Rejeitado — consent escopado é regra inviolável.
4. Cobrar comissão sobre pacote avulso
- Prós: receita extra
- Contras: contradiz princípio “só cobramos plano”; complexidade fiscal. Rejeitado.
Atualizações de documentos
- AGENTS.md §5.15 (Marketplace), §5.7.4 (pacote sem comissão)
- BLUEPRINT.md §6 (princípios)
docs/consultancy/perfil-publico.mddocs/consultancy/configuracoes-pacotes.md
Referências
- ADR 0001 (multi-consultancy)
- ADR 0008 (modelo financeiro)
- ADR 0009 (consent escopado por pacote)
- ADR 0011 (cancelamento bilateral)