Skip to content

Audit/asaas api conformance - #1

Merged
cloviscoli merged 78 commits into
masterfrom
audit/asaas-api-conformance
May 25, 2026
Merged

Audit/asaas api conformance#1
cloviscoli merged 78 commits into
masterfrom
audit/asaas-api-conformance

Conversation

@cloviscoli

Copy link
Copy Markdown
Contributor

This pull request introduces significant improvements to the SDK's quality assurance, compliance, and CI/CD processes. The main highlights are the addition of a comprehensive compliance audit against the official Asaas API, improvements to test reliability and coverage, and enhancements to developer workflow through better test organization and documentation.

Compliance and Documentation:

  • Added a detailed compliance audit (AUDIT.md) comparing the SDK's implementation to the official Asaas API documentation, identifying coverage gaps, critical bugs, and providing a prioritized roadmap for fixes and new features.
  • Introduced .mcp.json to reference the official Asaas API documentation for automated or manual compliance checks.

Testing and CI/CD Improvements:

  • Updated .github/workflows/ci.yml to filter out integration tests from the main test run unless the required ASAAS_SANDBOX_TOKEN is present, ensuring that only unit and contract tests run by default, increasing reliability for contributors without sandbox credentials.
  • Added a new workflow .github/workflows/integration-sandbox.yml to run real integration tests against the Asaas sandbox API, triggered manually or on a nightly schedule, and separated from regular PR checks.
  • Ensured test fixture JSON files are copied to the output directory for use in contract tests, improving test reproducibility and coverage. (Codout.Apis.Asaas.Tests.csproj)

Codebase Quality:

  • Fixed a typo in the sample code, updating WasSucessfull() to the correct WasSuccessful() method, aligning with naming best practices. (Codout.Apis.Asaas.Sample/Program.cs)

cloviscoli added 30 commits May 24, 2026 14:07
Adiciona AUDIT.md com a comparacao completa do SDK contra a API oficial do
Asaas (via MCP em docs.asaas.com/mcp) e IMPLEMENTATION_PLAN.md com a
sequencia de 26 commits para fechar a conformidade.

Tambem inclui .mcp.json com type=http explicito para que o servidor MCP
do Asaas carregue corretamente no Claude Code.
A API oficial documenta PUT nos seguintes endpoints, mas o SDK estava
enviando POST, fazendo com que toda atualizacao falhasse silenciosamente
(boa parte das chamadas era aceita pela API e processada como criacao
ou retornava 404).

Corrigido em:
- CustomerManager.Update
- PaymentManager.Update
- SubscriptionManager.Update
- SubscriptionManager.UpdateInvoiceSettings
- NotificationManager.Update
- NotificationManager.BatchUpdate

PaymentLinkManager.Update e InvoiceManager.Update ja estavam corretos.

Testes existentes ajustados para validar HttpMethod.Put.
BREAKING CHANGE: CustomerFiscalInfoManager renomeado para FiscalInfoManager
e a propriedade asaas.CustomerFiscalInfo renomeada para asaas.FiscalInfo.

A rota usada pelo SDK era /v3/customerFiscalInfo, mas o endpoint correto
e /v3/fiscalInfo. Todas as 3 operacoes antigas retornavam 404.

Tambem corrige:
- Move ListMunicipalServices de InvoiceManager para FiscalInfoManager
  (rota correta: /v3/fiscalInfo/services, nao /v3/invoices/municipalServices)
- Renomeia campo MunicipalService.Iss para IssTax conforme schema da API
- Move MunicipalService de Models.Invoice para Models.FiscalInfo
- Renomeia classes CustomerFiscalInfo -> FiscalInfo,
  CreateCustomerFiscalInfoRequest -> CreateFiscalInfoRequest
- Renomeia namespace Models.CustomerFiscalInfo -> Models.FiscalInfo

Migracao:
- asaas.CustomerFiscalInfo.X -> asaas.FiscalInfo.X
- CustomerFiscalInfo -> FiscalInfo (model)
- CreateCustomerFiscalInfoRequest -> CreateFiscalInfoRequest
- Manager.ListMunicipalServices(desc) -> asaas.FiscalInfo.ListServices(desc)

Todos os 400 testes existentes continuam verdes apos a renomeacao.
BREAKING CHANGE: FinanceManager.Balance() (retornando decimal) renomeado
para GetBalance() retornando ResponseObject<Balance>.

A API documenta resposta como objeto { "balance": 5210.96 }, mas o SDK
tentava deserializar como decimal direto, o que falhava silenciosamente
e retornava 0.

Adiciona novo tipo Models/Finance/Balance.cs com propriedade Value
mapeada via JsonPropertyName("balance").

Migracao:
- decimal saldo = (await asaas.Finance.Balance()).Data;
+ decimal saldo = (await asaas.Finance.GetBalance()).Data.Value;
BREAKING CHANGE: AnticipationManager.SignAgreement(...) removido.

O metodo chamava POST /v3/anticipations/agreement/sign, mas esse endpoint
nao existe na documentacao oficial atual da API. Confirmado via busca no
MCP do Asaas (mcp__asaas__search-endpoints com pattern 'agreement' nao
retorna nada). Provavelmente foi um endpoint removido ou que nunca
existiu no v3.

Tambem remove o model SignAnticipationAgreementRequest e os testes
associados.

Migracao: nao ha substituto direto. Se voce precisa assinar o termo de
antecipacao, isso e feito pelo painel web do Asaas (1x por conta).
Adiciona os endpoints documentados que faltavam:
- POST /v3/installments         -> Create(CreateInstallmentRequest)
- POST /v3/installments/        -> CreateWithCreditCard(...)
  (path com barra final = endpoint separado para cartao de credito)
- GET  /v3/installments/{id}/payments -> ListPayments(...)
- DELETE /v3/installments/{id}/payments -> CancelPendingPayments(...)
- PUT  /v3/installments/{id}/splits -> UpdateSplits(...)

Tambem expande Installment.cs (response model) com campos faltantes:
- object, dateCreated, checkoutSession

Adiciona modelos:
- CreateInstallmentRequest
- CreateInstallmentWithCreditCardRequest (herda do anterior + cartao)
- InstallmentSplitRequest
- UpdateInstallmentSplitsRequest

10 testes novos cobrindo happy path, serializacao e erro.
BREAKING CHANGE: WebhookManager foi totalmente reescrito.

O modelo antigo (/webhook singular com paths /webhook/invoice e
/webhook/mobilePhoneRecharge) ja nao existe na API. Agora ha um
recurso CRUD generico em /v3/webhooks/{id} onde cada webhook tem
seu proprio id, nome, lista de eventos e tipo de envio.

Novo API:
- Create(CreateWebhookRequest)       -> POST   /v3/webhooks
- List(offset, limit, filter)        -> GET    /v3/webhooks
- Find(id)                           -> GET    /v3/webhooks/{id}
- Update(id, UpdateWebhookRequest)   -> PUT    /v3/webhooks/{id}
- Delete(id)                         -> DELETE /v3/webhooks/{id}
- RemoveBackoff(id)                  -> POST   /v3/webhooks/{id}/removeBackoff

Modelos adicionados:
- Webhook (com Id, Name, HasAuthToken, SendType, PenalizedRequestsCount, Events)
- CreateWebhookRequest, UpdateWebhookRequest, WebhookListFilter
- Enum WebhookSendType (SEQUENTIALLY, NON_SEQUENTIALLY)
- Enum WebhookEvent (~100 valores conforme API: PAYMENT_*, INVOICE_*,
  TRANSFER_*, BILL_*, RECEIVABLE_ANTICIPATION_*, MOBILE_PHONE_RECHARGE_*,
  ACCOUNT_STATUS_*, SUBSCRIPTION_*, CHECKOUT_*, BALANCE_VALUE_*,
  INTERNAL_TRANSFER_*, ACCESS_TOKEN_*, PIX_AUTOMATIC_RECURRING_*)

Modelos removidos:
- WebhookRequest (substituido por CreateWebhookRequest e UpdateWebhookRequest)

Metodos publicos removidos:
- CreateOrUpdatePaymentWebhook
- FindPaymentWebhook
- CreateOrUpdateInvoiceWebhook
- FindInvoiceWebhook
- CreateOrUpdateMobilePhoneRechargeWebhook
- FindMobilePhoneRechargeWebhook

Migracao: agora voce gerencia webhooks individualmente. Para receber
eventos de pagamento, crie um Webhook com Events=[PAYMENT_CONFIRMED,
PAYMENT_RECEIVED, ...]. Para receber eventos de NF-e use INVOICE_*, etc.
Endpoints novos:
- POST /v3/payments/                        -> CreateWithCreditCard
- POST /v3/payments/{id}/captureAuthorizedPayment -> CaptureAuthorizedPayment
- POST /v3/payments/{id}/payWithCreditCard  -> PayWithCreditCard
- GET  /v3/payments/{id}/billingInfo        -> GetBillingInfo
- GET  /v3/payments/{id}/viewingInfo        -> GetViewingInfo
- GET  /v3/payments/{id}/status             -> GetStatus
- POST /v3/payments/simulate                -> Simulate
- GET  /v3/payments/limits                  -> GetLimits
- POST /v3/payments/{id}/documents          -> UploadDocument (multipart)
- GET  /v3/payments/{id}/documents          -> ListDocuments
- GET  /v3/payments/{id}/documents/{docId}  -> FindDocument
- PUT  /v3/payments/{id}/documents/{docId}  -> UpdateDocument
- DELETE /v3/payments/{id}/documents/{docId} -> DeleteDocument
- GET  /v3/payments/{id}/refunds            -> ListRefunds
- POST /v3/payments/{id}/bankSlip/refund    -> RefundBankSlip

Models novos: PaymentDocument, UploadPaymentDocumentRequest,
UpdatePaymentDocumentRequest, PaymentBillingInfo (+CreditCard/Pix/BankSlip),
PaymentViewingInfo, PaymentStatusInfo, SimulatePaymentRequest,
SimulatedPayment, PaymentLimits (+Item), PaymentRefund,
CapturePaymentRequest, PayWithCreditCardRequest, ReceiveInCashRequest,
PaymentCallback.

Models alterados:
- PaymentStatus: adicionado valor REFUND_IN_PROGRESS
- CreatePaymentRequest: adicionados Callback, PixAutomaticAuthorizationId,
  DaysAfterDueDateToRegistrationCancellation

ReceiveInCash agora usa o tipo ReceiveInCashRequest (era RequestParameters
inline) para garantir contrato tipado.

17 testes novos cobrindo cada endpoint.
PUT /v3/subscriptions/{id}/creditCard - atualiza dados do cartao da
assinatura sem efetuar nova cobranca.

Novo model: UpdateSubscriptionCreditCardRequest (com CreditCardRequest,
CreditCardHolderInfoRequest, CreditCardToken e RemoteIp).
Endpoints adicionados:
- POST /v3/anticipations/{id}/cancel        -> Cancel
- GET  /v3/anticipations/limits             -> GetLimits
- GET  /v3/anticipations/configurations     -> GetAutomaticConfiguration
- PUT  /v3/anticipations/configurations     -> UpdateAutomaticConfiguration

Models novos:
- AnticipationLimits + AnticipationLimitsItem (separados por bankSlip/creditCard)
- AutomaticAnticipationConfig + UpdateAutomaticAnticipationConfigRequest
Endpoints adicionados:
- POST /v3/creditCard/preAuthorization/config -> SavePreAuthorizationConfig
- GET  /v3/creditCard/preAuthorization/config -> GetPreAuthorizationConfig

Pre-autorizacao permite reservar valor no cartao sem capturar
imediatamente, com captura automatica apos N dias se nao for
capturada manualmente (via captureAuthorizedPayment).

Models novos:
- PreAuthorizationConfig (response: Enabled, AutomaticCaptureDelay)
- SavePreAuthorizationConfigRequest (request)
BREAKING CHANGE: TransferManager.Execute(...) sobrecarregado foi
substituido por dois metodos com nomes claros:
- TransferToBankAccount(BankAccountTransferRequest) -> POST /v3/transfers
- TransferToAsaasAccount(AsaasAccountTransferRequest) -> POST /v3/transfers/
  (path com barra final = endpoint separado para conta Asaas)

Antes, os dois overloads de Execute postavam para /v3/transfers,
fazendo a transferencia entre contas Asaas falhar com 400 ou ser
tratada como transferencia externa.

Adicionado:
- Cancel(transferId) -> DELETE /v3/transfers/{id}/cancel

Migracao:
- asaas.Transfer.Execute(asaasReq)  -> asaas.Transfer.TransferToAsaasAccount(asaasReq)
- asaas.Transfer.Execute(bankReq)   -> asaas.Transfer.TransferToBankAccount(bankReq)
…KeyTokenBucket

Endpoints adicionados:
- GET    /v3/pix/transactions/{id}        -> FindTransaction
- DELETE /v3/pix/qrCodes/static/{id}      -> DeleteStaticQrCode
- GET    /v3/pix/tokenBucket/addressKey   -> GetAddressKeyTokenBucket

Model novo: PixAddressKeyTokenBucket (RemainingTokens, MaxTokens).
BREAKING CHANGE: MyAccountManager.Find() removido. Antes apontava para
/v3/myAccount, mas esse endpoint na verdade e DELETE (excluir subconta
white label). O equivalente para recuperar dados comerciais agora e
GetCommercialInfo() apontando para /v3/myAccount/commercialInfo.

Endpoints adicionados:
- GET   /v3/myAccount/commercialInfo  -> GetCommercialInfo (substitui Find)
- POST  /v3/myAccount/commercialInfo  -> UpdateCommercialInfo
- GET   /v3/myAccount/status          -> GetStatus
- DELETE /v3/myAccount                -> DeleteWhiteLabelAccount
- GET   /v3/myAccount/documents       -> ListPendingDocuments
- POST  /v3/myAccount/documents/{id}  -> SubmitDocument (multipart)
- GET   /v3/myAccount/documents/files/{id}    -> ViewDocumentFile
- POST  /v3/myAccount/documents/files/{id}    -> UpdateDocumentFile (multipart)
- DELETE /v3/myAccount/documents/files/{id}   -> DeleteDocumentFile

Models novos: UpdateCommercialInfoRequest, AccountStatus,
AccountDocumentSection, AccountDocument, AccountDocumentFile,
UploadAccountDocumentRequest.

Migracao: asaas.MyAccount.Find() -> asaas.MyAccount.GetCommercialInfo()
Endpoints adicionados:
- GET    /v3/accounts/{id}                              -> Find
- POST   /v3/accounts/{id}/resendActivationLink         -> ResendActivationLink
- POST   /v3/accounts/{id}/accessTokens                 -> CreateAccessToken
- GET    /v3/accounts/{id}/accessTokens                 -> ListAccessTokens
- PUT    /v3/accounts/{id}/accessTokens/{tokenId}       -> UpdateAccessToken
- DELETE /v3/accounts/{id}/accessTokens/{tokenId}       -> DeleteAccessToken

Models novos:
- AccessToken (Id, Name, Token, ApiKey, CreationDate, ExpirationDate, Enabled)
- CreateAccessTokenRequest, UpdateAccessTokenRequest
Novo dominio Chargeback com 3 endpoints:
- GET  /v3/chargebacks                       -> List
- GET  /v3/payments/{id}/chargeback          -> FindByPayment
- POST /v3/chargebacks/{id}/dispute          -> CreateDispute (multipart)

Models: Chargeback, CreateChargebackDisputeRequest e enums
ChargebackStatus, ChargebackReason (32 valores), ChargebackDisputeStatus.

Exposto via asaas.Chargeback.
Novo dominio Escrow (Conta de Garantia) com 6 endpoints:
- POST /v3/accounts/{id}/escrow      -> SaveSubaccountConfig
- GET  /v3/accounts/{id}/escrow      -> GetSubaccountConfig
- POST /v3/accounts/escrow           -> SaveDefaultConfig
- GET  /v3/accounts/escrow           -> GetDefaultConfig
- POST /v3/escrow/{id}/finish        -> FinishPaymentEscrow
- GET  /v3/payments/{id}/escrow      -> GetPaymentEscrow

Models: Escrow, EscrowConfig, SaveEscrowConfigRequest, FinishEscrowRequest.

Exposto via asaas.Escrow.
Dominio Checkout (links de checkout customizado) com 2 endpoints:
- POST /v3/checkouts                 -> Create
- POST /v3/checkouts/{id}/cancel     -> Cancel

Models: Checkout, CreateCheckoutRequest, CheckoutCustomerData,
CheckoutCallback.

Exposto via asaas.Checkout.
Dominio Recarga de Celular com 5 endpoints:
- POST /v3/mobilePhoneRecharges                          -> Create
- GET  /v3/mobilePhoneRecharges                          -> List
- GET  /v3/mobilePhoneRecharges/{id}                     -> Find
- POST /v3/mobilePhoneRecharges/{id}/cancel              -> Cancel
- GET  /v3/mobilePhoneRecharges/{phoneNumber}/provider   -> GetProvider

Models: MobilePhoneRecharge, CreateMobilePhoneRechargeRequest,
MobilePhoneProvider.

Exposto via asaas.MobilePhoneRecharge.
Endpoints adicionados em PaymentManager:
- GET /v3/payments/splits/paid           -> ListPaidSplits
- GET /v3/payments/splits/paid/{id}      -> FindPaidSplit
- GET /v3/payments/splits/received       -> ListReceivedSplits
- GET /v3/payments/splits/received/{id}  -> FindReceivedSplit

Model novo: PaymentSplitView (visualizacao de split com Id, Payment,
WalletId, FixedValue, PercentualValue, TotalValue, Status, CreditDate,
ExternalReference, Description).
Helpers oficiais que so funcionam em AsaasEnvironment.SANDBOX:
- POST /v3/sandbox/myAccount/approve         -> ApproveAccount
- POST /v3/sandbox/payment/{id}/confirm      -> ConfirmPayment
- POST /v3/sandbox/payment/{id}/overdue      -> ForceOverdue

Em producao todos lancam InvalidOperationException antes de fazer
qualquer chamada HTTP, garantindo que dados reais nao sejam afetados
por um erro de configuracao.

Exposto via asaas.Sandbox.
Dominio Pix Automatico (recorrencia Bacen) com 6 endpoints:
- POST   /v3/pix/automatic/authorizations         -> CreateAuthorization
- GET    /v3/pix/automatic/authorizations         -> ListAuthorizations
- GET    /v3/pix/automatic/authorizations/{id}    -> FindAuthorization
- DELETE /v3/pix/automatic/authorizations/{id}    -> CancelAuthorization
- GET    /v3/pix/automatic/paymentInstructions/{id} -> FindPaymentInstruction
- GET    /v3/pix/automatic/paymentInstructions      -> ListPaymentInstructions

Models: PixAutomaticAuthorization, CreatePixAutomaticAuthorizationRequest,
PixAutomaticAuthorizationListFilter, PixAutomaticPaymentInstruction,
PixAutomaticPaymentInstructionListFilter.

Exposto via asaas.PixAutomatic.
Dominio Pix Recorrente (parcelado no Pix) com 5 endpoints:
- GET    /v3/pix/transactions/recurrings                       -> List
- GET    /v3/pix/transactions/recurrings/{id}                  -> Find
- POST   /v3/pix/transactions/recurrings/{id}/cancel           -> Cancel
- GET    /v3/pix/transactions/recurrings/{id}/items            -> ListItems
- POST   /v3/pix/transactions/recurrings/items/{id}/cancel     -> CancelItem

Models: PixRecurringTransaction, PixRecurringItem.

Exposto via asaas.PixRecurring.
Adicionado em Customer (response):
- Object (sempre "customer")
- CityName
- StateInscription
- Company
- GroupName
- ForeignCustomer

Tambem convertido Deleted e NotificationDisabled para bool? (a API
pode omitir esses campos).

Adicionado em CreateCustomerRequest: Company, ForeignCustomer.
Adicionado em UpdateCustomerRequest: GroupName, Company, ForeignCustomer.
Adicionados em Payment (response):
- Object, PixTransaction, PixQrCodeId, CheckoutSession, PaymentLinkId
  (com [JsonPropertyName(\"paymentLink\")]), InstallmentNumber, CreditDate,
  EstimatedCreditDate, TransactionReceiptUrl, NossoNumero, Anticipable,
  CanBePaidAfterDueDate, DaysAfterDueDateToRegistrationCancellation.

Convertidos para nullable (a API pode omitir):
- Deleted, PostalService, Anticipated.

Os 478 testes existentes continuam verdes apos as mudancas.
…icoes

BaseManager criava um novo HttpClient (e por consequencia um novo
SocketsHttpHandler) a cada chamada HTTP. Isso causava esgotamento de
sockets (TIME_WAIT) em apps que fazem muitas chamadas ao Asaas e
forcava DNS lookup a cada request.

Agora HttpClient continua sendo criado per-request (BuildHttpClient
ainda eh virtual para overrides de teste), mas o SocketsHttpHandler eh
estatico/compartilhado com:
- PooledConnectionLifetime: 10 min (capta mudancas de DNS)
- PooledConnectionIdleTimeout: 2 min
- MaxConnectionsPerServer: 32

HttpClient eh construido com disposeHandler:false para nao descartar o
handler compartilhado a cada request.

Solucao mais simples que IHttpClientFactory, mantem mesmo contrato
publico e o padrao de testes (TestableManager override). 478 testes
continuam verdes.
Adiciona o metodo WasSuccessful() com a grafia correta no BaseResponse,
mantendo WasSucessfull() como alias [Obsolete] para nao quebrar codigo
existente. Sera removido em versao futura.

Uso interno (BuildErrors) atualizado para a nova grafia.
Encerramento da auditoria de conformidade do SDK contra a documentacao
oficial da API Asaas (via MCP). Cobertura passou de ~45% para 100% dos
endpoints documentados.

Major release com breaking changes: PUT em Updates, FiscalInfoManager
renomeado, Webhook reescrito, Transfer overloads separados, MyAccount
.Find -> GetCommercialInfo, Finance.Balance shape, e mais.

7 novos managers: Chargeback, Escrow, Checkout, MobilePhoneRecharge,
Sandbox, PixAutomatic, PixRecurring.

~50 endpoints novos em managers existentes.

Suite de testes: 478 testes (em Release config).

Veja CHANGELOG.md para a lista completa de breaking changes e guia de
migracao 2.x -> 3.x, e AUDIT.md / IMPLEMENTATION_PLAN.md para o
historico da auditoria.
Grupo 1 dos achados da revisao:

- B-01: corrige NRE em PostMultipartFormDataContentAsync para
  propriedades nulas (afetava PaymentManager.UploadDocument
  com Available=null e ChargebackManager.CreateDispute com Description=null).

- B-08: PaymentBillingInfo.BankSlip.Nossonumero (grafia errada)
  renomeado para NossoNumero, e adicionados campos do schema:
  BankSlipUrl, DaysAfterDueDateToRegistrationCancellation no BankSlip,
  Description no Pix.

- B-05: MobilePhoneRecharge agora usa OperatorName (era Provider) e
  expoe CanBeCancelled. Removidos campos inventados DateCreated e
  ConfirmedDate. Status convertido para enum MobilePhoneRechargeStatus
  (PENDING/CONFIRMED/CANCELLED/REFUNDED/WAITING_CRITICAL_ACTION) conforme doc.

- I-04: Installment.Deleted convertido para bool? para alinhar com a
  mesma migracao feita em Customer e Payment durante o PR.

Teste novo cobrindo deserializacao de operatorName/canBeCancelled
e status enum no MobilePhoneRecharge.

Achados B-01, B-05, B-08 foram detectados via leitura do schema oficial
do Asaas via MCP apos a revisao do code-reviewer.
…latedPayment

Grupo 2 dos achados da revisao (B-02, B-03):

PaymentLimits estava completamente errado. Schema real:
{ creation: { daily: { limit, used, wasReached } } }
Estava: { creditCard, pix, bankSlip } cada um com daily/monthly/averageTicket.

SimulatePaymentRequest tinha BillingType (singular) e campos inventados
(DiscountValue, Splits). API requer billingTypes (lista) + value, com
installmentCount opcional.

SimulatedPayment era flat com Fee/NetValue/InstallmentValue. API retorna
estrutura aninhada com creditCard, bankSlip, pix, cada um com seus
proprios netValue/feePercentage/feeValue/operationFee/installment.

Testes do Simulate e GetLimits atualizados para o novo shape. 56 testes
do PaymentManager continuam verdes.
cloviscoli added 29 commits May 24, 2026 20:11
Fase 3g da auditoria schema-first contra MCP oficial. BREAKING CHANGE.

Bugs criticos corrigidos (B-20):
- B-20a/b/c/d: AccountDocument.Status, AccountDocumentGroup.Status,
  AccountDocumentGroup.Type, AccountDocumentResponsible.Type eram string
  ou List<string>. Trocados por enums tipados:
  - AccountDocumentStatus (4 valores)
  - AccountDocumentGroupStatus (5 valores: ganha IGNORED)
  - AccountDocumentType (12 valores)
  - AccountDocumentResponsibleType (13 valores)

- B-20f: AccountDocumentFile tinha campos ficticios Name e Url. Schema
  real retorna apenas {id, status}. Classe REMOVIDA.

- B-20g: SubmitDocument retornava AccountDocumentGroup (objeto rico).
  Schema retorna AccountDocumentGetResponseDTO {id, status}. Tipo
  de retorno mudado para AccountDocument.

- B-20h: UploadAccountDocumentRequest tinha DocumentType: string e
  File: IAsaasFile. Schema espera multipart fields "type" e
  "documentFile". Renomeado para Type: AccountDocumentType? e
  DocumentFile: IAsaasFile (FirstCharToLower do BaseManager casa).

Contract tests (8 novos):
- Envelope minimalista {rejectReasons, data:[]} (B-07 regression)
- Document response shape {id, status} (B-20f regression)
- Todos os 4+5+12+13 valores de enums (4 testes parametrizados)
- Multipart field names via reflexao (B-20h regression)

Test antigo MyAccountManagerTests.ViewDocumentFile atualizado para
usar shape correto.

Fixtures criadas a partir dos exemplos oficiais MCP em 2026-05-24.

Total: 562 testes passando (+8 desta fase).
Fase 3h da auditoria schema-first contra MCP oficial.

Bugs corrigidos (B-21):
- B-21a: Taxes model tinha apenas 7 campos. Schema InvoiceTaxesResponseDTO
  tem 19 (incluindo nbsCode, taxSituationCode, taxClassificationCode,
  operationIndicatorCode, pisCofinsRetentionType, pisCofinsTaxStatus +
  6 da Reforma Tributaria: stateIbs/value, municipalIbs/value, cbs/value).
  Adicionados todos os campos faltantes (nullable para opcionais).

- B-21b: InvoiceListFilter usava effectiveDate[ge] e [le] lowercase.
  Schema oficial usa [Ge] e [Le] maiusculos. Filtro era silenciosamente
  ignorado pela API com casing errado. Corrigido.

- B-21c: InvoiceListFilter faltava customer e externalReference (ambos
  no schema). Adicionados.

- B-21d: CreateInvoiceRequest e UpdateInvoiceRequest faltavam
  updatePayment: bool? (presente em ambos schemas). Adicionado.

Contract tests (9 novos):
- Create request: required keys, payment vs paymentId, updatePayment
- Update request: updatePayment
- Invoice response: shape completa
- Taxes response: TODOS os 19 campos (incluindo Reforma Tributaria)
- Status enum (6 valores)
- Filter: capital Ge/Le casing (B-21b regression)
- Filter: customer + externalReference (B-21c regression)

Total: 571 testes passando (+9 desta fase).
Fase 3i da auditoria schema-first contra MCP oficial.

Bugs corrigidos (B-22):
- B-22a: DunningNumber era string. Schema integer. -> int?
- B-22b: PaymentDunning faltava CannotBeCancelledReason. Adicionado.
- B-22c/d: CanBeCancelled e IsNecessaryResendDocumentation eram bool
  non-nullable. Schema permite null. Sem o fix, omissao forcava false
  silenciosamente. -> bool?
- B-22e: ReceivedInCashFeeValue/CancellationFeeValue marcados [Obsolete]
  (schema oficial: deprecated).
- B-22f: PaymentDunningEventHistory.Status era string. Schema e enum
  PaymentDunningHistoryStatus (IN_NEGOTIATION, NEGOTIATION_FAIL,
  NEGOTIATED, PAID). -> enum tipado.
- B-22h: PaymentDunningType enum tinha apenas CREDIT_BUREAU. Filter
  aceita tambem DEBT_RECOVERY_ASSISTANCE. Adicionado.
- B-22k: Simulate(request) enviava payment no body JSON. Schema oficial
  expoe como QUERY param (?payment=pay_xxx) e exige body vazio.
  Manager corrigido para construir query string.
- B-22m: SimulatedPaymentDunning.TypeSimulations e
  PaymentDunningPaymentAvailable.TypeSimulations eram objeto unico.
  Schema retorna ARRAY. Sem o fix, deserializacao lancava
  InvalidCastException no JSON real. -> List<PaymentDunningTypeSimulations>

Contract tests (12 novos):
- Dunning response shape + nullable bool handling
- Standard envelope com paginacao
- Status enum (8), Type enum (2), HistoryStatus enum (4)
- History event response + status enum coverage
- Partial payments response
- Payments available for dunning response
- Simulate response com array TypeSimulations (B-22m regression)
- Create request: payment vs paymentId
- List filter com todos os 5 campos

Tests antigos do manager atualizados:
- DunningNumber: "DUN001" -> 15 (int)
- History: status "CREATED" -> "NEGOTIATED" (enum)
- Simulate: assert query param em vez de body
- Cancel: remover assert sobre CancellationFeeValue (deprecated)

Total: 583 testes passando (+12 desta fase).
Fase 3j da auditoria schema-first contra MCP oficial. BREAKING CHANGE.

Bugs corrigidos (B-23):
- B-23a/b: CreditBureauReport tinha State e Status (string). Nenhum
  dos dois existe no schema oficial. REMOVIDOS.
- B-23c: CreditBureauReport faltava DownloadUrl e ReportFile (PDF
  Base64). Adicionados. Sem o fix, consumidores nao tinham como baixar
  o relatorio retornado pelo POST.
- B-23d: CreateCreditBureauReportRequest.State removido (nao existe).
- B-23e: List(offset, limit) nao aceitava filtro. Schema expoe
  startDate e endDate. Criado CreditBureauReportListFilter e novo
  overload List(offset, limit, filter) backwards-compatible.

Contract tests (8 novos):
- Create request: apenas customer+cpfCnpj
- Create request: nao serializa state/status (B-23a/b regression)
- Response shape em GET (reportFile=null)
- Response shape em POST (reportFile populado com Base64)
- Response: garantir que schema nao expoe state/status
- List envelope padrao com paginacao
- Filter: startDate/endDate serializados como YYYY-MM-DD
- Filter: campos nullable sao omitidos

Tests antigos atualizados:
- CreditBureauReportManagerTests: substituir state/status por
  downloadUrl/reportFile
- SerializationTests: idem
- PaymentDunningManagerTests: remover assert sobre
  ReceivedInCashFeeValue (deprecated)

Total: 591 testes passando (+8 desta fase).
… (B-24)

Fase 3k da auditoria schema-first contra MCP oficial.

Bugs corrigidos (B-24):
- B-24a: BillPayment faltava Interest, Fine, PaymentDate,
  ExternalReference. FailReasons era string (nao fazia sentido);
  schema e array of string -> List<string>.
- B-24b: BillPaymentStatus enum tinha 5 valores. Schema tem 7:
  REFUNDED + AWAITING_CHECKOUT_RISK_ANALYSIS_REQUEST adicionados.
- B-24c: BillPayment.CanBeCancelled/DueDate/ScheduleDate/PaymentDate
  trocados para nullable (response pode omitir em status iniciais).
- B-24d: CreateBillPaymentRequest faltava Interest, Fine,
  ExternalReference. Campos opcionais (Value, DueDate, ScheduleDate,
  Discount) trocados para nullable (so IdentificationField e required).
- B-24e: BankSlipInfo tinha 5 campos com "BankCode" (chute). Schema
  tem 17 campos com "bank" + Beneficiary, MinValue/MaxValue,
  AllowChangeValue, discount/interest/fineValue, originalValue,
  totalDiscount/Additional, isOverdue. Modelo reescrito completo.

Contract tests (8 novos):
- Bill response shape com todos os campos novos
- failReasons como array (B-24a regression)
- Standard envelope com paginacao
- Status enum (7 valores - B-24b regression)
- Create request: serializa todos os 9 campos
- Create request: opcionais omitidos quando null
- SimulateResponse com BankSlipInfo completo (B-24e regression)
- SimulateRequest aceita identificationField OU barCode

Total: 599 testes passando (+8 desta fase).
Fase 4 da auditoria. Tests reais contra api-sandbox.asaas.com,
skip automatico sem ASAAS_SANDBOX_TOKEN.

Tests implementados:
- CustomerIntegrationTests.Create_Find_Update_Delete_RoundTrip: CRUD
  end-to-end com cleanup garantido.
- CustomerIntegrationTests.List_RespectsOffsetAndLimit: paginacao +
  envelope padrao validados contra API real.
- PaymentIntegrationTests.CreatePayment_Boleto: schema de criacao
  BOLETO via sandbox + cleanup do customer.
- PaymentIntegrationTests.CreatePayment_Pix: fluxo completo cobranca
  PIX -> GET /payments/{id}/pixQrCode (payload + encodedImage).
- PaymentIntegrationTests.ListPayments_WithAnticipatedFilter: garantia
  SISTEMICA de que bool? em filtro serializa lowercase (true vs True).
  Cobertura unit ja existe (RequestParametersContractTests), aqui
  validamos o end-to-end: API nao retorna 400 com casing correto.

Infraestrutura:
- IntegrationFactAttribute (custom): Skip automatico se ASAAS_SANDBOX_TOKEN
  ausente, com mensagem clara apontando como definir.
- IntegrationTestBase: Trait("Category", "Integration"), monta AsaasApi
  apontando para AsaasEnvironment.SANDBOX.

Cada test cria seus proprios recursos (suffix timestampado para evitar
colisao) e limpa no finally para nao poluir o sandbox.

Para rodar:
  $env:ASAAS_SANDBOX_TOKEN = "aact_..."
  dotnet test --filter "Category=Integration"

Para CI local (sem credencial):
  dotnet test --filter "Category!=Integration"

Total: 599 unit/contract passando, 5 integration skipped (executam
quando token disponivel).
Fase 5 quality sweep. SDK compila com 0 warnings agora (antes: 3).

- Fees.cs: ExpirationDate, DiscountExpiration (string? -> string)
- CreatePaymentRequest.cs: CreditCardToken (string? -> string)

Reference types ja sao nullable por padrao em projetos sem
#nullable enable habilitado. As anotacoes ? geravam warning
CS8632 sem ganho funcional. Comportamento ao consumidor inalterado.
Fase 6 — fechamento da auditoria schema-first.

CONFORMANCE.md:
- Status header atualizado: "FASES 1-6 CONCLUIDAS"
- Resumo: 599 testes unit/contract + 5 integration, 11 managers
  auditados, 24 familias de bugs corrigidas, 0 warnings
- Secao "Riscos remanescentes" preenchida com lista honesta do que
  NAO esta coberto (managers nao auditados schema-first, divergencias
  spec vs runtime, webhooks, Reforma Tributaria, deprecated fields)

CHANGELOG.md:
- Nova entrada [3.1.0] - 2026-05-24 listando todas as breaking changes
  e bugs corrigidos por manager (PaymentDunning, CreditBureauReport,
  BillPayment, Invoice, AccountDocument, MobilePhoneRecharge,
  PixAutomatic) + features adicionadas (CONFORMANCE.md, integration
  tests, contract tests, PixRecurringTransactionListFilter,
  Subscription.Cycle.BIMONTHLY) + fixes sistemicos (bool/decimal/
  DateTime culture-invariant)

README.md:
- Badge: 492 -> 599 testes + 5 integration + schema-first audit
- Versao 3.0.0 -> 3.1.0 com referencia a CONFORMANCE.md
- Secao Testes ampliada com instrucoes de integration test e como
  pular Integration no CI local
Fase 7 da auditoria final.

Bugs corrigidos (B-25):
- B-25a: Customer.DateCreated DateTime -> DateTime? (response pode
  omitir em casos de borda; antes deserializacao quebrava).
- B-25e: CreateCustomerRequest.NotificationDisabled e
  UpdateCustomerRequest.NotificationDisabled: bool -> bool?.
  Antes, todo Create/Update enviava notificationDisabled=false
  silenciosamente quando consumidor nao tocava no campo,
  potencialmente desabilitando notificacoes nao intencionalmente.
- B-25g: GetNotifications endpoint estava faltando no manager.
  Adicionado GET /v3/customers/{id}/notifications retornando
  ResponseList<Notification>.

Contract tests (8 novos):
- CreateRequest: apenas name+cpfCnpj required, full payload mapping
- UpdateRequest: NotificationDisabled nullable (B-25e regression)
- Customer response shape completo
- DateCreated nullable (B-25a regression)
- Lista com envelope padrao
- PersonType enum (FISICA/JURIDICA)
- Filter com todos os 5 campos

Total: 607 testes passando (+8 desta fase).
Fase 8 da auditoria final.

Bugs corrigidos (B-26):
- B-26a/b/c: Payment.DateCreated, DueDate, OriginalDueDate eram
  DateTime non-nullable. Trocados para DateTime? (response pode
  omitir; antes deserializacao quebrava).
- B-26d: PaymentListFilter faltava 9 filtros expostos no schema:
  customerGroupName, invoiceStatus, estimatedCreditDate, pixQrCodeId,
  anticipable, user, checkoutSession, dateCreated[ge]/[le],
  estimatedCreditDate[ge]/[le].

Confirmado em paralelo (NAO foram bugs, mas verificado):
- BillingType enum: 7 valores OK
- PaymentStatus enum: 14 valores OK
- Schema usa [ge]/[le] LOWERCASE em Payment (diferente de Invoice
  que usa [Ge]/[Le]). Filter pre-existente ja estava correto.

Contract tests (7 novos):
- Payment response shape completo
- Nullable dates handling (B-26a/b/c regression)
- List envelope padrao
- BillingType (7 valores) + PaymentStatus (14 valores)
- 9 novos filter fields serializam corretamente
- Date range filters com casing correto [ge]/[le]

Total: 614 unit/contract + 5 integration skip.
Fase 9 da auditoria final.

Bugs corrigidos (B-27):
- B-27a: SubscriptionStatus enum tinha apenas ACTIVE+EXPIRED.
  Schema tem 3 valores: adicionado INACTIVE.
- B-27b/c: Subscription.DateCreated e NextDueDate eram DateTime
  non-nullable. Trocados para DateTime?.
- B-27d: Subscription faltava Object, PaymentLinkId, CheckoutSession,
  Split (array). Adicionados.
- B-27e: SubscriptionListFilter faltava 6 campos do schema:
  customerGroupName, status (enum), deletedOnly (bool), externalReference,
  order, sort. Adicionados.

Contract tests (5 novos):
- Subscription response shape completo
- Nullable dates handling (B-27b/c regression)
- SubscriptionStatus enum 3 valores (B-27a regression)
- Cycle enum 7 valores
- ListFilter com todos os 9 campos
Fase 10 da auditoria final.

Bugs criticos corrigidos (B-28):
- B-28a: PixTransactionStatus enum estava QUEBRADO. Tinha 5 valores
  inventados (PENDING, DONE, CANCELLED, SCHEDULED, FAILED). Schema
  tem 11 valores reais; PENDING e FAILED nao existem. Adicionados:
  AWAITING_BALANCE_VALIDATION, AWAITING_INSTANT_PAYMENT_ACCOUNT_BALANCE,
  AWAITING_CRITICAL_ACTION_AUTHORIZATION, AWAITING_CHECKOUT_RISK_ANALYSIS_REQUEST,
  AWAITING_CASH_IN_RISK_ANALYSIS_REQUEST, AWAITING_REQUEST, REQUESTED, REFUSED.
  Sem o fix, deserializar JSON real lancava exception em qualquer
  transacao em estado de espera.

- B-28b: PixTransaction estava grosseiramente incompleto. Tinha 7
  campos; schema tem 25. Reescrito do zero. TransactionDate era
  nome inventado (correto: EffectiveDate). ScheduleDate era nome
  errado (correto: ScheduledDate, com 'd'). Adicionados todos os
  campos novos: endToEndIdentifier, finality (enum), changeValue,
  refundedValue, type (enum), originType (enum), conciliationIdentifier,
  transactionReceiptUrl, refusalReason, canBeCanceled, originalTransaction
  (objeto), externalAccount (objeto), qrCode (objeto), canBeRefunded,
  refundDisabledReason, chargedFeeValue, dateCreated, addressKey,
  addressKeyType, transferId, externalReference.

- B-28c: PixAddressKey.Status era string. Schema e enum
  PixAddressKeyStatus (6 valores). DateCreated era non-nullable.
  Faltavam CanBeDeleted, CannotBeDeletedReason, QrCode (objeto
  com encodedImage + payload). Corrigidos todos.

- B-28e: ListTransactions nao aceitava filtro. Schema expoe
  status, type, endToEndIdentifier. Criado PixTransactionListFilter
  e overload backwards-compatible.

Novos models/enums criados:
- Enums: PixTransactionType (5), PixTransactionOriginType (6),
  PixTransactionFinality (2), PixAddressKeyStatus (6)
- Models: PixTransactionExternalAccount, PixOriginalTransaction,
  PixTransactionQrCode (+ PixTransactionQrCodePayer),
  PixAddressKeyQrCode, PixTransactionListFilter

Contract tests (7 novos):
- Transaction response shape completo
- TransactionStatus 11 valores (B-28a regression)
- TransactionType 5 valores
- TransactionOriginType 6 valores
- AddressKey response com QrCode aninhado
- AddressKeyStatus 6 valores (B-28c regression)
- ListTransactions filter (B-28e regression)

Tests antigos atualizados:
- ResponseListTests: PENDING -> SCHEDULED
- SerializationTests: PixTransaction_Deserialize_WithEnum atualizado
  para usar effectiveDate/scheduledDate, AllStatuses lista valores
  reais do schema
- SerializationTests: PixAddressKey.Status assertion virou enum
- PixManagerTests: idem

Total: 626 unit/contract + 5 integration skip.
…atus

+ Bank/BankAccount/Filter (B-29)

Fase 11 da auditoria final.

Bugs corrigidos (B-29):
- B-29b/c: BaseTransfer.DateCreated e Authorized eram non-nullable.
  Trocados para DateTime? e bool?.
- B-29d: AsaasAccountTransferStatus tinha apenas 3 valores (PENDING,
  DONE, CANCELLED). Schema unifica todos os transfers no mesmo enum:
  PENDING, BANK_PROCESSING, DONE, CANCELLED, FAILED. Faltavam 2.
- B-29e: campo novo operationType (PIX/TED/INTERNAL) nao existia.
  Criado enum TransferOperationType e adicionado em BaseTransfer.
- B-29g: BaseTransfer faltava Object, NetValue (movido pra base),
  EndToEndIdentifier, FailReason, ExternalReference, Description,
  Recurring. Adicionados.
- B-29h: TransferListFilter usava dateCreated single. Schema expoe
  dateCreated[ge]/[le] e transferDate[ge]/[le]. Adicionados.
- Bank model tinha apenas Code. Schema tem Ispb + Code + Name.
- BankAccount faltava AgencyDigit, PixAddressKey, Ispb. Adicionados.

Contract tests (5 novos):
- BankAccountTransfer response shape completo
- Nullable dates/bools handling (B-29b/c regression)
- AsaasAccountTransferStatus 5 valores (B-29d regression)
- TransferOperationType 3 valores (B-29e regression)
- ListFilter com date ranges [ge]/[le] (B-29h regression)

Total: 631 unit/contract + 5 integration skip.
Fase 12 da auditoria final.

Bugs corrigidos (B-30):
- B-30a: Anticipation.AnticipationDate, DueDate, RequestDate eram
  DateTime non-nullable. Trocados para DateTime?.
- B-30b: Faltava campo Object (response inclui).

Confirmado em paralelo:
- AnticipationStatus enum: 7 valores OK

Contract tests (3 novos):
- Response shape completo
- Nullable dates handling (B-30a regression)
- Status enum 7 valores

Total: 634 unit/contract + 5 integration skip.
…le (B-31)

Fase 13 da auditoria final.

Bugs corrigidos (B-31):
- B-31a: Installment.ExpirationDay era int non-nullable.
  Schema marca optional. Trocado para int?.
- B-31b: Installment faltava CreditCard (nested object) e Refunds
  (array de InstallmentRefund com paymentId). Adicionados.

Contract tests (2 novos):
- Response shape com fields novos
- Nullable ExpirationDay handling (B-31a regression)

Total: 636 unit/contract + 5 integration skip.
Fase 14 da auditoria final.

Verificado contra MCP:
- Webhook response com todos os campos OK
- WebhookEvent enum: 110+ valores OK (confirmados via schema)
- WebhookSendType enum: 2 valores OK
- Sem bugs estruturais.

Nota: GET /v3/webhooks no schema oficial so aceita offset/limit
(sem filtros name/enabled/interrupted). WebhookListFilter expoe esses
campos por compatibilidade — backend pode aceitar mesmo nao
documentado.

Contract tests (3 novos):
- Response shape com sendType + events array
- SendType enum (2 valores)
- Sample de WebhookEvent (10 representativos dos 110+ valores)

Total: 639 unit/contract + 5 integration skip.
… B-34)

Fases 15-16 da auditoria final.

WalletManager (B-33):
- Wallet faltava Object (response wrapper). Adicionado.

NotificationManager (B-34):
- B-34a: Notification faltava campo Event (enum NotificationEvent
  com 6 valores). Adicionado. Sem o fix, o evento que dispara a
  notificacao sumia silenciosamente.
- B-34b: Todos os bools (Enabled, Email*, Sms*, PhoneCall*, Whatsapp*)
  eram non-nullable. UpdateNotificationRequest forcava false em
  todo update parcial. Trocados para bool? em ambos Notification
  e UpdateNotificationRequest.
- Adicionados: Object, Deleted no Notification.
- Novo enum: NotificationEvent (PAYMENT_CREATED, PAYMENT_UPDATED,
  PAYMENT_RECEIVED, PAYMENT_OVERDUE, PAYMENT_DUEDATE_WARNING,
  SEND_LINHA_DIGITAVEL).

Contract tests (4 novos):
- WalletList envelope
- NotificationResponse shape completo
- NotificationEvent 6 valores
- UpdateRequest com bools nullable (B-34b regression)

Total: 643 unit/contract + 5 integration skip.
Fase 17 da auditoria final.

Bugs corrigidos (B-35):
- B-35a: Common.CreditCard.Brand era string. Schema e enum
  CreditCardBrand (13 valores: VISA, MASTERCARD, ELO, DINERS,
  DISCOVER, AMEX, CABAL, BANESCARD, CREDZ, SOROCRED, CREDSYSTEM,
  JCB, UNKNOWN). Trocado para CreditCardBrand?.
- B-35b: PreAuthorizationConfig tinha campos INVENTADOS (Enabled,
  AutomaticCaptureDelay). Schema real: apenas {daysToExpire: int
  required}. Modelo reescrito.
- B-35c: SavePreAuthorizationConfigRequest tinha mesmos campos
  inventados. Reescrito.

Novo enum: Common.Enums.CreditCardBrand (13 valores).

Tests antigos atualizados:
- CreditCardManagerTests: brand string -> enum, PreAuth tests
  refazem assertions com DaysToExpire.

Contract tests (4 novos):
- TokenizeResponse shape com brand enum
- CreditCardBrand 13 valores (regression)
- PreAuthorizationConfig com daysToExpire apenas (B-35b regression)
- SaveRequest nao serializa campos inventados (B-35b regression)
- TokenizeRequest required keys

Total: 648 unit/contract + 5 integration skip.
… (B-36)

Fase 18 da auditoria final.

Bugs corrigidos (B-36):
- B-36a: PaymentLink.SubscriptionCycle era string. Schema e Cycle enum
  (WEEKLY/BIWEEKLY/MONTHLY/BIMONTHLY/QUARTERLY/SEMIANNUALLY/YEARLY).
  Trocado para Cycle?.
- B-36b: PaymentLink faltava ViewCount, IsAddressRequired,
  ExternalReference. Adicionados.
- B-36c: Value, Active, NotificationEnabled, Deleted,
  DueDateLimitDays, MaxInstallmentCount eram non-nullable.
  Schema permite omissao. Trocados para nullable.

Contract tests (3 novos):
- Response shape com todos os campos
- ChargeType enum 3 valores
- SubscriptionCycle enum 7 valores (B-36a regression)

Tests antigos atualizados: SerializationTests usa Cycle enum.

Total: 651 unit/contract + 5 integration skip.
Fase 19 da auditoria final.

Bugs corrigidos (B-37):
- B-37a: SplitStatistics tinha {TotalPendingValue, TotalReceivedValue}
  INVENTADOS. Schema oficial: {income, value}. Modelo reescrito.
- B-37b: GetPaymentStatistics nao aceitava filtros. Schema oficial
  expoe 11 filtros (customer, billingType, status, anticipated,
  dateCreated[ge/le], dueDate[ge/le], estimatedCreditDate[ge/le],
  externalReference). Criado PaymentStatisticsFilter e overload
  backwards-compatible.

Confirmado:
- Balance shape OK ({balance})
- PaymentStatistics shape OK ({quantity, value, netValue})

Contract tests (4 novos):
- Balance deserialization
- PaymentStatistics shape
- SplitStatistics com income/value (B-37a regression)
- PaymentStatisticsFilter com todos os 11 campos (B-37b regression)

Tests antigos atualizados: FinanceManagerTests usa income/value.

Total: 655 unit/contract + 5 integration skip.
Fase 20 da auditoria final. Resto do MyAccountManager (alem dos
documents §7 ja auditados).

Bugs corrigidos (B-38):
- B-38a: MyAccount.Status era string. Schema e enum AccountInfoStatus
  (APPROVED, AWAITING_ACTION_AUTHORIZATION, DENIED, PENDING).
- B-38b: MyAccount faltava CompanyName, IncomeValue, TradingName,
  Site, AvailableCompanyNames (array), CommercialInfoExpiration
  (nested objeto). Adicionados.
- InscricaoEstadual marcado [Obsolete] (nao existe no schema atual).

Novos models:
- Enums.AccountInfoStatus (4 valores)
- CommercialInfoExpiration (isExpired, scheduledDate)

Contract tests (3 novos):
- CommercialInfo response shape completo
- AccountInfoStatus 4 valores (B-38a regression)
- AccountStatus 4 valores (ja existia, validado)

Tests antigos atualizados: MyAccountManagerTests usa APPROVED enum.

Total: 658 unit/contract + 5 integration skip.
Fase 21 da auditoria final.

Bugs corrigidos (B-39):
- B-39a: Account.City era string. Schema oficial e integer (city id).
  Trocado para long?.
- B-39b: Account faltava Object, Id, BirthDate, TradingName, Site,
  AccountNumber (objeto aninhado com agency/account/accountDigit),
  CommercialInfoExpiration (objeto aninhado). Adicionados.
- B-39c: Account.ApiKey marcado [Obsolete] (nao existe no schema
  AccountGetResponseDTO; mantido por backwards-compat).

Contract tests (1 novo):
- Account response shape completo, City como int, AccountNumber e
  CommercialInfoExpiration aninhados.

Total: 659 unit/contract + 5 integration skip.
Fase 22 da auditoria final.

Bugs corrigidos (B-40):
- B-40a: FiscalInfo faltava NbsCode (Brazilian Nomenclature of Services).
- B-40b: RpsNumber e LoteNumber eram string. Schema oficial e integer.
  Trocados para int?.
- B-40c: FiscalInfo faltava PasswordSent, AccessTokenSent,
  CertificateSent (bools), NationalPortalTaxCalculationRegime (string),
  Object (response wrapper). Adicionados.
- B-40d: StateInscription marcado [Obsolete] (nao existe no schema
  FiscalInfoGetResponseDTO).
- B-40e: AccessToken (string) marcado [Obsolete]. Schema usa
  AccessTokenSent (bool); o token nunca e retornado.
- SimplesNacional, CulturalProjectsPromoter trocados para bool?.

Contract tests (1 novo):
- Response shape com tipos corretos + campos novos (B-40 regression).

Tests antigos atualizados: FiscalInfoManagerTests + SerializationTests
usam rpsNumber/loteNumber como int.

Total: 659 unit/contract + 5 integration skip.
Fase 23 da auditoria final.

Bugs corrigidos (B-41):
- B-41a: Chargeback faltava CreditCard (objeto aninhado com number e
  brand enum). Schema PaymentChargebackResponseDTO inclui esse campo.
  Adicionado novo modelo ChargebackCreditCard.
- B-41b: Reason era non-nullable; schema permite null (varios statuses
  nao tem reason). Trocado para ChargebackReason?.

Contract tests (3 novos):
- Response shape completo com creditCard aninhado (B-41a regression)
- ChargebackStatus 5 valores
- ChargebackDisputeStatus 3 valores

Total: 663 unit/contract + 5 integration skip.
Fase 24 da auditoria final.

Verificado contra MCP:
- POST /v3/sandbox/myAccount/approve OK
- POST /v3/sandbox/payment/{id}/confirm OK
- POST /v3/sandbox/payment/{id}/overdue OK
- Manager ja expoe os 3 endpoints
- EnsureSandbox() bloqueia uso em producao (cobertura existente)

Contract test (1 novo): sanity check via reflexao.

Total: 664 unit/contract + 5 integration skip.

==============================================
Concluido auditoria de TODOS os 27 managers.
==============================================
Fase 25-26 da auditoria final.

Fase 25 — Integration tests expandidos (+10):
- SubscriptionIntegrationTests: CreateSubscription_Boleto_RoundTrip
  + ListSubscriptions_WithFilterAndStatus (B-27a regression)
- PixIntegrationTests: ListAddressKeys + ListTransactions_WithStatusFilter
  (B-28a regression — valida PixTransactionStatus.AWAITING_REQUEST)
- TransferIntegrationTests: ListTransfers_WithDateRangeFilter
  (B-29h regression — valida date range [ge]/[le] lowercase)
- AnticipationIntegrationTests: ListAnticipations + GetLimits
- FinanceIntegrationTests: GetBalance + GetPaymentStatistics_WithFilter
  (B-37b regression) + GetSplitStatistics (B-37a regression — valida
  shape {income, value})

Manager PixManager.ListTransactions ganhou overload com filter (faltava).

Fase 26 — CI workflow:
- ci.yml: filter Category!=Integration para nao quebrar sem token.
- integration-sandbox.yml (NOVO): workflow dedicado com:
  * workflow_dispatch (manual)
  * schedule nightly (04:00 UTC)
  * usa secret ASAAS_SANDBOX_TOKEN
  * warning se secret ausente
  * filter Category=Integration

Para rodar local:
  $env:ASAAS_SANDBOX_TOKEN = "aact_..."
  dotnet test --filter "Category=Integration"

Para rodar no CI: vai automaticamente toda noite, ou trigger manual
em Actions -> Integration (sandbox) -> Run workflow.

Total: 664 unit/contract + 15 integration skip (sem token).
…sificados

Fases 27-28 da auditoria final.

CONFORMANCE.md atualizado:
- Status: AUDITORIA COMPLETA — 27/27 MANAGERS SCHEMA-FIRST
- 664 tests unit/contract + 15 integration tests
- Adicionadas secoes §12-§29 (16 novos managers auditados):
  Customer, Payment(resto), Subscription, Pix, Transfer, Anticipation,
  Installment, Webhook, Wallet, Notification, CreditCard, PaymentLink,
  Finance, MyAccount(resto), AsaasAccount, FiscalInfo, Chargeback, Sandbox.
- Cada secao tem: endpoint table, bugs B-XX corrigidos, contract test count.

Nova secao §50 — Cross-pattern bug list:
11 padroes de bug identificados em multiplos managers:
1. Envelope {data:[...]} minimalista
2. bool PascalCase em query
3. Casing errado em range filters ([Ge]/[Le] vs [ge]/[le])
4. Body vs query param (B-22k)
5. Enum incompleto ou inventado (12 ocorrencias)
6. Array vs objeto unico (B-22m)
7. Nullable incorreto (9 ocorrencias)
8. Paginacao incorreta
9. Campos obrigatorios ausentes
10. Nome de campo errado
11. Campos INVENTADOS / nao existem no schema (6 ocorrencias graves)

Sandbox §99 ampliado para 15 tests + CI workflow documentado.

Riscos remanescentes reclassificados em 3 niveis:
- NAO ACEITAVEIS: nenhum
- ACEITAVEIS COM RESSALVA: integration tests nao rodaram + fixtures manuais
- ACEITAVEIS (decisao explicita): /financialTransactions legado,
  webhooks payload decoders, Reforma Tributaria, [Obsolete] fields,
  WebhookListFilter nao-documentado, FiscalInfo lookup endpoints extras.

Total: 664 unit/contract + 15 integration skip. 0 warnings.
…integration)

CHANGELOG.md:
- Nova entrada [3.2.0] cobrindo Fase 7-29 da auditoria final.
- Listadas TODAS as breaking changes por manager (13 managers com
  fix: Pix, Customer, Payment, Subscription, Transfer, Anticipation,
  Installment, Notification, CreditCard, PaymentLink, Finance,
  MyAccount, AsaasAccount, FiscalInfo, Chargeback, Wallet).
- Metricas: 599 -> 664 tests, 11 -> 27 managers, 24 -> 42 bugs.

README.md:
- Badge atualizado: 599 -> 664 + 15 integration, schema-first 27/27.
- Versao 3.1.0 -> 3.2.0.
- Secao Testes ja referenciava integration; numeros corrigidos.

Total final: 664 unit/contract + 15 integration skip. 0 warnings.
@cloviscoli
cloviscoli merged commit 5b8fd98 into master May 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant