nameform

package
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

Documentation

Overview

Package nameform несёт ЕДИНСТВЕННУЮ форму имени ресурса Kachō и чистый предикат к ней — без транспорта.

Зачем отдельный пакет, а не константа рядом с валидаторами. Форма нужна и слою домена (self-validating newtype), а домену запрещено тянуть транспорт: правило чистой архитектуры — `domain/` только stdlib и контракты, без grpc (`architecture.md`). Валидаторы же обязаны возвращать готовый gRPC-статус, поэтому `pkg/validate` импортирует grpc — и импорт ЛЮБОГО его символа тянет grpc в граф зависимостей импортёра целиком: в Go зависимость пакетная, а не посимвольная.

Отсюда разделение: здесь — форма и предикат (ноль зависимостей вне stdlib), в `pkg/validate` — отказы в форме gRPC-статуса поверх этого предиката. Обе стороны читают ОДНУ строку, поэтому разойтись им не на чем.

Index

Constants

View Source
const ConstraintSuffix = "_name_check"

ConstraintSuffix — суффикс имени ограничения таблицы, которым форма имени продублирована на уровне базы.

Значение не выдумано здесь: имя ограничения строится как `<таблица> || '_name_check'` — одинаково в ШЕСТИ схемах, принявших канон формы имени (vpc, compute, storage, nlb, geo, iam). Согласие этой константы с миграциями держит гейт продукта internal/repohygiene TestNameFormConstraintSuffixMatchesMigrations: разойдись они — и отображение ошибки перестало бы узнавать ограничение, а «сервис пропустил негодное имя» снова читалось бы как «виноват ваш ввод».

Файл миграции здесь НЕ называется, и это не небрежность. Прежняя редакция называла `715001_resource_name_single_form.sql` — верно для пяти схем и неверно для шестой: цепь iam сведена в одну первичную миграцию, ограничение стоит в ней. Координата, верная для части популяции, посылает читателя не туда у остальной; какие схемы приняли канон и откуда, гейт ВЫВОДИТ из содержимого миграций и печатает переписью на каждом прогоне.

View Source
const Form = `^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$`

Form — единственная форма имени ресурса в дереве: DNS label по RFC 1123.

Строчные латинские буквы, цифры и дефис; первый и последний символ — буква или цифра; длина 1..63. Производных «как общий, но здесь ещё подчёркивание» не заводится: два имени одного правила расходятся молча — так и разошлись четыре прежних валидатора (заглавные у одного, подчёркивание у двух, пустая строка у трёх), давая один контракт и разное исполнение (задача #715).

Форма взята внешним стандартом намеренно. Имя, годное как DNS label, годится сегментом адреса, меткой в средствах наблюдения и именем в конфигурации развёртывания — без экранирования и без второго правила «а здесь можно иначе». Спор о вкусах при заведении следующего ресурса снят: форма не наша.

Единственность объявления держит гейт internal/repohygiene TestResourceNameFormIsDeclaredOnce.

View Source
const MaxLen = 63

MaxLen — верхняя граница длины имени, та же, что в Form.

Variables

This section is empty.

Functions

func IsConstraint

func IsConstraint(table, constraint string) bool

IsConstraint отвечает, является ли ограничение `constraint` таблицы `table` тем самым дублем формы имени.

Зачем предикат вообще нужен

Ограничение формы — ЗАЩИТА ПОСЛЕДНЕГО РУБЕЖА, а не проверка ввода: форму имени сервис проверяет сам, до вставки (`validate.Name` / доменный newtype). Значит его срабатывание означает не «вызывающий прислал негодное имя», а «сервис пропустил негодное значение», — то есть НАШ дефект. Отображать такой отказ в `INVALID_ARGUMENT` значит обвинять вызывающего в чужой ошибке; ему место в фиксированном `INTERNAL` с записью в журнал.

Почему сравнение, а не суффикс

Проверка «имя кончается на ConstraintSuffix» короче и неверна: `users_display_name_check` в схеме iam кончается ровно так же, но сторожит длину другого поля в схеме, которой миграция 715001 не касалась. Точное сравнение с конструкцией миграции ошибиться не может, а имя таблицы Postgres сообщает в том же отказе (`pgconn.PgError.TableName`), поэтому дополнительных сведений вызывающему собирать не надо.

Пустые аргументы дают `false`: Postgres оставляет эти поля пустыми, когда отказ не про ограничение таблицы, и совпадение пустого с пустым было бы утверждением о форме имени там, где о ней речи не было.

func OK

func OK(value string) bool

OK сообщает, отвечает ли значение форме.

Пустая строка форме НЕ отвечает — и это верно на обоих путях, но означает разное: на правке пустое имя отвергается, на создании оно законный вход и до записи заменяется умолчанием. Решает это вызывающий; предикат отвечает только про форму.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL