@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
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { uuidv7 } from '@baruk/shared';
|
|
2
|
+
import { resolveMunicipality } from './ibge.js';
|
|
3
|
+
import { cnpjDigits, isValidCnpj, } from './provider.js';
|
|
4
|
+
/** Os campos do cadastro que uma consulta oficial pode preencher. */
|
|
5
|
+
const CAMPOS = [
|
|
6
|
+
'legalName',
|
|
7
|
+
'tradeName',
|
|
8
|
+
'email',
|
|
9
|
+
'phone',
|
|
10
|
+
'addressLine',
|
|
11
|
+
'postalCode',
|
|
12
|
+
'municipality',
|
|
13
|
+
'stateUf',
|
|
14
|
+
'municipalityIbgeCode',
|
|
15
|
+
];
|
|
16
|
+
function endereco(r) {
|
|
17
|
+
const partes = [r.address.street, r.address.number, r.address.complement, r.address.district]
|
|
18
|
+
.map((p) => (p ?? '').trim())
|
|
19
|
+
.filter(Boolean);
|
|
20
|
+
return partes.length > 0 ? partes.join(', ') : null;
|
|
21
|
+
}
|
|
22
|
+
/** Só dígitos — CEP e telefone chegam com máscara de toda fonte. */
|
|
23
|
+
function digitos(v) {
|
|
24
|
+
const d = (v ?? '').replace(/\D/g, '');
|
|
25
|
+
return d === '' ? null : d;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Confronta o retrato oficial com o cadastro atual e devolve PROPOSTAS.
|
|
29
|
+
*
|
|
30
|
+
* Quatro desfechos por campo, e a UI trata cada um de um jeito:
|
|
31
|
+
*
|
|
32
|
+
* `absent` a fonte não informou. Nada a propor.
|
|
33
|
+
* `unchanged` igual ao que já está. Nada a fazer.
|
|
34
|
+
* `prefill` o cadastro está vazio — preencher é ganho, não é conflito.
|
|
35
|
+
* `conflict` os dois têm valor e diferem. **Só aqui alguém precisa decidir.**
|
|
36
|
+
*
|
|
37
|
+
* Separar `prefill` de `conflict` é o que evita a tela pedir confirmação de
|
|
38
|
+
* dezoito campos quando dezessete estavam em branco.
|
|
39
|
+
*/
|
|
40
|
+
export function buildProposals(record, atual, ibge) {
|
|
41
|
+
const oficial = {
|
|
42
|
+
legalName: record.legalName,
|
|
43
|
+
tradeName: record.tradeName,
|
|
44
|
+
email: record.email,
|
|
45
|
+
phone: digitos(record.phone),
|
|
46
|
+
addressLine: endereco(record),
|
|
47
|
+
postalCode: digitos(record.address.zipCode),
|
|
48
|
+
municipality: record.address.municipality,
|
|
49
|
+
stateUf: record.address.uf,
|
|
50
|
+
municipalityIbgeCode: ibge.status === 'match' ? ibge.code : null,
|
|
51
|
+
};
|
|
52
|
+
return CAMPOS.map((field) => {
|
|
53
|
+
const off = oficial[field];
|
|
54
|
+
const cur = atual[field] ?? null;
|
|
55
|
+
let decision;
|
|
56
|
+
if (off === null || off === '')
|
|
57
|
+
decision = 'absent';
|
|
58
|
+
else if (cur === null || cur === '')
|
|
59
|
+
decision = 'prefill';
|
|
60
|
+
else if (String(cur).trim().toLowerCase() === String(off).trim().toLowerCase())
|
|
61
|
+
decision = 'unchanged';
|
|
62
|
+
else
|
|
63
|
+
decision = 'conflict';
|
|
64
|
+
return { field, current: cur, official: off, decision };
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Executa a consulta e monta o resultado — sem tocar no banco.
|
|
69
|
+
*
|
|
70
|
+
* A separação é deliberada: consultar é uma operação de rede que pode falhar, e
|
|
71
|
+
* gravar é uma decisão humana que vem depois. Fundi-las faria uma consulta
|
|
72
|
+
* bem-sucedida alterar cadastro sem que ninguém tivesse confirmado.
|
|
73
|
+
*/
|
|
74
|
+
export async function lookupCompany(provider, cnpj, atual = {}) {
|
|
75
|
+
if (!isValidCnpj(cnpj)) {
|
|
76
|
+
return {
|
|
77
|
+
status: 'failed',
|
|
78
|
+
provider: provider.name,
|
|
79
|
+
official: provider.official,
|
|
80
|
+
reason: 'invalid_document',
|
|
81
|
+
proposals: [],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
let resultado;
|
|
85
|
+
try {
|
|
86
|
+
resultado = await provider.lookup(cnpjDigits(cnpj));
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Nenhuma exceção de provedor atravessa: a mensagem de um cliente HTTP cita
|
|
90
|
+
// URL, e URL de provedor pode carregar credencial no query string.
|
|
91
|
+
return {
|
|
92
|
+
status: 'failed',
|
|
93
|
+
provider: provider.name,
|
|
94
|
+
official: provider.official,
|
|
95
|
+
reason: 'provider_unavailable',
|
|
96
|
+
proposals: [],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (resultado.status === 'failed') {
|
|
100
|
+
return {
|
|
101
|
+
status: 'failed',
|
|
102
|
+
provider: provider.name,
|
|
103
|
+
official: provider.official,
|
|
104
|
+
reason: resultado.reason,
|
|
105
|
+
proposals: [],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const ibge = resolveMunicipality(resultado.record.address.municipality ?? '', resultado.record.address.uf);
|
|
109
|
+
return {
|
|
110
|
+
status: 'ok',
|
|
111
|
+
provider: provider.name,
|
|
112
|
+
official: provider.official,
|
|
113
|
+
record: resultado.record,
|
|
114
|
+
ibge,
|
|
115
|
+
proposals: buildProposals(resultado.record, atual, ibge),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Grava o retrato oficial ao lado do cadastro.
|
|
120
|
+
*
|
|
121
|
+
* `client` não é tocado aqui. O retrato é o que a fonte disse; aplicar sobre o
|
|
122
|
+
* cadastro é outro ato, com outra assinatura.
|
|
123
|
+
*/
|
|
124
|
+
export async function saveRegistrySnapshot(tx, input) {
|
|
125
|
+
const r = input.record;
|
|
126
|
+
const rows = await tx `
|
|
127
|
+
INSERT INTO client_registry_snapshot (
|
|
128
|
+
id, tenant_id, client_id, provider, provider_official, document_digits,
|
|
129
|
+
legal_name, trade_name, registration_status, opened_on, legal_nature, company_size,
|
|
130
|
+
primary_activity_code, primary_activity_text, secondary_activities,
|
|
131
|
+
street, street_number, complement, district, postal_code, municipality, state_uf,
|
|
132
|
+
phone, email, share_capital_cents, simples_optant, mei_optant
|
|
133
|
+
) VALUES (
|
|
134
|
+
${uuidv7()}, current_setting('app.current_tenant')::uuid, ${input.clientId},
|
|
135
|
+
${input.provider}, ${input.official}, ${cnpjDigits(r.cnpj)},
|
|
136
|
+
${r.legalName}, ${r.tradeName}, ${r.registrationStatus}, ${r.openedOn},
|
|
137
|
+
${r.legalNature}, ${r.size},
|
|
138
|
+
${r.primaryActivity?.code ?? null}, ${r.primaryActivity?.description ?? null},
|
|
139
|
+
${tx.json(r.secondaryActivities)},
|
|
140
|
+
${r.address.street}, ${r.address.number}, ${r.address.complement}, ${r.address.district},
|
|
141
|
+
${digitos(r.address.zipCode)}, ${r.address.municipality}, ${r.address.uf},
|
|
142
|
+
${digitos(r.phone)}, ${r.email},
|
|
143
|
+
${r.shareCapital === null ? null : Math.round(r.shareCapital * 100)},
|
|
144
|
+
${r.simplesOptant}, ${r.meiOptant}
|
|
145
|
+
)
|
|
146
|
+
RETURNING id
|
|
147
|
+
`;
|
|
148
|
+
return rows[0].id;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Marca a origem de um campo do cadastro.
|
|
152
|
+
*
|
|
153
|
+
* `human` vence: um campo que uma pessoa escreveu NUNCA volta a `official_lookup`
|
|
154
|
+
* por uma atualização automática. É esta função — e o `WHERE` dela — que faz
|
|
155
|
+
* `HUMAN_OVERRIDE_PRESERVED` ser uma consulta, e não uma promessa.
|
|
156
|
+
*/
|
|
157
|
+
export async function markFieldProvenance(tx, input) {
|
|
158
|
+
const oficial = input.origin === 'official_lookup';
|
|
159
|
+
await tx `
|
|
160
|
+
INSERT INTO client_field_provenance (
|
|
161
|
+
id, tenant_id, client_id, field, origin, provider, verified_at, updated_by
|
|
162
|
+
) VALUES (
|
|
163
|
+
${uuidv7()}, current_setting('app.current_tenant')::uuid, ${input.clientId},
|
|
164
|
+
${input.field}, ${input.origin}, ${oficial ? (input.provider ?? null) : null},
|
|
165
|
+
${oficial ? new Date().toISOString() : null}, ${input.updatedBy ?? null}
|
|
166
|
+
)
|
|
167
|
+
ON CONFLICT (tenant_id, client_id, field) DO UPDATE SET
|
|
168
|
+
origin = EXCLUDED.origin, provider = EXCLUDED.provider,
|
|
169
|
+
verified_at = EXCLUDED.verified_at, updated_by = EXCLUDED.updated_by,
|
|
170
|
+
updated_at = now()
|
|
171
|
+
-- A cláusula que preserva a decisão humana: uma atualização automática não
|
|
172
|
+
-- rebaixa um campo que alguém assumiu. Só outra pessoa faz isso.
|
|
173
|
+
WHERE client_field_provenance.origin <> 'human' OR EXCLUDED.origin = 'human'
|
|
174
|
+
`;
|
|
175
|
+
}
|
|
176
|
+
/** Os campos que uma pessoa assumiu — o autofill não os toca. */
|
|
177
|
+
export async function humanOwnedFields(tx, clientId) {
|
|
178
|
+
const rows = await tx `
|
|
179
|
+
SELECT field FROM client_field_provenance
|
|
180
|
+
WHERE client_id = ${clientId} AND origin = 'human'
|
|
181
|
+
`;
|
|
182
|
+
return rows.map((r) => r.field);
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=lookup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lookup.js","sourceRoot":"","sources":["../../../src/clients/registry/lookup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { isValidCnpj } from '../../import/br-documents.js';
|
|
2
|
+
/**
|
|
3
|
+
* A fonte oficial de dados cadastrais de uma empresa — atrás de uma interface.
|
|
4
|
+
*
|
|
5
|
+
* ## Por que interface, e não uma chamada à Receita dentro da tela
|
|
6
|
+
*
|
|
7
|
+
* Três razões, e a terceira é a que decide:
|
|
8
|
+
*
|
|
9
|
+
* 1. a fonte muda (Serpro hoje, Conecta amanhã, um convênio estadual depois);
|
|
10
|
+
* 2. o teste precisa de um provedor determinístico, e um teste que fala com a
|
|
11
|
+
* Receita não é um teste — é uma consulta paga com asserção em volta;
|
|
12
|
+
* 3. **a fonte oficial em tempo real exige contrato comercial.** Sem a interface,
|
|
13
|
+
* a ausência do contrato viraria uma chamada a uma API comunitária "só por
|
|
14
|
+
* enquanto", e o "por enquanto" de uma fonte cadastral é o que fica.
|
|
15
|
+
*
|
|
16
|
+
* ## O que este produto NÃO faz
|
|
17
|
+
*
|
|
18
|
+
* Não raspa página pública, e não elege API comunitária como fonte canônica.
|
|
19
|
+
* Dado cadastral de terceiro que decide obrigação fiscal precisa de origem
|
|
20
|
+
* nomeável — e `PROVIDER_NOT_CONFIGURED` é uma resposta melhor que um dado de
|
|
21
|
+
* procedência incerta.
|
|
22
|
+
*/
|
|
23
|
+
/** Situação cadastral, tal como a Receita a publica. Vocabulário fechado. */
|
|
24
|
+
export type RegistrationStatus = 'ATIVA' | 'SUSPENSA' | 'INAPTA' | 'BAIXADA' | 'NULA' | 'DESCONHECIDA';
|
|
25
|
+
export interface CompanyAddress {
|
|
26
|
+
street: string | null;
|
|
27
|
+
number: string | null;
|
|
28
|
+
complement: string | null;
|
|
29
|
+
district: string | null;
|
|
30
|
+
zipCode: string | null;
|
|
31
|
+
municipality: string | null;
|
|
32
|
+
uf: string | null;
|
|
33
|
+
}
|
|
34
|
+
export interface CompanyActivity {
|
|
35
|
+
code: string;
|
|
36
|
+
description: string | null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* O retrato normalizado. Todo campo é opcional porque toda fonte tem lacuna —
|
|
40
|
+
* e um campo ausente precisa ser dizível como ausente, não como vazio.
|
|
41
|
+
*/
|
|
42
|
+
export interface CompanyRegistryRecord {
|
|
43
|
+
cnpj: string;
|
|
44
|
+
legalName: string | null;
|
|
45
|
+
tradeName: string | null;
|
|
46
|
+
registrationStatus: RegistrationStatus;
|
|
47
|
+
openedOn: string | null;
|
|
48
|
+
legalNature: string | null;
|
|
49
|
+
size: string | null;
|
|
50
|
+
primaryActivity: CompanyActivity | null;
|
|
51
|
+
secondaryActivities: readonly CompanyActivity[];
|
|
52
|
+
address: CompanyAddress;
|
|
53
|
+
phone: string | null;
|
|
54
|
+
email: string | null;
|
|
55
|
+
shareCapital: number | null;
|
|
56
|
+
/**
|
|
57
|
+
* Optante pelo Simples / MEI, quando a FONTE informa.
|
|
58
|
+
*
|
|
59
|
+
* `null` é "a fonte não disse" e NÃO é `false`. A diferença decide regime
|
|
60
|
+
* tributário, e tratar silêncio como negativa é como um cliente do Simples
|
|
61
|
+
* vira Lucro Presumido por omissão.
|
|
62
|
+
*/
|
|
63
|
+
simplesOptant: boolean | null;
|
|
64
|
+
meiOptant: boolean | null;
|
|
65
|
+
}
|
|
66
|
+
/** Classes de falha. Cada uma pede uma reação diferente de quem chama. */
|
|
67
|
+
export type CompanyLookupFailure =
|
|
68
|
+
/** Não há provedor configurado — o caminho oficial existe e não foi contratado. */
|
|
69
|
+
'provider_not_configured'
|
|
70
|
+
/** O CNPJ não tem forma válida. Recusado antes de sair da máquina. */
|
|
71
|
+
| 'invalid_document'
|
|
72
|
+
/** A fonte respondeu que não conhece este CNPJ. */
|
|
73
|
+
| 'not_found'
|
|
74
|
+
/** Teto de consultas. Reagir esperando, nunca insistindo. */
|
|
75
|
+
| 'rate_limited'
|
|
76
|
+
/** A fonte falhou ou demorou. Retentável. */
|
|
77
|
+
| 'provider_unavailable'
|
|
78
|
+
/** A fonte respondeu algo que este contrato não sabe ler. Fail closed. */
|
|
79
|
+
| 'unexpected_payload';
|
|
80
|
+
export type CompanyLookupResult = {
|
|
81
|
+
status: 'ok';
|
|
82
|
+
record: CompanyRegistryRecord;
|
|
83
|
+
source: string;
|
|
84
|
+
fetchedAt: string;
|
|
85
|
+
} | {
|
|
86
|
+
status: 'failed';
|
|
87
|
+
reason: CompanyLookupFailure;
|
|
88
|
+
source: string;
|
|
89
|
+
};
|
|
90
|
+
export interface CompanyRegistryProvider {
|
|
91
|
+
/** Nome curto e estável — vai para a proveniência do dado e para a trilha. */
|
|
92
|
+
readonly name: string;
|
|
93
|
+
/** `true` só quando a fonte é oficial. A UI diz isso ao operador. */
|
|
94
|
+
readonly official: boolean;
|
|
95
|
+
lookup(cnpj: string): Promise<CompanyLookupResult>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Dígitos do CNPJ, sem máscara.
|
|
99
|
+
*
|
|
100
|
+
* Delega a `onlyDigits`, e não repete o `replace`: o dia em que a normalização
|
|
101
|
+
* precisar tratar um caractere invisível colado de um PDF, ela precisa mudar
|
|
102
|
+
* num lugar só.
|
|
103
|
+
*/
|
|
104
|
+
export declare function cnpjDigits(value: string): string;
|
|
105
|
+
/**
|
|
106
|
+
* Validade do CNPJ — reexportada, nunca reimplementada.
|
|
107
|
+
*
|
|
108
|
+
* A regra já vive em `import/br-documents.ts`, onde nasceu para a importação de
|
|
109
|
+
* carteira. Escrever uma segunda aqui produziria duas réguas para a mesma
|
|
110
|
+
* pergunta, e a divergência entre elas decidiria quais cadastros entram: um
|
|
111
|
+
* documento aceito pela importação e recusado pela consulta (ou o contrário) é
|
|
112
|
+
* um defeito que nenhum dos dois lados vê sozinho.
|
|
113
|
+
*/
|
|
114
|
+
export { isValidCnpj };
|
|
115
|
+
/**
|
|
116
|
+
* O provedor que responde quando nenhum está configurado.
|
|
117
|
+
*
|
|
118
|
+
* Existe para que a ausência de contrato seja um estado NOMEADO do produto, e
|
|
119
|
+
* não uma exceção no meio de um formulário. Quem chama recebe
|
|
120
|
+
* `provider_not_configured` e mostra "não foi possível consultar
|
|
121
|
+
* automaticamente" — o cadastro manual segue funcionando.
|
|
122
|
+
*/
|
|
123
|
+
export declare const unconfiguredCompanyRegistry: CompanyRegistryProvider;
|
|
124
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/clients/registry/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAc,MAAM,8BAA8B,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,kBAAkB,GAC5B,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,cAAc,CAAC;AAExE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,mBAAmB,EAAE,SAAS,eAAe,EAAE,CAAC;IAChD,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;;;;OAMG;IACH,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;CAC3B;AAED,0EAA0E;AAC1E,MAAM,MAAM,oBAAoB;AAC9B,mFAAmF;AACjF,yBAAyB;AAC3B,sEAAsE;GACpE,kBAAkB;AACpB,mDAAmD;GACjD,WAAW;AACb,6DAA6D;GAC3D,cAAc;AAChB,6CAA6C;GAC3C,sBAAsB;AACxB,0EAA0E;GACxE,oBAAoB,CAAC;AAEzB,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAClF;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,MAAM,WAAW,uBAAuB;IACtC,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACpD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;;;;;GAQG;AACH,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,EAAE,uBAQzC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { isValidCnpj, onlyDigits } from '../../import/br-documents.js';
|
|
2
|
+
/**
|
|
3
|
+
* Dígitos do CNPJ, sem máscara.
|
|
4
|
+
*
|
|
5
|
+
* Delega a `onlyDigits`, e não repete o `replace`: o dia em que a normalização
|
|
6
|
+
* precisar tratar um caractere invisível colado de um PDF, ela precisa mudar
|
|
7
|
+
* num lugar só.
|
|
8
|
+
*/
|
|
9
|
+
export function cnpjDigits(value) {
|
|
10
|
+
return onlyDigits(value);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Validade do CNPJ — reexportada, nunca reimplementada.
|
|
14
|
+
*
|
|
15
|
+
* A regra já vive em `import/br-documents.ts`, onde nasceu para a importação de
|
|
16
|
+
* carteira. Escrever uma segunda aqui produziria duas réguas para a mesma
|
|
17
|
+
* pergunta, e a divergência entre elas decidiria quais cadastros entram: um
|
|
18
|
+
* documento aceito pela importação e recusado pela consulta (ou o contrário) é
|
|
19
|
+
* um defeito que nenhum dos dois lados vê sozinho.
|
|
20
|
+
*/
|
|
21
|
+
export { isValidCnpj };
|
|
22
|
+
/**
|
|
23
|
+
* O provedor que responde quando nenhum está configurado.
|
|
24
|
+
*
|
|
25
|
+
* Existe para que a ausência de contrato seja um estado NOMEADO do produto, e
|
|
26
|
+
* não uma exceção no meio de um formulário. Quem chama recebe
|
|
27
|
+
* `provider_not_configured` e mostra "não foi possível consultar
|
|
28
|
+
* automaticamente" — o cadastro manual segue funcionando.
|
|
29
|
+
*/
|
|
30
|
+
export const unconfiguredCompanyRegistry = {
|
|
31
|
+
name: 'unconfigured',
|
|
32
|
+
official: false,
|
|
33
|
+
lookup: async (cnpj) => ({
|
|
34
|
+
status: 'failed',
|
|
35
|
+
reason: isValidCnpj(cnpj) ? 'provider_not_configured' : 'invalid_document',
|
|
36
|
+
source: 'unconfigured',
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/clients/registry/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAmGvE;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;;;;GAQG;AACH,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAA4B;IAClE,IAAI,EAAE,cAAc;IACpB,QAAQ,EAAE,KAAK;IACf,MAAM,EAAE,KAAK,EAAE,IAAY,EAAE,EAAE,CAAC,CAAC;QAC/B,MAAM,EAAE,QAAQ;QAChB,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,kBAAkB;QAC1E,MAAM,EAAE,cAAc;KACvB,CAAC;CACH,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type CompanyRegistryProvider } from './provider.js';
|
|
2
|
+
/**
|
|
3
|
+
* Qual provedor este ambiente tem — e por que ele pode não ter nenhum.
|
|
4
|
+
*
|
|
5
|
+
* ## A ausência é um estado do produto, não um defeito
|
|
6
|
+
*
|
|
7
|
+
* Não há contrato com fonte oficial hoje. A resposta a isso não é adiar a
|
|
8
|
+
* funcionalidade nem improvisar com um agregador: é fazer "sem fonte oficial"
|
|
9
|
+
* ser uma resposta que o produto sabe dar. A tela de cadastro continua
|
|
10
|
+
* funcionando — o operador digita tudo à mão, como digita hoje — e diz por que
|
|
11
|
+
* o botão de consulta não está lá.
|
|
12
|
+
*
|
|
13
|
+
* O ganho de nomear o estado é que ligar a fonte, quando o contrato existir,
|
|
14
|
+
* é uma variável de ambiente. Não é uma refatoração.
|
|
15
|
+
*/
|
|
16
|
+
export type RegistryProviderChoice = 'none' | 'synthetic' | 'serpro';
|
|
17
|
+
export interface RegistryAvailability {
|
|
18
|
+
provider: CompanyRegistryProvider;
|
|
19
|
+
/** `true` quando há um provedor que de fato consulta alguma coisa. */
|
|
20
|
+
enabled: boolean;
|
|
21
|
+
/** Por que não está disponível — o texto que a tela explica ao operador. */
|
|
22
|
+
reason: 'available' | 'not_configured' | 'contract_unverified' | 'missing_credential' | 'unknown_choice';
|
|
23
|
+
}
|
|
24
|
+
export interface RegistryEnv {
|
|
25
|
+
COMPANY_REGISTRY_PROVIDER?: string | undefined;
|
|
26
|
+
SERPRO_CONSULTA_CNPJ_TOKEN?: string | undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolve o provedor a partir do ambiente.
|
|
30
|
+
*
|
|
31
|
+
* O padrão é `none`. Um padrão que tentasse adivinhar — "tem token? então usa"
|
|
32
|
+
* — ligaria consulta paga em qualquer ambiente onde a variável vazasse, e a
|
|
33
|
+
* primeira fatura seria a notificação.
|
|
34
|
+
*/
|
|
35
|
+
export declare function resolveCompanyRegistry(env?: RegistryEnv): RegistryAvailability;
|
|
36
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/clients/registry/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,EAA+B,KAAK,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAE1F;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;AAErE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,uBAAuB,CAAC;IAClC,sEAAsE;IACtE,OAAO,EAAE,OAAO,CAAC;IACjB,4EAA4E;IAC5E,MAAM,EACF,WAAW,GACX,gBAAgB,GAChB,qBAAqB,GACrB,oBAAoB,GACpB,gBAAgB,CAAC;CACtB;AAQD,MAAM,WAAW,WAAW;IAC1B,yBAAyB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,0BAA0B,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,WAAyB,GAAG,oBAAoB,CA2B3F"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createSerproCompanyRegistry, SerproContractUnverifiedError } from './serpro.js';
|
|
2
|
+
import { syntheticCompanyRegistry } from './synthetic.js';
|
|
3
|
+
import { unconfiguredCompanyRegistry } from './provider.js';
|
|
4
|
+
const INDISPONIVEL = (reason) => ({
|
|
5
|
+
provider: unconfiguredCompanyRegistry,
|
|
6
|
+
enabled: false,
|
|
7
|
+
reason,
|
|
8
|
+
});
|
|
9
|
+
/**
|
|
10
|
+
* Resolve o provedor a partir do ambiente.
|
|
11
|
+
*
|
|
12
|
+
* O padrão é `none`. Um padrão que tentasse adivinhar — "tem token? então usa"
|
|
13
|
+
* — ligaria consulta paga em qualquer ambiente onde a variável vazasse, e a
|
|
14
|
+
* primeira fatura seria a notificação.
|
|
15
|
+
*/
|
|
16
|
+
export function resolveCompanyRegistry(env = process.env) {
|
|
17
|
+
const escolha = (env.COMPANY_REGISTRY_PROVIDER ?? 'none').trim().toLowerCase();
|
|
18
|
+
if (escolha === '' || escolha === 'none')
|
|
19
|
+
return INDISPONIVEL('not_configured');
|
|
20
|
+
if (escolha === 'synthetic') {
|
|
21
|
+
// Sintético é `official: false` na origem, e o carimbo acompanha todo dado
|
|
22
|
+
// que ele produzir. Ver `synthetic.ts`.
|
|
23
|
+
return { provider: syntheticCompanyRegistry(), enabled: true, reason: 'available' };
|
|
24
|
+
}
|
|
25
|
+
if (escolha === 'serpro') {
|
|
26
|
+
const token = (env.SERPRO_CONSULTA_CNPJ_TOKEN ?? '').trim();
|
|
27
|
+
if (token === '')
|
|
28
|
+
return INDISPONIVEL('missing_credential');
|
|
29
|
+
try {
|
|
30
|
+
return {
|
|
31
|
+
provider: createSerproCompanyRegistry({ token }),
|
|
32
|
+
enabled: true,
|
|
33
|
+
reason: 'available',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (err instanceof SerproContractUnverifiedError)
|
|
38
|
+
return INDISPONIVEL('contract_unverified');
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return INDISPONIVEL('unknown_choice');
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/clients/registry/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAgC,MAAM,eAAe,CAAC;AAgC1F,MAAM,YAAY,GAAG,CAAC,MAAsC,EAAwB,EAAE,CAAC,CAAC;IACtF,QAAQ,EAAE,2BAA2B;IACrC,OAAO,EAAE,KAAK;IACd,MAAM;CACP,CAAC,CAAC;AAOH;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAmB,OAAO,CAAC,GAAG;IACnE,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,yBAAyB,IAAI,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE/E,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAEhF,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC5B,2EAA2E;QAC3E,wCAAwC;QACxC,OAAO,EAAE,QAAQ,EAAE,wBAAwB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACtF,CAAC;IAED,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5D,IAAI,KAAK,KAAK,EAAE;YAAE,OAAO,YAAY,CAAC,oBAAoB,CAAC,CAAC;QAC5D,IAAI,CAAC;YACH,OAAO;gBACL,QAAQ,EAAE,2BAA2B,CAAC,EAAE,KAAK,EAAE,CAAC;gBAChD,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,WAAW;aACpB,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,6BAA6B;gBAAE,OAAO,YAAY,CAAC,qBAAqB,CAAC,CAAC;YAC7F,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAC,gBAAgB,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { CompanyRegistryProvider, CompanyRegistryRecord } from './provider.js';
|
|
2
|
+
/**
|
|
3
|
+
* Serpro — Consulta CNPJ. Escrito, e deliberadamente fechado.
|
|
4
|
+
*
|
|
5
|
+
* ## Por que existe um adaptador que ninguém pode ligar
|
|
6
|
+
*
|
|
7
|
+
* A descoberta desta rodada encontrou exatamente três fontes oficiais de dado
|
|
8
|
+
* cadastral de CNPJ, e nenhuma delas está disponível para este produto hoje:
|
|
9
|
+
*
|
|
10
|
+
* - **Conecta gov.br (Receita Federal)** — restrita a órgãos públicos. A SC é
|
|
11
|
+
* uma empresa privada. Não é questão de pedir acesso; é fora do escopo.
|
|
12
|
+
* - **Serpro Consulta CNPJ** — oficial e disponível, mediante **contrato
|
|
13
|
+
* comercial**. Há período de avaliação (30 dias / 3.000 consultas), que
|
|
14
|
+
* também exige cadastro e aceite de termos por uma pessoa jurídica.
|
|
15
|
+
* - **Dados Abertos da RFB** — oficial, mas são dumps CSV mensais. Servem
|
|
16
|
+
* para conferência em lote; não respondem "consulte este CNPJ agora".
|
|
17
|
+
*
|
|
18
|
+
* Agregadores comunitários gratuitos resolveriam o problema técnico hoje e
|
|
19
|
+
* criariam outro: o dado não teria autoria, e a etiqueta de proveniência diria
|
|
20
|
+
* "oficial" sobre algo que ninguém oficial afirmou. Ficam fora.
|
|
21
|
+
*
|
|
22
|
+
* ## Por que não basta ter o token
|
|
23
|
+
*
|
|
24
|
+
* **Os nomes dos campos da resposta não foram conferidos contra o serviço
|
|
25
|
+
* real.** O `parse` abaixo é a melhor leitura da documentação pública, e uma
|
|
26
|
+
* leitura não conferida que roda em produção é como um campo silenciosamente
|
|
27
|
+
* vazio vira "a Receita não informou" — indistinguível de uma ausência
|
|
28
|
+
* verdadeira, e muito pior, porque ninguém vai procurar.
|
|
29
|
+
*
|
|
30
|
+
* Enquanto `SERPRO_CONTRACT_VERIFIED` for `false`, este provedor não é
|
|
31
|
+
* construível, mesmo com credencial. Ligar exige DUAS coisas: o contrato
|
|
32
|
+
* (humano, externo) e a conferência do envelope contra uma resposta real.
|
|
33
|
+
*/
|
|
34
|
+
export declare const SERPRO_BASE_URL = "https://gateway.apiserpro.serpro.gov.br/consulta-cnpj-df/v2";
|
|
35
|
+
/**
|
|
36
|
+
* O envelope de resposta foi conferido contra o serviço real?
|
|
37
|
+
*
|
|
38
|
+
* Vira `true` numa mudança de código com a evidência anexada — nunca por
|
|
39
|
+
* variável de ambiente. Uma flag de ambiente permitiria ligar em produção o que
|
|
40
|
+
* ninguém verificou, que é precisamente o que esta constante impede.
|
|
41
|
+
*/
|
|
42
|
+
export declare const SERPRO_CONTRACT_VERIFIED = false;
|
|
43
|
+
export declare class SerproContractUnverifiedError extends Error {
|
|
44
|
+
constructor();
|
|
45
|
+
}
|
|
46
|
+
/** Leitura da documentação pública. NÃO conferida contra resposta real. */
|
|
47
|
+
export declare function parseSerproPayload(body: unknown): CompanyRegistryRecord | null;
|
|
48
|
+
export interface SerproOptions {
|
|
49
|
+
token: string;
|
|
50
|
+
baseUrl?: string;
|
|
51
|
+
fetchImpl?: typeof fetch;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Constrói o provedor do Serpro. Recusa enquanto o contrato não for conferido.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createSerproCompanyRegistry(options: SerproOptions): CompanyRegistryProvider;
|
|
57
|
+
//# sourceMappingURL=serpro.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serpro.d.ts","sourceRoot":"","sources":["../../../src/clients/registry/serpro.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EAEtB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,eAAO,MAAM,eAAe,gEAAgE,CAAC;AAE7F;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAE9C,qBAAa,6BAA8B,SAAQ,KAAK;;CAQvD;AAkCD,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,qBAAqB,GAAG,IAAI,CA+C9E;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,aAAa,GAAG,uBAAuB,CAa3F"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { createHttpCompanyRegistry } from './http.js';
|
|
2
|
+
/**
|
|
3
|
+
* Serpro — Consulta CNPJ. Escrito, e deliberadamente fechado.
|
|
4
|
+
*
|
|
5
|
+
* ## Por que existe um adaptador que ninguém pode ligar
|
|
6
|
+
*
|
|
7
|
+
* A descoberta desta rodada encontrou exatamente três fontes oficiais de dado
|
|
8
|
+
* cadastral de CNPJ, e nenhuma delas está disponível para este produto hoje:
|
|
9
|
+
*
|
|
10
|
+
* - **Conecta gov.br (Receita Federal)** — restrita a órgãos públicos. A SC é
|
|
11
|
+
* uma empresa privada. Não é questão de pedir acesso; é fora do escopo.
|
|
12
|
+
* - **Serpro Consulta CNPJ** — oficial e disponível, mediante **contrato
|
|
13
|
+
* comercial**. Há período de avaliação (30 dias / 3.000 consultas), que
|
|
14
|
+
* também exige cadastro e aceite de termos por uma pessoa jurídica.
|
|
15
|
+
* - **Dados Abertos da RFB** — oficial, mas são dumps CSV mensais. Servem
|
|
16
|
+
* para conferência em lote; não respondem "consulte este CNPJ agora".
|
|
17
|
+
*
|
|
18
|
+
* Agregadores comunitários gratuitos resolveriam o problema técnico hoje e
|
|
19
|
+
* criariam outro: o dado não teria autoria, e a etiqueta de proveniência diria
|
|
20
|
+
* "oficial" sobre algo que ninguém oficial afirmou. Ficam fora.
|
|
21
|
+
*
|
|
22
|
+
* ## Por que não basta ter o token
|
|
23
|
+
*
|
|
24
|
+
* **Os nomes dos campos da resposta não foram conferidos contra o serviço
|
|
25
|
+
* real.** O `parse` abaixo é a melhor leitura da documentação pública, e uma
|
|
26
|
+
* leitura não conferida que roda em produção é como um campo silenciosamente
|
|
27
|
+
* vazio vira "a Receita não informou" — indistinguível de uma ausência
|
|
28
|
+
* verdadeira, e muito pior, porque ninguém vai procurar.
|
|
29
|
+
*
|
|
30
|
+
* Enquanto `SERPRO_CONTRACT_VERIFIED` for `false`, este provedor não é
|
|
31
|
+
* construível, mesmo com credencial. Ligar exige DUAS coisas: o contrato
|
|
32
|
+
* (humano, externo) e a conferência do envelope contra uma resposta real.
|
|
33
|
+
*/
|
|
34
|
+
export const SERPRO_BASE_URL = 'https://gateway.apiserpro.serpro.gov.br/consulta-cnpj-df/v2';
|
|
35
|
+
/**
|
|
36
|
+
* O envelope de resposta foi conferido contra o serviço real?
|
|
37
|
+
*
|
|
38
|
+
* Vira `true` numa mudança de código com a evidência anexada — nunca por
|
|
39
|
+
* variável de ambiente. Uma flag de ambiente permitiria ligar em produção o que
|
|
40
|
+
* ninguém verificou, que é precisamente o que esta constante impede.
|
|
41
|
+
*/
|
|
42
|
+
export const SERPRO_CONTRACT_VERIFIED = false;
|
|
43
|
+
export class SerproContractUnverifiedError extends Error {
|
|
44
|
+
constructor() {
|
|
45
|
+
super('o envelope de resposta do Serpro Consulta CNPJ não foi conferido contra o serviço real; ' +
|
|
46
|
+
'o provedor permanece fechado até que seja');
|
|
47
|
+
this.name = 'SerproContractUnverifiedError';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function texto(v) {
|
|
51
|
+
const s = typeof v === 'string' ? v.trim() : typeof v === 'number' ? String(v) : '';
|
|
52
|
+
return s === '' ? null : s;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Situação cadastral pelo código da RFB.
|
|
56
|
+
*
|
|
57
|
+
* Código desconhecido vira `DESCONHECIDA`, e não `ATIVA`. Tratar o desconhecido
|
|
58
|
+
* como ativo faria uma empresa baixada entrar na carteira como operante — e o
|
|
59
|
+
* motor fiscal passaria a gerar obrigação para quem não tem mais nenhuma.
|
|
60
|
+
*/
|
|
61
|
+
function situacao(codigo) {
|
|
62
|
+
switch (texto(codigo)) {
|
|
63
|
+
case '2':
|
|
64
|
+
return 'ATIVA';
|
|
65
|
+
case '3':
|
|
66
|
+
return 'SUSPENSA';
|
|
67
|
+
case '4':
|
|
68
|
+
return 'INAPTA';
|
|
69
|
+
case '8':
|
|
70
|
+
return 'BAIXADA';
|
|
71
|
+
case '1':
|
|
72
|
+
return 'NULA';
|
|
73
|
+
default:
|
|
74
|
+
return 'DESCONHECIDA';
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const bag = (v) => (v && typeof v === 'object' ? v : {});
|
|
78
|
+
/** Leitura da documentação pública. NÃO conferida contra resposta real. */
|
|
79
|
+
export function parseSerproPayload(body) {
|
|
80
|
+
const b = bag(body);
|
|
81
|
+
const ni = texto(b.ni);
|
|
82
|
+
if (!ni)
|
|
83
|
+
return null;
|
|
84
|
+
const end = bag(b.endereco);
|
|
85
|
+
const principal = bag(b.cnaePrincipal);
|
|
86
|
+
const telefone = Array.isArray(b.telefones) ? bag(b.telefones[0]) : {};
|
|
87
|
+
const ddd = texto(telefone.ddd);
|
|
88
|
+
const numero = texto(telefone.numero);
|
|
89
|
+
return {
|
|
90
|
+
cnpj: ni,
|
|
91
|
+
legalName: texto(b.nomeEmpresarial),
|
|
92
|
+
tradeName: texto(b.nomeFantasia),
|
|
93
|
+
registrationStatus: situacao(bag(b.situacaoCadastral).codigo),
|
|
94
|
+
openedOn: texto(b.dataAbertura),
|
|
95
|
+
legalNature: texto(bag(b.naturezaJuridica).descricao),
|
|
96
|
+
size: texto(b.porte),
|
|
97
|
+
primaryActivity: texto(principal.codigo)
|
|
98
|
+
? { code: texto(principal.codigo), description: texto(principal.descricao) }
|
|
99
|
+
: null,
|
|
100
|
+
secondaryActivities: (Array.isArray(b.cnaeSecundarias) ? b.cnaeSecundarias : [])
|
|
101
|
+
.map((c) => bag(c))
|
|
102
|
+
.filter((c) => texto(c.codigo))
|
|
103
|
+
.map((c) => ({ code: texto(c.codigo), description: texto(c.descricao) })),
|
|
104
|
+
address: {
|
|
105
|
+
street: texto(end.logradouro),
|
|
106
|
+
number: texto(end.numero),
|
|
107
|
+
complement: texto(end.complemento),
|
|
108
|
+
district: texto(end.bairro),
|
|
109
|
+
zipCode: texto(end.cep),
|
|
110
|
+
municipality: texto(bag(end.municipio).descricao) ?? texto(end.municipio),
|
|
111
|
+
uf: texto(end.uf),
|
|
112
|
+
},
|
|
113
|
+
phone: ddd && numero ? `${ddd}${numero}` : numero,
|
|
114
|
+
email: texto(b.correioEletronico),
|
|
115
|
+
shareCapital: typeof b.capitalSocial === 'number' ? b.capitalSocial : null,
|
|
116
|
+
// ═══ O silêncio, preservado ═══════════════════════════════════════════
|
|
117
|
+
// Esta consulta NÃO informa opção pelo Simples nem MEI. `null` diz isso.
|
|
118
|
+
// Preencher `false` aqui — "a resposta não citou, então não é" — faria um
|
|
119
|
+
// optante do Simples ser tratado como Lucro Presumido pelo motor fiscal,
|
|
120
|
+
// por uma dedução que nenhuma fonte fez.
|
|
121
|
+
simplesOptant: null,
|
|
122
|
+
meiOptant: null,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Constrói o provedor do Serpro. Recusa enquanto o contrato não for conferido.
|
|
127
|
+
*/
|
|
128
|
+
export function createSerproCompanyRegistry(options) {
|
|
129
|
+
if (!SERPRO_CONTRACT_VERIFIED)
|
|
130
|
+
throw new SerproContractUnverifiedError();
|
|
131
|
+
const base = options.baseUrl ?? SERPRO_BASE_URL;
|
|
132
|
+
return createHttpCompanyRegistry({
|
|
133
|
+
name: 'serpro',
|
|
134
|
+
official: true,
|
|
135
|
+
buildUrl: (cnpj) => `${base}/basica/${cnpj}`,
|
|
136
|
+
// A credencial vive AQUI e só aqui. Nunca na URL: query string entra em log
|
|
137
|
+
// de proxy, em `Referer` e em mensagem de erro.
|
|
138
|
+
headers: () => ({ authorization: `Bearer ${options.token}` }),
|
|
139
|
+
parse: parseSerproPayload,
|
|
140
|
+
...(options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=serpro.js.map
|