@comando.one/mcp-server 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +806 -16
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -51,7 +51,7 @@ Ambos expõem o **mesmo conjunto de ferramentas** (50 curadas + `lookups` + `com
51
51
 
52
52
  ## Como funciona
53
53
 
54
- - **~50 tools curadas** (gerados a partir do OpenAPI canônico, zero drift) cobrindo as operações de maior valor — `customers_list`, `invoices_create`, `charges_create`, `nfse_emit`, `payouts_create`, etc.
54
+ - **126 tools curadas** (gerados a partir do OpenAPI canônico, zero drift) cobrindo as operações de maior valor — `customers_list`, `invoices_create`/`invoices_delete`, `charges_create`, `nfse_emit`, `payouts_create`, `contracts_pause`/`contracts_resume`, `service_categories_create`, `reports_aging_actions`/`reports_cashflow_forecast`, `audit_timeline`, `cost_centers_create`, etc.
55
55
  - **`comando_request`** — escape hatch genérico (`method`, `path`, `query`, `body`) que cobre 100% dos endpoints restantes.
56
56
  - **`lookups`** — catálogos read-only (centros de custo, condições/métodos de pagamento, naturezas, contas bancárias).
57
57
  - **`whoami`** — identidade, empresas acessíveis e scopes da chave.
package/dist/index.js CHANGED
@@ -180,7 +180,108 @@ var MANIFEST = [
180
180
  // ----- Webhooks -----
181
181
  { operationId: "listWebhooks", tool: "webhooks_list" },
182
182
  { operationId: "getWebhookById", tool: "webhooks_get" },
183
- { operationId: "createWebhook", tool: "webhooks_create", write: true }
183
+ { operationId: "createWebhook", tool: "webhooks_create", write: true },
184
+ // ----- Split de Pagamentos -----
185
+ { operationId: "listSplitRules", tool: "split_rules_list" },
186
+ { operationId: "getSplitRule", tool: "split_rules_get" },
187
+ { operationId: "createSplitRule", tool: "split_rules_create", write: true },
188
+ { operationId: "updateSplitRule", tool: "split_rules_update", write: true },
189
+ { operationId: "deleteSplitRule", tool: "split_rules_delete", write: true, destructive: true },
190
+ { operationId: "listSplitExecutions", tool: "split_executions_list" },
191
+ { operationId: "getSplitExecution", tool: "split_executions_get" },
192
+ { operationId: "reverseSplitExecution", tool: "split_reverse", write: true, destructive: true },
193
+ { operationId: "releaseSplitItem", tool: "split_release_item", write: true },
194
+ // Auditoria
195
+ { operationId: "getAuditTimeline", tool: "audit_timeline" },
196
+ // Categorias de serviço
197
+ { operationId: "listServiceCategories", tool: "service_categories_list" },
198
+ { operationId: "createServiceCategory", tool: "service_categories_create", write: true },
199
+ { operationId: "updateServiceCategory", tool: "service_categories_update", write: true },
200
+ { operationId: "deleteServiceCategory", tool: "service_categories_delete", write: true, destructive: true },
201
+ // Relatórios (read-only)
202
+ { operationId: "reportAgingActions", tool: "reports_aging_actions" },
203
+ { operationId: "reportCashflowForecast", tool: "reports_cashflow_forecast" },
204
+ // Contratos — pausar/retomar
205
+ { operationId: "pauseContract", tool: "contracts_pause", write: true },
206
+ { operationId: "resumeContract", tool: "contracts_resume", write: true },
207
+ // Reajustes de contrato (specs/reajustes/) — aplicar muda preço → destructive
208
+ { operationId: "listDueReadjustments", tool: "contracts_readjustments_due" },
209
+ { operationId: "listContractReadjustments", tool: "contracts_readjustments_list" },
210
+ { operationId: "applyContractReadjustment", tool: "contracts_readjustments_apply", write: true, destructive: true },
211
+ { operationId: "getMarketIndices", tool: "market_indices_get" },
212
+ // Faturas — exclusão física
213
+ { operationId: "deleteInvoice", tool: "invoices_delete", write: true, destructive: true },
214
+ // NFS-e — sincronizar status / baixar arquivos
215
+ { operationId: "syncNfse", tool: "nfse_sync", write: true },
216
+ { operationId: "getNfseFiles", tool: "nfse_files" },
217
+ // Centros de custo (CRUD)
218
+ { operationId: "listCostCenters", tool: "cost_centers_list" },
219
+ { operationId: "createCostCenter", tool: "cost_centers_create", write: true },
220
+ { operationId: "updateCostCenter", tool: "cost_centers_update", write: true },
221
+ { operationId: "deleteCostCenter", tool: "cost_centers_delete", write: true, destructive: true },
222
+ // Lembretes (CRUD)
223
+ { operationId: "listReminders", tool: "reminders_list" },
224
+ { operationId: "createReminder", tool: "reminders_create", write: true },
225
+ { operationId: "updateReminder", tool: "reminders_update", write: true },
226
+ { operationId: "deleteReminder", tool: "reminders_delete", write: true, destructive: true },
227
+ // ── Cobertura completa da API (2026-08-14) ──────────────────────────────
228
+ // 43 operações que já existiam na API pública e não tinham tool: um agente
229
+ // conseguia criar cliente mas não editar endereço, listar fatura mas não
230
+ // apagar despesa. Deriva do MANIFEST curado, não decisão de projeto.
231
+ // Flags seguem a convenção: mutação = write; remoção = write + destructive.
232
+ // Identidade e empresa
233
+ { operationId: "getMe", tool: "me_get" },
234
+ { operationId: "getCompany", tool: "companies_get" },
235
+ // Clientes — sub-recursos e edição
236
+ { operationId: "listCustomerAddresses", tool: "customers_list_addresses" },
237
+ { operationId: "updateCustomerAddress", tool: "customers_update_address", write: true },
238
+ { operationId: "deleteCustomerAddress", tool: "customers_delete_address", write: true, destructive: true },
239
+ { operationId: "listCustomerContacts", tool: "customers_list_contacts" },
240
+ { operationId: "updateCustomerContact", tool: "customers_update_contact", write: true },
241
+ { operationId: "deleteCustomerContact", tool: "customers_delete_contact", write: true, destructive: true },
242
+ { operationId: "listCustomerContracts", tool: "customers_list_contracts" },
243
+ { operationId: "listCustomerProposals", tool: "customers_list_proposals" },
244
+ // Propostas e contratos — edição e exclusão
245
+ { operationId: "updateProposal", tool: "proposals_update", write: true },
246
+ { operationId: "deleteProposal", tool: "proposals_delete", write: true, destructive: true },
247
+ { operationId: "updateContract", tool: "contracts_update", write: true },
248
+ { operationId: "deleteContract", tool: "contracts_delete", write: true, destructive: true },
249
+ // Fornecedores — edição e formas de pagamento
250
+ { operationId: "updateSupplier", tool: "suppliers_update", write: true },
251
+ { operationId: "deleteSupplier", tool: "suppliers_delete", write: true, destructive: true },
252
+ { operationId: "listSupplierPaymentMethods", tool: "suppliers_list_payment_methods" },
253
+ { operationId: "createSupplierPaymentMethod", tool: "suppliers_add_payment_method", write: true },
254
+ { operationId: "updateSupplierPaymentMethod", tool: "suppliers_update_payment_method", write: true },
255
+ { operationId: "deleteSupplierPaymentMethod", tool: "suppliers_delete_payment_method", write: true, destructive: true },
256
+ // Serviços
257
+ { operationId: "getService", tool: "services_get" },
258
+ { operationId: "updateService", tool: "services_update", write: true },
259
+ { operationId: "deleteService", tool: "services_delete", write: true, destructive: true },
260
+ { operationId: "listServiceUnits", tool: "service_units_list" },
261
+ // Despesas
262
+ { operationId: "getExpense", tool: "expenses_get" },
263
+ { operationId: "updateExpense", tool: "expenses_update", write: true },
264
+ { operationId: "deleteExpense", tool: "expenses_delete", write: true, destructive: true },
265
+ // Financeiro e contas bancárias
266
+ { operationId: "listFinancialNatures", tool: "finance_list_natures" },
267
+ { operationId: "deleteFinancialMovement", tool: "finance_delete_movement", write: true, destructive: true },
268
+ { operationId: "listBankAccounts", tool: "bank_accounts_list" },
269
+ { operationId: "getBankAccount", tool: "bank_accounts_get" },
270
+ // Dados de referência de pagamento
271
+ { operationId: "listPaymentConditions", tool: "payment_conditions_list" },
272
+ { operationId: "listPaymentMethods", tool: "payment_methods_list" },
273
+ { operationId: "listPaymentMethodsAp", tool: "payment_methods_ap_list" },
274
+ // Repasses
275
+ { operationId: "syncPayout", tool: "payouts_sync", write: true },
276
+ // Webhooks — edição, teste e entregas
277
+ { operationId: "updateWebhook", tool: "webhooks_update", write: true },
278
+ { operationId: "deleteWebhook", tool: "webhooks_delete", write: true, destructive: true },
279
+ { operationId: "getWebhook", tool: "webhooks_get_config" },
280
+ { operationId: "upsertWebhook", tool: "webhooks_upsert_config", write: true },
281
+ { operationId: "testWebhook", tool: "webhooks_test", write: true },
282
+ { operationId: "listWebhookDeliveries", tool: "webhooks_list_deliveries" },
283
+ { operationId: "listWebhookEvents", tool: "webhooks_list_events" },
284
+ { operationId: "redeliverWebhook", tool: "webhooks_redeliver", write: true }
184
285
  ];
185
286
 
186
287
  // ../../src/lib/openApiSpec.ts
@@ -230,7 +331,14 @@ var WEBHOOK_EVENT_KEYS = [
230
331
  "customer.deleted",
231
332
  "supplier.created",
232
333
  "supplier.updated",
233
- "supplier.deleted"
334
+ "supplier.deleted",
335
+ "split.calculated",
336
+ "repasse.released",
337
+ "repasse.paid",
338
+ "repasse.failed",
339
+ "repasse.reversed",
340
+ "supplier_payout_request.created",
341
+ "supplier_payout_request.approved"
234
342
  ];
235
343
  var SCHEMAS = {
236
344
  Error: {
@@ -406,6 +514,65 @@ var SCHEMAS = {
406
514
  notes: { type: "string" }
407
515
  }
408
516
  },
517
+ ContractReadjustment: {
518
+ type: "object",
519
+ description: "Reajuste aplicado a um contrato (specs/reajustes/).",
520
+ properties: {
521
+ id: { type: "string", format: "uuid" },
522
+ contract_id: { type: "string", format: "uuid" },
523
+ applied_at: { type: "string", format: "date-time" },
524
+ applied_by: { type: ["string", "null"], format: "uuid" },
525
+ period_start: { type: ["string", "null"], format: "date", description: "In\xEDcio do per\xEDodo coberto (\xFAltimo reajuste anterior)" },
526
+ period_end: { type: ["string", "null"], format: "date" },
527
+ previous_amount: { type: "number" },
528
+ new_amount: { type: "number" },
529
+ applied_percent: { type: "number", description: "Percentual efetivamente aplicado" },
530
+ suggested_percent: { type: ["number", "null"], description: "Sugest\xE3o do \xEDndice preferido no momento da aplica\xE7\xE3o" },
531
+ suggested_index: { type: ["string", "null"], enum: ["ipca", "igpm", "inpc", "usd", "eur", null] },
532
+ notes: { type: ["string", "null"] }
533
+ }
534
+ },
535
+ ContractReadjustmentCreate: {
536
+ type: "object",
537
+ description: "Informe 'new_amount' OU 'percent' \u2014 o outro \xE9 derivado do valor atual do contrato.",
538
+ properties: {
539
+ new_amount: { type: "number", description: "Novo valor do contrato (R$)" },
540
+ percent: { type: "number", description: "Percentual de reajuste (ex.: 4.62)" },
541
+ suggested_percent: { type: "number", description: "Sugest\xE3o exibida no momento (para o hist\xF3rico sugerido \xD7 aplicado)" },
542
+ suggested_index: { type: "string", enum: ["ipca", "igpm", "inpc", "usd", "eur"] },
543
+ notes: { type: "string" }
544
+ }
545
+ },
546
+ ContractReadjustmentQueueItem: {
547
+ type: "object",
548
+ description: "Contrato na fila de reajuste (vencido ou na janela).",
549
+ properties: {
550
+ id: { type: "string", format: "uuid" },
551
+ customer_id: { type: "string", format: "uuid" },
552
+ customers: { type: "object", properties: { name: { type: "string" } } },
553
+ title: { type: ["string", "null"] },
554
+ status: { type: "string" },
555
+ frequency: { type: "string" },
556
+ amount: { type: "number" },
557
+ readjustment_index: { type: "string", enum: ["ipca", "igpm", "inpc", "usd", "eur", "manual"] },
558
+ readjustment_period_months: { type: "integer" },
559
+ last_readjustment_date: { type: ["string", "null"], format: "date" },
560
+ next_readjustment_date: { type: ["string", "null"], format: "date" },
561
+ next_generation_date: { type: ["string", "null"], format: "date", description: "Quando a pr\xF3xima fatura ser\xE1 gerada \u2014 se antes do reajuste, ela sai no valor antigo" },
562
+ overdue: { type: "boolean" }
563
+ }
564
+ },
565
+ MarketIndexSuggestion: {
566
+ type: "object",
567
+ description: "Acumulado de um \xEDndice oficial no per\xEDodo (fonte: BCB, cache local).",
568
+ properties: {
569
+ index_code: { type: "string", enum: ["ipca", "igpm", "inpc", "usd", "eur"] },
570
+ accumulated_pct: { type: ["number", "null"], description: "Acumulado em pontos percentuais (4.62 = 4,62%); null = sem cobertura de dados" },
571
+ coverage_start: { type: ["string", "null"], format: "date" },
572
+ coverage_end: { type: ["string", "null"], format: "date" },
573
+ last_ref_date: { type: ["string", "null"], format: "date", description: "At\xE9 onde o \xEDndice cobre (IPCA sai com ~15 dias de atraso)" }
574
+ }
575
+ },
409
576
  InvoiceItem: {
410
577
  type: "object",
411
578
  properties: {
@@ -510,7 +677,9 @@ var SCHEMAS = {
510
677
  type: "object",
511
678
  properties: {
512
679
  id: { type: "string", format: "uuid" },
513
- name: { type: "string" },
680
+ name: { type: "string", description: "T\xEDtulo / r\xF3tulo de exibi\xE7\xE3o do fornecedor" },
681
+ legal_name: { type: ["string", "null"], description: "Raz\xE3o social (PJ) ou nome completo (PF/estrangeira)" },
682
+ surname: { type: ["string", "null"], description: "Sobrenome (pessoa f\xEDsica)" },
514
683
  email: { type: ["string", "null"] },
515
684
  phone: { type: ["string", "null"] },
516
685
  document: { type: ["string", "null"], description: "CPF ou CNPJ" },
@@ -523,6 +692,8 @@ var SCHEMAS = {
523
692
  payment_terms_days: { type: ["integer", "null"] },
524
693
  status: { type: "string", enum: ["ativo", "inativo"] },
525
694
  notes: { type: ["string", "null"] },
695
+ pagarme_recipient_id: { type: ["string", "null"], description: "ID do recebedor Pagar.me (re_\u2026) para split nativo. Criado pela aplica\xE7\xE3o." },
696
+ pagarme_kyc_status: { type: ["string", "null"], enum: ["pending", "registration", "approved", "refused", "suspended", "blocked", null], description: "Status de KYC do recebedor Pagar.me." },
526
697
  created_at: { type: "string", format: "date-time" },
527
698
  updated_at: { type: "string", format: "date-time" }
528
699
  }
@@ -531,7 +702,9 @@ var SCHEMAS = {
531
702
  type: "object",
532
703
  required: ["name"],
533
704
  properties: {
534
- name: { type: "string" },
705
+ name: { type: "string", description: "T\xEDtulo / r\xF3tulo de exibi\xE7\xE3o. Se omitido, derivado de legal_name." },
706
+ legal_name: { type: "string", description: "Raz\xE3o social (PJ) ou nome completo (PF/estrangeira)" },
707
+ surname: { type: "string", description: "Sobrenome (pessoa f\xEDsica)" },
535
708
  email: { type: "string" },
536
709
  phone: { type: "string" },
537
710
  document: { type: "string" },
@@ -674,8 +847,8 @@ var SCHEMAS = {
674
847
  id: { type: "string", format: "uuid" },
675
848
  status: { type: "string", enum: ["pending", "paid", "cancelled", "expired", "failed"] },
676
849
  status_raw: { type: "string", description: "Status bruto do provider" },
677
- method: { type: "string", enum: ["pix", "boleto", "checkout"] },
678
- provider: { type: "string", enum: ["inter", "c6bank", "pix_offline"], description: "Provedor resolvido. 'pix_offline' = Pix est\xE1tico (BR Code gerado localmente, sem API banc\xE1ria)." },
850
+ method: { type: "string", enum: ["pix", "boleto", "checkout", "credit_card"] },
851
+ provider: { type: "string", enum: ["inter", "c6bank", "pix_offline", "pagarme"], description: "Provedor resolvido. 'pix_offline' = Pix est\xE1tico (BR Code local). 'pagarme' = Pix server-side ou cart\xE3o (method=credit_card retorna 'checkout.url' = link da p\xE1gina de pagamento)." },
679
852
  invoice_id: { type: ["string", "null"], format: "uuid" },
680
853
  customer_id: { type: ["string", "null"], format: "uuid" },
681
854
  amount: { type: ["number", "null"] },
@@ -691,7 +864,8 @@ var SCHEMAS = {
691
864
  type: "object",
692
865
  required: ["method"],
693
866
  properties: {
694
- method: { type: "string", enum: ["pix", "boleto", "checkout"], description: "Canal de pagamento" },
867
+ method: { type: "string", enum: ["pix", "boleto", "checkout", "credit_card"], description: "Canal de pagamento" },
868
+ provider: { type: "string", enum: ["inter", "c6bank", "pix_offline", "pagarme"], description: "Opcional. Desambigua quando a empresa tem mais de um provedor no mesmo canal (ex.: Pix Inter x Pix Pagar.me). Se omitido, usa o provedor ativo do canal." },
695
869
  invoice_id: { type: "string", format: "uuid", description: "Fatura existente (opcional)" },
696
870
  customer_id: { type: "string", format: "uuid", description: "Obrigat\xF3rio se invoice_id omitido" },
697
871
  amount: { type: "number", description: "Obrigat\xF3rio se invoice_id omitido" },
@@ -773,6 +947,122 @@ var SCHEMAS = {
773
947
  description: { type: "string" }
774
948
  }
775
949
  },
950
+ SplitRuleRecipient: {
951
+ type: "object",
952
+ description: "Linha de uma regra de split: um benefici\xE1rio e sua base de c\xE1lculo.",
953
+ properties: {
954
+ id: { type: "string", format: "uuid" },
955
+ recipient_type: { type: "string", enum: ["supplier", "platform", "company_master"] },
956
+ supplier_id: { type: ["string", "null"], format: "uuid" },
957
+ supplier_payment_method_id: { type: ["string", "null"], format: "uuid" },
958
+ basis: { type: "string", enum: ["percentual", "fixo", "combinado"] },
959
+ percent: { type: "number", description: "0\u2013100 (percentual)" },
960
+ fixed_cents: { type: "integer", description: "Valor fixo em centavos" },
961
+ is_platform_fee: { type: "boolean" },
962
+ apply_per_installment: { type: "boolean" },
963
+ installments: { type: ["object", "null"], description: "Divis\xE3o por parcela (jsonb)" },
964
+ sort_order: { type: "integer" }
965
+ }
966
+ },
967
+ SplitRule: {
968
+ type: "object",
969
+ description: "Regra de divis\xE3o (template) de um recebimento entre benefici\xE1rios.",
970
+ properties: {
971
+ id: { type: "string", format: "uuid" },
972
+ name: { type: "string" },
973
+ description: { type: ["string", "null"] },
974
+ scope: { type: "string", enum: ["company_default", "contract", "invoice", "charge"] },
975
+ contract_id: { type: ["string", "null"], format: "uuid" },
976
+ fiscal_mode: { type: "string", enum: ["intermediacao", "revenda"] },
977
+ fee_payer: { type: "string", enum: ["platform", "recipients", "proportional"] },
978
+ release_trigger: { type: "string", enum: ["on_settlement", "on_nota", "manual", "scheduled"] },
979
+ rounding_strategy: { type: "string", enum: ["remainder_to_master", "largest_remainder"] },
980
+ is_active: { type: "boolean" },
981
+ gateway_split_enabled: { type: "boolean", description: "Quando true, usa o split nativo da Pagar.me (divis\xE3o no ato do pagamento) se a cobran\xE7a for Pagar.me e os fornecedores tiverem recebedor aprovado; sen\xE3o, repasse interno." },
982
+ recipients: { type: "array", items: { $ref: "#/components/schemas/SplitRuleRecipient" } },
983
+ created_at: { type: "string", format: "date-time" },
984
+ updated_at: { type: "string", format: "date-time" }
985
+ }
986
+ },
987
+ SplitRuleCreate: {
988
+ type: "object",
989
+ required: ["name", "recipients"],
990
+ properties: {
991
+ name: { type: "string" },
992
+ description: { type: "string" },
993
+ scope: { type: "string", enum: ["company_default", "contract", "invoice", "charge"], default: "company_default" },
994
+ contract_id: { type: "string", format: "uuid", description: "Obrigat\xF3rio quando scope=contract" },
995
+ fiscal_mode: { type: "string", enum: ["intermediacao", "revenda"], default: "intermediacao" },
996
+ fee_payer: { type: "string", enum: ["platform", "recipients", "proportional"], default: "platform" },
997
+ release_trigger: { type: "string", enum: ["on_settlement", "on_nota", "manual", "scheduled"], default: "on_settlement" },
998
+ rounding_strategy: { type: "string", enum: ["remainder_to_master", "largest_remainder"], default: "remainder_to_master" },
999
+ is_active: { type: "boolean", default: true },
1000
+ gateway_split_enabled: { type: "boolean", default: true, description: "Usar o split nativo da Pagar.me quando aplic\xE1vel (sen\xE3o repasse interno)." },
1001
+ recipients: {
1002
+ type: "array",
1003
+ description: "Benefici\xE1rios. Percentual primeiro, depois fixo. Soma de percentuais \u2264 100.",
1004
+ items: {
1005
+ type: "object",
1006
+ required: ["recipient_type", "basis"],
1007
+ properties: {
1008
+ recipient_type: { type: "string", enum: ["supplier", "platform", "company_master"] },
1009
+ supplier_id: { type: "string", format: "uuid", description: "Obrigat\xF3rio se recipient_type=supplier" },
1010
+ supplier_payment_method_id: { type: "string", format: "uuid" },
1011
+ basis: { type: "string", enum: ["percentual", "fixo", "combinado"] },
1012
+ percent: { type: "number" },
1013
+ fixed_cents: { type: "integer" },
1014
+ is_platform_fee: { type: "boolean" },
1015
+ sort_order: { type: "integer" },
1016
+ apply_per_installment: { type: "boolean", description: "Split por parcela: percent/fixo v\xEAm de 'installments'" },
1017
+ installments: { type: "object", description: 'Por n\xBA de parcela, ex.: { "1": { "percent": 50 }, "default": { "percent": 100 } }' }
1018
+ }
1019
+ }
1020
+ }
1021
+ }
1022
+ },
1023
+ SplitExecutionItem: {
1024
+ type: "object",
1025
+ description: "Fatia de uma execu\xE7\xE3o de split, por benefici\xE1rio.",
1026
+ properties: {
1027
+ id: { type: "string", format: "uuid" },
1028
+ recipient_type: { type: "string", enum: ["supplier", "platform", "company_master"] },
1029
+ supplier_id: { type: ["string", "null"], format: "uuid" },
1030
+ supplier_name: { type: ["string", "null"] },
1031
+ is_platform_fee: { type: "boolean" },
1032
+ gross_share_cents: { type: "integer" },
1033
+ fee_share_cents: { type: "integer" },
1034
+ net_share_cents: { type: "integer" },
1035
+ status: { type: "string", enum: ["pending", "awaiting_nota", "released", "paying", "paid", "reversed", "failed"] },
1036
+ payment_order_id: { type: ["string", "null"], format: "uuid" },
1037
+ nota_status: { type: "string" },
1038
+ error_message: { type: ["string", "null"], description: "Motivo da falha do repasse (quando status=failed)" },
1039
+ released_at: { type: ["string", "null"], format: "date-time" },
1040
+ paid_at: { type: ["string", "null"], format: "date-time" },
1041
+ reversed_at: { type: ["string", "null"], format: "date-time" }
1042
+ }
1043
+ },
1044
+ SplitExecution: {
1045
+ type: "object",
1046
+ description: "Execu\xE7\xE3o de split: inst\xE2ncia concreta de uma divis\xE3o por cobran\xE7a recebida.",
1047
+ properties: {
1048
+ id: { type: "string", format: "uuid" },
1049
+ invoice_id: { type: ["string", "null"], format: "uuid" },
1050
+ charge_id: { type: ["string", "null"], format: "uuid" },
1051
+ split_rule_id: { type: ["string", "null"], format: "uuid" },
1052
+ gateway_provider: { type: ["string", "null"] },
1053
+ gross_cents: { type: "integer" },
1054
+ gateway_fee_cents: { type: "integer" },
1055
+ net_cents: { type: "integer" },
1056
+ fiscal_mode: { type: "string", enum: ["intermediacao", "revenda"] },
1057
+ release_trigger: { type: "string", enum: ["on_settlement", "on_nota", "manual", "scheduled"] },
1058
+ status: { type: "string", enum: ["pending", "calculated", "releasing", "completed", "partial", "reversed", "failed"] },
1059
+ settled_at: { type: ["string", "null"], format: "date-time" },
1060
+ error_message: { type: ["string", "null"] },
1061
+ items: { type: "array", items: { $ref: "#/components/schemas/SplitExecutionItem" } },
1062
+ created_at: { type: "string", format: "date-time" },
1063
+ updated_at: { type: "string", format: "date-time" }
1064
+ }
1065
+ },
776
1066
  SupplierPaymentMethod: {
777
1067
  type: "object",
778
1068
  properties: {
@@ -991,6 +1281,34 @@ var SCHEMAS = {
991
1281
  sort_order: { type: "integer" }
992
1282
  }
993
1283
  },
1284
+ Reminder: {
1285
+ type: "object",
1286
+ properties: {
1287
+ id: { type: "string", format: "uuid" },
1288
+ scope: { type: "string", enum: ["personal", "company"] },
1289
+ audience: { type: "array", items: { type: "string", enum: ["admin", "operador", "visualizador"] }, description: "Pap\xE9is que recebem (vazio = todos os membros)." },
1290
+ kind: { type: "string", enum: ["manual", "digest"] },
1291
+ template_key: { type: ["string", "null"], description: "Para digest: revenue.summary, receivables.overdue, payables.due, cards.upcoming, nfse.monthly, cashflow.position, mrr.snapshot." },
1292
+ params: { type: "object", description: "Par\xE2metros do digest (ex: { period: 'week' } ou { days_ahead: 7 })." },
1293
+ title: { type: ["string", "null"] },
1294
+ body: { type: ["string", "null"] },
1295
+ entity_type: { type: ["string", "null"] },
1296
+ entity_id: { type: ["string", "null"], format: "uuid" },
1297
+ channels: { type: "object", properties: { in_app: { type: "boolean" }, email: { type: "boolean" }, push: { type: "boolean" } } },
1298
+ recurrence_type: { type: "string", enum: ["once", "daily", "weekly", "monthly"] },
1299
+ run_time: { type: "string", description: "HH:MM[:SS], hora local do fuso." },
1300
+ weekday: { type: ["integer", "null"], description: "0=domingo \u2026 6=s\xE1bado (semanal)." },
1301
+ day_of_month: { type: ["integer", "null"], description: "1\u201331 (mensal; meses curtos usam o \xFAltimo dia)." },
1302
+ timezone: { type: "string" },
1303
+ start_date: { type: ["string", "null"], format: "date" },
1304
+ end_date: { type: ["string", "null"], format: "date" },
1305
+ next_run_at: { type: ["string", "null"], format: "date-time" },
1306
+ last_run_at: { type: ["string", "null"], format: "date-time" },
1307
+ active: { type: "boolean" },
1308
+ created_at: { type: "string", format: "date-time" },
1309
+ updated_at: { type: "string", format: "date-time" }
1310
+ }
1311
+ },
994
1312
  PaymentCondition: {
995
1313
  type: "object",
996
1314
  properties: {
@@ -1004,6 +1322,15 @@ var SCHEMAS = {
1004
1322
  type: "object",
1005
1323
  properties: { id: { type: "string", format: "uuid" }, name: { type: "string" } }
1006
1324
  },
1325
+ ServiceCategory: {
1326
+ type: "object",
1327
+ properties: {
1328
+ id: { type: "string", format: "uuid" },
1329
+ name: { type: "string" },
1330
+ color: { type: ["string", "null"] },
1331
+ created_at: { type: "string", format: "date-time" }
1332
+ }
1333
+ },
1007
1334
  WebhookDelivery: {
1008
1335
  type: "object",
1009
1336
  properties: {
@@ -1072,7 +1399,7 @@ var OPENAPI_SPEC = {
1072
1399
  },
1073
1400
  servers: [
1074
1401
  { url: "https://api.comando.one/v1", description: "Produ\xE7\xE3o" },
1075
- { url: "https://pecdxlrbutkrtxvjsquf.supabase.co/functions/v1/public-api/v1", description: "Supabase direto" }
1402
+ { url: "https://sb.comando.one/functions/v1/public-api/v1", description: "Supabase direto" }
1076
1403
  ],
1077
1404
  security: API_KEY_SECURITY,
1078
1405
  tags: [
@@ -1093,7 +1420,8 @@ var OPENAPI_SPEC = {
1093
1420
  { name: "Contas banc\xE1rias", description: "Contas banc\xE1rias (somente leitura)" },
1094
1421
  { name: "Pagamentos a Fornecedor", description: "Payouts \u2014 pagar/agendar Pix e boleto a fornecedores" },
1095
1422
  { name: "M\xE9todos de pagamento", description: "Formas de recebimento dispon\xEDveis" },
1096
- { name: "Formas de pagamento do fornecedor", description: "Cadastro de destinos de pagamento por fornecedor" }
1423
+ { name: "Formas de pagamento do fornecedor", description: "Cadastro de destinos de pagamento por fornecedor" },
1424
+ { name: "Lembretes", description: "Lembretes e resumos agendados (recorrentes ou avulsos)" }
1097
1425
  ],
1098
1426
  components: {
1099
1427
  securitySchemes: {
@@ -1526,6 +1854,89 @@ var OPENAPI_SPEC = {
1526
1854
  responses: { "204": { description: "Exclu\xEDdo" }, "404": errorResponse("Contrato n\xE3o encontrado"), "409": errorResponse("H\xE1 registros vinculados que impedem a exclus\xE3o"), ...COMMON_ERRORS }
1527
1855
  }
1528
1856
  },
1857
+ "/contracts/{id}/pause": {
1858
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
1859
+ post: {
1860
+ tags: ["Contratos"],
1861
+ summary: "Pausar contrato (status \u2192 suspenso)",
1862
+ operationId: "pauseContract",
1863
+ security: [{ ApiKeyAuth: ["contracts:write"] }],
1864
+ responses: { "200": { description: "Contrato pausado", content: { "application/json": { schema: { $ref: "#/components/schemas/Contract" } } } }, "404": errorResponse("Contrato n\xE3o encontrado"), ...COMMON_ERRORS }
1865
+ }
1866
+ },
1867
+ "/contracts/{id}/resume": {
1868
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
1869
+ post: {
1870
+ tags: ["Contratos"],
1871
+ summary: "Retomar contrato (status \u2192 ativo)",
1872
+ operationId: "resumeContract",
1873
+ security: [{ ApiKeyAuth: ["contracts:write"] }],
1874
+ responses: { "200": { description: "Contrato retomado", content: { "application/json": { schema: { $ref: "#/components/schemas/Contract" } } } }, "404": errorResponse("Contrato n\xE3o encontrado"), "409": errorResponse("Status n\xE3o permite retomada"), ...COMMON_ERRORS }
1875
+ }
1876
+ },
1877
+ "/contracts/readjustments/due": {
1878
+ get: {
1879
+ tags: ["Contratos"],
1880
+ summary: "Fila de reajuste (contratos atrasados + janela)",
1881
+ description: "Contratos ativos, n\xE3o isentos, com reajuste vencido ou vencendo na janela informada. Campo 'overdue' indica atraso.",
1882
+ operationId: "listDueReadjustments",
1883
+ security: [{ ApiKeyAuth: ["contracts:read"] }],
1884
+ parameters: [
1885
+ { name: "days", in: "query", schema: { type: "integer", default: 30, minimum: 0, maximum: 365 }, description: "Janela em dias al\xE9m dos atrasados" }
1886
+ ],
1887
+ responses: {
1888
+ "200": { description: "Fila de reajuste", content: { "application/json": { schema: { type: "object", properties: { data: { type: "array", items: { $ref: "#/components/schemas/ContractReadjustmentQueueItem" } }, window_days: { type: "integer" } } } } } },
1889
+ ...COMMON_ERRORS
1890
+ }
1891
+ }
1892
+ },
1893
+ "/contracts/{id}/readjustments": {
1894
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
1895
+ get: {
1896
+ tags: ["Contratos"],
1897
+ summary: "Hist\xF3rico de reajustes do contrato",
1898
+ operationId: "listContractReadjustments",
1899
+ security: [{ ApiKeyAuth: ["contracts:read"] }],
1900
+ responses: {
1901
+ "200": { description: "Reajustes aplicados (mais recente primeiro)", content: { "application/json": { schema: { type: "object", properties: { data: { type: "array", items: { $ref: "#/components/schemas/ContractReadjustment" } } } } } } },
1902
+ "404": errorResponse("Contrato n\xE3o encontrado"),
1903
+ ...COMMON_ERRORS
1904
+ }
1905
+ },
1906
+ post: {
1907
+ tags: ["Contratos"],
1908
+ summary: "Aplicar reajuste no contrato",
1909
+ description: "Atualiza o valor do contrato (e escala os itens proporcionalmente), grava o hist\xF3rico e avan\xE7a a data do pr\xF3ximo reajuste. Informe 'new_amount' OU 'percent'. Faturas j\xE1 geradas n\xE3o s\xE3o alteradas.",
1910
+ operationId: "applyContractReadjustment",
1911
+ security: [{ ApiKeyAuth: ["contracts:write"] }],
1912
+ requestBody: { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/ContractReadjustmentCreate" } } } },
1913
+ responses: {
1914
+ "201": { description: "Reajuste aplicado", content: { "application/json": { schema: { $ref: "#/components/schemas/ContractReadjustment" } } } },
1915
+ "400": errorResponse("Dados inv\xE1lidos"),
1916
+ "404": errorResponse("Contrato n\xE3o encontrado"),
1917
+ "409": errorResponse("Contrato com valor zero \u2014 informe new_amount"),
1918
+ ...COMMON_ERRORS
1919
+ }
1920
+ }
1921
+ },
1922
+ "/market-indices": {
1923
+ get: {
1924
+ tags: ["Contratos"],
1925
+ summary: "\xCDndices de mercado acumulados no per\xEDodo (BCB)",
1926
+ description: "Acumulado de IPCA/IGP-M/INPC (composto mensal) e varia\xE7\xE3o da PTAX de d\xF3lar/euro entre 'from' e 'to'. Fonte: Banco Central (SGS e PTAX), sincronizada diariamente.",
1927
+ operationId: "getMarketIndices",
1928
+ security: [{ ApiKeyAuth: ["contracts:read"] }],
1929
+ parameters: [
1930
+ { name: "from", in: "query", required: true, schema: { type: "string", format: "date" }, description: "In\xEDcio do per\xEDodo (ex.: data do \xFAltimo reajuste)" },
1931
+ { name: "to", in: "query", schema: { type: "string", format: "date" }, description: "Fim do per\xEDodo (padr\xE3o: hoje)" }
1932
+ ],
1933
+ responses: {
1934
+ "200": { description: "Acumulados por \xEDndice", content: { "application/json": { schema: { type: "object", properties: { from: { type: "string", format: "date" }, to: { type: "string", format: "date" }, data: { type: "array", items: { $ref: "#/components/schemas/MarketIndexSuggestion" } } } } } } },
1935
+ "400": errorResponse("Par\xE2metro 'from' obrigat\xF3rio"),
1936
+ ...COMMON_ERRORS
1937
+ }
1938
+ }
1939
+ },
1529
1940
  // -----------------------------------------------------------------------
1530
1941
  // Invoices
1531
1942
  // -----------------------------------------------------------------------
@@ -1571,6 +1982,14 @@ var OPENAPI_SPEC = {
1571
1982
  "404": errorResponse("Fatura n\xE3o encontrada"),
1572
1983
  ...COMMON_ERRORS
1573
1984
  }
1985
+ },
1986
+ delete: {
1987
+ tags: ["Faturas"],
1988
+ summary: "Excluir fatura",
1989
+ operationId: "deleteInvoice",
1990
+ description: "Exclus\xE3o f\xEDsica da fatura (itens e cobran\xE7as vinculadas via cascade). Use cancel para apenas cancelar.",
1991
+ security: [{ ApiKeyAuth: ["invoices:delete"] }],
1992
+ responses: { "204": { description: "Exclu\xEDda" }, "404": errorResponse("Fatura n\xE3o encontrada"), "409": errorResponse("H\xE1 registros vinculados que impedem a exclus\xE3o"), ...COMMON_ERRORS }
1574
1993
  }
1575
1994
  },
1576
1995
  "/invoices/{id}/cancel": {
@@ -1668,6 +2087,114 @@ var OPENAPI_SPEC = {
1668
2087
  security: [{ ApiKeyAuth: ["expenses:read", "expenses:write", "finance:read"] }],
1669
2088
  parameters: [...PAGINATION_PARAMS, { name: "active", in: "query", schema: { type: "string", enum: ["true", "false"] } }],
1670
2089
  responses: { "200": paginatedResponse("#/components/schemas/CostCenter"), ...COMMON_ERRORS }
2090
+ },
2091
+ post: {
2092
+ tags: ["Cat\xE1logos"],
2093
+ summary: "Criar centro de custo",
2094
+ operationId: "createCostCenter",
2095
+ security: [{ ApiKeyAuth: ["finance:write"] }],
2096
+ requestBody: { required: true, content: { "application/json": { schema: { type: "object", required: ["name"], properties: {
2097
+ name: { type: "string" },
2098
+ color: { type: "string" },
2099
+ icon: { type: "string" },
2100
+ dre_group: { type: "string" },
2101
+ sort_order: { type: "integer" },
2102
+ active: { type: "boolean" }
2103
+ } } } } },
2104
+ responses: { "201": { description: "Centro de custo criado", content: { "application/json": { schema: { $ref: "#/components/schemas/CostCenter" } } } }, "400": errorResponse("Nome ausente"), "409": errorResponse("Nome duplicado"), ...COMMON_ERRORS }
2105
+ }
2106
+ },
2107
+ "/cost-centers/{id}": {
2108
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
2109
+ patch: {
2110
+ tags: ["Cat\xE1logos"],
2111
+ summary: "Atualizar centro de custo",
2112
+ operationId: "updateCostCenter",
2113
+ security: [{ ApiKeyAuth: ["finance:write"] }],
2114
+ requestBody: { required: true, content: { "application/json": { schema: { type: "object", properties: { name: { type: "string" }, color: { type: "string" }, icon: { type: "string" }, dre_group: { type: "string" }, sort_order: { type: "integer" }, active: { type: "boolean" } } } } } },
2115
+ responses: { "200": { description: "Atualizado", content: { "application/json": { schema: { $ref: "#/components/schemas/CostCenter" } } } }, "400": errorResponse("Nada para atualizar"), "404": errorResponse("N\xE3o encontrado"), "409": errorResponse("Nome duplicado"), ...COMMON_ERRORS }
2116
+ },
2117
+ delete: {
2118
+ tags: ["Cat\xE1logos"],
2119
+ summary: "Excluir centro de custo",
2120
+ operationId: "deleteCostCenter",
2121
+ security: [{ ApiKeyAuth: ["finance:delete"] }],
2122
+ responses: { "204": { description: "Exclu\xEDdo" }, "404": errorResponse("N\xE3o encontrado"), "409": errorResponse("H\xE1 registros vinculados"), ...COMMON_ERRORS }
2123
+ }
2124
+ },
2125
+ "/reminders": {
2126
+ get: {
2127
+ tags: ["Lembretes"],
2128
+ summary: "Listar lembretes",
2129
+ operationId: "listReminders",
2130
+ description: "Lembretes e resumos agendados da empresa.",
2131
+ security: [{ ApiKeyAuth: ["reminders:list"] }],
2132
+ parameters: [
2133
+ ...PAGINATION_PARAMS,
2134
+ { name: "active", in: "query", schema: { type: "string", enum: ["true", "false"] } },
2135
+ { name: "scope", in: "query", schema: { type: "string", enum: ["personal", "company"] } }
2136
+ ],
2137
+ responses: { "200": paginatedResponse("#/components/schemas/Reminder"), ...COMMON_ERRORS }
2138
+ },
2139
+ post: {
2140
+ tags: ["Lembretes"],
2141
+ summary: "Criar lembrete",
2142
+ operationId: "createReminder",
2143
+ description: "Cria um lembrete. ESCOPO: scope='personal' cria um lembrete s\xF3 do usu\xE1rio (aparece em 'Meus lembretes'); scope='company' cria para a empresa (todos os membros veem). No chat, scope='personal' usa o usu\xE1rio autenticado; via chave cmd_live (sem usu\xE1rio) informe owner_user_id para pessoal. RELATIVO ('daqui 30 min'): { title, remind_in_minutes } \u2014 o servidor calcula o hor\xE1rio. ABSOLUTO: { title, remind_at } (ISO, use 'Z' p/ UTC). Em ambos, kind=manual, recurrence_type=once, start_date e run_time s\xE3o inferidos.",
2144
+ security: [{ ApiKeyAuth: ["reminders:create"] }],
2145
+ requestBody: { required: true, content: { "application/json": { schema: { type: "object", required: ["title"], properties: {
2146
+ scope: { type: "string", enum: ["personal", "company"], description: "personal = s\xF3 do usu\xE1rio; company = todos da empresa. Default: personal no chat (com usu\xE1rio), company via chave de API." },
2147
+ owner_user_id: { type: "string", format: "uuid", description: "Dono do lembrete pessoal (membro da empresa). No chat \xE9 inferido do usu\xE1rio; s\xF3 necess\xE1rio via chave cmd_live para scope=personal." },
2148
+ kind: { type: "string", enum: ["manual", "digest"], description: "Default: manual (ou digest se houver template_key)." },
2149
+ title: { type: "string", description: "T\xEDtulo do lembrete (obrigat\xF3rio para kind=manual)." },
2150
+ body: { type: "string" },
2151
+ template_key: { type: "string", description: "Obrigat\xF3rio para kind=digest." },
2152
+ remind_in_minutes: { type: "integer", description: "Atalho RELATIVO: minutos a partir de agora (servidor calcula). Ex.: 'daqui 30min' \u2192 30. Preferir para lembretes relativos." },
2153
+ remind_at: { type: "string", description: "Atalho ABSOLUTO: instante ISO (use 'Z' para UTC). Vira recurrence once + start_date + run_time no fuso." },
2154
+ params: { type: "object" },
2155
+ audience: { type: "array", items: { type: "string", enum: ["admin", "operador", "visualizador"] } },
2156
+ channels: { type: "object", properties: { in_app: { type: "boolean" }, email: { type: "boolean" }, push: { type: "boolean" } } },
2157
+ recurrence_type: { type: "string", enum: ["once", "daily", "weekly", "monthly"], description: "Default once quando se usa remind_in_minutes/remind_at." },
2158
+ run_time: { type: "string", description: "HH:MM (hora local) \u2014 para recorr\xEAncias." },
2159
+ weekday: { type: "integer", description: "0\u20136 (semanal)." },
2160
+ day_of_month: { type: "integer", description: "1\u201331 (mensal)." },
2161
+ timezone: { type: "string" },
2162
+ start_date: { type: "string", format: "date" },
2163
+ end_date: { type: "string", format: "date" }
2164
+ } } } } },
2165
+ responses: { "201": { description: "Lembrete criado", content: { "application/json": { schema: { $ref: "#/components/schemas/Reminder" } } } }, "400": errorResponse("Campos inv\xE1lidos"), ...COMMON_ERRORS }
2166
+ }
2167
+ },
2168
+ "/reminders/{id}": {
2169
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
2170
+ patch: {
2171
+ tags: ["Lembretes"],
2172
+ summary: "Atualizar / pausar lembrete",
2173
+ operationId: "updateReminder",
2174
+ security: [{ ApiKeyAuth: ["reminders:update"] }],
2175
+ requestBody: { required: true, content: { "application/json": { schema: { type: "object", properties: {
2176
+ title: { type: "string" },
2177
+ body: { type: "string" },
2178
+ params: { type: "object" },
2179
+ audience: { type: "array", items: { type: "string" } },
2180
+ channels: { type: "object" },
2181
+ recurrence_type: { type: "string", enum: ["once", "daily", "weekly", "monthly"] },
2182
+ run_time: { type: "string" },
2183
+ weekday: { type: "integer" },
2184
+ day_of_month: { type: "integer" },
2185
+ timezone: { type: "string" },
2186
+ start_date: { type: "string", format: "date" },
2187
+ end_date: { type: "string", format: "date" },
2188
+ active: { type: "boolean" }
2189
+ } } } } },
2190
+ responses: { "200": { description: "Atualizado", content: { "application/json": { schema: { $ref: "#/components/schemas/Reminder" } } } }, "400": errorResponse("Nada para atualizar"), "404": errorResponse("N\xE3o encontrado"), ...COMMON_ERRORS }
2191
+ },
2192
+ delete: {
2193
+ tags: ["Lembretes"],
2194
+ summary: "Excluir lembrete",
2195
+ operationId: "deleteReminder",
2196
+ security: [{ ApiKeyAuth: ["reminders:delete"] }],
2197
+ responses: { "204": { description: "Exclu\xEDdo" }, "404": errorResponse("N\xE3o encontrado"), ...COMMON_ERRORS }
1671
2198
  }
1672
2199
  },
1673
2200
  "/payment-conditions": {
@@ -1690,6 +2217,116 @@ var OPENAPI_SPEC = {
1690
2217
  responses: { "200": paginatedResponse("#/components/schemas/ServiceUnit"), ...COMMON_ERRORS }
1691
2218
  }
1692
2219
  },
2220
+ "/audit/timeline": {
2221
+ get: {
2222
+ tags: ["Auditoria"],
2223
+ summary: "Timeline de auditoria de uma entidade",
2224
+ operationId: "getAuditTimeline",
2225
+ description: "Retorna o hist\xF3rico de altera\xE7\xF5es (audit_logs) de uma entidade da empresa, mais recente primeiro.",
2226
+ security: [{ ApiKeyAuth: ["audit:read"] }],
2227
+ parameters: [
2228
+ { name: "entity_type", in: "query", required: true, schema: { type: "string" }, description: "Tipo da entidade (ex.: invoice, customer, contract)" },
2229
+ { name: "entity_id", in: "query", required: true, schema: { type: "string", format: "uuid" }, description: "ID da entidade" },
2230
+ { name: "limit", in: "query", schema: { type: "integer", minimum: 1, maximum: 30, default: 12 }, description: "M\xE1ximo de eventos (1\u201330)" }
2231
+ ],
2232
+ responses: {
2233
+ "200": {
2234
+ description: "Timeline da entidade",
2235
+ content: { "application/json": { schema: {
2236
+ type: "object",
2237
+ properties: {
2238
+ entity_type: { type: "string" },
2239
+ entity_id: { type: "string", format: "uuid" },
2240
+ entries: { type: "array", items: { type: "object", properties: {
2241
+ created_at: { type: "string", format: "date-time" },
2242
+ action: { type: "string" },
2243
+ description: { type: "string" },
2244
+ user_email: { type: "string" }
2245
+ } } }
2246
+ }
2247
+ } } }
2248
+ },
2249
+ ...COMMON_ERRORS
2250
+ }
2251
+ }
2252
+ },
2253
+ "/service-categories": {
2254
+ get: {
2255
+ tags: ["Servi\xE7os"],
2256
+ summary: "Listar categorias de servi\xE7o",
2257
+ operationId: "listServiceCategories",
2258
+ security: [{ ApiKeyAuth: ["services:read"] }],
2259
+ parameters: [...PAGINATION_PARAMS, { name: "search", in: "query", schema: { type: "string" }, description: "Filtro por nome (ilike)" }],
2260
+ responses: { "200": paginatedResponse("#/components/schemas/ServiceCategory"), ...COMMON_ERRORS }
2261
+ },
2262
+ post: {
2263
+ tags: ["Servi\xE7os"],
2264
+ summary: "Criar categoria(s) de servi\xE7o",
2265
+ operationId: "createServiceCategory",
2266
+ security: [{ ApiKeyAuth: ["services:write"] }],
2267
+ requestBody: { required: true, content: { "application/json": { schema: { type: "object", properties: {
2268
+ name: { type: "string", description: "Nome de uma categoria" },
2269
+ names: { type: "array", items: { type: "string" }, description: "Lista de nomes (cria v\xE1rias de uma vez)" },
2270
+ color: { type: "string", description: "Cor hex (default #6366f1)" }
2271
+ } } } } },
2272
+ responses: { "201": { description: "Categoria(s) criada(s)", content: { "application/json": { schema: { $ref: "#/components/schemas/ServiceCategory" } } } }, "400": errorResponse("Nome ausente"), "409": errorResponse("Categoria j\xE1 existe"), ...COMMON_ERRORS }
2273
+ }
2274
+ },
2275
+ "/service-categories/{id}": {
2276
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
2277
+ patch: {
2278
+ tags: ["Servi\xE7os"],
2279
+ summary: "Atualizar categoria de servi\xE7o",
2280
+ operationId: "updateServiceCategory",
2281
+ security: [{ ApiKeyAuth: ["services:write"] }],
2282
+ requestBody: { required: true, content: { "application/json": { schema: { type: "object", properties: { name: { type: "string" }, color: { type: "string" } } } } } },
2283
+ responses: { "200": { description: "Atualizada", content: { "application/json": { schema: { $ref: "#/components/schemas/ServiceCategory" } } } }, "400": errorResponse("Nada para atualizar"), "404": errorResponse("N\xE3o encontrada"), "409": errorResponse("Nome duplicado"), ...COMMON_ERRORS }
2284
+ },
2285
+ delete: {
2286
+ tags: ["Servi\xE7os"],
2287
+ summary: "Excluir categoria de servi\xE7o",
2288
+ operationId: "deleteServiceCategory",
2289
+ security: [{ ApiKeyAuth: ["services:delete"] }],
2290
+ responses: { "204": { description: "Exclu\xEDda" }, "404": errorResponse("N\xE3o encontrada"), ...COMMON_ERRORS }
2291
+ }
2292
+ },
2293
+ "/reports/aging-actions": {
2294
+ get: {
2295
+ tags: ["Relat\xF3rios"],
2296
+ summary: "Aging de inadimpl\xEAncia com a\xE7\xF5es sugeridas",
2297
+ operationId: "reportAgingActions",
2298
+ security: [{ ApiKeyAuth: ["invoices:read", "finance:read"] }],
2299
+ parameters: [
2300
+ { name: "limit", in: "query", schema: { type: "integer", minimum: 1, maximum: 40, default: 12 } },
2301
+ { name: "min_overdue_days", in: "query", schema: { type: "integer", minimum: 1, maximum: 365, default: 1 } },
2302
+ { name: "include_shared", in: "query", schema: { type: "boolean", default: true }, description: "Incluir clientes compartilhados" },
2303
+ { name: "customer_id", in: "query", schema: { type: "string", format: "uuid" } },
2304
+ { name: "search", in: "query", schema: { type: "string" } }
2305
+ ],
2306
+ responses: { "200": { description: "Faturas em atraso + a\xE7\xF5es recomendadas", content: { "application/json": { schema: { type: "object", properties: {
2307
+ count: { type: "integer" },
2308
+ limit: { type: "integer" },
2309
+ min_overdue_days: { type: "integer" },
2310
+ total_overdue_amount: { type: "number" },
2311
+ actions: { type: "array", items: { type: "object" } }
2312
+ } } } } }, ...COMMON_ERRORS }
2313
+ }
2314
+ },
2315
+ "/reports/cashflow-forecast": {
2316
+ get: {
2317
+ tags: ["Relat\xF3rios"],
2318
+ summary: "Previs\xE3o de fluxo de caixa",
2319
+ operationId: "reportCashflowForecast",
2320
+ security: [{ ApiKeyAuth: ["finance:read"] }],
2321
+ parameters: [
2322
+ { name: "horizon_days", in: "query", schema: { type: "integer", minimum: 1, maximum: 120, default: 30 } },
2323
+ { name: "opening_balance", in: "query", schema: { type: "number", default: 0 } },
2324
+ { name: "include_receivables", in: "query", schema: { type: "boolean", default: true } },
2325
+ { name: "include_payables", in: "query", schema: { type: "boolean", default: true } }
2326
+ ],
2327
+ responses: { "200": { description: "Proje\xE7\xE3o di\xE1ria de caixa (timeline)", content: { "application/json": { schema: { type: "object" } } } }, ...COMMON_ERRORS }
2328
+ }
2329
+ },
1693
2330
  // -----------------------------------------------------------------------
1694
2331
  // NFS-e
1695
2332
  // -----------------------------------------------------------------------
@@ -1744,6 +2381,27 @@ var OPENAPI_SPEC = {
1744
2381
  }
1745
2382
  }
1746
2383
  },
2384
+ "/nfse/{id}/sync": {
2385
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
2386
+ post: {
2387
+ tags: ["NFS-e"],
2388
+ summary: "Sincronizar status da NFS-e com o provedor",
2389
+ operationId: "syncNfse",
2390
+ security: [{ ApiKeyAuth: ["nfse:read"] }],
2391
+ responses: { "200": { description: "Resultado da sincroniza\xE7\xE3o", content: { "application/json": { schema: { type: "object", properties: { id: { type: "string" }, invoice_id: { type: "string" }, processed: { type: "integer" }, updated: { type: "integer" }, attached: { type: "integer" } } } } } }, "404": errorResponse("NFS-e n\xE3o encontrada"), "502": errorResponse("Erro do provedor de NFS-e"), ...COMMON_ERRORS }
2392
+ }
2393
+ },
2394
+ "/nfse/{id}/files": {
2395
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
2396
+ get: {
2397
+ tags: ["NFS-e"],
2398
+ summary: "URLs assinadas do XML e DANFSE",
2399
+ operationId: "getNfseFiles",
2400
+ description: "Retorna URLs tempor\xE1rias (30 min) para download do XML e do PDF (DANFSE). Gera o PDF sob demanda se a nota estiver autorizada/cancelada.",
2401
+ security: [{ ApiKeyAuth: ["nfse:read"] }],
2402
+ responses: { "200": { description: "URLs assinadas", content: { "application/json": { schema: { type: "object", properties: { id: { type: "string" }, invoice_id: { type: "string" }, status: { type: "string" }, xml_signed_url: { type: ["string", "null"] }, danfse_signed_url: { type: ["string", "null"] }, signed_url_ttl_seconds: { type: "integer" } } } } } }, "404": errorResponse("NFS-e n\xE3o encontrada"), ...COMMON_ERRORS }
2403
+ }
2404
+ },
1747
2405
  // -----------------------------------------------------------------------
1748
2406
  // Fornecedores
1749
2407
  // -----------------------------------------------------------------------
@@ -1963,7 +2621,7 @@ var OPENAPI_SPEC = {
1963
2621
  parameters: [
1964
2622
  ...PAGINATION_PARAMS,
1965
2623
  { name: "status", in: "query", schema: { type: "string", enum: ["pending", "paid", "cancelled", "expired", "failed"] } },
1966
- { name: "method", in: "query", schema: { type: "string", enum: ["pix", "boleto", "checkout"] } },
2624
+ { name: "method", in: "query", schema: { type: "string", enum: ["pix", "boleto", "checkout", "credit_card"] } },
1967
2625
  { name: "customer_id", in: "query", schema: { type: "string", format: "uuid" } },
1968
2626
  { name: "invoice_id", in: "query", schema: { type: "string", format: "uuid" } }
1969
2627
  ],
@@ -1971,9 +2629,9 @@ var OPENAPI_SPEC = {
1971
2629
  },
1972
2630
  post: {
1973
2631
  tags: ["Cobran\xE7as"],
1974
- summary: "Criar cobran\xE7a (Pix, boleto ou checkout)",
2632
+ summary: "Criar cobran\xE7a (Pix, boleto, checkout ou cart\xE3o)",
1975
2633
  operationId: "createCharge",
1976
- description: "Gera uma cobran\xE7a no provider ativo da empresa (Inter ou C6 Bank). Forne\xE7a invoice_id ou customer_id+amount+due_date.",
2634
+ description: "Gera uma cobran\xE7a no provider ativo da empresa (Inter, C6 Bank, Pix Offline ou Pagar.me). Forne\xE7a invoice_id ou customer_id+amount+due_date. Com Pagar.me, method=pix retorna o copia-e-cola e method=credit_card retorna 'checkout.url' (link da p\xE1gina de pagamento pr\xF3pria).",
1977
2635
  security: [{ ApiKeyAuth: ["charges:create"] }],
1978
2636
  requestBody: { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/ChargeCreate" } } } },
1979
2637
  responses: {
@@ -2255,6 +2913,104 @@ var OPENAPI_SPEC = {
2255
2913
  }
2256
2914
  },
2257
2915
  // -----------------------------------------------------------------------
2916
+ // Split de Pagamentos (regras, execuções, repasses)
2917
+ // -----------------------------------------------------------------------
2918
+ "/split-rules": {
2919
+ get: {
2920
+ tags: ["Split de Pagamentos"],
2921
+ summary: "Listar regras de split",
2922
+ operationId: "listSplitRules",
2923
+ security: [{ ApiKeyAuth: ["split:list"] }],
2924
+ parameters: [
2925
+ ...PAGINATION_PARAMS,
2926
+ { name: "scope", in: "query", schema: { type: "string", enum: ["company_default", "contract", "invoice", "charge"] } }
2927
+ ],
2928
+ responses: { "200": paginatedResponse("#/components/schemas/SplitRule"), ...COMMON_ERRORS }
2929
+ },
2930
+ post: {
2931
+ tags: ["Split de Pagamentos"],
2932
+ summary: "Criar regra de split",
2933
+ operationId: "createSplitRule",
2934
+ description: "Cria uma regra de divis\xE3o com seus benefici\xE1rios (recipients). Percentual primeiro, depois fixo; soma de percentuais \u2264 100.",
2935
+ security: [{ ApiKeyAuth: ["split:create"] }],
2936
+ requestBody: { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/SplitRuleCreate" } } } },
2937
+ responses: { "201": { description: "Regra criada", content: { "application/json": { schema: { $ref: "#/components/schemas/SplitRule" } } } }, "400": errorResponse("Dados inv\xE1lidos"), ...COMMON_ERRORS }
2938
+ }
2939
+ },
2940
+ "/split-rules/{id}": {
2941
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
2942
+ get: {
2943
+ tags: ["Split de Pagamentos"],
2944
+ summary: "Obter regra de split",
2945
+ operationId: "getSplitRule",
2946
+ security: [{ ApiKeyAuth: ["split:list"] }],
2947
+ responses: { "200": { description: "Regra", content: { "application/json": { schema: { $ref: "#/components/schemas/SplitRule" } } } }, "404": errorResponse("Regra n\xE3o encontrada"), ...COMMON_ERRORS }
2948
+ },
2949
+ patch: {
2950
+ tags: ["Split de Pagamentos"],
2951
+ summary: "Atualizar regra de split",
2952
+ operationId: "updateSplitRule",
2953
+ description: "Atualiza campos da regra. Se 'recipients' for enviado, substitui todos os benefici\xE1rios.",
2954
+ security: [{ ApiKeyAuth: ["split:update"] }],
2955
+ requestBody: { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/SplitRuleCreate" } } } },
2956
+ responses: { "200": { description: "Regra atualizada", content: { "application/json": { schema: { $ref: "#/components/schemas/SplitRule" } } } }, "404": errorResponse("Regra n\xE3o encontrada"), ...COMMON_ERRORS }
2957
+ },
2958
+ delete: {
2959
+ tags: ["Split de Pagamentos"],
2960
+ summary: "Excluir regra de split",
2961
+ operationId: "deleteSplitRule",
2962
+ security: [{ ApiKeyAuth: ["split:delete"] }],
2963
+ responses: { "200": { description: "Removida", content: { "application/json": { schema: { type: "object", properties: { deleted: { type: "boolean" }, id: { type: "string" } } } } } }, "404": errorResponse("Regra n\xE3o encontrada"), ...COMMON_ERRORS }
2964
+ }
2965
+ },
2966
+ "/split-executions": {
2967
+ get: {
2968
+ tags: ["Split de Pagamentos"],
2969
+ summary: "Listar execu\xE7\xF5es de split",
2970
+ operationId: "listSplitExecutions",
2971
+ security: [{ ApiKeyAuth: ["split:list"] }],
2972
+ parameters: [
2973
+ ...PAGINATION_PARAMS,
2974
+ { name: "status", in: "query", schema: { type: "string", enum: ["pending", "calculated", "releasing", "completed", "partial", "reversed", "failed"] } },
2975
+ { name: "invoice_id", in: "query", schema: { type: "string", format: "uuid" } },
2976
+ { name: "supplier_id", in: "query", schema: { type: "string", format: "uuid" }, description: "Filtra execu\xE7\xF5es que contenham fatia deste fornecedor" }
2977
+ ],
2978
+ responses: { "200": paginatedResponse("#/components/schemas/SplitExecution"), ...COMMON_ERRORS }
2979
+ }
2980
+ },
2981
+ "/split-executions/{id}": {
2982
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
2983
+ get: {
2984
+ tags: ["Split de Pagamentos"],
2985
+ summary: "Obter execu\xE7\xE3o de split (com fatias)",
2986
+ operationId: "getSplitExecution",
2987
+ security: [{ ApiKeyAuth: ["split:list"] }],
2988
+ responses: { "200": { description: "Execu\xE7\xE3o", content: { "application/json": { schema: { $ref: "#/components/schemas/SplitExecution" } } } }, "404": errorResponse("Execu\xE7\xE3o n\xE3o encontrada"), ...COMMON_ERRORS }
2989
+ }
2990
+ },
2991
+ "/split-executions/{id}/reverse": {
2992
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
2993
+ post: {
2994
+ tags: ["Split de Pagamentos"],
2995
+ summary: "Estornar execu\xE7\xE3o de split",
2996
+ operationId: "reverseSplitExecution",
2997
+ description: "Marca a execu\xE7\xE3o e suas fatias como 'reversed'. Para cada fatia de fornecedor j\xE1 paga, registra um ajuste de recupera\xE7\xE3o (o fornecedor deve devolver o valor).",
2998
+ security: [{ ApiKeyAuth: ["split:update"] }],
2999
+ responses: { "200": { description: "Estornada", content: { "application/json": { schema: { type: "object", properties: { execution_id: { type: "string" }, status: { type: "string" }, adjustments_created: { type: "integer" }, recover_amount_cents: { type: "integer" } } } } } }, "404": errorResponse("Execu\xE7\xE3o n\xE3o encontrada"), "409": errorResponse("J\xE1 estornada"), ...COMMON_ERRORS }
3000
+ }
3001
+ },
3002
+ "/split-items/{id}/release": {
3003
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
3004
+ post: {
3005
+ tags: ["Split de Pagamentos"],
3006
+ summary: "Liberar fatia manualmente",
3007
+ operationId: "releaseSplitItem",
3008
+ description: "Libera uma fatia (pending/awaiting_nota/failed \u2192 released), apta a virar payout.",
3009
+ security: [{ ApiKeyAuth: ["split:update"] }],
3010
+ responses: { "200": { description: "Liberada", content: { "application/json": { schema: { type: "object", properties: { id: { type: "string" }, status: { type: "string" } } } } } }, "404": errorResponse("Fatia n\xE3o encontrada"), ...COMMON_ERRORS }
3011
+ }
3012
+ },
3013
+ // -----------------------------------------------------------------------
2258
3014
  // Formas de pagamento do fornecedor
2259
3015
  // -----------------------------------------------------------------------
2260
3016
  "/suppliers/{id}/payment-methods": {
@@ -2310,7 +3066,7 @@ var OPENAPI_SPEC = {
2310
3066
  ...PAGINATION_PARAMS,
2311
3067
  { name: "active", in: "query", schema: { type: "string", enum: ["true", "false"] } },
2312
3068
  { name: "provider", in: "query", schema: { type: "string", enum: ["inter", "c6bank"] } },
2313
- { name: "channel", in: "query", schema: { type: "string", enum: ["pix", "boleto", "checkout"] } }
3069
+ { name: "channel", in: "query", schema: { type: "string", enum: ["pix", "boleto", "checkout", "credit_card"] } }
2314
3070
  ],
2315
3071
  responses: { "200": paginatedResponse("#/components/schemas/PaymentMethod"), ...COMMON_ERRORS }
2316
3072
  }
@@ -2350,7 +3106,7 @@ var API_MODULES = [
2350
3106
  permissions: [
2351
3107
  { key: "read", label: "Listar e visualizar", description: "Consultar propostas comerciais" },
2352
3108
  { key: "write", label: "Criar e editar", description: "Criar e editar propostas" },
2353
- { key: "send", label: "Enviar", description: "Enviar propostas por e-mail ou WhatsApp" },
3109
+ { key: "send", label: "Enviar", description: "Enviar propostas por e-mail" },
2354
3110
  { key: "delete", label: "Excluir", description: "Excluir propostas" }
2355
3111
  ]
2356
3112
  },
@@ -2360,7 +3116,8 @@ var API_MODULES = [
2360
3116
  permissions: [
2361
3117
  { key: "read", label: "Listar e visualizar", description: "Consultar faturas e cobran\xE7as" },
2362
3118
  { key: "create", label: "Criar cobran\xE7a", description: "Gerar boletos, Pix e cobran\xE7as" },
2363
- { key: "cancel", label: "Cancelar cobran\xE7a", description: "Cancelar cobran\xE7as em aberto" }
3119
+ { key: "cancel", label: "Cancelar cobran\xE7a", description: "Cancelar cobran\xE7as em aberto" },
3120
+ { key: "delete", label: "Excluir fatura", description: "Excluir faturas permanentemente (itens e cobran\xE7as vinculadas)" }
2364
3121
  ]
2365
3122
  },
2366
3123
  {
@@ -2458,6 +3215,33 @@ var API_MODULES = [
2458
3215
  { key: "create", label: "Pagar / agendar", description: "Executar ou agendar pagamentos Pix e boleto a fornecedores" },
2459
3216
  { key: "cancel", label: "Cancelar agendamento", description: "Cancelar pagamentos agendados" }
2460
3217
  ]
3218
+ },
3219
+ {
3220
+ key: "split",
3221
+ label: "Split de Pagamentos",
3222
+ permissions: [
3223
+ { key: "list", label: "Listar e visualizar", description: "Consultar regras, execu\xE7\xF5es e repasses de split" },
3224
+ { key: "create", label: "Criar regra", description: "Criar regras de divis\xE3o de recebimentos" },
3225
+ { key: "update", label: "Atualizar / liberar", description: "Editar regras, liberar fatias e estornar repasses" },
3226
+ { key: "delete", label: "Excluir regra", description: "Remover regras de split" }
3227
+ ]
3228
+ },
3229
+ {
3230
+ key: "audit",
3231
+ label: "Auditoria",
3232
+ permissions: [
3233
+ { key: "read", label: "Consultar hist\xF3rico", description: "Consultar a timeline de altera\xE7\xF5es de uma entidade (audit_logs)" }
3234
+ ]
3235
+ },
3236
+ {
3237
+ key: "reminders",
3238
+ label: "Lembretes",
3239
+ permissions: [
3240
+ { key: "list", label: "Listar e visualizar", description: "Consultar lembretes e resumos agendados" },
3241
+ { key: "create", label: "Criar", description: "Criar lembretes e resumos recorrentes da empresa" },
3242
+ { key: "update", label: "Atualizar / pausar", description: "Editar, ativar e pausar lembretes" },
3243
+ { key: "delete", label: "Excluir", description: "Excluir lembretes" }
3244
+ ]
2461
3245
  }
2462
3246
  ];
2463
3247
  var ALL_SCOPES = API_MODULES.flatMap(
@@ -2726,7 +3510,8 @@ function buildRequestTool(api) {
2726
3510
  body: { type: "object", description: "Corpo JSON (para POST/PATCH/PUT).", additionalProperties: true },
2727
3511
  company_id: { type: "string", description: "Opcional: UUID da empresa (header X-Company-Id)." },
2728
3512
  idempotency_key: { type: "string", description: "Opcional: chave de idempot\xEAncia (POST)." },
2729
- dry_run: { type: "boolean", description: "Se true, n\xE3o executa \u2014 s\xF3 mostra o que seria enviado." }
3513
+ dry_run: { type: "boolean", description: "Se true, n\xE3o executa \u2014 s\xF3 mostra o que seria enviado." },
3514
+ confirm: { type: "boolean", description: "Obrigat\xF3rio para DELETE: confirma a exclus\xE3o." }
2730
3515
  }
2731
3516
  },
2732
3517
  handler: async (args) => {
@@ -2735,6 +3520,11 @@ function buildRequestTool(api) {
2735
3520
  if (!METHODS.includes(method)) {
2736
3521
  return fail(`M\xE9todo inv\xE1lido: ${args.method}. Use um de: ${METHODS.join(", ")}.`);
2737
3522
  }
3523
+ if (method === "DELETE" && args.confirm !== true && args.dry_run !== true) {
3524
+ return fail(
3525
+ "A\xE7\xE3o destrutiva bloqueada. Passe confirm: true para executar, ou dry_run: true para pr\xE9-visualizar."
3526
+ );
3527
+ }
2738
3528
  let path = String(args.path ?? "");
2739
3529
  if (!path.startsWith("/")) return fail("path deve come\xE7ar com / (ex.: /customers).");
2740
3530
  if (args.query && typeof args.query === "object") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comando.one/mcp-server",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "Servidor MCP (Model Context Protocol) para a API pública do Comando.One — opere seu ERP por linguagem natural.",
5
5
  "type": "module",
6
6
  "license": "MIT",