GhostPayMesh — Diagnóstico B2B Core
Prontidão Geral B2B
~40%
Core B2B · média de 3 dimensões
SDK Dart (gpm_pcl_core)
~58%
SDK externo · packages/gpm_pcl_core/
APIs B2B Backend
~43%
Endpoints externos · FastAPI · Railway
Fluxo Offline-first
~56%
PCL + PLC + Identity end-to-end
5 Bloqueadores Críticos para Venda B2B
- authenticate_by_key() órfão — API keys geradas mas NENHUMA rota as valida. Qualquer agente externo acessa /plc/create e /balance sem autenticação.
- MockSignatureAdapter no SDK — sign() retorna 'MOCK_SIG_POC_<len>' sem Ed25519 real. OfflineRiskValidator não chama verify(). PCL forjável offline.
- Multi-tenancy ausente — PromissoryToken sem b2b_customer_id. GET /balance/{owner_id} expõe saldo de qualquer conta sem autenticação.
- Webhooks outbound inexistentes — parceiro não recebe notificação de status. Só polling manual. GAP_ANALYSIS.md:123 confirma.
- Identity offline sem sync real — débito Hive local nunca sincroniza com payments/authorize. Saldo diverge do backend indefinidamente.
Três fluxos offline paralelos com nomenclatura sobreposta
- (A) PLC Mesh: protocolo criptográfico completo com ledger double-entry e fila offline no ghostpay_app.
- (B) PCL Comercial POS: gpm_commercial_pcl via QR entre ghostpay_app e ghostpay_pos_app — fluxo de loja.
- (C) Identity Wallet: débito Hive local SEM protocolo PCL/PLC e SEM sync de pagamento — ghostpay_identity_app não usa gpm_pcl_core.
SDK Dart — gpm_pcl_core
~58% médio
| Módulo | Pronto | Status | O que existe | Evidências | Gaps | Risco | Vendável | Próximo passo |
|---|---|---|---|---|---|---|---|---|
| Modelos PCL (payload, order, sync) | Funcional | PclCommercialPayload, OrderPayload, SyncBatch, SyncBatchItem | pcl_commercial_payload.dart, order_payload.dart, sync_batch.dart |
Sem payload customizado/extensível; sem fromJson em SyncBatch | Médio — campos fixos limitam extensão por parceiro | Com restrição | Adicionar extras Map<String,dynamic>; testar round-trip JSON | |
| Hash SHA-256 / CanonicalJson | Pronto | OrderHashCalculator, ReceiptHashCalculator, CanonicalJson | order_hash_calculator.dart, canonical_json.dart |
Sem teste de adulteração de campo individual; sem doc formal | Baixo — algoritmo determinístico e bem testado (4 testes) | Sim | Documentar estrutura canônica para integradores externos | |
| Assinatura Ed25519 | Mock / POC | Interface SignatureAdapter; MockSignatureAdapter (sign → 'MOCK_SIG_POC_<len>') | signature_adapter.dart:18-31 — verify() só checa prefixo string, sem crypto real |
Ed25519SignatureAdapter ausente; OfflineRiskValidator NÃO chama verify() | CRÍTICO — PCL forjável: qualquer string com prefixo mock passa na validação offline | Não | Implementar Ed25519SignatureAdapter; integrar verify() no OfflineRiskValidator | |
| Nonce / Replay Protection | Parcial — in-memory | NonceValidator (Set<String> in-memory), registerAndCheck, restoreFrom | nonce_validator.dart:10-27 |
In-memory puro — reinicialização limpa Set; integração com RiskValidator é manual | Médio — janela de replay entre restarts do app | Com restrição | Expor factory de nonce no SDK; clarificar contrato de persistência | |
| TTL / Expiração | Pronto | TtlValidator.isValid(), isExpired(), remaining(); parâmetro 'now' injetável | ttl_validator.dart:6-20 |
Sem constantes de TTL recomendadas no SDK; apps definem seus próprios valores | Baixo — lógica simples; suscetível a clock skew de dispositivo | Sim | Documentar responsabilidade do clock; adicionar constantes de TTL sugeridas | |
| Risco offline (limites/tx/dia) | Funcional — sem sig verify | OfflineRiskValidator, TerminalRiskConfig (R$500/tx, R$5.000/dia default) | offline_risk_validator.dart:26-124 |
NÃO verifica assinatura; dailyAccumulated passado externamente; sem limite por usuário | Médio — valida estrutura e limites mas não integridade criptográfica offline | Com restrição | Integrar verify() Ed25519; documentar modelo de limites para parceiros | |
| QR encode / decode | Funcional — JSON puro | PclQrEncoder.encodePcl/encodeOrder, PclQrDecoder.decode | pcl_qr_encoder.dart, pcl_qr_decoder.dart:27-42 |
Sem compressão/base64; sem chunking; sem teste de payloads grandes | Médio — ordens com muitos itens podem exceder capacidade QR v40 | Com restrição | Definir limite máximo de campos; avaliar zlib+base64 ou CBOR | |
| SyncBatch (offline→online) | Funcional — HTTP no app | SyncBatchBuilder.add(), build(); SyncBatch.toJson() | sync_batch_builder.dart:17-37 |
Sem fromJson; schema de resposta do servidor não definido no SDK | Baixo no SDK — parceiro precisa implementar o POST | Com restrição | Documentar schema de request/response para endpoint de sync | |
| Testes do SDK | 32 testes — gaps em crypto | 8 grupos: CanonicalJson, OrderHash, QR, TTL, Nonce, RiskValidator, SyncBatch, ReceiptHash | test/gpm_pcl_core_test.dart — 32 casos; execução isolada |
0 testes para SignatureAdapter; sem testes de adulteração | Médio — gaps específicos em segurança criptográfica | Com restrição | Adicionar testes de assinatura real, adulteração de hash, round-trip | |
| Documentação e empacotamento | Ausente | pubspec.yaml v0.1.0; dartdoc parcial em classes; comentários internos | publish_to: none em pubspec.yaml:4; 0 arquivos README/CHANGELOG |
Sem README, CHANGELOG, example/, analysis_options.yaml; não publicável no pub.dev | Alto — integrador externo não consegue usar sem orientação manual | Não | Criar README com quickstart, campos obrigatórios, exemplo mínimo |
APIs B2B Backend
~43% médio
| Módulo | Pronto | Status | O que existe | Evidências | Gaps | Risco | Vendável | Próximo passo |
|---|---|---|---|---|---|---|---|---|
| PLC — create, status, chain, cancel | Funcional / sem auth B2B | POST /plc/create, GET /plc/{id}/status, GET /plc/{id}/chain, POST /plc/{id}/cancel | routes/plc.py — sem Depends B2B; Idempotency-Key via Redis 300s |
Sem autenticação B2B; sem b2b_customer_id no modelo PromissoryToken | Alto — endpoint público; qualquer agente externo cria PLCs sem rastreio | Com restrição | Conectar authenticate_by_key() como Depends; gravar customer_id em cada PLC | |
| Transfer / Redeem | Funcional / sem auth B2B | POST /transfer (valida Ed25519), POST /redeem; idempotência habilitada | routes/transfer.py, routes/redemption.py |
Sem auth B2B; sem multi-tenancy; sem logging de customer_id | Médio — transfer já exige Ed25519, mas sem rastreio de parceiro | Com restrição | Auth B2B + log de customer_id por operação | |
| Balance / Ledger | Público / sem isolamento | GET /balance/{owner_id}, /transactions, /promises; POST /reconcile | routes/balance.py:73-77 — sem Depends; owner_id na URL expõe saldo de qualquer conta |
CRÍTICO: qualquer owner_id acessível sem auth; parceiro A lê dados do parceiro B | CRÍTICO — vazamento de dados de saldo/transações entre parceiros | Não | Exigir auth B2B; validar que owner_id pertence ao customer autenticado | |
| B2B Onboarding / Admin | Funcional | POST /b2b/signup, GET /b2b/status/{id}, GET /b2b/plans; admin: approve/suspend/block | routes/b2b.py |
GET /b2b/status/{id} público expõe metadados de credenciais; sem paginação | Médio — vaza metadados de credenciais sem auth | Com restrição | Proteger /b2b/status com auth; rate limit no signup público | |
| API Keys — Geração e revogação | Gerado / não enforced | create_credentials() → key_id + api_secret (SHA-256 hash); revoke_credential(); scopes definidos | b2b_service.py:218-268 — authenticate_by_key() implementado mas sem wiring em NENHUMA rota |
authenticate_by_key() órfão; scopes gravados mas nunca verificados em runtime | CRÍTICO — API keys existem no banco mas não protegem absolutamente nada | Não | Criar Depends(require_b2b_api_key) e aplicar nas rotas PLC/transfer/balance | |
| Multi-tenancy (isolamento de dados) | Não implementado | Modelo B2BCustomer, ApiCredential com customer_id; metering e audit no modelo | models/plc.py:14-41 — PromissoryToken SEM b2b_customer_id |
PLCs, transfers, balance sem tenant_id; parceiro A acessa dados do parceiro B | CRÍTICO — violação de privacidade entre parceiros para produto comercial | Não | Adicionar b2b_customer_id em PromissoryToken + migration Alembic | |
| Webhooks outbound para parceiros | Inexistente | Scopes incluem 'webhooks'; SDK Python define HMAC verify; Supabase Realtime para PLC | GAP_ANALYSIS.md:123 — 'Webhooks customizados por parceiro: ❌' |
Sem endpoint de registro de URL; sem dispatcher outbound; sem retry/backoff para parceiros | Alto — integração event-driven impossível; parceiro fica em polling | Não | POST /b2b/webhooks (registro URL) + dispatcher async + HMAC payload | |
| Rate limit por API key | Só por IP | Middleware rate_limit.py; /plc: 60/min, /transfer: 30/min, /redeem: 20/min | rate_limit.py:80-82 — key Redis = 'ratelimit:{prefix}:{ip}:{device_id}' |
Sem rate limit por API key; parceiros em IPs compartilhados afetam-se mutuamente | Médio — abuso de plano básico não rastreável | Não | Estender rate_limit.py para incluir api_key_id na key do Redis | |
| Sandbox self-service B2B | Global / sem self-service | ASAAS sandbox via key prefix; /api/v1/dev/* (requer DEV_SIM_SECRET) | config.py:244-255; dev_sandbox.py |
Sem sandbox por parceiro; parceiro não consegue testar sem suporte manual | Alto para venda — parceiro não valida integração sem nós | Não | Campo sandbox_mode em B2BCustomer + mock Asaas per-tenant | |
| OpenAPI e documentação técnica | Auto gerado / divergente | FastAPI /openapi.json; docs developers/ (getting-started, sdk-overview, transfer-signing) | test_security_hardening.py:264-269; docs/developers/ |
Divergência SDK vs backend; sem doc PCL comercial; sem Postman | Médio — integrador segue docs e encontra inconsistências no runtime | Com restrição | Sincronizar docs com implementação; publicar Postman; criar guia PCL comercial | |
| Idempotência | Implementado — header opcional | Idempotency-Key header; Redis NX EX 300s; fallback in-memory; X-Idempotency-Replayed | middleware/idempotency.py:18-81 — cobre /plc/create, /transfer, /redeem |
Header opcional — sem key cada POST processa novamente; TTL curto (300s) | Baixo quando usado; parceiro precisa saber implementar | Sim | Considerar Idempotency-Key obrigatório para parceiros B2B | |
| Audit / metering por parceiro | Admin only | AuditLog (B2B_SIGNUP, CREDENTIAL_CREATED); UsageMetering (PLCs/mês) no modelo | b2b_service.py:27-42 — check_plc_limit() e increment_metering() NUNCA chamados nas rotas |
Parceiro não acessa seus logs; metering não enforced; sem GET /b2b/me/usage | Médio — billing difícil sem metering; compliance sem auditoria do parceiro | Não | GET /b2b/me/usage + GET /b2b/me/audit; enforçar increment_metering() no plc_service |
Fluxo Offline-first end-to-end
~56% médio
| Módulo | Pronto | Status | O que existe | Evidências | Gaps | Risco | Vendável | Próximo passo |
|---|---|---|---|---|---|---|---|---|
| PCL comercial — Geração (ghostpay_app) | Funcional / app interno | ConfirmPclScreen._signAndConfirm(); PclCommercialPayload + CanonicalJson + GhostCrypto | ghostpay_app/.../confirm_pcl_screen.dart:57-106 |
Lógica acoplada ao app interno; sem factory no SDK; chave privada em Hive local | Alto — parceiro precisa reimplementar ou usar app interno | Com restrição | Mover _signAndConfirm() para PclFactory no gpm_pcl_core | |
| PCL comercial — Assinatura Ed25519 real | Real no app / mock no SDK | GhostCrypto.sign() real (ed25519_edwards) no ghostpay_app; MockSignatureAdapter no SDK | ghostpay_app/.../ghost_crypto.dart:37-44 |
Ed25519SignatureAdapter ausente no SDK; parceiro não assina sem usar internals do ghostpay_app | Alto — sem implementação oficial de assinatura no SDK público | Não | Implementar Ed25519SignatureAdapter no gpm_pcl_core | |
| PCL comercial — Validação offline (POS) | Funcional — sem sig verify | ScanPclScreen + OfflineRiskValidator + NonceValidator; PosLocalDb (Hive) | ghostpay_pos_app/.../scan_pcl_screen.dart:38-132 |
verify() Ed25519 não chamado no OfflineRiskValidator; validação acoplada ao app POS | Médio — valida estrutura e limites; NÃO valida integridade criptográfica offline | Com restrição | Integrar verify() no OfflineRiskValidator; doc para parceiros criarem validador próprio | |
| PCL comercial — Sync offline→online | Funcional / endpoint POS | SyncBatchBuilder.build() → PosApiClient.syncBatch() → POST /api/v1/pos/sync | pos_api_client.dart:58-68, 141-163 |
Endpoint /pos/sync é merchant SaaS; parceiro externo sem terminal cadastrado não tem acesso | Alto — sync depende de contexto POS interno (merchantId, terminalId) | Com restrição | Criar POST /api/v1/b2b/sync-batch independente de contexto POS interno | |
| PCL comercial — Validação backend | Implementado — registro manual | _verify_ed25519_signature() em pos.py:162-203; verifica KeyBackup.public_key vs device_id | routes/pos.py:162-203 |
Exige public_key registrada via POST /security/key/backup ANTES do sync; sem automação | Médio — onboarding de dispositivo B2B sem fluxo self-service | Com restrição | Criar fluxo self-service de registro de chave pública por parceiro B2B | |
| PLC Mesh — Protocolo completo | Funcional / sem tenant | create/transfer/redeem/cancel; ledger double-entry; fila offline (OutboxQueue, SyncService) | routes/plc.py; services/plc_service.py; .../sync_service.dart |
Sem auth B2B; sem isolamento por parceiro; notificação via Supabase Realtime (não webhook) | Médio — protocolo sólido mas sem camada enterprise B2B | Com restrição | Adicionar auth B2B e b2b_customer_id nos endpoints PLC | |
| Identity — Pagamento offline | GAP crítico — sem sync | Débito local Hive (PinValidationScreen._pay); offlinePaymentLimitCents=5000 | pin_validation_screen.dart:220-241 |
Pagamentos offline NÃO têm fila de replay; http_ledger chama HTTP imediato; saldo diverge | CRÍTICO — inconsistência de saldo; pagamento sem registro no backend | Não | Implementar OfflinePaymentQueue + replay em IdentitySyncService | |
| Transporte BLE / NFC | Apenas QR funcional | Enum BLE, NFC, MESH, QR, KEY no backend; NFC só para UID no Identity | nfc_service.dart — 'bloqueado para pagamento'; 0 código BLE no SDK |
BLE/NFC para transporte de PCL/PLC NÃO implementado; material marketing pode mencionar BLE | Alto — promessa de marketing sem implementação real | Não | Alinhar material de marketing; roadmap BLE explícito com data |
Respostas Finais — 12 Perguntas
1
Possui SDK real hoje?
Parcial
gpm_pcl_core v0.1.0 existe com modelos, hash, TTL, nonce, QR. Assinatura é mock. Sem README.
publish_to: none.
2
SDK desacoplado ou preso ao app?
Parcial
SDK Dart desacoplado (zero imports internos). Porém geração + assinatura real da PCL está no ghostpay_app (ConfirmPclScreen), não no SDK.
3
Empresa consegue integrar sozinha?
Não / Crítico
Não. Sem README, sem Ed25519 real no SDK, sem auth B2B enforced, sem sandbox self-service, sem webhooks. Inviável sem suporte.
4
Empresa consegue integrar com suporte?
Parcial
Sim, com suporte intensivo. Python SDK para PLC mesh funciona. PCL comercial exige orientação manual. Estimativa: 2–4 semanas.
5
Core offline/PCL é vendável hoje?
Parcial
PCL comercial: piloto assistido (55%). PLC mesh: com suporte (55–60%). Identity offline: não vendável (15%).
6
As APIs são vendáveis hoje?
Não / Crítico
Não. Endpoints PLC/balance públicos sem auth. API keys geradas mas não enforced. Multi-tenancy ausente. Webhooks inexistentes.
7
Percentual do Core técnico?
~62%
Protocolo PLC sólido, hash, ledger double-entry, Ed25519 em transfers, sync batch. Gaps: mock offline, sem tenancy, Identity incompleto.
8
Percentual do SDK externo?
~35%
Modelos, hash, TTL, nonce, QR funcionam. Sem Ed25519 real, sem README, sem pub.dev, assinatura acoplada ao app.
9
Percentual das APIs externas?
~30%
Endpoints existem internamente. Sem auth B2B enforced, sem multi-tenancy, sem webhooks, sem sandbox por parceiro.
10
Prontidão comercial B2B Core?
~40%
Produto demonstrável mas sem empacotamento comercial: sem auth, sem sandbox, sem webhooks, docs divergentes.
11
7 dias para piloto B2B?
Plano
1) Conectar authenticate_by_key() nas rotas PLC/transfer/balance. 2) Implementar Ed25519SignatureAdapter. 3) README mínimo do SDK. 4) Provisionar parceiro piloto manualmente com credencial + KeyBackup.
12
30 dias para SDK/API vendável?
Plano
1) Webhooks outbound. 2) Sandbox self-service. 3) Rate limit por API key. 4) /b2b/me/usage + audit. 5) Multi-tenancy PLC. 6) Docs + Postman. 7) Remover mock de assinatura.
Planos de Ação
7 dias — Piloto B2B assistido
1
Conectar
authenticate_by_key() como Depends nas rotas /plc, /transfer, /balance2
Implementar
Ed25519SignatureAdapter no gpm_pcl_core (~30 linhas usando ed25519_edwards)3
Adicionar
b2b_customer_id em PromissoryToken + migration Alembic4
Criar README mínimo do gpm_pcl_core (quickstart + campos obrigatórios + exemplo)
5
Provisionar parceiro piloto manualmente: B2BCustomer → approve → credencial → KeyBackup
30 dias — SDK/API vendável
1
Webhooks outbound: POST /b2b/webhooks + dispatcher async + HMAC payload
2
Sandbox self-service: sandbox_mode em B2BCustomer + mock Asaas per-tenant
3
Rate limit por api_key_id no Redis (extensão simples do middleware)
4
GET /b2b/me/usage + GET /b2b/me/audit (endpoints do próprio parceiro)
5
Mover PclFactory para gpm_pcl_core; enforçar increment_metering() no plc_service
6
README completo + Postman collection + guia PCL comercial em docs/developers/
7
Remover MockSignatureAdapter de caminhos de produção
8
Sync de pagamento offline no IdentitySyncService (OfflinePaymentQueue + replay)