@verdeect/kit 0.0.0-stage → 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/README.md +804 -2
  3. package/alerts/verdeect-kit.rules.yml +133 -0
  4. package/dist/cli/commands/crypto.d.ts +9 -0
  5. package/dist/cli/commands/crypto.js +87 -0
  6. package/dist/cli/commands/db.d.ts +11 -0
  7. package/dist/cli/commands/db.js +151 -0
  8. package/dist/cli/commands/openapi.d.ts +9 -0
  9. package/dist/cli/commands/openapi.js +144 -0
  10. package/dist/cli/commands/rabbitmq.d.ts +11 -0
  11. package/dist/cli/commands/rabbitmq.js +124 -0
  12. package/dist/cli/commands/redis.d.ts +11 -0
  13. package/dist/cli/commands/redis.js +119 -0
  14. package/dist/cli/main.d.ts +2 -0
  15. package/dist/cli/main.js +31 -0
  16. package/dist/config/cli-schemas.d.ts +29 -0
  17. package/dist/config/cli-schemas.js +15 -0
  18. package/dist/config/define-env.d.ts +21 -0
  19. package/dist/config/define-env.js +43 -0
  20. package/dist/config/fragments.d.ts +105 -0
  21. package/dist/config/fragments.js +86 -0
  22. package/dist/config/helpers.d.ts +26 -0
  23. package/dist/config/helpers.js +62 -0
  24. package/dist/config/index.d.ts +7 -0
  25. package/dist/config/index.js +7 -0
  26. package/dist/config/kit-config.module.d.ts +20 -0
  27. package/dist/config/kit-config.module.js +23 -0
  28. package/dist/config/parse-env.d.ts +14 -0
  29. package/dist/config/parse-env.js +28 -0
  30. package/dist/crypto/cipher.d.ts +61 -0
  31. package/dist/crypto/cipher.js +136 -0
  32. package/dist/crypto/index.d.ts +2 -0
  33. package/dist/crypto/index.js +2 -0
  34. package/dist/database/batches.d.ts +42 -0
  35. package/dist/database/batches.js +49 -0
  36. package/dist/database/db.d.ts +93 -0
  37. package/dist/database/db.js +234 -0
  38. package/dist/database/if-newer.d.ts +9 -0
  39. package/dist/database/if-newer.js +15 -0
  40. package/dist/database/index.d.ts +17 -0
  41. package/dist/database/index.js +13 -0
  42. package/dist/database/kit-database.module.d.ts +47 -0
  43. package/dist/database/kit-database.module.js +181 -0
  44. package/dist/database/migrations.d.ts +42 -0
  45. package/dist/database/migrations.js +142 -0
  46. package/dist/database/pg.d.ts +20 -0
  47. package/dist/database/pg.js +19 -0
  48. package/dist/database/prepare-database.d.ts +39 -0
  49. package/dist/database/prepare-database.js +75 -0
  50. package/dist/database/run-exclusive.d.ts +19 -0
  51. package/dist/database/run-exclusive.js +62 -0
  52. package/dist/database/tenant.d.ts +34 -0
  53. package/dist/database/tenant.js +28 -0
  54. package/dist/http/api/api.decorator.d.ts +18 -0
  55. package/dist/http/api/api.decorator.js +9 -0
  56. package/dist/http/api/openapi-document.d.ts +40 -0
  57. package/dist/http/api/openapi-document.js +452 -0
  58. package/dist/http/bootstrap-service.d.ts +33 -0
  59. package/dist/http/bootstrap-service.js +107 -0
  60. package/dist/http/create-http-app.d.ts +38 -0
  61. package/dist/http/create-http-app.js +137 -0
  62. package/dist/http/errors.d.ts +118 -0
  63. package/dist/http/errors.js +94 -0
  64. package/dist/http/index.d.ts +12 -0
  65. package/dist/http/index.js +8 -0
  66. package/dist/http/kit-exception.filter.d.ts +18 -0
  67. package/dist/http/kit-exception.filter.js +151 -0
  68. package/dist/http/kit-http-core.module.d.ts +19 -0
  69. package/dist/http/kit-http-core.module.js +122 -0
  70. package/dist/http/pagination.d.ts +30 -0
  71. package/dist/http/pagination.js +73 -0
  72. package/dist/http/zod-validation.pipe.d.ts +15 -0
  73. package/dist/http/zod-validation.pipe.js +47 -0
  74. package/dist/idempotency/idempotency.interceptor.d.ts +55 -0
  75. package/dist/idempotency/idempotency.interceptor.js +317 -0
  76. package/dist/idempotency/idempotent.decorator.d.ts +7 -0
  77. package/dist/idempotency/idempotent.decorator.js +16 -0
  78. package/dist/idempotency/index.d.ts +7 -0
  79. package/dist/idempotency/index.js +6 -0
  80. package/dist/idempotency/kit-idempotency.module.d.ts +47 -0
  81. package/dist/idempotency/kit-idempotency.module.js +173 -0
  82. package/dist/idempotency/peer.d.ts +1 -0
  83. package/dist/idempotency/peer.js +4 -0
  84. package/dist/idempotency/table.d.ts +203 -0
  85. package/dist/idempotency/table.js +86 -0
  86. package/dist/internal/cleanup-result.d.ts +7 -0
  87. package/dist/internal/cleanup-result.js +12 -0
  88. package/dist/internal/ids.d.ts +13 -0
  89. package/dist/internal/ids.js +41 -0
  90. package/dist/internal/metadata.d.ts +12 -0
  91. package/dist/internal/metadata.js +3 -0
  92. package/dist/internal/outbox-policy.d.ts +8 -0
  93. package/dist/internal/outbox-policy.js +10 -0
  94. package/dist/internal/peer.d.ts +16 -0
  95. package/dist/internal/peer.js +56 -0
  96. package/dist/internal/pg-errors.d.ts +21 -0
  97. package/dist/internal/pg-errors.js +115 -0
  98. package/dist/internal/preparsed-env.d.ts +4 -0
  99. package/dist/internal/preparsed-env.js +14 -0
  100. package/dist/internal/rabbitmq-definitions.d.ts +85 -0
  101. package/dist/internal/rabbitmq-definitions.js +73 -0
  102. package/dist/internal/redis-acl.d.ts +21 -0
  103. package/dist/internal/redis-acl.js +30 -0
  104. package/dist/internal/service-name.d.ts +4 -0
  105. package/dist/internal/service-name.js +10 -0
  106. package/dist/internal/sql-identifier.d.ts +5 -0
  107. package/dist/internal/sql-identifier.js +12 -0
  108. package/dist/internal/tokens.d.ts +10 -0
  109. package/dist/internal/tokens.js +12 -0
  110. package/dist/internal/tx-context.d.ts +5 -0
  111. package/dist/internal/tx-context.js +9 -0
  112. package/dist/messaging/cleanup.d.ts +49 -0
  113. package/dist/messaging/cleanup.js +129 -0
  114. package/dist/messaging/config.d.ts +43 -0
  115. package/dist/messaging/config.js +8 -0
  116. package/dist/messaging/define-event.d.ts +29 -0
  117. package/dist/messaging/define-event.js +38 -0
  118. package/dist/messaging/envelope.d.ts +66 -0
  119. package/dist/messaging/envelope.js +49 -0
  120. package/dist/messaging/errors.d.ts +45 -0
  121. package/dist/messaging/errors.js +63 -0
  122. package/dist/messaging/inbox.d.ts +4 -0
  123. package/dist/messaging/inbox.js +9 -0
  124. package/dist/messaging/index.d.ts +13 -0
  125. package/dist/messaging/index.js +10 -0
  126. package/dist/messaging/kit-messaging.module.d.ts +39 -0
  127. package/dist/messaging/kit-messaging.module.js +309 -0
  128. package/dist/messaging/outbox-relay.d.ts +67 -0
  129. package/dist/messaging/outbox-relay.js +260 -0
  130. package/dist/messaging/outbox-store.d.ts +75 -0
  131. package/dist/messaging/outbox-store.js +126 -0
  132. package/dist/messaging/peer.d.ts +1 -0
  133. package/dist/messaging/peer.js +5 -0
  134. package/dist/messaging/rabbit-connection.d.ts +144 -0
  135. package/dist/messaging/rabbit-connection.js +472 -0
  136. package/dist/messaging/redelivery.d.ts +6 -0
  137. package/dist/messaging/redelivery.js +17 -0
  138. package/dist/messaging/subscriber.d.ts +102 -0
  139. package/dist/messaging/subscriber.js +412 -0
  140. package/dist/messaging/tables.d.ts +315 -0
  141. package/dist/messaging/tables.js +72 -0
  142. package/dist/messaging/topology.d.ts +56 -0
  143. package/dist/messaging/topology.js +56 -0
  144. package/dist/observability/fail-startup.d.ts +14 -0
  145. package/dist/observability/fail-startup.js +51 -0
  146. package/dist/observability/health-registry.d.ts +34 -0
  147. package/dist/observability/health-registry.js +81 -0
  148. package/dist/observability/index.d.ts +16 -0
  149. package/dist/observability/index.js +10 -0
  150. package/dist/observability/lifecycle.d.ts +52 -0
  151. package/dist/observability/lifecycle.js +151 -0
  152. package/dist/observability/logger-options.d.ts +54 -0
  153. package/dist/observability/logger-options.js +91 -0
  154. package/dist/observability/metrics-server.d.ts +33 -0
  155. package/dist/observability/metrics-server.js +108 -0
  156. package/dist/observability/metrics.d.ts +30 -0
  157. package/dist/observability/metrics.js +53 -0
  158. package/dist/observability/redaction.d.ts +23 -0
  159. package/dist/observability/redaction.js +65 -0
  160. package/dist/observability/sanitize-error.d.ts +47 -0
  161. package/dist/observability/sanitize-error.js +194 -0
  162. package/dist/observability/sentry.d.ts +64 -0
  163. package/dist/observability/sentry.js +233 -0
  164. package/dist/redis/channels.d.ts +34 -0
  165. package/dist/redis/channels.js +128 -0
  166. package/dist/redis/client.d.ts +42 -0
  167. package/dist/redis/client.js +85 -0
  168. package/dist/redis/index.d.ts +7 -0
  169. package/dist/redis/index.js +7 -0
  170. package/dist/redis/kit-redis.module.d.ts +18 -0
  171. package/dist/redis/kit-redis.module.js +131 -0
  172. package/dist/redis/peer.d.ts +1 -0
  173. package/dist/redis/peer.js +4 -0
  174. package/dist/redis/rate-limiter.d.ts +49 -0
  175. package/dist/redis/rate-limiter.js +139 -0
  176. package/dist/testing/count-queries.d.ts +30 -0
  177. package/dist/testing/count-queries.js +58 -0
  178. package/dist/testing/create-test-app.d.ts +26 -0
  179. package/dist/testing/create-test-app.js +32 -0
  180. package/dist/testing/expect-matches-api.d.ts +8 -0
  181. package/dist/testing/expect-matches-api.js +49 -0
  182. package/dist/testing/expect-problem.d.ts +24 -0
  183. package/dist/testing/expect-problem.js +23 -0
  184. package/dist/testing/images.d.ts +10 -0
  185. package/dist/testing/images.js +14 -0
  186. package/dist/testing/index.d.ts +23 -0
  187. package/dist/testing/index.js +17 -0
  188. package/dist/testing/launch-command.d.ts +52 -0
  189. package/dist/testing/launch-command.js +510 -0
  190. package/dist/testing/outbox-coverage.d.ts +26 -0
  191. package/dist/testing/outbox-coverage.js +98 -0
  192. package/dist/testing/rabbitmq-admin.d.ts +81 -0
  193. package/dist/testing/rabbitmq-admin.js +146 -0
  194. package/dist/testing/redis-worker.d.ts +10 -0
  195. package/dist/testing/redis-worker.js +15 -0
  196. package/dist/testing/repo-conventions.d.ts +10 -0
  197. package/dist/testing/repo-conventions.js +524 -0
  198. package/dist/testing/repo-files.d.ts +113 -0
  199. package/dist/testing/repo-files.js +401 -0
  200. package/dist/testing/scratch-database.d.ts +19 -0
  201. package/dist/testing/scratch-database.js +75 -0
  202. package/dist/testing/start-test-stack.d.ts +85 -0
  203. package/dist/testing/start-test-stack.js +342 -0
  204. package/dist/testing/tcp-proxy.d.ts +40 -0
  205. package/dist/testing/tcp-proxy.js +164 -0
  206. package/dist/testing/tenant-isolation.d.ts +31 -0
  207. package/dist/testing/tenant-isolation.js +205 -0
  208. package/dist/testing/test-events.d.ts +37 -0
  209. package/dist/testing/test-events.js +150 -0
  210. package/dist/testing/timeout-scale.d.ts +4 -0
  211. package/dist/testing/timeout-scale.js +17 -0
  212. package/dist/testing/timing-guard.d.ts +22 -0
  213. package/dist/testing/timing-guard.js +54 -0
  214. package/dist/testing/worker-scope.d.ts +31 -0
  215. package/dist/testing/worker-scope.js +68 -0
  216. package/package.json +177 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,132 @@
1
+ # Changelog
2
+
3
+ Все заметные изменения `@verdeect/kit`. Формат — [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/), версии — [Semantic Versioning](https://semver.org/lang/ru/). У мажорной версии есть раздел «Как перейти» (NFR-5).
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [1.0.0-rc.1] - 2026-11-12
8
+
9
+ Первый выпуск: подпути `/config` и `/testing` (этап E1, PRD v1.7), `/observability` (этап E2, PRD v1.11), `/http` и CLI `verdeect-kit` (этап E3, PRD v1.13), `/database`, `/idempotency` и CLI `db` (этап E4, PRD v1.14), `/messaging` и CLI `rabbitmq` (этап E5, PRD v1.14), `/crypto` и CLI `crypto` (этап E7, PRD v1.16), `/redis` и CLI `redis` (этап E8, PRD v1.17).
10
+
11
+ ### Added
12
+
13
+ - `/config`: фрагменты окружения `envBase`, `envDatabase`, `envMessaging`, `envRedis`, `envSentry`, `envCrypto`, `envServiceUrls`.
14
+ - `/config`: `defineEnv` — схема окружения сервиса; несовместимое переопределение ключа пакета — ошибка компиляции.
15
+ - `/config`: `withBaseChecks` — `PORT` ≠ `METRICS_PORT` (кроме 0), `SHUTDOWN_DRAIN_MS` < `SHUTDOWN_TIMEOUT_MS`.
16
+ - `/config`: `parseEnv` и `InvalidEnvironmentError` — полные пути ключей через точку, без значений.
17
+ - `/config`: `KitConfigModule.forRoot({schema})` — обёртка над `ConfigModule` из `@nestjs/config`.
18
+ - `/config`: схемы CLI `migrateEnvSchema`, `prepareEnvSchema`.
19
+ - `/config`: помощники `port`, `positiveInt`, `optionalText`, `booleanFlag`, `jsonValue`, `httpUrl`, `uniqueBy`.
20
+ - `/config`: типы `KitBaseEnv`, `KitDatabaseEnv`, `KitMessagingEnv`, `KitRedisEnv`, `KitCryptoEnv`.
21
+ - `/testing`: `TEST_IMAGES` — PostgreSQL 17.11, Redis 7.4.11, RabbitMQ 4.3.6, mailpit 1.31.6, MinIO RELEASE.2026-08-04.
22
+ - `/testing`: `startTestStack` — контейнеры `postgres`, `mailpit`, `minio` раз на прогон, адреса через `provide`.
23
+ - `/testing`: `assertRepoConventions` — правила `test-images`, `replica-id`, `stop-grace-period`, `env-keys`, `peer-versions`, `instrument-import`, `command-unrecognized`, `redaction-imports`.
24
+ - `/testing`: `assertRepoConventions` — правило команды «на запрет» (PRD v1.11): у приложения обязателен распознанный запуск; `main.*` в аргументах любой команды, вызов оболочки с `-c` без выделенного скрипта, опция `tini`/`dumb-init` вне списка, переменная без умолчания на месте программы, опций `node` или файла входа — `command-unrecognized`; длинные опции и `-O`/`+O` оболочки поддержаны.
25
+ - `/testing`: `tcpProxy` и тип `TcpProxy` — обрывы и задержки TCP.
26
+ - `/testing`: `timingGuard` — `globalSetup` замеров времени.
27
+ - `/testing`: `TEST_TIMEOUT_SCALE` — множитель тайм-аутов тестов.
28
+ - `/observability`: `SENSITIVE_KEYS` и тип `KitRedaction` — общий список имён для логов и GlitchTip, `sensitiveKeys` дополняют базовый список, `maskPath` — маска пути.
29
+ - `/observability`: `createLoggerOptions` и типы `KitLoggerOptions`, `KitLoggerParams` — опции `nestjs-pino`: `base: {service, entry, replica}`, trace-id из `traceparent` (`trustTraceparent: false` — новый), `/ok` вне журнала доступа, `quietRoutes` на `debug`, путь без query.
30
+ - `/observability`: `sanitizeError`, `registerErrorSanitizer` — ветки pg/Drizzle и ioredis по форме объекта, цепочка `cause` до 10, ветки сервиса.
31
+ - `/observability`: `initSentry` и тип `KitSentryOptions` — GlitchTip только при `SENTRY_DSN` и `NODE_ENV = production`, `dataCollection: NO_PERSONAL_DATA`, `tracesSampleRate: 0`, скраббер событий; неверный `SENTRY_*` — выключен без исключения.
32
+ - `/observability`: `captureError` (одно событие на ошибку), `captureThrottled` (одно событие за окно на ключ).
33
+ - `/observability`: `HealthRegistry` и типы `HealthProbe`, `HealthReport` — пробы `/health` со сроком 2 с, `critical`, 503 с начала остановки.
34
+ - `/observability`: `MetricsServer` — `/health` и `/metrics` на `METRICS_PORT` (`node:http`); ошибка прослушивания — отказ `listen()`.
35
+ - `/observability`: `kitMetrics` и тип `KitMetrics` — реестр на экземпляр с меткой `service`, метрики процесса Node, `verdeect_outbox_pending`, `verdeect_outbox_lag_seconds`, `verdeect_events_consumed_total`, `verdeect_db_pool_wait_timeouts_total`, `verdeect_rate_limit_unavailable_total`.
36
+ - `/observability`: `alertRulesTemplate` — путь к шаблону правил vmalert.
37
+ - `/observability`: `failStartup` и интерфейс `StartupFailure` — `fatal`-лог, событие GlitchTip с ожиданием до 2 с, `exit(1)`.
38
+ - `/observability`: `KitLifecycle` и типы `KitShutdownParticipant`, `KitShutdownStep` — остановка по шагам 1–5; по сигналу — сторож `SHUTDOWN_TIMEOUT_MS` (`SHUTDOWN_TIMEOUT`, `SHUTDOWN_NOT_EXITED`, `exit(1)`), программный `close()` — без сторожа и `exit`.
39
+ - `/http`: `bootstrapService` и тип `KitBootstrapOptions` — точка входа `main.ts`: окружение до создания приложения (ошибка — `failStartup`, порт не открывается), логгер, `warn` `SENTRY_NOT_PRELOADED`, сервер метрик (шаг 5), `KitLifecycle.listen()`, `PORT` на `0.0.0.0`; опции по роли `logger.trustTraceparent`, `logger.quietRoutes`, `http.bodyLimit`, `redaction`; имя сервиса вне формата — отказ запуска.
40
+ - `/http`: `createHttpApp` и тип `KitHttpAppOptions` — Fastify-приложение Nest: `nosniff`, `Referrer-Policy: no-referrer`, trace-id, `GET /ok`, фильтр ошибок, 404 `ROUTE_NOT_FOUND`; участники остановки `http` (шаг 2) и `nest` (шаг 3), `app.close()` = `lifecycle.close()`; модули сервиса внедряют `KitLifecycle` и `HealthRegistry`.
41
+ - `/http`: `kitErrors`, `defineErrors` и типы `KitErrorDictionary`, `KitErrorEntry` — словарь кодов на процесс; код пакета с другим статусом — ошибка компиляции, тот же код с другим статусом — ошибка при определении. Коды пакета: `UNAUTHENTICATED` 401, `FORBIDDEN` 403, `VALIDATION_FAILED` 422, `BAD_REQUEST` 400, `PAYLOAD_TOO_LARGE` 413, `UNSUPPORTED_MEDIA_TYPE` 415, `ROUTE_NOT_FOUND` 404, `VERSION_CONFLICT` 409, `RATE_LIMITED` 429, `INTERNAL_ERROR` 500, `SERVICE_UNAVAILABLE` 503, `SERVICE_STOPPING` 503, `PLATFORM_UNAVAILABLE` 503, `IDEMPOTENCY_KEY_REUSED` 422, `IDEMPOTENCY_IN_PROGRESS` 409, `IDEMPOTENCY_KEY_REQUIRED` 400.
42
+ - `/http`: `DomainError` — ошибка домена со статусом из словаря и `{cause}`; незарегистрированный код — 500 `INTERNAL_ERROR` и событие GlitchTip.
43
+ - `/http`: `KitExceptionFilter` — `{error: {code, message, details}}`; тело guard'ов `@verdeect/auth` без изменений; срок пула БД — 503 `SERVICE_UNAVAILABLE` + `Retry-After: 1`, метрика, `captureThrottled`; `HttpException` без тела 400/401/403/404/413/415/429 — код по статусу, прочие — 500.
44
+ - `/http`: `ZodValidationPipe` — 422 `VALIDATION_FAILED` с `issues: [{path, code}]` без значений.
45
+ - `/http`: keyset-пагинация `PageQuerySchema`, `pageOf`, `afterCursor`, `encodeCursor`, `decodeCursor` и тип `Page` — `limit` 100/200, неверный курсор — 422 `path: cursor`, последний ключ — уникальный.
46
+ - `/http`: `Api` и тип `KitApiOptions` — описание маршрута для OpenAPI 3.1.
47
+ - CLI `verdeect-kit` (поле `bin`): команда `openapi --out <файл> [--module <файл>#<экспорт>]` — документ по метаданным без запуска приложения, слияние `contracts/openapi.extra.json`, результат `{written, operations}`; ошибки — `{error: {code, message}}` и выход 1, коды `USAGE`, `MODULE_NOT_FOUND`, `INVALID_PACKAGE_JSON`, `INVALID_EXTRA`, `INVALID_ENVIRONMENT`, `OPENAPI_FAILED`, `UNKNOWN_COMMAND`.
48
+ - `/testing`: `createTestApp` и типы `KitTestAppOptions`, `KitTestOverride` — тот же `createHttpApp` на `Test.createTestingModule`, `overrides`.
49
+ - `/testing`: `expectProblem` и типы `KitExpectedProblem`, `KitTestResponse` — утверждение об ответе-ошибке.
50
+ - `/testing`: `expectMatchesApi` — ответ по схеме `@Api` маршрута (Ajv 2020).
51
+ - Опциональный peer `@nestjs/testing` `^12.1.0` — только для `createTestApp`, грузится при вызове; зависимость `ajv` 8.20.0 — внутренняя деталь `/testing`.
52
+ - Шаблон алертов `alerts/verdeect-kit.rules.yml` (в архиве пакета): правило на каждую метрику пакета, порог по умолчанию и переопределение `verdeect_kit_threshold:<метрика>` по `service`.
53
+ - `/database`: `KitDatabaseModule.forRoot({schema})` и тип `KitDatabaseModuleOptions` — основной пул и пул чтения (`statement_timeout` 5 с), пробы `/health` `database` и `database-read` (критичные), закрытие пулов на шаге 4; срок пула — `verdeect_db_pool_wait_timeouts_total{pool="main"|"read"}` и `captureThrottled` при ошибке получения соединения.
54
+ - `/database`: токены `DRIZZLE`, `DRIZZLE_READ` — Drizzle со схемой сервиса для запросов вне `Db`.
55
+ - `/database`: `Db` — `transaction`, `read`, `readGlobal`, `afterCommit`, `setLocal`; один `set_config('app.tenant', …, true)` на транзакцию; типы `DbTx`, `DbReader`, `AfterCommitTask`; ошибки `TenantRequiredError` (`read` без тенанта), `AfterCommitInReadOnlyError`.
56
+ - `/database`: тип `DbContext` — `{tenant, traceId, actor}`.
57
+ - `/database`: `tenantColumn`, `tenantPolicy` — строгий RLS `tenant = current_setting('app.tenant', true)` (P0).
58
+ - `/database`: `prepareDatabase` и типы `KitPrepareDatabaseOptions`, `KitPrepareDatabaseResult` — роли `<svc>_owner`, `<svc>_app` (без `CREATE`), `<svc>_directory` и схема сервиса, идемпотентно.
59
+ - `/database`: `runMigrations` и тип `KitRunMigrationsOptions` — журнал `<svc>.__migrations`, схема `drizzle` не создаётся.
60
+ - `/database`: `deleteInBatches` и типы `KitDeleteInBatchesOptions`, `KitDeleteInBatchesResult` — пачка — транзакция, остановка `Db` ждёт текущую пачку.
61
+ - `/database`: `runExclusive` — `pg_try_advisory_lock` без ожидания.
62
+ - `/database`: `occurredAtColumn`, `ifNewer` — обновление только событием новее.
63
+ - `/database`: `newId`, `ulid` — id `<prefix>_<ulid>`, префикс `^[a-z]{2,5}$`.
64
+ - `/database`: `isUniqueViolation`, `isConnectionError`, `isPoolTimeout` — реэкспорт распознавания ошибок pg по форме; `isConnectionError` узнаёт и «Client has encountered a connection error».
65
+ - `/idempotency`: `KitIdempotencyModule.forRoot({table})` и тип `KitIdempotencyModuleOptions` — интерсептор, проверка функции `idempotency_purge` при старте (нет — отказ запуска), очистка при старте и раз в час одной репликой.
66
+ - `/idempotency`: `Idempotent` и тип `KitIdempotentOptions` — `@Idempotent({required?, tenantFromBody?})`: повтор — сохранённый ответ и `Idempotent-Replayed: true`, коды `IDEMPOTENCY_*`; только с `VerdeectAuthGuard` (без принципала — 500).
67
+ - `/idempotency`: `createIdempotencyTable` и тип `KitIdempotencyTable` — таблица `idempotency_key` под RLS `IS NOT DISTINCT FROM`.
68
+ - `/idempotency`: `idempotencyPurgeSql` — текст функции очистки `SECURITY DEFINER` для миграции сервиса.
69
+ - `/observability`: аннотация алерта `VerdeectEventsDlq` — разбор `<svc>.dlq` по `x-dlq-reason`; у очередей реплики сообщение не сохраняется.
70
+ - `/observability`: метрика `verdeect_cleanup_runs_total{table, result}` в `kitMetrics` и правило алерта `VerdeectCleanupFailing` (порог `verdeect_kit_threshold:cleanup_runs`).
71
+ - `/http`: OpenAPI — `Idempotency-Key`, `Idempotent-Replayed` и ошибки 409/422/400 по метаданным `@Idempotent`.
72
+ - `/testing`: `createScratchDatabase` и тип `KitScratchDatabase` — пустая мигрированная БД из шаблона.
73
+ - `/testing`: `workerScope` и тип `KitWorkerScope` — слаг компании воркера `tenant`.
74
+ - `/testing`: `countQueries` и тип `KitCountablePool` — запросы пула за время функции.
75
+ - `/testing`: `assertStrictTenantIsolation` и тип `KitTenantIsolationOptions` — строгий RLS схемы сервиса и функция очистки.
76
+ - `/testing`: `assertAppRoleIsNotOwner` и тип `KitQueryable` — роль приложения не владелец, без `CREATE`.
77
+ - `/messaging`: `defineEvent` и типы `KitEvent`, `KitEventTenant` — определение события каталога с признаком тенанта (`'required'` по умолчанию, `'none'`), `data` без `.strict()`.
78
+ - `/messaging`: `EnvelopeSchema` и тип `Envelope` — конверт `01` §7.1; `tenant` в типе — по признаку события.
79
+ - `/messaging`: `createOutboxTable` (тип `KitOutboxTable`, опции `KitOutboxTableOptions` — `tenantNullable`) и `createInboxTable` (тип `KitInboxTable`) — таблицы outbox (политика-исключение строгой модели) и inbox.
80
+ - `/messaging`: `KitMessagingModule.forRoot({service, outbox?, subscriber?})` и тип `KitMessagingModuleOptions` — соединение RabbitMQ (пассивная проверка `verdeect.events`), relay, подписчик, очистка, проба `rabbitmq`; отказ запуска `MESSAGING_TENANT_NOT_NULLABLE` (событие `'none'` при NOT NULL `tenant`) и `MESSAGING_RETRY_TTL_MISMATCH` (другой TTL `<svc>.retry`); `pg` — только при outbox или `dedupe: 'inbox'`.
81
+ - `/messaging`: `OutboxStore` — `add(tx, Event, {subjectId, data})`: запись события в транзакции `Db` из кода (без триггеров), проверка `data` и признака тенанта; relay с подтверждениями брокера, пачкой ≤ 100 по `seq`, паузами 1 с → 5 мин, `error` + GlitchTip после 5 неудач строки.
82
+ - `/messaging`: `KitSubscriber` и типы `KitEventHandler`, `KitReplicaHandler` — `on(Event, (event, tx) => …)` с inbox в транзакции обработчика, повторами через `<svc>.retry` (5 по `x-death`), DLQ `<svc>.dlq` с `x-dlq-reason`, `prefetch` 10; `onReplica` — очередь реплики без inbox, повтора и DLQ (ошибка — `error`-лог, `captureThrottled`, `result="dlq"`); метрика `verdeect_events_consumed_total{type, result}`.
83
+ - `/messaging`: `ExpectedMessageError` (повтор, затем DLQ с кодом, без GlitchTip), `InvalidMessageError` (сразу DLQ с причиной, без GlitchTip) и `MessagingStartupError` — отказ запуска с кодом `MESSAGING_TENANT_NOT_NULLABLE` или `MESSAGING_RETRY_TTL_MISMATCH`.
84
+ - `/messaging`: очистка опубликованного outbox и inbox старше 7 дней раз в час одной репликой — метрика `verdeect_cleanup_runs_total{table: outbox|inbox}`.
85
+ - `/testing`: `startTestStack({rabbitmq: true})` — RabbitMQ с `definitions.json`, vhost и пользователь на воркер, удаление в teardown; ключи `inject` `kitRabbitmqUrl`, `kitRabbitmqManagementUrl`, `kitRabbitmqWorkers`; `workerScope().rabbitmq` — `{vhost, url}`.
86
+ - `/testing`: `startTestStack({outboxEvents})` и ключ `inject` `kitOutboxCoverageDir` — покрытие outbox прогона.
87
+ - CLI `verdeect-kit rabbitmq definitions --services <svc,…> [--out <файл>]` — `definitions.json` с хешами паролей из `RABBITMQ_PASSWORD_HASH_<SVC>`; коды ошибок `USAGE`, `INVALID_ENVIRONMENT`.
88
+ - `/testing`: `expectOutbox`, `assertOutboxCoverage` — проверка записи события в транзакции и покрытие событий за прогон (`startTestStack({outboxEvents})`, `KIT_OUTBOX_COVERAGE=1`).
89
+ - `/testing`: `publishTestEvent`, `waitForInbox` — публикация конверта в vhost воркера и ожидание обработки подписчиком без `sleep`.
90
+ - `/testing`: ключи `inject` `kitDatabaseUrl`, `kitDatabaseOwnerUrl`, `kitDatabaseAdminUrl`, `kitDatabaseService`, `kitDatabaseTemplate`.
91
+ - CLI `verdeect-kit db`: `prepare --service <svc>`, `migrate --folder <путь> --schema <svc>`, `move-journal --from <схема> --to <svc>`; коды ошибок `USAGE`, `INVALID_ENVIRONMENT`, `DATABASE_UNAVAILABLE`, `DB_COMMAND_FAILED`.
92
+ - `/crypto`: `createCipher` и типы `KitCipher`, `KitCipherOptions` — AES-256-GCM, ключ HKDF-SHA256 (`info = verdeect-<svc>:<purpose>`), значение `v<N>:<iv>:<ct>:<tag>` base64url, обязательный `aad`, `needsReencrypt`; `keys` проверяются схемой `ENCRYPTION_KEYS`.
93
+ - `/crypto`: `DecryptError` и тип `DecryptErrorReason` — `'format' | 'unknown_version' | 'auth'` без открытого текста и ключей.
94
+ - `/crypto`: `generateSecret(bytes = 32)` — секрет base64url без `=` (не меньше 32 байт).
95
+ - CLI `verdeect-kit crypto generate-secret [--bytes N]` — `{"secret":"…"}` в stdout; код ошибки `USAGE`.
96
+ - `/redis`: `KitRedisModule.forRoot({service, subscriber?: true})` и `KitRedisModuleOptions` — `keyPrefix <svc>:`, подписочное соединение по `subscriber`, проба `redis` (некритичная), закрытие на шаге 4.
97
+ - `/redis`: `KIT_REDIS`, `KitRedisChannels` — основное соединение и каналы с префиксом `<svc>:`.
98
+ - `/redis`: `RateLimiter.hit/peek`, `RateLimitOptions`, `RateLimitResult` — фиксированное окно (`PEXPIRE … NX`, Redis ≥ 7.0), fail-open и `verdeect_rate_limit_unavailable_total`.
99
+ - `/redis`: `throwRateLimited` — 429 `RATE_LIMITED` + `Retry-After` (секунды вверх).
100
+ - `/testing`: `startTestStack({redis})` с aclfile пользователя сервиса и администратором теста, `workerScope().redisPrefix`, `redisWorkerOverride`, ключи `provide` `kitRedisUrl`, `kitRedisAdminUrl`, `kitRedisService`.
101
+ - CLI `verdeect-kit redis acl --services <svc,…> --out <файл>` — aclfile (`user default off`, хеши sha256 из `REDIS_PASSWORD_HASH_<SVC>`); коды ошибок `USAGE`, `INVALID_ENVIRONMENT`.
102
+
103
+ ### Changed
104
+
105
+ - `/http`: `KitExceptionFilter` ставит `Retry-After` для `RATE_LIMITED` по `details.retryAfterSec` (E8).
106
+ - `/testing`: `countQueries(pool, fn, {onQuery})` и тип `KitCountQueriesOptions` — колбэк на каждый запрос пула (сигнал без пауз в тесте).
107
+ - `/database`: `Db` связывает транзакцию с её `DbContext` (для `OutboxStore.add`) — без изменения API.
108
+ - `/testing`: `assertStrictTenantIsolation` проверяет политику `outbox` по `createOutboxTable` (раньше — только наличие политики).
109
+ - `/testing`: `startTestStack({postgres: true})` готовит БД — `prepareDatabase`, шаблон `<svc>_template`, миграции опции `migrations` (без `postgres` — `TypeError`).
110
+ - `/http`: `KitExceptionFilter` больше не считает срок пула — `pool: 'unknown'` удалён; метрику и событие пишет пул `/database` с меткой `main`/`read`, фильтр отвечает 503 `SERVICE_UNAVAILABLE` + `Retry-After: 1`.
111
+ - `KitConfigModule.forRoot({schema})` разбирает окружение при сборке контекста, а не при импорте `AppModule`: неверное окружение отклоняет сборку контекста, сам `forRoot` не отклоняется. Умолчания в `process.env` не дописываются, `ConfigService` читает только разобранные значения. При запуске через `bootstrapService` окружение не разбирается повторно.
112
+ - Обязательный peer `prom-client` заменён на `@prometheus-io/client` `^0.16.1` (`prom-client` помечен deprecated, преемник — тот же API; PRD v1.12, NFR-3): `kitMetrics` и `MetricsServer` работают на `Registry`, `Counter`, `Gauge` из `@prometheus-io/client`. Сервис ставит `@prometheus-io/client` вместо `prom-client`.
113
+
114
+ ### Fixed
115
+
116
+ - CLI `verdeect-kit`: команды грузят для логгера только `config/fragments` и `observability/logger-options`, а не точки входа `/config` и `/observability` (без `@nestjs/*`, `nestjs-pino`, `@sentry/nestjs`): холодный запуск команды ~0,3 с вместо ~2,5 с; поведение и вывод не меняются (KT-31).
117
+ - `/redis`: `KitRedisChannels.subscribe` — после отказа `SUBSCRIBE` (NOPERM, срок, обрыв) обработчик не остаётся в подписке, повторный `subscribe` снова шлёт `SUBSCRIBE`; одновременные `subscribe` на канал ждут одного подтверждения и вместе отклоняются при его ошибке (KT-31).
118
+ - `/database`: `Db.setLocal` отвергает служебную `app.tenant` (`TypeError`) — тенант задаётся только `DbContext` в `transaction`/`read` (KT-22 п. 1).
119
+ - `/database`: `Db.afterCommit` с транзакцией другого `Db` или вложенной — `AfterCommitOutsideTransactionError` вместо молчаливой потери задачи (KT-22 п. 2).
120
+ - `/idempotency`: ответ пишет только попытка, захватившая строку, — колонка `attempt` в `createIdempotencyTable`; долгий первый запрос не затирает ответ перехватившего повтора, `warn` без ключа и тела (KT-22 п. 3). Сервису — миграция `drizzle-kit` с новой колонкой.
121
+ - `/database`: `runExclusive` передаёт в `fn` соединение блокировки, `deleteInBatches` — опция `connection`; очистка идемпотентности идёт на соединении блокировки и работает при `DB_POOL_MAX = 1` (KT-22 п. 4).
122
+ - `/idempotency`: проход очистки, прерванный остановкой, — `verdeect_cleanup_runs_total{result="interrupted"}` вместо `ok`; алерт `VerdeectCleanupFailing` его не учитывает (KT-22 п. 5).
123
+ - CLI `db`: `sqlState` ищется по цепочке `cause` (до 10 уровней) — код pg внутри `DrizzleQueryError` больше не теряется; системные коды Node (`EPIPE`) в `sqlState` не попадают (KT-22 п. 6).
124
+ - `/testing`: `assertStrictTenantIsolation` проверяет функцию очистки по точной сигнатуре `idempotency_purge(integer)`; другая перегрузка без нужной — «функции нет» (KT-22 п. 7).
125
+ - Тесты `/database` и `/idempotency` уровня I — без реальных пауз: сигналы входа в обработчик, события `acquire` пула и шлагбаумы вместо `setTimeout` и опроса (KT-22 п. 8).
126
+ - `/testing`: `publishTestEvent` после обрыва соединения или закрытия канала открывает новое соединение при следующем вызове (раньше переиспользовал закрытый канал); неудачное подключение не запоминается.
127
+ - `/testing`: `publishTestEvent` закрывает соединение, если после `connect()` не открылся confirm-канал, — повторные неудачные вызовы не копят открытых соединений (KT-24 п. 1).
128
+ - `/database`: `runExclusive` сбрасывает сеанс соединения блокировки (`RESET ALL`) перед возвратом в пул; TSDoc запрещает `SET` и `set_config(…, false)` внутри `fn`.
129
+ - `/http`: OpenAPI — у маршрутов с `@RequireTenant()` ответ 409 `TENANT_REQUIRED` (тело guard'а `@verdeect/auth`); `expectMatchesApi` проверяет описанные статусы ошибок по схеме `ErrorResponse` и падает на неописанном статусе.
130
+ - `/http`: `bootstrapService` — `SENTRY_NOT_PRELOADED` только при верной конфигурации Sentry (верный `SENTRY_DSN`, `NODE_ENV = production`); при неверном `SENTRY_*` предупреждения нет — `initSentry` выключил Sentry намеренно.
131
+ - `/testing`: `expectMatchesApi` — скомпилированная схема Ajv кэшируется по маршруту и статусу.
132
+ - `/http`: OpenAPI — маршруты с `@Api`, унаследованные от базового контроллера, попадают в документ с путём наследника; переопределённый метод — один маршрут.