34 KiB
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.
Операбельный вариант:
- приложения на каждой VM экспортируют OTLP gRPC только в свой local
otel-collector:4317; - Collector отправляет telemetry в self-hosted SigNoz на отдельной VM
192.168.0.5:4317; - JSON stdout остаётся аварийным локальным журналом Docker с rotation;
- пока удалённый backend недоступен в конкретном окружении, допустим архитектурный минимум из arch-03: bounded JSON stdout/platform logs и Collector
debugexporter с 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
otlpgRPC0.0.0.0:4317— основной internal receiver;otlpHTTP0.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:
memory_limiter: check interval 1s, soft/hard limit относительно container memory;resource: нормализуетservice.namespace=han-chat,deployment.environment,service.version;attributes: удаляет/маскирует sensitive attributes;transform: нормализует route/status/error semantic conventions;filter: исключает health noise, debug events и запрещённые поля;probabilistic_samplerили tail sampling для traces;batch: bounded batch/timeout;- при remote export —
queued_retry/sending queue иfile_storageextension.
memory_limiter не заменяется Docker OOM limit. При pressure Collector отбрасывает telemetry контролируемо и увеличивает otelcol_processor_refused_*.
3.4. Exporters
otlp/remote: endpoint из secret env/mount; для SigNoz в доверенной private network — plaintext192.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 на volumeotel-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либо canonicaldeployment.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 обязан иметь:
- Executive/SLO: availability, error budget burn, p50/p95/p99, message delivery, auth, active incidents.
- Business flow: guest config → OTP → bootstrap → session → dialog → safety → Open Lines → operator reply.
- 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 — 5–10%;
- 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 и отказоустойчивость
Контролируются:
/healthextension;- 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-queuevolume 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 root10001:10001 0700; collector зависит отservice_completed_successfully; - initial limit: 0.5 CPU/512 MiB, queue disk 5–10 ГБ; уточнить 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
docker compose ps otel-collectorи bounded logs.- Проверить config validation, memory/OOM, queue volume.
- Проверить DNS/TLS/auth remote exporter.
- Не рестартовать бесконечно при полной queue; сначала освободить/расширить безопасно.
- Бизнес-сервисы оставить работающими; подтвердить local JSON logs.
- После восстановления проверить drain и gap.
Telemetry отсутствует у одного сервиса
- Проверить
service.name, endpoint/protocol и сетьobservability. - Проверить SDK queue/drop counters и clock.
- Отправить synthetic request с
X-Request-ID. - Найти его в stdout, Collector accepted и backend.
- Проверить sampling/filter/redaction rules.
Remote backend outage
- Подтвердить exporter errors, а не application outage.
- Оценить queue fill rate/time-to-full.
- Ограничить debug exporter; не включать verbose.
- При длительном outage увеличить sampling только через reviewed config.
- После восстановления подтвердить drain и создать incident note о потере данных.
Cardinality/ingest spike
- Найти новое metric/log attribute по release annotation.
- Отключить offending instrument/filter в Collector.
- Проверить raw path/id/user/session labels.
- Rollback instrumentation при риске стоимости/доступности.
- Добавить CI regression test.
Логи содержат секрет/PII
- Ограничить доступ и остановить offending export.
- Сохранить только incident metadata, не копировать значение.
- Ротировать скомпрометированный secret.
- Удалить данные по процедуре backend/provider.
- Исправить 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.
Обнаруженные архитектурные конфликты
arch-03разрешает stdout/platform exporter как минимум, но production-like расследования и alerts без backend ограничены. Закрыто выбором SigNoz (O1 / O-TBD1); stdout остаётся аварийным buffer.- Test-only режимы Message Safety не входят в production SLO. Production dashboards используют canonical
403, sticky verdict и фактическийprocessing_mode; значениеstubсчитается ошибкой cutover. Детали — спецификация ВМ2. - Queue/CRM SLI включаются только после module-07 preflight/cutover и отражают фактическое состояние
bitrix-syncна ВМ2; синтетический CRM success запрещён. Детали — спецификация ВМ2. - Retention, RPO/RTO и production SLO открыты в module-01/04/06/08; значения этого документа являются initial ops policy, не закрывают legal/product TBD.
- Observability env (
OTEL_REMOTE_*, service names, sampling/queue limits) добавлены в arch-04 и.env.example; sampling/queue limits уточняются после load test.
19. Ссылки
- Профильные спецификации:
module-09-observability-vm1.md,module-09-observability-vm2.md. - VM/Docker logging и firewall:
arch-06-service-hosting-security.mdи профильные module-10/runbook. - Nginx stdout/access log:
arch-08-nginx.mdи профильные module-03. - HTTP/OTLP registry:
arch-02-api-contracts.md. - Compose topology:
arch-03-docker-compose-blueprint.md.