@useinvio/nfse-sdk 2.2.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/JSON_MAPPING.md +30 -17
  2. package/README.md +145 -67
  3. package/dist/agent.d.ts +86 -0
  4. package/dist/agent.js +235 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/certificate.d.ts +96 -0
  7. package/dist/certificate.js +218 -0
  8. package/dist/certificate.js.map +1 -0
  9. package/dist/certificateValidation.d.ts +12 -5
  10. package/dist/certificateValidation.js +25 -9
  11. package/dist/certificateValidation.js.map +1 -1
  12. package/dist/client.d.ts +8 -3
  13. package/dist/client.js +8 -7
  14. package/dist/client.js.map +1 -1
  15. package/dist/decimal.d.ts +7 -0
  16. package/dist/decimal.js +24 -0
  17. package/dist/decimal.js.map +1 -0
  18. package/dist/dpsJson.js +15 -45
  19. package/dist/dpsJson.js.map +1 -1
  20. package/dist/dpsJsonSchema.d.ts +17 -0
  21. package/dist/dpsJsonSchema.js +184 -0
  22. package/dist/dpsJsonSchema.js.map +1 -0
  23. package/dist/dpsNormalization.d.ts +10 -0
  24. package/dist/dpsNormalization.js +85 -0
  25. package/dist/dpsNormalization.js.map +1 -0
  26. package/dist/emissaoNota.d.ts +4 -4
  27. package/dist/emissaoNota.js +27 -8
  28. package/dist/emissaoNota.js.map +1 -1
  29. package/dist/fiscalDomains.d.ts +22 -0
  30. package/dist/fiscalDomains.js +99 -0
  31. package/dist/fiscalDomains.js.map +1 -0
  32. package/dist/fiscalValidation.d.ts +1 -0
  33. package/dist/fiscalValidation.js +119 -88
  34. package/dist/fiscalValidation.js.map +1 -1
  35. package/dist/index.d.ts +9 -4
  36. package/dist/index.js +5 -3
  37. package/dist/index.js.map +1 -1
  38. package/dist/jsonSchemaCheck.d.ts +12 -0
  39. package/dist/jsonSchemaCheck.js +70 -0
  40. package/dist/jsonSchemaCheck.js.map +1 -0
  41. package/dist/loadPfx.d.ts +2 -0
  42. package/dist/loadPfx.js +2 -1
  43. package/dist/loadPfx.js.map +1 -1
  44. package/dist/sefinClient.d.ts +10 -4
  45. package/dist/sefinClient.js +22 -4
  46. package/dist/sefinClient.js.map +1 -1
  47. package/dist/signXml.d.ts +3 -3
  48. package/dist/signXml.js +8 -6
  49. package/dist/signXml.js.map +1 -1
  50. package/dist/xmlInspection.d.ts +6 -0
  51. package/dist/xmlInspection.js +62 -0
  52. package/dist/xmlInspection.js.map +1 -0
  53. package/dist/xsdValidation.d.ts +17 -5
  54. package/dist/xsdValidation.js +75 -67
  55. package/dist/xsdValidation.js.map +1 -1
  56. package/docs/CORRECOES_EMISSAO.md +55 -0
  57. package/docs/FISCAL_MATRIX.md +11 -0
  58. package/docs/REGRAS_NEGOCIO_EMISSAO.md +317 -0
  59. package/examples/README.md +4 -1
  60. package/examples/client-resource.ts +8 -44
  61. package/examples/emit-homologation.ts +4 -40
  62. package/examples/generate-dps-xml.ts +3 -40
  63. package/examples/handle-errors.ts +6 -5
  64. package/examples/payloads.ts +36 -0
  65. package/llms.txt +22 -7
  66. package/package.json +9 -4
package/dist/agent.js ADDED
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Framework-neutral tool definitions for MCP servers and LLM agents.
3
+ *
4
+ * Each tool carries a JSON Schema for input and output, MCP-style annotations
5
+ * and a `run` handler. Adapters (MCP, OpenAI, LangChain, Vercel AI SDK) only
6
+ * need to map these fields. Certificate and environment are host
7
+ * configuration passed in `NfseAgentContext`, never tool input, so a model
8
+ * cannot select production or see key material.
9
+ */
10
+ import { CertificateValidationError } from './certificateValidation.js';
11
+ import { DEFAULT_AMBIENTE } from './config.js';
12
+ import { buildDpsFromJson } from './dpsJson.js';
13
+ import { DPS_JSON_REQUEST_SCHEMA } from './dpsJsonSchema.js';
14
+ import { EmitirNotaError } from './emissaoNota.js';
15
+ import { DpsFiscalValidationError, validateDpsJsonRequest } from './fiscalValidation.js';
16
+ import { gunzipBase64 } from './gzipB64.js';
17
+ import { checkJsonSchema } from './jsonSchemaCheck.js';
18
+ import { consultarNfse, extrairErros } from './sefinClient.js';
19
+ import { DpsXsdValidationError, validateDpsXmlAgainstXsd } from './xsdValidation.js';
20
+ export { DPS_JSON_REQUEST_SCHEMA } from './dpsJsonSchema.js';
21
+ function fromValidationIssue(issue) {
22
+ return { ...issue };
23
+ }
24
+ function sefinIssue(erro) {
25
+ const authorization = erro.Codigo === 'INVALID_AUTHORIZATION_RESPONSE';
26
+ return {
27
+ code: erro.Codigo,
28
+ path: '$',
29
+ severity: 'error',
30
+ source: authorization ? 'sdk' : 'sefin',
31
+ message: erro.Complemento ? `${erro.Descricao} (${erro.Complemento})` : erro.Descricao,
32
+ ...(authorization ? { suggestion: 'Consulte a nota pela chave ou concilie a DPS antes de reenviar.' } : {}),
33
+ };
34
+ }
35
+ /**
36
+ * Converts known SDK errors to `NfseAgentIssue[]`. Returns `undefined` for
37
+ * anything else (transport, XSD engine, programming errors) so the caller can rethrow.
38
+ */
39
+ export function toAgentIssues(error) {
40
+ if (error instanceof DpsFiscalValidationError)
41
+ return error.issues.map(fromValidationIssue);
42
+ if (error instanceof DpsXsdValidationError) {
43
+ return error.details.map((message) => ({ code: 'XSD_INVALID', path: '$', severity: 'error', source: 'xsd', message }));
44
+ }
45
+ if (error instanceof CertificateValidationError) {
46
+ return [{ code: error.code, path: '$', severity: 'error', source: 'certificate', message: error.message }];
47
+ }
48
+ if (error instanceof EmitirNotaError) {
49
+ const issues = error.erros.map(sefinIssue);
50
+ return issues.length ? issues : [{ code: 'SEFIN_REJECTED', path: '$', severity: 'error', source: 'sefin', message: error.message }];
51
+ }
52
+ return undefined;
53
+ }
54
+ function resolveAmbiente(context) {
55
+ return context?.ambiente ?? DEFAULT_AMBIENTE;
56
+ }
57
+ function stripEmissao(path) {
58
+ return path.replace(/^emissao\./, '');
59
+ }
60
+ /** Fields the schema does not accept are reported instead of silently ignored by the builder. */
61
+ function unsupportedFieldIssues(request) {
62
+ return checkJsonSchema(DPS_JSON_REQUEST_SCHEMA, request)
63
+ .filter(({ keyword }) => keyword === 'additionalProperties')
64
+ .map(({ path }) => ({
65
+ code: 'UNSUPPORTED_FIELD',
66
+ path: stripEmissao(path),
67
+ severity: 'error',
68
+ source: 'schema',
69
+ message: `${path} nao e um campo suportado pelo schema da DPS`,
70
+ suggestion: 'Remova o campo ou use o nome canonico descrito no schema.',
71
+ }));
72
+ }
73
+ function environmentIssue(request, ambiente) {
74
+ const requested = request?.ambiente;
75
+ if (requested === undefined || requested === ambiente)
76
+ return [];
77
+ return [{
78
+ code: 'AMBIENTE_NOT_ALLOWED',
79
+ path: 'ambiente',
80
+ severity: 'error',
81
+ source: 'environment',
82
+ message: `O ambiente e definido pelo host (${ambiente}); a requisicao pediu ${String(requested)}.`,
83
+ suggestion: 'Remova o campo ambiente da requisicao.',
84
+ }];
85
+ }
86
+ function validateForAgent(input, context) {
87
+ const ambiente = resolveAmbiente(context);
88
+ const request = input?.request;
89
+ const hostIssues = environmentIssue(request, ambiente);
90
+ const withAmbiente = request && typeof request === 'object' && !Array.isArray(request) ? { ...request, ambiente } : request;
91
+ const report = validateDpsJsonRequest(withAmbiente);
92
+ const structural = report.issues.some((issue) => issue.code === 'INVALID_STRUCTURE');
93
+ const issues = [
94
+ ...hostIssues,
95
+ ...(structural ? [] : unsupportedFieldIssues(withAmbiente)),
96
+ ...report.issues.map(fromValidationIssue),
97
+ ];
98
+ return { ambiente, report, issues, warnings: report.warnings.map(fromValidationIssue), request: withAmbiente };
99
+ }
100
+ const { $schema: _draft, ...requestSchema } = DPS_JSON_REQUEST_SCHEMA;
101
+ const { ambiente: _ambiente, ...requestProperties } = requestSchema.properties;
102
+ /** `DPS_JSON_REQUEST_SCHEMA` without `ambiente`, which belongs to the host. */
103
+ export const DPS_AGENT_REQUEST_SCHEMA = { ...requestSchema, properties: requestProperties };
104
+ const DPS_REQUEST_INPUT_SCHEMA = {
105
+ type: 'object',
106
+ properties: { request: DPS_AGENT_REQUEST_SCHEMA },
107
+ required: ['request'],
108
+ additionalProperties: false,
109
+ };
110
+ const ISSUE_SCHEMA = {
111
+ type: 'object',
112
+ properties: {
113
+ code: { type: 'string', description: 'Codigo estavel do problema, ex.: TOT_TRIB_REQUIRED ou codigo SEFIN.' },
114
+ path: { type: 'string', description: 'Campo afetado; $ quando global.' },
115
+ severity: { type: 'string', enum: ['error', 'warning'] },
116
+ source: { type: 'string', enum: ['sdk', 'invio', 'schema', 'xsd', 'sefin', 'certificate', 'environment'] },
117
+ message: { type: 'string' },
118
+ suggestion: { type: 'string' },
119
+ },
120
+ required: ['code', 'path', 'severity', 'source', 'message'],
121
+ additionalProperties: false,
122
+ };
123
+ const ISSUES = { type: 'array', items: ISSUE_SCHEMA };
124
+ const AMBIENTE = { type: 'string', enum: ['restrita', 'producao'] };
125
+ export const validateDpsTool = {
126
+ name: 'validate_dps',
127
+ title: 'Validar DPS da NFS-e',
128
+ description: 'Valida uma requisicao de DPS (NFS-e Nacional) sem certificado, sem rede e sem efeitos colaterais. ' +
129
+ 'Retorna issues com code, path, message e suggestion; corrija os campos indicados e valide novamente ate valid=true. ' +
130
+ 'Nao invente codigos fiscais (cTribNac, regime, tributacao): pergunte ao usuario quando faltarem.',
131
+ inputSchema: DPS_REQUEST_INPUT_SCHEMA,
132
+ outputSchema: {
133
+ type: 'object',
134
+ properties: { valid: { type: 'boolean' }, schemaVersion: { type: 'string' }, ambiente: AMBIENTE, issues: ISSUES, warnings: ISSUES },
135
+ required: ['valid', 'schemaVersion', 'ambiente', 'issues', 'warnings'],
136
+ additionalProperties: false,
137
+ },
138
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
139
+ requiresCertificate: false,
140
+ async run(input, context) {
141
+ const { ambiente, report, issues, warnings } = validateForAgent(input, context);
142
+ return { valid: issues.length === 0, schemaVersion: report.schemaVersion, ambiente, issues, warnings };
143
+ },
144
+ };
145
+ export const buildDpsXmlTool = {
146
+ name: 'build_dps_xml',
147
+ title: 'Gerar XML da DPS',
148
+ description: 'Valida a requisicao e gera o XML nao assinado da DPS, conferido contra o XSD oficial v1.01. ' +
149
+ 'Nao assina nem transmite. Use para revisar a nota antes de pedir a emissao ao usuario.',
150
+ inputSchema: DPS_REQUEST_INPUT_SCHEMA,
151
+ outputSchema: {
152
+ type: 'object',
153
+ properties: {
154
+ ok: { type: 'boolean' },
155
+ ambiente: AMBIENTE,
156
+ dpsId: { type: 'string', description: 'Id de 45 caracteres da DPS.' },
157
+ xml: { type: 'string', description: 'XML da DPS nao assinado.' },
158
+ issues: ISSUES,
159
+ warnings: ISSUES,
160
+ },
161
+ required: ['ok', 'ambiente', 'issues', 'warnings'],
162
+ additionalProperties: false,
163
+ },
164
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
165
+ requiresCertificate: false,
166
+ async run(input, context) {
167
+ const { ambiente, issues, warnings, request } = validateForAgent(input, context);
168
+ if (issues.length)
169
+ return { ok: false, ambiente, issues, warnings };
170
+ try {
171
+ const built = buildDpsFromJson(request);
172
+ validateDpsXmlAgainstXsd(built.xml);
173
+ return { ok: true, ambiente, dpsId: built.id, xml: built.xml, issues: [], warnings };
174
+ }
175
+ catch (error) {
176
+ const mapped = toAgentIssues(error);
177
+ if (!mapped)
178
+ throw error;
179
+ return { ok: false, ambiente, issues: mapped, warnings };
180
+ }
181
+ },
182
+ };
183
+ export const getNfseTool = {
184
+ name: 'get_nfse',
185
+ title: 'Consultar NFS-e',
186
+ description: 'Consulta uma NFS-e na SEFIN pela chave de acesso de 50 digitos, no ambiente configurado pelo host. ' +
187
+ 'Use tambem para conciliar uma emissao com resposta ambigua antes de qualquer reenvio.',
188
+ inputSchema: {
189
+ type: 'object',
190
+ properties: { chaveAcesso: { type: 'string', pattern: '^\\d{50}$', description: 'Chave de acesso da NFS-e, 50 digitos.' } },
191
+ required: ['chaveAcesso'],
192
+ additionalProperties: false,
193
+ },
194
+ outputSchema: {
195
+ type: 'object',
196
+ properties: {
197
+ ok: { type: 'boolean' },
198
+ ambiente: AMBIENTE,
199
+ chaveAcesso: { type: 'string' },
200
+ status: { type: 'number', description: 'Status HTTP da SEFIN.' },
201
+ nfseXml: { type: 'string', description: 'XML da NFS-e quando retornado.' },
202
+ body: { description: 'Corpo da resposta da SEFIN, sem o XML compactado.' },
203
+ issues: ISSUES,
204
+ },
205
+ required: ['ok', 'ambiente', 'chaveAcesso', 'issues'],
206
+ additionalProperties: false,
207
+ },
208
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
209
+ requiresCertificate: true,
210
+ async run(input, context) {
211
+ const ambiente = resolveAmbiente(context);
212
+ const chaveAcesso = String(input?.chaveAcesso ?? '');
213
+ const fail = (issue) => ({ ok: false, ambiente, chaveAcesso, issues: [issue] });
214
+ if (!/^\d{50}$/.test(chaveAcesso)) {
215
+ return fail({ code: 'CHAVE_ACESSO_INVALID_FORMAT', path: 'chaveAcesso', severity: 'error', source: 'sdk', message: 'chaveAcesso deve ter 50 digitos numericos.' });
216
+ }
217
+ if (!context?.pfx) {
218
+ return fail({ code: 'CERTIFICATE_REQUIRED', path: '$', severity: 'error', source: 'certificate', message: 'O host nao configurou um certificado A1 para consultar a SEFIN.' });
219
+ }
220
+ const { status, body } = await consultarNfse(chaveAcesso, context.pfx, ambiente);
221
+ const { nfseXmlGZipB64, NfseXmlGZipB64, ...rest } = (body && typeof body === 'object' && !Array.isArray(body) ? body : { value: body });
222
+ const compressed = nfseXmlGZipB64 ?? NfseXmlGZipB64;
223
+ if (status < 200 || status >= 300) {
224
+ const issues = extrairErros(body).map(sefinIssue);
225
+ return { ok: false, ambiente, chaveAcesso, status, body: rest, issues: issues.length ? issues : [
226
+ { code: `HTTP_${status}`, path: '$', severity: 'error', source: 'sefin', message: `A SEFIN respondeu HTTP ${status}.` },
227
+ ] };
228
+ }
229
+ const nfseXml = typeof compressed === 'string' ? gunzipBase64(compressed) : undefined;
230
+ return { ok: true, ambiente, chaveAcesso, status, ...(nfseXml ? { nfseXml } : {}), body: rest, issues: [] };
231
+ },
232
+ };
233
+ /** All tools, in the order an agent typically needs them. */
234
+ export const nfseAgentTools = [validateDpsTool, buildDpsXmlTool, getNfseTool];
235
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import { type KeyObject } from 'node:crypto';
2
+ import https from 'node:https';
3
+ import { inspect } from 'node:util';
4
+ import forge from 'node-forge';
5
+ import { type PfxMaterial } from './loadPfx.js';
6
+ /** Public, non-secret facts about an A1 certificate. Safe to log. */
7
+ export interface NfseCertificateInfo {
8
+ /** Subject common name, e.g. `EMPRESA LTDA:12345678000195`. */
9
+ subject: string;
10
+ issuer: string;
11
+ /** CNPJ from the ICP-Brasil otherName (OID 2.16.76.1.3.3), when present. */
12
+ cnpj?: string;
13
+ /** CPF from the ICP-Brasil otherName (OID 2.16.76.1.3.1), when present. */
14
+ cpf?: string;
15
+ notBefore: Date;
16
+ notAfter: Date;
17
+ serialNumber: string;
18
+ /** SHA-256 fingerprint, colon-separated hex. Use it to identify the certificate in logs. */
19
+ fingerprintSha256: string;
20
+ }
21
+ /** Everything the SDK accepts as signing + mTLS material. */
22
+ export type CertificateInput = NfseCertificate | PfxMaterial;
23
+ export interface NfseCertificateFromPemInput {
24
+ /** Private key in PEM (PKCS#1 or PKCS#8). */
25
+ key: string | Buffer;
26
+ /** Holder certificate in PEM. */
27
+ cert: string | Buffer;
28
+ /** Passphrase when the PEM key is encrypted. */
29
+ passphrase?: string;
30
+ }
31
+ /** Environment variable names read by {@link NfseCertificate.fromEnv}. */
32
+ export declare const NFSE_CERT_ENV: {
33
+ readonly path: "NFSE_CERT_PATH";
34
+ readonly base64: "NFSE_CERT_BASE64";
35
+ readonly password: "NFSE_CERT_PASSWORD";
36
+ readonly passwordFile: "NFSE_CERT_PASSWORD_FILE";
37
+ };
38
+ /** @internal Material the signer and the HTTPS client need. Never exported from the package root. */
39
+ export interface CertificateCredentials {
40
+ privateKey: KeyObject | string;
41
+ certPem: string;
42
+ certDerBase64: string;
43
+ tls: Pick<https.RequestOptions, 'agent' | 'key' | 'cert'>;
44
+ }
45
+ /**
46
+ * Reads CNPJ/CPF from the ICP-Brasil subjectAltName otherName fields. Falls
47
+ * back to the `NOME:DOCUMENTO` suffix of the common name used by ICP-Brasil CAs.
48
+ */
49
+ export declare function icpBrasilTaxIds(cert: forge.pki.Certificate, commonName?: string): {
50
+ cnpj?: string;
51
+ cpf?: string;
52
+ };
53
+ /**
54
+ * An A1 (ICP-Brasil) certificate loaded for signing and mTLS.
55
+ *
56
+ * The private key is kept as a non-exportable-by-accident `KeyObject` and a
57
+ * dedicated TLS agent, both held outside the object. The PFX bytes and the
58
+ * password are not retained. `console.log`, `JSON.stringify` and error
59
+ * serializers only ever see {@link NfseCertificateInfo}.
60
+ */
61
+ export declare class NfseCertificate implements NfseCertificateInfo {
62
+ readonly subject: string;
63
+ readonly issuer: string;
64
+ readonly cnpj?: string;
65
+ readonly cpf?: string;
66
+ readonly notBefore: Date;
67
+ readonly notAfter: Date;
68
+ readonly serialNumber: string;
69
+ readonly fingerprintSha256: string;
70
+ private constructor();
71
+ /** Loads a `.pfx`/`.p12` from memory. */
72
+ static fromPfx(pfx: Buffer | Uint8Array, password: string): NfseCertificate;
73
+ /** Loads a `.pfx`/`.p12` file from disk. */
74
+ static fromFile(path: string, password: string): NfseCertificate;
75
+ /** Loads a base64-encoded PFX (whitespace and `data:` URLs accepted), the usual format for env vars and secret managers. */
76
+ static fromBase64(content: string, password: string): NfseCertificate;
77
+ /** Loads a PEM key + certificate pair, e.g. extracted once with `openssl pkcs12 -legacy`. */
78
+ static fromPem(input: NfseCertificateFromPemInput): NfseCertificate;
79
+ /**
80
+ * Loads the certificate from environment variables:
81
+ * `NFSE_CERT_PATH` or `NFSE_CERT_BASE64`, plus `NFSE_CERT_PASSWORD` or
82
+ * `NFSE_CERT_PASSWORD_FILE` (Docker/Kubernetes secrets).
83
+ */
84
+ static fromEnv(env?: NodeJS.ProcessEnv): NfseCertificate;
85
+ /** Wraps legacy {@link PfxMaterial}; the SDK keeps a `KeyObject`, not the PEM string. */
86
+ static fromMaterial(material: PfxMaterial): NfseCertificate;
87
+ isValidAt(now?: Date): boolean;
88
+ /** Whole days until expiry (negative once expired). Handy for renewal alerts. */
89
+ daysUntilExpiry(now?: Date): number;
90
+ /** Closes pooled mTLS sockets. Optional; idle sockets do not keep the process alive. */
91
+ destroy(): void;
92
+ toJSON(): NfseCertificateInfo;
93
+ [inspect.custom](): string;
94
+ }
95
+ /** @internal Resolves either input shape to signing + TLS material. */
96
+ export declare function resolveCredentials(input: CertificateInput): CertificateCredentials;
@@ -0,0 +1,218 @@
1
+ import { createPrivateKey, X509Certificate } from 'node:crypto';
2
+ import { readFileSync } from 'node:fs';
3
+ import https from 'node:https';
4
+ import { createSecureContext } from 'node:tls';
5
+ import { inspect } from 'node:util';
6
+ import forge from 'node-forge';
7
+ import { CertificateValidationError } from './certificateValidation.js';
8
+ import { parsePfx } from './loadPfx.js';
9
+ /** Environment variable names read by {@link NfseCertificate.fromEnv}. */
10
+ export const NFSE_CERT_ENV = {
11
+ path: 'NFSE_CERT_PATH',
12
+ base64: 'NFSE_CERT_BASE64',
13
+ password: 'NFSE_CERT_PASSWORD',
14
+ passwordFile: 'NFSE_CERT_PASSWORD_FILE',
15
+ };
16
+ const ICP_BRASIL_CNPJ_OID = '2.16.76.1.3.3';
17
+ const ICP_BRASIL_CPF_OID = '2.16.76.1.3.1';
18
+ const secrets = new WeakMap();
19
+ function readInfo(certPem) {
20
+ const x509 = new X509Certificate(certPem);
21
+ const forgeCert = forge.pki.certificateFromPem(certPem);
22
+ const commonName = String(forgeCert.subject.getField('CN')?.value ?? x509.subject);
23
+ const { cnpj, cpf } = icpBrasilTaxIds(forgeCert, commonName);
24
+ return {
25
+ subject: commonName,
26
+ issuer: String(forgeCert.issuer.getField('CN')?.value ?? x509.issuer),
27
+ ...(cnpj ? { cnpj } : {}),
28
+ ...(cpf ? { cpf } : {}),
29
+ notBefore: new Date(x509.validFrom),
30
+ notAfter: new Date(x509.validTo),
31
+ serialNumber: x509.serialNumber,
32
+ fingerprintSha256: x509.fingerprint256,
33
+ };
34
+ }
35
+ /**
36
+ * Reads CNPJ/CPF from the ICP-Brasil subjectAltName otherName fields. Falls
37
+ * back to the `NOME:DOCUMENTO` suffix of the common name used by ICP-Brasil CAs.
38
+ */
39
+ export function icpBrasilTaxIds(cert, commonName = String(cert.subject.getField('CN')?.value ?? '')) {
40
+ const found = {};
41
+ const extension = cert.getExtension('subjectAltName');
42
+ if (extension?.value) {
43
+ try {
44
+ const generalNames = forge.asn1.fromDer(extension.value).value;
45
+ for (const name of generalNames) {
46
+ // otherName is context-specific tag [0]: SEQUENCE { type-id OID, [0] EXPLICIT value }
47
+ if (name.tagClass !== forge.asn1.Class.CONTEXT_SPECIFIC || name.type !== 0 || !Array.isArray(name.value))
48
+ continue;
49
+ const [oidNode, wrapped] = name.value;
50
+ if (!oidNode || !wrapped || typeof oidNode.value !== 'string')
51
+ continue;
52
+ const oid = forge.asn1.derToOid(oidNode.value);
53
+ const inner = Array.isArray(wrapped.value) ? wrapped.value[0] : undefined;
54
+ const text = typeof inner?.value === 'string' ? inner.value : '';
55
+ if (oid === ICP_BRASIL_CNPJ_OID && /^\d{14}$/.test(text))
56
+ found.cnpj = text;
57
+ // ICP-Brasil e-CPF layout: birth date (8) + CPF (11) + ...
58
+ if (oid === ICP_BRASIL_CPF_OID && /^\d{19}/.test(text))
59
+ found.cpf = text.slice(8, 19);
60
+ }
61
+ }
62
+ catch {
63
+ // Non-ICP certificates may carry SANs in other shapes; fall back to the CN.
64
+ }
65
+ }
66
+ if (!found.cnpj && !found.cpf) {
67
+ const suffix = commonName.match(/(?:^|[:\s])(\d{14}|\d{11})$/)?.[1];
68
+ if (suffix?.length === 14)
69
+ found.cnpj = suffix;
70
+ else if (suffix)
71
+ found.cpf = suffix;
72
+ }
73
+ return found;
74
+ }
75
+ function readPasswordFromEnv(env) {
76
+ const file = env[NFSE_CERT_ENV.passwordFile]?.trim();
77
+ if (file)
78
+ return readFileSync(file, 'utf8').replace(/\r?\n$/, '');
79
+ const password = env[NFSE_CERT_ENV.password];
80
+ if (password === undefined) {
81
+ throw new CertificateValidationError('CERTIFICATE_PASSWORD_MISSING', `Defina ${NFSE_CERT_ENV.password} ou ${NFSE_CERT_ENV.passwordFile} com a senha do certificado A1.`);
82
+ }
83
+ return password;
84
+ }
85
+ function decodeBase64(content) {
86
+ const trimmed = content.trim();
87
+ const payload = trimmed.startsWith('data:') ? trimmed.slice(trimmed.indexOf(',') + 1) : trimmed;
88
+ return Buffer.from(payload.replace(/\s/g, ''), 'base64');
89
+ }
90
+ /**
91
+ * An A1 (ICP-Brasil) certificate loaded for signing and mTLS.
92
+ *
93
+ * The private key is kept as a non-exportable-by-accident `KeyObject` and a
94
+ * dedicated TLS agent, both held outside the object. The PFX bytes and the
95
+ * password are not retained. `console.log`, `JSON.stringify` and error
96
+ * serializers only ever see {@link NfseCertificateInfo}.
97
+ */
98
+ export class NfseCertificate {
99
+ subject;
100
+ issuer;
101
+ cnpj;
102
+ cpf;
103
+ notBefore;
104
+ notAfter;
105
+ serialNumber;
106
+ fingerprintSha256;
107
+ constructor(privateKeyPem, certPem, certDerBase64) {
108
+ Object.assign(this, readInfo(certPem));
109
+ const privateKey = createPrivateKey(privateKeyPem);
110
+ const secureContext = createSecureContext({ key: privateKeyPem, cert: certPem });
111
+ // One agent per certificate: pooled sockets are never shared between tenants.
112
+ const agent = new https.Agent({ keepAlive: true, secureContext });
113
+ secrets.set(this, { privateKey, certPem, certDerBase64, tls: { agent } });
114
+ Object.freeze(this);
115
+ }
116
+ /** Loads a `.pfx`/`.p12` from memory. */
117
+ static fromPfx(pfx, password) {
118
+ let material;
119
+ try {
120
+ material = parsePfx(Buffer.from(pfx), password);
121
+ }
122
+ catch (error) {
123
+ const message = error instanceof Error ? error.message : String(error);
124
+ if (/MAC could not be verified|Invalid password|senha incorreta/i.test(message)) {
125
+ throw new CertificateValidationError('CERTIFICATE_INVALID_PASSWORD', 'Senha do certificado A1 incorreta.');
126
+ }
127
+ throw new CertificateValidationError('CERTIFICATE_UNREADABLE', `Nao foi possivel ler o certificado A1 (.pfx): ${message}`);
128
+ }
129
+ return new NfseCertificate(material.privateKeyPem, material.certPem, material.certDerBase64);
130
+ }
131
+ /** Loads a `.pfx`/`.p12` file from disk. */
132
+ static fromFile(path, password) {
133
+ return NfseCertificate.fromPfx(readFileSync(path), password);
134
+ }
135
+ /** Loads a base64-encoded PFX (whitespace and `data:` URLs accepted), the usual format for env vars and secret managers. */
136
+ static fromBase64(content, password) {
137
+ return NfseCertificate.fromPfx(decodeBase64(content), password);
138
+ }
139
+ /** Loads a PEM key + certificate pair, e.g. extracted once with `openssl pkcs12 -legacy`. */
140
+ static fromPem(input) {
141
+ let privateKeyPem;
142
+ let certPem;
143
+ try {
144
+ const key = createPrivateKey({ key: input.key, format: 'pem', ...(input.passphrase !== undefined ? { passphrase: input.passphrase } : {}) });
145
+ privateKeyPem = key.export({ type: 'pkcs8', format: 'pem' }).toString();
146
+ certPem = new X509Certificate(input.cert).toString();
147
+ }
148
+ catch (error) {
149
+ const message = error instanceof Error ? error.message : String(error);
150
+ throw new CertificateValidationError('CERTIFICATE_UNREADABLE', `Nao foi possivel ler a chave/certificado PEM: ${message}`);
151
+ }
152
+ const certDerBase64 = new X509Certificate(certPem).raw.toString('base64');
153
+ return new NfseCertificate(privateKeyPem, certPem, certDerBase64);
154
+ }
155
+ /**
156
+ * Loads the certificate from environment variables:
157
+ * `NFSE_CERT_PATH` or `NFSE_CERT_BASE64`, plus `NFSE_CERT_PASSWORD` or
158
+ * `NFSE_CERT_PASSWORD_FILE` (Docker/Kubernetes secrets).
159
+ */
160
+ static fromEnv(env = process.env) {
161
+ const path = env[NFSE_CERT_ENV.path]?.trim();
162
+ const base64 = env[NFSE_CERT_ENV.base64]?.trim();
163
+ if (!path && !base64) {
164
+ throw new CertificateValidationError('CERTIFICATE_MISSING', `Defina ${NFSE_CERT_ENV.path} (arquivo .pfx) ou ${NFSE_CERT_ENV.base64} (PFX em base64).`);
165
+ }
166
+ const password = readPasswordFromEnv(env);
167
+ return path ? NfseCertificate.fromFile(path, password) : NfseCertificate.fromBase64(base64, password);
168
+ }
169
+ /** Wraps legacy {@link PfxMaterial}; the SDK keeps a `KeyObject`, not the PEM string. */
170
+ static fromMaterial(material) {
171
+ return new NfseCertificate(material.privateKeyPem, material.certPem, material.certDerBase64);
172
+ }
173
+ isValidAt(now = new Date()) {
174
+ return now >= this.notBefore && now < this.notAfter;
175
+ }
176
+ /** Whole days until expiry (negative once expired). Handy for renewal alerts. */
177
+ daysUntilExpiry(now = new Date()) {
178
+ return Math.floor((this.notAfter.getTime() - now.getTime()) / 86_400_000);
179
+ }
180
+ /** Closes pooled mTLS sockets. Optional; idle sockets do not keep the process alive. */
181
+ destroy() {
182
+ const agent = secrets.get(this)?.tls.agent;
183
+ if (agent instanceof https.Agent)
184
+ agent.destroy();
185
+ }
186
+ toJSON() {
187
+ return {
188
+ subject: this.subject,
189
+ issuer: this.issuer,
190
+ ...(this.cnpj ? { cnpj: this.cnpj } : {}),
191
+ ...(this.cpf ? { cpf: this.cpf } : {}),
192
+ notBefore: this.notBefore,
193
+ notAfter: this.notAfter,
194
+ serialNumber: this.serialNumber,
195
+ fingerprintSha256: this.fingerprintSha256,
196
+ };
197
+ }
198
+ [inspect.custom]() {
199
+ const holder = this.cnpj ? `cnpj=${this.cnpj}` : this.cpf ? `cpf=${this.cpf}` : `subject=${JSON.stringify(this.subject)}`;
200
+ return `NfseCertificate { ${holder}, notAfter=${this.notAfter.toISOString()}, fingerprintSha256=${this.fingerprintSha256} }`;
201
+ }
202
+ }
203
+ /** @internal Resolves either input shape to signing + TLS material. */
204
+ export function resolveCredentials(input) {
205
+ if (input instanceof NfseCertificate) {
206
+ const found = secrets.get(input);
207
+ if (!found)
208
+ throw new Error('NfseCertificate sem material de chave.');
209
+ return found;
210
+ }
211
+ return {
212
+ privateKey: input.privateKeyPem,
213
+ certPem: input.certPem,
214
+ certDerBase64: input.certDerBase64,
215
+ tls: { key: input.privateKeyPem, cert: input.certPem },
216
+ };
217
+ }
218
+ //# sourceMappingURL=certificate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certificate.js","sourceRoot":"","sources":["../certificate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAkB,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAoB,MAAM,cAAc,CAAC;AA8B1D,0EAA0E;AAC1E,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,kBAAkB;IAC1B,QAAQ,EAAE,oBAAoB;IAC9B,YAAY,EAAE,yBAAyB;CAC/B,CAAC;AAUX,MAAM,mBAAmB,GAAG,eAAe,CAAC;AAC5C,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAE3C,MAAM,OAAO,GAAG,IAAI,OAAO,EAA2C,CAAC;AAEvE,SAAS,QAAQ,CAAC,OAAe;IAC/B,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IACnF,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,eAAe,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC7D,OAAO;QACL,OAAO,EAAE,UAAU;QACnB,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;QACrE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvB,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QACnC,QAAQ,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;QAChC,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,iBAAiB,EAAE,IAAI,CAAC,cAAc;KACvC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAA2B,EAAE,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;IACxH,MAAM,KAAK,GAAoC,EAAE,CAAC;IAClD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAmC,CAAC;IACxF,IAAI,SAAS,EAAE,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,KAA0B,CAAC;YACpF,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;gBAChC,sFAAsF;gBACtF,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;oBAAE,SAAS;gBACnH,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,KAA0B,CAAC;gBAC3D,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ;oBAAE,SAAS;gBACxE,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAiC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC3G,MAAM,IAAI,GAAG,OAAO,KAAK,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjE,IAAI,GAAG,KAAK,mBAAmB,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;gBAC5E,2DAA2D;gBAC3D,IAAI,GAAG,KAAK,kBAAkB,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACxF,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,4EAA4E;QAC9E,CAAC;IACH,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,6BAA6B,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACpE,IAAI,MAAM,EAAE,MAAM,KAAK,EAAE;YAAE,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC;aAC1C,IAAI,MAAM;YAAE,KAAK,CAAC,GAAG,GAAG,MAAM,CAAC;IACtC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAsB;IACjD,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC;IACrD,IAAI,IAAI;QAAE,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,0BAA0B,CAClC,8BAA8B,EAC9B,UAAU,aAAa,CAAC,QAAQ,OAAO,aAAa,CAAC,YAAY,iCAAiC,CACnG,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAChG,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,eAAe;IACjB,OAAO,CAAU;IACjB,MAAM,CAAU;IAChB,IAAI,CAAU;IACd,GAAG,CAAU;IACb,SAAS,CAAQ;IACjB,QAAQ,CAAQ;IAChB,YAAY,CAAU;IACtB,iBAAiB,CAAU;IAEpC,YAAoB,aAAqB,EAAE,OAAe,EAAE,aAAqB;QAC/E,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QACvC,MAAM,UAAU,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;QACnD,MAAM,aAAa,GAAG,mBAAmB,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACjF,8EAA8E;QAC9E,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAC1E,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,yCAAyC;IACzC,MAAM,CAAC,OAAO,CAAC,GAAwB,EAAE,QAAgB;QACvD,IAAI,QAAwC,CAAC;QAC7C,IAAI,CAAC;YACH,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,IAAI,6DAA6D,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChF,MAAM,IAAI,0BAA0B,CAAC,8BAA8B,EAAE,oCAAoC,CAAC,CAAC;YAC7G,CAAC;YACD,MAAM,IAAI,0BAA0B,CAAC,wBAAwB,EAAE,iDAAiD,OAAO,EAAE,CAAC,CAAC;QAC7H,CAAC;QACD,OAAO,IAAI,eAAe,CAAC,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC/F,CAAC;IAED,4CAA4C;IAC5C,MAAM,CAAC,QAAQ,CAAC,IAAY,EAAE,QAAgB;QAC5C,OAAO,eAAe,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC/D,CAAC;IAED,4HAA4H;IAC5H,MAAM,CAAC,UAAU,CAAC,OAAe,EAAE,QAAgB;QACjD,OAAO,eAAe,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;IAClE,CAAC;IAED,6FAA6F;IAC7F,MAAM,CAAC,OAAO,CAAC,KAAkC;QAC/C,IAAI,aAAqB,CAAC;QAC1B,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,gBAAgB,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7I,aAAa,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;YACxE,OAAO,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,IAAI,0BAA0B,CAAC,wBAAwB,EAAE,iDAAiD,OAAO,EAAE,CAAC,CAAC;QAC7H,CAAC;QACD,MAAM,aAAa,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC1E,OAAO,IAAI,eAAe,CAAC,aAAa,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;IACpE,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,MAAyB,OAAO,CAAC,GAAG;QACjD,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;QACjD,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACrB,MAAM,IAAI,0BAA0B,CAClC,qBAAqB,EACrB,UAAU,aAAa,CAAC,IAAI,sBAAsB,aAAa,CAAC,MAAM,mBAAmB,CAC1F,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,MAAO,EAAE,QAAQ,CAAC,CAAC;IACzG,CAAC;IAED,yFAAyF;IACzF,MAAM,CAAC,YAAY,CAAC,QAAqB;QACvC,OAAO,IAAI,eAAe,CAAC,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC/F,CAAC;IAED,SAAS,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE;QACxB,OAAO,GAAG,IAAI,IAAI,CAAC,SAAS,IAAI,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;IACtD,CAAC;IAED,iFAAiF;IACjF,eAAe,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC;IAC5E,CAAC;IAED,wFAAwF;IACxF,OAAO;QACL,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC;QAC3C,IAAI,KAAK,YAAY,KAAK,CAAC,KAAK;YAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACpD,CAAC;IAED,MAAM;QACJ,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;SAC1C,CAAC;IACJ,CAAC;IAED,CAAC,OAAO,CAAC,MAAM,CAAC;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1H,OAAO,qBAAqB,MAAM,cAAc,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,uBAAuB,IAAI,CAAC,iBAAiB,IAAI,CAAC;IAC/H,CAAC;CACF;AAED,uEAAuE;AACvE,MAAM,UAAU,kBAAkB,CAAC,KAAuB;IACxD,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QACtE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO;QACL,UAAU,EAAE,KAAK,CAAC,aAAa;QAC/B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,GAAG,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE;KACvD,CAAC;AACJ,CAAC"}
@@ -1,7 +1,14 @@
1
- import type { PfxMaterial } from './loadPfx.js';
1
+ import { type CertificateInput } from './certificate.js';
2
+ export type CertificateValidationCode = 'CERTIFICATE_NOT_YET_VALID' | 'CERTIFICATE_EXPIRED' | 'CERTIFICATE_HOLDER_MISMATCH' | 'CERTIFICATE_INVALID_PASSWORD' | 'CERTIFICATE_UNREADABLE' | 'CERTIFICATE_MISSING' | 'CERTIFICATE_PASSWORD_MISSING';
2
3
  export declare class CertificateValidationError extends Error {
3
- readonly code: 'CERTIFICATE_NOT_YET_VALID' | 'CERTIFICATE_EXPIRED' | 'CERTIFICATE_HOLDER_MISMATCH';
4
- constructor(code: 'CERTIFICATE_NOT_YET_VALID' | 'CERTIFICATE_EXPIRED' | 'CERTIFICATE_HOLDER_MISMATCH', message: string);
4
+ readonly code: CertificateValidationCode;
5
+ constructor(code: CertificateValidationCode, message: string);
5
6
  }
6
- /** Final certificate validity and holder check performed immediately before transmission. */
7
- export declare function assertCertificateForProvider(pfx: PfxMaterial, providerTaxId: string, now?: Date): void;
7
+ /** Validity is checked at signing time and again immediately before transmission. */
8
+ export declare function assertCertificateValidity(certificate: CertificateInput, now?: Date): void;
9
+ /**
10
+ * Explicit holder check against the ICP-Brasil CNPJ/CPF fields of the
11
+ * certificate (otherName OIDs 2.16.76.1.3.3 / 2.16.76.1.3.1, or the
12
+ * `NOME:DOCUMENTO` common name). Does not resolve fiscal representation.
13
+ */
14
+ export declare function assertCertificateForProvider(certificate: CertificateInput, providerTaxId: string, now?: Date): void;