Контекст: видимость данных

NOTE

Статус: Target design. Документ описывает целевую доменную модель. Соответствующий код реализован частично (см. backend/internal/core/) или пока не начат. Правила маркировки — в 50-processes/documentation-standard.md.

Назначение

В P1 proposal pipeline (search-proposal.md) visibility поддерживается только как deny на Discovery (Layer 1). Transforms (price_to_range, hide_warehouse, response-shaping) — P5 (Layer 3d post-ranking). До P5 leaf resolvers не модифицируют цену/остаток/склад на основании visibility.

Единый движок управления видимостью данных. Применяется на всех точках выдачи: search, pricing, estimate, public/admin API, analytics, webhooks, media. Вместо рассеянных проверок «кому что показать» — декларативные DataVisibilityPolicy.

Главный смысл

Visibility — поперечный (cross-cutting) BC. Он не владеет товарными или клиентскими данными — он фильтрует/трансформирует выдачу для конкретного Subject. Дефолт системы: allow (явное deny нужно завести).

Агрегаты / сущности / value objects

ИмяТипНазначение
DataVisibilityPolicy🟨 AggregateПравило видимости.
SubjectVOdefault / customer / customer_group / customer_pricing_group / role. Shared Kernel.
TargetKindVO enumcatalog / offer / observation / price / characteristic / analytics / media.
EffectVO enumallow / deny / transform.
PredicateVOJSONB-дерево.
TransformSpecVOredact_field / price_to_range / round_value / hide_warehouse / …
CompiledPolicy🟩 Read modelКэшированное исполнимое представление per-subject.
PolicySimulationVODiff-режим: «что увидит X».

Predicate DSL: операции

  • Логические: and, or, not.
  • Сравнения: eq, neq, in, not_in, any_in, between, gt, gte, lt, lte.
  • Спец: matches_tag, characteristic_eq, characteristic_in_range, manufacturer_in_group, belongs_to_identity_profile.
  • По supply chain: real_manufacturer_in, chain_includes_supplier, has_warehouse_operator, chain_depth_gt, trust_level_in.

Доменные события

СобытиеПричина
ПолитикаВидимостиСоздана (VisibilityPolicyCreated)Operator
ПолитикаВидимостиИзменена (VisibilityPolicyChanged)Operator
ПолитикаВидимостиОтключена (VisibilityPolicyDisabled)Operator
КомпиляцияПолитикиВыполнена (PolicyCompiled)Cache miss → compile
КомпиляцияПолитикиСброшена (PolicyCacheInvalidated)Изменение policy / subject membership
НарушениеSLAПолитики (PolicyEvaluationPerfViolation)Hard limit пробит
ПолитикаВDryRun (PolicyDryRunObservation)Pre-prod observation

Команды

КомандаАкторЦелевой агрегатРезультат
СоздатьПолитику (CreatePolicy)OperatorDataVisibilityPolicyVisibilityPolicyCreated
ИзменитьПолитику (UpdatePolicy)OperatorDataVisibilityPolicyVisibilityPolicyChanged
СкомпилироватьПолитики (CompileForSubject)EnginePolicyCompiled
СимулироватьПолитику (Simulate)OperatorPolicySimulation
ВключитьDryRun (EnableDryRun)OperatorDataVisibilityPolicy

Политики

ТриггерРеакция
VisibilityPolicyCreated/Changed/DisabledPolicyCacheInvalidated для затронутых subjects
CustomerPricingGroupChanged (Customer)→ invalidate cache subject=customer
PolicyEvaluationPerfViolation→ alert + запись policy_evaluation_audit
Создание новой policy→ автоматический EnableDryRun (опция, по умолчанию on)

Read-модели

  • 🟩 compiled_policy_cache (Redis) per-subject. TTL 5 мин (configurable).
  • 🟩 policy_evaluation_audit (CH) — для аудита нарушений и расследования.
  • 🟩 policy_simulation_runs (PG) — история симуляций.

Инварианты

  1. Дефолт системы — allow. Чтобы что-то скрыть — нужна явная deny-policy.
  2. Алгоритм применения детерминирован: при тех же (subject, target, candidate) — тот же effect.
  3. Performance budget (см. data-visibility-policy.md раньше — теперь здесь):
    • compile p95 < 20 мс (cache miss).
    • evaluate p95 < 0.5 мс (cache hit).
    • overhead на 10 policies p95 < 5 мс.
  4. Privacy: policy не утечёт данных другого клиента; сама policy запрещена цитировать конкретные customer_id из другой группы (валидируется при сохранении).
  5. Cyclic policy references — hard error.

Точки применения

BCЧто фильтрует
SearchРезультаты поиска catalog/offers
PricingObservations (выбор), price (transform)
EstimateКакие offers разрешены в смете
API response shapingRedact полей в ответах
AnalyticsКакие агрегаты доступны
WebhooksКакие события push’ить
Media servingКакие изображения / сертификаты разрешены

Интеграционные события (публикуем)

Топик: visibility.events.v1. Partition key: policy_id.

ИмяКогда
VisibilityPolicyCreated, VisibilityPolicyChanged, VisibilityPolicyDisabledИзменения справочника
PolicyCacheInvalidatedДля всех потребителей кэша

Подписанные интеграционные события

ИсточникСобытиеРеакция
CustomerCustomerPricingGroupChangedInvalidate cache subject=customer
CustomerCustomerGroupMembershipChangedInvalidate per-subject
Supplier NetworkSupplyChainTraceRecomputed(опционально) Re-evaluate где predicate использует chain

Связи в context map

BCПаттернНазначение
PricingSK (Visibility filter применяется внутри)
SearchSK
EstimateSK
CustomerSK (Subject shared)
Supplier NetworkSK (SupplyChainTrace для chain-предикатов)

Мини event storming

flowchart LR
    subgraph OPS["Actor"]
        OP["🟫 Operator"]
    end
    subgraph V["Visibility"]
        CMD["🟦 CreatePolicy"]
        DVP["🟨 DataVisibilityPolicy"]
        EV["🟧 VisibilityPolicyCreated"]
        DR["🟧 PolicyDryRunObservation"]
        COMP["🟦 CompileForSubject"]
        EC["🟧 PolicyCompiled"]
        CACHE["🟩 compiled_policy_cache"]
    end
    subgraph CONS["Pricing / Search / Estimate"]
        REQ["🟦 Evaluate(subject, target, candidate)"]
    end
    subgraph C["Customer"]
        CC["🟧 CustomerPricingGroupChanged"]
    end

    OP --> CMD --> DVP --> EV --> DR
    EV --> COMP --> EC --> CACHE
    REQ -. read .-> CACHE
    CC -.invalidate.-> CACHE

Связанные файлы