@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.
- package/.baruk-provenance.json +4 -4
- package/dist/cjs/clients/ibge.js +14 -0
- package/dist/cjs/clients/ibge.js.map +1 -1
- package/dist/cjs/clients/registry/http.js +157 -0
- package/dist/cjs/clients/registry/http.js.map +1 -0
- package/dist/cjs/clients/registry/ibge-municipios.js +28 -0
- package/dist/cjs/clients/registry/ibge-municipios.js.map +1 -0
- package/dist/cjs/clients/registry/ibge.js +63 -0
- package/dist/cjs/clients/registry/ibge.js.map +1 -0
- package/dist/cjs/clients/registry/lookup.js +191 -0
- package/dist/cjs/clients/registry/lookup.js.map +1 -0
- package/dist/cjs/clients/registry/provider.js +34 -0
- package/dist/cjs/clients/registry/provider.js.map +1 -0
- package/dist/cjs/clients/registry/resolve.js +47 -0
- package/dist/cjs/clients/registry/resolve.js.map +1 -0
- package/dist/cjs/clients/registry/serpro.js +149 -0
- package/dist/cjs/clients/registry/serpro.js.map +1 -0
- package/dist/cjs/clients/registry/service.js +230 -0
- package/dist/cjs/clients/registry/service.js.map +1 -0
- package/dist/cjs/clients/registry/synthetic.js +165 -0
- package/dist/cjs/clients/registry/synthetic.js.map +1 -0
- package/dist/cjs/clients/repository.js +6 -2
- package/dist/cjs/clients/repository.js.map +1 -1
- package/dist/cjs/db/provision-e2e-identity.js +8 -3
- package/dist/cjs/db/provision-e2e-identity.js.map +1 -1
- package/dist/cjs/fiscal/collection/authorization.js +186 -0
- package/dist/cjs/fiscal/collection/authorization.js.map +1 -0
- package/dist/cjs/fiscal/collection/competence.js +97 -0
- package/dist/cjs/fiscal/collection/competence.js.map +1 -0
- package/dist/cjs/fiscal/collection/first-contact.js +204 -0
- package/dist/cjs/fiscal/collection/first-contact.js.map +1 -0
- package/dist/cjs/fiscal/collection/plan.js +122 -0
- package/dist/cjs/fiscal/collection/plan.js.map +1 -0
- package/dist/cjs/fiscal/coverage/model.js +11 -1
- package/dist/cjs/fiscal/coverage/model.js.map +1 -1
- package/dist/cjs/fiscal/credentials/inspect.js +182 -0
- package/dist/cjs/fiscal/credentials/inspect.js.map +1 -0
- package/dist/cjs/fiscal/credentials/material.js +1 -1
- package/dist/cjs/fiscal/credentials/material.js.map +1 -1
- package/dist/cjs/fiscal/credentials/onboarding.js +266 -0
- package/dist/cjs/fiscal/credentials/onboarding.js.map +1 -0
- package/dist/cjs/fiscal/credentials/readiness.js +29 -2
- package/dist/cjs/fiscal/credentials/readiness.js.map +1 -1
- package/dist/cjs/fiscal/enrollment.js +134 -0
- package/dist/cjs/fiscal/enrollment.js.map +1 -0
- package/dist/cjs/fiscal/transport/synthetic-tls.js +52 -0
- package/dist/cjs/fiscal/transport/synthetic-tls.js.map +1 -1
- package/dist/cjs/index.js +196 -113
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/legal/documents.js +64 -4
- package/dist/cjs/legal/documents.js.map +1 -1
- package/dist/cjs/legal/types.js.map +1 -1
- package/dist/cjs/platform/capabilities.js +29 -0
- package/dist/cjs/platform/capabilities.js.map +1 -1
- package/dist/cjs/rbac/catalog.js +78 -2
- package/dist/cjs/rbac/catalog.js.map +1 -1
- package/dist/cjs/subscription-billing/index.js +8 -1
- package/dist/cjs/subscription-billing/index.js.map +1 -1
- package/dist/cjs/subscription-billing/platform-exemption.js +121 -0
- package/dist/cjs/subscription-billing/platform-exemption.js.map +1 -0
- package/dist/cjs/subscription-billing/service.js +93 -1
- package/dist/cjs/subscription-billing/service.js.map +1 -1
- package/dist/cjs/vault/repository.js +92 -5
- package/dist/cjs/vault/repository.js.map +1 -1
- package/dist/clients/ibge.d.ts.map +1 -1
- package/dist/clients/ibge.js +14 -0
- package/dist/clients/ibge.js.map +1 -1
- package/dist/clients/registry/http.d.ts +61 -0
- package/dist/clients/registry/http.d.ts.map +1 -0
- package/dist/clients/registry/http.js +151 -0
- package/dist/clients/registry/http.js.map +1 -0
- package/dist/clients/registry/ibge-municipios.d.ts +25 -0
- package/dist/clients/registry/ibge-municipios.d.ts.map +1 -0
- package/dist/clients/registry/ibge-municipios.js +25 -0
- package/dist/clients/registry/ibge-municipios.js.map +1 -0
- package/dist/clients/registry/ibge.d.ts +62 -0
- package/dist/clients/registry/ibge.d.ts.map +1 -0
- package/dist/clients/registry/ibge.js +57 -0
- package/dist/clients/registry/ibge.js.map +1 -0
- package/dist/clients/registry/lookup.d.ts +94 -0
- package/dist/clients/registry/lookup.d.ts.map +1 -0
- package/dist/clients/registry/lookup.js +184 -0
- package/dist/clients/registry/lookup.js.map +1 -0
- package/dist/clients/registry/provider.d.ts +124 -0
- package/dist/clients/registry/provider.d.ts.map +1 -0
- package/dist/clients/registry/provider.js +39 -0
- package/dist/clients/registry/provider.js.map +1 -0
- package/dist/clients/registry/resolve.d.ts +36 -0
- package/dist/clients/registry/resolve.d.ts.map +1 -0
- package/dist/clients/registry/resolve.js +44 -0
- package/dist/clients/registry/resolve.js.map +1 -0
- package/dist/clients/registry/serpro.d.ts +57 -0
- package/dist/clients/registry/serpro.d.ts.map +1 -0
- package/dist/clients/registry/serpro.js +143 -0
- package/dist/clients/registry/serpro.js.map +1 -0
- package/dist/clients/registry/service.d.ts +59 -0
- package/dist/clients/registry/service.d.ts.map +1 -0
- package/dist/clients/registry/service.js +225 -0
- package/dist/clients/registry/service.js.map +1 -0
- package/dist/clients/registry/synthetic.d.ts +30 -0
- package/dist/clients/registry/synthetic.d.ts.map +1 -0
- package/dist/clients/registry/synthetic.js +161 -0
- package/dist/clients/registry/synthetic.js.map +1 -0
- package/dist/clients/repository.d.ts +4 -0
- package/dist/clients/repository.d.ts.map +1 -1
- package/dist/clients/repository.js +6 -2
- package/dist/clients/repository.js.map +1 -1
- package/dist/db/provision-e2e-identity.js +8 -3
- package/dist/db/provision-e2e-identity.js.map +1 -1
- package/dist/fiscal/collection/authorization.d.ts +152 -0
- package/dist/fiscal/collection/authorization.d.ts.map +1 -0
- package/dist/fiscal/collection/authorization.js +178 -0
- package/dist/fiscal/collection/authorization.js.map +1 -0
- package/dist/fiscal/collection/competence.d.ts +66 -0
- package/dist/fiscal/collection/competence.d.ts.map +1 -0
- package/dist/fiscal/collection/competence.js +90 -0
- package/dist/fiscal/collection/competence.js.map +1 -0
- package/dist/fiscal/collection/first-contact.d.ts +103 -0
- package/dist/fiscal/collection/first-contact.d.ts.map +1 -0
- package/dist/fiscal/collection/first-contact.js +201 -0
- package/dist/fiscal/collection/first-contact.js.map +1 -0
- package/dist/fiscal/collection/plan.d.ts +74 -0
- package/dist/fiscal/collection/plan.d.ts.map +1 -0
- package/dist/fiscal/collection/plan.js +119 -0
- package/dist/fiscal/collection/plan.js.map +1 -0
- package/dist/fiscal/coverage/model.d.ts +28 -0
- package/dist/fiscal/coverage/model.d.ts.map +1 -1
- package/dist/fiscal/coverage/model.js +11 -1
- package/dist/fiscal/coverage/model.js.map +1 -1
- package/dist/fiscal/credentials/inspect.d.ts +114 -0
- package/dist/fiscal/credentials/inspect.d.ts.map +1 -0
- package/dist/fiscal/credentials/inspect.js +178 -0
- package/dist/fiscal/credentials/inspect.js.map +1 -0
- package/dist/fiscal/credentials/material.js +2 -2
- package/dist/fiscal/credentials/material.js.map +1 -1
- package/dist/fiscal/credentials/onboarding.d.ts +119 -0
- package/dist/fiscal/credentials/onboarding.d.ts.map +1 -0
- package/dist/fiscal/credentials/onboarding.js +259 -0
- package/dist/fiscal/credentials/onboarding.js.map +1 -0
- package/dist/fiscal/credentials/readiness.d.ts +30 -3
- package/dist/fiscal/credentials/readiness.d.ts.map +1 -1
- package/dist/fiscal/credentials/readiness.js +29 -2
- package/dist/fiscal/credentials/readiness.js.map +1 -1
- package/dist/fiscal/enrollment.d.ts +91 -0
- package/dist/fiscal/enrollment.d.ts.map +1 -0
- package/dist/fiscal/enrollment.js +126 -0
- package/dist/fiscal/enrollment.js.map +1 -0
- package/dist/fiscal/transport/synthetic-tls.d.ts +19 -0
- package/dist/fiscal/transport/synthetic-tls.d.ts.map +1 -1
- package/dist/fiscal/transport/synthetic-tls.js +51 -0
- package/dist/fiscal/transport/synthetic-tls.js.map +1 -1
- package/dist/index.d.ts +32 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -2
- package/dist/index.js.map +1 -1
- package/dist/legal/documents.d.ts.map +1 -1
- package/dist/legal/documents.js +64 -4
- package/dist/legal/documents.js.map +1 -1
- package/dist/legal/index.d.ts +1 -1
- package/dist/legal/index.d.ts.map +1 -1
- package/dist/legal/types.d.ts +77 -0
- package/dist/legal/types.d.ts.map +1 -1
- package/dist/legal/types.js.map +1 -1
- package/dist/platform/capabilities.d.ts.map +1 -1
- package/dist/platform/capabilities.js +29 -0
- package/dist/platform/capabilities.js.map +1 -1
- package/dist/rbac/catalog.d.ts.map +1 -1
- package/dist/rbac/catalog.js +78 -2
- package/dist/rbac/catalog.js.map +1 -1
- package/dist/subscription-billing/index.d.ts +3 -1
- package/dist/subscription-billing/index.d.ts.map +1 -1
- package/dist/subscription-billing/index.js +2 -1
- package/dist/subscription-billing/index.js.map +1 -1
- package/dist/subscription-billing/platform-exemption.d.ts +89 -0
- package/dist/subscription-billing/platform-exemption.d.ts.map +1 -0
- package/dist/subscription-billing/platform-exemption.js +113 -0
- package/dist/subscription-billing/platform-exemption.js.map +1 -0
- package/dist/subscription-billing/service.d.ts +53 -0
- package/dist/subscription-billing/service.d.ts.map +1 -1
- package/dist/subscription-billing/service.js +92 -1
- package/dist/subscription-billing/service.js.map +1 -1
- package/dist/vault/repository.d.ts +69 -1
- package/dist/vault/repository.d.ts.map +1 -1
- package/dist/vault/repository.js +88 -5
- package/dist/vault/repository.js.map +1 -1
- package/package.json +3 -2
- package/src/db/migrations/0060_fiscal_credential_vault_and_run_authorization.sql +321 -0
- package/src/db/migrations/0061_client_official_registry_provenance.sql +193 -0
- package/src/db/migrations/0062_first_contact_and_capability_truth.sql +119 -0
|
@@ -19,6 +19,10 @@ function unknownCoverage(documentType, scope, code) {
|
|
|
19
19
|
credentialRequirement: 'unknown',
|
|
20
20
|
environments: [],
|
|
21
21
|
fallbackType: 'manual_upload',
|
|
22
|
+
officialApiAvailable: 'unknown',
|
|
23
|
+
connectorImplemented: false,
|
|
24
|
+
protocolVerified: false,
|
|
25
|
+
supportedOperations: [],
|
|
22
26
|
lastVerifiedAt: null,
|
|
23
27
|
sourceReference: null,
|
|
24
28
|
notes: 'Nenhuma linha de cobertura para esta combinação. Ninguém mediu.',
|
|
@@ -35,13 +39,19 @@ const map = (r) => ({
|
|
|
35
39
|
credentialRequirement: r.credential_requirement,
|
|
36
40
|
environments: r.environments ?? [],
|
|
37
41
|
fallbackType: r.fallback_type,
|
|
42
|
+
officialApiAvailable: r.official_api_available ?? 'unknown',
|
|
43
|
+
connectorImplemented: r.connector_implemented ?? false,
|
|
44
|
+
protocolVerified: r.protocol_verified ?? false,
|
|
45
|
+
supportedOperations: r.supported_operations ?? [],
|
|
38
46
|
lastVerifiedAt: r.last_verified_at ? r.last_verified_at.toISOString().slice(0, 10) : null,
|
|
39
47
|
sourceReference: r.source_reference,
|
|
40
48
|
notes: r.notes,
|
|
41
49
|
});
|
|
42
50
|
const COLUMNS = `id, document_type, jurisdiction_scope, jurisdiction_code, provider,
|
|
43
51
|
coverage_status, automation_method, credential_requirement, environments,
|
|
44
|
-
fallback_type,
|
|
52
|
+
fallback_type, official_api_available, connector_implemented,
|
|
53
|
+
protocol_verified, supported_operations,
|
|
54
|
+
last_verified_at, source_reference, notes`;
|
|
45
55
|
/**
|
|
46
56
|
* Resolve a cobertura de uma pergunta específica.
|
|
47
57
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../src/fiscal/coverage/model.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../src/fiscal/coverage/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.inspectPkcs12 = inspectPkcs12;
|
|
4
|
+
exports.matchIdentity = matchIdentity;
|
|
5
|
+
const node_tls_1 = require("node:tls");
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
7
|
+
/**
|
|
8
|
+
* OID 2.16.76.1.3.3 — o CNPJ da pessoa jurídica no `otherName` do
|
|
9
|
+
* `subjectAltName`, na forma que a ICP-Brasil padronizou (DOC-ICP-04).
|
|
10
|
+
*
|
|
11
|
+
* Em DER: tag `06`, comprimento `05`, e os componentes `2.16` colapsados em
|
|
12
|
+
* `0x60`. Procurar a sequência de bytes é mais confiável que ler
|
|
13
|
+
* `x509.subjectAltName`, que em várias versões do Node devolve `undefined` ou
|
|
14
|
+
* `othername:<unsupported>` justamente para os `otherName` do ICP-Brasil.
|
|
15
|
+
*/
|
|
16
|
+
const OID_CNPJ_ICP_BRASIL = Buffer.from([0x06, 0x05, 0x60, 0x4c, 0x01, 0x03, 0x03]);
|
|
17
|
+
/** Janela de busca depois do OID: o valor vem logo em seguida, dentro do mesmo `otherName`. */
|
|
18
|
+
const OID_VALUE_WINDOW = 48;
|
|
19
|
+
/**
|
|
20
|
+
* Inspeciona o material, sem rede e sem disco.
|
|
21
|
+
*
|
|
22
|
+
* NUNCA lança: toda falha vira uma classe. Quem chama é uma rota de upload, e
|
|
23
|
+
* uma exceção com texto de OpenSSL atravessando até o handler é exatamente como
|
|
24
|
+
* o sujeito de um certificado acaba num log.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Inspeciona o material, sem rede e sem disco.
|
|
28
|
+
*
|
|
29
|
+
* NUNCA lança: toda falha vira uma classe. Quem chama é uma rota de upload, e
|
|
30
|
+
* uma exceção com texto de OpenSSL atravessando até o handler é exatamente como
|
|
31
|
+
* o sujeito de um certificado acaba num log.
|
|
32
|
+
*
|
|
33
|
+
* `async` sem `await` é deliberado: o contrato é assíncrono porque a primeira
|
|
34
|
+
* implementação precisava de um handshake, e porque uma leitura de material
|
|
35
|
+
* criptográfico é o tipo de operação que pode voltar a precisar. Mudar a
|
|
36
|
+
* assinatura para síncrona obrigaria todo chamador a mudar junto, por nenhum
|
|
37
|
+
* ganho.
|
|
38
|
+
*/
|
|
39
|
+
async function inspectPkcs12(pfx, passphrase) {
|
|
40
|
+
if (pfx.byteLength === 0)
|
|
41
|
+
return { status: 'failed', reason: 'malformed_material' };
|
|
42
|
+
// Primeiro portão: o contexto abre? Isto é a checagem de senha, e ela lança
|
|
43
|
+
// aqui — antes de existir qualquer outra coisa.
|
|
44
|
+
let context;
|
|
45
|
+
try {
|
|
46
|
+
context = (0, node_tls_1.createSecureContext)({ pfx, passphrase, minVersion: 'TLSv1.2' });
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
return { status: 'failed', reason: classify(err) };
|
|
50
|
+
}
|
|
51
|
+
let der;
|
|
52
|
+
try {
|
|
53
|
+
der = certificateDerFrom(context);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
return { status: 'failed', reason: classify(err) };
|
|
57
|
+
}
|
|
58
|
+
if (!der || der.byteLength === 0)
|
|
59
|
+
return { status: 'failed', reason: 'inspection_failed' };
|
|
60
|
+
try {
|
|
61
|
+
return { status: 'ok', facts: factsFrom(new node_crypto_1.X509Certificate(der)) };
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
return { status: 'failed', reason: classify(err) };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* O DER do certificado carregado no contexto.
|
|
69
|
+
*
|
|
70
|
+
* `context.getCertificate()` é o handle NATIVO do `SecureContext`, não a API
|
|
71
|
+
* pública documentada do Node. Por isso o acesso é defensivo em vez de direto: o
|
|
72
|
+
* dia em que uma versão do Node o renomear, o produto deve responder
|
|
73
|
+
* `inspection_failed` — e a suíte, que lê um PKCS#12 sintético de verdade, vai
|
|
74
|
+
* ficar vermelha na atualização, que é quando alguém pode agir.
|
|
75
|
+
*
|
|
76
|
+
* A alternativa — depender do binário `openssl` na imagem — troca este risco por
|
|
77
|
+
* um pior: uma falha que só aparece em produção, num contêiner onde ninguém
|
|
78
|
+
* conferiu o que está instalado.
|
|
79
|
+
*/
|
|
80
|
+
function certificateDerFrom(context) {
|
|
81
|
+
const handle = context.context;
|
|
82
|
+
const der = handle?.getCertificate?.();
|
|
83
|
+
return Buffer.isBuffer(der) ? der : null;
|
|
84
|
+
}
|
|
85
|
+
function factsFrom(cert) {
|
|
86
|
+
const validTo = new Date(cert.validTo);
|
|
87
|
+
return {
|
|
88
|
+
fingerprintSha256: cert.fingerprint256.replace(/:/g, '').toLowerCase(),
|
|
89
|
+
subjectCommonName: commonName(cert.subject),
|
|
90
|
+
issuerCommonName: commonName(cert.issuer),
|
|
91
|
+
serialTail: cert.serialNumber ? cert.serialNumber.slice(-8) : null,
|
|
92
|
+
validFrom: new Date(cert.validFrom).toISOString(),
|
|
93
|
+
validTo: validTo.toISOString(),
|
|
94
|
+
expired: validTo.getTime() <= Date.now(),
|
|
95
|
+
document: documentFrom(cert),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/** `CN=` do DN multilinha que o Node devolve. `null` quando não há. */
|
|
99
|
+
function commonName(dn) {
|
|
100
|
+
if (!dn)
|
|
101
|
+
return null;
|
|
102
|
+
for (const line of dn.split('\n')) {
|
|
103
|
+
const m = /^\s*CN\s*=\s*(.+?)\s*$/.exec(line);
|
|
104
|
+
if (m?.[1])
|
|
105
|
+
return m[1];
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* O documento do titular, do material.
|
|
111
|
+
*
|
|
112
|
+
* Duas fontes, nesta ordem — e a ordem importa:
|
|
113
|
+
*
|
|
114
|
+
* 1. O `otherName` do OID da ICP-Brasil, varrido no DER. É onde a norma manda
|
|
115
|
+
* escrever, é o que a Receita valida, e é o único lugar que não depende de
|
|
116
|
+
* convenção de quem emitiu.
|
|
117
|
+
* 2. O sufixo `:<14 dígitos>` do `CN`, convenção quase universal dos e-CNPJ.
|
|
118
|
+
*
|
|
119
|
+
* Não há terceira fonte. Procurar "14 dígitos em qualquer lugar do sujeito"
|
|
120
|
+
* casaria com um CEP colado a um telefone e devolveria um CNPJ inventado — que
|
|
121
|
+
* é pior que `null`, porque `null` deixa a comparação `indeterminate` e essa é
|
|
122
|
+
* a resposta honesta.
|
|
123
|
+
*/
|
|
124
|
+
function documentFrom(cert) {
|
|
125
|
+
const fromOid = documentFromDer(cert.raw);
|
|
126
|
+
if (fromOid)
|
|
127
|
+
return fromOid;
|
|
128
|
+
const cn = commonName(cert.subject);
|
|
129
|
+
const m = cn ? /:(\d{11}|\d{14})\s*$/.exec(cn) : null;
|
|
130
|
+
return m?.[1] ?? null;
|
|
131
|
+
}
|
|
132
|
+
function documentFromDer(der) {
|
|
133
|
+
let from = 0;
|
|
134
|
+
for (;;) {
|
|
135
|
+
const at = der.indexOf(OID_CNPJ_ICP_BRASIL, from);
|
|
136
|
+
if (at < 0)
|
|
137
|
+
return null;
|
|
138
|
+
const window = der
|
|
139
|
+
.subarray(at + OID_CNPJ_ICP_BRASIL.length, at + OID_CNPJ_ICP_BRASIL.length + OID_VALUE_WINDOW)
|
|
140
|
+
.toString('latin1');
|
|
141
|
+
const digits = /(\d{14})/.exec(window);
|
|
142
|
+
if (digits?.[1])
|
|
143
|
+
return digits[1];
|
|
144
|
+
from = at + 1;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Traduz a falha do OpenSSL em classe, olhando SÓ os fragmentos conhecidos.
|
|
149
|
+
*
|
|
150
|
+
* A mensagem inteira nunca é propagada nem registrada. `mac verify failure` é a
|
|
151
|
+
* resposta do PKCS#12 a uma senha que não abre o MAC — é o único caso em que se
|
|
152
|
+
* pode dizer ao operador "a senha está errada" com alguma confiança.
|
|
153
|
+
*/
|
|
154
|
+
function classify(err) {
|
|
155
|
+
const raw = err instanceof Error ? err.message : '';
|
|
156
|
+
const message = raw.toLowerCase();
|
|
157
|
+
if (message.includes('mac verify failure') || message.includes('invalid password')) {
|
|
158
|
+
return 'wrong_password';
|
|
159
|
+
}
|
|
160
|
+
if (message.includes('not enough data') ||
|
|
161
|
+
message.includes('wrong tag') ||
|
|
162
|
+
message.includes('header too long') ||
|
|
163
|
+
message.includes('nested asn1') ||
|
|
164
|
+
message.includes('asn1')) {
|
|
165
|
+
return 'malformed_material';
|
|
166
|
+
}
|
|
167
|
+
if (message.includes('unsupported') || message.includes('unknown cipher')) {
|
|
168
|
+
return 'unsupported_material';
|
|
169
|
+
}
|
|
170
|
+
return 'inspection_failed';
|
|
171
|
+
}
|
|
172
|
+
function matchIdentity(certificateDocument, clientDocument) {
|
|
173
|
+
const a = digitsOnly(certificateDocument);
|
|
174
|
+
const b = digitsOnly(clientDocument);
|
|
175
|
+
if (!a || !b)
|
|
176
|
+
return 'indeterminate';
|
|
177
|
+
return a === b ? 'match' : 'mismatch';
|
|
178
|
+
}
|
|
179
|
+
function digitsOnly(v) {
|
|
180
|
+
return (v ?? '').replace(/\D/g, '');
|
|
181
|
+
}
|
|
182
|
+
//# 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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"}
|
|
@@ -155,7 +155,7 @@ async function loadFiscalTlsMaterial(tx, keyring, tenantId, input) {
|
|
|
155
155
|
return { status: 'unavailable', reason: 'no_credential' };
|
|
156
156
|
let secret;
|
|
157
157
|
try {
|
|
158
|
-
({ secret } = await (0, repository_js_1.
|
|
158
|
+
({ secret } = await (0, repository_js_1.revealWriteOnlySecretForProcess)(tx, keyring, tenantId, pointer));
|
|
159
159
|
}
|
|
160
160
|
catch {
|
|
161
161
|
// 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":";;AAwEA,4CAsCC;AA8DD,sDAsEC;AAlPD,6CAAyC;AAGzC,
|
|
1
|
+
{"version":3,"file":"material.js","sourceRoot":"","sources":["../../../../src/fiscal/credentials/material.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fiscalCertificateCredentialName = fiscalCertificateCredentialName;
|
|
4
|
+
exports.onboardFiscalCertificate = onboardFiscalCertificate;
|
|
5
|
+
exports.listFiscalCertificates = listFiscalCertificates;
|
|
6
|
+
exports.revokeFiscalCertificate = revokeFiscalCertificate;
|
|
7
|
+
exports.materialFingerprint = materialFingerprint;
|
|
8
|
+
const node_crypto_1 = require("node:crypto");
|
|
9
|
+
const shared_1 = require("@baruk/shared");
|
|
10
|
+
const crypto_js_1 = require("../../vault/crypto.js");
|
|
11
|
+
const inspect_js_1 = require("./inspect.js");
|
|
12
|
+
/** Impressão digital truncada. 16 hex identificam sem virar um segundo identificador. */
|
|
13
|
+
function shortFingerprint(full) {
|
|
14
|
+
return full.slice(0, 16);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Nome determinístico da credencial no cofre.
|
|
18
|
+
*
|
|
19
|
+
* Determinístico porque a substituição precisa ENCONTRAR o que já existe: o
|
|
20
|
+
* índice único do cofre é `(tenant, cliente, lower(nome))`, e um nome novo a
|
|
21
|
+
* cada upload deixaria uma trilha de chaves privadas órfãs, todas ainda
|
|
22
|
+
* decifráveis, nenhuma referenciada.
|
|
23
|
+
*/
|
|
24
|
+
function fiscalCertificateCredentialName(clientId, certType) {
|
|
25
|
+
return `fiscal:certificate:${certType}:${clientId}`;
|
|
26
|
+
}
|
|
27
|
+
async function onboardFiscalCertificate(tx, keyring, tenantId, input) {
|
|
28
|
+
const certType = input.certType ?? 'A1';
|
|
29
|
+
const clients = await tx `
|
|
30
|
+
SELECT id, document_number FROM client
|
|
31
|
+
WHERE id = ${input.clientId} AND deleted_at IS NULL
|
|
32
|
+
`;
|
|
33
|
+
const client = clients[0];
|
|
34
|
+
if (!client)
|
|
35
|
+
return { status: 'rejected', reason: 'client_not_found' };
|
|
36
|
+
const inspection = await (0, inspect_js_1.inspectPkcs12)(input.material, input.passphrase);
|
|
37
|
+
if (inspection.status === 'failed') {
|
|
38
|
+
return { status: 'rejected', reason: inspection.reason };
|
|
39
|
+
}
|
|
40
|
+
const facts = inspection.facts;
|
|
41
|
+
if (facts.expired)
|
|
42
|
+
return { status: 'rejected', reason: 'expired' };
|
|
43
|
+
const identity = (0, inspect_js_1.matchIdentity)(facts.document, client.document_number);
|
|
44
|
+
if (identity === 'mismatch' && !input.identityOverrideReason) {
|
|
45
|
+
return { status: 'rejected', reason: 'identity_mismatch', identityMatch: identity };
|
|
46
|
+
}
|
|
47
|
+
// O envelope é o MESMO que `material.ts` sabe abrir. Um segundo formato aqui
|
|
48
|
+
// significaria que o certificado que entra não é o que o transporte usa.
|
|
49
|
+
const envelope = JSON.stringify({
|
|
50
|
+
format: 'pkcs12',
|
|
51
|
+
material: input.material.toString('base64'),
|
|
52
|
+
...(input.passphrase ? { passphrase: input.passphrase } : {}),
|
|
53
|
+
});
|
|
54
|
+
const credentialName = fiscalCertificateCredentialName(input.clientId, certType);
|
|
55
|
+
const credentialId = await upsertWriteOnlyCredential(tx, keyring, tenantId, {
|
|
56
|
+
name: credentialName,
|
|
57
|
+
clientId: input.clientId,
|
|
58
|
+
secret: envelope,
|
|
59
|
+
expiresAt: facts.validTo,
|
|
60
|
+
actorId: input.actorId,
|
|
61
|
+
metadata: {
|
|
62
|
+
// Metadata do cofre é lida por telas e por trilha: só o que é público no
|
|
63
|
+
// certificado entra aqui.
|
|
64
|
+
fingerprint: shortFingerprint(facts.fingerprintSha256),
|
|
65
|
+
certType,
|
|
66
|
+
subject: facts.subjectCommonName,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
const expiresOn = facts.validTo.slice(0, 10);
|
|
70
|
+
const issuedAt = facts.validFrom.slice(0, 10);
|
|
71
|
+
const holderName = facts.subjectCommonName ?? 'Titular não identificado no certificado';
|
|
72
|
+
const existing = await tx `
|
|
73
|
+
SELECT id FROM digital_certificate
|
|
74
|
+
WHERE client_id = ${input.clientId} AND cert_type = ${certType} AND deleted_at IS NULL
|
|
75
|
+
ORDER BY created_at DESC LIMIT 1
|
|
76
|
+
`;
|
|
77
|
+
const override = identity === 'mismatch' ? (input.identityOverrideReason ?? null) : null;
|
|
78
|
+
const overrideBy = override ? input.actorId : null;
|
|
79
|
+
let rows;
|
|
80
|
+
if (existing[0]) {
|
|
81
|
+
rows = await tx `
|
|
82
|
+
UPDATE digital_certificate SET
|
|
83
|
+
holder_name = ${holderName},
|
|
84
|
+
holder_document = ${facts.document ?? client.document_number},
|
|
85
|
+
issued_at = ${issuedAt},
|
|
86
|
+
expires_at = ${expiresOn},
|
|
87
|
+
vault_credential_id = ${credentialId},
|
|
88
|
+
status = 'active',
|
|
89
|
+
fingerprint_sha256 = ${facts.fingerprintSha256},
|
|
90
|
+
subject_common_name = ${facts.subjectCommonName},
|
|
91
|
+
issuer_common_name = ${facts.issuerCommonName},
|
|
92
|
+
serial_tail = ${facts.serialTail},
|
|
93
|
+
certificate_document = ${facts.document},
|
|
94
|
+
identity_match = ${identity},
|
|
95
|
+
identity_override_by = ${overrideBy},
|
|
96
|
+
identity_override_reason = ${override},
|
|
97
|
+
uploaded_by = ${input.actorId},
|
|
98
|
+
uploaded_at = now(),
|
|
99
|
+
-- O material acabou de ser aberto pela inspeção — o mesmo OpenSSL do
|
|
100
|
+
-- handshake real. Isso é a validação LOCAL, e ela é fato deste instante:
|
|
101
|
+
-- senha correta, chave casando com o certificado, titular e datas
|
|
102
|
+
-- conferidos. Ver 1006.
|
|
103
|
+
local_validated_at = now(),
|
|
104
|
+
-- Material novo é uma afirmação nova: o que o ambiente oficial aceitou
|
|
105
|
+
-- foi o certificado ANTERIOR, e herdar a verificação diria que o novo
|
|
106
|
+
-- já funcionou. Ver 1004.
|
|
107
|
+
verified_at = NULL,
|
|
108
|
+
verified_by = NULL,
|
|
109
|
+
remote_verification_provider = NULL,
|
|
110
|
+
remote_verification_last_attempt_at = NULL,
|
|
111
|
+
last_verification_error = NULL,
|
|
112
|
+
updated_at = now()
|
|
113
|
+
WHERE id = ${existing[0].id}
|
|
114
|
+
RETURNING ${tx.unsafe(CERTIFICATE_COLUMNS)}
|
|
115
|
+
`;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
rows = await tx `
|
|
119
|
+
INSERT INTO digital_certificate (
|
|
120
|
+
id, tenant_id, client_id, cert_type, holder_name, holder_document,
|
|
121
|
+
issued_at, expires_at, vault_credential_id, status,
|
|
122
|
+
fingerprint_sha256, subject_common_name, issuer_common_name, serial_tail,
|
|
123
|
+
certificate_document, identity_match, identity_override_by, identity_override_reason,
|
|
124
|
+
uploaded_by, uploaded_at, local_validated_at
|
|
125
|
+
) VALUES (
|
|
126
|
+
${(0, shared_1.uuidv7)()}, current_setting('app.current_tenant')::uuid, ${input.clientId},
|
|
127
|
+
${certType}, ${holderName}, ${facts.document ?? client.document_number},
|
|
128
|
+
${issuedAt}, ${expiresOn}, ${credentialId}, 'active',
|
|
129
|
+
${facts.fingerprintSha256}, ${facts.subjectCommonName}, ${facts.issuerCommonName},
|
|
130
|
+
${facts.serialTail}, ${facts.document}, ${identity}, ${overrideBy}, ${override},
|
|
131
|
+
-- As duas datas coincidem aqui, e é correto: o material só chega a
|
|
132
|
+
-- esta linha porque a inspeção passou.
|
|
133
|
+
${input.actorId}, now(), now()
|
|
134
|
+
)
|
|
135
|
+
RETURNING ${tx.unsafe(CERTIFICATE_COLUMNS)}
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
status: 'stored',
|
|
140
|
+
certificate: mapCertificate(rows[0], { replaced: Boolean(existing[0]) }),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Grava (ou rotaciona) o segredo no cofre com `exposure = 'write_only'`.
|
|
145
|
+
*
|
|
146
|
+
* Não reutiliza `createCredential`/`rotateSecret` de `vault/repository.ts` por
|
|
147
|
+
* um motivo específico: aqueles não conhecem `exposure`, e um certificado
|
|
148
|
+
* gravado por eles nasceria `revealable` — a 0060 recusaria o INSERT, o que
|
|
149
|
+
* está correto, mas a mensagem de erro seria uma violação de CHECK em vez de
|
|
150
|
+
* uma decisão explícita. Aqui a classe do segredo é dita na escrita.
|
|
151
|
+
*/
|
|
152
|
+
async function upsertWriteOnlyCredential(tx, keyring, tenantId, input) {
|
|
153
|
+
const enc = (0, crypto_js_1.encryptSecret)(keyring, tenantId, input.secret);
|
|
154
|
+
const existing = await tx `
|
|
155
|
+
SELECT id FROM vault_credential
|
|
156
|
+
WHERE client_id = ${input.clientId}
|
|
157
|
+
AND lower(name) = lower(${input.name})
|
|
158
|
+
AND deleted_at IS NULL
|
|
159
|
+
LIMIT 1
|
|
160
|
+
`;
|
|
161
|
+
if (existing[0]) {
|
|
162
|
+
await tx `
|
|
163
|
+
UPDATE vault_credential SET
|
|
164
|
+
ciphertext = ${enc.ciphertext}, iv = ${enc.iv}, auth_tag = ${enc.authTag},
|
|
165
|
+
key_version = ${enc.keyVersion}, rotated_at = now(), updated_at = now(),
|
|
166
|
+
updated_by = ${input.actorId}, version = version + 1,
|
|
167
|
+
expires_at = ${input.expiresAt},
|
|
168
|
+
metadata = ${tx.json(input.metadata)},
|
|
169
|
+
exposure = 'write_only'
|
|
170
|
+
WHERE id = ${existing[0].id}
|
|
171
|
+
`;
|
|
172
|
+
return existing[0].id;
|
|
173
|
+
}
|
|
174
|
+
const rows = await tx `
|
|
175
|
+
INSERT INTO vault_credential (
|
|
176
|
+
id, tenant_id, client_id, name, category, provider,
|
|
177
|
+
ciphertext, iv, auth_tag, key_version, metadata, expires_at, created_by, exposure
|
|
178
|
+
) VALUES (
|
|
179
|
+
${(0, shared_1.uuidv7)()}, current_setting('app.current_tenant')::uuid, ${input.clientId},
|
|
180
|
+
${input.name}, 'certificate', 'icp_brasil',
|
|
181
|
+
${enc.ciphertext}, ${enc.iv}, ${enc.authTag}, ${enc.keyVersion},
|
|
182
|
+
${tx.json(input.metadata)}, ${input.expiresAt}, ${input.actorId}, 'write_only'
|
|
183
|
+
)
|
|
184
|
+
RETURNING id
|
|
185
|
+
`;
|
|
186
|
+
return rows[0].id;
|
|
187
|
+
}
|
|
188
|
+
const CERTIFICATE_COLUMNS = `
|
|
189
|
+
id, client_id, cert_type, status, subject_common_name, issuer_common_name,
|
|
190
|
+
serial_tail, fingerprint_sha256, certificate_document, identity_match,
|
|
191
|
+
identity_override_reason, issued_at, expires_at, uploaded_at, verified_at,
|
|
192
|
+
local_validated_at, remote_verification_provider
|
|
193
|
+
`;
|
|
194
|
+
function mapCertificate(r, extra) {
|
|
195
|
+
return {
|
|
196
|
+
id: r.id,
|
|
197
|
+
clientId: r.client_id,
|
|
198
|
+
certType: r.cert_type === 'A3' ? 'A3' : 'A1',
|
|
199
|
+
status: r.status,
|
|
200
|
+
subjectCommonName: r.subject_common_name,
|
|
201
|
+
issuerCommonName: r.issuer_common_name,
|
|
202
|
+
serialTail: r.serial_tail,
|
|
203
|
+
fingerprint: shortFingerprint(r.fingerprint_sha256 ?? ''),
|
|
204
|
+
certificateDocument: r.certificate_document,
|
|
205
|
+
identityMatch: r.identity_match ?? 'indeterminate',
|
|
206
|
+
identityOverrideReason: r.identity_override_reason,
|
|
207
|
+
issuedAt: r.issued_at ? isoDate(r.issued_at) : null,
|
|
208
|
+
expiresOn: isoDate(r.expires_at),
|
|
209
|
+
uploadedAt: r.uploaded_at?.toISOString() ?? null,
|
|
210
|
+
verifiedAt: r.verified_at?.toISOString() ?? null,
|
|
211
|
+
replaced: extra.replaced,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function isoDate(d) {
|
|
215
|
+
return d.toISOString().slice(0, 10);
|
|
216
|
+
}
|
|
217
|
+
/** Os certificados de um cliente, só metadata. É o que a tela lê. */
|
|
218
|
+
async function listFiscalCertificates(tx, clientId) {
|
|
219
|
+
const rows = await tx `
|
|
220
|
+
SELECT ${tx.unsafe(CERTIFICATE_COLUMNS)}
|
|
221
|
+
FROM digital_certificate
|
|
222
|
+
WHERE client_id = ${clientId} AND deleted_at IS NULL
|
|
223
|
+
ORDER BY expires_at DESC
|
|
224
|
+
`;
|
|
225
|
+
return rows.map((r) => mapCertificate(r, { replaced: false }));
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Revoga o uso do certificado DENTRO deste produto.
|
|
229
|
+
*
|
|
230
|
+
* Não toca a ICP-Brasil, e é por isso que a função se chama assim. Revogar de
|
|
231
|
+
* verdade um certificado é um ato junto à Autoridade Certificadora que o emitiu;
|
|
232
|
+
* apagar a linha daqui apenas garante que este produto pare de apresentá-lo. A
|
|
233
|
+
* tela repete a distinção, porque um operador que acredite ter revogado o
|
|
234
|
+
* certificado do cliente não vai à AC — e o certificado segue válido no mundo.
|
|
235
|
+
*
|
|
236
|
+
* O material sai do cofre no mesmo movimento (`deleted_at`), de modo que a
|
|
237
|
+
* revogação não deixa chave privada decifrável para trás.
|
|
238
|
+
*/
|
|
239
|
+
async function revokeFiscalCertificate(tx, clientId, certificateId) {
|
|
240
|
+
const rows = await tx `
|
|
241
|
+
UPDATE digital_certificate SET status = 'revoked', deleted_at = now(), updated_at = now()
|
|
242
|
+
WHERE id = ${certificateId} AND client_id = ${clientId} AND deleted_at IS NULL
|
|
243
|
+
RETURNING vault_credential_id
|
|
244
|
+
`;
|
|
245
|
+
if (rows.length === 0)
|
|
246
|
+
return { revoked: false };
|
|
247
|
+
const pointer = rows[0]?.vault_credential_id;
|
|
248
|
+
if (pointer) {
|
|
249
|
+
await tx `
|
|
250
|
+
UPDATE vault_credential SET deleted_at = now()
|
|
251
|
+
WHERE id = ${pointer} AND deleted_at IS NULL
|
|
252
|
+
`;
|
|
253
|
+
}
|
|
254
|
+
return { revoked: true };
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Impressão digital do material recebido, antes de qualquer decisão.
|
|
258
|
+
*
|
|
259
|
+
* Serve à trilha do upload recusado: registrar "tentaram subir algo" sem
|
|
260
|
+
* registrar o quê. É o mesmo cálculo de `material.ts`, e é seguro por
|
|
261
|
+
* construção — um hash não volta a ser um certificado.
|
|
262
|
+
*/
|
|
263
|
+
function materialFingerprint(material) {
|
|
264
|
+
return shortFingerprint((0, node_crypto_1.createHash)('sha256').update(material).digest('hex'));
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=onboarding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../../../../src/fiscal/credentials/onboarding.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,9 +25,12 @@ async function readFiscalCredentialReadiness(tx, input) {
|
|
|
25
25
|
const base = {
|
|
26
26
|
kind,
|
|
27
27
|
usableByWorker: false,
|
|
28
|
+
localValid: false,
|
|
29
|
+
eligibleForFirstContact: false,
|
|
28
30
|
selfHealing: false,
|
|
29
31
|
expiresOn: null,
|
|
30
32
|
verifiedAt: null,
|
|
33
|
+
localValidatedAt: null,
|
|
31
34
|
fingerprint: null,
|
|
32
35
|
providerAuthorization: 'unknown',
|
|
33
36
|
};
|
|
@@ -44,6 +47,7 @@ async function readFiscalCredentialReadiness(tx, input) {
|
|
|
44
47
|
try {
|
|
45
48
|
rows = await tx `
|
|
46
49
|
SELECT id, cert_type, status, expires_at, verified_at,
|
|
50
|
+
local_validated_at, fingerprint_sha256,
|
|
47
51
|
last_verification_error, vault_credential_id
|
|
48
52
|
FROM digital_certificate
|
|
49
53
|
WHERE client_id = ${input.clientId}
|
|
@@ -66,7 +70,14 @@ async function readFiscalCredentialReadiness(tx, input) {
|
|
|
66
70
|
}
|
|
67
71
|
const expiresOn = cert.expires_at ? isoDate(cert.expires_at) : null;
|
|
68
72
|
const verifiedAt = cert.verified_at?.toISOString() ?? null;
|
|
69
|
-
const
|
|
73
|
+
const localValidatedAt = cert.local_validated_at?.toISOString() ?? null;
|
|
74
|
+
const withDates = {
|
|
75
|
+
...base,
|
|
76
|
+
expiresOn,
|
|
77
|
+
verifiedAt,
|
|
78
|
+
localValidatedAt,
|
|
79
|
+
fingerprint: cert.fingerprint_sha256 ?? null,
|
|
80
|
+
};
|
|
70
81
|
if (cert.status === 'revoked') {
|
|
71
82
|
return { ...withDates, state: 'INVALID', detail: 'certificado revogado' };
|
|
72
83
|
}
|
|
@@ -105,10 +116,23 @@ async function readFiscalCredentialReadiness(tx, input) {
|
|
|
105
116
|
};
|
|
106
117
|
}
|
|
107
118
|
if (!cert.verified_at) {
|
|
119
|
+
// Aqui estava o impasse. Antes, tudo que não fora aceito remotamente caía
|
|
120
|
+
// num balde só, e o balde reprovava a execução — inclusive a execução que
|
|
121
|
+
// produziria o aceite. Agora o material conferido localmente tem estado
|
|
122
|
+
// próprio, e é ele que o primeiro contato aceita.
|
|
123
|
+
if (cert.local_validated_at) {
|
|
124
|
+
return {
|
|
125
|
+
...withDates,
|
|
126
|
+
state: 'LOCAL_VALID',
|
|
127
|
+
localValid: true,
|
|
128
|
+
eligibleForFirstContact: true,
|
|
129
|
+
detail: 'válida localmente; nenhum ambiente oficial a aceitou ainda',
|
|
130
|
+
};
|
|
131
|
+
}
|
|
108
132
|
return {
|
|
109
133
|
...withDates,
|
|
110
134
|
state: 'REQUIRES_REVIEW',
|
|
111
|
-
detail: '
|
|
135
|
+
detail: 'cadastrada sem validação local registrada',
|
|
112
136
|
};
|
|
113
137
|
}
|
|
114
138
|
// A autorização do provedor sai de execução OBSERVADA. Um `SELECT` sobre a
|
|
@@ -126,6 +150,9 @@ async function readFiscalCredentialReadiness(tx, input) {
|
|
|
126
150
|
...withDates,
|
|
127
151
|
state: 'READY',
|
|
128
152
|
usableByWorker: true,
|
|
153
|
+
localValid: true,
|
|
154
|
+
// Já aceita remotamente: não há primeiro contato a fazer.
|
|
155
|
+
eligibleForFirstContact: false,
|
|
129
156
|
selfHealing: true,
|
|
130
157
|
providerAuthorization: established ? 'established' : 'unknown',
|
|
131
158
|
detail: established
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readiness.js","sourceRoot":"","sources":["../../../../src/fiscal/credentials/readiness.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"readiness.js","sourceRoot":"","sources":["../../../../src/fiscal/credentials/readiness.ts"],"names":[],"mappings":"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"}
|