docs: split integrator guide (Diplodoc) vs internal docs + add build-docs CI

Чёткое разделение audiences:
- docs/ — consumer-facing only, Diplodoc-built. Public contract для
  интеграторов (Альтум, BI, third-party).
- docs-internal/ — operator runbooks, status snapshots, legacy tech pages.
  НЕ в Diplodoc build, НЕ публикуются.

Изменения:
- Move docs/{ops,status,tech} → docs-internal/{ops,status,tech}
- docs/toc.yaml: убраны секции Operations, Архитектура (legacy), Status
- docs/index.md: убран tab "оператор / on-call", focus на integrators
- docs/README.md: rewritten — scope только integrator guide, editorial
  guidelines (no leak internal architecture, stable API contract)
- .yfm: убран явный ignore status/* (теперь не нужно — папка переехала)
- docs-internal/README.md: index для внутренней документации с rationale
  разделения

Scrubbing implementation details из Diplodoc страниц:
- events.md: убраны Strimzi/cluster.142 references, OutboxPoller детали,
  internal alert names (OrdinisOutboxLagHigh, OrdinisOutboxDLQNonEmpty),
  metric names (nsi_outbox_*). Заменены на consumer-observable contract.
- webhooks.md: убраны metric names (nsi_webhook_ssrf_rejected_total),
  alert table (OrdinisWebhookHighFailureRate и т.д.). Retry policy
  переписана на user-side perspective.
- errors.md: убран alert name OrdinisReadApiErrorBudgetBurnFast, Tempo
  endpoint URL, internal connection details.
- x-references.md: OrphanReferenceScanner → general "Ordinis периодически
  детектирует". Убраны metric/alert names. Cascade roadmap без link на
  internal design doc.
- auth.md: убран file path ScopeContext.java.
- bundle-cuod.md: убран Maven module path.
- caching.md: cascade design link заменён на text reference.

CI:
- .gitlab-ci.yml: новый job build-docs (stage: build) — Node 20 alpine,
  pnpm install --frozen-lockfile + pnpm build, artifact docs/_dist на
  неделю. Triggers: auto на docs/**, либо manual web. Готов к follow-up
  pages-deploy job когда host решён.
- Новый pattern .docs-changes для rules.

Build verified clean: 13 HTML pages, 6.9M, no broken links/refs.
This commit is contained in:
Zimin A.N.
2026-05-07 23:27:03 +03:00
parent d5268b9395
commit bcfb07f547
23 changed files with 232 additions and 215 deletions
+28 -56
View File
@@ -12,53 +12,27 @@ Ordinis публикует все изменения справочников в
| `ordinis.cuod.events.internal` | INTERNAL | INTERNAL словари — нужна role `ordinis-internal`+. |
| `ordinis.cuod.events.restricted` | RESTRICTED | RESTRICTED — role `ordinis-restricted`. |
Topology: 1 broker (single-node на cluster.142), 3+ partitions per topic
(historical setup имел 12 partitions, при cluster recreate 2026-05-07
spec задал 3; existing topics annotated `strimzi.io/managed=false`,
broker partitions сохранены), `cleanup.policy: delete`,
`retention.ms: 604800000` (7 дней).
Параметры топиков (для consumer config):
- `cleanup.policy: delete`
- `retention.ms: 604800000` (7 дней)
- Multi-partition (точное число — спросить Ordinis team при registration,
partition count может меняться по operational reasons).
## Подключение
### Адреса bootstrap
### Bootstrap address + creds
| Среда | Bootstrap servers | Auth |
|---|---|---|
| prod | `ordinis-kafka-kafka-bootstrap.ordinis-prod:9092` (TLS+SASL: `:9093`) | SCRAM-SHA-512 |
| staging | `ordinis-kafka-kafka-bootstrap.ordinis-staging:9092` | SCRAM-SHA-512 |
Запросить у Ordinis team:
- Bootstrap servers (внутренний DNS на per-environment basis)
- SASL credentials (SCRAM-SHA-512 username + password)
- Topic ACL (Read + Describe на нужные топики)
- Consumer group prefix (для group ACL)
### Получение SASL креденшелов
Auth: **SASL/SCRAM-SHA-512**. TLS опциональный (отдельный listener).
Запросить у Ordinis team создание Kafka user (Strimzi `KafkaUser` CR):
```yaml
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaUser
metadata:
name: altum-consumer
namespace: ordinis-prod
labels:
strimzi.io/cluster: ordinis-kafka
spec:
authentication:
type: scram-sha-512
authorization:
type: simple
acls:
- resource:
type: topic
name: ordinis.cuod.events.public
patternType: literal
operations: [Read, Describe]
- resource:
type: group
name: altum-consumer-
patternType: prefix
operations: [Read]
```
Strimzi user-operator создаст Secret `altum-consumer` с полями `username`,
`password`. Используй их в Kafka client config.
Креденшелы выдаются per-consumer service. Не share между сервисами —
ACL и audit за каждым.
## Schema события
@@ -143,18 +117,17 @@ each businessKey изолирован.
## At-least-once семантика
Outbox pattern гарантирует **at-least-once** delivery:
1. Writer пишет запись в БД + outbox table в одной транзакции.
2. OutboxPoller (scheduled @1s) читает unpublished rows, отправляет в Kafka.
3. После Kafka ACK — отмечает row как published (`published_at` set).
Ordinis использует **outbox pattern** — изменение БД и публикация в Kafka
атомарны через transactional outbox. Гарантия: **at-least-once**.
Что это значит для consumer'а:
- Можешь получить **дубликат** события если poller crashed после ACK но до
`published_at` write. Idempotency у consumer'а — must.
- При network partition между Kafka и poller — сообщения накапливаются в
outbox (alert `OrdinisOutboxLagHigh` срабатывает > 100 events).
- Можешь получить **дубликат** события (rare, при partial failures на
стороне Ordinis). Idempotency у consumer'а — must.
- При недоступности Kafka события накапливаются в Ordinis side и
доставляются после восстановления — **events не теряются**.
- Order — гарантирован per partition key (`dictionary:businessKey`),
не глобально.
## Idempotency
@@ -167,13 +140,12 @@ if not seen:
redis.setex(f"ordinis:event:...", 86400, "1")
```
## DLQ (Dead-letter queue)
## Persistent failures (Ordinis side)
Если событие не публикуется > 1000 retry попыток (network issues,
Kafka unavailable) — переходит в DLQ table в Ordinis. Не теряется, но
требует ручного разбора.
Симптом: alert `OrdinisOutboxDLQNonEmpty` → check `/api/v1/admin/audit?action=outbox.dlq`.
Если событие не публикуется > 1000 retry попыток (multi-day Kafka outage),
оно складывается в DLQ внутри Ordinis. Не теряется, но требует ручного
разбора Ordinis team. Consumer не видит таких событий до их
re-publishing — но это очень редкий сценарий.
## Топик для discovery