TGViewer
Khraks dev Khraks dev @khraks_dev · 108 subscribers
Post #21 283
Хочется быть уверенным, что чувствительная информация случайно не утечет в сторонние системы при во время логирования и сериализации.

Изначально в Effect модуль Secret служил для этой цели, но ограничен только работой со строками. Тогда я предложил обобщить идею до любого типа данных и сделал PR с модулем Redacted<T>. Имплементация там специфична для экосистемы.


Я же хочу поделиться "домашним" вариантом этой фичи, которая работает на том же принципе.
Идея — оборачивать чувствительную информацию в объект Redacted, который под капотом сохраняет ee в WeakMap за ссылкой на свой же инстанс.


const globalRedactedRegistry = new WeakMap<Redacted<any>, any>();

export class Redacted<T = string> {
public readonly label: string = "redacted";

constructor(value: T, label?: string) {
if (label) { this.label = label; }
globalRedactedRegistry.set(this, value);
}

static value<T>(redacted: Redacted<T>): T {
return globalRedactedRegistry.get(redacted);
}
toString() { return `<${this.label}>`; }
toJSON() { return `<${this.label}>`; }
inspect() { return `<${this.label}>`; }
[Symbol.for("nodejs.util.inspect.custom")]() {
return `<${this.label}>`;
}
[Symbol.for("Deno.customInspect")]() {
return `<${this.label}>`;
}
[Bun.inspect.custom]() { return `<${this.label}>`; }
}



Когда чувствительные данные пересекают порог - оборачиваем их в Redacted и спим спокойно - разворачиваем только когда нужно передать их дальше, за пределы приложения.


const password = new Redacted(process.env.PASSWORD, 'PASSWORD');
const login = new Redacted(process.env.LOGIN, 'LOGIN');
// ...
console.log({ password, login })
/*
{ "password": "<PASSWORD>",
"login": "<LOGIN>" }
*/
// ...
const client = new SomeClient({
password: Redacted.value(password),
login: Redacted.value(login),
})



Обратить внимание, что .value - статический метод, а не геттер - это сделано нарочито-нарочно, чтобы можно было искать по коду все места, где раскрывается информация.


Может возникнуть вопрос — зачем? Я могу настроить фильтры в сторонних системах и добиться того, что информация будет отфильтрована. Но в этом подходе нет гарантий, что, допустим, при переименовании чувствительного поля или изменении формата данных система сделает все правильно. В то время как при использовании Redacted эта гарантия лежит в коде, рядом с данными.


Интересно пользуетесь ли вы чем-то похожим? Если еще нет - то можно затащить в проект)
Может кто-то знает — есть ли в других языках подобная утилита? (Хочу порекомендовать коллегам питонистам)
  • 👍 2
More from @khraks_dev
  1. Sep 10, 2026Добавил еще PR с Context.Mixin, чтобы подмешивать к классу поведение Context.Service Тепер…
  2. Sep 10, 2026Post #56
  3. Sep 7, 2026Post #55
  4. Sep 3, 2026Post #54
  5. Sep 3, 2026Итак HKT на основе TypeLambda interface TypeLambda { readonly Arg1: unknown; readonly Arg2…
  6. Aug 30, 2026# HKT Дефункционализация В TypeScript нет настоящих Higher-Kinded Types (HKT). А они приме…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →