From 89b3285b5a4a2dbe97e6ce9e882a1fa7d9742da7 Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Thu, 23 Jul 2026 18:19:25 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D0=B2=D0=B5=D0=BD=D1=86?= =?UTF-8?q?=D0=B8=D0=B8:=20=D1=83=D0=B1=D1=80=D0=B0=D1=82=D1=8C=20=D0=B8?= =?UTF-8?q?=D0=B7=20CLAUDE.md=20=D0=BF=D0=B5=D1=80=D0=B5=D1=81=D0=BA=D0=B0?= =?UTF-8?q?=D0=B7=20=D0=BC=D0=B5=D1=85=D0=B0=D0=BD=D0=B8=D0=B7=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Одно и то же жило в трёх местах: docs/conventions, openspec/config.yaml и CLAUDE.md, который читается каждую сессию. Механизируемое теперь одной строкой со ссылкой на гейт, прозой — только то, что правилом не выражается. Co-Authored-By: Claude Opus 4.8 (1M context) --- CLAUDE.md | 27 +++++++++++++-------------- docs/conventions/database.md | 7 +++---- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 657fee1..9eaf4c1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -137,20 +137,19 @@ Module path — `git.vakhrushev.me/av/jellybit`. Go 1.26, `CGO_ENABLED=0`. - Раскладка: `cmd/jellybit` (точка входа) + `internal/<пакет>` по компонентам из [architecture.md](docs/specs/architecture.md). -- Ошибки — stdlib, обёртка с контекстом (`fmt.Errorf("...: %w", err)`), - проверка через `errors.Is`/`errors.As`, трансляция на внешней границе: - [docs/conventions/errors.md](docs/conventions/errors.md). -- Логирование только через `slog`, без `fmt.Println` — уровни, обязательные - поля и что не логировать см. [docs/conventions/logging.md](docs/conventions/logging.md). -- Конфигурация — только TOML; секреты рендерит деплой (Ansible+Vault) в - файл (`config.toml` не коммитится, `0600`), не в env; валидация на старте: - [docs/conventions/config.md](docs/conventions/config.md). -- Время — храним в UTC, RFC 3339 с суффиксом `Z`; генерирует только приложение - (`store.Now()`), таймзона отображения — конфиг `[general].timezone`: - [docs/conventions/database.md](docs/conventions/database.md). -- Идентификаторы — TEXT ULID (lowercase) через `internal/ident`, без числовых - AUTOINCREMENT; внешние id валидируются `ident.Parse` на границе: - [docs/conventions/database.md](docs/conventions/database.md). +- Механизируемое проверяет `task gate` (`.golangci.yml` + `internal/archrules`): + форма ошибок и логов, конфиг мимо env, время мимо `store.Now()`, AUTOINCREMENT + в миграциях, направление зависимостей ядро↔транспорты. Пересказывать эти + правила не нужно — гейт скажет точнее. +- Прозой остаётся то, что правилом не выражается, и читается в источнике: + [ошибки](docs/conventions/errors.md) (трансляция доменной ошибки на внешней + границе, sentinel против типизированной), + [логи](docs/conventions/logging.md) (уровень по адресату, единственный + логирующий чокпоинт, `ext.*`, что не логируем), + [конфиг](docs/conventions/config.md) (секреты рендерит деплой в файл `0600`, + самодокументируемый `config.example.toml`, валидация на старте), + [БД](docs/conventions/database.md) (время в UTC RFC 3339, TEXT ULID через + `internal/ident`, `ident.Parse` на входной границе). - Миграции БД (goose, `internal/store/migrations`; SQL для DDL, Go — когда нужен код) — при изменении структуры (таблица/столбец/индекс/связь) в том же change обновляем ER-схему [docs/specs/database.md](docs/specs/database.md). diff --git a/docs/conventions/database.md b/docs/conventions/database.md index 80ed953..59aa9ec 100644 --- a/docs/conventions/database.md +++ b/docs/conventions/database.md @@ -46,10 +46,9 @@ лексикографическую сортировку TEXT = хронологию (`ORDER BY created_at`). Единая точка генерации — приложение: `store.Now()` + `store.FormatTime`/ `ParseTime` (аналогично `ident.NewID` для id), а не дефолт в схеме — так - забытая вставка падает громко (`NOT NULL` без дефолта). Измерение - длительности — не метка времени: для внешних вызовов его засекает - `logging.StartCall`. Зона хранения всегда UTC; таймзона отображения в UI — конфиг - `[general].timezone`. + забытая вставка падает громко. Измерение длительности — не метка времени: у + внешних вызовов его засекает `logging.StartCall`. Таймзона отображения в + UI — конфиг `[general].timezone`. - Миграции — goose (`internal/store/migrations`): SQL-файлы для DDL; Go-миграции (`goose.AddMigrationContext`) — когда нужен код (генерация id, backfill). При изменении структуры обновляем ER-схему