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.
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.
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.
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.
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}comreason(obrigatório) edetails(opcional). - Reportar usuário:
POST /api/v1/reports/users/{userId}(pode receberterritoryId). - 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}.
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"]
}'
- Upload de mídia: Primeiro, faça upload via
POST /api/v1/media/uploadpara obter omediaId(aceita imagens JPEG/PNG/WebP, vídeos MP4 e áudios MP3/WAV/OGG) - Associar ao item: Inclua os
mediaIdsno 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
ItemResponseincluiprimaryImageUrleimageUrls(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
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
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:
- Checkout pago → Sistema cria
SellerTransactionautomaticamente - Valor líquido → Subtotal - Fees da plataforma = Valor para o vendedor
- Período de retenção → Aguarda dias configurados (ex: 7 dias)
- Valor mínimo → Acumula até atingir valor mínimo configurado (ex: R$ 100,00)
- Payout automático → Background worker processa quando todas as condições são atendidas
- 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"
}'
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: Setrue, processa payouts automaticamente. Sefalse, apenas manualrequiresApproval: Setrue, 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>"
pendingAmountInCents: Valor que ainda está no período de retençãoreadyForPayoutAmountInCents: 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
- Migration aplicada: Execute a migration
20260119000000_AddFinancialSystem.csno banco de dados - Gateway de pagamento configurado: Tenha uma conta no gateway (Stripe Connect, MercadoPago, etc.)
- Background worker ativo: Certifique-se de que o
PayoutProcessingWorkerestá rodando
⚙️ Configuração Inicial
- Configure payout por território: Use
POST /api/v1/territories/{territoryId}/payout-config - Configure período de retenção: Recomendado: 7-14 dias (protege contra chargebacks)
- Configure valor mínimo: Recomendado: R$ 50,00 - R$ 200,00 (reduz custos de transferência)
- Configure valor máximo: Se necessário, limite por payout (ex: R$ 50.000,00)
- Escolha frequência:
"Daily"(diário),"Weekly"(semanal) ou"Monthly"(mensal) - Habilite payout automático: Defina
autoPayoutEnabled: true
🔌 Integração com Gateway de Pagamento
- Implemente IPayoutGateway: Crie implementação para seu gateway (Stripe, MercadoPago, etc.)
- Registre no DI: Substitua
MockPayoutGatewaypor sua implementação real emServiceCollectionExtensions.cs - Configure credenciais: Adicione chaves de API do gateway em
appsettings.jsonou variáveis de ambiente - Teste em sandbox: Use ambiente de testes do gateway antes de produção
🧪 Testes e Validação
- Teste checkout completo: Crie checkout, marque como
Paide verifique seSellerTransactionfoi criada - Verifique retenção: Confirme que o valor fica em
pendingAmountInCentsdurante o período de retenção - Teste valor mínimo: Crie múltiplos checkouts pequenos e confirme que só processa quando atinge o mínimo
- Verifique payout automático: Aguarde o background worker processar e verifique transferência no gateway
- Monitore logs: Verifique logs do
PayoutProcessingWorkerpara 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.).
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
PayoutProcessingWorkernos logs para ver processamento - Transações Financeiras: Consulte
GET /api/v1/territories/{territoryId}/platform-financial/revenuepara receitas - Transações de Despesa: Consulte
GET /api/v1/territories/{territoryId}/platform-financial/expensespara payouts - Status de Payouts: Use
UpdatePayoutStatusAsyncpara atualizar status do gateway periodicamente
🎯 Casos de Uso Comuns
- Vendedor quer saber quando receberá: Consulte
/seller-balance/mepara ver valores pendentes e prontos para payout - Processar payout manualmente: Use
ProcessPendingPayoutsAsyncdoSellerPayoutServicevia API admin - Ver histórico de transações: Consulte
/seller-balance/me/transactionspara ver todas as transações do vendedor - Auditar receitas da plataforma: Use endpoints de
/platform-financialpara 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
Para detalhes técnicos completos, consulte: docs/backlog-api/FASE7.md
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"]
}'
- Upload de mídia: Primeiro, faça upload via
POST /api/v1/media/uploadpara obter omediaId(aceita imagens JPEG/PNG/WebP, vídeos MP4 e áudios MP3/WAV/OGG) - Mídia de capa: Use
coverMediaIdpara 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
additionalMediaIdspara 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
EventResponseincluicoverImageUrleadditionalImageUrls(pode conter URLs de vídeos e áudios) - Validação: Todas as mídias devem pertencer ao usuário e
coverMediaIdnão pode estar emadditionalMediaIds. 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>"
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"
}'
⚙️ 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.
- 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
}
}'
- 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
- Documentação da Fase 10: docs/backlog-api/FASE10.md
- Configuração de Storage: docs/backlog-api/FASE10_STORAGE_CONFIG_ADMIN.md
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
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
Marketplace Checkout
Fluxo completo de marketplace: criar loja, adicionar itens, gerenciar carrinho, fazer checkout e processar payout.
Fluxo Completo
- Criar loja:
POST /api/v1/stores - Adicionar itens:
POST /api/v1/items - Adicionar ao carrinho:
POST /api/v1/cart/items - Checkout:
POST /api/v1/cart/checkout - Marcar como pago:
PATCH /api/v1/cart/checkout/{id}/status(Status: Paid) - Payout automático: Sistema processa payout conforme configuração
Diagrama de Sequência
📊 Ver Diagrama de Sequência
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.
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.
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.
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.
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.
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.
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.
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.
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.
Fases 20, 23-24: Moeda territorial, compra coletiva e trocas comunitárias. Economia circular e autonomia financeira territorial fortalecendo redes locais.
Fases 12, 15: Otimizações finais e inteligência artificial integrada. Performance e capacidades avançadas mantendo os princípios do projeto.
Fases 16, 19, 21-22: Entregas territoriais, arquitetura modular, suporte a criptomoedas e integrações externas. Flexibilidade arquitetural mantendo autonomia.
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.
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.
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.
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.
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.
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.
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\"}"
backend/Arah.Api/wwwroot/devportal (HTML/CSS/JS/OpenAPI). O deploy do GitHub Pages publica exatamente essa pasta.
Entidades principais e relacionamentos
🧭 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
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
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
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
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"]
}'
- Upload de mídia: Primeiro, faça upload via
POST /api/v1/media/uploadpara obter omediaId(aceita imagens JPEG/PNG/WebP, vídeos MP4 e áudios MP3/WAV/OGG) - Associar ao post: Inclua os
mediaIdsno 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
FeedItemResponseincluimediaUrls(array de URLs de imagens, vídeos e áudios) emediaCount - 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
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
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
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
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
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
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
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
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"
}'
- Upload de mídia: Use
POST /api/v1/media/uploadpara 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
mediaIdno 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
MessageResponseincluimediaUrlehasMedia - 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
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.
- Autenticar:
POST /api/v1/auth/social(obtém JWT) - Descobrir território:
GET /api/v1/territories/nearby?lat=-23.55&lng=-46.63 - Selecionar território:
POST /api/v1/territories/selection+ headerX-Session-Id - Declarar vínculo:
POST /api/v1/memberships/{territoryId}/enter-visitor - 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.
- Upload de mídias:
POST /api/v1/media/upload(obtémmediaIds) - Criar post:
POST /api/v1/feedcommediaIds(até 10 imagens) - GeoAnchors automáticos: derivados de mídias quando disponíveis
- Visualizar no mapa:
GET /api/v1/map/pins?types=post - Ver no feed:
GET /api/v1/feed/paged
🗺️ Assets territoriais com geolocalização
Recursos territoriais (rios, trilhas, nascentes) sempre com geolocalização obrigatória.
- Criar asset:
POST /api/v1/assets(geo obrigatória emgeoAnchors) - Tipos disponíveis:
river,trail,spring,lookout,sanctuary - Apenas moradores verificados ou curadores: podem criar/editar/arquivar
- 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.
- Criar conversa:
POST /api/v1/chat/conversations - Enviar mensagem:
POST /api/v1/chat/conversations/{id}/messages - Mensagem com imagem: incluir
mediaIdno payload - Listar conversas:
GET /api/v1/chat/conversations - 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.
- Criar loja:
POST /api/v1/stores - Adicionar itens:
POST /api/v1/itemscommediaIds(até 10 imagens) - Carrinho:
POST /api/v1/cart/items - Checkout:
POST /api/v1/cart/checkout - 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.
- Criar evento:
POST /api/v1/events(geo obrigatória) - Imagens:
coverMediaIdeadditionalMediaIds(até 10) - Marcar interesse:
POST /api/v1/events/{id}/interest - Confirmar presença:
POST /api/v1/events/{id}/confirm - 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
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:
- Checkout pago → Sistema cria
SellerTransactionautomaticamente - Valor líquido → Subtotal - Fees da plataforma = Valor para o vendedor
- Período de retenção → Aguarda dias configurados (ex: 7 dias)
- Valor mínimo → Acumula até atingir valor mínimo configurado (ex: R$ 100,00)
- Payout automático → Background worker processa quando todas as condições são atendidas
- 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"
}'
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: Setrue, processa payouts automaticamente. Sefalse, apenas manualrequiresApproval: Setrue, 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>"
pendingAmountInCents: Valor que ainda está no período de retençãoreadyForPayoutAmountInCents: 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
- Migration aplicada: Execute a migration
20260119000000_AddFinancialSystem.csno banco de dados - Gateway de pagamento configurado: Tenha uma conta no gateway (Stripe Connect, MercadoPago, etc.)
- Background worker ativo: Certifique-se de que o
PayoutProcessingWorkerestá rodando
⚙️ Configuração Inicial
- Configure payout por território: Use
POST /api/v1/territories/{territoryId}/payout-config - Configure período de retenção: Recomendado: 7-14 dias (protege contra chargebacks)
- Configure valor mínimo: Recomendado: R$ 50,00 - R$ 200,00 (reduz custos de transferência)
- Configure valor máximo: Se necessário, limite por payout (ex: R$ 50.000,00)
- Escolha frequência:
"Daily"(diário),"Weekly"(semanal) ou"Monthly"(mensal) - Habilite payout automático: Defina
autoPayoutEnabled: true
🔌 Integração com Gateway de Pagamento
- Implemente IPayoutGateway: Crie implementação para seu gateway (Stripe, MercadoPago, etc.)
- Registre no DI: Substitua
MockPayoutGatewaypor sua implementação real emServiceCollectionExtensions.cs - Configure credenciais: Adicione chaves de API do gateway em
appsettings.jsonou variáveis de ambiente - Teste em sandbox: Use ambiente de testes do gateway antes de produção
🧪 Testes e Validação
- Teste checkout completo: Crie checkout, marque como
Paide verifique seSellerTransactionfoi criada - Verifique retenção: Confirme que o valor fica em
pendingAmountInCentsdurante o período de retenção - Teste valor mínimo: Crie múltiplos checkouts pequenos e confirme que só processa quando atinge o mínimo
- Verifique payout automático: Aguarde o background worker processar e verifique transferência no gateway
- Monitore logs: Verifique logs do
PayoutProcessingWorkerpara 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.).
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
PayoutProcessingWorkernos logs para ver processamento - Transações Financeiras: Consulte
GET /api/v1/territories/{territoryId}/platform-financial/revenuepara receitas - Transações de Despesa: Consulte
GET /api/v1/territories/{territoryId}/platform-financial/expensespara payouts - Status de Payouts: Use
UpdatePayoutStatusAsyncpara atualizar status do gateway periodicamente
🎯 Casos de Uso Comuns
- Vendedor quer saber quando receberá: Consulte
/seller-balance/mepara ver valores pendentes e prontos para payout - Processar payout manualmente: Use
ProcessPendingPayoutsAsyncdoSellerPayoutServicevia API admin - Ver histórico de transações: Consulte
/seller-balance/me/transactionspara ver todas as transações do vendedor - Auditar receitas da plataforma: Use endpoints de
/platform-financialpara 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
Para detalhes técnicos completos, consulte: docs/backlog-api/FASE7.md
Onboarding Usuário
Primeira jornada: autenticação, descoberta de território e vínculo inicial.
Fluxo Completo
- Autenticar:
POST /api/v1/auth/social(obtém JWT) - Descobrir território:
GET /api/v1/territories/nearby?lat=-23.55&lng=-46.63 - Selecionar território:
POST /api/v1/territories/selection+ headerX-Session-Id - Declarar vínculo:
POST /api/v1/memberships/{territoryId}/enter-visitor - 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.
Fluxo Completo
- Upload de mídias:
POST /api/v1/media/upload(obtémmediaIds) - Criar post:
POST /api/v1/feedcommediaIds(até 10 imagens) - GeoAnchors automáticos: derivados de mídias quando disponíveis
- Visualizar no mapa:
GET /api/v1/map/pins?types=post - Ver no feed:
GET /api/v1/feed/paged
Assets territoriais com geolocalização
Recursos territoriais (rios, trilhas, nascentes) sempre com geolocalização obrigatória.
Fluxo Completo
- Criar asset:
POST /api/v1/assets(geo obrigatória emgeoAnchors) - Tipos disponíveis:
river,trail,spring,lookout,sanctuary - Apenas moradores verificados ou curadores: podem criar/editar/arquivar
- 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.
Fluxo Completo
- Criar conversa:
POST /api/v1/chat/conversations - Enviar mensagem:
POST /api/v1/chat/conversations/{id}/messages - Mensagem com imagem: incluir
mediaIdno payload - Listar conversas:
GET /api/v1/chat/conversations - 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.
Fluxo Completo
- Criar loja:
POST /api/v1/stores - Adicionar itens:
POST /api/v1/itemscommediaIds(até 10 imagens) - Carrinho:
POST /api/v1/cart/items - Checkout:
POST /api/v1/cart/checkout - 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.
Fluxo Completo
- Criar evento:
POST /api/v1/events(geo obrigatória) - Imagens:
coverMediaIdeadditionalMediaIds(até 10) - Marcar interesse:
POST /api/v1/events/{id}/interest - Confirmar presença:
POST /api/v1/events/{id}/confirm - Aparece no feed e mapa: eventos aparecem em ambos os contextos
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.
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.
Passo 1: Entendendo o Fluxo de Payout
Quando um cliente compra algo na loja de um vendedor e o pagamento é confirmado, o seguinte acontece:
- Checkout pago → Sistema cria
SellerTransactionautomaticamente - Valor líquido → Subtotal - Fees da plataforma = Valor para o vendedor
- Período de retenção → Aguarda dias configurados (ex: 7 dias)
- Valor mínimo → Acumula até atingir valor mínimo configurado (ex: R$ 100,00)
- Payout automático → Background worker processa quando todas as condições são atendidas
- 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.
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"
}'
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: Setrue, processa payouts automaticamente. Sefalse, apenas manualrequiresApproval: Setrue, 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:
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>"
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>"
pendingAmountInCents: Valor que ainda está no período de retençãoreadyForPayoutAmountInCents: Valor pronto para payout (após período de retenção e valor mínimo)paidAmountInCents: Valor já transferido para o vendedor
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
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:Policy. O valor padrão atual é ResidentOnly.
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.
Explorer pronto para carregar.
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).
GET /liveness responde {"status": "ok"} e
GET /readiness responde {"status": "ready"}. Logs seguem a configuração
padrão de Logging no appsettings.json.
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:8080ou URL de produção) - Conta de usuário: CPF ou documento estrangeiro para autenticação
Configuração (5 minutos):
- Instale ferramenta de teste de API: Baixe Postman (https://www.postman.com/downloads/) ou use curl
- Configure ambiente: Anote a URL da API e prepare dados de autenticação (CPF, nome, email)
- 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.
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:
- Observe os tipos de conteúdo: Quais tipos existem? (
General,AlertPost, etc.) - Analise visibilidade: O que significa
PublicvsResidentsOnly? - Identifique necessidades: Que filtros seriam úteis? (por tipo, por data, por autor)
- 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:
- Teste diferentes buscas: Por nome (
q=bolo), por categoria (category=Alimentos) - Observe resultados: As buscas são eficientes? Retornam resultados relevantes?
- Identifique necessidades: Que filtros faltam? (preço, localização, disponibilidade)
- 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]
- 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 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:
- .NET SDK 8.0: Baixe em https://dotnet.microsoft.com/download/dotnet/8.0 (escolha "SDK", não apenas Runtime)
- Git: Windows: https://git-scm.com/download/win | macOS:
brew install git| Linux:sudo apt install git
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).
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 restorenovamente - 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 detailedpara mais informações - Verifique dependências externas: Alguns testes podem precisar de banco de dados ou serviços externos
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:
- Baixe em https://cursor.sh/
- Instale normalmente (setup automático)
Abrir projeto no Cursor:
- Abra o Cursor
- File > Open Folder (ou
Ctrl+K Ctrl+Ono Windows/Linux,Cmd+K Cmd+Ono macOS) - Selecione a pasta
arapongaque você clonou - Pronto! O Cursor automaticamente:
- Lê o arquivo
.cursorrulescom todas as regras do projeto - Configura o ambiente de desenvolvimento
- Prepara autocompletar e sugestões baseadas no projeto
- Lê o arquivo
- 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:
- Controller (
Arah.Api/Controllers/FeedController.cs) recebe requisição HTTP - Controller chama Service (
Arah.Application/Services/PostCreationService.cs) - Service usa Entidades (
Arah.Domain/Feed/CommunityPost.cs) para criar post - Service usa Repository Interface (
IPostRepository) para salvar - 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:
- Escolha um endpoint: Ex:
GET /api/v1/feed(listar posts do feed) - Encontre o Controller:
backend/Arah.Api/Controllers/FeedController.cs - Encontre o Service:
backend/Arah.Application/Services/FeedService.cs - Analise o código: Pergunte ao Cursor "Como funciona a listagem de posts?"
- Identifique melhoria: Ex: Mensagem de erro quando não há posts poderia ser mais clara
- Implemente a mudança: Use o Cursor para fazer a alteração seguindo padrões
- Adicione teste: Crie teste que valida a nova mensagem de erro
- Valide build e testes:
dotnet build dotnet test - Crie Pull Request: Siga o template em
.github/pull_request_template.md
- 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
- O Cursor lê automaticamente o
.cursorrulese 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