@useinvio/nfse-sdk 3.0.0 → 3.2.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.
- package/CHANGELOG.md +176 -0
- package/README.en.md +146 -0
- package/README.md +77 -518
- package/dist/agent.d.ts +131 -0
- package/dist/agent.js +551 -0
- package/dist/agent.js.map +1 -0
- package/dist/certificate.d.ts +96 -0
- package/dist/certificate.js +218 -0
- package/dist/certificate.js.map +1 -0
- package/dist/certificateValidation.d.ts +11 -6
- package/dist/certificateValidation.js +23 -12
- package/dist/certificateValidation.js.map +1 -1
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +520 -0
- package/dist/cli.js.map +1 -0
- package/dist/cliBin.d.ts +2 -0
- package/dist/cliBin.js +6 -0
- package/dist/cliBin.js.map +1 -0
- package/dist/cliExample.d.ts +6 -0
- package/dist/cliExample.js +29 -0
- package/dist/cliExample.js.map +1 -0
- package/dist/client.d.ts +51 -4
- package/dist/client.js +41 -10
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/consultas.d.ts +34 -0
- package/dist/consultas.js +61 -0
- package/dist/consultas.js.map +1 -0
- package/dist/dpsJson.js +1 -41
- package/dist/dpsJson.js.map +1 -1
- package/dist/dpsJsonSchema.d.ts +17 -0
- package/dist/dpsJsonSchema.js +184 -0
- package/dist/dpsJsonSchema.js.map +1 -0
- package/dist/emissaoNota.d.ts +11 -6
- package/dist/emissaoNota.js +10 -6
- package/dist/emissaoNota.js.map +1 -1
- package/dist/eventoJson.d.ts +76 -0
- package/dist/eventoJson.js +128 -0
- package/dist/eventoJson.js.map +1 -0
- package/dist/eventosNfse.d.ts +38 -0
- package/dist/eventosNfse.js +73 -0
- package/dist/eventosNfse.js.map +1 -0
- package/dist/fiscalDomains.d.ts +22 -0
- package/dist/fiscalDomains.js +99 -0
- package/dist/fiscalDomains.js.map +1 -0
- package/dist/fiscalValidation.js +21 -53
- package/dist/fiscalValidation.js.map +1 -1
- package/dist/gzipB64.d.ts +5 -0
- package/dist/gzipB64.js +12 -0
- package/dist/gzipB64.js.map +1 -1
- package/dist/index.d.ts +22 -7
- package/dist/index.js +11 -4
- package/dist/index.js.map +1 -1
- package/dist/jsonSchemaCheck.d.ts +12 -0
- package/dist/jsonSchemaCheck.js +70 -0
- package/dist/jsonSchemaCheck.js.map +1 -0
- package/dist/loadPfx.d.ts +2 -0
- package/dist/loadPfx.js +2 -1
- package/dist/loadPfx.js.map +1 -1
- package/dist/mcpCli.d.ts +2 -0
- package/dist/mcpCli.js +7 -0
- package/dist/mcpCli.js.map +1 -0
- package/dist/mcpServer.d.ts +49 -0
- package/dist/mcpServer.js +159 -0
- package/dist/mcpServer.js.map +1 -0
- package/dist/nfseXml.d.ts +48 -0
- package/dist/nfseXml.js +86 -0
- package/dist/nfseXml.js.map +1 -0
- package/dist/rejeicoes.d.ts +50 -0
- package/dist/rejeicoes.js +62 -0
- package/dist/rejeicoes.js.map +1 -0
- package/dist/rejeicoesCatalog.d.ts +10 -0
- package/dist/rejeicoesCatalog.js +4449 -0
- package/dist/rejeicoesCatalog.js.map +1 -0
- package/dist/sefinClient.d.ts +107 -7
- package/dist/sefinClient.js +232 -22
- package/dist/sefinClient.js.map +1 -1
- package/dist/signXml.d.ts +3 -3
- package/dist/signXml.js +17 -7
- package/dist/signXml.js.map +1 -1
- package/dist/testing.d.ts +80 -0
- package/dist/testing.js +285 -0
- package/dist/testing.js.map +1 -0
- package/dist/xmlBuild.d.ts +11 -0
- package/dist/xmlBuild.js +44 -0
- package/dist/xmlBuild.js.map +1 -0
- package/dist/xmlInspection.d.ts +1 -1
- package/dist/xmlInspection.js +10 -9
- package/dist/xmlInspection.js.map +1 -1
- package/dist/xsdValidation.d.ts +24 -5
- package/dist/xsdValidation.js +97 -67
- package/dist/xsdValidation.js.map +1 -1
- package/docs/README.md +47 -0
- package/docs/REGRAS_NEGOCIO_EMISSAO.md +8 -8
- package/docs/conceitos/como-funciona.md +87 -0
- package/docs/guias/adn.md +51 -0
- package/docs/guias/agentes-ia.md +111 -0
- package/docs/guias/cancelar.md +70 -0
- package/docs/guias/certificado.md +88 -0
- package/docs/guias/cli.md +68 -0
- package/docs/guias/consultar.md +54 -0
- package/docs/guias/emitir.md +172 -0
- package/docs/guias/recuperar-emissao.md +33 -0
- package/docs/guias/rejeicoes.md +70 -0
- package/docs/guias/testes.md +79 -0
- package/docs/guias/timeouts.md +33 -0
- package/docs/referencia/ambientes.md +35 -0
- package/docs/referencia/api.md +137 -0
- package/docs/referencia/erros.md +55 -0
- package/docs/tutoriais/primeira-nfse.md +130 -0
- package/examples/README.md +3 -1
- package/examples/cancel-nfse.ts +29 -0
- package/examples/client-resource.ts +3 -5
- package/examples/emit-homologation.ts +3 -4
- package/examples/handle-errors.ts +3 -3
- package/examples/recover-emission.ts +29 -0
- package/llms.txt +97 -82
- package/package.json +31 -6
package/dist/xsdValidation.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { cpSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import { tmpdir } from 'node:os';
|
|
1
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
4
2
|
import { join } from 'node:path';
|
|
5
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { ParseOption, XmlBufferInputProvider, XmlDocument, XmlParseError, XmlValidateError, XsdValidator, xmlRegisterInputProvider, } from 'libxml2-wasm';
|
|
6
5
|
/** The DPS XML violates the NFS-e v1.01 XSD. This is a fiscal payload problem. */
|
|
7
6
|
export class DpsXsdValidationError extends Error {
|
|
8
7
|
details;
|
|
@@ -12,88 +11,119 @@ export class DpsXsdValidationError extends Error {
|
|
|
12
11
|
this.name = 'DpsXsdValidationError';
|
|
13
12
|
}
|
|
14
13
|
}
|
|
14
|
+
/** The pedRegEvento XML violates the NFS-e v1.01 event XSD. */
|
|
15
|
+
export class PedRegEventoXsdValidationError extends Error {
|
|
16
|
+
details;
|
|
17
|
+
constructor(details) {
|
|
18
|
+
super(`XML do pedido de registro de evento invalido para o XSD v1.01: ${details.join('; ')}`);
|
|
19
|
+
this.details = details;
|
|
20
|
+
this.name = 'PedRegEventoXsdValidationError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
15
23
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
24
|
+
* The embedded XSD engine (libxml2 compiled to WebAssembly) could not load the
|
|
25
|
+
* official schemas or crashed. This is an infrastructure problem, not proof
|
|
26
|
+
* that the XML is fiscally invalid, and callers must not treat it as a
|
|
19
27
|
* permanent rejection.
|
|
20
28
|
*/
|
|
21
|
-
export class
|
|
29
|
+
export class XsdEngineUnavailableError extends Error {
|
|
22
30
|
cause;
|
|
23
31
|
constructor(message, cause) {
|
|
24
32
|
super(message);
|
|
25
33
|
this.cause = cause;
|
|
26
|
-
this.name = '
|
|
34
|
+
this.name = 'XsdEngineUnavailableError';
|
|
27
35
|
}
|
|
28
36
|
}
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
/**
|
|
38
|
+
* @deprecated Since 3.1.0 the SDK no longer runs the `xmllint` binary.
|
|
39
|
+
* Kept as an alias so existing `instanceof XmllintUnavailableError` checks still work.
|
|
40
|
+
*/
|
|
41
|
+
export const XmllintUnavailableError = XsdEngineUnavailableError;
|
|
42
|
+
/** Virtual URL scheme for the bundled schemas, so includes never touch disk or network. */
|
|
43
|
+
const SCHEMA_URL_PREFIX = 'nfse-sdk-xsd://v1.01/';
|
|
44
|
+
const DPS_SCHEMA = 'DPS_v1.01.xsd';
|
|
45
|
+
const PED_REG_EVENTO_SCHEMA = 'pedRegEvento_v1.01.xsd';
|
|
46
|
+
/** Never load DTDs, external entities or network resources while parsing. */
|
|
47
|
+
export const SAFE_PARSE_OPTIONS = ParseOption.XML_PARSE_NONET | ParseOption.XML_PARSE_NO_XXE;
|
|
48
|
+
const compiledValidators = new Map();
|
|
49
|
+
let schemaBuffers;
|
|
50
|
+
function schemaSourceDir() {
|
|
51
|
+
return fileURLToPath(new URL('../schemas/nfse/v1.01/Schemas/1.01/', import.meta.url));
|
|
31
52
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
53
|
+
function loadSchemaBuffers() {
|
|
54
|
+
const dir = schemaSourceDir();
|
|
55
|
+
const encoder = new TextEncoder();
|
|
56
|
+
const buffers = {};
|
|
57
|
+
for (const file of readdirSync(dir)) {
|
|
58
|
+
if (!file.endsWith('.xsd'))
|
|
59
|
+
continue;
|
|
60
|
+
let text = readFileSync(join(dir, file), 'utf8');
|
|
61
|
+
if (file === 'tiposSimples_v1.01.xsd') {
|
|
62
|
+
// libxml2 treats ^/$ literally in XSD regexes. The official package ships
|
|
63
|
+
// one JavaScript-style anchor, so normalize that expression in memory.
|
|
64
|
+
text = text.replace('<xs:pattern value="^0{0,4}\\d{1,5}$"/>', '<xs:pattern value="0{0,4}\\d{1,5}"/>');
|
|
65
|
+
}
|
|
66
|
+
buffers[`${SCHEMA_URL_PREFIX}${file}`] = encoder.encode(text);
|
|
67
|
+
}
|
|
68
|
+
return buffers;
|
|
36
69
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
/** Compiles each official entry schema once per process; later calls reuse the validator. */
|
|
71
|
+
function getValidator(entrySchema) {
|
|
72
|
+
const cached = compiledValidators.get(entrySchema);
|
|
73
|
+
if (cached)
|
|
74
|
+
return cached;
|
|
75
|
+
let schemaDoc;
|
|
76
|
+
try {
|
|
77
|
+
if (!schemaBuffers) {
|
|
78
|
+
schemaBuffers = loadSchemaBuffers();
|
|
79
|
+
xmlRegisterInputProvider(new XmlBufferInputProvider(schemaBuffers));
|
|
80
|
+
}
|
|
81
|
+
const entry = schemaBuffers[`${SCHEMA_URL_PREFIX}${entrySchema}`];
|
|
82
|
+
if (!entry)
|
|
83
|
+
throw new Error(`${entrySchema} nao encontrado em ${schemaSourceDir()}`);
|
|
84
|
+
schemaDoc = XmlDocument.fromBuffer(entry, { url: `${SCHEMA_URL_PREFIX}${entrySchema}`, option: SAFE_PARSE_OPTIONS });
|
|
85
|
+
const validator = XsdValidator.fromDoc(schemaDoc);
|
|
86
|
+
compiledValidators.set(entrySchema, validator);
|
|
87
|
+
return validator;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
throw new XsdEngineUnavailableError(`Nao foi possivel carregar os XSD oficiais v1.01: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
// The validator keeps its own compiled copy of the schema.
|
|
94
|
+
schemaDoc?.dispose();
|
|
95
|
+
}
|
|
54
96
|
}
|
|
55
|
-
function
|
|
56
|
-
|
|
97
|
+
function detailsOf(error) {
|
|
98
|
+
const details = error.details.map((detail) => detail.message.trim()).filter(Boolean);
|
|
99
|
+
return details.length ? details : [error.message.trim() || error.name];
|
|
57
100
|
}
|
|
58
|
-
/**
|
|
101
|
+
/**
|
|
102
|
+
* Validates a DPS against the official v1.01 schema before signing.
|
|
103
|
+
* Runs in-process (libxml2 in WebAssembly): no `xmllint`, no temp files, no network.
|
|
104
|
+
*/
|
|
59
105
|
export function validateDpsXmlAgainstXsd(xml) {
|
|
60
|
-
|
|
61
|
-
|
|
106
|
+
validateAgainst(DPS_SCHEMA, xml, (details) => new DpsXsdValidationError(details));
|
|
107
|
+
}
|
|
108
|
+
/** Validates a pedRegEvento (cancellation, substitution, ...) against the official v1.01 event schema. */
|
|
109
|
+
export function validatePedRegEventoXmlAgainstXsd(xml) {
|
|
110
|
+
validateAgainst(PED_REG_EVENTO_SCHEMA, xml, (details) => new PedRegEventoXsdValidationError(details));
|
|
111
|
+
}
|
|
112
|
+
function validateAgainst(entrySchema, xml, payloadError) {
|
|
113
|
+
const validator = getValidator(entrySchema);
|
|
114
|
+
let doc;
|
|
62
115
|
try {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const xmlPath = join(workDir, 'dps.xml');
|
|
70
|
-
writeFileSync(xmlPath, xml);
|
|
71
|
-
try {
|
|
72
|
-
execFileSync('xmllint', ['--noout', '--schema', join(schemasDir, 'DPS_v1.01.xsd'), xmlPath], {
|
|
73
|
-
encoding: 'utf8',
|
|
74
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
catch (error) {
|
|
78
|
-
if (!isExecFileSyncFailure(error)) {
|
|
79
|
-
throw new XmllintUnavailableError(`Falha ao executar xmllint: ${String(error)}`, error);
|
|
80
|
-
}
|
|
81
|
-
if (error.code === 'ENOENT') {
|
|
82
|
-
throw new XmllintUnavailableError(`xmllint nao encontrado no ambiente de execucao (path=${error.path ?? 'xmllint'}). ` +
|
|
83
|
-
'Instale o pacote libxml2/xmllint antes de validar o XSD.', error);
|
|
84
|
-
}
|
|
85
|
-
const stderrText = toText(error.stderr).trim();
|
|
86
|
-
if (stderrText) {
|
|
87
|
-
const details = stderrText.split('\n').map((line) => line.trim()).filter(Boolean);
|
|
88
|
-
throw new DpsXsdValidationError(details.length ? details : [stderrText]);
|
|
89
|
-
}
|
|
90
|
-
// xmllint failed but produced no stderr: do not mask this as an XML
|
|
91
|
-
// schema violation, since we have no evidence about the XML content.
|
|
92
|
-
throw new XmllintUnavailableError(`xmllint falhou sem stderr: ${describeSpawnFailure(error)}`, error);
|
|
116
|
+
doc = XmlDocument.fromString(xml, { option: SAFE_PARSE_OPTIONS });
|
|
117
|
+
validator.validate(doc);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
if (error instanceof XmlValidateError || error instanceof XmlParseError) {
|
|
121
|
+
throw payloadError(detailsOf(error));
|
|
93
122
|
}
|
|
123
|
+
throw new XsdEngineUnavailableError(`Falha no motor de validacao XSD: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
94
124
|
}
|
|
95
125
|
finally {
|
|
96
|
-
|
|
126
|
+
doc?.dispose();
|
|
97
127
|
}
|
|
98
128
|
}
|
|
99
129
|
//# sourceMappingURL=xsdValidation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xsdValidation.js","sourceRoot":"","sources":["../xsdValidation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"xsdValidation.js","sourceRoot":"","sources":["../xsdValidation.ts"],"names":[],"mappings":"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"}
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Documentação do @useinvio/nfse-sdk
|
|
2
|
+
|
|
3
|
+
Comece pelo tutorial se for seu primeiro contato. Depois use os guias para
|
|
4
|
+
tarefas específicas e a referência para consultar detalhes.
|
|
5
|
+
|
|
6
|
+
## Tutorial
|
|
7
|
+
|
|
8
|
+
- [Sua primeira NFS-e na produção restrita](tutoriais/primeira-nfse.md): emitir,
|
|
9
|
+
consultar, baixar o DANFSe e cancelar, do zero.
|
|
10
|
+
|
|
11
|
+
## Guias
|
|
12
|
+
|
|
13
|
+
| Guia | Para |
|
|
14
|
+
|---|---|
|
|
15
|
+
| [Configurar o certificado A1](guias/certificado.md) | Variáveis de ambiente, cofres de segredo, vários emitentes. |
|
|
16
|
+
| [Emitir uma NFS-e](guias/emitir.md) | JSON declarativo, `NfseClient`, XML pronto, série e número. |
|
|
17
|
+
| [Consultar e baixar o DANFSe](guias/consultar.md) | Consulta tipada, consulta crua, PDF. |
|
|
18
|
+
| [Recuperar uma emissão após timeout](guias/recuperar-emissao.md) | Evitar notas duplicadas quando a conexão cai. |
|
|
19
|
+
| [Cancelar uma NFS-e](guias/cancelar.md) | Cancelamento e cancelamento por substituição. |
|
|
20
|
+
| [Tratar rejeições e erros](guias/rejeicoes.md) | O que cada erro significa e o que fazer. |
|
|
21
|
+
| [Timeouts e novas tentativas](guias/timeouts.md) | `timeoutMs`, `retries`, `signal`. |
|
|
22
|
+
| [Distribuição e parâmetros municipais](guias/adn.md) | NSU, convênio, alíquotas, regimes especiais. |
|
|
23
|
+
| [Usar pelo terminal](guias/cli.md) | `nfse init`, `doctor`, `validate`, `emit`, `explain`. |
|
|
24
|
+
| [Testar sem certificado](guias/testes.md) | SEFIN simulada e certificado de teste para o seu CI. |
|
|
25
|
+
| [Agentes de IA e MCP](guias/agentes-ia.md) | Servidor MCP, plugin do Claude Code e ferramentas para o seu agente. |
|
|
26
|
+
| [Métricas de latência](METRICS.md) | Observar a SEFIN em produção. |
|
|
27
|
+
|
|
28
|
+
## Referência
|
|
29
|
+
|
|
30
|
+
- [API](referencia/api.md): todas as funções e o `NfseClient`.
|
|
31
|
+
- [Erros](referencia/erros.md): classes, campos e códigos.
|
|
32
|
+
- [Ambientes](referencia/ambientes.md): URLs e endpoints.
|
|
33
|
+
- [Mapeamento do JSON da DPS](../JSON_MAPPING.md): cada campo de `DpsJsonRequest`.
|
|
34
|
+
- [Matriz fiscal](FISCAL_MATRIX.md): combinações aceitas por regime.
|
|
35
|
+
- [Códigos de rejeição](rejeicoes/README.md): uma página por código oficial da SEFIN.
|
|
36
|
+
- [Playground](https://useinvio.github.io/nfse-sdk/): JSON → DPS no navegador, sem instalar nada.
|
|
37
|
+
|
|
38
|
+
## Conceitos
|
|
39
|
+
|
|
40
|
+
- [Como o SDK funciona](conceitos/como-funciona.md): fluxo de emissão, SEFIN e
|
|
41
|
+
ADN, idempotência, certificado e o que o SDK não faz.
|
|
42
|
+
|
|
43
|
+
## Histórico
|
|
44
|
+
|
|
45
|
+
- [CHANGELOG](../CHANGELOG.md)
|
|
46
|
+
- [Migração 2.x → 3.0.0](CORRECOES_EMISSAO.md)
|
|
47
|
+
- [Regras de negócio da emissão (análise de 06/10/2026)](REGRAS_NEGOCIO_EMISSAO.md)
|
|
@@ -41,7 +41,7 @@ Para o ISS, a LC 116/2003 distingue exportação de serviço de serviço desenvo
|
|
|
41
41
|
|
|
42
42
|
**Entrada XML:** passa pelo XSD e pela assinatura, mas não pela matriz fiscal do JSON. Assim, uma restrição do builder não significa necessariamente proibição no leiaute. O XML externo precisa ser montado e validado pelo integrador.
|
|
43
43
|
|
|
44
|
-
Base: [fluxo de emissão](
|
|
44
|
+
Base: [fluxo de emissão](../emissaoNota.ts#L57), [builder](../dpsJson.ts#L475), [cliente](../client.ts#L88).
|
|
45
45
|
|
|
46
46
|
## 3. Regras comuns a todas as emissões
|
|
47
47
|
|
|
@@ -77,7 +77,7 @@ O serviço possui um único bloco, sem lista de itens. Não há modelagem de mú
|
|
|
77
77
|
|
|
78
78
|
**Atenção ao ambiente:** na função direta `emitirNfse`, `options.ambiente` escolhe o destino, mas o XML JSON é construído usando `request.ambiente`. Valores diferentes podem gerar `tpAmb` incompatível com o destino. No cliente, `invoices.get` usa o ambiente do construtor, mesmo que uma emissão tenha sobrescrito o ambiente.
|
|
79
79
|
|
|
80
|
-
Base: [cadastros e datas](
|
|
80
|
+
Base: [cadastros e datas](../fiscalValidation.ts#L186), [identificador](../dpsJson.ts#L290), [precedências](../client.ts#L88).
|
|
81
81
|
|
|
82
82
|
## 4. Matriz nacional × exterior
|
|
83
83
|
|
|
@@ -116,7 +116,7 @@ Quando `tomador` existe, `xNome` e exatamente um entre `CNPJ`, `CPF`, `NIF` e `c
|
|
|
116
116
|
|
|
117
117
|
**Intermediário:** opcional; a interface pública e o XML suportam CPF ou CNPJ e nome. O validador genérico também reconhece NIF/`cNaoNIF`, mas o builder do intermediário não os serializa. Portanto, intermediário estrangeiro não tem suporte completo, mesmo que um objeto JavaScript passe pela pré-validação.
|
|
118
118
|
|
|
119
|
-
Base: [pessoas](
|
|
119
|
+
Base: [pessoas](../fiscalValidation.ts#L223), [matriz operacional](../fiscalValidation.ts#L409).
|
|
120
120
|
|
|
121
121
|
## 5. ISSQN, regimes e carga tributária
|
|
122
122
|
|
|
@@ -161,7 +161,7 @@ A carga aproximada não é o ISS devido nem o valor líquido da nota. O SDK não
|
|
|
161
161
|
|
|
162
162
|
`regEspTrib` é obrigatório e aceita: `0` nenhum; `1` ato cooperado; `2` estimativa; `3` microempresa municipal; `4` notário/registrador; `5` autônomo; `6` sociedade de profissionais; `9` outros. Não há cruzamento com serviço, município ou opção pelo Simples.
|
|
163
163
|
|
|
164
|
-
Base: [ISSQN](
|
|
164
|
+
Base: [ISSQN](../fiscalValidation.ts#L297), [totais](../fiscalValidation.ts#L336), [domínios locais](../schemas/nfse/v1.01/Schemas/1.01/tiposSimples_v1.01.xsd#L996).
|
|
165
165
|
|
|
166
166
|
## 6. Valores e comércio exterior
|
|
167
167
|
|
|
@@ -197,7 +197,7 @@ Todos os campos abaixo são obrigatórios quando o bloco está presente, exceto
|
|
|
197
197
|
|
|
198
198
|
A pré-validação exige presença desses códigos; a verificação dos respectivos domínios fica principalmente no XSD. `comercioExterior.cPaisResult` existe no tipo, mas é ignorado na geração do XML: o campo efetivo fica em `tributacaoMunicipal.cPaisResult`.
|
|
199
199
|
|
|
200
|
-
Base: [cálculo](
|
|
200
|
+
Base: [cálculo](../dpsJson.ts#L243), [comércio exterior](../dpsJson.ts#L459), [estrutura local](../schemas/nfse/v1.01/Schemas/1.01/tiposComplexos_v1.01.xsd#L1364).
|
|
201
201
|
|
|
202
202
|
## 7. Tributos federais e funcionalidades especiais
|
|
203
203
|
|
|
@@ -229,7 +229,7 @@ No XSD, os tipos de retenção federal são: `0` nenhum dos três tributos retid
|
|
|
229
229
|
|
|
230
230
|
A ausência de suporte a IBS/CBS não permite concluir que sua omissão seja válida em qualquer emissão atual. O portal oficial mantém documentação de produção, esquemas e anexos próprios; esta análise verificou o código e os esquemas locais, sem certificar aderência integral a todas as atualizações publicadas. [Fonte: documentação técnica de produção da NFS-e](https://www.gov.br/nfse/pt-br/biblioteca/documentacao-tecnica/documentacao-atual).
|
|
231
231
|
|
|
232
|
-
Base: [validação federal e funcionalidades bloqueadas](
|
|
232
|
+
Base: [validação federal e funcionalidades bloqueadas](../fiscalValidation.ts#L384), [serialização de tributos](../dpsJson.ts#L385), [obra no XSD](../schemas/nfse/v1.01/Schemas/1.01/tiposComplexos_v1.01.xsd#L1517).
|
|
233
233
|
|
|
234
234
|
## 8. Autorização, erros e continuidade
|
|
235
235
|
|
|
@@ -252,7 +252,7 @@ Não existem armazenamento, estados persistentes, idempotência, controle de con
|
|
|
252
252
|
|
|
253
253
|
**Certificado:** `assertCertificateForProvider` verifica vigência e busca o CPF/CNPJ do prestador nos dados do certificado, mas não é chamada por `emitirNfse`, `prepararNota` ou `transmitirNotaPreparada`. A verificação criptográfica da assinatura não substitui essa checagem de titularidade/vigência.
|
|
254
254
|
|
|
255
|
-
Base: [respostas](
|
|
255
|
+
Base: [respostas](../emissaoNota.ts#L89), [certificado](../certificateValidation.ts#L15), [XSD](../xsdValidation.ts#L67), [transporte e erros](../sefinClient.ts#L205).
|
|
256
256
|
|
|
257
257
|
## 9. Catálogo de cenários para produto e QA
|
|
258
258
|
|
|
@@ -314,4 +314,4 @@ A análise cruzou validadores, builders, transmissão, cliente, testes, document
|
|
|
314
314
|
|
|
315
315
|
Nenhuma nota foi transmitida, nenhum certificado real foi utilizado e não houve homologação com a SEFIN. As evidências demonstram comportamento local, não aceitação em produção. O código de emissão não foi alterado.
|
|
316
316
|
|
|
317
|
-
**Referências de manutenção:** [validador fiscal](
|
|
317
|
+
**Referências de manutenção:** [validador fiscal](../fiscalValidation.ts), [modelo e XML](../dpsJson.ts), [testes de regras](../test/dpsJson.test.ts), [testes de XSD](../test/xsdValidation.test.ts), [matriz interna anterior](FISCAL_MATRIX.md), [mapeamento anterior](../JSON_MAPPING.md).
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Como o SDK funciona
|
|
2
|
+
|
|
3
|
+
O SDK cuida da camada de protocolo da NFS-e Nacional. A aplicação decide o
|
|
4
|
+
conteúdo fiscal; o SDK transforma esse conteúdo em uma DPS válida, assina,
|
|
5
|
+
transmite e devolve a resposta oficial em formato estruturado.
|
|
6
|
+
|
|
7
|
+
## O caminho de uma emissão
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
JSON (DpsJsonRequest) XML de DPS pronto
|
|
11
|
+
│ │
|
|
12
|
+
▼ │
|
|
13
|
+
validateDpsJsonRequest ──► buildDpsFromJson
|
|
14
|
+
│ │
|
|
15
|
+
└───────────────┬───────────────┘
|
|
16
|
+
▼
|
|
17
|
+
XSD oficial v1.01 (libxml2 em WebAssembly)
|
|
18
|
+
▼
|
|
19
|
+
vigência do certificado A1
|
|
20
|
+
▼
|
|
21
|
+
assinatura XMLDSIG de <infDPS> (RSA-SHA256)
|
|
22
|
+
▼
|
|
23
|
+
GZip + Base64 → POST /nfse por mTLS
|
|
24
|
+
▼
|
|
25
|
+
NFS-e autorizada (XML) ou EmitirNotaError
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`emitirNfse` faz tudo isso em uma chamada. `prepararNota` e
|
|
29
|
+
`transmitirNotaPreparada` separam a preparação do envio, para que você salve a
|
|
30
|
+
DPS assinada antes de transmitir.
|
|
31
|
+
|
|
32
|
+
## Dois serviços: SEFIN e ADN
|
|
33
|
+
|
|
34
|
+
| Serviço | Para quê | Funções |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| **SEFIN Nacional** | Emitir, consultar NFS-e e DPS, registrar e consultar eventos | `emitirNfse`, `obterNfse`, `recuperarNfsePorDps`, `cancelarNfse`, `consultarEvento` |
|
|
37
|
+
| **ADN** (Ambiente de Dados Nacional) | DANFSe em PDF, distribuição por NSU, eventos por chave, parâmetros municipais | `baixarDanfse`, `distribuirDfePorNsu`, `consultarEventosPorChaveAdn`, `consultarConvenio`, `consultarAliquota` |
|
|
38
|
+
|
|
39
|
+
Os dois usam o mesmo certificado A1 por mTLS. As URLs de cada ambiente estão em
|
|
40
|
+
[Ambientes](../referencia/ambientes.md).
|
|
41
|
+
|
|
42
|
+
## Ambientes
|
|
43
|
+
|
|
44
|
+
`restrita` (produção restrita, o sandbox oficial) é o padrão. Notas emitidas em
|
|
45
|
+
`producao` têm validade jurídica. O `tpAmb` dentro do XML precisa coincidir com
|
|
46
|
+
o ambiente de envio; o SDK recusa a divergência antes de transmitir.
|
|
47
|
+
|
|
48
|
+
## Idempotência
|
|
49
|
+
|
|
50
|
+
`POST /nfse` e `POST /nfse/{chave}/eventos` não são idempotentes. Por isso o SDK
|
|
51
|
+
nunca os repete sozinho. Só os GETs aceitam `retries`. Se uma emissão cair sem
|
|
52
|
+
resposta, consulte a DPS com `recuperarNfsePorDps` antes de reenviar; veja
|
|
53
|
+
[Recuperar uma emissão após timeout](../guias/recuperar-emissao.md).
|
|
54
|
+
|
|
55
|
+
## O certificado
|
|
56
|
+
|
|
57
|
+
O A1 (`.pfx`) assina o XML e autentica a conexão mTLS. `NfseCertificate` lê o
|
|
58
|
+
arquivo uma vez e guarda só o necessário:
|
|
59
|
+
|
|
60
|
+
- a chave privada como `KeyObject`, fora do objeto público;
|
|
61
|
+
- um agente HTTPS próprio, para que conexões nunca sejam compartilhadas entre
|
|
62
|
+
emitentes;
|
|
63
|
+
- metadados públicos: CNPJ/CPF dos campos ICP-Brasil, validade, emissor e
|
|
64
|
+
fingerprint.
|
|
65
|
+
|
|
66
|
+
A senha e os bytes do PFX são descartados. `console.log` e `JSON.stringify`
|
|
67
|
+
mostram só os metadados. Isso evita vazamentos acidentais; não protege contra
|
|
68
|
+
quem já tem acesso à memória do processo. Assinatura em KMS/HSM não está nos
|
|
69
|
+
planos: o mTLS exige a chave no processo de qualquer forma.
|
|
70
|
+
|
|
71
|
+
## O que o SDK não faz
|
|
72
|
+
|
|
73
|
+
- Não escolhe códigos de serviço, CST, alíquotas, retenções ou regime.
|
|
74
|
+
- Não calcula impostos nem valida se a declaração está contabilmente correta.
|
|
75
|
+
- Não guarda estado: sem banco de dados, sem numeração automática de `nDPS`,
|
|
76
|
+
sem memória de tenant.
|
|
77
|
+
- Não implementa ainda o grupo IBS/CBS da reforma tributária (NT 009).
|
|
78
|
+
|
|
79
|
+
Campos fiscais obrigatórios como `tributacaoMunicipal` e `totTrib` precisam vir
|
|
80
|
+
explícitos na entrada: não há defaults silenciosos.
|
|
81
|
+
|
|
82
|
+
## Princípios de design
|
|
83
|
+
|
|
84
|
+
- Funções pequenas, testáveis e reutilizáveis; o `NfseClient` é uma fachada fina.
|
|
85
|
+
- Erros oficiais da SEFIN preservados na íntegra, nunca engolidos.
|
|
86
|
+
- Nenhuma dependência nativa: XSD em WebAssembly, criptografia do Node.
|
|
87
|
+
- Parâmetros de URL validados antes de qualquer chamada de rede.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Distribuição e parâmetros municipais (ADN)
|
|
2
|
+
|
|
3
|
+
O Ambiente de Dados Nacional (ADN) distribui documentos fiscais e publica os
|
|
4
|
+
parâmetros de cada município conveniado. Todas as funções usam o mesmo
|
|
5
|
+
certificado A1 e devolvem a resposta crua `{ status, body }`.
|
|
6
|
+
|
|
7
|
+
## Documentos e eventos
|
|
8
|
+
|
|
9
|
+
| Função | Endpoint |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `distribuirDfePorNsu(nsu, certificado, ambiente?, { cnpjConsulta?, lote? })` | `GET /contribuintes/DFe/{nsu}` |
|
|
12
|
+
| `consultarEventosPorChaveAdn(chave, certificado, ambiente?)` | `GET /contribuintes/NFSe/{chave}/Eventos` |
|
|
13
|
+
|
|
14
|
+
Para sincronizar notas emitidas e recebidas, guarde o último NSU processado e
|
|
15
|
+
chame `distribuirDfePorNsu` a partir dele. Os documentos podem vir em Base64
|
|
16
|
+
simples ou duplo; `gunzipBase64Flexivel(b64)` decodifica os dois.
|
|
17
|
+
|
|
18
|
+
## Parâmetros municipais
|
|
19
|
+
|
|
20
|
+
| Função | Endpoint |
|
|
21
|
+
|---|---|
|
|
22
|
+
| `consultarConvenio(codMun, ...)` | `GET /parametrizacao/{codMun}/convenio` |
|
|
23
|
+
| `consultarAliquota(codMun, codServico, competencia, ...)` | `GET /parametrizacao/{codMun}/{codServico}/{competencia}/aliquota` |
|
|
24
|
+
| `consultarHistoricoAliquotas(codMun, codServico, ...)` | `GET /parametrizacao/{codMun}/{codServico}/historicoaliquotas` |
|
|
25
|
+
| `consultarRegimesEspeciais(codMun, codServico, competencia, ...)` | `GET /parametrizacao/{codMun}/{codServico}/{competencia}/regimes_especiais` |
|
|
26
|
+
| `consultarRetencoes(codMun, competencia, ...)` | `GET /parametrizacao/{codMun}/{competencia}/retencoes` |
|
|
27
|
+
| `consultarBeneficio(codMun, numeroBeneficio, competencia, ...)` | `GET /parametrizacao/{codMun}/{numeroBeneficio}/{competencia}/beneficio` |
|
|
28
|
+
|
|
29
|
+
`codMun` é o código IBGE de 7 dígitos, `codServico` o código do serviço (ex.:
|
|
30
|
+
`01.01.01`) e `competencia` uma data `AAAA-MM-DD`.
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { consultarAliquota, consultarConvenio } from '@useinvio/nfse-sdk';
|
|
34
|
+
|
|
35
|
+
const convenio = await consultarConvenio('4106902', certificado, 'restrita');
|
|
36
|
+
const aliquota = await consultarAliquota('4106902', '01.01.01', '2026-11-01', certificado, 'restrita');
|
|
37
|
+
console.log(convenio.status, aliquota.body);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Os parâmetros de caminho são validados antes de qualquer chamada de rede e
|
|
41
|
+
geram `SefinParametroInvalidoError` quando o formato está errado.
|
|
42
|
+
|
|
43
|
+
> Os caminhos seguem o ADN em uso pelos clientes abertos mais adotados. Um dos
|
|
44
|
+
> manuais oficiais lista os parâmetros em `/parametros_municipais/...`. Se o seu
|
|
45
|
+
> ambiente responder 404, abra uma issue com o retorno.
|
|
46
|
+
|
|
47
|
+
## No cliente
|
|
48
|
+
|
|
49
|
+
`client.distribution.byNsu(nsu, { cnpjConsulta, lote })`,
|
|
50
|
+
`client.events.listByAccessKey(chave)` e `client.municipalParameters.agreement`,
|
|
51
|
+
`.rate`, `.rateHistory`, `.specialRegimes`, `.withholdings`, `.benefit`.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Usar com agentes de IA e MCP
|
|
2
|
+
|
|
3
|
+
Há três formas, da mais rápida para a mais flexível:
|
|
4
|
+
|
|
5
|
+
| Forma | Para quem |
|
|
6
|
+
|---|---|
|
|
7
|
+
| [Servidor MCP](#servidor-mcp) `@useinvio/nfse-mcp` | Claude Code, Claude Desktop, Cursor, VS Code ou qualquer cliente MCP. |
|
|
8
|
+
| [Plugin do Claude Code](#plugin-do-claude-code) | Servidor MCP + uma skill que ensina o fluxo ao Claude, com o certificado configurado numa tela. |
|
|
9
|
+
| [Ferramentas do SDK](#ferramentas-no-seu-agente) `@useinvio/nfse-sdk/agent` | Seu próprio agente (Claude Agent SDK, OpenAI, LangChain, Vercel AI SDK). |
|
|
10
|
+
|
|
11
|
+
## Servidor MCP
|
|
12
|
+
|
|
13
|
+
Para experimentar sem certificado, o modo de teste usa uma SEFIN simulada dentro
|
|
14
|
+
do próprio servidor:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
claude mcp add nfse --env NFSE_MCP_MOCK=1 --env NFSE_MCP_ALLOW_WRITE=1 -- npx -y @useinvio/nfse-mcp
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Com o seu certificado A1, na produção restrita e só com ferramentas de leitura:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
claude mcp add nfse --env NFSE_CERT_PATH=/caminho/certificado.pfx --env NFSE_CERT_PASSWORD_FILE=/caminho/senha.txt -- npx -y @useinvio/nfse-mcp
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
| Variável | Padrão | |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `NFSE_CERT_PATH` / `NFSE_CERT_BASE64` | – | Certificado A1. Sem ele, só as ferramentas sem certificado funcionam. |
|
|
29
|
+
| `NFSE_CERT_PASSWORD` / `NFSE_CERT_PASSWORD_FILE` | – | Senha do certificado. Prefira o arquivo. |
|
|
30
|
+
| `NFSE_AMBIENTE` | `restrita` | `producao` emite notas com validade jurídica. |
|
|
31
|
+
| `NFSE_MCP_ALLOW_WRITE` | desligado | `1` habilita emitir e cancelar (prepare/confirm). |
|
|
32
|
+
| `NFSE_MCP_MOCK` | desligado | `1` usa a SEFIN simulada e um certificado de teste. Recusado com `producao`. |
|
|
33
|
+
|
|
34
|
+
Configuração para Claude Desktop, Cursor e VS Code no
|
|
35
|
+
[README do pacote](../../mcp/README.md).
|
|
36
|
+
|
|
37
|
+
## Plugin do Claude Code
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
/plugin install nfse-nacional --marketplace useinvio/nfse-sdk
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
O plugin pede o caminho do certificado, a senha (guardada no cofre de
|
|
44
|
+
credenciais do sistema), o ambiente e se emitir/cancelar fica liberado. Ele
|
|
45
|
+
inclui a skill `nfse-nacional`, que ensina o Claude a validar antes de emitir,
|
|
46
|
+
nunca inventar códigos fiscais, mostrar o resumo antes de confirmar e explicar
|
|
47
|
+
rejeições com o catálogo oficial.
|
|
48
|
+
|
|
49
|
+
## Ferramentas
|
|
50
|
+
|
|
51
|
+
| Ferramenta | Efeito | Certificado |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| `validate_dps` | Valida a requisição; nenhum efeito colateral. | Não |
|
|
54
|
+
| `build_dps_xml` | Gera o XML não assinado e confere contra o XSD v1.01. | Não |
|
|
55
|
+
| `explain_rejection` | Mensagem, regra e campo oficiais de códigos como `E0014`. | Não |
|
|
56
|
+
| `get_nfse` | Consulta uma NFS-e pela chave de acesso. | Sim |
|
|
57
|
+
| `recover_nfse_by_dps` | Diz se a SEFIN gerou NFS-e para um Id de DPS. | Sim |
|
|
58
|
+
| `prepare_nfse_emission` | Valida e assina **sem enviar**; devolve resumo e `confirmationId`. | Sim, escrita |
|
|
59
|
+
| `confirm_nfse_emission` | Envia a DPS preparada. | Sim, escrita |
|
|
60
|
+
| `prepare_nfse_cancellation` | Monta o cancelamento e mostra a nota; não envia. | Sim, escrita |
|
|
61
|
+
| `confirm_nfse_cancellation` | Envia o cancelamento preparado. | Sim, escrita |
|
|
62
|
+
|
|
63
|
+
## Segurança
|
|
64
|
+
|
|
65
|
+
- Certificado e ambiente vêm da configuração do host, nunca da entrada da
|
|
66
|
+
ferramenta: o modelo não escolhe `producao` nem vê material de chave.
|
|
67
|
+
- As ferramentas de escrita só existem com `allowWrite` (`NFSE_MCP_ALLOW_WRITE=1`).
|
|
68
|
+
- Emitir e cancelar sempre exigem duas chamadas. `prepare_*` devolve um resumo;
|
|
69
|
+
a descrição da ferramenta e as instruções do servidor mandam o modelo mostrar
|
|
70
|
+
o resumo e só chamar `confirm_*` depois da aprovação explícita do usuário.
|
|
71
|
+
- O `confirmationId` é de uso único e expira em 10 minutos.
|
|
72
|
+
- Se a conexão cair durante `confirm_nfse_emission`, repetir a chamada consulta
|
|
73
|
+
a DPS na SEFIN antes de reenviar: a mesma nota nunca é emitida duas vezes.
|
|
74
|
+
- `confirm_*` têm `destructiveHint: true`, então clientes MCP pedem confirmação
|
|
75
|
+
antes de executar.
|
|
76
|
+
|
|
77
|
+
## Ferramentas no seu agente
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { createNfseAgentToolkit, nfseAgentTools } from '@useinvio/nfse-sdk/agent';
|
|
81
|
+
|
|
82
|
+
const context = { pfx: certificado, ambiente: 'restrita' as const }; // configuração do host
|
|
83
|
+
const { tools } = createNfseAgentToolkit({ allowWrite: true }); // ou nfseAgentTools, só leitura
|
|
84
|
+
for (const tool of tools) {
|
|
85
|
+
// registre tool.name, tool.description, tool.inputSchema e tool.annotations no seu framework
|
|
86
|
+
// e chame tool.run(argumentos, context) quando o modelo usar a ferramenta
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Cada ferramenta traz `name`, `title`, `description`, `inputSchema` e
|
|
91
|
+
`outputSchema` em JSON Schema, `annotations` no formato MCP e um handler `run`.
|
|
92
|
+
Falhas esperadas retornam `ok: false` com `issues` (`code`, `path`, `severity`,
|
|
93
|
+
`source`, `message`, `suggestion`); rejeições da SEFIN trazem a regra oficial em
|
|
94
|
+
`suggestion`. Falhas de infraestrutura rejeitam a promise. `toAgentIssues(error)`
|
|
95
|
+
converte erros do SDK para esse formato.
|
|
96
|
+
|
|
97
|
+
Para montar o seu próprio servidor MCP com outro transporte, use
|
|
98
|
+
`createNfseMcpServer(options).handle(mensagem)` de `@useinvio/nfse-sdk/mcp`.
|
|
99
|
+
|
|
100
|
+
## JSON Schema
|
|
101
|
+
|
|
102
|
+
`DPS_JSON_REQUEST_SCHEMA` descreve o `DpsJsonRequest` em JSON Schema 2020-12 com
|
|
103
|
+
um subconjunto portável de palavras-chave. Ele cobre formatos e domínios de
|
|
104
|
+
códigos, mas não as regras entre campos (regime × `totTrib`, nacional ×
|
|
105
|
+
exportação): `validateDpsJsonRequest` continua sendo a autoridade.
|
|
106
|
+
|
|
107
|
+
## Contexto para assistentes de código
|
|
108
|
+
|
|
109
|
+
O pacote publica [`llms.txt`](../../llms.txt), um guia compacto da API para
|
|
110
|
+
assistentes como Claude Code, Cursor e Copilot. Quem for alterar o SDK encontra
|
|
111
|
+
as regras do repositório em [`AGENTS.md`](../../AGENTS.md).
|