Files
han-app/architectory/arch-07-observability.md
T

34 KiB
Raw Blame History

arch-07. Контракт наблюдаемости

Канонический контракт telemetry для всех application VM и private SigNoz.
Реализация на конкретной VM — в module-09-observability-vm1.md и module-09-observability-vm2.md.
Имена сущностей — arch-00-glossary.md. Границы системы — arch-01-system-architecture.md. HTTP — arch-02-api-contracts.md. Compose — arch-03-docker-compose-blueprint.md. Env — arch-04-settings-and-content.md. Процесс — arch-05-agent-development-process.md. Host security — arch-06-service-hosting-security.md.

Назначение

Документ фиксирует то, что должно совпасть между ВМ1 и ВМ2: схема сигналов, корреляция, redaction, sampling, Collector pipeline и удаленный backend. Локальные service.name, scrape targets, дашборды и алерты конкретной машины в этом файле не детализируются.

Этот контракт нельзя независимо кастомизировать в репозитории VM. Изменение JSON-полей, labels, redaction, sampling или service.namespace сначала вносится сюда.

1. Цели и границы

Наблюдаемость должна позволять:

  • найти пользовательский запрос по request_id, trace_id или ux_session_id;
  • восстановить путь «frontend → nginx → API → Safety → S3/Open Lines»;
  • измерять доступность, задержку, ошибки и насыщение каждого сервиса;
  • обнаруживать backlog, DLQ, circuit open, потерю telemetry и истечение TLS;
  • расследовать security/audit события без записи PII и секретов;
  • проверять SLO по данным, независимым от бизнес-логов.

Telemetry не является источником бизнес-истины и не влияет на auth, safety verdict или доставку сообщений. Недоступность Collector не должна блокировать запросы. Audit в han_app — отдельный durable контур.

2. Production-like решение MVP

2.1. Обязательный минимум в основном Compose

Каждый root Compose (ВМ1 и ВМ2) обязан содержать локальный otel-collector. Prometheus/Grafana/Loki/Tempo не обязаны размещаться на application VM.

Операбельный вариант:

  1. приложения на каждой VM экспортируют OTLP gRPC только в свой local otel-collector:4317;
  2. Collector отправляет telemetry в self-hosted SigNoz на отдельной VM 192.168.0.5:4317;
  3. JSON stdout остаётся аварийным локальным журналом Docker с rotation;
  4. пока удалённый backend недоступен в конкретном окружении, допустим архитектурный минимум из arch-03: bounded JSON stdout/platform logs и Collector debug exporter с sampling в acceptance; такой режим не считается полноценным production-хранением и не закрывает alerting/SLO.

Требуемые возможности backend: OTLP ingest, поиск traces, PromQL-совместимые или эквивалентные metrics, поиск структурированных logs, alerting, RBAC, retention и TLS. Для текущего SigNoz plaintext OTLP разрешён только внутри доверенной приватной сети; UI — через SSH jump host.

ВМ2 никогда не использует Docker hostname collector ВМ1. Каждый collector имеет собственный otel-queue.

2.2. Самостоятельно размещаемая опция

Опциональный Compose profile observability-local может включать Prometheus, Grafana, Loki и Tempo. Он не включается по умолчанию на малой VM: стек требует дополнительной RAM/диска и сам становится объектом backup/monitoring.

Для operable local-варианта нужны отдельный volume каждому backend, retention limits, compaction, auth через ops/VPN и отсутствие host ports. Grafana доступна только через отдельный защищённый ops route/VPN, не через публичный /.

Рекомендуемый минимум VM при local profile: дополнительно 4 vCPU, 8 ГБ RAM и 100+ ГБ SSD сверх приложения; точный размер — после измерения ingest. Нужен ли profile на ВМ1 — TBD профильной спецификации ВМ1.

3. Архитектура Collector

3.1. Компоненты

backend services ─OTLP gRPC/HTTP─┐
nginx/Redis/Keycloak exporters ──┼─> otel-collector
Docker JSON stdout ─filelog───────┘      ├─ OTLP remote backend (SigNoz)
                                        ├─ Prometheus endpoint (optional)
                                        └─ debug exporter (acceptance only)

Collector запускается одним сервисом MVP. При росте разделяется на agent/gateway: локальный agent принимает и буферизует, remote gateway выполняет policy/export.

3.2. Receivers

  • otlp gRPC 0.0.0.0:4317 — основной internal receiver;
  • otlp HTTP 0.0.0.0:4318 — совместимость SDK;
  • prometheus — scrape самого Collector, exporters и сервисных /metrics, если они не идут OTLP;
  • filelog — только если Docker logging driver предоставляет read-only каталог/volume; парсит JSON stdout без чтения secret-файлов;
  • hostmetrics — CPU, memory, filesystem, network VM/container host, если Collector получает только необходимые read-only mounts.

Порты 4317, 4318, 8888, 8889 используют expose, не ports. Receiver доступен только в сети observability.

3.3. Processors и порядок

Во всех pipelines первым стоит защита памяти, последним — batch:

  1. memory_limiter: check interval 1s, soft/hard limit относительно container memory;
  2. resource: нормализует service.namespace=han-chat, deployment.environment, service.version;
  3. attributes: удаляет/маскирует sensitive attributes;
  4. transform: нормализует route/status/error semantic conventions;
  5. filter: исключает health noise, debug events и запрещённые поля;
  6. probabilistic_sampler или tail sampling для traces;
  7. batch: bounded batch/timeout;
  8. при remote export — queued_retry/sending queue и file_storage extension.

memory_limiter не заменяется Docker OOM limit. При pressure Collector отбрасывает telemetry контролируемо и увеличивает otelcol_processor_refused_*.

3.4. Exporters

  • otlp/remote: endpoint из secret env/mount; для SigNoz в доверенной private network — plaintext 192.168.0.5:4317; для любого иного remote — TLS verify;
  • prometheus: optional pull endpoint только internal;
  • debug: только APP_ENV=test|acceptance, verbosity normal; production debug exporter по умолчанию выключен;
  • loki/otlphttp — только если выбран дополнительный backend и его контракт закреплён.

Секрет exporter-а не должен появляться в rendered config, логах или /debug/configz. Config монтируется read-only; secret подставляется env.

3.5. Extensions

  • health_check — internal endpoint, используется Compose;
  • pprof/zpages — только при явном ops profile, internal network;
  • file_storage — persistent sending queue на volume otel-queue;
  • basicauth/oauth2client — если требует remote backend.

3.6. Принципиальная конфигурация

receivers:
  otlp:
    protocols:
      grpc: {endpoint: 0.0.0.0:4317}
      http: {endpoint: 0.0.0.0:4318}
  prometheus:
    config:
      scrape_configs:
        - job_name: otel-collector
          static_configs: [{targets: ["127.0.0.1:8888"]}]

processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 384
    spike_limit_mib: 96
  resource/common:
    attributes:
      - {key: service.namespace, value: han-chat, action: upsert}
      - {key: deployment.environment, value: "${env:APP_ENV}", action: upsert}
  attributes/redact:
    actions:
      - {key: http.request.header.authorization, action: delete}
      - {key: http.request.header.cookie, action: delete}
      - {key: url.query, action: delete}
      - {key: db.statement, action: delete}
  filter/noise:
    error_mode: ignore
    traces:
      span:
        - 'attributes["http.route"] == "/health/live"'
  batch:
    send_batch_size: 1024
    timeout: 5s

exporters:
  otlp/remote:
    endpoint: "${env:OTEL_REMOTE_ENDPOINT}"
    # true только для утверждённого plaintext SigNoz внутри private network;
    # для любого другого remote — false и проверка CA.
    tls: {insecure: ${env:OTEL_REMOTE_TLS_INSECURE}}
    headers: {authorization: "${env:OTEL_REMOTE_AUTH_HEADER}"}

extensions:
  health_check: {endpoint: 0.0.0.0:13133}
  file_storage: {directory: /var/lib/otelcol/queue}

service:
  extensions: [health_check, file_storage]
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, resource/common, attributes/redact, filter/noise, batch]
      exporters: [otlp/remote]
    metrics:
      receivers: [otlp, prometheus]
      processors: [memory_limiter, resource/common, attributes/redact, batch]
      exporters: [otlp/remote]
    logs:
      receivers: [otlp]
      processors: [memory_limiter, resource/common, attributes/redact, filter/noise, batch]
      exporters: [otlp/remote]
  telemetry:
    metrics: {address: 0.0.0.0:8888}

Конкретная версия schema проверяется командой Collector validate; image закрепляется по digest. Значения memory/batch/queue — стартовые, не SLO. Для текущего SigNoz tls.insecure и auth header задаются профильной спецификацией VM согласно O1/O-TBD1. Scrape targets кроме самого Collector добавляет спецификация VM.

4. Resource attributes и корреляция

Обязательные resource attributes:

  • service.name — только из реестра ниже;
  • service.namespace=han-chat;
  • service.version=<release-or-git-sha>;
  • deployment.environment=production-like|production;
  • host.name/service.instance.id без публичного IP.

Для logs действуют те же resource attributes, что для traces/metrics. trace_id (32 hex) и span_id (16 hex) добавляются только из активного OpenTelemetry span. SigNoz связывает log со span по этой паре. Host, Redis, Docker и systemd события, у которых span отсутствует, коррелируются по host.name, service.name, времени и безопасным request/business IDs; синтетические trace/span IDs для них запрещены.

На application VM используются два непересекающихся канала:

  • Python application logs отправляются OTLP Logs SDK в Compose Collector и одновременно остаются в JSON stdout как локальный аварийный buffer;
  • platform logs (nginx, Keycloak, Redis, Docker и выбранные systemd units) собирает отдельный host agent без доступа к Docker socket.

Один источник не может одновременно экспортироваться SDK и host filelog. Allow-list источников и self-exclusion Collector обязательны, чтобы исключить дубли и feedback loop.

Реестр service.name:

Имя Владелец
nginx nginx каждой VM; различать экземпляры host.name / service.instance.id
api-backend ВМ1
delivery-worker ВМ1
safety-recovery-worker ВМ1
cleanup-worker ВМ1
notification-expire-worker ВМ1
notification-draft-cleanup-worker ВМ1
bitrix-local-app ВМ1
keycloak ВМ1
sms-service ВМ1, callback/internal API
sms-worker ВМ1, отправка в Direct
message-safety ВМ2
bitrix-sync ВМ2
redis Redis каждой VM; различать экземпляры
otel-collector collector каждой VM
otel-host-collector host telemetry agent ВМ1

Новое имя добавляется только сюда, затем в спецификацию владельца.

Обязательные поля request-события:

  • request_id;
  • trace_id, span_id;
  • ux_session_id — nullable, только когда передан;
  • service.name;
  • environment либо canonical deployment.environment.

request_id формирует/валидирует nginx; сервис возвращает его клиенту и передаёт downstream. trace_id берётся из active span. ux_session_id не является auth и не должен использоваться как metric label.

5. W3C propagation

  • принимаются только валидные traceparent и опциональный tracestate;
  • nginx передаёт context upstream; при edge instrumentation создаёт server span;
  • caller создаёт child spans для своих зависимостей (PostgreSQL, Redis, S3, Safety, Open Lines, JWKS, CRM);
  • internal calls передают traceparent, tracestate, X-Request-ID;
  • baggage по умолчанию не принимается от внешнего клиента; если включён, allow-list исключает PII;
  • Bitrix24/S3 могут не вернуть context: внешний client span всё равно закрывается результатом;
  • async outbox/inbox связывается span link с исходным trace; новый worker trace не притворяется продолжением спустя долгий срок.

Frontend может отправлять валидный traceparent, но backend не доверяет его sampling/security атрибутам.

6. JSON stdout contract

Одна JSON-запись на строку UTF-8:

{
  "timestamp": "2026-07-10T09:00:00.123Z",
  "level": "INFO",
  "service.name": "api-backend",
  "service.version": "git-abcdef0",
  "environment": "production-like",
  "module": "message_service",
  "event": "message.delivery.completed",
  "message": "Message delivery completed",
  "request_id": "01J...",
  "trace_id": "32hex",
  "span_id": "16hex",
  "ux_session_id": "uuid-or-null",
  "route": "/api/v1/dialogs/{dialog_id}/messages",
  "method": "POST",
  "status_code": 201,
  "duration_ms": 742,
  "dependency": "bitrix-local-app",
  "outcome": "success",
  "error_code": null
}

Правила:

  • event — стабильная mnemonic, message — безопасное описание;
  • route — template, никогда raw URI с id/query;
  • stack trace допускается только в internal error log после redaction;
  • message text, callback body, SQL values и file content запрещены;
  • Docker driver ограничен 50m × 5, но это buffer, не retention backend;
  • multiline stack trace сериализуется полем JSON, не отдельными строками.

7. Redaction и data minimization

Удаляются или маскируются:

  • Authorization, Cookie, Set-Cookie, JWT, OAuth/code/refresh/access tokens;
  • raw OTP/mock code, Keycloak admin/client password;
  • phone/email/full name, device id, IP по policy (допустим HMAC/truncated);
  • message text, filenames с PII, document/file contents;
  • DSN/password, Redis URL, S3 keys;
  • presigned URL и любая query string;
  • Bitrix raw payload/download URL/application token;
  • db.statement с literals; предпочтительно operation/table, не SQL.

Redaction выполняется в SDK/logger до stdout, затем повторяется Collector processor. Collector не может считаться единственной защитой. Автотесты отправляют canary secrets/PII и требуют отсутствие во всех трёх сигналах.

8. Общие правила instrumentation

Детальный список инструментов конкретной VM — в профильной спецификации. Ниже правила, общие для всех сервисов.

8.1. FastAPI и workers

  • OpenTelemetry ASGI/FastAPI server spans с route template;
  • HTTPX client spans с sanitized host/method/status;
  • SQLAlchemy/asyncpg spans без параметров и raw statement;
  • Redis instrumentation с command name и DB index, без key/value;
  • boto/S3 spans: operation/bucket logical name, без object key/query;
  • background workers: span на claim/process/finalize, links на origin;
  • исключить /health/live из traces; readiness оставить в metrics и sampled logs.

8.2. PostgreSQL

Собираются pool wait/checked-out, transaction duration, error class, migrations revision, managed PG provider metrics (CPU, storage, connections, locks, replication/PITR state). user_id, SQL text и row data не labels.

8.3. Redis

redis_exporter подключается отдельным ACL user только на INFO, PING, безопасные latency/keyspace metrics. Нужны memory ratio, evictions, expirations, blocked/rejected clients, command latency, AOF status/rewrite, Pub/Sub buffers, key count/TTL агрегаты. Keys/values не экспортируются.

8.4. nginx

JSON access log содержит request_id, извлечённый trace_id, route class, method, normalized path, status, bytes, request/upstream duration/status, TLS version, cache status. $request с query не используется.

Collector filelog parser:

  • разбирает JSON, timestamp и severity;
  • переносит service.name=nginx;
  • превращает пустые/- в null;
  • route class нормализует в bounded set;
  • отбрасывает ACME/health success noise;
  • не парсит raw URI в labels.

Native nginx OTEL module предпочтителен, если image/version закреплены. Без него nginx только передаёт W3C context и коррелирует access log; первый server span создаёт upstream.

8.5. Host/Docker

CPU, load, memory/swap, disk usage/inodes/IO, network, container restarts/OOM, Docker daemon health и clock sync. Container name/version — bounded labels; container id не хранится как долгосрочный high-cardinality label.

9. Метрики: запрет high-cardinality

Никакие UUID/user/session/dialog/task/message id не labels. Они допустимы только в sampled logs/traces при принятой retention. Allow-list labels; route template вместо raw path; status class/known code; dependency enum.

Карта бизнес-метрик принадлежит спецификации VM-владельца сервиса. Сквозные SLI ниже используют сигналы обеих VM.

10. Сквозные dashboards в SigNoz

SigNoz обязан иметь:

  1. Executive/SLO: availability, error budget burn, p50/p95/p99, message delivery, auth, active incidents.
  2. Business flow: guest config → OTP → bootstrap → session → dialog → safety → Open Lines → operator reply.
  3. Collector health: accepted/sent/refused/dropped, queue, retry, exporter errors, memory/CPU — отдельно по host.name ВМ1 и ВМ2.

Сервисные дашборды nginx/API/Safety/Keycloak/Redis/sync — в спецификациях VM. Каждая панель содержит release annotation, environment filter и links trace→logs по trace_id.

11. SLI, SLO и общие alerts

Значения — начальная production-like политика до load/product review:

SLI Initial SLO, 30 дней
HTTPS edge availability 99.9%
public config/content successful requests 99.9%
protected read API successful requests 99.5%
Keycloak login flow availability 99.5%
text message accepted и доставлен в Open Lines 99.0%
operator inbox applied без permanent loss 99.5%
p95 protected read API < 750 ms
p95 text send без внешнего rate limit < 5 s
telemetry Collector ingest availability 99.0%, не входит в business availability

Файловый send измеряется отдельно: p95 не должен превышать configured safety poll budget; user-cancel, safety deny, 4xx validation и edge abuse 429 не считаются server failure. 503/504 и unexpected 5xx считаются.

Paging/ticket alerts, привязанные к конкретному сервису, задаёт спецификация VM. Общие инфраструктурные paging alerts:

  • multi-window burn: 14.4× за 5m/1h или 6× за 30m/6h;
  • PostgreSQL unavailable/connection saturation >90%;
  • Collector exporter queue >80%, dropped/refused telemetry >0 sustained;
  • TLS expiry <14 дней warning, <7 дней page;
  • disk >85% warning, >92% page; OOM/restart loop;
  • managed PG backup/PITR failure.

Alert содержит service, environment, symptom, dashboard, runbook, release и безопасный query; не содержит PII.

12. Sampling, cardinality и retention

Traces

  • errors/5xx, circuit, timeout, DLQ, safety final deny и slow requests — 100%;
  • обычные успешные requests — 510%;
  • health/ACME success — 0%;
  • tail sampling предпочтителен в Collector, но head sample SDK должен оставлять достаточно данных;
  • sampling decision передаётся W3C.

Metrics

Cardinality budget: целевой <10 000 active series на MVP environment. CI проверяет запрещённые labels.

Retention initial

  • metrics: 30 дней high resolution, 13 месяцев downsampled при доступности backend;
  • traces: 7 дней, errors 14 дней;
  • technical logs: 14 дней, security/auth logs 30 дней;
  • audit han_app: 365 дней только как временное допущение до legal policy;
  • raw Bitrix callback не хранится в telemetry;
  • local Docker logs: не более 250 МБ/container и 5 файлов.

Legal retention/erasure имеет приоритет; изменение требует обновления policy и backup lifecycle.

13. Collector health и отказоустойчивость

Контролируются:

  • /health extension;
  • process CPU/RSS/restarts;
  • accepted/refused/sent/failed spans, points, records;
  • batch send size/latency;
  • exporter queue capacity/size, enqueue failures, retry age;
  • file storage usage/corruption;
  • scrape failures;
  • config reload/validation.

При remote outage queue хранится на otel-queue с bounded size/age. При заполнении отбрасываются сначала low-priority success traces/logs; приложение продолжает работу. Нельзя позволять queue заполнить системный диск. Telemetry outage/overflow fail-open для business и Safety readiness, но создаёт alert.

14. Docker Compose collector

otel-collector:

  • pinned contrib image;
  • networks: только observability, а для scrape internal targets — минимально необходимая backend;
  • expose: 4317, 4318, 13133, 8888/8889;
  • без host ports;
  • config read-only, otel-queue volume rw;
  • non-root, read-only rootfs, tmpfs /tmp, drop capabilities, no-new-privileges;
  • перед collector запускается idempotent otel-queue-init: one-shot без сети и secrets, с user: 0:0, cap_drop: ALL и только CHOWN/FOWNER, выставляет mount root 10001:10001 0700; collector зависит от service_completed_successfully;
  • initial limit: 0.5 CPU/512 MiB, queue disk 510 ГБ; уточнить load test;
  • healthcheck extension;
  • restart policy с backoff;
  • приложения имеют bounded non-blocking OTLP exporter queue.

Новый named volume считается потенциально root:root; основной collector не запускается от root и volume не получает 0777. Ownership init проверяется после первого create и повторного recreate.

Доступ к Docker socket запрещён. Для container metrics используется безопасный exporter/hostmetrics, а не unrestricted socket mount.

15. Security

  • OTLP receiver internal-only; при переходе между hosts — mTLS, кроме явно зафиксированного plaintext SigNoz в private network;
  • remote exporter credentials least privilege;
  • Grafana/Prometheus/Loki/Tempo не публичны;
  • RBAC: viewer/operator/admin; audit доступа к logs/traces;
  • dashboards не показывают PII;
  • config/secret permissions 0400/0600;
  • dependency/image scan и SBOM;
  • защита от log injection: JSON encoding, control chars, bounded field lengths;
  • telemetry input не исполняет expressions из пользовательских значений;
  • регулярная secret-canary проверка и incident deletion procedure.

16. Общие runbooks

Collector not-ready

  1. docker compose ps otel-collector и bounded logs.
  2. Проверить config validation, memory/OOM, queue volume.
  3. Проверить DNS/TLS/auth remote exporter.
  4. Не рестартовать бесконечно при полной queue; сначала освободить/расширить безопасно.
  5. Бизнес-сервисы оставить работающими; подтвердить local JSON logs.
  6. После восстановления проверить drain и gap.

Telemetry отсутствует у одного сервиса

  1. Проверить service.name, endpoint/protocol и сеть observability.
  2. Проверить SDK queue/drop counters и clock.
  3. Отправить synthetic request с X-Request-ID.
  4. Найти его в stdout, Collector accepted и backend.
  5. Проверить sampling/filter/redaction rules.

Remote backend outage

  1. Подтвердить exporter errors, а не application outage.
  2. Оценить queue fill rate/time-to-full.
  3. Ограничить debug exporter; не включать verbose.
  4. При длительном outage увеличить sampling только через reviewed config.
  5. После восстановления подтвердить drain и создать incident note о потере данных.

Cardinality/ingest spike

  1. Найти новое metric/log attribute по release annotation.
  2. Отключить offending instrument/filter в Collector.
  3. Проверить raw path/id/user/session labels.
  4. Rollback instrumentation при риске стоимости/доступности.
  5. Добавить CI regression test.

Логи содержат секрет/PII

  1. Ограничить доступ и остановить offending export.
  2. Сохранить только incident metadata, не копировать значение.
  3. Ротировать скомпрометированный secret.
  4. Удалить данные по процедуре backend/provider.
  5. Исправить source redaction + Collector defense; добавить canary test.

Разбор высокой latency сообщения — в спецификации VM, которая владеет соответствующим hop.

17. Общий Definition of Done

  • Collector config проходит validate и запускается в root Compose каждой VM;
  • OTLP gRPC и HTTP принимают три сигнала;
  • все сервисы имеют правильные resource attributes из реестра §4;
  • request проходит nginx/API/Safety/Open Lines с одним request_id и связанным trace;
  • ux_session_id есть только где передан и не является label;
  • remote outage, queue full, Collector restart и backend recovery rehearsed;
  • local profile, если включён, имеет volumes/retention/auth и не публикует порты;
  • secret/PII canary отсутствует в logs/traces/metrics;
  • cardinality и sampling tests проходят;
  • SLO queries воспроизводимы и исключения документированы;
  • runbooks связаны с alerts;
  • dashboards и alerts provisioned из versioned files для SigNoz; до полного provisioning это остаётся acceptance/TBD, а не выполненный production DoD.

Профильный DoD VM дополняет этот список своими сервисами и не переопределяет контракт.

18. Допущения, TBD и конфликты

Решения

  • O1: обязательный архитектурный минимум — local Collector на каждой application VM; выбран self-hosted SigNoz на отдельной VM 192.168.0.5, доступный по приватному OTLP gRPC.
  • O2: Prometheus/Grafana/Loki/Tempo — отдельный operable profile, не скрытая обязательная нагрузка основной VM.
  • O3: JSON stdout — аварийный локальный buffer; audit App DB — durable.
  • O4: telemetry fail-open для business path, но потеря telemetry alertится.
  • O5: ID/PII не labels; source redaction обязательна до Collector.

Поля JSON, resource attributes, redaction, sampling, service.namespace и адрес SigNoz меняются только здесь.

TBD

  • O-TBD1 закрыт: self-hosted SigNoz, 192.168.0.5:4317, plaintext только внутри доверенной приватной сети; UI через SSH jump host.
  • O-TBD2: утвердить SLO/RPS/error-budget с product owner.
  • O-TBD3: legal retention/erasure и допустимость IP/user-agent.
  • O-TBD4: точные sampling и resource limits после load test.
  • O-TBD5: поддерживаемый nginx OTEL module и Keycloak native tracing по pinned versions.
  • O-TBD6: нужен ли local observability profile в первой VM — решает спецификация ВМ1.

Обнаруженные архитектурные конфликты

  1. arch-03 разрешает stdout/platform exporter как минимум, но production-like расследования и alerts без backend ограничены. Закрыто выбором SigNoz (O1 / O-TBD1); stdout остаётся аварийным buffer.
  2. Test-only режимы Message Safety не входят в production SLO. Production dashboards используют canonical 403, sticky verdict и фактический processing_mode; значение stub считается ошибкой cutover. Детали — спецификация ВМ2.
  3. Queue/CRM SLI включаются только после module-07 preflight/cutover и отражают фактическое состояние bitrix-sync на ВМ2; синтетический CRM success запрещён. Детали — спецификация ВМ2.
  4. Retention, RPO/RTO и production SLO открыты в module-01/04/06/08; значения этого документа являются initial ops policy, не закрывают legal/product TBD.
  5. Observability env (OTEL_REMOTE_*, service names, sampling/queue limits) добавлены в arch-04 и .env.example; sampling/queue limits уточняются после load test.

19. Ссылки