letopis 1.4.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/AGENT-CHEATSHEET.md +329 -278
  2. package/CHANGELOG.md +558 -1
  3. package/README.md +606 -1037
  4. package/dist/acl.d.ts +78 -1
  5. package/dist/acl.js +264 -13
  6. package/dist/admin.d.ts +10 -141
  7. package/dist/admin.js +24 -175
  8. package/dist/auth.d.ts +2 -2
  9. package/dist/auth.js +5 -15
  10. package/dist/cache.d.ts +8 -1
  11. package/dist/cache.js +33 -10
  12. package/dist/chain.d.ts +19 -41
  13. package/dist/chain.js +169 -201
  14. package/dist/cli.js +51 -88
  15. package/dist/demo/booking.d.ts +352 -36
  16. package/dist/describe.d.ts +47 -0
  17. package/dist/describe.js +195 -0
  18. package/dist/errors.d.ts +59 -13
  19. package/dist/errors.js +190 -29
  20. package/dist/index.d.ts +52 -71
  21. package/dist/index.js +245 -130
  22. package/dist/internal.d.ts +12 -0
  23. package/dist/internal.js +5 -0
  24. package/dist/jsonschema.js +18 -17
  25. package/dist/load.d.ts +20 -12
  26. package/dist/load.js +225 -186
  27. package/dist/mcp.d.ts +5 -7
  28. package/dist/mcp.js +171 -215
  29. package/dist/messages/access.d.ts +90 -0
  30. package/dist/messages/access.js +113 -0
  31. package/dist/messages/api.d.ts +171 -0
  32. package/dist/messages/api.js +215 -0
  33. package/dist/messages/boot.d.ts +201 -0
  34. package/dist/messages/boot.js +256 -0
  35. package/dist/messages/codes.d.ts +172 -0
  36. package/dist/messages/codes.js +173 -0
  37. package/dist/messages/index.d.ts +95 -0
  38. package/dist/messages/index.js +118 -0
  39. package/dist/messages/mcp.d.ts +306 -0
  40. package/dist/messages/mcp.js +387 -0
  41. package/dist/messages/model.d.ts +233 -0
  42. package/dist/messages/model.js +283 -0
  43. package/dist/messages/query.d.ts +131 -0
  44. package/dist/messages/query.js +158 -0
  45. package/dist/messages/sql-access.d.ts +70 -0
  46. package/dist/messages/sql-access.js +87 -0
  47. package/dist/messages/sql-core.d.ts +150 -0
  48. package/dist/messages/sql-core.js +181 -0
  49. package/dist/messages/sql-time.d.ts +71 -0
  50. package/dist/messages/sql-time.js +88 -0
  51. package/dist/messages/sql-write.d.ts +246 -0
  52. package/dist/messages/sql-write.js +270 -0
  53. package/dist/messages/time.d.ts +23 -0
  54. package/dist/messages/time.js +29 -0
  55. package/dist/messages/types.d.ts +27 -0
  56. package/dist/messages/types.js +5 -0
  57. package/dist/messages/write.d.ts +405 -0
  58. package/dist/messages/write.js +509 -0
  59. package/dist/model.d.ts +73 -60
  60. package/dist/model.js +26 -29
  61. package/dist/ops.d.ts +35 -0
  62. package/dist/ops.js +101 -0
  63. package/dist/pglite.d.ts +0 -9
  64. package/dist/pglite.js +3 -1
  65. package/dist/registry.d.ts +3 -19
  66. package/dist/registry.js +3 -16
  67. package/dist/signals.d.ts +5 -9
  68. package/dist/signals.js +5 -9
  69. package/dist/sql.d.ts +13 -6
  70. package/dist/sql.js +176 -83
  71. package/dist/sync.d.ts +9 -3
  72. package/dist/sync.js +51 -21
  73. package/dist/tx.d.ts +26 -1
  74. package/dist/tx.js +44 -14
  75. package/dist/typed.d.ts +240 -45
  76. package/dist/types.d.ts +23 -91
  77. package/dist/types.js +12 -14
  78. package/dist/up.d.ts +53 -32
  79. package/dist/up.js +184 -73
  80. package/dist/uuid.js +5 -5
  81. package/dist/validate.d.ts +13 -1
  82. package/dist/validate.js +61 -29
  83. package/dist/watch.d.ts +11 -10
  84. package/dist/watch.js +33 -70
  85. package/dist/write.d.ts +9 -16
  86. package/dist/write.js +118 -187
  87. package/llms.txt +22 -25
  88. package/package.json +8 -11
  89. package/sql/10-core.sql +7 -50
  90. package/sql/15-errors.sql +64 -10
  91. package/sql/20-context.sql +7 -6
  92. package/sql/30-validate.sql +35 -27
  93. package/sql/40-class.sql +20 -114
  94. package/sql/50-acl.sql +8 -13
  95. package/sql/60-write.sql +220 -667
  96. package/sql/70-read.sql +20 -16
  97. package/sql/80-auth.sql +24 -27
  98. package/sql/90-time.sql +70 -859
  99. package/sql/95-seed.system.sql +7 -14
  100. package/sql/99-revision.sql +2 -1
  101. package/sql/README.md +32 -24
  102. package/sql/migrate/README.md +14 -0
  103. package/AGENT-CHEATSHEET.en.md +0 -485
  104. package/MIGRATION.md +0 -190
  105. package/README.en.md +0 -2859
  106. package/dist/import.d.ts +0 -185
  107. package/dist/import.js +0 -820
  108. package/dist/project.d.ts +0 -350
  109. package/dist/project.js +0 -1224
  110. package/sql/75-history.sql +0 -358
  111. package/sql/88-derived.sql +0 -1235
  112. package/sql/migrate/0006-changed-paths.sql +0 -3
  113. package/sql/migrate/0007-secret-account-fk.sql +0 -12
@@ -0,0 +1,71 @@
1
+ export declare const sqlTime: {
2
+ 'sql-time.signals_denied': {
3
+ code: "acl_denied";
4
+ ru: string;
5
+ };
6
+ 'sql-time.target_not_found': {
7
+ code: "target_not_found";
8
+ ru: string;
9
+ };
10
+ 'sql-time.no_session': {
11
+ code: "no_session";
12
+ ru: string;
13
+ };
14
+ 'sql-time.restore_not_deleted': {
15
+ code: "not_deleted";
16
+ ru: string;
17
+ };
18
+ 'sql-time.restore_class_row': {
19
+ code: "invalid_class";
20
+ ru: string;
21
+ };
22
+ 'sql-time.class_not_found': {
23
+ code: "invalid_class";
24
+ ru: string;
25
+ };
26
+ 'sql-time.class_deleted': {
27
+ code: "invalid_class";
28
+ ru: string;
29
+ };
30
+ 'sql-time.class_abstract': {
31
+ code: "invalid_class";
32
+ ru: string;
33
+ };
34
+ 'sql-time.invalid_data': {
35
+ code: "invalid_data";
36
+ ru: string;
37
+ };
38
+ 'sql-time.restore_key_changed': {
39
+ code: "id_mismatch";
40
+ ru: string;
41
+ };
42
+ 'sql-time.no_write_row': {
43
+ code: "acl_denied";
44
+ ru: string;
45
+ };
46
+ 'sql-time.purge_self': {
47
+ code: "acl_denied";
48
+ ru: string;
49
+ };
50
+ 'sql-time.account_purge_denied': {
51
+ code: "acl_denied";
52
+ ru: string;
53
+ };
54
+ 'sql-time.account_not_found': {
55
+ code: "target_not_found";
56
+ ru: string;
57
+ };
58
+ 'sql-time.last_owner': {
59
+ code: "acl_denied";
60
+ ru: string;
61
+ hint: string;
62
+ };
63
+ 'sql-time.account_referenced': {
64
+ code: "delete_restricted";
65
+ ru: string;
66
+ };
67
+ 'sql-time.maintain_denied': {
68
+ code: "acl_denied";
69
+ ru: string;
70
+ };
71
+ };
@@ -0,0 +1,88 @@
1
+ export const sqlTime = {
2
+ // 90-time.sql, signal_key()
3
+ 'sql-time.signals_denied': {
4
+ code: 'acl_denied',
5
+ ru: 'нет права letopis.signals',
6
+ },
7
+ // 90-time.sql, last_version_visible()
8
+ 'sql-time.target_not_found': {
9
+ code: 'target_not_found',
10
+ ru: 'цель не найдена',
11
+ },
12
+ // 90-time.sql, restore(), account_purge()
13
+ 'sql-time.no_session': {
14
+ code: 'no_session',
15
+ ru: 'нет действующей сессии',
16
+ },
17
+ // 90-time.sql, restore()
18
+ 'sql-time.restore_not_deleted': {
19
+ code: 'not_deleted',
20
+ ru: 'объект не удалён: restore — только для удалённых',
21
+ },
22
+ // 90-time.sql, restore()
23
+ 'sql-time.restore_class_row': {
24
+ code: 'invalid_class',
25
+ ru: 'описание класса восстанавливается созданием строки Class',
26
+ },
27
+ // 90-time.sql, restore()
28
+ 'sql-time.class_not_found': {
29
+ code: 'invalid_class',
30
+ ru: 'класс {cls} не найден',
31
+ },
32
+ // 90-time.sql, restore()
33
+ 'sql-time.class_deleted': {
34
+ code: 'invalid_class',
35
+ ru: 'класс {cls} удалён',
36
+ },
37
+ // 90-time.sql, restore()
38
+ 'sql-time.class_abstract': {
39
+ code: 'invalid_class',
40
+ ru: 'класс {cls} абстрактный',
41
+ },
42
+ // 90-time.sql, restore()
43
+ 'sql-time.invalid_data': {
44
+ code: 'invalid_data',
45
+ ru: 'данные не проходят описание класса {cls}',
46
+ },
47
+ // 90-time.sql, restore()
48
+ 'sql-time.restore_key_changed': {
49
+ code: 'id_mismatch',
50
+ ru: 'ключ класса {cls} изменился: id объекта не равен v5 от ключа',
51
+ },
52
+ // 90-time.sql, restore()
53
+ 'sql-time.no_write_row': {
54
+ code: 'acl_denied',
55
+ ru: 'нет права WRITE на строку класса {cls}',
56
+ },
57
+ // 90-time.sql, account_purge()
58
+ 'sql-time.purge_self': {
59
+ code: 'acl_denied',
60
+ ru: 'удалить себя нельзя',
61
+ },
62
+ // 90-time.sql, account_purge()
63
+ 'sql-time.account_purge_denied': {
64
+ code: 'acl_denied',
65
+ ru: 'удалить аккаунт может системный администратор или владелец его арендатора',
66
+ },
67
+ // 90-time.sql, account_purge()
68
+ 'sql-time.account_not_found': {
69
+ code: 'target_not_found',
70
+ ru: 'аккаунт не найден',
71
+ },
72
+ // 90-time.sql, account_purge(): аккаунт — единственный включённый владелец чужого арендатора; detail.tenant — он же
73
+ 'sql-time.last_owner': {
74
+ code: 'acl_denied',
75
+ ru: 'аккаунт — последний владелец арендатора {tenant}',
76
+ hint: 'сначала дать роль owner в этом арендаторе другому аккаунту (db.acl.roles от фасада арендатора), затем удалять',
77
+ },
78
+ // 90-time.sql, account_purge()
79
+ 'sql-time.account_referenced': {
80
+ code: 'delete_restricted',
81
+ ru: 'на аккаунт ссылаются другие строки',
82
+ },
83
+ // 90-time.sql, maintain()
84
+ 'sql-time.maintain_denied': {
85
+ code: 'acl_denied',
86
+ ru: 'нет права letopis.maintain',
87
+ },
88
+ };
@@ -0,0 +1,246 @@
1
+ export declare const sqlWrite: {
2
+ 'sql-write.lock_row_not_created': {
3
+ code: "internal";
4
+ ru: string;
5
+ };
6
+ 'sql-write.lock_row_not_found': {
7
+ code: "internal";
8
+ ru: string;
9
+ };
10
+ 'sql-write.invalid_data': {
11
+ code: "invalid_data";
12
+ ru: string;
13
+ };
14
+ 'sql-write.links_not_object': {
15
+ code: "invalid_data";
16
+ ru: string;
17
+ };
18
+ 'sql-write.end_undeclared': {
19
+ code: "undeclared_end";
20
+ ru: string;
21
+ };
22
+ 'sql-write.end_not_list': {
23
+ code: "invalid_data";
24
+ ru: string;
25
+ };
26
+ 'sql-write.end_not_uuid': {
27
+ code: "invalid_data";
28
+ ru: string;
29
+ };
30
+ 'sql-write.end_target_repeated': {
31
+ code: "invalid_data";
32
+ ru: string;
33
+ };
34
+ 'sql-write.end_too_few': {
35
+ code: "invalid_data";
36
+ ru: string;
37
+ };
38
+ 'sql-write.end_too_many': {
39
+ code: "invalid_data";
40
+ ru: string;
41
+ };
42
+ 'sql-write.end_required': {
43
+ code: "invalid_data";
44
+ ru: string;
45
+ };
46
+ 'sql-write.end_target_missing': {
47
+ code: "target_not_found";
48
+ ru: string;
49
+ };
50
+ 'sql-write.problem_abstract': {
51
+ code: "tightening_conflict";
52
+ ru: string;
53
+ };
54
+ 'sql-write.problem_data': {
55
+ code: "tightening_conflict";
56
+ ru: string;
57
+ };
58
+ 'sql-write.problem_key': {
59
+ code: "tightening_conflict";
60
+ ru: string;
61
+ };
62
+ 'sql-write.problem_ref': {
63
+ code: "tightening_conflict";
64
+ ru: string;
65
+ };
66
+ 'sql-write.problem_ref_hidden': {
67
+ code: "tightening_conflict";
68
+ ru: string;
69
+ };
70
+ 'sql-write.reparent_needs_all': {
71
+ code: "acl_denied";
72
+ ru: string;
73
+ };
74
+ 'sql-write.history_needs_all': {
75
+ code: "acl_denied";
76
+ ru: string;
77
+ };
78
+ 'sql-write.tighten_needs_all': {
79
+ code: "acl_denied";
80
+ ru: string;
81
+ };
82
+ 'sql-write.change_needs_all': {
83
+ code: "acl_denied";
84
+ ru: string;
85
+ };
86
+ 'sql-write.system_name_reserved': {
87
+ code: "invalid_class";
88
+ ru: string;
89
+ };
90
+ 'sql-write.system_flag': {
91
+ code: "invalid_class";
92
+ ru: string;
93
+ };
94
+ 'sql-write.system_name_taken': {
95
+ code: "invalid_class";
96
+ ru: string;
97
+ };
98
+ 'sql-write.link_name_reserved': {
99
+ code: "invalid_class";
100
+ ru: string;
101
+ };
102
+ 'sql-write.hub_name_reserved': {
103
+ code: "invalid_class";
104
+ ru: string;
105
+ };
106
+ 'sql-write.alias_taken': {
107
+ code: "invalid_class";
108
+ ru: string;
109
+ };
110
+ 'sql-write.name_is_alias': {
111
+ code: "invalid_class";
112
+ ru: string;
113
+ };
114
+ 'sql-write.alias_orphan_history': {
115
+ code: "invalid_class";
116
+ ru: string;
117
+ };
118
+ 'sql-write.end_other_class': {
119
+ code: "invalid_class";
120
+ ru: string;
121
+ };
122
+ 'sql-write.no_session': {
123
+ code: "no_session";
124
+ ru: string;
125
+ };
126
+ 'sql-write.foreign_tenant': {
127
+ code: "tenant_denied";
128
+ ru: string;
129
+ };
130
+ 'sql-write.account_tenant': {
131
+ code: "tenant_denied";
132
+ ru: string;
133
+ };
134
+ 'sql-write.class_not_found': {
135
+ code: "invalid_class";
136
+ ru: string;
137
+ };
138
+ 'sql-write.class_deleted': {
139
+ code: "invalid_class";
140
+ ru: string;
141
+ };
142
+ 'sql-write.class_abstract': {
143
+ code: "invalid_class";
144
+ ru: string;
145
+ };
146
+ 'sql-write.member_tenant': {
147
+ code: "invalid_data";
148
+ ru: string;
149
+ };
150
+ 'sql-write.id_from_db': {
151
+ code: "id_from_db";
152
+ ru: string;
153
+ };
154
+ 'sql-write.id_mismatch': {
155
+ code: "id_mismatch";
156
+ ru: string;
157
+ };
158
+ 'sql-write.history_recreate': {
159
+ code: "invalid_class";
160
+ ru: string;
161
+ };
162
+ 'sql-write.owner_not_found': {
163
+ code: "target_not_found";
164
+ ru: string;
165
+ };
166
+ 'sql-write.immutable_columns': {
167
+ code: "immutable_key";
168
+ ru: string;
169
+ };
170
+ 'sql-write.class_immutable': {
171
+ code: "immutable_key";
172
+ ru: string;
173
+ };
174
+ 'sql-write.key_changed': {
175
+ code: "immutable_key";
176
+ ru: string;
177
+ };
178
+ 'sql-write.tightening_mismatch': {
179
+ code: "tightening_conflict";
180
+ ru: string;
181
+ };
182
+ 'sql-write.delete_isolation': {
183
+ code: "isolation_level";
184
+ ru: string;
185
+ };
186
+ 'sql-write.system_account_delete': {
187
+ code: "acl_denied";
188
+ ru: string;
189
+ };
190
+ 'sql-write.recreated_in_statement': {
191
+ code: "recreated_in_statement";
192
+ ru: string;
193
+ };
194
+ 'sql-write.class_not_empty': {
195
+ code: "invalid_class";
196
+ ru: string;
197
+ };
198
+ 'sql-write.class_has_history': {
199
+ code: "invalid_class";
200
+ ru: string;
201
+ };
202
+ 'sql-write.cascade_delete_denied': {
203
+ code: "acl_denied";
204
+ ru: string;
205
+ };
206
+ 'sql-write.cascade_delete_denied_hidden': {
207
+ code: "acl_denied";
208
+ ru: string;
209
+ };
210
+ 'sql-write.unset_write_denied': {
211
+ code: "acl_denied";
212
+ ru: string;
213
+ };
214
+ 'sql-write.unset_write_denied_hidden': {
215
+ code: "acl_denied";
216
+ ru: string;
217
+ };
218
+ 'sql-write.delete_restricted': {
219
+ code: "delete_restricted";
220
+ ru: string;
221
+ };
222
+ 'sql-write.links_patch_op': {
223
+ code: "invalid_data";
224
+ ru: string;
225
+ };
226
+ 'sql-write.inc_args': {
227
+ code: "invalid_data";
228
+ ru: string;
229
+ };
230
+ 'sql-write.inc_path_missing': {
231
+ code: "invalid_data";
232
+ ru: string;
233
+ };
234
+ 'sql-write.inc_path_not_object': {
235
+ code: "invalid_data";
236
+ ru: string;
237
+ };
238
+ 'sql-write.inc_no_field': {
239
+ code: "invalid_data";
240
+ ru: string;
241
+ };
242
+ 'sql-write.inc_not_number': {
243
+ code: "invalid_data";
244
+ ru: string;
245
+ };
246
+ };
@@ -0,0 +1,270 @@
1
+ export const sqlWrite = {
2
+ // 60-write.sql, lock_row(), family_lock(): внутренняя ошибка (SQLSTATE XX000) — строки-замка нет и после вставки или
3
+ // блокировка её не нашла; name — имя строки-замка
4
+ 'sql-write.lock_row_not_created': {
5
+ code: 'internal',
6
+ ru: 'строка-замок {name} не создана',
7
+ },
8
+ 'sql-write.lock_row_not_found': {
9
+ code: 'internal',
10
+ ru: 'строка-замок {name} не найдена',
11
+ },
12
+ // 60-write.sql, триггеры вставки и правки, move_row: данные не проходят описание класса; detail.issues — нарушения
13
+ 'sql-write.invalid_data': {
14
+ code: 'invalid_data',
15
+ ru: 'данные не проходят описание класса {cls}',
16
+ },
17
+ // links_shape(): разбор концов строки (триггеры вставки и правки; check_links — restore)
18
+ 'sql-write.links_not_object': {
19
+ code: 'invalid_data',
20
+ ru: 'links — не объект',
21
+ },
22
+ 'sql-write.end_undeclared': {
23
+ code: 'undeclared_end',
24
+ ru: 'конец {end} не объявлен в классе {cls}',
25
+ },
26
+ 'sql-write.end_not_list': {
27
+ code: 'invalid_data',
28
+ ru: 'конец {end} — список id',
29
+ },
30
+ 'sql-write.end_not_uuid': {
31
+ code: 'invalid_data',
32
+ ru: 'конец {end}: значение не uuid',
33
+ },
34
+ 'sql-write.end_target_repeated': {
35
+ code: 'invalid_data',
36
+ ru: 'конец {end}: цель повторяется',
37
+ },
38
+ 'sql-write.end_too_few': {
39
+ code: 'invalid_data',
40
+ ru: 'у конца {end} слишком мало целей',
41
+ },
42
+ 'sql-write.end_too_many': {
43
+ code: 'invalid_data',
44
+ ru: 'у конца {end} слишком много целей',
45
+ },
46
+ 'sql-write.end_required': {
47
+ code: 'invalid_data',
48
+ ru: 'обязательный конец {end} не задан',
49
+ },
50
+ // check_links(), триггеры после вставки и правки (targets_bad): цель конца не найдена
51
+ 'sql-write.end_target_missing': {
52
+ code: 'target_not_found',
53
+ ru: 'цель конца {end} не найдена',
54
+ },
55
+ // family_conflicts(): чем строка семейства не проходит новое описание — поле problem в detail.rows отказа
56
+ // tightening_conflict (ужесточение класса); у строки ещё key и params — fromDbError их убирает
57
+ 'sql-write.problem_abstract': {
58
+ code: 'tightening_conflict',
59
+ ru: 'класс абстрактный',
60
+ },
61
+ // issues — нарушения текстом JSON без key и params; в params строки — сами нарушения с ключами (массив)
62
+ 'sql-write.problem_data': {
63
+ code: 'tightening_conflict',
64
+ ru: 'данные: {issues}',
65
+ },
66
+ 'sql-write.problem_key': {
67
+ code: 'tightening_conflict',
68
+ ru: 'id не соответствует ключу класса',
69
+ },
70
+ // ссылающаяся строка видна актору — её роль и id; не видна — ни роли, ни id
71
+ 'sql-write.problem_ref': {
72
+ code: 'tightening_conflict',
73
+ ru: 'на строку ссылается роль {role} строки {id}, которая не принимает класс',
74
+ },
75
+ 'sql-write.problem_ref_hidden': {
76
+ code: 'tightening_conflict',
77
+ ru: 'на строку ссылается строка, которой актор не видит, и она не принимает класс',
78
+ },
79
+ // class_rows_admit(): нет права без условий на все строки класса {target} (сам класс {cls} или его потомок); что
80
+ // меняется — p_what: reparent, history, tighten; иной p_what — прежний готовый текст {what}
81
+ 'sql-write.reparent_needs_all': {
82
+ code: 'acl_denied',
83
+ ru: 'класс {cls} меняет предков или алиас: нужно право {op} на все строки класса {target}',
84
+ },
85
+ 'sql-write.history_needs_all': {
86
+ code: 'acl_denied',
87
+ ru: 'класс {cls} включает или выключает журнал (history): нужно право {op} на все строки класса {target}',
88
+ },
89
+ 'sql-write.tighten_needs_all': {
90
+ code: 'acl_denied',
91
+ ru: 'ужесточение класса {cls}: нужно право {op} на все строки класса {target}',
92
+ },
93
+ 'sql-write.change_needs_all': {
94
+ code: 'acl_denied',
95
+ ru: '{what}: нужно право {op} на все строки класса {target}',
96
+ },
97
+ // class_admit(): проверки строки Class сверх метасхемы
98
+ 'sql-write.system_name_reserved': {
99
+ code: 'invalid_class',
100
+ ru: 'имя {name} зарезервировано за системным классом',
101
+ },
102
+ 'sql-write.system_flag': {
103
+ code: 'invalid_class',
104
+ ru: 'признак system задаёт только установка',
105
+ },
106
+ 'sql-write.system_name_taken': {
107
+ code: 'invalid_class',
108
+ ru: 'имя {name} занято системным классом',
109
+ },
110
+ 'sql-write.link_name_reserved': {
111
+ code: 'invalid_class',
112
+ ru: 'имя связи {name} совпадает с методом цепочки',
113
+ },
114
+ // хаб с зарезервированным именем (план 2.0, этап 4, п. 2; 7.10 №3): прежние такие хабы up() оставляет и называет в
115
+ // предупреждении (boot.reserved_hubs), но описание их строки Class база больше не пишет
116
+ 'sql-write.hub_name_reserved': {
117
+ code: 'invalid_class',
118
+ ru: 'имя хаба {name} совпадает с методом цепочки',
119
+ },
120
+ 'sql-write.alias_taken': {
121
+ code: 'invalid_class',
122
+ ru: 'алиас {alias} класса {cls} совпадает с именем или алиасом другого класса',
123
+ },
124
+ 'sql-write.name_is_alias': {
125
+ code: 'invalid_class',
126
+ ru: 'имя класса {cls} совпадает с алиасом другого класса',
127
+ },
128
+ 'sql-write.alias_orphan_history': {
129
+ code: 'invalid_class',
130
+ ru: 'удалённые потомки класса {cls} хранят историю строк: алиас не меняется',
131
+ },
132
+ 'sql-write.end_other_class': {
133
+ code: 'invalid_class',
134
+ ru: 'конец {end} в классе {cls} ведёт на другой класс',
135
+ },
136
+ // триггеры вставки и правки
137
+ 'sql-write.no_session': {
138
+ code: 'no_session',
139
+ ru: 'нет действующей сессии',
140
+ },
141
+ 'sql-write.foreign_tenant': {
142
+ code: 'tenant_denied',
143
+ ru: 'запись в чужого арендатора',
144
+ },
145
+ 'sql-write.account_tenant': {
146
+ code: 'tenant_denied',
147
+ ru: 'аккаунты лежат в арендаторе System',
148
+ },
149
+ 'sql-write.class_not_found': {
150
+ code: 'invalid_class',
151
+ ru: 'класс {cls} не найден',
152
+ },
153
+ // класс удалили, пока писатель ждал блокировку семейства
154
+ 'sql-write.class_deleted': {
155
+ code: 'invalid_class',
156
+ ru: 'класс {cls} удалён',
157
+ },
158
+ 'sql-write.class_abstract': {
159
+ code: 'invalid_class',
160
+ ru: 'класс {cls} абстрактный',
161
+ },
162
+ 'sql-write.member_tenant': {
163
+ code: 'invalid_data',
164
+ ru: 'конец Tenant членства — арендатор строки',
165
+ },
166
+ 'sql-write.id_from_db': {
167
+ code: 'id_from_db',
168
+ ru: 'id класса без ключа {cls} выдаёт база',
169
+ },
170
+ // detail.expected — id от ключа
171
+ 'sql-write.id_mismatch': {
172
+ code: 'id_mismatch',
173
+ ru: 'id не равен v5 от ключа класса {cls}',
174
+ },
175
+ 'sql-write.history_recreate': {
176
+ code: 'invalid_class',
177
+ ru: 'журнал хранит историю строк класса {cls} или его удалённых потомков: создать его можно только заново и с прежними parent, alias и history',
178
+ },
179
+ 'sql-write.owner_not_found': {
180
+ code: 'target_not_found',
181
+ ru: 'владелец строки не найден',
182
+ },
183
+ 'sql-write.immutable_columns': {
184
+ code: 'immutable_key',
185
+ ru: 'id, арендатора, владельца и время создания менять нельзя',
186
+ },
187
+ // класс строки неизменен (план 2.0, редакция 2): смены класса нет
188
+ 'sql-write.class_immutable': {
189
+ code: 'immutable_key',
190
+ ru: 'класс строки {cls} неизменен: объект другого класса — новый объект',
191
+ },
192
+ 'sql-write.key_changed': {
193
+ code: 'immutable_key',
194
+ ru: 'ключевое поле класса {cls} менять нельзя: id изменился бы',
195
+ },
196
+ // class_evolve(): detail — видимые нарушающие строки и число остальных (visible_detail)
197
+ 'sql-write.tightening_mismatch': {
198
+ code: 'tightening_conflict',
199
+ ru: 'новому описанию класса {cls} не соответствуют строки',
200
+ },
201
+ // триггеры удаления
202
+ 'sql-write.delete_isolation': {
203
+ code: 'isolation_level',
204
+ ru: 'удаление разрешено только в read committed',
205
+ },
206
+ 'sql-write.system_account_delete': {
207
+ code: 'acl_denied',
208
+ ru: 'аккаунт System не удаляется: ему принадлежат служебные строки установки',
209
+ },
210
+ 'sql-write.recreated_in_statement': {
211
+ code: 'recreated_in_statement',
212
+ ru: 'id удалён и создан заново одним оператором',
213
+ },
214
+ 'sql-write.class_not_empty': {
215
+ code: 'invalid_class',
216
+ ru: 'у класса {cls} есть строки или потомки',
217
+ },
218
+ 'sql-write.class_has_history': {
219
+ code: 'invalid_class',
220
+ ru: 'у класса {cls} есть история строк в журнале: класс с историей строк не удаляется',
221
+ },
222
+ // каскад и снятие конца: класс отказавшей строки — только если актор её видит (visible_class)
223
+ 'sql-write.cascade_delete_denied': {
224
+ code: 'acl_denied',
225
+ ru: 'нет права DELETE на класс {cls} в каскаде удаления',
226
+ },
227
+ 'sql-write.cascade_delete_denied_hidden': {
228
+ code: 'acl_denied',
229
+ ru: 'нет права DELETE на строки в каскаде удаления',
230
+ },
231
+ 'sql-write.unset_write_denied': {
232
+ code: 'acl_denied',
233
+ ru: 'нет права WRITE на класс {cls}: снятие конца при удалении',
234
+ },
235
+ 'sql-write.unset_write_denied_hidden': {
236
+ code: 'acl_denied',
237
+ ru: 'нет права WRITE на ссылающуюся строку: снятие конца при удалении',
238
+ },
239
+ // detail — видимые актору мешающие строки и число остальных (visible_detail)
240
+ 'sql-write.delete_restricted': {
241
+ code: 'delete_restricted',
242
+ ru: 'на удаляемые строки ссылаются другие строки (onDelete: restrict)',
243
+ },
244
+ // links_patch() и inc() исполняет приложение: raise с lt_text(), в detail — key и params
245
+ 'sql-write.links_patch_op': {
246
+ code: 'invalid_data',
247
+ ru: 'links_patch: неизвестная операция {op}',
248
+ },
249
+ // inc(): нарушение — и в detail.issues[0].message
250
+ 'sql-write.inc_args': {
251
+ code: 'invalid_data',
252
+ ru: 'inc: нужны путь и величина',
253
+ },
254
+ 'sql-write.inc_path_missing': {
255
+ code: 'invalid_data',
256
+ ru: 'inc: путь {path} идёт через отсутствующий объект',
257
+ },
258
+ 'sql-write.inc_path_not_object': {
259
+ code: 'invalid_data',
260
+ ru: 'inc: путь {path} идёт не через объект',
261
+ },
262
+ 'sql-write.inc_no_field': {
263
+ code: 'invalid_data',
264
+ ru: 'inc: поля {path} нет — задайте start',
265
+ },
266
+ 'sql-write.inc_not_number': {
267
+ code: 'invalid_data',
268
+ ru: 'inc: в поле {path} не число',
269
+ },
270
+ };