Learning Platform
Глоссарий Troubleshooting
Урок 06.03 · 26 мин
Продвинутый
Application ControlsInput ValidationProcessing ControlsOutput ControlsTrade-offsSwiftRide

Введение

M5.2 закрыл фундаментальный слой — ITGC. Это инфраструктура: access, change, ops, SDLC. Они защищают всю среду, но не знают про business-семантику конкретного CDE. Если ваш commission engine считает payouts неправильно из-за бага в формуле, никакой Snowflake RBAC не поможет — инженер с легитимным доступом записал bad logic, всё прошло через CI, и неверные значения уверенно протекли в driver_earnings_ledger.

Application controls — это слой контролей, сидящий поверх ITGC, специфичный для business logic. Они вступают в действие во время обработки данных: на input, во время processing, на output. Commission engine SwiftRide — пайплайн на ~25 dbt-моделей — нуждается в application controls на каждом из этих трёх этапов.

В этом уроке разберём три категории — input, processing, output — на конкретных примерах из пайплайна расчёта driver earnings SwiftRide. Под конец увидим компромисс: при сильных ITGC application controls становятся primary audit-relevant defense (PCAOB AS 2201 ¶.47 «lower risk» классификация); при слабых ITGC application controls не убеждают аудитора сами по себе.

Категория 1 — Input controls

Цель: блокировать invalid, malformed или out-of-domain data до того, как они попадут в source-of-truth.

Schema enforcement

Базовый input control — schema validation. Пайплайн отказывается принимать запись, если schema не соответствует.

В реализации SwiftRide:

  • Kafka topic trips.completed — Avro schema через Confluent Schema Registry. Compatibility check BACKWARD включён; producer, пытающийся подать несовместимую schema, получает 4xx response.
  • dbt source contract на raw.trips — column types + non-null constraints + uniqueness. dbt-контракт fails build при schema drift.
  • PostgreSQL trips table — строгие типы (DECIMAL(10,2) на fare_total), check constraints, foreign keys.

Range / domain validation

После schema check — value-level validation. Schema говорит «fare_total это DECIMAL»; range check говорит «между 0и0 и 5000».

Примеры SwiftRide на trips:

  • fare_total_cents >= 0 AND fare_total_cents <= 500000 (max $5000 per trip).
  • commission_pct >= 0.0 AND commission_pct <= 0.5 (max 50% commission, регуляторный потолок).
  • country_code IN (whitelist на 40 стран).
  • trip_started_at < trip_completed_at.
  • trip_completed_at <= now() + interval '1 hour' (поездки с датой в будущем — ошибка).

Реализации:

  • Database CHECK constraints (PostgreSQL).
  • dbt accepted_values, not_null, custom tests.
  • GE Core 1.17.1 expectation suite — запускается на каждом batch.

Type validation / sanitization

Кроме schema — семантическая валидация.

Примеры:

  • email_address соответствует regex pattern + DNS-MX check.
  • phone_number соответствует E.164 format + country prefix матчится с country_code.
  • vat_number соответствует per-country format (VIES validation).
  • ip_address валидный IPv4 / IPv6.

Специфика PII — input validation также является соответствием GDPR Art. 5(1)(c) («data minimisation») — не принимать data вне периметра.

Completeness controls (на стороне input)

Обнаруживают missing batches / частичные loads.

Примеры:

  • Daily batch приходит — record count соответствует ожидаемому (в пределах толеранса ±2% против trailing 7-day average).
  • Hourly Kafka offset committed — детекция gap per partition (alert если consumer lag больше 5 минут).
  • Source-system file load — checksum match против producer-published manifest.

Категория 2 — Processing controls

Цель: гарантировать, чтобы transformation от raw input к canonical output была корректной и без silent corruption.

Reconciliation (в полёте)

Reconciliation между промежуточными стадиями.

Пайплайн driver earnings SwiftRide:

  1. trips.completed Kafka → stg_trips (dbt staging) — count match (в пределах ±1% — толеранс late-arriving).
  2. stg_tripsint_trip_aggregates (dbt intermediate) — sum check: total fare в staging = total fare в intermediate.
  3. int_trip_aggregates × commission_rulesfct_driver_earnings — formula spot-check: 100 random rows recompute formula, ожидается match.

Каждый шаг reconciliation имеет собственную log entry в S3 object lock + immutable evidence.

Double-entry / parity

Заимствовано из accounting principle. Каждая транзакция записывается дважды, и накопленные balances должны match.

SwiftPay wallet SwiftRide:

  • Каждый payout — debit к pool account + credit к driver account. Daily reconciliation: sum(debits) = sum(credits). Любая разница → ledger imbalance, Sev-1.

Не каждый CDE требует double-entry, но любой financial CDE — да.

Formula validation

Критично для calculation-пайплайнов.

Расчёт commission SwiftRide:

  • Production formula хранится в version-controlled config (commission_rules.yaml).
  • Spot-check pipeline: для каждого batch выбирает 100 случайных trip_id, перевычисляет earnings через canonical Python implementation (отдельный codepath), сравнивает с dbt model output. Mismatch больше 0 row → Sev-1.
  • Почему две реализации? Защита от бага в логике dbt model. Если SQL имеет subtle bug (rounding, type coercion), Python check ловит. См. K019 — это reference-вариант parity check.

Sequence / ordering controls

Для event-sourced пайплайнов — обеспечить обработку событий по порядку.

Kafka consumer SwiftRide:

  • Каждое событие имеет monotonic sequence_id per trip_id partition key.
  • Consumer отбрасывает события с lower seq, чем уже обработанные (идемпотентность).
  • Out-of-order events логируются + reviewed (могут указывать на clock skew у источника).

Категория 3 — Output controls

Цель: обеспечить, чтобы final output (CDE table, regulatory file, BI dashboard feed) был accurate, complete и timely.

Cross-system reconciliation

Самый важный output control — подробно покрыт в M5.6.

Концепция: независимое сравнение final output между двумя независимыми источниками.

Примеры SwiftRide:

  • fct_driver_earnings.gross_earnings_usd (Snowflake daily aggregate) против swiftpay.payouts.amount_paid_usd (Aurora actual payouts, после обработки) — daily delta больше 0.05% триггерит инцидент.
  • fct_revenue_daily.net_revenue_usd (Snowflake) против Treasury cash-in (банковский источник, ежемесячно) — monthly delta больше 0.1% триггерит расследование.
  • kyc_profile.status='approved' count (Snowflake) против Onfido provider count (внешняя истина) — еженедельный анализ delta.

Threshold alerts

Output-значения против ожидаемых диапазонов; alert при выходе за границы.

SwiftRide:

  • Daily net_revenue_usd < 5Mили>5M или > 10M → operations review (типично $6-8M).
  • Daily kyc_approvals_count drop больше 40% против trailing 30-day average → fraud / outage investigation.
  • driver_earnings.payout_per_driver outlier больше $10K per day → manual review.

Completeness controls (на стороне output)

Проверяют, что ожидаемый output произведён.

  • fct_revenue_daily — 6 БЮ × 40 стран = 240 ожидаемых partition rows per day. Row count <230 → completeness check fails.
  • IRS 1099 export — ожидается ~50K eligible drivers; фактический count в пределах ±2% оценки.

Timeliness controls

Output произведён в пределах SLA.

  • fct_driver_earnings для day T должен завершиться к T+1 06:00 UTC. Airflow DAG SLA fail → PagerDuty.
  • KYC approval decision в течение 24h после подачи — count pending больше 24h → Sev-3 alert.

Distribution / access controls

Output controls также включают, куда output идёт.

  • IRS 1099 export — S3 bucket с restricted access (Tax team + Finance Lead); SHA-256 signed; зашифрованный передаётся IRS-партнёру по email.
  • Driver Payouts Dashboard в Looker — RBAC на уровне БЮ; PII fields замаскированы без явного grant.

Driver earnings SwiftRide — полный набор контролей

Application controls — пайплайн SwiftRide driver_earnings_ledger

Контроли input / processing / output встроены в пайплайн. Каждая ячейка — конкретный control + evidence artifact.

PostgreSQL.tripsOLTP source — Aurora trips table
ingest
Kafka topicKafka topic trips.completed
dbt
dbt stgstg_trips staging model
aggregate
dbt intint_trip_aggregates intermediate
apply commission
fct_driver_earningsCDE-SWR-003 driver_earnings_ledger
INPUTSchema (CHECK)PostgreSQL CHECK constraint: fare 0-5000$, commission 0-50%; FK; uniqueness
INPUTSchema RegistryKafka Avro schema BACKWARD compat; отклоняет несовместимых producers
INPUTdbt contract + testsdbt 1.9 contract на columns; accepted_values; not_null; row_count против 7d avg ±2%
PROCESSSum reconciliationsum(fare) staging = sum(fare) intermediate; нулевая толерантность
PROCESSFormula parity100 случайных rows перевычисляются Python implementation; нулевая толерантность к mismatch
SwiftPay payoutsOutput → SwiftPay payouts (Aurora) для фактической выплаты
reconcile
fct_driver_earningsCDE-SWR-003
aggregate
IRS 1099Годовой 1099-NEC export
BI
LookerLooker Driver Payouts Dashboard
OUTPUTCross-system reconDaily Snowflake earnings против Aurora фактических payouts; delta больше 0.05% → Sev-1
OUTPUTThreshold alertsPer-driver outlier больше $10K/day → manual review; payout_count drop больше 40% → Sev-2
OUTPUTCompleteness240 ожидаемых БЮ×country rows; <230 → completeness fail; IRS count ±2% оценки
OUTPUTSLA + accessT+1 06:00 UTC SLA; PagerDuty при breach; Looker RBAC per БЮ; PII замаскирован

Пайплайн имеет 13 application controls. Каждый имеет evidence artifact: dbt run artifacts, GE Data Docs, reconciliation logs в S3 object lock, Airflow run logs, PagerDuty incidents, Looker audit logs.

Компромиссы — ITGC против application controls

Когда строить ITGC против application control для покрытия риска?

АспектITGCApplication control
ПериметрCross-CDE (purpose-agnostic)CDE-specific (или семейство CDE)
СтоимостьHigh initial; амортизируется по всем CDEPer-CDE; может масштабироваться медленно
Стоимость audit-testТестируется один раз, используется много разТестируется per material control
Время реакцииЧасто медленное (UAR квартально, change CR ежедневно)Быстрое (real-time, per-record)
Периметр сбояFailure cascades — все CDE на этой инфре затронутыFailure локализован в пределах одного семейства CDE
Оптимальное применениеФундамент; auth, deploy, ops, lifecycleКорректность business-logic, per-CDE

PCAOB AS 2201 ¶.47 следствие: при effective ITGC application controls «generally expected to be lower risk» — audit testing сокращается.

Практическое правило:

  • Сначала строим сильный ITGC. Без effective ITGC application controls не могут получить lower-risk классификацию под AS 2201 ¶.47.
  • Затем наслаиваем application controls. Per material CDE. Используем M5.1 defense-in-depth (минимум 1 preventive + 1 detective + желательно corrective).
  • Не подменяем одно другим. ITGC не закрывает business logic risk; application controls не закрывают infrastructure risk. Они комплементарны.

BCBS 239 Principle 3 — accuracy and integrity

BCBS 239 Principle 3 требует largely automated aggregation, минимизированных manual workarounds, reconciliation to source. На языке SwiftRide — это автоматизированные input + processing + output controls, с reconciliation evidence.

BIS BCBS d559 (November 2023) implementation review — из 31 G-SIBs только 2 fully compliant. Principle 3 (accuracy) — повторяющаяся слабость: банки выполняют DQ checks, но без traceable reconciliation chain. SwiftRide должен начинать с traceable chain reconciliation как day-1 requirement для material CDE.

Проверка знанийKnowledge check
SwiftRide T+9M внутренний аудит: на CDE-SWR-001 `revenue_gmv_aggregates` (weighted score 5.00, прямой feed S-1) — список контролей: (a) Snowflake RBAC (только Finance может SELECT); (b) ServiceNow CR на любые changes; (c) dbt test row_count >= 0 (тривиальный); (d) Looker dashboard с CFO sign-off раз в квартал. Какой класс controls отсутствует — input / processing / output / ITGC?
ОтветAnswer
Mapping: (a) Snowflake RBAC = ITGC access control; (b) ServiceNow CR = ITGC change management; (c) dbt test row_count >= 0 = input control (но тривиальный — истинно для любого non-broken pipeline); (d) Looker dashboard CFO sign-off = output manual detective control. Отсутствуют: substantive input controls (range checks, schema enforcement на CDE columns), processing controls (sum reconciliation между стадиями, formula parity на rev_calc), output controls (cross-system reconciliation Snowflake fct_revenue_daily vs Treasury cash-in, threshold alerts на anomalous values, completeness checks 6 BU × 40 countries = 240 ожидаемых partitions). Фактически только 2 controls — пара ITGC + косметический dbt test + late-stage manual review. Для CDE-SWR-001 (score 5.00, SOX 404 direct) это неприемлемо. Ремедиация: добавить минимум 4 application controls per defense-in-depth (1 input preventive — range + schema + completeness; 1 processing preventive — sum reconciliation между dbt stages; 2 output detective — cross-system reconciliation + threshold alerts). Без application controls ITGC сам по себе не покрывает корректность business logic.

Anti-patterns

Input validation в downstream вместо upstream

Паттерн: валидация происходит в dbt staging layer вместо на источнике (PostgreSQL CHECK или Kafka schema). Bad data попадает в raw layer, ловится позже.

Почему плохо: больше latency catch; bad data может протечь в других consumers raw-слоя.

Fix: валидируем на источнике (PostgreSQL CHECK constraints, Kafka Schema Registry). Staging layer повторяет validation как defense-in-depth.

Processing без reconciliation между стадиями

Паттерн: пайплайн staging → intermediate → mart, но никаких sum/count checks между стадиями.

Почему плохо: silent corruption в intermediate layer (например, JOIN, дропающий rows из-за NULL key) не обнаруживается.

Fix: каждый переход между стадиями имеет как минимум count + sum reconciliation log entry; immutable storage.

Output controls только в production, не в pipeline runs

Паттерн: cross-system reconciliation запускается только после завершения пайплайна; если пайплайн производит wrong data, reconciliation ловит — но wrong data уже visible в Looker-дашборде в течение 6 часов.

Почему плохо: latency window между production и detection — material exposure.

Fix: reconciliation в pipeline DAG как gating step; downstream consumers получают output только после прохождения reconciliation.

Чрезмерная опора на один тип control

Паттерн: «у нас daily reconciliation — все CDE покрыты».

Почему плохо: daily reconciliation = detective only. Input bug + reconciliation = damage caught after damage done.

Fix: defense-in-depth (M5.1). Каждый material CDE имеет input preventive (schema + range) + processing preventive (formula validation) + output detective (cross-system reconciliation).

Резюме

  • Application controls в 3 категориях: input (schema, range, type, completeness), processing (reconciliation in-flight, double-entry, formula parity, sequence), output (cross-system reconciliation, threshold alerts, completeness, timeliness, distribution).
  • Пайплайн driver_earnings SwiftRide — 13 application controls. Каждый с evidence artifact (dbt run, GE Data Docs, reconciliation log, Airflow log, PagerDuty incident, Looker audit).
  • ITGC против application controls: комплементарны, не взаимозаменяемы. Периметр ITGC cross-CDE; application controls CDE-specific. PCAOB AS 2201 ¶.47 — effective ITGC даёт lower-risk классификацию application controls.
  • BCBS 239 Principle 3 — accuracy and integrity — требует largely automated aggregation + reconciliation to source. BIS d559 review: только 2 из 31 G-SIBs fully compliant.
  • Сначала строим сильный ITGC (M5.2). Затем наслаиваем application controls per material CDE (M5.4 — декомпозиция objective/activity/evidence).

В M5.4 разберём подробно — как разложить «control» на objective + activity + evidence; почему «SELECT COUNT(*) > 0» не является control.

Измерение completeness — input controls Выявление нарушений DQ — processing controls

Проверьте понимание

Результат: 0 из 0
Аналитический
Вопрос 1 из 4. SwiftRide T+9M внутренний audit на CDE-SWR-001 `revenue_gmv_aggregates` (5.00 weighted score, direct S-1 feed): controls list — (a) Snowflake RBAC, (b) ServiceNow CR на changes, (c) dbt test `row_count >= 0`, (d) Looker dashboard quarterly CFO sign-off. Audit deems coverage inadequate. Какие application controls missing + remediation priority?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 9