migrations

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 13, 2026 License: AGPL-3.0 Imports: 6 Imported by: 0

README

kaname — миграции

Schema kaname. Число миграций здесь НЕ выписано намеренно: оно росло с каждой задачей, а строка с ним не правилась ни разу — на момент этой правки документ утверждал двадцать четыре при ста семнадцати файлах в каталоге. Перечень получают предикатом, а не памятью:

ls services/iam/internal/migrations/*.sql | wc -l

Номера в каталоге принадлежат трём эрам сразу (0001_initial.sql и далее по возрастанию — ранняя; затем выведенные из номера задачи; затем по метке времени). Смешение законно: переномеровать применённое нельзя.

Форма НОВОЙ миграции — метка времени заведения YYYYMMDDHHMMSS_<имя>.sql (date -u +%Y%m%d%H%M%S). Объявлена она в ОДНОМ месте и здесь НЕ переписывается: docs/architecture/migration-version-namespace.md — там же названо, чем закрыты доводы двух прежних форм. Держит форму гейт internal/repohygiene TestNewMigrationOutranksEveryAppliedOne; он судит ТОЛЬКО добавленные относительно ствола файлы. Создают миграции этого каталога:

  • core resource model (operations, users, accounts, projects, service_accounts, groups, group_members, roles, access_bindings)
    • default-roles seed (12 system-ролей с детерминированными id);
  • governance расширения (access_bindings_jit_eligibility, _jit_pending, break_glass_*);
  • federation / identity (federation_*, scim_*);
  • чеканку своих токенов — ключница подписных ключей (token_signing_keys: kid, алгоритм, состояние, публичная половина, ОБЁРНУТАЯ приватная половина, срок; «подписывает ровно один» держит частичный уникальный индекс) и отзыв отчеканенного (minted_token_revocations);
  • outbox-cluster (fga_outbox, subject_change_outbox, caep_outbox, audit_outbox).

[!note] Прежнее хранилище подписных ключей здесь названо не было, и это не опечатка редакции Оно существовало, стояло в этом перечне и было СНЯТО миграцией: приватную половину не читал обратно никто, а запись в хранилище удавалась — поэтому оно выглядело исправным всё время своей жизни. Имя снятой таблицы в этом перечне не воспроизводится: в перечне действующих таблиц оно читается как действующая координата. Его текст остался в применённых миграциях и в ведомости дропов — там он свидетельство, и править его нельзя.

Ключница задачи #897 названа ИНАЧЕ намеренно. Совпадение имён сделало бы стража ведомости дропов красным СПРАВЕДЛИВО: он увидел бы воскресшую таблицу, которую сам же считает снятой.

CHECK / FK / UNIQUE / partial UNIQUE / триггеры inline в соответствующих миграциях. Helper-функции: kacho_labels_valid(jsonb), iam_permissions_valid(jsonb), триггер group_members_member_exists_trg.

Squash в единый 0001_initial.sql baseline запланирован в Wave M рефакторинга KAC-193 (после Wave D evgeniy-compliance pass).

Запуск

make migrate-up (требует KANAME_DB_PASSWORD=...).

Запреты

  • НЕ редактировать примененную миграцию (workspace CLAUDE.md запрет #5) — только новая миграция, и её номер — метка времени заведения (YYYYMMDDHHMMSS_<имя>.sql), а не следующий по порядку. Здесь стояло «следующий — 0025_*»: номер выписан, ни разу не правился и разошёлся с деревом на порядки (в каталоге живут 0092, 484002, 795001), а инкрементная форма к тому же отвергается гейтом формы. Каталог не пересчитывают глазами — предикат выше.
  • Таблица operations объявлена в baseline под схемой kaname. Цели, которая «подтягивала бы общую operations», больше нет: она ничего не делала ни в одном сервисе, а копия common-файла создала бы конфликтующий unqualified public.operations.

Documentation

Overview

grant_removal_trace.go — миграция, СНИМАЮЩАЯ выдачи, обязана оставить след той формы, которую платформа для этого завела; и ни одна миграция не переносит выдачу с одной роли на другую.

Порт с монорепо (`internal/repohygiene/grantremovaltrace.go`, снят вынесением службы — `kacho#2597`; приёмка `seed-identity-names-its-own-service.md` §6 уже называла держателем `TestNoMigrationMovesGrantsBetweenRoles`, а он не существовал ни в одном файле — только в комментариях).

Предмет

Строка `kaname.access_bindings` — это доступ, выданный арендатору. Миграция, удаляющая её, доступ ОТБИРАЕТ; и если рядом нет записи в журнал жизненного цикла выдачи, у которого есть читатель, то «отобрано» становится неотличимо от «никогда не выдавалось». Арендатор видит отсутствие права и не может узнать ни что оно было, ни когда исчезло, ни почему.

Замер на дне переезда (эта ревизия, `internal/migrations`)

Корпус — 10 файлов. Ровно один называет таблицу выдач ОПЕРАТОРОМ удаления (`20260909202745_module_identities_leave_the_baseline.sql`), и он несёт след — вставку в `kaname.audit_outbox` — ДО удаления, в той же накатной половине. Храповик заведён нулём и это подтверждено переписью гейта, а не предположено: см. `TestMigrationRemovingGrantsLeavesATrace`.

Почему ХРАПОВИК, а не ведомость имён

Применённую миграцию не правят (запрет #5) — значит найденную без следа придётся либо простить, либо держать ствол красным за прошлое. Ведомость имён растёт молча, и её никто не сверяет; число сверяется одним обходом и меняется только сознательно. Перечень имён при этом ПЕЧАТАЕТСЯ каждым прогоном — прощение остаётся видимым.

Храповик ДВУСТОРОННИЙ: находка приходит и на следующей миграции без следа, и на уменьшении числа прощённых. Односторонний потолок не истекает никогда и потому механизмом не является.

Почему снятие выдач У СУБЪЕКТА входит в класс

Норма — про ОТОБРАННЫЙ ДОСТУП, а не про снятую роль: строки выдач исчезают одинаково, а служебная учётка — такой же первоклассный принципал, как человек.

Граница, названная честно

Гейт судит НАКАТНУЮ половину: `DELETE` в откатной половине снимает СВОЮ ЖЕ вставку, откатываясь, и доступа не отбирает. Он не судит, ВЕРЕН ли текст оставленного следа и доедет ли он до читателя, — только что запись есть. И он ничего не говорит о выдачах, снятых прод-кодом: у того путь свой и свой журнал.

sql_text.go — исполняемая часть миграции: Up-секция без комментариев и без содержимого строковых литералов.

Порт с монорепо (`internal/repohygiene/migrationsqltext.go`, снят вынесением службы — `kacho#2597`). Поведение переносом не менялось: функции перенесены дословно и экспортированы, чтобы их звала внешняя тестовая обёртка (`package migrations_test`), а не только пакет-владелец.

Здесь у монорепо было НЕСКОЛЬКО инвентарей, зовущих эти функции; в этом дереве сегодня один владелец — `grant_removal_trace.go`. Заводя второй, проверь СНАЧАЛА, не завёл ли кто-то копию: две реализации одного разбора расходятся молча, и расходятся именно там, где расхождение не видно — на законном входе обе отвечают одинаково.

Index

Constants

View Source
const GrantRemovalRatchet = 0

GrantRemovalRatchet — сколько миграций корпуса СЕГОДНЯ снимают выдачи без следа. Число, а не перечень: см. шапку файла. Отклонение в любую сторону — находка.

Variables

FS — embedded миграции (squashed baseline в одном файле). Используется cmd/migrator/main.go через runner.Config.FS.

Functions

func AuditGrantRoleReassignment added in v0.2.0

func AuditGrantRoleReassignment(corpus []GrantMigrationSource) (moves []string, statements int)

AuditGrantRoleReassignment — миграции, переставляющие выдачу с одной роли на другую, и число осмотренных операторов.

Второе число обязательно: ноль переносов при нуле прочитанных операторов означает «распознаватель ослеп», а не «переносов нет».

func GrantRemovalFinding added in v0.2.0

func GrantRemovalFinding(got int, names []string) string

GrantRemovalFinding — текст находки. Отдельной функцией, чтобы обе стороны храповика (перебор и недобор) говорили ОДНИМ голосом и назывались вместе с перечнем.

func GrantTableMentions added in v0.2.0

func GrantTableMentions(corpus []GrantMigrationSource) int

GrantTableMentions — сколько операторов корпуса называют таблицу выдач ЛЮБЫМ глаголом. Общая предпосылка обоих гейтов файла: ноль означает, что корпус не прочитан либо таблица выдач из него исчезла.

func MigrationUpSection added in v0.2.0

func MigrationUpSection(body string) string

MigrationUpSection — исполняемая часть миграции: Up-секция без комментариев.

Порядок двух шагов обязателен и обратим быть не может: маркер `-- +goose Down` САМ является комментарием, поэтому секция отрезается по СЫРОМУ тексту, и только потом забеливаются комментарии. Забелив сперва, разбор потерял бы границу секций и прочитал бы откат как часть наката.

func SQLBlankComments added in v0.2.0

func SQLBlankComments(s string) string

SQLBlankComments заменяет содержимое SQL-комментариев пробелами, сохраняя длину строки и позиции переводов строк.

Приоритет состояний: строка > комментарий > код. Внутри строкового литерала `--` комментария не начинает; внутри комментария кавычка строки не открывает. Блочные комментарии Postgres ВЛОЖЕННЫЕ — глубина считается, а не ищется первый `*/`.

func SQLBlankStrings added in v0.2.0

func SQLBlankStrings(s string) string

SQLBlankStrings заменяет СОДЕРЖИМОЕ строковых литералов пробелами, сохраняя длину и позиции переводов строк.

Зачем отдельно от SQLBlankComments. Тот забеливает комментарии и при этом НАМЕРЕННО пропускает литералы целиком — иначе `--` внутри строки открыл бы комментарий. Но литерал не исполняется как SQL: прозаическое сообщение об ошибке, содержащее слова конструкции, для инвентаря по образцу неотличимо от самой конструкции.

Кавычки-границы ОСТАЮТСЯ на месте: забеливается содержимое, поэтому `WHERE x = 'DROP COLUMN'` остаётся синтаксически тем же и по-прежнему не склеивает соседние лексемы.

Types

type GrantMigrationSource added in v0.2.0

type GrantMigrationSource struct {
	Name string
	Body string
}

GrantMigrationSource — один файл корпуса: имя для находки и текст для разбора.

func ReadMigrationCorpus added in v0.2.0

func ReadMigrationCorpus(paths []string, read func(string) ([]byte, error)) ([]GrantMigrationSource, error)

ReadMigrationCorpus — корпус миграций, состав берётся у вызывающего (индекс git либо `embed.FS`), а не с диска напрямую.

type GrantRemovalCensus added in v0.2.0

type GrantRemovalCensus struct {
	FilesRead  int
	WithDelete int // удаление выдач где угодно в файле
	InUpHalf   int // из них — в накатной половине
}

GrantRemovalCensus — объём осмотренного. Три величины, а не одна: «ноль находок» обязано быть отличимо от «ноль прочитанного», а «ноль в накатной половине» — от «распознаватель перестал узнавать удаление вовсе».

func AuditGrantRemovalTrace added in v0.2.0

func AuditGrantRemovalTrace(corpus []GrantMigrationSource) (silent []string, c GrantRemovalCensus)

AuditGrantRemovalTrace — ядро гейта. Возвращает имена миграций, снимающих выдачи без следа, и перепись.

Jump to

Keyboard shortcuts

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