feat(rest): consulta CPE OAuth + padrón RUC local#3
Merged
Conversation
Adds two new capabilities orthogonal to the SOAP CPE emission flow:
1. SUNAT REST OAuth 2.0 client_credentials wrapper
- src/sunat-rest/oauth.ts — token fetch + in-process cache + 401 retry
- Token cached for ~1h (60s before SUNAT-reported expiry)
- Single postSoap-style helper callRestApi<T>() unifies all REST calls
- Two SUNAT host families: api-seguridad (token), api.sunat.gob.pe (ops)
2. Consulta Integrada CPE — sunat cpe consulta
- POST /v1/contribuyente/contribuyentes/{ruc}/validarcomprobante
- Validates ANY CPE against SUNAT records (yours or vendor's)
- Auto-converts ISO date (2026-04-29) → DD/MM/YYYY (29/04/2026)
- Friendly mapping of SUNAT codes (estadoCp, estadoRuc, condDomiRuc) to
human descriptions (Aceptado, Activo, Habido, etc)
- Required env: SUNAT_API_CLIENT_ID, SUNAT_API_CLIENT_SECRET (from SOL menu)
3. Padrón Reducido del RUC local — sunat padron sync|status|ruc|batch
- Downloads ~370MB ZIP from www2.sunat.gob.pe (no auth, daily updated)
- Streams raw bytes to disk (no encoding conversion in hot path — 12s
instead of 12+ minutes when we tried UTF-8 conversion in flight)
- 6.1M entries indexed by 11-char RUC prefix
- Streaming lookup: ~1s per single RUC on 1GB TXT
- Batch lookup: one scan for any number of RUCs
- 24h freshness check; --force to re-sync earlier
- Pipe-separated TXT, ISO-8859-1 encoded
Tests: 209 pass / 2 skip / 0 fail (was 182)
- oauth.test.ts (13) — token cache, 401 retry, query params, scope
- consulta-cpe.test.ts (6) — ISO→DD/MM/YYYY, code mappings, monto formatting
- padron-local.test.ts (8) — line parser, isStale, edge cases
Smoke: bun smoke:padron — downloads padrón, looks up SUNAT's own RUC,
verifies razon social. Verified passing 2026-04-29.
Out of scope (next PRs):
- Tipo de cambio: SUNAT/SBS WAF blocks fetch directly. Needs agent-browser.
- Padrón RUC consulta puntual via portal: requires numRnd token + reCAPTCHA.
Local padrón is a strictly better answer for batch/scriptable use.
- GRE (Guía de Remisión REST API): same OAuth shape; oauth.ts is reusable.
- SIRE (RVIE/RCE) REST API: distinct host api-sire.sunat.gob.pe.
- sqlite index for sub-ms padrón lookups.
See src/sunat-rest/RESEARCH.md for full notes including the WAF observations
and SUNAT code → friendly description maps.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds two new SUNAT capabilities, both orthogonal to the SOAP CPE emission flow shipped in #1 and #2:
sunat cpe consulta— validate any CPE (yours or vendor's) against SUNAT records via the official REST OAuth 2.0 APIsunat padron— local mirror of the SUNAT Padrón Reducido del RUC (~370MB ZIP, 6.1M entries), no auth, instant lookupsBoth verified end-to-end against real SUNAT infrastructure 2026-04-29.
What's in this PR
REST OAuth 2.0 client_credentials wrapper (
src/sunat-rest/oauth.ts)callRestApi<T>()helper — auto-retries once on 401 with fresh tokenapi-seguridad.sunat.gob.pe(token),api.sunat.gob.pe(ops)Consulta Integrada CPE (
sunat cpe consulta)/v1/contribuyente/contribuyentes/{rucConsultante}/validarcomprobantePadrón Reducido del RUC local (
sunat padron *)--forceto re-sync earlierTests
Smoke tests
All three verified passing 2026-04-29.
Verified end-to-end
Out of scope (deliberately deferred)
--driver agent-browser(same pattern as RHE/F616)numRndtoken + reCAPTCHA one-consultaruc.sunat.gob.peoauth.tsis reusableapi-sire.sunat.gob.pe, mandatory monthly filingTest plan
bun testgreen (209/2 skip/0 fail)bun smoke:padrongreen (downloads + lookup verified)sunat cpe consulta --helpparses correctlysunat padron statusreports cache statesunat padron ruc 20131312955returns SUNAT row in <2sSUNAT_API_CLIENT_ID/SECRETworks forcpe consulta