@baruk/core 0.5.0 → 0.6.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 (189) hide show
  1. package/.baruk-provenance.json +4 -4
  2. package/dist/cjs/clients/ibge.js +14 -0
  3. package/dist/cjs/clients/ibge.js.map +1 -1
  4. package/dist/cjs/clients/registry/http.js +157 -0
  5. package/dist/cjs/clients/registry/http.js.map +1 -0
  6. package/dist/cjs/clients/registry/ibge-municipios.js +28 -0
  7. package/dist/cjs/clients/registry/ibge-municipios.js.map +1 -0
  8. package/dist/cjs/clients/registry/ibge.js +63 -0
  9. package/dist/cjs/clients/registry/ibge.js.map +1 -0
  10. package/dist/cjs/clients/registry/lookup.js +191 -0
  11. package/dist/cjs/clients/registry/lookup.js.map +1 -0
  12. package/dist/cjs/clients/registry/provider.js +34 -0
  13. package/dist/cjs/clients/registry/provider.js.map +1 -0
  14. package/dist/cjs/clients/registry/resolve.js +47 -0
  15. package/dist/cjs/clients/registry/resolve.js.map +1 -0
  16. package/dist/cjs/clients/registry/serpro.js +149 -0
  17. package/dist/cjs/clients/registry/serpro.js.map +1 -0
  18. package/dist/cjs/clients/registry/service.js +230 -0
  19. package/dist/cjs/clients/registry/service.js.map +1 -0
  20. package/dist/cjs/clients/registry/synthetic.js +165 -0
  21. package/dist/cjs/clients/registry/synthetic.js.map +1 -0
  22. package/dist/cjs/clients/repository.js +6 -2
  23. package/dist/cjs/clients/repository.js.map +1 -1
  24. package/dist/cjs/db/provision-e2e-identity.js +8 -3
  25. package/dist/cjs/db/provision-e2e-identity.js.map +1 -1
  26. package/dist/cjs/fiscal/collection/authorization.js +186 -0
  27. package/dist/cjs/fiscal/collection/authorization.js.map +1 -0
  28. package/dist/cjs/fiscal/collection/competence.js +97 -0
  29. package/dist/cjs/fiscal/collection/competence.js.map +1 -0
  30. package/dist/cjs/fiscal/collection/first-contact.js +204 -0
  31. package/dist/cjs/fiscal/collection/first-contact.js.map +1 -0
  32. package/dist/cjs/fiscal/collection/plan.js +122 -0
  33. package/dist/cjs/fiscal/collection/plan.js.map +1 -0
  34. package/dist/cjs/fiscal/coverage/model.js +11 -1
  35. package/dist/cjs/fiscal/coverage/model.js.map +1 -1
  36. package/dist/cjs/fiscal/credentials/inspect.js +182 -0
  37. package/dist/cjs/fiscal/credentials/inspect.js.map +1 -0
  38. package/dist/cjs/fiscal/credentials/material.js +1 -1
  39. package/dist/cjs/fiscal/credentials/material.js.map +1 -1
  40. package/dist/cjs/fiscal/credentials/onboarding.js +266 -0
  41. package/dist/cjs/fiscal/credentials/onboarding.js.map +1 -0
  42. package/dist/cjs/fiscal/credentials/readiness.js +29 -2
  43. package/dist/cjs/fiscal/credentials/readiness.js.map +1 -1
  44. package/dist/cjs/fiscal/enrollment.js +134 -0
  45. package/dist/cjs/fiscal/enrollment.js.map +1 -0
  46. package/dist/cjs/fiscal/transport/synthetic-tls.js +52 -0
  47. package/dist/cjs/fiscal/transport/synthetic-tls.js.map +1 -1
  48. package/dist/cjs/index.js +196 -113
  49. package/dist/cjs/index.js.map +1 -1
  50. package/dist/cjs/legal/documents.js +64 -4
  51. package/dist/cjs/legal/documents.js.map +1 -1
  52. package/dist/cjs/legal/types.js.map +1 -1
  53. package/dist/cjs/platform/capabilities.js +29 -0
  54. package/dist/cjs/platform/capabilities.js.map +1 -1
  55. package/dist/cjs/rbac/catalog.js +78 -2
  56. package/dist/cjs/rbac/catalog.js.map +1 -1
  57. package/dist/cjs/subscription-billing/index.js +8 -1
  58. package/dist/cjs/subscription-billing/index.js.map +1 -1
  59. package/dist/cjs/subscription-billing/platform-exemption.js +121 -0
  60. package/dist/cjs/subscription-billing/platform-exemption.js.map +1 -0
  61. package/dist/cjs/subscription-billing/service.js +93 -1
  62. package/dist/cjs/subscription-billing/service.js.map +1 -1
  63. package/dist/cjs/vault/repository.js +92 -5
  64. package/dist/cjs/vault/repository.js.map +1 -1
  65. package/dist/clients/ibge.d.ts.map +1 -1
  66. package/dist/clients/ibge.js +14 -0
  67. package/dist/clients/ibge.js.map +1 -1
  68. package/dist/clients/registry/http.d.ts +61 -0
  69. package/dist/clients/registry/http.d.ts.map +1 -0
  70. package/dist/clients/registry/http.js +151 -0
  71. package/dist/clients/registry/http.js.map +1 -0
  72. package/dist/clients/registry/ibge-municipios.d.ts +25 -0
  73. package/dist/clients/registry/ibge-municipios.d.ts.map +1 -0
  74. package/dist/clients/registry/ibge-municipios.js +25 -0
  75. package/dist/clients/registry/ibge-municipios.js.map +1 -0
  76. package/dist/clients/registry/ibge.d.ts +62 -0
  77. package/dist/clients/registry/ibge.d.ts.map +1 -0
  78. package/dist/clients/registry/ibge.js +57 -0
  79. package/dist/clients/registry/ibge.js.map +1 -0
  80. package/dist/clients/registry/lookup.d.ts +94 -0
  81. package/dist/clients/registry/lookup.d.ts.map +1 -0
  82. package/dist/clients/registry/lookup.js +184 -0
  83. package/dist/clients/registry/lookup.js.map +1 -0
  84. package/dist/clients/registry/provider.d.ts +124 -0
  85. package/dist/clients/registry/provider.d.ts.map +1 -0
  86. package/dist/clients/registry/provider.js +39 -0
  87. package/dist/clients/registry/provider.js.map +1 -0
  88. package/dist/clients/registry/resolve.d.ts +36 -0
  89. package/dist/clients/registry/resolve.d.ts.map +1 -0
  90. package/dist/clients/registry/resolve.js +44 -0
  91. package/dist/clients/registry/resolve.js.map +1 -0
  92. package/dist/clients/registry/serpro.d.ts +57 -0
  93. package/dist/clients/registry/serpro.d.ts.map +1 -0
  94. package/dist/clients/registry/serpro.js +143 -0
  95. package/dist/clients/registry/serpro.js.map +1 -0
  96. package/dist/clients/registry/service.d.ts +59 -0
  97. package/dist/clients/registry/service.d.ts.map +1 -0
  98. package/dist/clients/registry/service.js +225 -0
  99. package/dist/clients/registry/service.js.map +1 -0
  100. package/dist/clients/registry/synthetic.d.ts +30 -0
  101. package/dist/clients/registry/synthetic.d.ts.map +1 -0
  102. package/dist/clients/registry/synthetic.js +161 -0
  103. package/dist/clients/registry/synthetic.js.map +1 -0
  104. package/dist/clients/repository.d.ts +4 -0
  105. package/dist/clients/repository.d.ts.map +1 -1
  106. package/dist/clients/repository.js +6 -2
  107. package/dist/clients/repository.js.map +1 -1
  108. package/dist/db/provision-e2e-identity.js +8 -3
  109. package/dist/db/provision-e2e-identity.js.map +1 -1
  110. package/dist/fiscal/collection/authorization.d.ts +152 -0
  111. package/dist/fiscal/collection/authorization.d.ts.map +1 -0
  112. package/dist/fiscal/collection/authorization.js +178 -0
  113. package/dist/fiscal/collection/authorization.js.map +1 -0
  114. package/dist/fiscal/collection/competence.d.ts +66 -0
  115. package/dist/fiscal/collection/competence.d.ts.map +1 -0
  116. package/dist/fiscal/collection/competence.js +90 -0
  117. package/dist/fiscal/collection/competence.js.map +1 -0
  118. package/dist/fiscal/collection/first-contact.d.ts +103 -0
  119. package/dist/fiscal/collection/first-contact.d.ts.map +1 -0
  120. package/dist/fiscal/collection/first-contact.js +201 -0
  121. package/dist/fiscal/collection/first-contact.js.map +1 -0
  122. package/dist/fiscal/collection/plan.d.ts +74 -0
  123. package/dist/fiscal/collection/plan.d.ts.map +1 -0
  124. package/dist/fiscal/collection/plan.js +119 -0
  125. package/dist/fiscal/collection/plan.js.map +1 -0
  126. package/dist/fiscal/coverage/model.d.ts +28 -0
  127. package/dist/fiscal/coverage/model.d.ts.map +1 -1
  128. package/dist/fiscal/coverage/model.js +11 -1
  129. package/dist/fiscal/coverage/model.js.map +1 -1
  130. package/dist/fiscal/credentials/inspect.d.ts +114 -0
  131. package/dist/fiscal/credentials/inspect.d.ts.map +1 -0
  132. package/dist/fiscal/credentials/inspect.js +178 -0
  133. package/dist/fiscal/credentials/inspect.js.map +1 -0
  134. package/dist/fiscal/credentials/material.js +2 -2
  135. package/dist/fiscal/credentials/material.js.map +1 -1
  136. package/dist/fiscal/credentials/onboarding.d.ts +119 -0
  137. package/dist/fiscal/credentials/onboarding.d.ts.map +1 -0
  138. package/dist/fiscal/credentials/onboarding.js +259 -0
  139. package/dist/fiscal/credentials/onboarding.js.map +1 -0
  140. package/dist/fiscal/credentials/readiness.d.ts +30 -3
  141. package/dist/fiscal/credentials/readiness.d.ts.map +1 -1
  142. package/dist/fiscal/credentials/readiness.js +29 -2
  143. package/dist/fiscal/credentials/readiness.js.map +1 -1
  144. package/dist/fiscal/enrollment.d.ts +91 -0
  145. package/dist/fiscal/enrollment.d.ts.map +1 -0
  146. package/dist/fiscal/enrollment.js +126 -0
  147. package/dist/fiscal/enrollment.js.map +1 -0
  148. package/dist/fiscal/transport/synthetic-tls.d.ts +19 -0
  149. package/dist/fiscal/transport/synthetic-tls.d.ts.map +1 -1
  150. package/dist/fiscal/transport/synthetic-tls.js +51 -0
  151. package/dist/fiscal/transport/synthetic-tls.js.map +1 -1
  152. package/dist/index.d.ts +32 -4
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.js +22 -2
  155. package/dist/index.js.map +1 -1
  156. package/dist/legal/documents.d.ts.map +1 -1
  157. package/dist/legal/documents.js +64 -4
  158. package/dist/legal/documents.js.map +1 -1
  159. package/dist/legal/index.d.ts +1 -1
  160. package/dist/legal/index.d.ts.map +1 -1
  161. package/dist/legal/types.d.ts +77 -0
  162. package/dist/legal/types.d.ts.map +1 -1
  163. package/dist/legal/types.js.map +1 -1
  164. package/dist/platform/capabilities.d.ts.map +1 -1
  165. package/dist/platform/capabilities.js +29 -0
  166. package/dist/platform/capabilities.js.map +1 -1
  167. package/dist/rbac/catalog.d.ts.map +1 -1
  168. package/dist/rbac/catalog.js +78 -2
  169. package/dist/rbac/catalog.js.map +1 -1
  170. package/dist/subscription-billing/index.d.ts +3 -1
  171. package/dist/subscription-billing/index.d.ts.map +1 -1
  172. package/dist/subscription-billing/index.js +2 -1
  173. package/dist/subscription-billing/index.js.map +1 -1
  174. package/dist/subscription-billing/platform-exemption.d.ts +89 -0
  175. package/dist/subscription-billing/platform-exemption.d.ts.map +1 -0
  176. package/dist/subscription-billing/platform-exemption.js +113 -0
  177. package/dist/subscription-billing/platform-exemption.js.map +1 -0
  178. package/dist/subscription-billing/service.d.ts +53 -0
  179. package/dist/subscription-billing/service.d.ts.map +1 -1
  180. package/dist/subscription-billing/service.js +92 -1
  181. package/dist/subscription-billing/service.js.map +1 -1
  182. package/dist/vault/repository.d.ts +69 -1
  183. package/dist/vault/repository.d.ts.map +1 -1
  184. package/dist/vault/repository.js +88 -5
  185. package/dist/vault/repository.js.map +1 -1
  186. package/package.json +3 -2
  187. package/src/db/migrations/0060_fiscal_credential_vault_and_run_authorization.sql +321 -0
  188. package/src/db/migrations/0061_client_official_registry_provenance.sql +193 -0
  189. package/src/db/migrations/0062_first_contact_and_capability_truth.sql +119 -0
@@ -0,0 +1,114 @@
1
+ /**
2
+ * O que dá para saber sobre um certificado SEM falar com ninguém.
3
+ *
4
+ * ## Por que a validação local existe, e o que ela não é
5
+ *
6
+ * Um A1 recém-cadastrado tem duas perguntas em aberto, e elas têm custos
7
+ * opostos. "A senha abre o arquivo?" custa milissegundos e nenhuma consequência
8
+ * externa. "A Receita aceita este titular?" custa uma requisição autenticada em
9
+ * nome de um terceiro — e, se ela for feita fora de hora, custa ao CLIENTE um
10
+ * CNPJ bloqueado.
11
+ *
12
+ * Este módulo responde só a primeira família de perguntas. O produto inteiro
13
+ * depende de nunca confundir as duas: `verified_at` (1004) continua significando
14
+ * "o ambiente oficial já aceitou", e nada aqui o preenche.
15
+ *
16
+ * ## Por que o SecureContext, e não uma biblioteca de PKCS#12
17
+ *
18
+ * O Node não expõe leitor de PKCS#12 na API pública — `X509Certificate` lê PEM e
19
+ * DER, não `.pfx`. As saídas óbvias seriam uma dependência nova (superfície
20
+ * grande para uma tela de upload) ou chamar o binário `openssl` (que exige o
21
+ * binário na imagem, e cuja saída de erro cita caminho de arquivo e sujeito do
22
+ * certificado).
23
+ *
24
+ * A saída usada aqui é o leitor de PKCS#12 que já está no processo: o do OpenSSL
25
+ * que o próprio Node embute. `tls.createSecureContext({ pfx, passphrase })` o
26
+ * invoca e LANÇA na hora se a senha não abrir — esse é o teste de senha, e ele
27
+ * não custa nem um socket. O contexto resultante guarda o certificado carregado,
28
+ * e o handle nativo o devolve em DER.
29
+ *
30
+ * A propriedade que isso compra é um ORÁCULO CORRETO: "abre aqui" passa a
31
+ * significar exatamente "abre no handshake real", porque é o mesmo código de
32
+ * OpenSSL, com os mesmos parâmetros, que o transporte de mTLS usaria. Um parser
33
+ * de terceiro poderia aceitar um arquivo que o handshake recusa — e a diferença
34
+ * apareceria só contra o servidor da Receita.
35
+ *
36
+ * ## A primeira escrita usava um servidor TLS em loopback, e estava errada
37
+ *
38
+ * Ela subia um servidor com o `pfx` em `127.0.0.1`, conectava um cliente do
39
+ * mesmo processo e lia o certificado apresentado. Funcionava — e exigia
40
+ * `rejectUnauthorized: false` no cliente, porque um A1 é assinado por uma AC da
41
+ * ICP-Brasil que não está no truststore e o nome nunca seria `localhost`.
42
+ *
43
+ * O guarda `tls-no-bypass` reprovou, e com razão. A resposta certa não era
44
+ * abrir uma exceção nominal para este arquivo: um controle com uma exceção tem
45
+ * duas na semana seguinte. Era não precisar da exceção — o que este caminho
46
+ * consegue, com menos código e sem socket nenhum.
47
+ *
48
+ * Nada toca o disco e nada toca a rede: `pfx` é um `Buffer`, e tudo acontece
49
+ * dentro do processo.
50
+ */
51
+ /** Classe da falha. CLASSE — a mensagem do OpenSSL cita sujeito e caminho. */
52
+ export type CertificateInspectionFailure = 'wrong_password' | 'malformed_material' | 'unsupported_material' | 'inspection_failed';
53
+ export interface CertificateFacts {
54
+ /** sha256 do DER do certificado apresentado, minúsculo e sem dois-pontos. */
55
+ fingerprintSha256: string;
56
+ subjectCommonName: string | null;
57
+ issuerCommonName: string | null;
58
+ /** Últimos 8 caracteres do serial. O serial inteiro identifica sem acrescentar. */
59
+ serialTail: string | null;
60
+ validFrom: string;
61
+ validTo: string;
62
+ /** Já venceu, medido contra o relógio de quem inspeciona. */
63
+ expired: boolean;
64
+ /**
65
+ * CNPJ/CPF lido DO MATERIAL — nunca o digitado no cadastro.
66
+ * `null` quando o certificado não o carrega em forma reconhecível.
67
+ */
68
+ document: string | null;
69
+ }
70
+ export type CertificateInspection = {
71
+ status: 'ok';
72
+ facts: CertificateFacts;
73
+ } | {
74
+ status: 'failed';
75
+ reason: CertificateInspectionFailure;
76
+ };
77
+ /**
78
+ * Inspeciona o material, sem rede e sem disco.
79
+ *
80
+ * NUNCA lança: toda falha vira uma classe. Quem chama é uma rota de upload, e
81
+ * uma exceção com texto de OpenSSL atravessando até o handler é exatamente como
82
+ * o sujeito de um certificado acaba num log.
83
+ */
84
+ /**
85
+ * Inspeciona o material, sem rede e sem disco.
86
+ *
87
+ * NUNCA lança: toda falha vira uma classe. Quem chama é uma rota de upload, e
88
+ * uma exceção com texto de OpenSSL atravessando até o handler é exatamente como
89
+ * o sujeito de um certificado acaba num log.
90
+ *
91
+ * `async` sem `await` é deliberado: o contrato é assíncrono porque a primeira
92
+ * implementação precisava de um handshake, e porque uma leitura de material
93
+ * criptográfico é o tipo de operação que pode voltar a precisar. Mudar a
94
+ * assinatura para síncrona obrigaria todo chamador a mudar junto, por nenhum
95
+ * ganho.
96
+ */
97
+ export declare function inspectPkcs12(pfx: Buffer, passphrase: string | undefined): Promise<CertificateInspection>;
98
+ /**
99
+ * O certificado é DESTE cliente?
100
+ *
101
+ * Três respostas, e a do meio é a que impede o vínculo silencioso:
102
+ *
103
+ * `match` os dois documentos existem e são o mesmo.
104
+ * `mismatch` os dois existem e são diferentes. Exige assinatura humana
105
+ * (a restrição está na 0060, não aqui).
106
+ * `indeterminate` falta um dos dois. Não é aprovação.
107
+ *
108
+ * A comparação é por DÍGITOS: o cadastro do produto guarda o documento sem
109
+ * máscara, o certificado o traz sem máscara, e uma comparação textual passaria a
110
+ * reprovar no dia em que alguém colasse um CNPJ pontuado num dos dois lados.
111
+ */
112
+ export type IdentityMatch = 'match' | 'mismatch' | 'indeterminate';
113
+ export declare function matchIdentity(certificateDocument: string | null, clientDocument: string | null | undefined): IdentityMatch;
114
+ //# sourceMappingURL=inspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../../src/fiscal/credentials/inspect.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,4BAA4B,GACtC,gBAAgB,GAAG,oBAAoB,GAAG,sBAAsB,GAAG,mBAAmB,CAAC;AAEzF,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mFAAmF;IACnF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,4BAA4B,CAAA;CAAE,CAAC;AAe/D;;;;;;GAMG;AACH;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,qBAAqB,CAAC,CAyBhC;AA+GD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,UAAU,GAAG,eAAe,CAAC;AAEnE,wBAAgB,aAAa,CAC3B,mBAAmB,EAAE,MAAM,GAAG,IAAI,EAClC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACxC,aAAa,CAKf"}
@@ -0,0 +1,178 @@
1
+ import { createSecureContext } from 'node:tls';
2
+ import { X509Certificate } from 'node:crypto';
3
+ /**
4
+ * OID 2.16.76.1.3.3 — o CNPJ da pessoa jurídica no `otherName` do
5
+ * `subjectAltName`, na forma que a ICP-Brasil padronizou (DOC-ICP-04).
6
+ *
7
+ * Em DER: tag `06`, comprimento `05`, e os componentes `2.16` colapsados em
8
+ * `0x60`. Procurar a sequência de bytes é mais confiável que ler
9
+ * `x509.subjectAltName`, que em várias versões do Node devolve `undefined` ou
10
+ * `othername:<unsupported>` justamente para os `otherName` do ICP-Brasil.
11
+ */
12
+ const OID_CNPJ_ICP_BRASIL = Buffer.from([0x06, 0x05, 0x60, 0x4c, 0x01, 0x03, 0x03]);
13
+ /** Janela de busca depois do OID: o valor vem logo em seguida, dentro do mesmo `otherName`. */
14
+ const OID_VALUE_WINDOW = 48;
15
+ /**
16
+ * Inspeciona o material, sem rede e sem disco.
17
+ *
18
+ * NUNCA lança: toda falha vira uma classe. Quem chama é uma rota de upload, e
19
+ * uma exceção com texto de OpenSSL atravessando até o handler é exatamente como
20
+ * o sujeito de um certificado acaba num log.
21
+ */
22
+ /**
23
+ * Inspeciona o material, sem rede e sem disco.
24
+ *
25
+ * NUNCA lança: toda falha vira uma classe. Quem chama é uma rota de upload, e
26
+ * uma exceção com texto de OpenSSL atravessando até o handler é exatamente como
27
+ * o sujeito de um certificado acaba num log.
28
+ *
29
+ * `async` sem `await` é deliberado: o contrato é assíncrono porque a primeira
30
+ * implementação precisava de um handshake, e porque uma leitura de material
31
+ * criptográfico é o tipo de operação que pode voltar a precisar. Mudar a
32
+ * assinatura para síncrona obrigaria todo chamador a mudar junto, por nenhum
33
+ * ganho.
34
+ */
35
+ export async function inspectPkcs12(pfx, passphrase) {
36
+ if (pfx.byteLength === 0)
37
+ return { status: 'failed', reason: 'malformed_material' };
38
+ // Primeiro portão: o contexto abre? Isto é a checagem de senha, e ela lança
39
+ // aqui — antes de existir qualquer outra coisa.
40
+ let context;
41
+ try {
42
+ context = createSecureContext({ pfx, passphrase, minVersion: 'TLSv1.2' });
43
+ }
44
+ catch (err) {
45
+ return { status: 'failed', reason: classify(err) };
46
+ }
47
+ let der;
48
+ try {
49
+ der = certificateDerFrom(context);
50
+ }
51
+ catch (err) {
52
+ return { status: 'failed', reason: classify(err) };
53
+ }
54
+ if (!der || der.byteLength === 0)
55
+ return { status: 'failed', reason: 'inspection_failed' };
56
+ try {
57
+ return { status: 'ok', facts: factsFrom(new X509Certificate(der)) };
58
+ }
59
+ catch (err) {
60
+ return { status: 'failed', reason: classify(err) };
61
+ }
62
+ }
63
+ /**
64
+ * O DER do certificado carregado no contexto.
65
+ *
66
+ * `context.getCertificate()` é o handle NATIVO do `SecureContext`, não a API
67
+ * pública documentada do Node. Por isso o acesso é defensivo em vez de direto: o
68
+ * dia em que uma versão do Node o renomear, o produto deve responder
69
+ * `inspection_failed` — e a suíte, que lê um PKCS#12 sintético de verdade, vai
70
+ * ficar vermelha na atualização, que é quando alguém pode agir.
71
+ *
72
+ * A alternativa — depender do binário `openssl` na imagem — troca este risco por
73
+ * um pior: uma falha que só aparece em produção, num contêiner onde ninguém
74
+ * conferiu o que está instalado.
75
+ */
76
+ function certificateDerFrom(context) {
77
+ const handle = context.context;
78
+ const der = handle?.getCertificate?.();
79
+ return Buffer.isBuffer(der) ? der : null;
80
+ }
81
+ function factsFrom(cert) {
82
+ const validTo = new Date(cert.validTo);
83
+ return {
84
+ fingerprintSha256: cert.fingerprint256.replace(/:/g, '').toLowerCase(),
85
+ subjectCommonName: commonName(cert.subject),
86
+ issuerCommonName: commonName(cert.issuer),
87
+ serialTail: cert.serialNumber ? cert.serialNumber.slice(-8) : null,
88
+ validFrom: new Date(cert.validFrom).toISOString(),
89
+ validTo: validTo.toISOString(),
90
+ expired: validTo.getTime() <= Date.now(),
91
+ document: documentFrom(cert),
92
+ };
93
+ }
94
+ /** `CN=` do DN multilinha que o Node devolve. `null` quando não há. */
95
+ function commonName(dn) {
96
+ if (!dn)
97
+ return null;
98
+ for (const line of dn.split('\n')) {
99
+ const m = /^\s*CN\s*=\s*(.+?)\s*$/.exec(line);
100
+ if (m?.[1])
101
+ return m[1];
102
+ }
103
+ return null;
104
+ }
105
+ /**
106
+ * O documento do titular, do material.
107
+ *
108
+ * Duas fontes, nesta ordem — e a ordem importa:
109
+ *
110
+ * 1. O `otherName` do OID da ICP-Brasil, varrido no DER. É onde a norma manda
111
+ * escrever, é o que a Receita valida, e é o único lugar que não depende de
112
+ * convenção de quem emitiu.
113
+ * 2. O sufixo `:<14 dígitos>` do `CN`, convenção quase universal dos e-CNPJ.
114
+ *
115
+ * Não há terceira fonte. Procurar "14 dígitos em qualquer lugar do sujeito"
116
+ * casaria com um CEP colado a um telefone e devolveria um CNPJ inventado — que
117
+ * é pior que `null`, porque `null` deixa a comparação `indeterminate` e essa é
118
+ * a resposta honesta.
119
+ */
120
+ function documentFrom(cert) {
121
+ const fromOid = documentFromDer(cert.raw);
122
+ if (fromOid)
123
+ return fromOid;
124
+ const cn = commonName(cert.subject);
125
+ const m = cn ? /:(\d{11}|\d{14})\s*$/.exec(cn) : null;
126
+ return m?.[1] ?? null;
127
+ }
128
+ function documentFromDer(der) {
129
+ let from = 0;
130
+ for (;;) {
131
+ const at = der.indexOf(OID_CNPJ_ICP_BRASIL, from);
132
+ if (at < 0)
133
+ return null;
134
+ const window = der
135
+ .subarray(at + OID_CNPJ_ICP_BRASIL.length, at + OID_CNPJ_ICP_BRASIL.length + OID_VALUE_WINDOW)
136
+ .toString('latin1');
137
+ const digits = /(\d{14})/.exec(window);
138
+ if (digits?.[1])
139
+ return digits[1];
140
+ from = at + 1;
141
+ }
142
+ }
143
+ /**
144
+ * Traduz a falha do OpenSSL em classe, olhando SÓ os fragmentos conhecidos.
145
+ *
146
+ * A mensagem inteira nunca é propagada nem registrada. `mac verify failure` é a
147
+ * resposta do PKCS#12 a uma senha que não abre o MAC — é o único caso em que se
148
+ * pode dizer ao operador "a senha está errada" com alguma confiança.
149
+ */
150
+ function classify(err) {
151
+ const raw = err instanceof Error ? err.message : '';
152
+ const message = raw.toLowerCase();
153
+ if (message.includes('mac verify failure') || message.includes('invalid password')) {
154
+ return 'wrong_password';
155
+ }
156
+ if (message.includes('not enough data') ||
157
+ message.includes('wrong tag') ||
158
+ message.includes('header too long') ||
159
+ message.includes('nested asn1') ||
160
+ message.includes('asn1')) {
161
+ return 'malformed_material';
162
+ }
163
+ if (message.includes('unsupported') || message.includes('unknown cipher')) {
164
+ return 'unsupported_material';
165
+ }
166
+ return 'inspection_failed';
167
+ }
168
+ export function matchIdentity(certificateDocument, clientDocument) {
169
+ const a = digitsOnly(certificateDocument);
170
+ const b = digitsOnly(clientDocument);
171
+ if (!a || !b)
172
+ return 'indeterminate';
173
+ return a === b ? 'match' : 'mismatch';
174
+ }
175
+ function digitsOnly(v) {
176
+ return (v ?? '').replace(/\D/g, '');
177
+ }
178
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../../src/fiscal/credentials/inspect.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { createHash } from 'node:crypto';
2
- import { revealSecret } from '../../vault/repository.js';
2
+ import { revealWriteOnlySecretForProcess } from '../../vault/repository.js';
3
3
  import { FiscalSecretBoundaryError, assertFiscalSecretAccess, } from '../sync/secret-boundary.js';
4
4
  /**
5
5
  * Constrói o material a partir do envelope decifrado.
@@ -151,7 +151,7 @@ export async function loadFiscalTlsMaterial(tx, keyring, tenantId, input) {
151
151
  return { status: 'unavailable', reason: 'no_credential' };
152
152
  let secret;
153
153
  try {
154
- ({ secret } = await revealSecret(tx, keyring, tenantId, pointer));
154
+ ({ secret } = await revealWriteOnlySecretForProcess(tx, keyring, tenantId, pointer));
155
155
  }
156
156
  catch {
157
157
  // Ponteiro pendurado, chave de cifra ausente, linha invisível sob RLS: os
@@ -1 +1 @@
1
- {"version":3,"file":"material.js","sourceRoot":"","sources":["../../../src/fiscal/credentials/material.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"material.js","sourceRoot":"","sources":["../../../src/fiscal/credentials/material.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import type { Tx } from '../../db/client.js';
2
+ import type { Keyring } from '../../vault/crypto.js';
3
+ import { type IdentityMatch } from './inspect.js';
4
+ /**
5
+ * O caminho de entrada do certificado digital — o único.
6
+ *
7
+ * ## O que esta frente entrega, e por que ela existe
8
+ *
9
+ * Até aqui o produto sabia USAR um certificado (`material.ts`) e sabia dizer se
10
+ * ele estava pronto (`readiness.ts`). O que não existia era como ele ENTRA:
11
+ * `POST /v1/compliance/certificates` aceitava um `vaultCredentialId` já
12
+ * existente, e nada no produto criava esse ponteiro. Na prática, a única forma
13
+ * de cadastrar um A1 era alguém colar o base64 do `.pfx` — e a senha — na tela
14
+ * genérica do cofre, ou digitá-los num terminal.
15
+ *
16
+ * Uma senha de certificado digitada num terminal é uma senha no histórico do
17
+ * shell, no scrollback e, se o comando falhar, na mensagem de erro. O objetivo
18
+ * declarado desta fase é que ela nunca precise sair do navegador.
19
+ *
20
+ * ## Três recusas que acontecem ANTES de qualquer escrita
21
+ *
22
+ * **Senha que não abre.** Sem isso, o cadastro fica `active` e o defeito só
23
+ * aparece no dia em que o worker apresentar o material à Receita.
24
+ *
25
+ * **Certificado vencido.** Guardar material vencido é assumir o risco de
26
+ * custodiar uma chave privada sem nenhum uso possível em troca.
27
+ *
28
+ * **Certificado de outra empresa.** É o caso que a arquitetura precisa impedir
29
+ * em silêncio total: cliente A com o certificado da empresa B consulta a Receita
30
+ * em nome de quem não autorizou. Aqui ele exige assinatura — nome e motivo —, e
31
+ * a 0060 repete a exigência como CHECK, para o caminho que ainda não foi escrito.
32
+ *
33
+ * ## O que NUNCA sai daqui
34
+ *
35
+ * Nenhum retorno desta função carrega material nem senha. O que volta é
36
+ * metadata: sujeito, emissor, validade, impressão digital e estado. É essa
37
+ * estrutura que a tela mostra, e é por isso que ela não tem como mostrar mais.
38
+ */
39
+ export type CertificateRejection = 'wrong_password' | 'malformed_material' | 'unsupported_material' | 'inspection_failed' | 'expired' | 'identity_mismatch' | 'client_not_found';
40
+ /** Metadata segura para tela, trilha e resposta de API. Nunca há material aqui. */
41
+ export interface FiscalCertificateSummary {
42
+ id: string;
43
+ clientId: string;
44
+ certType: 'A1' | 'A3';
45
+ status: string;
46
+ subjectCommonName: string | null;
47
+ issuerCommonName: string | null;
48
+ serialTail: string | null;
49
+ /** sha256 do certificado apresentado, truncado — identifica sem revelar. */
50
+ fingerprint: string;
51
+ certificateDocument: string | null;
52
+ identityMatch: IdentityMatch;
53
+ identityOverrideReason: string | null;
54
+ issuedAt: string | null;
55
+ expiresOn: string;
56
+ uploadedAt: string | null;
57
+ /** Já exercido contra o ambiente oficial? Preenchido por execução, nunca aqui. */
58
+ verifiedAt: string | null;
59
+ /** `true` quando esta chamada substituiu material que já existia. */
60
+ replaced: boolean;
61
+ }
62
+ export type CertificateOnboardingResult = {
63
+ status: 'stored';
64
+ certificate: FiscalCertificateSummary;
65
+ } | {
66
+ status: 'rejected';
67
+ reason: CertificateRejection;
68
+ identityMatch?: IdentityMatch;
69
+ };
70
+ export interface CertificateOnboardingInput {
71
+ clientId: string;
72
+ certType?: 'A1' | 'A3';
73
+ /** O `.pfx`/`.p12` em bytes. Nunca um caminho de arquivo: não há arquivo. */
74
+ material: Buffer;
75
+ passphrase?: string;
76
+ actorId: string;
77
+ /**
78
+ * A assinatura humana que destrava um titular divergente. Sem ela, divergência
79
+ * é recusa — e é assim que "cliente A + certificado B" deixa de ser possível
80
+ * por distração.
81
+ */
82
+ identityOverrideReason?: string;
83
+ }
84
+ /**
85
+ * Nome determinístico da credencial no cofre.
86
+ *
87
+ * Determinístico porque a substituição precisa ENCONTRAR o que já existe: o
88
+ * índice único do cofre é `(tenant, cliente, lower(nome))`, e um nome novo a
89
+ * cada upload deixaria uma trilha de chaves privadas órfãs, todas ainda
90
+ * decifráveis, nenhuma referenciada.
91
+ */
92
+ export declare function fiscalCertificateCredentialName(clientId: string, certType: 'A1' | 'A3'): string;
93
+ export declare function onboardFiscalCertificate(tx: Tx, keyring: Keyring, tenantId: string, input: CertificateOnboardingInput): Promise<CertificateOnboardingResult>;
94
+ /** Os certificados de um cliente, só metadata. É o que a tela lê. */
95
+ export declare function listFiscalCertificates(tx: Tx, clientId: string): Promise<FiscalCertificateSummary[]>;
96
+ /**
97
+ * Revoga o uso do certificado DENTRO deste produto.
98
+ *
99
+ * Não toca a ICP-Brasil, e é por isso que a função se chama assim. Revogar de
100
+ * verdade um certificado é um ato junto à Autoridade Certificadora que o emitiu;
101
+ * apagar a linha daqui apenas garante que este produto pare de apresentá-lo. A
102
+ * tela repete a distinção, porque um operador que acredite ter revogado o
103
+ * certificado do cliente não vai à AC — e o certificado segue válido no mundo.
104
+ *
105
+ * O material sai do cofre no mesmo movimento (`deleted_at`), de modo que a
106
+ * revogação não deixa chave privada decifrável para trás.
107
+ */
108
+ export declare function revokeFiscalCertificate(tx: Tx, clientId: string, certificateId: string): Promise<{
109
+ revoked: boolean;
110
+ }>;
111
+ /**
112
+ * Impressão digital do material recebido, antes de qualquer decisão.
113
+ *
114
+ * Serve à trilha do upload recusado: registrar "tentaram subir algo" sem
115
+ * registrar o quê. É o mesmo cálculo de `material.ts`, e é seguro por
116
+ * construção — um hash não volta a ser um certificado.
117
+ */
118
+ export declare function materialFingerprint(material: Buffer): string;
119
+ //# sourceMappingURL=onboarding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../../src/fiscal/credentials/onboarding.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAAgC,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,MAAM,MAAM,oBAAoB,GAC5B,gBAAgB,GAChB,oBAAoB,GACpB,sBAAsB,GACtB,mBAAmB,GACnB,SAAS,GACT,mBAAmB,GACnB,kBAAkB,CAAC;AAEvB,mFAAmF;AACnF,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kFAAkF;IAClF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,2BAA2B,GACnC;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,wBAAwB,CAAA;CAAE,GAC3D;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAC;IAAC,aAAa,CAAC,EAAE,aAAa,CAAA;CAAE,CAAC;AAExF,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAOD;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAE/F;AAED,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,2BAA2B,CAAC,CA0HtC;AAiHD,qEAAqE;AACrE,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAQrC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAgB/B;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D"}