feat: harden community production foundation through story 1.5

This commit is contained in:
2026-08-14 00:21:59 +03:00
parent c30461cc92
commit f6fc2e5c9b
161 changed files with 16758 additions and 2515 deletions
+81 -4
View File
@@ -2,6 +2,70 @@
Crank настраивается через переменные окружения. Один и тот же набор переменных используется при запуске из исходников и при запуске готовых Docker-образов.
<!-- BEGIN GENERATED CRANK RUNTIME CONFIG -->
| Environment | Semantic path | Process | Type/unit | Default | Bounds | Sensitivity | Mode |
|---|---|---|---|---|---|---|---|
| `CRANK_DATABASE_URL` | `database.url` | `Shared` | `url/-` | `blank` | `-` | `Secret` | `Effective` |
| `POSTGRES_HOST` | `database.host` | `Shared` | `string/-` | `postgres` | `-` | `Internal` | `Effective` |
| `POSTGRES_PORT` | `database.port` | `Shared` | `u16/port` | `5432` | `1..=65535` | `Public` | `Effective` |
| `POSTGRES_DB` | `database.name` | `Shared` | `string/-` | `crank` | `-` | `Internal` | `Effective` |
| `POSTGRES_USER` | `database.user` | `Shared` | `string/-` | `crank` | `-` | `Internal` | `Effective` |
| `POSTGRES_PASSWORD` | `database.password` | `Shared` | `secret/-` | `configured` | `-` | `Secret` | `Effective` |
| `POSTGRES_MAX_CONNECTIONS` | `database.pool.max_connections` | `Shared` | `u32/connections` | `20` | `1..=1024` | `Public` | `Effective` |
| `POSTGRES_MIN_CONNECTIONS` | `database.pool.min_connections` | `Shared` | `u32/connections` | `2` | `0..=1024` | `Public` | `Effective` |
| `POSTGRES_ACQUIRE_TIMEOUT_MS` | `database.pool.acquire_timeout_ms` | `Shared` | `u64/milliseconds` | `5000` | `1..=300000` | `Public` | `Effective` |
| `POSTGRES_IDLE_TIMEOUT_MS` | `database.pool.idle_timeout_ms` | `Shared` | `u64/milliseconds` | `600000` | `1000..=86400000` | `Public` | `Effective` |
| `POSTGRES_MAX_LIFETIME_MS` | `database.pool.max_lifetime_ms` | `Shared` | `u64/milliseconds` | `1800000` | `1000..=86400000` | `Public` | `Effective` |
| `CRANK_MASTER_KEY` | `runtime.master_key` | `Shared` | `secret/-` | `required/blank` | `-` | `Secret` | `Effective` |
| `CRANK_BASE_URL` | `runtime.base_url` | `Shared` | `url/-` | `blank` | `-` | `Internal` | `Effective` |
| `CRANK_RUNTIME_MAX_CONCURRENT_UNARY` | `runtime.max_concurrent_unary` | `Shared` | `u32/requests` | `64` | `1..=65535` | `Public` | `Effective` |
| `CRANK_CACHE_BACKEND` | `cache.backend` | `Shared` | `enum/-` | `memory` | `-` | `Public` | `Effective` |
| `CRANK_CACHE_URL` | `cache.url` | `Shared` | `url/-` | `blank` | `-` | `Secret` | `Effective` |
| `CRANK_CACHE_DEFAULT_TTL_MS` | `cache.default_ttl_ms` | `Shared` | `u64/milliseconds` | `blank` | `1..=86400000` | `Public` | `DeprecatedNoEffect` |
| `CRANK_OUTBOUND_ALLOWED_HOSTS` | `outbound.allowed_hosts` | `Shared` | `host_list/-` | `` | `-` | `Internal` | `Effective` |
| `CRANK_OUTBOUND_DENIED_HOSTS` | `outbound.denied_hosts` | `Shared` | `host_list/-` | `` | `-` | `Internal` | `Effective` |
| `CRANK_OUTBOUND_MAX_RESPONSE_BYTES` | `outbound.max_response_bytes` | `Shared` | `u64/bytes` | `4194304` | `1..=67108864` | `Public` | `Effective` |
| `CRANK_ENVIRONMENT` | `observability.environment` | `Shared` | `label/-` | `development` | `-` | `Public` | `Effective` |
| `CRANK_LOG_LEVEL` | `observability.log_filter` | `Shared` | `string/-` | `blank` | `-` | `Public` | `Effective` |
| `CRANK_SENTRY_DSN` | `observability.sentry_dsn` | `Shared` | `url/-` | `blank` | `-` | `Secret` | `Effective` |
| `CRANK_METRICS_ENABLED` | `observability.metrics.enabled` | `Shared` | `bool/-` | `true` | `-` | `Public` | `Effective` |
| `CRANK_METRICS_BEARER_TOKEN` | `observability.metrics.bearer_token` | `Shared` | `secret/-` | `blank` | `-` | `Secret` | `Effective` |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | `observability.otlp.endpoint` | `Shared` | `url/-` | `blank` | `-` | `Internal` | `Effective` |
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | `observability.otlp.traces_endpoint` | `Shared` | `url/-` | `blank` | `-` | `Internal` | `Effective` |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | `observability.otlp.protocol` | `Shared` | `enum/-` | `http/protobuf` | `-` | `Public` | `Effective` |
| `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` | `observability.otlp.traces_protocol` | `Shared` | `enum/-` | `blank` | `-` | `Public` | `Effective` |
| `OTEL_EXPORTER_OTLP_TIMEOUT` | `observability.otlp.timeout` | `Shared` | `duration/milliseconds` | `10000` | `1..=300000` | `Public` | `Effective` |
| `OTEL_EXPORTER_OTLP_TRACES_TIMEOUT` | `observability.otlp.traces_timeout` | `Shared` | `duration/milliseconds` | `blank` | `1..=300000` | `Public` | `Effective` |
| `OTEL_EXPORTER_OTLP_HEADERS` | `observability.otlp.headers` | `Shared` | `headers/-` | `blank` | `-` | `Secret` | `Effective` |
| `OTEL_EXPORTER_OTLP_TRACES_HEADERS` | `observability.otlp.traces_headers` | `Shared` | `headers/-` | `blank` | `-` | `Secret` | `Effective` |
| `OTEL_BSP_MAX_QUEUE_SIZE` | `observability.otlp.max_queue_size` | `Shared` | `u32/spans` | `2048` | `1..=65536` | `Public` | `Effective` |
| `OTEL_BSP_MAX_EXPORT_BATCH_SIZE` | `observability.otlp.max_export_batch_size` | `Shared` | `u32/spans` | `512` | `1..=65536` | `Public` | `Effective` |
| `OTEL_BSP_SCHEDULE_DELAY` | `observability.otlp.schedule_delay` | `Shared` | `duration/milliseconds` | `5000` | `1..=300000` | `Public` | `Effective` |
| `OTEL_BSP_EXPORT_TIMEOUT` | `observability.otlp.export_timeout` | `Shared` | `duration/milliseconds` | `30000` | `1..=300000` | `Public` | `Effective` |
| `CRANK_ADMIN_BIND` | `admin.bind` | `AdminApi` | `socket/-` | `0.0.0.0:3001` | `-` | `Internal` | `Effective` |
| `CRANK_ADMIN_METRICS_BIND` | `admin.metrics_bind` | `AdminApi` | `socket/-` | `127.0.0.1:9464` | `-` | `Internal` | `Effective` |
| `CRANK_STORAGE_ROOT` | `admin.storage_root` | `AdminApi` | `absolute_path/-` | `/var/lib/crank/storage` | `-` | `Internal` | `Effective` |
| `CRANK_ADMIN_RATE_LIMIT_RPS` | `admin.rate_limit.rps` | `AdminApi` | `u32/requests_per_second` | `30` | `1..=100000` | `Public` | `Effective` |
| `CRANK_ADMIN_RATE_LIMIT_BURST` | `admin.rate_limit.burst` | `AdminApi` | `u32/requests` | `60` | `1..=1000000` | `Public` | `Effective` |
| `CRANK_INVOCATION_LOG_RETENTION_DAYS` | `admin.invocation_log_retention_days` | `AdminApi` | `u32/days` | `30` | `1..=36500` | `Public` | `Effective` |
| `CRANK_SESSION_SECRET` | `admin.session.secret` | `AdminApi` | `secret/-` | `required/blank` | `-` | `Secret` | `Effective` |
| `CRANK_PASSWORD_PEPPER` | `admin.password_pepper` | `AdminApi` | `secret/-` | `required/blank` | `-` | `Secret` | `Effective` |
| `CRANK_SESSION_TTL_HOURS` | `admin.session.ttl_hours` | `AdminApi` | `u32/hours` | `24` | `1..=8760` | `Public` | `Effective` |
| `CRANK_TRUST_FORWARDED_HEADERS` | `admin.trust_forwarded_headers` | `AdminApi` | `bool/-` | `false` | `-` | `Public` | `Effective` |
| `CRANK_BOOTSTRAP_ADMIN_EMAIL` | `admin.bootstrap.email` | `AdminApi` | `string/-` | `required/blank` | `-` | `Internal` | `Effective` |
| `CRANK_BOOTSTRAP_ADMIN_PASSWORD` | `admin.bootstrap.password` | `AdminApi` | `secret/-` | `required/blank` | `-` | `Secret` | `Effective` |
| `CRANK_BOOTSTRAP_ADMIN_DISPLAY_NAME` | `admin.bootstrap.display_name` | `AdminApi` | `string/-` | `Crank Owner` | `-` | `Internal` | `Effective` |
| `CRANK_DEMO_SEED` | `admin.demo_seed` | `AdminApi` | `bool/-` | `false` | `-` | `Public` | `Effective` |
| `CRANK_MCP_BIND` | `mcp.bind` | `McpServer` | `socket/-` | `0.0.0.0:3002` | `-` | `Internal` | `Effective` |
| `CRANK_MCP_METRICS_BIND` | `mcp.metrics_bind` | `McpServer` | `socket/-` | `127.0.0.1:9465` | `-` | `Internal` | `Effective` |
| `CRANK_MCP_REFRESH_MS` | `mcp.refresh_ms` | `McpServer` | `u64/milliseconds` | `5000` | `100..=3600000` | `Public` | `Effective` |
| `CRANK_MCP_RATE_LIMIT_RPS` | `mcp.rate_limit.rps` | `McpServer` | `u32/requests_per_second` | `60` | `1..=100000` | `Public` | `Effective` |
| `CRANK_MCP_RATE_LIMIT_BURST` | `mcp.rate_limit.burst` | `McpServer` | `u32/requests` | `120` | `1..=1000000` | `Public` | `Effective` |
| `CRANK_RUNTIME_MAX_CONCURRENT_SESSIONS` | `runtime.max_concurrent_sessions` | `McpServer` | `u32/sessions` | `16` | `1..=65535` | `Public` | `Effective` |
<!-- END GENERATED CRANK RUNTIME CONFIG -->
## PostgreSQL
Обязательные параметры:
@@ -22,6 +86,13 @@ Crank настраивается через переменные окружен
Если используется PgBouncer, укажите его адрес в `POSTGRES_HOST` и порт в `POSTGRES_PORT`.
`CRANK_DATABASE_URL` — compatibility-форма для существующих установок. Она
содержит credentials и поэтому никогда не выводится в diagnostics или
fingerprint. URL нельзя смешивать с явно заданными `POSTGRES_HOST`,
`POSTGRES_PORT`, `POSTGRES_DB`, `POSTGRES_USER` или `POSTGRES_PASSWORD`:
конфликт останавливает startup. Для новых установок canonical-формой остаются
раздельные `POSTGRES_*` параметры.
## HTTP-сервисы
- `CRANK_ADMIN_BIND` - адрес `admin-api`, например `0.0.0.0:3001`.
@@ -79,11 +150,9 @@ Demo seed идемпотентный: повторный старт не соз
## Runtime limits
- `CRANK_RUNTIME_MAX_CONCURRENT_UNARY`
- `CRANK_RUNTIME_MAX_CONCURRENT_WINDOW`
- `CRANK_RUNTIME_MAX_CONCURRENT_SESSIONS`
- `CRANK_RUNTIME_MAX_CONCURRENT_JOBS`
Эти настройки ограничивают параллельное выполнение операций и служебных задач.
Эти настройки ограничивают параллельное выполнение unary-запросов и MCP-сессий.
## Исходящие HTTP-запросы
@@ -124,9 +193,12 @@ CRANK_CACHE_BACKEND=memory
```env
CRANK_CACHE_BACKEND=valkey
CRANK_CACHE_URL=redis://valkey:6379/0
CRANK_CACHE_DEFAULT_TTL_MS=60000
```
`CRANK_CACHE_DEFAULT_TTL_MS` в прежних шаблонах не имел runtime consumer.
Непустое значение теперь отклоняется как deprecated no-effect configuration;
TTL задаётся владельцем конкретного cache operation.
Внешний кэш используется для служебного краткоживущего состояния: rate limiting, replay guard и опубликованные каталоги MCP-инструментов.
## Логи
@@ -141,6 +213,11 @@ CRANK_CACHE_DEFAULT_TTL_MS=60000
Поля с паролями, токенами, ключами, cookie, authorization, query, полным телом
или результатом очищаются до сериализации.
`crank-migrate` использует только database-поля этого контракта. Ему не
требуются и не должны передаваться master key, session/bootstrap secrets,
runtime, metrics или OTLP configuration. Команды и recovery contract описаны
в [migrations.md](migrations.md).
Пример:
```env