Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions packages/cli/LIMITATIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# sunat-cli β€” Limitations & Known Issues

Single source of truth for everything that's deliberately stubbed, deferred,
blocked by SUNAT/WAF, or pending verification with real production credentials.
Updated each PR. Anything **not** in here should Just Workβ„’.

If you hit something that's not documented here, open an issue.

---

## Quick legend

- **🚧 Shaped, not implemented** β€” interface exists, returns clear error. Future PR.
- **β›” Blocked by SUNAT** β€” endpoint or path actively rejects our requests; needs alternate approach.
- **⚠️ Verified shape, untested live** β€” code matches official SUNAT manual but never executed against real prod.
- **πŸ”¬ Verified end-to-end** β€” confirmed working against real SUNAT (beta or test cert).

---

## CPE / Emission (PRs #1, #2)

### Driver matrix

| Driver | Factura | Boleta | NC/ND | Guia | Resumen Diario | ComunicaciΓ³n Baja |
|--------|---------|--------|-------|------|----------------|-------------------|
| `mock` | πŸ”¬ | πŸ”¬ | πŸ”¬ | 🚧 | 🚧 | 🚧 |
| `sunat-direct` | πŸ”¬ | πŸ”¬ (β‰₯S/700 individual) | 🚧 | 🚧 | ⚠️ XML verified, send blocked by WAF on test RUC | ⚠️ XML verified, untested live |
| `facturador` | 🚧 | 🚧 | 🚧 | 🚧 | 🚧 | 🚧 |
| `nubefact` | 🚧 | 🚧 | 🚧 | 🚧 | 🚧 | 🚧 |
| `apisperu` | 🚧 | 🚧 | 🚧 | 🚧 | 🚧 | 🚧 |

### Active limitations

- **NC, ND, GuΓ­a de RemisiΓ³n** β€” driver methods throw "not yet implemented" errors. UBL builders shaped in `src/cpe/ubl/`, signer + SOAP infra reusable. Estimated 1 day each. **Future PR**.
- **`sunat cpe void` (T3)** β€” intent-token flow shaped, command stubbed. Voiding is currently done via ComunicaciΓ³n de Baja (`sunat cpe baja send`) for boletas or NC for facturas. **Future PR**.
- **Resumen Diario `sendSummary` against SUNAT beta** β€” XML structure 100% verified against Greenter twig template; unit tests cover all 14 structural assertions. **However**, the actual SUNAT beta nginx wrapper returns transient HTTP 401 on the `/sendSummary` path with the public test RUC `20000000001`. `sendBill` calls in the same window work fine. Hypothesis: rate-limit specific to the RC endpoint on the shared test RUC. **Production cert + RUC will not see this.** Documented in `src/commands/cpe/RESEARCH.md` appendix.
- **Drivers `facturador`, `nubefact`, `apisperu`** β€” `getDriver()` returns a clear "shaped but not implemented" error. The `facturador` driver requires coordination with Christian Pasquel's containerized Java Facturador. The other two are PSE/OSE adapters; useful when the user wants to keep their existing OSE while gaining the CLI UX.
- **CatΓ‘logos SUNAT minimal** β€” codigos producto (Cat 02), unidades (Cat 03 β€” currently using `ZZ`/`NIU` only), tipos doc (Cat 06), etc. Working set is hardcoded for the most common cases. Full catalog import is a separate PR.
- **ProducciΓ³n (`e-factura.sunat.gob.pe`)** β€” never tested. All verifications were against `e-beta.sunat.gob.pe`. Switching `--mode prod` should work but **never run prod without dry-run + careful first emission**.

### Verified end-to-end against SUNAT beta (2026-04-29)

- βœ… `cpe factura emit --driver sunat-direct` β†’ `cdrCode=0` Aceptado
- βœ… `cpe boleta emit --driver sunat-direct` (β‰₯S/700) β†’ `cdrCode=0` Aceptado
- βœ… Idempotency cache (re-emit same serie+numero returns cached CDR)

---

## SUNAT REST OAuth APIs (PR #3)

### PadrΓ³n RUC

- βœ… **Local padrΓ³n download + lookup** β€” verified end-to-end (PR #3 smoke test).
- β›” **PadrΓ³n puntual via portal `e-consultaruc.sunat.gob.pe`** β€” the form now requires a `numRnd` token + reCAPTCHA. Plain HTTP POSTs return 404. Workaround would need `agent-browser` automation (same pattern as RHE/F616 already use). **Local padrΓ³n is strictly better for batch/scriptable use anyway** β€” instantaneous after sync, no network roundtrip per RUC.

### Tipo de Cambio

- β›” **SUNAT `e-consulta.sunat.gob.pe/cl-at-ittipcam/tcS01Alias`** β€” blocked by WAF, returns "Request Rejected".
- β›” **SBS `sbs.gob.pe`** β€” also blocked by WAF.
- 🚧 **`sunat tipo-cambio` command** β€” not implemented. Future PR with `agent-browser` driver.

### Consulta CPE Integrada

- ⚠️ **`sunat cpe consulta`** β€” code matches Greenter's openapi spec. Not yet tested live because it requires `SUNAT_API_CLIENT_ID/SECRET` from a real RUC's SOL menu (the shared test RUC doesn't have these credentials). When you set those env vars, should work first call.

---

## SIRE β€” Registro de Ventas / Compras (PR #4)

### Verified shapes (untested live)

All endpoints follow Manual de Servicios Web Api SIRE Ventas v22 (March 2024) at the byte level. Unit tests cover URL paths, request methods, body shapes, and OAuth password grant flow.

### Active limitations

- ⚠️ **Never tested against real SIRE.** Same reason as Consulta CPE: needs real RUC with SIRE credentials + active billing periods. The Greenter test RUC `20000000001` has no RVIE history. When you run the first time with your own creds + a periodo with data, `propuesta --wait --out X.zip` should give you the working ZIP.
- 🚧 **`reemplazar propuesta` + `importar comprobantes` (propuesta/preliminar/ajustes)** β€” not implemented. These use **TUS.IO resumable upload protocol**. SUNAT's own manual notes "deben ser desarrollados en JAVA". Needs a TUS.IO client in TS. **Estimated next PR (#5)**.
- 🚧 **Reportes complementarios** (resumen, inconsistencias, CAR, casillas, reporte de exportadores, reporte de cumplimiento, reporte estadΓ­stico) β€” same async ticket pattern as `propuesta`. Easy adds when needed.
- 🚧 **Tipo de cambio masivo** β€” JSON POST endpoint, easy add.
- 🚧 **Eliminar comprobantes** (propuesta / preliminar / reemplazo) β€” same shape, low priority.
- ⚠️ **CORS warning from SUNAT** β€” "los servicios del API SIRE no deben ser consumidos desde un cliente Web". CLI is server-side, not affected. Don't try to call these from a browser bundle.

---

## RHE / F616 β€” Personas Naturales (legacy, pre-existing)

These predate the agent-first refactor and use the older agent-browser scraping path. Not part of recent PRs but documenting for completeness:

- ⚠️ **Browser scraping** β€” uses `agent-browser` to drive the SOL portal directly. Brittle to UI changes. Currently working but expect maintenance.
- ⚠️ **reCAPTCHA via mouse coordinates** β€” F616 (Nueva Plataforma) requires solving reCAPTCHA. Solved via coordinate injection. Documented as fragile in `CLAUDE.md`.
- βœ… **RHE emission** β€” verified working, used by Hunter monthly for Clerk income.
- βœ… **F616 declaration** β€” verified working, used by Hunter monthly.

---

## Cross-cutting

### Testing gaps

- **Production submissions** never tested. Always use `--mode beta` (or its equivalent) until you've manually verified one production emission.
- **Stress / rate-limit tests** never run. SUNAT WAF behavior under load is unknown.
- **Multi-RUC** β€” config file supports profiles, but never tested with multiple active RUCs in the same process.
- **Cert expiry** β€” `cpe doctor` warns at <30 days. Never tested with an actually-expired cert.

### Environment

- **Java not bundled** β€” driver `facturador` (when implemented) will assume Java 8u202+ already running in a sibling container. Not auto-installed.
- **Bun-only** β€” code uses Bun-native APIs (`Bun.spawn`, `crypto.subtle`, native fetch). Won't run on plain Node without porting.
- **macOS / Linux only** β€” Windows untested. Path handling uses `~/.sunat/` style; tests use `tmpdir()`. Should work on Windows in theory but no CI for it.

### Audit / observability

- **Audit log under `~/.sunat/audit/`** β€” never rotated. Will grow unbounded over time.
- **No remote telemetry** β€” by design. Everything stays on disk.
- **`cpe doctor` stale-pending check** β€” alerts when audit has `pending` entries >1h old. Cleanup is manual (user decides whether to retry, void, or just delete).

### Security

- **Cert PFX password** β€” read from env var `CPE_CERT_PASSWORD`. Never persisted on disk. Never logged.
- **SOL password** β€” read from env var `CPE_SOL_PASSWORD` / `SUNAT_PASSWORD`. Never persisted. Never logged.
- **API client_secret** β€” read from env var. Never persisted. Tests use mocks, no real secrets in repo.
- **No keychain integration yet** β€” env vars only. Future PR could add macOS keychain / Linux secret-service.

---

## What's deliberately out of scope (no plans)

- **Mexico CFDI, Colombia DIAN, etc** β€” Peru-only by design.
- **PDF render del CPE** β€” there are 50 libs for that. We return UBL XML; render somewhere else.
- **GUI / dashboard / web UI** β€” CLI + REST API only.
- **Reemplazar a un OSE acreditado** β€” for empresas obligadas a OSE (>75 UIT/aΓ±o en CPE B2B), the CLI should be able to USE one as driver (`--driver nubefact`), not replace one. Acreditarse cuesta meses de trΓ‘mite SUNAT.
- **"Auto-anular" en caso de error** β€” anular es siempre T3 manual con intent token. No automation.
- **Cumplimiento garantizado** β€” disclaimer in SKILL.md and `--help`. SUNAT compliance is the empresa emisora's responsibility.

---

## How to update this doc

When opening a PR:

1. Add new limitations to the relevant section (or create one)
2. Move items from "shaped/blocked" to "verified" when you confirm them live
3. Update the verification timestamp on the verified items
4. Link from PR description: "see LIMITATIONS.md for what's NOT in this PR"

Don't let this doc rot. If a PR adds capability without updating LIMITATIONS, that's a review blocker.
6 changes: 6 additions & 0 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ Full shaping rationale + recon dossier + SUNAT debugging notes:
- Schema introspection at runtime
- [agentskills.io](https://agentskills.io) compliant SKILL.md

## Limitations & known issues

See [`LIMITATIONS.md`](./LIMITATIONS.md) for the single source of truth:
what's stubbed, what's blocked by SUNAT WAF, what's verified end-to-end,
what's pending live verification with real production credentials.

## License

MIT β€” [Crafter Station](https://crafterstation.com)
13 changes: 13 additions & 0 deletions packages/cli/skills/sunat-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,19 @@ sunat schema cpe-nota-credito

Use `sunat schema <resource>` to get machine-readable field definitions before constructing payloads.

## Limitations

Before assuming any feature works end-to-end, check `LIMITATIONS.md` in the
package root. It tracks: stubbed verbs, SUNAT WAF-blocked endpoints,
shapes-verified-but-untested-live capabilities, and TUS.IO upload paths
that need a separate client. **Anything not in LIMITATIONS.md should Just Work**.

Quick markers used there:
- πŸ”¬ **Verified end-to-end** β€” confirmed against real SUNAT
- ⚠️ **Verified shape, untested live** β€” code matches manual, never executed in prod
- 🚧 **Shaped, not implemented** β€” clear "not yet implemented" error
- β›” **Blocked by SUNAT** β€” WAF / captcha / breaking schema change

## Output Formats

All commands support `--output <format>`:
Expand Down
Loading