feat(dict): soft-delete с recovery (Phase 1)

This commit is contained in:
Александр Зимин
2026-06-08 14:27:34 +00:00
parent 4516559e21
commit 0ccdff95d2
6 changed files with 217 additions and 43 deletions
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.27.xsd">
<!--
Soft-delete для dictionaries (Phase 1 НСИ governance).
Контекст: MR !292 (v2.52.0) добавил DELETE endpoint с cascade на FK
(migration 0030 ON DELETE CASCADE). Юзер: «удаление справочников
серьезная вещь тут разве ревью не нужно? и это физическое удаление
из бд?». Ответ — да, это было unsafe.
Phase 1 (этот MR): soft-delete. DELETE endpoint вместо физического
cascade удаления ставит `deleted_at = now()`. Records/drafts intact.
`list()` excludes deleted by default. Admin Корзина page + restore
endpoint позволяют вернуть случайно удалённое.
Phase 2 (follow-up MR): 2nd-admin approval workflow (создаст таблицу
`dictionary_deletion_requests` с maker/reviewer как для drafts).
Permanent purge — отдельный admin-only flow `POST /admin/dictionaries/
{name}/purge` после approval+30d retention (follow-up cron). Migration
0030 ON DELETE CASCADE остаётся — нужен для finalize physical delete
в purge endpoint (cascade на records/drafts/schema_drafts).
-->
<changeSet id="0031-1-dictionary-soft-delete-columns" author="ordinis">
<comment>deleted_at + deleted_by columns на dictionary_definitions</comment>
<addColumn tableName="dictionary_definitions">
<column name="deleted_at" type="TIMESTAMP WITH TIME ZONE"/>
<column name="deleted_by" type="VARCHAR(64)"/>
</addColumn>
<createIndex tableName="dictionary_definitions"
indexName="idx_dict_def_deleted_at">
<column name="deleted_at"/>
</createIndex>
</changeSet>
<!-- Phase 2 (follow-up): создать таблицу dictionary_deletion_requests
с maker/reviewer/status для 2nd-admin approval workflow. Сейчас Phase 1
только soft-delete сам с admin self-confirmation. -->
</databaseChangeLog>
@@ -40,5 +40,6 @@
<include file="changes/0028-phase3-prep-org-id.xml" relativeToChangelogFile="true"/>
<include file="changes/0029-drop-self-approve-constraints.xml" relativeToChangelogFile="true"/>
<include file="changes/0030-dictionary-delete-cascade.xml" relativeToChangelogFile="true"/>
<include file="changes/0031-dictionary-soft-delete-approval.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>