Bem-vindo ao Developer Portal

Este é o portal técnico da plataforma Arah. Explore a documentação, guias e referências da API através do menu lateral e das abas acima.

Use o menu lateral para navegar entre diferentes seções ou clique nas abas superiores para acessar categorias principais.

Visão geral

API orientada a território com governança comunitária transparente

A API Arah fornece uma base confiável para territórios, vínculos, feed, mapa, marketplace e eventos. Regras explícitas de visibilidade, validação e moderação garantem que experiências locais sejam auditáveis e evoluam com segurança. A arquitetura suporta decisões comunitárias, economia circular local e regeneração social territorial através de ferramentas técnicas que respeitam a soberania e pertencimento dos grupos locais.

Território como base estrutural

Território é a unidade geográfica fundamental que separa "onde" de "quem" e "o quê". Esta separação evita que conteúdo social distorça o mapa e mantém o contexto local como primeira classe. A geografia como fundamento estrutural fortalece vínculos de pertencimento e permite que comunidades gerenciem seus próprios processos de organização e economia.

Governança em camadas transparentes

Vínculos (visitor/resident), validações comunitárias, moderação (reports/bloqueios) e notificações formam as camadas que definem visibilidade no feed e mapa. Cada camada é configurável e auditável pela comunidade, garantindo transparência total e autonomia nas decisões que afetam o território.

Como o Arah funciona

Do visitante ao morador validado

Visitante

Visitantes declaram vínculo com role=Visitor. Não existe "validação" para visitante: é apenas um vínculo leve para acesso a conteúdo público e operações permitidas para não-moradores.

Pedido de moradia

Para virar morador, o visitante cria um pedido (JoinRequest) via POST /api/v1/memberships/{territoryId}/become-resident. Se ele conhecer alguém, pode enviar recipientUserIds e fazer um convite direcionado. Sem destinatários, o pedido vai para a curadoria (Curator) e, se necessário, para SystemAdmin.

Aprovação comunitária

Destinatários (ou curadores) aprovam/rejeitam via POST /api/v1/join-requests/{id}/approve|reject. Ao aprovar, o requester torna-se RESIDENT (ainda NÃO verificado). A verificação de residência acontece depois via POST /api/v1/memberships/{territoryId}/verify-residency/geo ou /verify-residency/document.

Bootstrap (primeiro morador)

Não existe "fundador" autoaprovado. Se o território ainda não tiver curadores/moradores verificados, o pedido faz fallback para SystemAdmin (governança global) para destravar o bootstrap.

Territórios

Unidade primária com vínculo estrutural

Estado atual

Territórios continuam sendo a unidade primária de organização. Todo conteúdo e governança são ancorados diretamente no território selecionado.

ParentTerritoryId

O campo ParentTerritoryId existe apenas para modelar hierarquia estrutural (ex.: bairro → município). Ele ainda não gera herança de permissões, feeds ou validações.

Roadmap (não implementado)

Herança de permissões, feeds agregados e regras automáticas por hierarquia permanecem como roadmap e não fazem parte do backend atual.

Conceitos de produto

Semântica de negócio

Territory-first

Território é uma célula geográfica neutra. Não carrega conteúdo social embutido; ele apenas organiza contexto, priorização e governança.

Memberships

Vínculos entre usuário e território podem ser VISITOR ou RESIDENT. O pedido de moradia (JoinRequest) tem status PENDING/APPROVED/REJECTED. Já a verificação de residência do membership é feita por flags: NONE/GEOVERIFIED/DOCUMENTVERIFIED, influenciando visibilidade e autorização.

Feature flags por território

Cada território pode habilitar flags como AlertPosts em /api/v1/territories/{territoryId}/features. Elas controlam quais tipos de post são aceitos.

Curadoria/Validação

A aprovação de pedidos de moradia é feita por Curators e/ou por moradores já verificados (geo/doc). Curadores também continuam responsáveis por validação de entidades do mapa e alertas ambientais.

Moderação & segurança

Moderação é um conjunto de sinais (reports) + ações (bloqueios) para manter o território útil e seguro. O objetivo aqui não é "censura automática", e sim reduzir abuso e ruído com decisões auditáveis e fluxo claro de triagem por curadoria.

  • Reportar post: POST /api/v1/reports/posts/{postId} com reason (obrigatório) e details (opcional).
  • Reportar usuário: POST /api/v1/reports/users/{userId} (pode receber territoryId).
  • Triagem: curadoria lista e filtra em GET /api/v1/reports (por território, status e tipo).
  • Bloquear/desbloquear: corta visibilidade de conteúdo no feed e no mapa via POST/DELETE /api/v1/blocks/users/{userId}.
Marketplace

Economia local territorial

O marketplace permite criar lojas e publicar produtos/serviços (items), gerenciar carrinho de compras e receber inquiries de interessados. Tudo ancorado no território. O sistema de payout territorial garante que recursos financeiros permaneçam na comunidade, fortalecendo ciclos econômicos locais e permitindo que comunidades construam autonomia através de suas próprias capacidades produtivas.

12. Criar ou atualizar loja

Moradores validados podem criar ou atualizar sua loja no território via POST /api/v1/stores. A loja define informações de contato e visibilidade.

curl -X POST http://localhost:8080/api/v1/stores \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "territoryId": "11111111-1111-1111-1111-111111111111",
    "displayName": "Loja da Ana",
    "description": "Produtos artesanais",
    "contactVisibility": "Public",
    "contact": {
      "phone": "+5511999999999",
      "email": "ana@exemplo.com"
    }
  }'

13. Criar item (produto ou serviço) com imagens

Lojas podem criar items via POST /api/v1/items. Items podem ser produtos ou serviços, com preço fixo, negociável ou gratuito. Items podem incluir até 10 imagens através do campo mediaIds.

curl -X POST http://localhost:8080/api/v1/items \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "territoryId": "11111111-1111-1111-1111-111111111111",
    "storeId": "22222222-2222-2222-2222-222222222222",
    "type": "Product",
    "title": "Bolo de chocolate",
    "description": "Bolo caseiro",
    "category": "Alimentos",
    "tags": "bolo,chocolate",
    "pricingType": "Fixed",
    "priceAmount": 25.00,
    "currency": "BRL",
    "unit": "unidade",
    "latitude": -23.55,
    "longitude": -46.63,
    "mediaIds": ["dddddddd-dddd-dddd-dddd-dddddddddddd", "eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee"]
  }'
📸🎥🎧 Mídias em Items (Imagens, Vídeos e Áudios):
  • Upload de mídia: Primeiro, faça upload via POST /api/v1/media/upload para obter o mediaId (aceita imagens JPEG/PNG/WebP, vídeos MP4 e áudios MP3/WAV/OGG)
  • Associar ao item: Inclua os mediaIds no array ao criar o item (máximo 10 mídias: imagens, vídeos e/ou áudios)
  • Vídeos: Máximo 1 vídeo por item, até 30MB, até 30 segundos (demonstração rápida de produto). Formatos suportados: MP4
  • Áudios: Máximo 1 áudio por item, até 5MB, até 2 minutos (descrição de produto, demonstração de serviço). Formatos suportados: MP3, WAV, OGG
  • Imagens: Múltiplas imagens permitidas (até 10 mídias no total, combinando imagens, vídeos e áudios). Formatos suportados: JPEG, PNG, WebP
  • Imagem principal: A primeira mídia do array é usada como primaryImageUrl (se for vídeo ou áudio, a URL é retornada)
  • Resposta: O ItemResponse inclui primaryImageUrl e imageUrls (array com todas as mídias: imagens, vídeos e áudios)
  • Validação: Todas as mídias devem pertencer ao usuário que está criando o item. Vídeos maiores que 30MB, áudios maiores que 5MB, mais de 1 vídeo ou mais de 1 áudio por item retornam erro

14. Buscar items

Use GET /api/v1/items para buscar produtos e serviços por território, categoria, tags ou texto livre (q).

curl "http://localhost:8080/api/v1/items?territoryId=11111111-1111-1111-1111-111111111111&q=bolo&category=Alimentos" \
  -H "Authorization: Bearer <token>"

15. Gerenciar carrinho

Usuários podem adicionar itens ao carrinho via POST /api/v1/cart/items, atualizar quantidade via PATCH /api/v1/cart/items/{id} e fazer checkout via POST /api/v1/cart/checkout.

curl -X POST http://localhost:8080/api/v1/cart/items \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "territoryId": "11111111-1111-1111-1111-111111111111",
    "itemId": "33333333-3333-3333-3333-333333333333",
    "quantity": 2,
    "notes": "Entregar após 18h (se possível)"
  }'

16. Criar inquiry

Interessados podem criar inquiries diretamente em items via POST /api/v1/items/{id}/inquiries.

curl -X POST http://localhost:8080/api/v1/items/{id}/inquiries \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"message": "Gostaria de mais informações"}'
📊 Ver Diagrama de Sequência
Diagrama de sequência: Marketplace - Fluxo completo (loja → item → carrinho → checkout → payout)
Payout & Gestão Financeira

Sistema de Payout e Rastreabilidade Financeira Completa

O Arah implementa um sistema completo de payout (transferência para vendedores) com rastreabilidade financeira total. Cada centavo é rastreado, permitindo transparência total e autonomia para territórios.

🎯 O que é o Sistema de Payout?

Quando um checkout é marcado como Paid, o sistema automaticamente cria uma transação de vendedor e processa o payout conforme configurações do território. O vendedor recebe o valor líquido (subtotal - fees da plataforma).

✨ Principais Funcionalidades

  • Rastreabilidade completa: Cada centavo é rastreado em FinancialTransaction
  • Retenção configurável: Aguarda período configurado antes de liberar para payout
  • Valor mínimo/máximo: Acumula até atingir mínimo ou divide se exceder máximo
  • Payout automático: Background worker processa payouts automaticamente
  • Gestão financeira da plataforma: Saldo, receitas e despesas separadas por território
🚀 Guia de Produção (Passo a Passo)

Abaixo você encontrará um guia completo para colocar o sistema de payout em produção. O guia foi projetado para ser seguido por qualquer pessoa, mesmo com conhecimento mínimo de programação.

📋 Passo 1: Entendendo o Fluxo de Payout

Quando um cliente compra algo na loja de um vendedor e o pagamento é confirmado, o seguinte acontece:

  1. Checkout pago → Sistema cria SellerTransaction automaticamente
  2. Valor líquido → Subtotal - Fees da plataforma = Valor para o vendedor
  3. Período de retenção → Aguarda dias configurados (ex: 7 dias)
  4. Valor mínimo → Acumula até atingir valor mínimo configurado (ex: R$ 100,00)
  5. Payout automático → Background worker processa quando todas as condições são atendidas
  6. Transferência → Dinheiro é transferido para o vendedor via gateway (Stripe, MercadoPago, etc.)

⚙️ Passo 2: Configurar Payout para um Território

Antes de usar o sistema de payout, você precisa configurar como ele funciona para cada território. Essa configuração define período de retenção, valores mínimo/máximo, frequência e se requer aprovação manual.

# Criar ou atualizar configuração de payout
curl -X POST "http://localhost:8080/api/v1/territories/{territoryId}/payout-config" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "retentionPeriodDays": 7,
    "minimumPayoutAmountInCents": 10000,
    "maximumPayoutAmountInCents": 5000000,
    "frequency": "Weekly",
    "autoPayoutEnabled": true,
    "requiresApproval": false,
    "currency": "BRL"
  }'
📝 Explicação dos Campos:
  • retentionPeriodDays: Quantos dias aguardar antes de liberar para payout (ex: 7 = aguarda 7 dias)
  • minimumPayoutAmountInCents: Valor mínimo em centavos para processar payout (ex: 10000 = R$ 100,00)
  • maximumPayoutAmountInCents: Valor máximo por payout - se exceder, divide em múltiplos (ex: 5000000 = R$ 50.000,00)
  • frequency: Frequência do payout automático - "Daily", "Weekly", "Monthly" ou "Manual"
  • autoPayoutEnabled: Se true, processa payouts automaticamente. Se false, apenas manual
  • requiresApproval: Se true, requer aprovação manual antes de processar (ainda não implementado)
  • currency: Moeda da configuração - "BRL", "USD", etc.

🔍 Passo 3: Consultar Configuração de Payout

Para ver a configuração atual de payout de um território:

# Consultar configuração ativa
curl "http://localhost:8080/api/v1/territories/{territoryId}/payout-config" \
  -H "Authorization: Bearer <token>"

💰 Passo 4: Consultar Saldo do Vendedor

Vendedores podem consultar seu saldo e histórico de transações:

# Consultar meu saldo como vendedor
curl "http://localhost:8080/api/v1/territories/{territoryId}/seller-balance/me" \
  -H "Authorization: Bearer <token>"

# Consultar minhas transações como vendedor
curl "http://localhost:8080/api/v1/territories/{territoryId}/seller-balance/me/transactions" \
  -H "Authorization: Bearer <token>"
📊 Entendendo o Saldo do Vendedor:
  • pendingAmountInCents: Valor que ainda está no período de retenção
  • readyForPayoutAmountInCents: Valor pronto para payout (após período de retenção e valor mínimo)
  • paidAmountInCents: Valor já transferido para o vendedor

📈 Passo 5: Gestão Financeira da Plataforma

Administradores podem consultar o saldo financeiro da plataforma (receitas de fees e despesas de payouts):

# Consultar saldo da plataforma (apenas SystemAdmin ou FinancialManager)
curl "http://localhost:8080/api/v1/territories/{territoryId}/platform-financial/balance" \
  -H "Authorization: Bearer <token>"

# Listar receitas (fees coletadas)
curl "http://localhost:8080/api/v1/territories/{territoryId}/platform-financial/revenue" \
  -H "Authorization: Bearer <token>"

# Listar despesas (payouts processados)
curl "http://localhost:8080/api/v1/territories/{territoryId}/platform-financial/expenses" \
  -H "Authorization: Bearer <token>"

🔧 Passo 6: Configuração em Produção - Checklist

Para colocar o sistema de payout em produção, siga este checklist:

✅ Pré-requisitos
  1. Migration aplicada: Execute a migration 20260119000000_AddFinancialSystem.cs no banco de dados
  2. Gateway de pagamento configurado: Tenha uma conta no gateway (Stripe Connect, MercadoPago, etc.)
  3. Background worker ativo: Certifique-se de que o PayoutProcessingWorker está rodando
⚙️ Configuração Inicial
  1. Configure payout por território: Use POST /api/v1/territories/{territoryId}/payout-config
  2. Configure período de retenção: Recomendado: 7-14 dias (protege contra chargebacks)
  3. Configure valor mínimo: Recomendado: R$ 50,00 - R$ 200,00 (reduz custos de transferência)
  4. Configure valor máximo: Se necessário, limite por payout (ex: R$ 50.000,00)
  5. Escolha frequência: "Daily" (diário), "Weekly" (semanal) ou "Monthly" (mensal)
  6. Habilite payout automático: Defina autoPayoutEnabled: true
🔌 Integração com Gateway de Pagamento
  1. Implemente IPayoutGateway: Crie implementação para seu gateway (Stripe, MercadoPago, etc.)
  2. Registre no DI: Substitua MockPayoutGateway por sua implementação real em ServiceCollectionExtensions.cs
  3. Configure credenciais: Adicione chaves de API do gateway em appsettings.json ou variáveis de ambiente
  4. Teste em sandbox: Use ambiente de testes do gateway antes de produção
🧪 Testes e Validação
  1. Teste checkout completo: Crie checkout, marque como Paid e verifique se SellerTransaction foi criada
  2. Verifique retenção: Confirme que o valor fica em pendingAmountInCents durante o período de retenção
  3. Teste valor mínimo: Crie múltiplos checkouts pequenos e confirme que só processa quando atinge o mínimo
  4. Verifique payout automático: Aguarde o background worker processar e verifique transferência no gateway
  5. Monitore logs: Verifique logs do PayoutProcessingWorker para erros ou avisos

🏗️ Passo 7: Implementar Gateway de Pagamento Real

O sistema vem com um MockPayoutGateway para desenvolvimento. Para produção, você precisa implementar o IPayoutGateway para seu gateway de pagamento preferido (Stripe Connect, MercadoPago, etc.).

📝 Exemplo: Interface IPayoutGateway
public interface IPayoutGateway
{
  Task<OperationResult<PayoutResult>> CreatePayoutAsync(
    long amountInCents,
    string currency,
    string sellerAccountId,
    string description,
    Dictionary<string, string>? metadata,
    CancellationToken cancellationToken);

  Task<OperationResult<PayoutStatusResult>> GetPayoutStatusAsync(
    string payoutId,
    CancellationToken cancellationToken);

  Task<OperationResult> CancelPayoutAsync(
    string payoutId,
    CancellationToken cancellationToken);
}

Você precisa implementar os 3 métodos acima para seu gateway de pagamento. Veja o exemplo de MockPayoutGateway em backend/Arah.Infrastructure/Payments/MockPayoutGateway.cs como referência.

🔄 Passo 8: Como Funciona o Background Worker

O PayoutProcessingWorker verifica payouts pendentes a cada 5 minutos e processa automaticamente conforme a frequência configurada:

  • Daily: Processa payouts todos os dias (quando o worker roda)
  • Weekly: Processa payouts toda segunda-feira às 00:00 UTC
  • Monthly: Processa payouts no dia 1 de cada mês às 00:00 UTC
  • Manual: Não processa automaticamente - apenas quando chamado manualmente via API

O worker está configurado automaticamente quando você roda a API. Não precisa fazer nada extra para ativá-lo.

📊 Passo 9: Monitoramento e Troubleshooting

Para monitorar o sistema de payout em produção:

  • Logs do Worker: Procure por PayoutProcessingWorker nos logs para ver processamento
  • Transações Financeiras: Consulte GET /api/v1/territories/{territoryId}/platform-financial/revenue para receitas
  • Transações de Despesa: Consulte GET /api/v1/territories/{territoryId}/platform-financial/expenses para payouts
  • Status de Payouts: Use UpdatePayoutStatusAsync para atualizar status do gateway periodicamente

🎯 Casos de Uso Comuns

  • Vendedor quer saber quando receberá: Consulte /seller-balance/me para ver valores pendentes e prontos para payout
  • Processar payout manualmente: Use ProcessPendingPayoutsAsync do SellerPayoutService via API admin
  • Ver histórico de transações: Consulte /seller-balance/me/transactions para ver todas as transações do vendedor
  • Auditar receitas da plataforma: Use endpoints de /platform-financial para ver fees coletadas

⚠️ Pontos de Atenção

  • Período de retenção: Protege contra chargebacks - não configure muito curto
  • Valor mínimo: Reduz custos de transferência - configure baseado no custo do gateway
  • Valor máximo: Limita exposição a risco - configure se necessário
  • Moedas diferentes: Cada território pode ter configuração em moeda diferente
  • Testes primeiro: Sempre teste com valores pequenos antes de produção
📚 Documentação Técnica Completa

Para detalhes técnicos completos, consulte: docs/backlog-api/FASE7.md

Eventos

Eventos territoriais com data/hora e localização

Eventos são criados por moradores e aparecem no feed e no mapa. Eles têm data/hora de início (obrigatória) e fim (opcional), além de geolocalização obrigatória.

17. Criar evento com imagem de capa e imagens adicionais

Use POST /api/v1/events para criar eventos. O evento automaticamente gera um post no feed e aparece no mapa. Eventos podem incluir uma imagem de capa (coverMediaId) e até 10 imagens adicionais (additionalMediaIds).

curl -X POST http://localhost:8080/api/v1/events \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "X-Session-Id: session-123" \
  -d '{
    "territoryId": "11111111-1111-1111-1111-111111111111",
    "title": "Feira de artesanato",
    "description": "Feira mensal no centro",
    "startsAtUtc": "2024-12-15T10:00:00Z",
    "endsAtUtc": "2024-12-15T18:00:00Z",
    "latitude": -23.55,
    "longitude": -46.63,
    "locationLabel": "Praça Central",
    "coverMediaId": "ffffffff-ffff-ffff-ffff-ffffffffffff",
    "additionalMediaIds": ["aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"]
  }'
📸🎥🎧 Mídias em Eventos (Imagens, Vídeos e Áudios):
  • Upload de mídia: Primeiro, faça upload via POST /api/v1/media/upload para obter o mediaId (aceita imagens JPEG/PNG/WebP, vídeos MP4 e áudios MP3/WAV/OGG)
  • Mídia de capa: Use coverMediaId para definir a mídia principal do evento (imagem, vídeo ou áudio, opcional). Formatos: JPEG, PNG, WebP (imagens), MP4 (vídeos) ou MP3, WAV, OGG (áudios)
  • Mídias adicionais: Use additionalMediaIds para incluir até 5 mídias adicionais (imagens, vídeos ou áudios). Formatos: JPEG, PNG, WebP (imagens), MP4 (vídeos) ou MP3, WAV, OGG (áudios)
  • Vídeos: Máximo 1 vídeo por evento (em capa ou adicionais), até 100MB, até 2 minutos. Formatos suportados: MP4
  • Áudios: Máximo 1 áudio por evento (em capa ou adicionais), até 20MB, até 10 minutos (promoção de eventos, trilhas sonoras). Formatos suportados: MP3, WAV, OGG
  • Imagens: Múltiplas imagens permitidas (até 6 mídias no total: 1 capa + 5 adicionais, combinando imagens, vídeos e áudios). Formatos suportados: JPEG, PNG, WebP
  • Resposta: O EventResponse inclui coverImageUrl e additionalImageUrls (pode conter URLs de vídeos e áudios)
  • Validação: Todas as mídias devem pertencer ao usuário e coverMediaId não pode estar em additionalMediaIds. Vídeos maiores que 100MB, áudios maiores que 20MB, mais de 1 vídeo ou mais de 1 áudio por evento retornam erro

18. Interesse e confirmação em eventos

Usuários podem marcar interesse via POST /api/v1/events/{eventId}/interest e confirmar participação via POST /api/v1/events/{eventId}/confirm.

# Marcar interesse
curl -X POST http://localhost:8080/api/v1/events/{eventId}/interest \
  -H "Authorization: Bearer <token>" \

# Confirmar participação
curl -X POST http://localhost:8080/api/v1/events/{eventId}/confirm \
  -H "Authorization: Bearer <token>"
Admin & Filas

Sistema de Filas e Administração

O sistema de filas (WorkQueue) permite processar tarefas que requerem revisão humana ou decisões administrativas. Ele é usado para aprovação de pedidos de moradia quando não há curadores, validação de evidências de residência, triagem de reports de moderação e outras tarefas que precisam de intervenção humana.

🎯 O que é o Sistema de Filas?

O WorkQueue é uma fila genérica de tarefas que requerem revisão humana. Ele permite que administradores e curadores processem tarefas pendentes de forma organizada e auditável.

✨ Principais Funcionalidades

  • Filas por território: Cada território tem sua própria fila de tarefas
  • Tipos de tarefa: JoinRequest, ResidencyVerification, ModerationCase, etc.
  • Status de tarefa: Pending, InProgress, Completed, Rejected
  • Atribuição: Tarefas podem ser atribuídas a curadores ou administradores
  • Auditoria: Todas as ações são registradas e auditáveis

19. Listar tarefas pendentes

Use GET /api/v1/work-queue para listar tarefas pendentes. Você pode filtrar por território, tipo de tarefa e status.

curl "http://localhost:8080/api/v1/work-queue?territoryId=11111111-1111-1111-1111-111111111111&status=Pending" \
  -H "Authorization: Bearer <token>"

20. Processar tarefa

Use POST /api/v1/work-queue/{id}/process para processar uma tarefa. Você pode aprovar, rejeitar ou adiar a tarefa.

curl -X POST http://localhost:8080/api/v1/work-queue/{id}/process \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "Approve",
    "notes": "Aprovado após verificação"
  }'
📚 Documentação Completa: Documentação completa: docs/33_ADMIN_SYSTEM_CONFIG_WORKQUEUE.md

⚙️ Configuração Avançada de Limites de Mídia por Território

Cada território pode configurar limites personalizados de tamanho e tipos MIME para mídias (imagens, vídeos e áudios) em diferentes contextos (Posts, Eventos, Marketplace, Chat). Os limites territoriais não podem exceder os limites globais do sistema, garantindo consistência e controle centralizado.

🔧 Endpoints de Configuração:
  • Obter configuração: GET /api/v1/territories/{territoryId}/media-config
  • Atualizar configuração: PUT /api/v1/territories/{territoryId}/media-config (requer Curator)
📋 Estrutura da Configuração

A configuração permite ajustar limites separadamente para cada contexto:

  • Posts: Limites para mídias em posts do feed
  • Eventos: Limites para mídias de capa e adicionais em eventos
  • Marketplace: Limites para mídias em itens do marketplace
  • Chat: Limites para imagens e áudios em mensagens (vídeos sempre bloqueados)
🔒 Limites Globais vs Territoriais

O sistema possui limites globais configurados em MediaStorageOptions que definem os valores máximos permitidos em toda a plataforma. Os limites territoriais podem ser mais restritivos, mas nunca mais permissivos que os globais:

  • Limites globais (padrão): Imagens 10MB, Vídeos 50MB, Áudios 20MB
  • Limites territoriais: Podem ser menores que os globais (ex: 5MB para imagens), mas nunca maiores
  • Tipos MIME: Podem ser restringidos por território (ex: apenas JPEG para imagens)
  • Fallback automático: Se não configurado, usa limites globais
📝 Exemplo: Atualizar Limites de Posts
# Atualizar limites de mídia para Posts (como Curator)
curl -X PUT "http://localhost:8080/api/v1/territories/{territoryId}/media-config" \
  -H "Authorization: Bearer <curator-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "posts": {
      "imagesEnabled": true,
      "videosEnabled": true,
      "audioEnabled": true,
      "maxMediaCount": 10,
      "maxVideoCount": 1,
      "maxAudioCount": 1,
      "maxImageSizeBytes": 5242880,
      "maxVideoSizeBytes": 26214400,
      "maxAudioSizeBytes": 5242880,
      "maxVideoDurationSeconds": 60,
      "maxAudioDurationSeconds": 300,
      "allowedImageMimeTypes": ["image/jpeg", "image/png"],
      "allowedVideoMimeTypes": ["video/mp4"],
      "allowedAudioMimeTypes": ["audio/mpeg", "audio/wav"]
    },
    "events": null,
    "marketplace": null,
    "chat": null
  }'
🔄 Atualização Parcial

Você pode atualizar apenas uma parte da configuração. Os campos não especificados mantêm seus valores atuais:

# Atualizar apenas limites de Chat
curl -X PUT "http://localhost:8080/api/v1/territories/{territoryId}/media-config" \
  -H "Authorization: Bearer <curator-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "posts": null,
    "events": null,
    "marketplace": null,
    "chat": {
      "imagesEnabled": true,
      "audioEnabled": true,
      "maxImageSizeBytes": 2097152,
      "maxAudioSizeBytes": 1048576,
      "maxAudioDurationSeconds": 60
    }
  }'
⚠️ Validações Automáticas:
  • Valores que excedem limites globais são automaticamente ajustados para os limites globais
  • Tipos MIME não especificados usam os tipos MIME globais permitidos
  • Limites mínimos: 1KB para qualquer tipo de mídia
  • Chat sempre bloqueia vídeos, independente da configuração
📚 Referências:
Operação

Autenticação Social

Use POST /api/v1/auth/social com Provider, ExternalId, DisplayName e CPF ou ForeignDocument. A resposta traz o token JWT.

Endpoint

POST /api/v1/auth/social

Exemplo de Requisição

curl -X POST http://localhost:8080/api/v1/auth/social \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "google",
    "externalId": "abc-123",
    "displayName": "Ana Souza",
    "cpf": "12345678900",
    "email": "ana@exemplo.com"
  }'

Diagrama de Sequência

📊 Ver Diagrama de Sequência
Diagrama de sequência: Autenticação
Operação

Descoberta de Território

Descubra territórios próximos usando geolocalização ou liste todos os territórios disponíveis.

Endpoints

  • Territórios próximos: GET /api/v1/territories/nearby?lat=-23.55&lng=-46.63
  • Listar todos: GET /api/v1/territories

Exemplo de Requisição

curl "http://localhost:8080/api/v1/territories/nearby?lat=-23.55&lng=-46.63" \
  -H "Authorization: Bearer <token>"

Diagrama de Sequência

📊 Ver Diagrama de Sequência
Diagrama de sequência: Descoberta de Território
Operação

Marketplace Checkout

Fluxo completo de marketplace: criar loja, adicionar itens, gerenciar carrinho, fazer checkout e processar payout.

Fluxo Completo

  1. Criar loja: POST /api/v1/stores
  2. Adicionar itens: POST /api/v1/items
  3. Adicionar ao carrinho: POST /api/v1/cart/items
  4. Checkout: POST /api/v1/cart/checkout
  5. Marcar como pago: PATCH /api/v1/cart/checkout/{id}/status (Status: Paid)
  6. Payout automático: Sistema processa payout conforme configuração

Diagrama de Sequência

📊 Ver Diagrama de Sequência
Diagrama de sequência: Marketplace - Fluxo completo (loja → item → carrinho → checkout → payout)
Fundações Técnicas

Qualidade, Performance e Observabilidade

A API Arah foi construída sobre uma base sólida de práticas de engenharia moderna. Arquitetura limpa, testes abrangentes e observabilidade completa garantem confiabilidade, manutenibilidade e escalabilidade para comunidades em produção.

Qualidade de Código

Engenharia de software orientada a qualidade e confiabilidade, com foco em manutenibilidade a longo prazo e evolução segura da plataforma.

Paginação padronizada
15 endpoints críticos implementam paginação completa com PaginatedResult<T>, garantindo performance consistente em grandes volumes de dados.
Validação robusta
FluentValidation em todas as camadas: contratos de API, comandos de aplicação e regras de domínio. Validações declarativas e mensagens de erro claras.
Cobertura de testes acima de 90%
Testes unitários, de integração e end-to-end cobrindo fluxos críticos. Testes de infraestrutura para repositórios e serviços de aplicação.
Testes de segurança e performance
Testes automatizados de vulnerabilidades comuns, validação de autorização e testes de carga para endpoints críticos.
Refatoração completa de services
Arquitetura limpa com Single Responsibility Principle. Services focados, testáveis e desacoplados, facilitando manutenção e evolução.

Performance & Escalabilidade

Otimizações arquiteturais e técnicas avançadas para garantir baixa latência e capacidade de crescimento com o aumento da demanda.

Concorrência otimista
RowVersion em entidades críticas previne condições de corrida e garante consistência de dados em operações concorrentes.
Cache distribuído
Redis para cache de sessões, configurações e dados frequentemente acessados, reduzindo carga no banco de dados.
Processamento assíncrono
Event Bus com padrão Outbox/Inbox para processamento confiável de eventos, notificações e operações em background.
Read replicas
Suporte nativo para leitura distribuída, permitindo escalar consultas independentemente de operações de escrita.
Deployment multi-instância
Arquitetura stateless permite escalonamento horizontal sem compartilhamento de estado entre instâncias.
📊

Observabilidade

Visibilidade completa sobre o comportamento da plataforma em produção, permitindo detecção proativa de problemas e otimização contínua.

Logs estruturados
Serilog com Seq para logs centralizados, pesquisáveis e estruturados. Contexto enriquecido para debugging eficiente.
Métricas Prometheus
Métricas de negócio e infraestrutura expostas em formato Prometheus para monitoramento e alertas baseados em thresholds.
Distributed tracing
OpenTelemetry para rastreamento de requisições através de serviços, facilitando identificação de gargalos e dependências.
Dashboards e alertas
Grafana para visualização de métricas e alertas configuráveis para eventos críticos e degradação de performance.
Runbook e troubleshooting
Documentação operacional detalhada para incidentes comuns, facilitando resolução rápida e consistente de problemas.
🔒

Segurança

Múltiplas camadas de proteção para garantir integridade de dados, privacidade dos usuários e resistência a ataques comuns.

Autenticação multi-fator
2FA via TOTP (Time-based One-Time Password) para proteção adicional de contas sensíveis e operações críticas.
Sanitização avançada
Validação e sanitização rigorosa de inputs em todas as camadas, prevenindo injeção de código e XSS.
Proteção CSRF
Anti-forgery tokens para prevenir requisições cross-site não autorizadas em operações de estado.
Security headers
Content Security Policy (CSP), HTTP Strict Transport Security (HSTS) e outros headers de segurança configurados adequadamente.
Auditoria completa
Log de todas as ações críticas (mudanças de role, moderação, configurações) para rastreabilidade e compliance.

Qualidade em produção: A API Arah segue rigorosamente os princípios de engenharia de software de alto padrão, com foco em confiabilidade, manutenibilidade e escalabilidade. Todas as decisões arquiteturais foram documentadas e são continuamente revisadas para garantir evolução segura e sustentável da plataforma.

Visão Futura

Roadmap e Direcionamento

O Arah evolui de forma consciente e sustentável, priorizando funcionalidades que fortalecem a organização comunitária local. O roadmap de 28 fases desenha um caminho gradual em direção a maior autonomia territorial, economia circular e regeneração social. Cada fase expande capacidades técnicas que, em conjunto, permitem que comunidades construam e sustentem seus próprios sistemas de organização, economia e cuidado territorial. Abaixo estão as direções planejadas e oportunidades de contribuição.

1️⃣

Onda 1: MVP Essencial

Fases 8-11: Infraestrutura de mídia, perfil completo, mídias em conteúdo e edição. Base sólida para comunicação rica e expressão comunitária.

2️⃣

Onda 2: Comunicação e Governança

Fases 13-14: Conector de e-mail e governança comunitária com votação. Ferramentas para decisão coletiva e participação democrática.

3️⃣

Onda 3: Soberania Territorial

Fases 17-18: Gamificação harmoniosa e saúde territorial com monitoramento. Engajamento sustentável e cuidado com o território através de mecânicas conscientes.

4️⃣

Onda 4: Economia Local

Fases 20, 23-24: Moeda territorial, compra coletiva e trocas comunitárias. Economia circular e autonomia financeira territorial fortalecendo redes locais.

5️⃣

Onda 5: Conformidade e Inteligência

Fases 12, 15: Otimizações finais e inteligência artificial integrada. Performance e capacidades avançadas mantendo os princípios do projeto.

6️⃣

Onda 6: Diferenciais

Fases 16, 19, 21-22: Entregas territoriais, arquitetura modular, suporte a criptomoedas e integrações externas. Flexibilidade arquitetural mantendo autonomia.

7️⃣

Onda 7: Autonomia Digital e Economia Circular

Fases 25-28: Hub de serviços digitais, chat com IA, consumo consciente, negociação territorial, assinatura coletiva e banco de sementes. Autonomia digital completa e soberania alimentar territorial.

🎯

Direcionamento e Princípios

Princípios fundamentais que guiam a evolução do Arah através das 28 fases.

  • Território-first: Todas as funcionalidades fortalecem o vínculo com o território físico e organização comunitária local.
  • Governança transparente: Regras explícitas, auditáveis e evolutivas, com separação clara entre governança global e territorial.
  • Baixa excitação, alto cuidado: Interface e funcionalidades que promovem foco, clareza e continuidade, sem manipulação algorítmica.
  • Qualidade sobre velocidade: Cobertura de testes >90%, validações robustas, arquitetura limpa e documentação atualizada.

📊 Visão completa: Consulte o Roadmap Visual e a Estratégia Executiva para detalhes completos das 28 fases e suas correlações.

Contribuição

Contribua com o Arah

O Arah é um projeto comunitário de código aberto. Contribuições são bem-vindas e essenciais para fortalecer a plataforma e alcançar comunidades ao redor do mundo.

💻 Para Desenvolvedores

Contribua com código, testes, documentação e melhorias técnicas.

  • Implementar funcionalidades alinhadas ao roadmap
  • Melhorar cobertura de testes e qualidade de código
  • Documentar APIs e exemplos de uso
  • Otimizar performance e escalabilidade
  • Revisar Pull Requests e sugerir melhorias

🛠️ Setup local: .NET 8, PostgreSQL + PostGIS, Redis (opcional). Consulte CONTRIBUTING.md para detalhes técnicos e padrões de código.

📚 Formas de Contribuição

Existem várias formas de contribuir, independente do nível técnico.

  • Relatar bugs e propor melhorias via Issues
  • Validar fluxos e testar funcionalidades em desenvolvimento
  • Ajustar documentação e melhorar exemplos práticos
  • Sugerir features alinhadas à visão do produto
  • Traduzir conteúdo para outros idiomas
  • Compartilhar casos de uso e experiências reais

📖 Documentação: Consulte docs/ para visão de produto, arquitetura, decisões técnicas e guias de implementação.

💚

Contribuição Financeira via PIX

Ajude a sustentar o projeto Arah com uma contribuição financeira. Sua doação apoia o desenvolvimento contínuo e a manutenção da plataforma.

Contribuições são investidas diretamente em infraestrutura, ferramentas de desenvolvimento e melhorias da plataforma.

💰 Contribuir via PIX

Qualquer valor faz diferença para o crescimento do projeto

Próximos passos: Explore o repositório, abra uma Issue para discussão ou envie um Pull Request. Todas as contribuições seguem o Código de Conduta e passam por revisão cuidadosa para manter os altos padrões de qualidade do projeto.

Versões & compatibilidade

Versionamento

A API atual utiliza prefixo /api/v1. Mudanças compatíveis devem manter o contrato dentro dessa versão. Para evolução maior, a estratégia recomendada é introduzir um novo prefixo.

Consulte o changelog do repositório em docs/40_CHANGELOG.md para histórico.
Configure seu Ambiente

Configure seu Ambiente - Guia Rápido

Este guia rápido ajuda você a configurar seu ambiente para começar a usar a API Arah em poucos passos.

Quickstart - Copie e cole (5–10 comandos)

Bash (Linux/macOS/Git Bash)

# 1) Rodar API
ASPNETCORE_ENVIRONMENT=Development dotnet run --project backend/Arah.Api --urls http://localhost:8080

# 2) Autenticação social (gera token)
curl -X POST http://localhost:8080/api/v1/auth/social \
  -H "Content-Type: application/json" \
  -d '{"provider":"google","externalId":"abc-123","displayName":"Ana","cpf":"12345678900"}'

# 3) Descobrir território
curl http://localhost:8080/api/v1/territories

# 4) Selecionar território (X-Session-Id)
curl -X POST http://localhost:8080/api/v1/territories/selection \
  -H "Content-Type: application/json" \
  -H "X-Session-Id: session-123" \
  -d '{"territoryId":"11111111-1111-1111-1111-111111111111"}'

PowerShell (Windows)

# 1) Rodar API
$env:ASPNETCORE_ENVIRONMENT="Development"
dotnet run --project backend/Arah.Api --urls "http://localhost:8080"

# 2) Autenticação social (gera token)
curl.exe -X POST "http://localhost:8080/api/v1/auth/social" `
  -H "Content-Type: application/json" `
  -d "{\"provider\":\"google\",\"externalId\":\"abc-123\",\"displayName\":\"Ana\",\"cpf\":\"12345678900\"}"

# 3) Descobrir território
curl.exe "http://localhost:8080/api/v1/territories"

# 4) Selecionar território (X-Session-Id)
curl.exe -X POST "http://localhost:8080/api/v1/territories/selection" `
  -H "Content-Type: application/json" `
  -H "X-Session-Id: session-123" `
  -d "{\"territoryId\":\"11111111-1111-1111-1111-111111111111\"}"
Dica: este portal tem fonte única em backend/Arah.Api/wwwroot/devportal (HTML/CSS/JS/OpenAPI). O deploy do GitHub Pages publica exatamente essa pasta.
Modelo de domínio

Entidades principais e relacionamentos

Diagrama do domínio: temporariamente removido (atualização pendente).

🧭 Território & Configuração

Territory
Unidade primária. Contexto para visibilidade, governança e conteúdo.
Feature Flags
Habilitam recursos por território (ex.: tipos de post como AlertPosts).
SystemConfig
Parâmetros calibráveis (governança e validações globais).

👤 Identidade, Perfil & Preferências

User
Identidade autenticada usada em todos os módulos.
UserProfile
Perfil do usuário (ex.: display name e contato).
UserPreferences
Preferências (privacidade e notificações).
2FA (TOTP)
Camada adicional de segurança para login (setup/confirm/verify).

🤝 Membership & Onboarding

TerritoryMembership
Vínculo User ↔ Territory com role (Visitor/Resident) e status de residência.
JoinRequest
Pedido para virar residente (aprovação/rejeição pela comunidade/curadoria).
WorkItem
Fila genérica de revisão humana (fallback para governança global quando necessário).

🧾 Verificação & Evidências

Verification
Processos de verificação (identidade e residência) conforme políticas.
DocumentEvidence
Metadados de evidência (upload e download via proxy).
TerritoryWorkItems
Backlog territorial para curadoria e validações.

📝 Feed & Publicações

CommunityPost
Post do território, com tipo/visibilidade e autoria.
PostGeoAnchor
Âncora geográfica opcional para integrar feed e mapa.
Share
Compartilhamento de posts dentro do território.

🗺️ Mapa, Assets & Alerts

MapEntity
Entidade do mapa (pode começar sugerida e ser confirmada/validada).
TerritoryAsset
Recurso territorial com geolocalização obrigatória.
Alert
Alerta territorial (validação/curadoria, aparece em feed + mapa).

🛒 Marketplace

TerritoryStore
Loja do morador no território.
Item
Produto/serviço publicado pela loja (categoria, tags, preço, status).
Cart / CartItem
Carrinho por território com itens (quantidade e notas por item).
Inquiry
Mensagem de interesse em um item (inquiries enviadas/recebidas).

💰 Payout & Gestão Financeira

FinancialTransaction
Tabela central de rastreabilidade - rastreia cada centavo.
SellerBalance
Saldo do vendedor por território (Pending, ReadyForPayout, Paid).
SellerTransaction
Transação do vendedor vinculada a um checkout pago.
TerritoryPayoutConfig
Configuração de payout por território (retenção, valores mínimo/máximo, frequência).
PlatformFinancialBalance
Saldo da plataforma por território (receitas - despesas).
PlatformRevenueTransaction
Receitas da plataforma (fees coletadas de checkouts).
PlatformExpenseTransaction
Despesas da plataforma (payouts processados para vendedores).

📅 Eventos

TerritoryEvent
Evento territorial com início obrigatório, fim opcional e geolocalização.
Interest / Confirm
Estados de engajamento: marcar interesse e confirmar presença no evento.
Integração Feed-Mapa
Evento criado aparece automaticamente no feed e no mapa (mesmo território).

💬 Chat

Conversation
Conversas e grupos (inclui chat territorial).
ChatMessage
Mensagens com paginação por cursor (beforeCreatedAt / beforeMessageId). Suporta imagens (1 por mensagem, máx. 5MB) e áudios curtos (1 por mensagem, máx. 2MB, até 60s). Vídeos não permitidos.
Participants
Participantes, papéis e "read state" (marcar como lido).

🛡️ Moderação & Segurança

Report
Sinalização de abuso (posts e usuários), com motivo e detalhes.
Block
Remove visibilidade do conteúdo produzido por um usuário bloqueado.
TerritoryModerationCase
Casos de moderação por território (triagem e rastreabilidade).

🔔 Notificações

OutboxMessage
Registro transacional da intenção de notificar.
UserNotification
Inbox in-app por usuário (listar e marcar como lida).

Por que essa estrutura existe

Separação de responsabilidades

Território separado de identidade evita acoplamento social no mapa

Governança clara

Vínculos explicitam presença local e governança comunitária

Integração feed-mapa

Posts + geo anchors conectam feed e mapa sem confundir o domínio

Economia local

Marketplace permite economia dentro do território

Engajamento

Eventos conectam comunidade com atividades locais

Confiança

Moderação mantém confiança com regras auditáveis

Confiabilidade

Notificações usam outbox para evitar perda de eventos após commit

Fluxos principais

Sequências orientadas a produto e API

1. Autenticação social → JWT

Use POST /api/v1/auth/social com Provider, ExternalId, DisplayName e CPF ou ForeignDocument. A resposta traz o token JWT.

curl -X POST http://localhost:8080/api/v1/auth/social \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "google",
    "externalId": "abc-123",
    "displayName": "Ana Souza",
    "cpf": "12345678900",
    "email": "ana@exemplo.com"
  }'
📊 Ver Diagrama de Sequência
Diagrama de sequência: Autenticação

2. Descoberta de território

GET /api/v1/territories lista territórios disponíveis. Para busca, use /search ou /nearby com lat e lng.

curl "http://localhost:8080/api/v1/territories/nearby?lat=-23.55&lng=-46.63&radiusKm=10"
📊 Ver Diagrama de Sequência
Diagrama de sequência: territory-discovery

3. Seleção de território (sessão)

Defina o território ativo com POST /api/v1/territories/selection usando X-Session-Id. Esse header substitui o territoryId em várias rotas.

curl -X POST http://localhost:8080/api/v1/territories/selection \
  -H "Content-Type: application/json" \
  -H "X-Session-Id: session-123" \
  -d '{"territoryId": "11111111-1111-1111-1111-111111111111"}'

4. Feed territorial

GET /api/v1/feed retorna posts filtrados pelo território ativo. Visitantes veem apenas posts públicos publicados. Moradores veem conteúdo ampliado.

curl http://localhost:8080/api/v1/feed \
  -H "Authorization: Bearer <token>" \
  -H "X-Session-Id: session-123"
📊 Ver Diagrama de Sequência
Diagrama de sequência: Listagem de Feed

5. Criar post + âncoras geográficas + mídias

Para criar post use POST /api/v1/feed. As âncoras geográficas são opcionais e posts são criados por moradores. Posts podem incluir até 10 mídias (imagens, vídeos e/ou áudios) através do campo mediaIds, com no máximo 1 vídeo e 1 áudio por post. Eventos são criados via POST /api/v1/events, com data/hora e geolocalização obrigatória, e aparecem no feed e no mapa.

curl -X POST http://localhost:8080/api/v1/feed \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "X-Session-Id: session-123" \
  -d '{
    "title": "Mutirão de limpeza",
    "content": "Encontro sábado 9h.",
    "type": "General",
    "visibility": "Public",
    "mapEntityId": null,
    "geoAnchors": [{"latitude": -23.55, "longitude": -46.63, "type": "POST"}],
    "assetIds": ["aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"],
    "mediaIds": ["bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", "cccccccc-cccc-cccc-cccc-cccccccccccc"]
  }'
📸🎥🎧 Mídias em Posts (Imagens, Vídeos e Áudios):
  • Upload de mídia: Primeiro, faça upload via POST /api/v1/media/upload para obter o mediaId (aceita imagens JPEG/PNG/WebP, vídeos MP4 e áudios MP3/WAV/OGG)
  • Associar ao post: Inclua os mediaIds no array ao criar o post (máximo 10 mídias: imagens, vídeos e/ou áudios)
  • Vídeos: Máximo 1 vídeo por post, até 50MB, até 60 segundos (similar a TikTok/Instagram Reels). Formatos suportados: MP4
  • Áudios: Máximo 1 áudio por post, até 10MB, até 5 minutos (podcasts curtos, narrações). Formatos suportados: MP3, WAV, OGG
  • Imagens: Múltiplas imagens permitidas (até 10 mídias no total, combinando imagens, vídeos e áudios). Formatos suportados: JPEG, PNG, WebP
  • Resposta: O FeedItemResponse inclui mediaUrls (array de URLs de imagens, vídeos e áudios) e mediaCount
  • Validação: Todas as mídias devem pertencer ao usuário que está criando o post. Vídeos maiores que 50MB, áudios maiores que 10MB, mais de 1 vídeo ou mais de 1 áudio por post retornam erro
📊 Ver Diagrama de Sequência
Diagrama de sequência: post-creation

5a. Criar evento comunitário

Eventos são criados via POST /api/v1/events com data/hora e geolocalização obrigatória. Eventos aparecem automaticamente no feed e no mapa. Usuários podem marcar interesse ou confirmação.

curl -X POST http://localhost:8080/api/v1/events \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "X-Session-Id: session-123" \
  -d '{
    "territoryId": "11111111-1111-1111-1111-111111111111",
    "title": "Mutirão de limpeza",
    "description": "Encontro sábado 9h",
    "startsAtUtc": "2025-01-25T09:00:00Z",
    "latitude": -23.55,
    "longitude": -46.63,
    "locationLabel": "Praça Central"
  }'
📊 Ver Diagrama de Sequência
Diagrama de sequência: Eventos - Criação e confirmação

6. Assets territoriais (com geolocalização obrigatória)

Assets sempre possuem ao menos uma âncora geográfica e são exibidos no mapa via pins do tipo asset. Somente moradores validados ou curadores podem criar/editar/arquivar.

curl -X POST http://localhost:8080/api/v1/assets \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "X-Session-Id: session-123" \
  -d '{
    "territoryId": "11111111-1111-1111-1111-111111111111",
    "type": "river",
    "name": "Rio do Vale",
    "description": "Trecho monitorado",
    "geoAnchors": [{"latitude": -23.55, "longitude": -46.63}]
  }'
📊 Ver Diagrama de Sequência
Diagrama de sequência: Assets - Criação e validação por curador

7. Alertas ambientais (feed + mapa)

Alertas usam /api/v1/alerts e aparecem no feed e no mapa (pins do tipo alert) quando validados por curadores.

curl -X POST http://localhost:8080/api/v1/alerts \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "X-Session-Id: session-123" \
  -d '{"title": "Queimada", "description": "Fumaça próxima à nascente"}'

8. Mapa: entidades, pins e validação

Use GET /api/v1/map/entities e /pins para visualizar. Sugestões usam POST /api/v1/map/entities (categorias: estabelecimento, órgão do governo, espaço público, espaço natural). Confirmações usam /confirmations e validações /validation são exclusivas para curadores. Pins aceitam filtros por types, assetId e assetTypes.

curl http://localhost:8080/api/v1/map/pins?types=asset,alert,entity \
  -H "Authorization: Bearer <token>" \
  -H "X-Session-Id: session-123"
📊 Ver Diagrama de Sequência
Diagrama de sequência: Mapa - Entidades (sugestão → confirmação → validação)

9. Membership: visitor → resident

O visitante solicita residência via POST /api/v1/memberships/{territoryId}/become-resident (convite direcionado via recipientUserIds ou fila de curadoria). Destinatários (ou curadores) aprovam em POST /api/v1/join-requests/{id}/approve, promovendo para RESIDENT (com ResidencyVerification=NONE). O status atual do vínculo está em GET /api/v1/memberships/{territoryId}/me. Para verificar residência (geo/doc), use /verify-residency/geo ou /verify-residency/document. Quando a policy exige presença, envie X-Geo-Latitude/X-Geo-Longitude.

📊 Ver Diagrama de Sequência
Diagrama de sequência: membership-resident

10. Moderação & segurança: reports, triagem e bloqueios

O fluxo típico é: (1) um usuário reporta; (2) a curadoria lista reports do território e prioriza; (3) quando necessário, aplica bloqueio para cortar propagação do conteúdo no feed e no mapa. Reports usam reason (obrigatório) e details (opcional).

# Reportar um post
curl -X POST http://localhost:8080/api/v1/reports/posts/{postId} \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"reason":"Spam","details":"Link suspeito no conteúdo"}'

# Reportar um usuário (opcionalmente por território)
curl -X POST "http://localhost:8080/api/v1/reports/users/{userId}?territoryId=11111111-1111-1111-1111-111111111111" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"reason":"Abuso","details":"Comportamento inadequado"}'

# Curadoria lista reports para triagem
curl "http://localhost:8080/api/v1/reports?territoryId=11111111-1111-1111-1111-111111111111&status=Open" \
  -H "Authorization: Bearer <token>"

# Bloquear / desbloquear um usuário
curl -X POST http://localhost:8080/api/v1/blocks/users/{userId} \
  -H "Authorization: Bearer <token>"

curl -X DELETE http://localhost:8080/api/v1/blocks/users/{userId} \
  -H "Authorization: Bearer <token>"
📊 Ver Diagrama de Sequência
Diagrama de sequência: moderation

9a. Verificação de residência

Moradores podem verificar residência por geolocalização (POST /api/v1/memberships/{territoryId}/verify-residency/geo) ou por comprovante documental (POST /api/v1/memberships/{territoryId}/verify-residency/document). Quando a policy exige presença, envie X-Geo-Latitude/X-Geo-Longitude.

# Verificação por geo
curl -X POST http://localhost:8080/api/v1/memberships/{territoryId}/verify-residency/geo \
  -H "Authorization: Bearer <token>" \
  -H "X-Geo-Latitude: -23.55" \
  -H "X-Geo-Longitude: -46.63" \
  -H "Content-Type: application/json" \
  -d '{"lat": -23.55, "lng": -46.63}'

# Verificação por documento
curl -X POST http://localhost:8080/api/v1/evidences \
  -H "Authorization: Bearer <token>" \
  -F "file=@comprovante.pdf" \
  -F "type=ResidencyDocument"

curl -X POST http://localhost:8080/api/v1/memberships/{territoryId}/verify-residency/document \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"evidenceId": "evidence-id"}'
📊 Ver Diagrama de Sequência
Diagrama de sequência: Verificação de residência (geo/document)

11. Notificações in-app

Eventos relevantes geram mensagens em outbox que são processadas em background para criar notificações por usuário. Consulte GET /api/v1/notifications e marque como lidas em POST /api/v1/notifications/{id}/read.

📊 Ver Diagrama de Sequência
Diagrama de sequência: Sistema de Notificações (Outbox Pattern)

11a. Enviar mensagem no chat com imagem

O chat permite enviar imagens junto com mensagens de texto. Cada mensagem pode conter uma imagem (máximo 5MB, apenas imagens). Primeiro faça upload da imagem via POST /api/v1/media/upload e depois inclua o mediaId ao enviar a mensagem.

# 1) Upload da imagem
curl -X POST http://localhost:8080/api/v1/media/upload \
  -H "Authorization: Bearer <token>" \
  -F "file=@imagem.jpg"

# 2) Enviar mensagem com imagem
curl -X POST http://localhost:8080/api/v1/chat/conversations/{conversationId}/messages \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Olha essa foto!",
    "mediaId": "gggggggg-gggg-gggg-gggg-gggggggggggg"
  }'
💬 Mídias em Chat:
  • Upload de mídia: Use POST /api/v1/media/upload para fazer upload da imagem ou áudio (aceita imagens JPEG/PNG/WebP e áudios MP3/WAV/OGG, não aceita vídeos)
  • Enviar mensagem: Inclua o mediaId no campo opcional ao enviar mensagem
  • Imagens: 1 imagem por mensagem, máximo 5MB. Formatos: JPEG, PNG, WebP
  • Áudios: 1 áudio por mensagem (mensagens de voz), máximo 2MB, até 60 segundos. Formatos: MP3, WAV, OGG
  • Vídeos: Não permitidos (apenas imagens e áudios permitidos por questões de performance e privacidade)
  • Resposta: O MessageResponse inclui mediaUrl e hasMedia
  • Validação: A mídia deve pertencer ao usuário que está enviando a mensagem. Vídeos retornam erro "Only images and audios are allowed in chat messages"
📊 Ver Diagrama de Sequência
Diagrama de sequência: Chat com mídia
Casos de uso

Jornadas práticas e funcionalidades implementadas

Cenários práticos conectando objetivo → pré-requisitos → endpoints. Todas as jornadas requerem autenticação (JWT) e seleção de território via X-Session-Id. Os exemplos abaixo refletem funcionalidades já implementadas e testadas em produção.

🚀 Onboarding completo

Primeira jornada: autenticação, descoberta de território e vínculo inicial.

  1. Autenticar: POST /api/v1/auth/social (obtém JWT)
  2. Descobrir território: GET /api/v1/territories/nearby?lat=-23.55&lng=-46.63
  3. Selecionar território: POST /api/v1/territories/selection + header X-Session-Id
  4. Declarar vínculo: POST /api/v1/memberships/{territoryId}/enter-visitor
  5. Verificar membership: GET /api/v1/memberships/{territoryId}/me

📝 Publicar conteúdo com mídias

Criar post com até 10 imagens e âncoras geográficas opcionais.

  1. Upload de mídias: POST /api/v1/media/upload (obtém mediaIds)
  2. Criar post: POST /api/v1/feed com mediaIds (até 10 imagens)
  3. GeoAnchors automáticos: derivados de mídias quando disponíveis
  4. Visualizar no mapa: GET /api/v1/map/pins?types=post
  5. Ver no feed: GET /api/v1/feed/paged

🗺️ Assets territoriais com geolocalização

Recursos territoriais (rios, trilhas, nascentes) sempre com geolocalização obrigatória.

  1. Criar asset: POST /api/v1/assets (geo obrigatória em geoAnchors)
  2. Tipos disponíveis: river, trail, spring, lookout, sanctuary
  3. Apenas moradores verificados ou curadores: podem criar/editar/arquivar
  4. Visualizar no mapa: GET /api/v1/map/pins?types=asset&assetTypes=river,trail

💬 Chat territorial e grupos

Conversas territoriais, grupos e mensagens diretas com suporte a mídias.

  1. Criar conversa: POST /api/v1/chat/conversations
  2. Enviar mensagem: POST /api/v1/chat/conversations/{id}/messages
  3. Mensagem com imagem: incluir mediaId no payload
  4. Listar conversas: GET /api/v1/chat/conversations
  5. Histórico: GET /api/v1/chat/conversations/{id}/messages

🏪 Marketplace e economia local

Lojas, produtos/serviços, carrinho e checkout com até 10 imagens por item. Economia circular territorial que mantém recursos na comunidade.

  1. Criar loja: POST /api/v1/stores
  2. Adicionar itens: POST /api/v1/items com mediaIds (até 10 imagens)
  3. Carrinho: POST /api/v1/cart/items
  4. Checkout: POST /api/v1/cart/checkout
  5. Consultar itens: GET /api/v1/items (paginação incluída)

📅 Eventos comunitários com mídias

Eventos territoriais com data/hora, geolocalização obrigatória e imagens.

  1. Criar evento: POST /api/v1/events (geo obrigatória)
  2. Imagens: coverMediaId e additionalMediaIds (até 10)
  3. Marcar interesse: POST /api/v1/events/{id}/interest
  4. Confirmar presença: POST /api/v1/events/{id}/confirm
  5. Aparece no feed e mapa: eventos aparecem em ambos os contextos

✨ Principais Funcionalidades

  • Rastreabilidade completa: Cada centavo é rastreado em FinancialTransaction
  • Retenção configurável: Aguarda período configurado antes de liberar para payout
  • Valor mínimo/máximo: Acumula até atingir mínimo ou divide se exceder máximo
  • Payout automático: Background worker processa payouts automaticamente
  • Gestão financeira da plataforma: Saldo, receitas e despesas separadas por território
🚀 Guia de Produção (Passo a Passo)

Abaixo você encontrará um guia completo para colocar o sistema de payout em produção. O guia foi projetado para ser seguido por qualquer pessoa, mesmo com conhecimento mínimo de programação.

📋 Passo 1: Entendendo o Fluxo de Payout

Quando um cliente compra algo na loja de um vendedor e o pagamento é confirmado, o seguinte acontece:

  1. Checkout pago → Sistema cria SellerTransaction automaticamente
  2. Valor líquido → Subtotal - Fees da plataforma = Valor para o vendedor
  3. Período de retenção → Aguarda dias configurados (ex: 7 dias)
  4. Valor mínimo → Acumula até atingir valor mínimo configurado (ex: R$ 100,00)
  5. Payout automático → Background worker processa quando todas as condições são atendidas
  6. Transferência → Dinheiro é transferido para o vendedor via gateway (Stripe, MercadoPago, etc.)

⚙️ Passo 2: Configurar Payout para um Território

Antes de usar o sistema de payout, você precisa configurar como ele funciona para cada território. Essa configuração define período de retenção, valores mínimo/máximo, frequência e se requer aprovação manual.

# Criar ou atualizar configuração de payout
curl -X POST "http://localhost:8080/api/v1/territories/{territoryId}/payout-config" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "retentionPeriodDays": 7,
    "minimumPayoutAmountInCents": 10000,
    "maximumPayoutAmountInCents": 5000000,
    "frequency": "Weekly",
    "autoPayoutEnabled": true,
    "requiresApproval": false,
    "currency": "BRL"
  }'
📝 Explicação dos Campos:
  • retentionPeriodDays: Quantos dias aguardar antes de liberar para payout (ex: 7 = aguarda 7 dias)
  • minimumPayoutAmountInCents: Valor mínimo em centavos para processar payout (ex: 10000 = R$ 100,00)
  • maximumPayoutAmountInCents: Valor máximo por payout - se exceder, divide em múltiplos (ex: 5000000 = R$ 50.000,00)
  • frequency: Frequência do payout automático - "Daily", "Weekly", "Monthly" ou "Manual"
  • autoPayoutEnabled: Se true, processa payouts automaticamente. Se false, apenas manual
  • requiresApproval: Se true, requer aprovação manual antes de processar (ainda não implementado)
  • currency: Moeda da configuração - "BRL", "USD", etc.

🔍 Passo 3: Consultar Configuração de Payout

Para ver a configuração atual de payout de um território:

# Consultar configuração ativa
curl "http://localhost:8080/api/v1/territories/{territoryId}/payout-config" \
  -H "Authorization: Bearer <token>"

💰 Passo 4: Consultar Saldo do Vendedor

Vendedores podem consultar seu saldo e histórico de transações:

# Consultar meu saldo como vendedor
curl "http://localhost:8080/api/v1/territories/{territoryId}/seller-balance/me" \
  -H "Authorization: Bearer <token>"

# Consultar minhas transações como vendedor
curl "http://localhost:8080/api/v1/territories/{territoryId}/seller-balance/me/transactions" \
  -H "Authorization: Bearer <token>"
📊 Entendendo o Saldo do Vendedor:
  • pendingAmountInCents: Valor que ainda está no período de retenção
  • readyForPayoutAmountInCents: Valor pronto para payout (após período de retenção e valor mínimo)
  • paidAmountInCents: Valor já transferido para o vendedor

📈 Passo 5: Gestão Financeira da Plataforma

Administradores podem consultar o saldo financeiro da plataforma (receitas de fees e despesas de payouts):

# Consultar saldo da plataforma (apenas SystemAdmin ou FinancialManager)
curl "http://localhost:8080/api/v1/territories/{territoryId}/platform-financial/balance" \
  -H "Authorization: Bearer <token>"

# Listar receitas (fees coletadas)
curl "http://localhost:8080/api/v1/territories/{territoryId}/platform-financial/revenue" \
  -H "Authorization: Bearer <token>"

# Listar despesas (payouts processados)
curl "http://localhost:8080/api/v1/territories/{territoryId}/platform-financial/expenses" \
  -H "Authorization: Bearer <token>"

🔧 Passo 6: Configuração em Produção - Checklist

Para colocar o sistema de payout em produção, siga este checklist:

✅ Pré-requisitos
  1. Migration aplicada: Execute a migration 20260119000000_AddFinancialSystem.cs no banco de dados
  2. Gateway de pagamento configurado: Tenha uma conta no gateway (Stripe Connect, MercadoPago, etc.)
  3. Background worker ativo: Certifique-se de que o PayoutProcessingWorker está rodando
⚙️ Configuração Inicial
  1. Configure payout por território: Use POST /api/v1/territories/{territoryId}/payout-config
  2. Configure período de retenção: Recomendado: 7-14 dias (protege contra chargebacks)
  3. Configure valor mínimo: Recomendado: R$ 50,00 - R$ 200,00 (reduz custos de transferência)
  4. Configure valor máximo: Se necessário, limite por payout (ex: R$ 50.000,00)
  5. Escolha frequência: "Daily" (diário), "Weekly" (semanal) ou "Monthly" (mensal)
  6. Habilite payout automático: Defina autoPayoutEnabled: true
🔌 Integração com Gateway de Pagamento
  1. Implemente IPayoutGateway: Crie implementação para seu gateway (Stripe, MercadoPago, etc.)
  2. Registre no DI: Substitua MockPayoutGateway por sua implementação real em ServiceCollectionExtensions.cs
  3. Configure credenciais: Adicione chaves de API do gateway em appsettings.json ou variáveis de ambiente
  4. Teste em sandbox: Use ambiente de testes do gateway antes de produção
🧪 Testes e Validação
  1. Teste checkout completo: Crie checkout, marque como Paid e verifique se SellerTransaction foi criada
  2. Verifique retenção: Confirme que o valor fica em pendingAmountInCents durante o período de retenção
  3. Teste valor mínimo: Crie múltiplos checkouts pequenos e confirme que só processa quando atinge o mínimo
  4. Verifique payout automático: Aguarde o background worker processar e verifique transferência no gateway
  5. Monitore logs: Verifique logs do PayoutProcessingWorker para erros ou avisos

🏗️ Passo 7: Implementar Gateway de Pagamento Real

O sistema vem com um MockPayoutGateway para desenvolvimento. Para produção, você precisa implementar o IPayoutGateway para seu gateway de pagamento preferido (Stripe Connect, MercadoPago, etc.).

📝 Exemplo: Interface IPayoutGateway
public interface IPayoutGateway
{
  Task<OperationResult<PayoutResult>> CreatePayoutAsync(
    long amountInCents,
    string currency,
    string sellerAccountId,
    string description,
    Dictionary<string, string>? metadata,
    CancellationToken cancellationToken);

  Task<OperationResult<PayoutStatusResult>> GetPayoutStatusAsync(
    string payoutId,
    CancellationToken cancellationToken);

  Task<OperationResult> CancelPayoutAsync(
    string payoutId,
    CancellationToken cancellationToken);
}

Você precisa implementar os 3 métodos acima para seu gateway de pagamento. Veja o exemplo de MockPayoutGateway em backend/Arah.Infrastructure/Payments/MockPayoutGateway.cs como referência.

🔄 Passo 8: Como Funciona o Background Worker

O PayoutProcessingWorker verifica payouts pendentes a cada 5 minutos e processa automaticamente conforme a frequência configurada:

  • Daily: Processa payouts todos os dias (quando o worker roda)
  • Weekly: Processa payouts toda segunda-feira às 00:00 UTC
  • Monthly: Processa payouts no dia 1 de cada mês às 00:00 UTC
  • Manual: Não processa automaticamente - apenas quando chamado manualmente via API

O worker está configurado automaticamente quando você roda a API. Não precisa fazer nada extra para ativá-lo.

📊 Passo 9: Monitoramento e Troubleshooting

Para monitorar o sistema de payout em produção:

  • Logs do Worker: Procure por PayoutProcessingWorker nos logs para ver processamento
  • Transações Financeiras: Consulte GET /api/v1/territories/{territoryId}/platform-financial/revenue para receitas
  • Transações de Despesa: Consulte GET /api/v1/territories/{territoryId}/platform-financial/expenses para payouts
  • Status de Payouts: Use UpdatePayoutStatusAsync para atualizar status do gateway periodicamente

🎯 Casos de Uso Comuns

  • Vendedor quer saber quando receberá: Consulte /seller-balance/me para ver valores pendentes e prontos para payout
  • Processar payout manualmente: Use ProcessPendingPayoutsAsync do SellerPayoutService via API admin
  • Ver histórico de transações: Consulte /seller-balance/me/transactions para ver todas as transações do vendedor
  • Auditar receitas da plataforma: Use endpoints de /platform-financial para ver fees coletadas

⚠️ Pontos de Atenção

  • Período de retenção: Protege contra chargebacks - não configure muito curto
  • Valor mínimo: Reduz custos de transferência - configure baseado no custo do gateway
  • Valor máximo: Limita exposição a risco - configure se necessário
  • Moedas diferentes: Cada território pode ter configuração em moeda diferente
  • Testes primeiro: Sempre teste com valores pequenos antes de produção
📚 Documentação Técnica Completa

Para detalhes técnicos completos, consulte: docs/backlog-api/FASE7.md

Cenário Prático

Onboarding Usuário

Primeira jornada: autenticação, descoberta de território e vínculo inicial.

Fluxo Completo

  1. Autenticar: POST /api/v1/auth/social (obtém JWT)
  2. Descobrir território: GET /api/v1/territories/nearby?lat=-23.55&lng=-46.63
  3. Selecionar território: POST /api/v1/territories/selection + header X-Session-Id
  4. Declarar vínculo: POST /api/v1/memberships/{territoryId}/enter-visitor
  5. Verificar membership: GET /api/v1/memberships/{territoryId}/me
Cenário Prático

Publicar conteúdo com mídias

Criar post com até 10 imagens e âncoras geográficas opcionais.

Fluxo Completo

  1. Upload de mídias: POST /api/v1/media/upload (obtém mediaIds)
  2. Criar post: POST /api/v1/feed com mediaIds (até 10 imagens)
  3. GeoAnchors automáticos: derivados de mídias quando disponíveis
  4. Visualizar no mapa: GET /api/v1/map/pins?types=post
  5. Ver no feed: GET /api/v1/feed/paged
Cenário Prático

Assets territoriais com geolocalização

Recursos territoriais (rios, trilhas, nascentes) sempre com geolocalização obrigatória.

Fluxo Completo

  1. Criar asset: POST /api/v1/assets (geo obrigatória em geoAnchors)
  2. Tipos disponíveis: river, trail, spring, lookout, sanctuary
  3. Apenas moradores verificados ou curadores: podem criar/editar/arquivar
  4. Visualizar no mapa: GET /api/v1/map/pins?types=asset&assetTypes=river,trail
Cenário Prático

Chat territorial e grupos

Conversas territoriais, grupos e mensagens diretas com suporte a mídias.

Fluxo Completo

  1. Criar conversa: POST /api/v1/chat/conversations
  2. Enviar mensagem: POST /api/v1/chat/conversations/{id}/messages
  3. Mensagem com imagem: incluir mediaId no payload
  4. Listar conversas: GET /api/v1/chat/conversations
  5. Histórico: GET /api/v1/chat/conversations/{id}/messages
Cenário Prático

Marketplace e economia local

Lojas, produtos/serviços, carrinho e checkout com até 10 imagens por item. Economia circular territorial que mantém recursos na comunidade.

Fluxo Completo

  1. Criar loja: POST /api/v1/stores
  2. Adicionar itens: POST /api/v1/items com mediaIds (até 10 imagens)
  3. Carrinho: POST /api/v1/cart/items
  4. Checkout: POST /api/v1/cart/checkout
  5. Consultar itens: GET /api/v1/items (paginação incluída)
Cenário Prático

Eventos comunitários com mídias

Eventos territoriais com data/hora, geolocalização obrigatória e imagens.

Fluxo Completo

  1. Criar evento: POST /api/v1/events (geo obrigatória)
  2. Imagens: coverMediaId e additionalMediaIds (até 10)
  3. Marcar interesse: POST /api/v1/events/{id}/interest
  4. Confirmar presença: POST /api/v1/events/{id}/confirm
  5. Aparece no feed e mapa: eventos aparecem em ambos os contextos
Referência

Casos de Uso Comuns

Casos de uso frequentes e soluções práticas para tarefas comuns na API.

Vendedor quer saber quando receberá

Consulte /seller-balance/me para ver valores pendentes e prontos para payout.

GET /api/v1/territories/{territoryId}/seller-balance/me
Authorization: Bearer <token>

Processar payout manualmente

Use ProcessPendingPayoutsAsync do SellerPayoutService via API admin.

Ver histórico de transações

Consulte /seller-balance/me/transactions para ver todas as transações do vendedor.

GET /api/v1/territories/{territoryId}/seller-balance/me/transactions
Authorization: Bearer <token>

Auditar receitas da plataforma

Use endpoints de /platform-financial para ver fees coletadas.

Referência

Pontos de Atenção

Considerações importantes e melhores práticas para usar a API com segurança e eficiência.

Período de retenção

Protege contra chargebacks - não configure muito curto. Recomendado: 7-14 dias.

Valor mínimo

Reduz custos de transferência - configure baseado no custo do gateway. Recomendado: R$ 50,00 - R$ 200,00.

Valor máximo

Limita exposição a risco - configure se necessário. Exemplo: R$ 50.000,00 por payout.

Moedas diferentes

Cada território pode ter configuração em moeda diferente. Configure conforme necessário.

Testes primeiro

Sempre teste com valores pequenos antes de produção para validar fluxo completo.

Guia de Produção

Passo 1: Entendendo o Fluxo de Payout

Quando um cliente compra algo na loja de um vendedor e o pagamento é confirmado, o seguinte acontece:

  1. Checkout pago → Sistema cria SellerTransaction automaticamente
  2. Valor líquido → Subtotal - Fees da plataforma = Valor para o vendedor
  3. Período de retenção → Aguarda dias configurados (ex: 7 dias)
  4. Valor mínimo → Acumula até atingir valor mínimo configurado (ex: R$ 100,00)
  5. Payout automático → Background worker processa quando todas as condições são atendidas
  6. Transferência → Dinheiro é transferido para o vendedor via gateway (Stripe, MercadoPago, etc.)
Guia de Produção

Passo 2: Configurar Payout para um Território

Antes de usar o sistema de payout, você precisa configurar como ele funciona para cada território. Essa configuração define período de retenção, valores mínimo/máximo, frequência e se requer aprovação manual.

Endpoint

POST /api/v1/territories/{territoryId}/payout-config

Exemplo de Requisição

curl -X POST "http://localhost:8080/api/v1/territories/{territoryId}/payout-config" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "retentionPeriodDays": 7,
    "minimumPayoutAmountInCents": 10000,
    "maximumPayoutAmountInCents": 5000000,
    "frequency": "Weekly",
    "autoPayoutEnabled": true,
    "requiresApproval": false,
    "currency": "BRL"
  }'
📝 Explicação dos Campos:
  • retentionPeriodDays: Quantos dias aguardar antes de liberar para payout (ex: 7 = aguarda 7 dias)
  • minimumPayoutAmountInCents: Valor mínimo em centavos para processar payout (ex: 10000 = R$ 100,00)
  • maximumPayoutAmountInCents: Valor máximo por payout - se exceder, divide em múltiplos (ex: 5000000 = R$ 50.000,00)
  • frequency: Frequência do payout automático - "Daily", "Weekly", "Monthly" ou "Manual"
  • autoPayoutEnabled: Se true, processa payouts automaticamente. Se false, apenas manual
  • requiresApproval: Se true, requer aprovação manual antes de processar (ainda não implementado)
  • currency: Moeda da configuração - "BRL", "USD", etc.
Guia de Produção

Passo 3: Consultar Configuração de Payout

Para ver a configuração atual de payout de um território:

Endpoint

GET /api/v1/territories/{territoryId}/payout-config

Exemplo de Requisição

curl "http://localhost:8080/api/v1/territories/{territoryId}/payout-config" \
  -H "Authorization: Bearer <token>"
Guia de Produção

Passo 4: Consultar Saldo do Vendedor

Vendedores podem consultar seu saldo e histórico de transações:

Endpoints

# Consultar meu saldo como vendedor
GET /api/v1/territories/{territoryId}/seller-balance/me

# Consultar minhas transações como vendedor
GET /api/v1/territories/{territoryId}/seller-balance/me/transactions

Exemplo de Requisição

curl "http://localhost:8080/api/v1/territories/{territoryId}/seller-balance/me" \
  -H "Authorization: Bearer <token>"
📊 Entendendo o Saldo do Vendedor:
  • pendingAmountInCents: Valor que ainda está no período de retenção
  • readyForPayoutAmountInCents: Valor pronto para payout (após período de retenção e valor mínimo)
  • paidAmountInCents: Valor já transferido para o vendedor
Autenticação

JWT (HS256)

O token é emitido pelo endpoint /api/v1/auth/social. Ele utiliza algoritmo HS256 e valida issuer e audience conforme configuração em appsettings.json.

Configuração Chave Local
Issuer Jwt:Issuer backend/Arah.Api/appsettings.json
Audience Jwt:Audience backend/Arah.Api/appsettings.json
SigningKey Jwt:SigningKey backend/Arah.Api/appsettings.json

Autenticação de Dois Fatores (2FA)

A API suporta autenticação de dois fatores usando TOTP (Time-based One-Time Password). Usuários podem configurar 2FA via POST /api/v1/auth/2fa/setup e confirmar via POST /api/v1/auth/2fa/confirm. Recovery codes são fornecidos durante a configuração.

  • Setup: POST /api/v1/auth/2fa/setup - Gera secret e QR code
  • Confirm: POST /api/v1/auth/2fa/confirm - Habilita 2FA após validar código
  • Verify: POST /api/v1/auth/2fa/verify - Verifica código TOTP e retorna JWT
  • Recover: POST /api/v1/auth/2fa/recover - Usa recovery code para autenticação
  • Disable: POST /api/v1/auth/2fa/disable - Desabilita 2FA (requer código válido)

Segurança

A API implementa várias camadas de segurança para proteger dados e operações críticas.

  • Sanitização de Inputs: HTML, paths, URLs e SQL são sanitizados
  • Proteção CSRF: Anti-forgery tokens configurados
  • Security Headers: CSP, HSTS, X-Frame-Options e outros headers de segurança
  • Rate Limiting: Proteção contra abuso e DDoS
  • Auditoria: Todas as ações críticas são registradas
Erro 401: token ausente, inválido, expirado ou com issuer/audience incorretos. Em geral, autorizações negadas retornam 401, mas a validação de membership sem morador validado retorna 403.
Contexto e headers

Território, sessão e geolocalização

Várias rotas aceitam o território via territoryId na query ou via sessão com X-Session-Id. Além disso, algumas operações exigem presença geográfica.

Header Uso Onde é obrigatório
X-Session-Id Seleciona território ativo da sessão. Feed, Mapa, Alerts, Assets, Marketplace, Events, Moderação quando territoryId não está na query.
X-Geo-Latitude / X-Geo-Longitude Comprova presença no território. Declaração de membership conforme policy.
PresencePolicy: a exigência de geolocalização para membership é configurada em PresencePolicy:Policy. O valor padrão atual é ResidentOnly.
OpenAPI

API Explorer (Swagger UI local)

O explorer usa a especificação real da API. Ele tenta carregar o Swagger dinâmico em /swagger/v1/swagger.json (quando o backend roda em Development) e usa fallback para ../openapi.json. A navegação é feita por tags, endpoints e schemas.

Baixar OpenAPI (JSON)

Explorer pronto para carregar.

Erros & convenções

Como interpretar respostas

Formato de erro

Erros de validação costumam retornar {"error": "mensagem"}. Exceções não tratadas retornam ProblemDetails com title, status, detail, traceId e path.

Códigos comuns

  • 400 dados inválidos ou headers obrigatórios ausentes.
  • 401 token ausente/ inválido ou falta de permissão.
  • 404 recurso inexistente (territory, post, user).
  • 409 não usado atualmente.
  • 500 exceções não tratadas (ProblemDetails).
Status da API: GET /liveness responde {"status": "ok"} e GET /readiness responde {"status": "ready"}. Logs seguem a configuração padrão de Logging no appsettings.json.
Onboarding Técnico

Onboarding para Analistas Funcionais - Guia Técnico Detalhado

Este guia técnico fornece um passo a passo detalhado para analistas funcionais começarem a trabalhar com o Arah, desde a configuração inicial até a análise funcional prática usando a API.

Passo 1: Configuração Inicial do Ambiente

O que você precisa:

  • Navegador web com suporte a JavaScript (Chrome, Firefox, Edge, Safari)
  • Ferramenta para testar API: Postman, Insomnia, ou curl (linha de comando)
  • Acesso à API Arah: URL base da API (ex: http://localhost:8080 ou URL de produção)
  • Conta de usuário: CPF ou documento estrangeiro para autenticação

Configuração (5 minutos):

  1. Instale ferramenta de teste de API: Baixe Postman (https://www.postman.com/downloads/) ou use curl
  2. Configure ambiente: Anote a URL da API e prepare dados de autenticação (CPF, nome, email)
  3. Verifique acesso: Teste se consegue acessar a URL base da API no navegador

Passo 2: Autenticação Social (Primeiro Acesso)

O que acontece: Você obtém um token JWT que permite acesso à API.

Endpoint: POST /api/v1/auth/social

curl -X POST http://localhost:8080/api/v1/auth/social \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "google",
    "externalId": "seu-id-unico",
    "displayName": "Seu Nome",
    "cpf": "12345678900",
    "email": "seu@email.com"
  }'

Resposta esperada:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresAt": "2025-01-21T10:00:00Z"
}

Próximo passo: Guarde o token. Você vai usar ele em todas as requisições autenticadas.

Importante: O token expira após um período (verifique expiresAt). Se receber erro 401, você precisa autenticar novamente.

Passo 3: Descobrir Territórios Disponíveis

O que acontece: Você lista todos os territórios disponíveis na plataforma para escolher qual analisar.

Endpoint: GET /api/v1/territories

curl http://localhost:8080/api/v1/territories \
  -H "Authorization: Bearer <seu-token>"

Resposta esperada:

{
  "items": [
    {
      "id": "11111111-1111-1111-1111-111111111111",
      "name": "Sertão do Camburi",
      "description": "Território comunitário...",
      "latitude": -23.55,
      "longitude": -46.63
    }
  ]
}

Análise funcional:

  • Observe os dados retornados: Nome, descrição, localização geográfica
  • Pergunte-se: Esses dados são suficientes para identificar um território? Falta algo?
  • Documente observações: O que você observa que poderia melhorar?

Passo 4: Selecionar Território para Análise

O que acontece: Você define qual território vai analisar, facilitando requisições subsequentes.

Endpoint: POST /api/v1/territories/selection

curl -X POST http://localhost:8080/api/v1/territories/selection \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <seu-token>" \
  -H "X-Session-Id: sessao-analise-001" \
  -d '{
    "territoryId": "11111111-1111-1111-1111-111111111111"
  }'

Análise funcional:

  • Observe o fluxo: Você precisa de um X-Session-Id único para cada sessão de análise
  • Pergunte-se: Seria melhor não precisar disso? Como isso afeta a experiência?
  • Documente necessidades: O que facilitaria seu trabalho como analista?

Passo 5: Explorar Feed do Território

O que acontece: Você vê o conteúdo publicado no feed do território selecionado.

Endpoint: GET /api/v1/feed

curl http://localhost:8080/api/v1/feed \
  -H "Authorization: Bearer <seu-token>" \
  -H "X-Session-Id: sessao-analise-001"

Resposta esperada:

{
  "items": [
    {
      "id": "...",
      "title": "Mutirão de limpeza",
      "content": "Encontro sábado 9h...",
      "type": "General",
      "visibility": "Public",
      "authorName": "Ana Silva",
      "createdAtUtc": "2025-01-20T10:00:00Z"
    }
  ],
  "pagination": {
    "pageNumber": 1,
    "pageSize": 20,
    "totalCount": 45,
    "totalPages": 3
  }
}

Análise funcional - exercício prático:

  1. Observe os tipos de conteúdo: Quais tipos existem? (General, AlertPost, etc.)
  2. Analise visibilidade: O que significa Public vs ResidentsOnly?
  3. Identifique necessidades: Que filtros seriam úteis? (por tipo, por data, por autor)
  4. Documente proposta: Escreva uma proposta de melhoria baseada na observação

Passo 6: Analisar Marketplace do Território

O que acontece: Você explora produtos e serviços disponíveis no marketplace territorial.

Endpoint: GET /api/v1/items

curl "http://localhost:8080/api/v1/items?territoryId=11111111-1111-1111-1111-111111111111&q=bolo&category=Alimentos" \
  -H "Authorization: Bearer <seu-token>"

Análise funcional - exercício prático:

  1. Teste diferentes buscas: Por nome (q=bolo), por categoria (category=Alimentos)
  2. Observe resultados: As buscas são eficientes? Retornam resultados relevantes?
  3. Identifique necessidades: Que filtros faltam? (preço, localização, disponibilidade)
  4. Documente observações: O que você observa que poderia melhorar?

Passo 7: Propor Melhoria Funcional (Criar Issue no GitHub)

O que fazer: Após observar e analisar, documente suas observações e propostas.

Template de Issue (GitHub):

## Análise Funcional: [Nome da Funcionalidade Proposta]

### Contexto Territorial
- **Território observado**: [Nome]
- **Necessidade identificada**: [Descrição clara]

### Análise Técnica (via API)
- **Endpoint testado**: `GET /api/v1/...`
- **Comportamento atual**: [O que observou]
- **Limitações identificadas**: [O que falta]

### Proposta Funcional
- **O que faria**: [Descrição clara]
- **Como funcionaria**: [Fluxo de uso]
- **Regras de negócio**: [Quem pode fazer o quê]

### Benefícios
- Para o território: [Benefício territorial]
- Para a comunidade: [Benefício comunitário]

### Evidências Técnicas
[Exemplos de requisições/respostas da API que suportam a proposta]
Próximos Passos para Analistas Funcionais:
  • Continue explorando a API: Teste outros endpoints (/api/v1/events, /api/v1/map/entities)
  • Documente observações: Crie um documento com suas análises e propostas
  • Valide com comunidade: Converse com pessoas do território sobre necessidades observadas
  • Crie Issues no GitHub: Transforme observações em propostas concretas
  • Participe de Discussions: Debata propostas com desenvolvedores e outros analistas
Onboarding Técnico

Onboarding para Desenvolvedores - Guia Técnico Detalhado

Este guia técnico fornece um passo a passo detalhado para desenvolvedores configurarem o ambiente de desenvolvimento e começarem a contribuir com código no Arah.

Passo 1: Verificar Requisitos do Sistema

Requisitos obrigatórios:

Componente Versão Mínima Como Verificar
Sistema Operacional Windows 10/11, macOS 10.15+, Linux (Ubuntu 20.04+) systeminfo (Windows) ou uname -a (Linux/macOS)
.NET SDK 8.0 ou superior dotnet --version (deve mostrar 8.0.x)
Git 2.30 ou superior git --version
Memória RAM Mínimo 4GB (recomendado 8GB+) Verificar nas configurações do sistema

Se algum requisito faltar:

Passo 2: Clonar o Repositório

O que acontece: Você baixa todo o código fonte do projeto para sua máquina local.

# Clone o repositório
git clone https://github.com/sraphaz/araponga.git

# Entre na pasta do projeto
cd araponga

Verificação:

# Verifique que os arquivos foram baixados
ls backend/
# Deve mostrar: Arah.Api, Arah.Application, Arah.Domain, etc.

Estrutura do projeto:

  • backend/: Código fonte C# (.NET) organizado em camadas (Clean Architecture)
  • docs/: Documentação do projeto (visão, roadmap, API, etc.)
  • frontend/: Código frontend (Wiki e DevPortal)
  • .cursorrules: Regras e padrões do projeto (Cursor lê automaticamente)

Passo 3: Restaurar Dependências

O que acontece: O .NET baixa todas as bibliotecas (pacotes NuGet) necessárias para o projeto compilar e rodar.

# Restaura pacotes NuGet
dotnet restore

O que você vai ver:

Determining projects to restore...
Restored backend/Arah.Domain/Arah.Domain.csproj
Restored backend/Arah.Application/Arah.Application.csproj
...
Restore succeeded.

Tempo estimado: 2-5 minutos na primeira vez (depende da velocidade da internet).

Se houver erros: Verifique sua conexão com internet e se o .NET SDK 8.0 está instalado corretamente.

Passo 4: Compilar o Projeto

O que acontece: O .NET compila todo o código C# para verificar se está tudo correto e pronto para executar.

# Compila o projeto
dotnet build

Resultado esperado:

Build succeeded.
    0 Warning(s)
    0 Error(s)
Time Elapsed 00:01:23

Se houver erros de compilação:

  • Verifique se o .NET SDK 8.0 está instalado: dotnet --version
  • Verifique se todas as dependências foram restauradas: dotnet restore novamente
  • Verifique se há conflitos de versão: procure por mensagens de erro específicas

Passo 5: Executar Testes Automatizados

O que acontece: Todos os testes automatizados são executados para garantir que o código está funcionando corretamente.

# Executa todos os testes
dotnet test

Resultado esperado:

Passed!  - Failed:     0, Passed:   245, Skipped:     0
Total:   245
Duration: 00:02:15

Se alguns testes falharem:

  • Não se preocupe imediatamente: Pode ser configuração específica do seu ambiente
  • Verifique mensagens de erro: Leia a saída do teste para entender o problema
  • Teste em modo verbose: dotnet test --verbosity detailed para mais informações
  • Verifique dependências externas: Alguns testes podem precisar de banco de dados ou serviços externos
Cobertura de testes: O projeto mantém cobertura acima de 90%. Novos códigos devem incluir testes.

Passo 6: Executar a API Localmente

O que acontece: Você inicia o servidor da API localmente para testar e desenvolver.

# Configurar ambiente de desenvolvimento
export ASPNETCORE_ENVIRONMENT=Development  # Linux/macOS
# OU
$env:ASPNETCORE_ENVIRONMENT="Development"  # Windows PowerShell

# Executar a API
dotnet run --project backend/Arah.Api --urls http://localhost:8080

O que você vai ver:

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:8080
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.

Testar a API:

# Em outro terminal, teste se a API está respondendo
curl http://localhost:8080/api/v1/territories

# Ou abra no navegador:
# http://localhost:8080

Para parar a API: Pressione Ctrl+C no terminal onde está rodando.

Passo 7: Abrir o Projeto no Cursor (Recomendado)

O que é o Cursor: Editor de código com IA que entende o contexto do projeto e ajuda você a programar seguindo os padrões.

Instalar Cursor:

Abrir projeto no Cursor:

  1. Abra o Cursor
  2. File > Open Folder (ou Ctrl+K Ctrl+O no Windows/Linux, Cmd+K Cmd+O no macOS)
  3. Selecione a pasta araponga que você clonou
  4. Pronto! O Cursor automaticamente:
    • Lê o arquivo .cursorrules com todas as regras do projeto
    • Configura o ambiente de desenvolvimento
    • Prepara autocompletar e sugestões baseadas no projeto
Como o Cursor te ajuda:
  • Entender código: Pergunte "Como funciona a criação de posts?" e o Cursor explica
  • Criar código novo: Descreva o que quer ("Criar endpoint para listar eventos") e o Cursor gera seguindo padrões
  • Validar código: Peça "Este código segue Clean Architecture?" e o Cursor valida
  • Aprender padrões: O Cursor aplica automaticamente as regras do .cursorrules

Passo 8: Entender a Estrutura do Código (Clean Architecture)

Organização em camadas:

backend/
├── Arah.Domain/          # Camada mais interna (não depende de nada)
│   └── Entidades, Value Objects, Interfaces de Repositórios
│
├── Arah.Application/     # Camada de lógica de negócio
│   └── Services, Use Cases, DTOs de Aplicação
│
├── Arah.Infrastructure/  # Camada de infraestrutura
│   └── Implementações de Repositórios, Storage, External Services
│
├── Arah.Api/             # Camada mais externa (HTTP, Controllers)
│   └── Controllers, Middlewares, Configurações de API
│
└── Arah.Tests/           # Testes automatizados
    └── Testes unitários, integração, E2E

Regra fundamental: Dependências apontam para dentro (Domain não depende de nada, Application depende apenas de Domain, etc.).

Exemplo prático - Criação de Posts:

  1. Controller (Arah.Api/Controllers/FeedController.cs) recebe requisição HTTP
  2. Controller chama Service (Arah.Application/Services/PostCreationService.cs)
  3. Service usa Entidades (Arah.Domain/Feed/CommunityPost.cs) para criar post
  4. Service usa Repository Interface (IPostRepository) para salvar
  5. Repository Implementation (Arah.Infrastructure/Postgres/PostgresPostRepository.cs) salva no banco

Passo 9: Primeira Contribuição - Exemplo Prático

Exercício sugerido: Melhorar mensagem de erro em um endpoint.

Passo a passo:

  1. Escolha um endpoint: Ex: GET /api/v1/feed (listar posts do feed)
  2. Encontre o Controller: backend/Arah.Api/Controllers/FeedController.cs
  3. Encontre o Service: backend/Arah.Application/Services/FeedService.cs
  4. Analise o código: Pergunte ao Cursor "Como funciona a listagem de posts?"
  5. Identifique melhoria: Ex: Mensagem de erro quando não há posts poderia ser mais clara
  6. Implemente a mudança: Use o Cursor para fazer a alteração seguindo padrões
  7. Adicione teste: Crie teste que valida a nova mensagem de erro
  8. Valide build e testes:
    dotnet build
    dotnet test
  9. Crie Pull Request: Siga o template em .github/pull_request_template.md
Recursos de Aprendizado para Desenvolvedores:
  • Documentação técnica: docs/60_API_LÓGICA_NEGÓCIO.md - Como as funcionalidades funcionam
  • Modelo de domínio: docs/12_DOMAIN_MODEL.md - Entidades e relacionamentos
  • Padrões de código: .cursorrules - Regras que o Cursor aplica automaticamente
  • Arquitetura: docs/10_ARCHITECTURE_DECISIONS.md - Decisões arquiteturais (ADRs)
  • Guia de contribuição: docs/41_CONTRIBUTING.md - Como contribuir com código
Lembrete importante:
  • O Cursor lê automaticamente o .cursorrules e aplica padrões
  • Você não precisa saber tudo de uma vez - aprenda fazendo
  • Pequenas contribuições são bem-vindas - comece pequeno
  • Testes são obrigatórios para código novo - cobertura >90%
  • Documentação deve ser atualizada quando código muda