Help us shape the future of Go! Take the 2026 Go Developer Survey

processors

package
v1.26.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 10, 2026 License: MIT Imports: 21 Imported by: 0

README

Data processors

Processors transform data in flight, on export and on import.

Purpose

Pre-processors run on export:

  • masking sensitive data
  • anonymising personal information
  • normalising formats
  • validating data

Post-processors run on import:

  • enriching data
  • reshaping it for the target system
  • filling in defaults
  • business logic on the receiving side

Architecture

┌─────────────────────────────────────────────────────┐
│  Export flow                                        │
│  ─────────────────────                              │
│  DB → [pre-processors] → TDTP packet → broker       │
└─────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────┐
│  Import flow                                        │
│  ─────────────────────                              │
│  Broker → TDTP packet → [post-processors] → DB      │
└─────────────────────────────────────────────────────┘

The built-in processors

1. FieldMasker — masking

Hides sensitive information, to protect PII.

Masking modes:

  • partial — masks the middle (email: j***@example.com)
  • middle — masks the central part (phone: +1 (555) XXX-X567)
  • stars — replaces everything with asterisks (**** *****)
  • first2_last2 — shows only the first two and last two characters

Examples:

processors:
  pre_export:
    - type: field_masker
      params:
        fields:
          email: partial           # john@example.com → j***@example.com
          phone: middle            # +1 (555) 123-4567 → +1 (555) XXX-X567
          passport: first2_last2   # 1234 567890 → 12** ****90
          password: stars          # MyPass123 → *********

Use cases:

  • exporting data for a test environment
  • GDPR compliance, and the Russian 152-FZ equivalent
  • sharing data safely with a contractor
2. FieldNormalizer — normalisation

Brings data to one consistent format.

Normalisation rules:

  • phone — international format, digits only
  • email — lower-cased, spaces stripped
  • whitespace — collapses redundant spaces
  • uppercase
  • lowercase
  • date — YYYY-MM-DD

Examples:

processors:
  pre_export:
    - type: field_normalizer
      params:
        fields:
          phone: phone             # +1 (555) 123-4567 → 15551234567
          email: email             # John@EXAMPLE.com → john@example.com
          name: whitespace         # "John   Doe" → "John Doe"
          country_code: uppercase  # "ru" → "RU"
          created_at: date         # 01.12.2024 → 2024-12-01

Use cases:

  • cleaning data before an integration
  • conforming to the target system's conventions
  • fixing user-entry mistakes
3. FieldValidator — validation

Checks data quality before an export or an import.

Validation rules:

  • regex:pattern — match a regular expression
  • range:min-max — a numeric range, for example range:0-150
  • enum:val1,val2,... — one of a list of permitted values
  • required — the field must not be empty
  • length:min-max — string length, for example length:3-50
  • email — a valid email address
  • phone — a valid telephone number
  • url — a valid URL
  • date — a valid date, YYYY-MM-DD

Examples:

processors:
  pre_export:
    - type: field_validator
      params:
        stop_on_first_error: false  # false = collect every error; true = stop at the first
        rules:
          email: email                         # john@example.com ✓
          age: range:18-65                     # 25 ✓, 17 ✗
          status: enum:active,inactive,pending # active ✓, deleted ✗
          username: length:3-20                # john_doe ✓, ab ✗
          phone: phone                         # +1 (555) 123-4567 ✓
          website: url                         # https://example.com ✓
          birth_date: date                     # 1990-05-15 ✓

  post_import:
    - type: field_validator
      params:
        stop_on_first_error: true  # stop at the first error
        rules:
          name:
            - required              # must be present
            - length:2-100          # between 2 and 100 characters
          price:
            - required
            - range:0-1000000       # a price from 0 to a million

Custom regexes and error messages:

processors:
  pre_export:
    - type: field_validator
      params:
        rules:
          sku: regex:^[A-Z]{3}-\d{5}$          # SKU format: ABC-12345
          postal_code: regex:^\d{5}(-\d{4})?$  # US ZIP code

Use cases:

  • checking data quality before an export
  • stopping invalid data from being imported
  • enforcing business rules
  • catching data problems early

Usage

In the configuration (config.yaml)
database:
  # ... database configuration ...

# Processor configuration
processors:
  # Processors for export
  pre_export:
    - type: field_masker
      params:
        fields:
          email: partial
          phone: middle
          passport_series: stars

    - type: field_normalizer
      params:
        fields:
          phone: phone
          email: email

  # Processors for import
  post_import:
    - type: field_normalizer
      params:
        fields:
          created_at: date
          status: lowercase
In code
package main

import (
    "context"
    "github.com/queuebridge/tdtp/pkg/processors"
    "github.com/queuebridge/tdtp/pkg/core/packet"
)

func main() {
    ctx := context.Background()

    // Build the processors through the factory
    factory := processors.NewFactory()

    config := processors.Config{
        Type: "field_masker",
        Params: map[string]interface{}{
            "fields": map[string]interface{}{
                "email": "partial",
                "phone": "middle",
            },
        },
    }

    masker, err := factory.Create(config)
    if err != nil {
        panic(err)
    }

    // Apply one
    data := [][]string{
        {"john.doe@example.com", "+1 (555) 123-4567"},
        {"jane.smith@test.com", "+1 (555) 987-6543"},
    }

    schema := packet.Schema{
        Fields: []packet.Field{
            {Name: "email", Type: "TEXT"},
            {Name: "phone", Type: "TEXT"},
        },
    }

    processed, err := masker.Process(ctx, data, schema)
    if err != nil {
        panic(err)
    }

    // processed:
    // [
    //   ["j***@example.com", "+1 (555) XXX-X567"],
    //   ["j***@test.com", "+1 (555) XXX-X543"]
    // ]
}
A chain of processors
// Create the chain
chain := processors.NewChain()

// Add processors
masker := processors.NewFieldMasker(map[string]processors.MaskPattern{
    "email": processors.MaskPartial,
})
normalizer := processors.NewFieldNormalizer(map[string]processors.NormalizeRule{
    "phone": processors.NormalizePhone,
})

chain.Add(masker)
chain.Add(normalizer)

// Apply the whole chain
processed, err := chain.Process(ctx, data, schema)
Building a chain from configuration
configs := []processors.Config{
    {
        Type: "field_masker",
        Params: map[string]interface{}{
            "fields": map[string]interface{}{
                "email": "partial",
            },
        },
    },
    {
        Type: "field_normalizer",
        Params: map[string]interface{}{
            "fields": map[string]interface{}{
                "phone": "phone",
            },
        },
    },
}

chain, err := processors.CreateChainFromConfigs(configs)
if err != nil {
    panic(err)
}

processed, err := chain.Process(ctx, data, schema)

Writing your own processor

package myprocessors

import (
    "context"
    "github.com/queuebridge/tdtp/pkg/core/packet"
    "github.com/queuebridge/tdtp/pkg/processors"
)

// MyCustomProcessor is an example
type MyCustomProcessor struct {
    name string
    // ... parameters
}

func (p *MyCustomProcessor) Name() string {
    return p.name
}

func (p *MyCustomProcessor) Process(ctx context.Context, data [][]string, schema packet.Schema) ([][]string, error) {
    // Your processing logic
    result := make([][]string, len(data))
    for i, row := range data {
        newRow := make([]string, len(row))
        copy(newRow, row)

        // Transform the value
        // ...

        result[i] = newRow
    }
    return result, nil
}

// Register it with the factory
func init() {
    processors.DefaultFactory.Register("my_custom", func(params map[string]interface{}) (processors.Processor, error) {
        return &MyCustomProcessor{
            name: "my_custom",
            // ... parse the parameters
        }, nil
    })
}

Worked use cases

1. A safe export for testing
processors:
  pre_export:
    - type: field_masker
      params:
        fields:
          email: partial
          phone: middle
          passport: stars
          card_number: stars
          ssn: stars
2. Integrating with an external system
processors:
  pre_export:
    - type: field_normalizer
      params:
        fields:
          phone: phone              # international format, digits only
          email: email              # Lowercase
          country_code: uppercase   # ISO 3166-1 alpha-2
          created_at: date          # YYYY-MM-DD

  post_import:
    - type: field_normalizer
      params:
        fields:
          status: lowercase         # to match the target's enum
          priority: uppercase       # HIGH, MEDIUM, LOW
3. Cleaning data before an import
processors:
  post_import:
    - type: field_normalizer
      params:
        fields:
          name: whitespace          # collapse redundant spaces
          email: email              # Lowercase + trim
          phone: phone              # one consistent format

Performance

  • processors work in memory — fast, and cheap
  • regular expressions are compiled once, when the processor is created
  • data is handled row by row — the whole table never needs to be in memory
  • chains run in order, so the result is predictable

Security

  • masking happens before anything crosses the network
  • the original data in the source database is never modified
  • processors have no network access — only the data in memory
  • processor configuration lives in the config file, under version control

📝 Roadmap

Planned processors:

  • field_validator — validation (regex, ranges, enums)
  • field_enricher — enrichment from an external source
  • field_transformer — arithmetic and string transformations
  • field_anonymizer — pseudonyms that preserve referential integrity
  • field_encryptor — encrypting and decrypting individual fields
  • conditional_processor — behaviour conditional on other fields' values

Contributing

Processors are easy to extend. Write your own and share them.

What a processor must do:

  1. implement the Processor interface
  2. have no side effects — a pure function
  3. come with unit tests
  4. be documented, with examples

Documentation

Overview

Package processors — FileEncryptor выполняет шифрование готового TDTP-файла. Встаёт в пайплайне после CompressionProcessor (уровень файла, не строк).

Использование в exporter.go:

enc := processors.NewFileEncryptor(mercuryClient, serverSecret, packageUUID)
if err := enc.EncryptFile(ctx, xmlData); err != nil { ... }

Index

Constants

View Source
const (
	AlgoZstd  = "zstd"
	AlgoKanzi = "kanzi"
)

Алгоритмы сжатия, поддерживаемые TDTP.

View Source
const MaxDecompressedBytes = 256 << 20 // 256 MB

MaxDecompressedBytes — предел размера распакованных данных одного пакета.

Без него распаковка — удалённый отказ в обслуживании: сжатие не ограничено сверху по коэффициенту, поэтому крошечный пакет разворачивается во сколько угодно. Замерено на обычных повторяющихся данных: 25 КБ в пакете → 200 МБ после распаковки (8184×), то есть мегабайтный файл даёт около 8 ГБ. На специально подобранном содержимом коэффициент кратно выше.

Ни один другой предел сюда не достаёт: maxBufferedParse ограничивает вход (а он крошечный), MaxSchemaBytesRead — секцию Schema (а бомба в Data).

Тот, кто читает пакет, не выбирает его происхождение — файл приходит из брокера, из объектного хранилища, от контрагента. Поэтому предел нужен на чтении, даже если все свои пакеты заведомо доверенные.

Variables

View Source
var DefaultFactory = NewFactory()

DefaultFactory возвращает фабрику со всеми встроенными процессорами

Functions

func Compress

func Compress(input []byte, level int) ([]byte, error)

Compress сжимает блок данных, используя zstd, и кодирует в base64. Эта функция-хелпер инкапсулирует создание и закрытие процессора.

func CompressKanzi

func CompressKanzi(input []byte, level int) ([]byte, error)

CompressKanzi сжимает данные с помощью kanzi и кодирует результат в base64.

func ComputeChecksum

func ComputeChecksum(data []byte) string

ComputeChecksum вычисляет xxh3 хеш данных и возвращает hex-encoded строку.

func Decompress

func Decompress(input []byte) ([]byte, error)

Decompress декодирует блок данных из base64 и распаковывает с помощью zstd. Эта функция-хелпер инкапсулирует создание и закрытие процессора.

func DecompressDataForTdtp

func DecompressDataForTdtp(compressed string) ([]string, error)

DecompressDataForTdtp распаковывает данные из TDTP пакета обратно в массив строк.

func DecompressDataForTdtpAlgo

func DecompressDataForTdtpAlgo(compressed, algo string) ([]string, error)

DecompressDataForTdtpAlgo was a byte-for-byte duplicate of DecompressDataForTdtpWithAlgo. Kept as a forwarding alias for callers outside this repo.

func DecompressDataForTdtpWithAlgo

func DecompressDataForTdtpWithAlgo(compressed, algo string) ([]string, error)

DecompressDataForTdtpWithAlgo декомпрессирует данные с учётом алгоритма.

func DecompressKanzi

func DecompressKanzi(input []byte) ([]byte, error)

DecompressKanzi декодирует данные из base64 и распаковывает с помощью kanzi.

func DecompressPacket

func DecompressPacket(ctx context.Context, pkt *packet.DataPacket) error

DecompressPacket validates the checksum (if present), decompresses pkt.Data via the algorithm pkt.Data.Compression names, expands a columnar layout, and verifies RecordsInPart — the full sequence every reader of a compressed TDTP packet needs. No-op if pkt isn't compressed.

This is the one place that sequence should exist. Eight call sites had their own copy of it before this function did, two of them missing the columnar expansion (silent corruption: one "row" per schema column) and one hardcoding zstd regardless of what the packet actually declared.

func DryDecompress

func DryDecompress(compressed, algo string) error

DryDecompress проверяет что сжатый блоб валиден (не битый), не разбирая содержимое.

ВЫЗЫВАЮЩИХ НЕТ. Держится как публичный API для внешних потребителей.

Прежний комментарий гласил «используется в --test: содержимое <Data> непрозрачно, RecordsInPart — авторитетный счётчик». Обе половины устарели: --test с 1f31620 считает строки сам, а счётчик из заголовка авторитетным не является — он не покрыт ни одним хешем, и его сверяет VerifyRowCount. Строка осталась бы инструкцией для следующего читателя завести баг заново.

func ShouldCompress

func ShouldCompress(dataSize, minSize int) bool

ShouldCompress определяет, стоит ли сжимать данные. Возвращает true, если данные достаточно большие для выгоды от сжатия.

func ValidateChecksum

func ValidateChecksum(data []byte, expectedHash string) error

ValidateChecksum проверяет соответствие данных ожидаемому хешу. Возвращает ошибку если хеш не совпадает.

func VerifyKanziStreamStrict

func VerifyKanziStreamStrict(b64 string) error

VerifyKanziStreamStrict is the import-side forgery gate (Defense 1). It admits only what tdtp itself produces: version 6, one of the L6/L7 presets, a 1 MiB block size, a declared output within the decompression limit, a correct header checksum, and block prefixes that stay within bounds.

func WriteEncrypted

func WriteEncrypted(path string, data []byte) error

WriteEncrypted записывает зашифрованный блоб в файл. Расширение .tdtp.enc помогает downstream-компонентам отличить зашифрованные файлы.

Types

type BlockProcessor

type BlockProcessor interface {
	ProcessBlock(ctx context.Context, input []byte) ([]byte, error)
}

BlockProcessor определяет интерфейс для блочной обработки данных.

type Chain

type Chain struct {
	// contains filtered or unexported fields
}

Chain представляет цепочку процессоров

func CreateChainFromConfigs

func CreateChainFromConfigs(configs []Config) (*Chain, error)

CreateChainFromConfigs создает цепочку процессоров используя дефолтную фабрику

func NewChain

func NewChain(processors ...Processor) *Chain

NewChain создает новую цепочку процессоров

func (*Chain) Add

func (c *Chain) Add(processor Processor)

Add добавляет процессор в цепочку

func (*Chain) IsEmpty

func (c *Chain) IsEmpty() bool

IsEmpty проверяет, пуста ли цепочка

func (*Chain) Len

func (c *Chain) Len() int

Len возвращает количество процессоров в цепочке

func (*Chain) Process

func (c *Chain) Process(ctx context.Context, data [][]string, schema packet.Schema) ([][]string, error)

Process выполняет все процессоры в цепочке последовательно

type ChecksumProcessor

type ChecksumProcessor struct {
	// contains filtered or unexported fields
}

ChecksumProcessor вычисляет и проверяет контрольные суммы данных. Использует xxh3 (64-bit) для быстрой проверки целостности.

Режимы работы:

  1. Генерация (expectedHash == ""): вычисляет хеш и передает через callback
  2. Валидация (expectedHash != ""): проверяет соответствие вычисленного хеша ожидаемому

func NewChecksumProcessor

func NewChecksumProcessor(expectedHash string, callback func(string)) *ChecksumProcessor

NewChecksumProcessor создает новый процессор контрольных сумм.

Параметры:

expectedHash - ожидаемый хеш для валидации (пустая строка для режима генерации)
callback - функция для получения вычисленного хеша (опционально, для генерации)

func (*ChecksumProcessor) ProcessBlock

func (p *ChecksumProcessor) ProcessBlock(ctx context.Context, input []byte) ([]byte, error)

ProcessBlock вычисляет xxh3 хеш блока данных. В режиме валидации проверяет соответствие ожидаемому значению. В режиме генерации вызывает callback с вычисленным хешом.

type CompressionProcessor

type CompressionProcessor struct {
	// contains filtered or unexported fields
}

CompressionProcessor сжимает данные с помощью zstd.

func NewCompressionProcessor

func NewCompressionProcessor(level int) (*CompressionProcessor, error)

NewCompressionProcessor создает новый, готовый к использованию процессор сжатия. level: 1 (самый быстрый) - 22 (лучшее сжатие). Уровень 3 является хорошим балансом по умолчанию.

func (*CompressionProcessor) Close

func (p *CompressionProcessor) Close()

Close освобождает ресурсы, связанные с энкодером.

func (*CompressionProcessor) ProcessBlock

func (p *CompressionProcessor) ProcessBlock(_ context.Context, input []byte) ([]byte, error)

ProcessBlock сжимает блок данных и кодирует результат в base64.

type CompressionStats

type CompressionStats struct {
	OriginalSize   int           `json:"original_size"`
	CompressedSize int           `json:"compressed_size"`
	Ratio          float64       `json:"ratio"`
	Time           time.Duration `json:"time"`
}

CompressionStats содержит статистику сжатия.

func CompressChunksForTdtpAlgo

func CompressChunksForTdtpAlgo(chunks [][]byte, algo string, level int) (compressedRow string, stats CompressionStats, err error)

CompressChunksForTdtpAlgo сжимает набор кусков как один поток, разделяя их '\n' — то же, что делает CompressDataForTdtpAlgo, но без склейки.

Разница не косметическая. Строковый вариант зовёт strings.Join, а это полная копия всех данных: на экспорте в 15 МБ — лишние 15 МБ, выделенные и заполненные только затем, чтобы тут же уйти в кодек и быть выброшенными. Куски пишутся в энкодер по одному, так что копии нет вовсе.

Куски не копируются и не изменяются; после возврата их можно переиспользовать.

func CompressDataForTdtp

func CompressDataForTdtp(rows []string, level int) (compressedRow string, stats CompressionStats, err error)

CompressDataForTdtp сжимает строки данных для TDTP пакета. Строки объединяются через \n; \n внутри значений полей экранируется в writeEscaped.

func CompressDataForTdtpAlgo

func CompressDataForTdtpAlgo(rows []string, algo string, level int) (compressedRow string, stats CompressionStats, err error)

CompressDataForTdtpAlgo сжимает строки TDTP-пакета выбранным алгоритмом.

func GetCompressionStats

func GetCompressionStats(original, compressed []byte, compressTime time.Duration) CompressionStats

GetCompressionStats вычисляет статистику сжатия для данных.

type Config

type Config struct {
	Type   string         `yaml:"type"`   // Тип процессора (field_masker, normalizer, etc)
	Params map[string]any `yaml:"params"` // Параметры процессора
}

Config содержит конфигурацию процессора

type CreatorFunc

type CreatorFunc func(params map[string]any) (Processor, error)

CreatorFunc функция для создания процессора из конфигурации

type DecompressionProcessor

type DecompressionProcessor struct {
	// contains filtered or unexported fields
}

DecompressionProcessor распаковывает данные из base64+zstd.

func NewDecompressionProcessor

func NewDecompressionProcessor() (*DecompressionProcessor, error)

NewDecompressionProcessor создает новый, готовый к использованию процессор распаковки.

func (*DecompressionProcessor) Close

func (p *DecompressionProcessor) Close()

Close освобождает ресурсы, связанные с декодером.

func (*DecompressionProcessor) ProcessBlock

func (p *DecompressionProcessor) ProcessBlock(_ context.Context, input []byte) ([]byte, error)

ProcessBlock декодирует данные из base64 и распаковывает их.

type EncryptionResult

type EncryptionResult struct {
	PackageUUID string
	KeyB64      string // только для dev-режима; в prod всегда ""
	Encrypted   []byte // зашифрованный блоб
}

EncryptionResult — результат шифрования файла.

type Factory

type Factory struct {
	// contains filtered or unexported fields
}

Factory создает процессоры по их типу и конфигурации

func NewFactory

func NewFactory() *Factory

NewFactory создает новую фабрику процессоров

func (*Factory) Create

func (f *Factory) Create(config Config) (Processor, error)

Create создает процессор по конфигурации

func (*Factory) CreateChain

func (f *Factory) CreateChain(configs []Config) (*Chain, error)

CreateChain создает цепочку процессоров из массива конфигураций

func (*Factory) Register

func (f *Factory) Register(processorType string, creator CreatorFunc)

Register регистрирует новый тип процессора

type FieldMasker

type FieldMasker struct {
	// contains filtered or unexported fields
}

FieldMasker маскирует чувствительные данные в указанных полях Используется для защиты PII (Personally Identifiable Information) при экспорте данных

func NewFieldMasker

func NewFieldMasker(fieldsToMask map[string]MaskPattern) *FieldMasker

NewFieldMasker создает новый маскировщик полей

func NewFieldMaskerFromConfig

func NewFieldMaskerFromConfig(params map[string]any) (*FieldMasker, error)

NewFieldMaskerFromConfig создает FieldMasker из конфигурации

func (*FieldMasker) Name

func (m *FieldMasker) Name() string

Name возвращает имя процессора

func (*FieldMasker) Process

func (m *FieldMasker) Process(ctx context.Context, data [][]string, schema packet.Schema) ([][]string, error)

Process реализует интерфейс PreProcessor

type FieldNormalizer

type FieldNormalizer struct {
	// contains filtered or unexported fields
}

FieldNormalizer нормализует данные в указанных полях Используется для приведения данных к единому формату перед импортом

func NewFieldNormalizer

func NewFieldNormalizer(fieldsToNormalize map[string]NormalizeRule) *FieldNormalizer

NewFieldNormalizer создает новый нормализатор полей

func NewFieldNormalizerFromConfig

func NewFieldNormalizerFromConfig(params map[string]any) (*FieldNormalizer, error)

NewFieldNormalizerFromConfig создает FieldNormalizer из конфигурации

func (*FieldNormalizer) Name

func (n *FieldNormalizer) Name() string

Name возвращает имя процессора

func (*FieldNormalizer) Process

func (n *FieldNormalizer) Process(ctx context.Context, data [][]string, schema packet.Schema) ([][]string, error)

Process реализует интерфейс PreProcessor/PostProcessor

type FieldValidationRule

type FieldValidationRule struct {
	Type   ValidationRule // Тип валидации
	Param  string         // Параметр правила (regex pattern, range, enum values, etc.)
	ErrMsg string         // Кастомное сообщение об ошибке (опционально)
}

FieldValidationRule содержит правило валидации для поля

type FieldValidator

type FieldValidator struct {
	// contains filtered or unexported fields
}

FieldValidator валидирует данные в указанных полях Может использоваться как PreProcessor (проверка перед экспортом) или PostProcessor (проверка перед импортом)

func NewFieldValidator

func NewFieldValidator(fieldsToValidate map[string][]FieldValidationRule, stopOnFirstError bool) (*FieldValidator, error)

NewFieldValidator создает новый валидатор полей. Стратегия по умолчанию — StrategyFail.

func NewFieldValidatorFromConfig

func NewFieldValidatorFromConfig(params map[string]any) (*FieldValidator, error)

NewFieldValidatorFromConfig создает FieldValidator из конфигурации

func (*FieldValidator) Name

func (v *FieldValidator) Name() string

Name возвращает имя процессора

func (*FieldValidator) Process

func (v *FieldValidator) Process(ctx context.Context, data [][]string, schema packet.Schema) ([][]string, error)

Process реализует интерфейс Processor. Поведение при ошибках определяется полем errorStrategy:

  • StrategyFail — возвращает ошибку, данные не передаются
  • StrategyFilter — удаляет невалидные строки, передаёт остальные
  • StrategyWarn — выводит предупреждения в stderr, передаёт все строки

type FileEncryptor

type FileEncryptor struct {
	// contains filtered or unexported fields
}

FileEncryptor шифрует TDTP XML блоб алгоритмом AES-256-GCM, получая ключ от xZMercury через UUID-binding флоу.

func NewFileEncryptor

func NewFileEncryptor(client MercuryBinder, serverSecret, packageUUID, pipelineName string) *FileEncryptor

NewFileEncryptor создаёт FileEncryptor для продакшен-режима. serverSecret — значение переменной MERCURY_SERVER_SECRET для верификации HMAC.

func (*FileEncryptor) Encrypt

func (f *FileEncryptor) Encrypt(ctx context.Context, plaintext []byte) (*EncryptionResult, string, error)

Encrypt получает ключ от Mercury, верифицирует HMAC, шифрует plaintext. Возвращает (result, errCode, error):

  • result: зашифрованный блоб + метаданные
  • errCode: mercury.ErrCode* — код для error-пакета при сбое
  • error: детальная ошибка

func (*FileEncryptor) EncryptSectionsV15

func (f *FileEncryptor) EncryptSectionsV15(ctx context.Context, pkt *packet.DataPacket) (string, error)

EncryptSectionsV15 получает ключ от Mercury (тем же BindKey+HMAC флоу что и Encrypt) и шифрует QueryContext/Schema/Data пакета "на месте" через packet.EncryptSections (TDTP v1.5 — Header остаётся plain XML). pkt должен уже пройти ComputeIntegrity и сжатие, если оно включено — порядок hash->compress->encrypt фиксирован, эта функция ничего из этого не выполняет сама. f.packageUUID должен быть pkt.Header.MessageID — иначе консьюмер не сможет узнать, каким uuid делать RetrieveKey, не расшифровав то, что как раз требует ключа (см. docs/tdtp-protocol-schema.md → "v1.5").

type MaskPattern

type MaskPattern string

MaskPattern определяет тип маскирования

const (
	// MaskPartial маскирует среднюю часть (email: j***@example.com)
	MaskPartial MaskPattern = "partial"
	// MaskMiddle маскирует середину (phone: +1 (555) ***-*567)
	MaskMiddle MaskPattern = "middle"
	// MaskStars заменяет все на звездочки (**** *****)
	MaskStars MaskPattern = "stars"
	// MaskFirst2Last2 показывает только первые 2 и последние 2 символа (1234 5678 → 12** **78)
	MaskFirst2Last2 MaskPattern = "first2_last2"
)

type MercuryBinder

type MercuryBinder interface {
	BindKey(ctx context.Context, packageUUID, pipelineName string) (*mercury.KeyBinding, error)
}

MercuryBinder — интерфейс для BindKey, позволяет подменять в тестах и dev-режиме.

type NormalizeRule

type NormalizeRule string

NormalizeRule определяет правило нормализации

const (
	// NormalizePhone приводит телефон к формату 79991234567
	NormalizePhone NormalizeRule = "phone"
	// NormalizeEmail приводит email к нижнему регистру
	NormalizeEmail NormalizeRule = "email"
	// NormalizeWhitespace убирает лишние пробелы
	NormalizeWhitespace NormalizeRule = "whitespace"
	// NormalizeUpperCase приводит к верхнему регистру
	NormalizeUpperCase NormalizeRule = "uppercase"
	// NormalizeLowerCase приводит к нижнему регистру
	NormalizeLowerCase NormalizeRule = "lowercase"
	// NormalizeDate приводит дату к формату YYYY-MM-DD
	NormalizeDate NormalizeRule = "date"
)

type PacketChain

type PacketChain struct {
	// contains filtered or unexported fields
}

PacketChain последовательно выполняет цепочку PacketProcessor.

func NewPacketChain

func NewPacketChain(procs ...PacketProcessor) *PacketChain

NewPacketChain создаёт PacketChain.

func (*PacketChain) Add

func (c *PacketChain) Add(p PacketProcessor)

Add добавляет процессор в конец цепочки.

func (*PacketChain) IsEmpty

func (c *PacketChain) IsEmpty() bool

IsEmpty возвращает true если цепочка пуста.

func (*PacketChain) ProcessPacket

func (c *PacketChain) ProcessPacket(ctx context.Context, pkt *packet.DataPacket) error

ProcessPacket прогоняет пакет через все процессоры цепочки последовательно.

type PacketProcessor

type PacketProcessor interface {
	Name() string
	ProcessPacket(ctx context.Context, pkt *packet.DataPacket) error
}

PacketProcessor обрабатывает DataPacket целиком (in-place). Уровень пакета: compact, compress, encrypt, hash. Порядок в цепочке: mask/normalize → compact → compress → encrypt → hash.

type PostProcessor

type PostProcessor interface {
	Processor
}

PostProcessor выполняется после парсинга TDTP пакета (при импорте) Используется для: обогащения, трансформации, валидации, присвоения значений по умолчанию

type PreProcessor

type PreProcessor interface {
	Processor
}

PreProcessor выполняется перед генерацией TDTP пакета (при экспорте) Используется для: маскирования, анонимизации, нормализации, валидации

type Processor

type Processor interface {
	// Name возвращает имя процессора
	Name() string

	// Process обрабатывает данные
	// data - строки данных (каждая строка - массив строк)
	// schema - схема данных для понимания типов полей
	Process(ctx context.Context, data [][]string, schema packet.Schema) ([][]string, error)
}

Processor определяет интерфейс для обработки данных

func CreateProcessor

func CreateProcessor(config Config) (Processor, error)

CreateProcessor создает процессор используя дефолтную фабрику

type ProcessorConfig

type ProcessorConfig struct {
	PreExport  []Config `yaml:"pre_export"`  // Процессоры перед экспортом
	PostImport []Config `yaml:"post_import"` // Процессоры после импорта
}

ProcessorConfig содержит конфигурацию цепочки процессоров

type ValidationErrorStrategy

type ValidationErrorStrategy string

ValidationErrorStrategy defines how validation errors are handled.

const (
	// StrategyFail aborts the operation and returns all collected errors (default).
	StrategyFail ValidationErrorStrategy = "fail"
	// StrategyFilter silently removes invalid rows and passes the rest through.
	StrategyFilter ValidationErrorStrategy = "filter"
	// StrategyWarn prints a warning for each invalid row but passes all rows through.
	StrategyWarn ValidationErrorStrategy = "warn"
)

type ValidationRule

type ValidationRule string

ValidationRule определяет тип правила валидации

const (
	// ValidateRegex - валидация по регулярному выражению
	ValidateRegex ValidationRule = "regex"
	// ValidateRange - валидация числового диапазона (min-max)
	ValidateRange ValidationRule = "range"
	// ValidateEnum - валидация по списку допустимых значений
	ValidateEnum ValidationRule = "enum"
	// ValidateRequired - проверка обязательности поля (не пустое)
	ValidateRequired ValidationRule = "required"
	// ValidateLength - валидация длины строки (min-max)
	ValidateLength ValidationRule = "length"
	// ValidateEmail - валидация email адреса
	ValidateEmail ValidationRule = "email"
	// ValidatePhone - валидация телефонного номера
	ValidatePhone ValidationRule = "phone"
	// ValidateURL - валидация URL
	ValidateURL ValidationRule = "url"
	// ValidateDate - валидация даты (формат YYYY-MM-DD)
	ValidateDate ValidationRule = "date"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL