@gyramais/log-redaction 0.2.1 → 0.3.1
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/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +47 -21
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { IncomingHttpHeaders } from 'http';
|
|
2
|
-
export declare const SAFE_HEADERS: string[];
|
|
3
|
-
export declare const SENSITIVE_FIELDS: string[];
|
|
4
|
-
export declare const OAUTH_CALLBACK_ONLY_FIELDS: string[];
|
|
5
|
-
export declare const OIDC_CALLBACK_MARKERS: string[];
|
|
6
|
-
export declare const PII_FIELDS: string[];
|
|
7
|
-
export declare const DOCUMENT_FIELDS: string[];
|
|
8
|
-
export declare const AMBIGUOUS_PII_FIELDS: string[];
|
|
2
|
+
export declare const SAFE_HEADERS: readonly string[];
|
|
3
|
+
export declare const SENSITIVE_FIELDS: readonly string[];
|
|
4
|
+
export declare const OAUTH_CALLBACK_ONLY_FIELDS: readonly string[];
|
|
5
|
+
export declare const OIDC_CALLBACK_MARKERS: readonly string[];
|
|
6
|
+
export declare const PII_FIELDS: readonly string[];
|
|
7
|
+
export declare const DOCUMENT_FIELDS: readonly string[];
|
|
8
|
+
export declare const AMBIGUOUS_PII_FIELDS: readonly string[];
|
|
9
9
|
export declare const LOOKS_PERSONAL: RegExp;
|
|
10
10
|
export declare const FORMATTING_NOISE: RegExp;
|
|
11
11
|
export declare const looksPersonal: (value: unknown) => boolean;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAQhD,eAAO,MAAM,YAAY,mBAMvB,CAAC;AAGH,eAAO,MAAM,gBAAgB,mBAuB3B,CAAC;AAWH,eAAO,MAAM,0BAA0B,mBAA2B,CAAC;AAGnE,eAAO,MAAM,qBAAqB,mBAAqC,CAAC;AAgBxE,eAAO,MAAM,UAAU,mBAcrB,CAAC;AAUH,eAAO,MAAM,eAAe,mBAO1B,CAAC;AAQH,eAAO,MAAM,oBAAoB,mBAAwB,CAAC;AAM1D,eAAO,MAAM,cAAc,QAAqB,CAAC;AAKjD,eAAO,MAAM,gBAAgB,QAAa,CAAC;AAE3C,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,OAEW,CAAC;AAE3D,eAAO,MAAM,QAAQ,SAAS,CAAC;AAC/B,eAAO,MAAM,SAAS,+BAA0B,CAAC;AACjD,eAAO,MAAM,QAAQ,eAAe,CAAC;AAIrC,eAAO,MAAM,cAAc,IAAI,CAAC;AAOhC,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,MACH,CAAC;AAWzC,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,OACH,CAAC;AACxC,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,KAAG,OAA0C,CAAC;AAC/E,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,KAAG,OACH,CAAC;AAYvC,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,EAAE,OAAO,OAAO,KAAG,OAEkB,CAAC;AAEhF,eAAO,MAAM,mBAAmB,GAAI,KAAK,MAAM,KAAG,OACD,CAAC;AAElD,eAAO,MAAM,mBAAmB,GAAI,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,OACM,CAAC;AAK1E,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,KAAG,OAgBxC,CAAC;AA6BF,eAAO,MAAM,YAAY,GAAI,OAAO,OAAO,KAAG,OAoC7C,CAAC;AAIF,eAAO,MAAM,eAAe,GAC1B,SAAS,mBAAmB,GAAG,SAAS,KACvC,MAAM,CAAC,MAAM,EAAE,OAAO,CAcxB,CAAC;AAcF,eAAO,MAAM,aAAa,GAAI,CAAC,EAC7B,OAAO,CAAC,EACR,cAAS,EACT,sBAA4B,KAC3B,CA8CF,CAAC;AAMF,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,KAAG,MAgCrC,CAAC;AAOF,eAAO,MAAM,aAAa,GACxB,KAAK,OAAO,KACX;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAUlD,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -8,15 +8,15 @@ exports.describeError = exports.maskUrl = exports.maskSensitive = exports.pickSa
|
|
|
8
8
|
// Ficam de fora, por serem credencial viva: `authorization`, `cookie`,
|
|
9
9
|
// `gyra-client-secret`. O `gyra-client-id` também fica de fora: sozinho é só
|
|
10
10
|
// um identificador, mas emparelhado com o secret num mesmo log facilita ataque.
|
|
11
|
-
exports.SAFE_HEADERS = [
|
|
11
|
+
exports.SAFE_HEADERS = Object.freeze([
|
|
12
12
|
'x-amzn-trace-id',
|
|
13
13
|
'x-forwarded-for',
|
|
14
14
|
'user-agent',
|
|
15
15
|
'content-type',
|
|
16
16
|
'content-length',
|
|
17
|
-
];
|
|
17
|
+
]);
|
|
18
18
|
// Credencial: o valor não tem utilidade nenhuma no log, vai inteiro para `****`.
|
|
19
|
-
exports.SENSITIVE_FIELDS = [
|
|
19
|
+
exports.SENSITIVE_FIELDS = Object.freeze([
|
|
20
20
|
'password',
|
|
21
21
|
'token',
|
|
22
22
|
'accessToken',
|
|
@@ -39,7 +39,7 @@ exports.SENSITIVE_FIELDS = [
|
|
|
39
39
|
// usa `code` como campo não sensível.
|
|
40
40
|
'code',
|
|
41
41
|
'idToken',
|
|
42
|
-
];
|
|
42
|
+
]);
|
|
43
43
|
// `state` é o nonce anti-CSRF do OAuth. Na query ele é sempre OAuth. No body só
|
|
44
44
|
// é OAuth no callback OIDC com `responseMode: 'form_post'` — o do Microsoft
|
|
45
45
|
// (`microsoft-oauth.strategy.ts:19`, `responseType: 'code id_token'`), numa rota
|
|
@@ -49,9 +49,9 @@ exports.SENSITIVE_FIELDS = [
|
|
|
49
49
|
// No body, portanto, só mascara quando a assinatura do callback OIDC está
|
|
50
50
|
// presente: `code` ou `idToken` no mesmo objeto. Um payload de endereço não tem
|
|
51
51
|
// nenhum dos dois.
|
|
52
|
-
exports.OAUTH_CALLBACK_ONLY_FIELDS = ['state'];
|
|
52
|
+
exports.OAUTH_CALLBACK_ONLY_FIELDS = Object.freeze(['state']);
|
|
53
53
|
// Presença destas chaves marca o objeto como callback OIDC.
|
|
54
|
-
exports.OIDC_CALLBACK_MARKERS = ['code', 'idToken'];
|
|
54
|
+
exports.OIDC_CALLBACK_MARKERS = Object.freeze(['code', 'idToken']);
|
|
55
55
|
// Dado pessoal: categoria distinta de credencial. Não pode ir em plain text —
|
|
56
56
|
// requisito LGPD já vigente na plataforma, registrado em
|
|
57
57
|
// `gyra-integration/specs/001-scr-raw-data-api/spec.md:179` — mas, diferente de
|
|
@@ -66,7 +66,7 @@ exports.OIDC_CALLBACK_MARKERS = ['code', 'idToken'];
|
|
|
66
66
|
// `documentType` e `documentTypes` NÃO entram: são enums (CPF/CNPJ), não
|
|
67
67
|
// valores. A comparação é por chave exata, então ficam de fora naturalmente —
|
|
68
68
|
// um match por substring em "document" os pegaria e perderia informação útil.
|
|
69
|
-
exports.PII_FIELDS = [
|
|
69
|
+
exports.PII_FIELDS = Object.freeze([
|
|
70
70
|
'email',
|
|
71
71
|
'signerEmail',
|
|
72
72
|
'username',
|
|
@@ -80,7 +80,7 @@ exports.PII_FIELDS = [
|
|
|
80
80
|
'phoneNumber',
|
|
81
81
|
'signerPhoneNumber',
|
|
82
82
|
'signerName',
|
|
83
|
-
];
|
|
83
|
+
]);
|
|
84
84
|
// Documento é PII, mas de um tipo em que dígito parcial ainda é útil para
|
|
85
85
|
// investigar sem identificar a pessoa. Estas chaves recebem mascaramento PARCIAL
|
|
86
86
|
// (`maskDocument`) em vez de `****`; as outras chaves de PII_FIELDS seguem no
|
|
@@ -89,21 +89,21 @@ exports.PII_FIELDS = [
|
|
|
89
89
|
// A lista é subconjunto de PII_FIELDS de propósito: a ordem de checagem em
|
|
90
90
|
// `maskSensitive` testa documento ANTES de PII, então o que estiver aqui ganha o
|
|
91
91
|
// tratamento parcial e o resto cai no total.
|
|
92
|
-
exports.DOCUMENT_FIELDS = [
|
|
92
|
+
exports.DOCUMENT_FIELDS = Object.freeze([
|
|
93
93
|
'cpf',
|
|
94
94
|
'cnpj',
|
|
95
95
|
'document',
|
|
96
96
|
'documents',
|
|
97
97
|
'newDocument',
|
|
98
98
|
'signerDocument',
|
|
99
|
-
];
|
|
99
|
+
]);
|
|
100
100
|
// Chaves cujo significado varia entre os 15 serviços. Aqui a decisão é pelo
|
|
101
101
|
// VALOR, não pelo nome: `to` é destinatário de e-mail no gyra-communication, mas
|
|
102
102
|
// é data ISO em `UsageQueryDto.to` (gyra-billing) e limite de faixa numérica em
|
|
103
103
|
// `CreateDto.to: number` (gyra-core e gyra-credit-policy, 6 DTOs). Mascarar por
|
|
104
104
|
// nome apagaria o campo que se quer ver ao depurar faixa de risco ou intervalo
|
|
105
105
|
// de cobrança — a mesma disciplina já aplicada ao `documentType`.
|
|
106
|
-
exports.AMBIGUOUS_PII_FIELDS = ['to'];
|
|
106
|
+
exports.AMBIGUOUS_PII_FIELDS = Object.freeze(['to']);
|
|
107
107
|
// Casa e-mail e telefone; não casa data ISO nem número pequeno. Erra para o
|
|
108
108
|
// lado de mascarar: um epoch em milissegundos tem 13 dígitos e seria mascarado —
|
|
109
109
|
// aceitável, porque nenhum `to` da plataforma carrega epoch hoje e o custo de
|
|
@@ -185,16 +185,22 @@ exports.maskPii = maskPii;
|
|
|
185
185
|
// entrega é minimização com utilidade: dá para correlacionar duas linhas do mesmo
|
|
186
186
|
// documento e conferir prefixo de CNPJ sem reconstruir o número.
|
|
187
187
|
//
|
|
188
|
-
// Só valor com FORMA de documento sai parcial
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
//
|
|
188
|
+
// Só valor com FORMA de documento sai parcial. Qualquer outra coisa que chegue numa
|
|
189
|
+
// chave de documento é dado desconhecido — pode ser um nome, um e-mail, um id — e
|
|
190
|
+
// expor pedaço de dado desconhecido num campo de PII é o default errado. Esses vão
|
|
191
|
+
// para mascaramento total.
|
|
192
|
+
//
|
|
193
|
+
// FORMA, não comprimento. A guarda já foi só `[11, 14]`, e comprimento sozinho não
|
|
194
|
+
// distingue documento de nome: `signerDocument: 'Ana Carolina'` tem 11 caracteres
|
|
195
|
+
// depois de tirar o espaço e saía `Ana******na` — exatamente o vazamento que este
|
|
196
|
+
// bloco existe para impedir. CPF são 11 DÍGITOS; o CNPJ alfanumérico da GYR-1444 são
|
|
197
|
+
// 12 posições alfanuméricas mais 2 dígitos verificadores, que são sempre numéricos.
|
|
192
198
|
//
|
|
193
199
|
// Isto é mais restritivo que o `mask-document.ts` do gyra-integration, que aplica o
|
|
194
200
|
// parcial a qualquer valor com mais de 5 caracteres. A divergência é deliberada e só
|
|
195
201
|
// para o lado seguro: para CPF e CNPJ de verdade — os casos que importam — as duas
|
|
196
202
|
// implementações produzem exatamente a mesma saída.
|
|
197
|
-
const
|
|
203
|
+
const DOCUMENT_SHAPES = [/^\d{11}$/, /^[0-9A-Za-z]{12}\d{2}$/];
|
|
198
204
|
const maskDocument = (value) => {
|
|
199
205
|
if (Array.isArray(value)) {
|
|
200
206
|
return value.map(exports.maskDocument);
|
|
@@ -218,7 +224,7 @@ const maskDocument = (value) => {
|
|
|
218
224
|
if (!chars) {
|
|
219
225
|
return exports.REDACTED;
|
|
220
226
|
}
|
|
221
|
-
if (!
|
|
227
|
+
if (!DOCUMENT_SHAPES.some((shape) => shape.test(chars))) {
|
|
222
228
|
return exports.REDACTED;
|
|
223
229
|
}
|
|
224
230
|
const head = chars.slice(0, 3);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,uDAAuD;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -8,10 +8,30 @@
|
|
|
8
8
|
mesmo bloco existia duplicado e identico nos 15 servicos
|
|
9
9
|
(md5 cc04916718f5db4c776d256fc05068b3, 313 linhas, conferido nos 15 em main).
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
Nenhum comentario da fonte foi alterado — eles registram seis rodadas de revisao
|
|
12
|
+
e tres revisoes humanas, e explicam decisoes que ja foram questionadas e
|
|
13
|
+
defendidas. Nao reformate e nao os remova.
|
|
14
|
+
|
|
15
|
+
Divergencias em relacao a fonte, todas deliberadas e datadas:
|
|
16
|
+
|
|
17
|
+
- VISIBILIDADE (0.1.0): as declaracoes ganharam `export`. Sem mudanca de
|
|
18
|
+
assinatura nem de comportamento.
|
|
19
|
+
|
|
20
|
+
- DOCUMENTO PARCIAL (0.2.0): campos de DOCUMENT_FIELDS passam por
|
|
21
|
+
`maskDocument` e saem com 3 primeiros + 2 ultimos digitos, em vez de `****`.
|
|
22
|
+
Aqui a identidade byte-a-byte com a fonte acabou, de proposito. O formato e o
|
|
23
|
+
mesmo de gyra-integration/src/common/utils/mask-document.ts, que ja estava em
|
|
24
|
+
producao. A LGPD e principiologica e NAO prescreve contagem de digitos: mudar
|
|
25
|
+
essa contagem e decisao de compliance, com dono, e muda o log de 15 servicos.
|
|
26
|
+
|
|
27
|
+
- LISTAS CONGELADAS (0.3.0): as listas exportadas passam por `Object.freeze`.
|
|
28
|
+
Elas iam por referencia, entao um consumidor podia alterar SENSITIVE_FIELDS e
|
|
29
|
+
desligar o mascaramento do processo inteiro em silencio — o oposto do que este
|
|
30
|
+
modulo existe para garantir. Congelar faz a tentativa falhar alto, e o tipo
|
|
31
|
+
vira `readonly string[]`, o que tambem acusa em tempo de compilacao.
|
|
32
|
+
|
|
33
|
+
O md5 acima segue valendo para conferir que o bloco que cada servico REMOVE na
|
|
34
|
+
migracao nao sofreu deriva. Isso e independente do estado deste arquivo.
|
|
15
35
|
|
|
16
36
|
API que os servicos consomem: maskSensitive, maskUrl, pickSafeHeaders,
|
|
17
37
|
describeError — os quatro usados por todas as 9 variantes da classe
|
|
@@ -30,16 +50,16 @@ import type { IncomingHttpHeaders } from 'http';
|
|
|
30
50
|
// Ficam de fora, por serem credencial viva: `authorization`, `cookie`,
|
|
31
51
|
// `gyra-client-secret`. O `gyra-client-id` também fica de fora: sozinho é só
|
|
32
52
|
// um identificador, mas emparelhado com o secret num mesmo log facilita ataque.
|
|
33
|
-
export const SAFE_HEADERS = [
|
|
53
|
+
export const SAFE_HEADERS = Object.freeze([
|
|
34
54
|
'x-amzn-trace-id',
|
|
35
55
|
'x-forwarded-for',
|
|
36
56
|
'user-agent',
|
|
37
57
|
'content-type',
|
|
38
58
|
'content-length',
|
|
39
|
-
];
|
|
59
|
+
]);
|
|
40
60
|
|
|
41
61
|
// Credencial: o valor não tem utilidade nenhuma no log, vai inteiro para `****`.
|
|
42
|
-
export const SENSITIVE_FIELDS = [
|
|
62
|
+
export const SENSITIVE_FIELDS = Object.freeze([
|
|
43
63
|
'password',
|
|
44
64
|
'token',
|
|
45
65
|
'accessToken',
|
|
@@ -62,7 +82,7 @@ export const SENSITIVE_FIELDS = [
|
|
|
62
82
|
// usa `code` como campo não sensível.
|
|
63
83
|
'code',
|
|
64
84
|
'idToken',
|
|
65
|
-
];
|
|
85
|
+
]);
|
|
66
86
|
|
|
67
87
|
// `state` é o nonce anti-CSRF do OAuth. Na query ele é sempre OAuth. No body só
|
|
68
88
|
// é OAuth no callback OIDC com `responseMode: 'form_post'` — o do Microsoft
|
|
@@ -73,10 +93,10 @@ export const SENSITIVE_FIELDS = [
|
|
|
73
93
|
// No body, portanto, só mascara quando a assinatura do callback OIDC está
|
|
74
94
|
// presente: `code` ou `idToken` no mesmo objeto. Um payload de endereço não tem
|
|
75
95
|
// nenhum dos dois.
|
|
76
|
-
export const OAUTH_CALLBACK_ONLY_FIELDS = ['state'];
|
|
96
|
+
export const OAUTH_CALLBACK_ONLY_FIELDS = Object.freeze(['state']);
|
|
77
97
|
|
|
78
98
|
// Presença destas chaves marca o objeto como callback OIDC.
|
|
79
|
-
export const OIDC_CALLBACK_MARKERS = ['code', 'idToken'];
|
|
99
|
+
export const OIDC_CALLBACK_MARKERS = Object.freeze(['code', 'idToken']);
|
|
80
100
|
|
|
81
101
|
// Dado pessoal: categoria distinta de credencial. Não pode ir em plain text —
|
|
82
102
|
// requisito LGPD já vigente na plataforma, registrado em
|
|
@@ -92,7 +112,7 @@ export const OIDC_CALLBACK_MARKERS = ['code', 'idToken'];
|
|
|
92
112
|
// `documentType` e `documentTypes` NÃO entram: são enums (CPF/CNPJ), não
|
|
93
113
|
// valores. A comparação é por chave exata, então ficam de fora naturalmente —
|
|
94
114
|
// um match por substring em "document" os pegaria e perderia informação útil.
|
|
95
|
-
export const PII_FIELDS = [
|
|
115
|
+
export const PII_FIELDS = Object.freeze([
|
|
96
116
|
'email',
|
|
97
117
|
'signerEmail',
|
|
98
118
|
'username',
|
|
@@ -106,7 +126,7 @@ export const PII_FIELDS = [
|
|
|
106
126
|
'phoneNumber',
|
|
107
127
|
'signerPhoneNumber',
|
|
108
128
|
'signerName',
|
|
109
|
-
];
|
|
129
|
+
]);
|
|
110
130
|
|
|
111
131
|
// Documento é PII, mas de um tipo em que dígito parcial ainda é útil para
|
|
112
132
|
// investigar sem identificar a pessoa. Estas chaves recebem mascaramento PARCIAL
|
|
@@ -116,14 +136,14 @@ export const PII_FIELDS = [
|
|
|
116
136
|
// A lista é subconjunto de PII_FIELDS de propósito: a ordem de checagem em
|
|
117
137
|
// `maskSensitive` testa documento ANTES de PII, então o que estiver aqui ganha o
|
|
118
138
|
// tratamento parcial e o resto cai no total.
|
|
119
|
-
export const DOCUMENT_FIELDS = [
|
|
139
|
+
export const DOCUMENT_FIELDS = Object.freeze([
|
|
120
140
|
'cpf',
|
|
121
141
|
'cnpj',
|
|
122
142
|
'document',
|
|
123
143
|
'documents',
|
|
124
144
|
'newDocument',
|
|
125
145
|
'signerDocument',
|
|
126
|
-
];
|
|
146
|
+
]);
|
|
127
147
|
|
|
128
148
|
// Chaves cujo significado varia entre os 15 serviços. Aqui a decisão é pelo
|
|
129
149
|
// VALOR, não pelo nome: `to` é destinatário de e-mail no gyra-communication, mas
|
|
@@ -131,7 +151,7 @@ export const DOCUMENT_FIELDS = [
|
|
|
131
151
|
// `CreateDto.to: number` (gyra-core e gyra-credit-policy, 6 DTOs). Mascarar por
|
|
132
152
|
// nome apagaria o campo que se quer ver ao depurar faixa de risco ou intervalo
|
|
133
153
|
// de cobrança — a mesma disciplina já aplicada ao `documentType`.
|
|
134
|
-
export const AMBIGUOUS_PII_FIELDS = ['to'];
|
|
154
|
+
export const AMBIGUOUS_PII_FIELDS = Object.freeze(['to']);
|
|
135
155
|
|
|
136
156
|
// Casa e-mail e telefone; não casa data ISO nem número pequeno. Erra para o
|
|
137
157
|
// lado de mascarar: um epoch em milissegundos tem 13 dígitos e seria mascarado —
|
|
@@ -230,16 +250,22 @@ export const maskPii = (value: unknown): unknown => {
|
|
|
230
250
|
// entrega é minimização com utilidade: dá para correlacionar duas linhas do mesmo
|
|
231
251
|
// documento e conferir prefixo de CNPJ sem reconstruir o número.
|
|
232
252
|
//
|
|
233
|
-
// Só valor com FORMA de documento sai parcial
|
|
234
|
-
//
|
|
235
|
-
//
|
|
236
|
-
//
|
|
253
|
+
// Só valor com FORMA de documento sai parcial. Qualquer outra coisa que chegue numa
|
|
254
|
+
// chave de documento é dado desconhecido — pode ser um nome, um e-mail, um id — e
|
|
255
|
+
// expor pedaço de dado desconhecido num campo de PII é o default errado. Esses vão
|
|
256
|
+
// para mascaramento total.
|
|
257
|
+
//
|
|
258
|
+
// FORMA, não comprimento. A guarda já foi só `[11, 14]`, e comprimento sozinho não
|
|
259
|
+
// distingue documento de nome: `signerDocument: 'Ana Carolina'` tem 11 caracteres
|
|
260
|
+
// depois de tirar o espaço e saía `Ana******na` — exatamente o vazamento que este
|
|
261
|
+
// bloco existe para impedir. CPF são 11 DÍGITOS; o CNPJ alfanumérico da GYR-1444 são
|
|
262
|
+
// 12 posições alfanuméricas mais 2 dígitos verificadores, que são sempre numéricos.
|
|
237
263
|
//
|
|
238
264
|
// Isto é mais restritivo que o `mask-document.ts` do gyra-integration, que aplica o
|
|
239
265
|
// parcial a qualquer valor com mais de 5 caracteres. A divergência é deliberada e só
|
|
240
266
|
// para o lado seguro: para CPF e CNPJ de verdade — os casos que importam — as duas
|
|
241
267
|
// implementações produzem exatamente a mesma saída.
|
|
242
|
-
const
|
|
268
|
+
const DOCUMENT_SHAPES = [/^\d{11}$/, /^[0-9A-Za-z]{12}\d{2}$/];
|
|
243
269
|
|
|
244
270
|
export const maskDocument = (value: unknown): unknown => {
|
|
245
271
|
if (Array.isArray(value)) {
|
|
@@ -269,7 +295,7 @@ export const maskDocument = (value: unknown): unknown => {
|
|
|
269
295
|
return REDACTED;
|
|
270
296
|
}
|
|
271
297
|
|
|
272
|
-
if (!
|
|
298
|
+
if (!DOCUMENT_SHAPES.some((shape) => shape.test(chars))) {
|
|
273
299
|
return REDACTED;
|
|
274
300
|
}
|
|
275
301
|
|