feat(env): типизированная env-схема (контракт env-schema.1, env-catalog item 5) - #33
Merged
Conversation
…v-catalog item 5) apps/server/src/env.ts — единственная точка чтения process.env в репо: zod-реестр всех 42 переменных (типы int/bool/enum/url/duration_ms по контракту), fail-fast валидация на старте с перечислением всех невалидных переменных разом, экспорт документа env-schema.1 (repo trading-office) через `npm run env:schema` (детерминированный JSON в stdout, сортировка по name, без timestamp). VITE_* объявлены как build-time (owner_unit office-web), OFFICE_IMAGE_TAG/ULPC_DIR — declaration-only. loadConfig переведён на схему целиком (механическая замена чтений); кросс-переменные fail-closed гейты (#32 SEC-O1: connected-режим требует непустой OFFICE_OPERATOR_PASSWORD; явные TRADING_LAB_READ_URL/TOKEN и TRADING_PLATFORM_READ_URL/TOKEN) остаются в config.ts и не ослаблены — в схеме пароль описан как required:false + secret:true, потому что standalone (fixture) без него легален. Тесты (TDD): env.test.ts — типы/дефолты/агрегация ошибок/валидность и детерминизм экспорта; envCompleteness.test.ts — гейт «Полнота схемы» (process.env вне env.ts = красный CI, allowlist только для compose-lpc-agents.mjs). Экспорт прогнан через нормативный валидатор control-center (validateEnvSchemaDocument) — VALID. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`npm run env:docs` (apps/server/src/envDocs.ts) рендерит из env-схемы: корневой ENV.md (полная таблица переменных), apps/server/.env.example, apps/web/.env.example (VITE_*), deploy/.env.example (compose-подмножество). Правило секретов соблюдено: значения секретов нигде не появляются — NAME= с комментарием про SOPS/age-контур (b2c-ops-hardening item 3). envDocs.test.ts — гейт «Генерация»: рендер сравнивается с закоммиченными артефактами байт-в-байт, дрейф = красный CI (работает внутри npm test — отдельного CI-джоба не нужно). README сервера: ручная таблица переменных заменена ссылкой на ENV.md (item 7 — ручные списки удаляются); заодно поправлено устаревшее «авто- загрузки .env нет» (loadEnv.ts подхватывает apps/server/.env c #24). ROADMAP: зафиксирована офисная часть env-catalog item 5. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Свежая установка TS в CI (noUncheckedIndexedAccess по строгому разрешению) ругалась на m[1] из matchAll, enum_values[0] и прямой каст EnvSchemaVariable → Record — поправлено без изменения смысла тестов. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что сделано
Офисная часть item 5 инициативы env-catalog (контракт — control-center
docs/architecture/contracts/env-schema.md+scripts/src/contracts/env-schema-1.schema.json, PR cc#131).apps/server/src/env.ts— единственная точка чтенияprocess.envв репо: zod-реестр всех 42 переменных (типыint/bool/enum/url/duration_msпо семантике контракта), fail-fast валидация на старте — печатаются все невалидные переменные разом (safeParse), тихих дефолтов для невалидных значений нет.npm run env:schema→ детерминированный JSON-документenv-schema.1в stdout (repotrading-office,generated_from: apps/server/src/env.ts, variables отсортированы по name, без timestamp; файл не коммитится). Экспорт прогнан через нормативный валидатор control-center (validateEnvSchemaDocument) — VALID.npm run env:docs—ENV.mdи.env*.example(server/web/deploy) генерируются из схемы; правило секретов соблюдено (значения секретов нигде не появляются,NAME=+ комментарий про SOPS/age-контур).loadConfigпереведён на схему целиком (механическая замена всех серверных чтений); поведение для валидных env не изменено, существующие тесты (включая typed-403 из feat(security): fail-closed operator auth in connected mode; typed 403 on authority refusal #32) не тронуты и зелёные.envCompleteness.test.ts):process.envвнеenv.ts— падение; VITE_*-имена в web-исходниках обязаны быть объявлены в схеме; allowlist только дляcompose-lpc-agents.mjs(declaration-onlyULPC_DIR).envDocs.test.ts): рендер артефактов сравнивается с закоммиченными байт-в-байт.Fail-closed #32 не ослаблен
OFFICE_OPERATOR_PASSWORDв схеме —required: false+secret: true(standalone/fixture-режим без него легален); описание фиксирует connected-правило. Авторитетный гейт SEC-O1 (connected-режим отказывается стартовать без непустого пароля) остаётся вloadConfigи покрыт прежними тестами. Инварианты «в trading-lab-режиме URL/токены заданы явно» тоже сохранены дословно (проверка по сырому env, дефолт схемы не считается).Границы
VITE_*объявлены в схеме (owner_unitoffice-web, build-time), но точка чтения web-части остаётсяimport.meta.env/vite.OFFICE_IMAGE_TAG(compose) иULPC_DIR(build-тул floor) — declaration-only.Осознанные изменения поведения (только для НЕвалидных env)
Раньше мусорные значения тихо падали в дефолт (
num()/=== 'true'); теперь сервер отказывается стартовать и перечисляет все ошибки — это и есть цель контракта. Для валидных значений поведение бит-в-бит прежнее.Проверки
npm run typecheck— зелёный (все workspaces)npm run test— зелёный: 516 тестов (server 306, из них 28 новых env-тестов; web 172; floor 27; gateway 11)npm run build+verify:assets— зелёные🤖 Generated with Claude Code