letopis 2.0.0 → 3.0.1
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.
- package/AGENT-CHEATSHEET.md +491 -414
- package/CHANGELOG.md +361 -0
- package/LICENSE +75 -21
- package/LICENSE-COMMERCIAL.md +49 -0
- package/README.md +969 -210
- package/api-contract.json +385 -0
- package/dist/acl.d.ts +7 -2
- package/dist/acl.js +19 -2
- package/dist/admin.d.ts +7 -1
- package/dist/admin.js +16 -9
- package/dist/auth.d.ts +47 -11
- package/dist/auth.js +129 -15
- package/dist/chain.d.ts +52 -25
- package/dist/chain.js +445 -64
- package/dist/cli.js +72 -20
- package/dist/errors.d.ts +23 -6
- package/dist/errors.js +52 -13
- package/dist/index.d.ts +32 -15
- package/dist/index.js +209 -68
- package/dist/internal.d.ts +2 -0
- package/dist/load.d.ts +10 -6
- package/dist/load.js +30 -11
- package/dist/log.d.ts +121 -0
- package/dist/log.js +654 -0
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +34 -16
- package/dist/messages/access.d.ts +10 -0
- package/dist/messages/access.js +13 -0
- package/dist/messages/api.d.ts +76 -0
- package/dist/messages/api.js +109 -7
- package/dist/messages/boot.d.ts +5 -0
- package/dist/messages/boot.js +11 -4
- package/dist/messages/codes.js +4 -4
- package/dist/messages/index.d.ts +5 -2
- package/dist/messages/index.js +5 -2
- package/dist/messages/log.d.ts +232 -0
- package/dist/messages/log.js +105 -0
- package/dist/messages/mcp.js +7 -7
- package/dist/messages/model.d.ts +40 -1
- package/dist/messages/model.js +52 -3
- package/dist/messages/query.d.ts +10 -0
- package/dist/messages/query.js +13 -0
- package/dist/messages/sql-core.d.ts +15 -1
- package/dist/messages/sql-core.js +20 -3
- package/dist/messages/sql-time.d.ts +15 -0
- package/dist/messages/sql-time.js +23 -0
- package/dist/messages/write.d.ts +52 -0
- package/dist/messages/write.js +77 -6
- package/dist/model.d.ts +10 -2
- package/dist/model.js +28 -6
- package/dist/registry.d.ts +6 -0
- package/dist/registry.js +6 -0
- package/dist/sql.d.ts +2 -0
- package/dist/sql.js +77 -25
- package/dist/sync.d.ts +4 -5
- package/dist/sync.js +53 -4
- package/dist/tx.d.ts +10 -1
- package/dist/tx.js +44 -2
- package/dist/typed.d.ts +18 -14
- package/dist/types.d.ts +91 -8
- package/dist/types.js +8 -3
- package/dist/up.d.ts +8 -5
- package/dist/up.js +71 -23
- package/dist/uuid.d.ts +8 -0
- package/dist/uuid.js +9 -1
- package/dist/validate.js +24 -7
- package/dist/watch.d.ts +5 -0
- package/dist/watch.js +13 -0
- package/dist/write.d.ts +84 -3
- package/dist/write.js +427 -40
- package/llms.txt +38 -17
- package/package.json +12 -6
- package/sql/20-context.sql +11 -3
- package/sql/30-validate.sql +51 -10
- package/sql/40-class.sql +21 -1
- package/sql/60-write.sql +18 -6
- package/sql/80-auth.sql +88 -17
- package/sql/90-time.sql +34 -6
- package/sql/99-revision.sql +5 -1
- package/sql/migrate/0009-restore-rev.tenants-name.sql +10 -0
- package/sql/migrate/0010-impersonation-no-account.sql +5 -0
- package/sql/migrate/0011-key-lock.otp-enabled.sql +7 -0
- package/sql/migrate/README.md +5 -1
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
export declare const log: {
|
|
2
|
+
'log.bad_level': {
|
|
3
|
+
code: "invalid_data";
|
|
4
|
+
ru: string;
|
|
5
|
+
hint: string;
|
|
6
|
+
};
|
|
7
|
+
'log.bad_logger': {
|
|
8
|
+
code: "invalid_data";
|
|
9
|
+
ru: string;
|
|
10
|
+
hint: string;
|
|
11
|
+
};
|
|
12
|
+
'log.bad_redact': {
|
|
13
|
+
code: "invalid_data";
|
|
14
|
+
ru: string;
|
|
15
|
+
hint: string;
|
|
16
|
+
};
|
|
17
|
+
'log.db_error': {
|
|
18
|
+
code: "internal";
|
|
19
|
+
ru: string;
|
|
20
|
+
};
|
|
21
|
+
'log.logger_failed': {
|
|
22
|
+
code: "internal";
|
|
23
|
+
ru: string;
|
|
24
|
+
};
|
|
25
|
+
'log.notify_failed': {
|
|
26
|
+
code: "internal";
|
|
27
|
+
ru: string;
|
|
28
|
+
};
|
|
29
|
+
'log.renew_failed': {
|
|
30
|
+
code: "no_session";
|
|
31
|
+
ru: string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
/** Уровень события. */
|
|
35
|
+
export type LogEventLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
36
|
+
/** Запись каталога событий: уровень по умолчанию и что значит событие. */
|
|
37
|
+
export interface LogEventInfo {
|
|
38
|
+
level: LogEventLevel;
|
|
39
|
+
ru: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Каталог событий логирования — объект (не массив): имя события → `{ level, ru }`, где `level` — уровень события по
|
|
43
|
+
* умолчанию (`debug`, `info`, `warn`, `error`), `ru` — что значит событие. Тип — `Readonly<Record<LogEventName,
|
|
44
|
+
* LogEventInfo>>`: `LOG_EVENTS.write.level` — `'info'`, список имён — `Object.keys(LOG_EVENTS)`. Основные события:
|
|
45
|
+
* connect, close, up, migrate, sync, read, cache.hit, cache.miss, write, delete.preview, delete, restore, tx.*,
|
|
46
|
+
* auth.login, auth.logout, auth.revoke, auth.switch, watch.start, watch.stop, signal, maintain, warning, error, sql;
|
|
47
|
+
* остальные — дополнительные.
|
|
48
|
+
*/
|
|
49
|
+
export declare const LOG_EVENTS: {
|
|
50
|
+
readonly connect: {
|
|
51
|
+
readonly level: "info";
|
|
52
|
+
readonly ru: "connect() готов: схема, режим сигналов, кэш, способ входа";
|
|
53
|
+
};
|
|
54
|
+
readonly close: {
|
|
55
|
+
readonly level: "info";
|
|
56
|
+
readonly ru: "db.close(): пул, подписки и таймеры закрыты";
|
|
57
|
+
};
|
|
58
|
+
readonly 'registry.refresh': {
|
|
59
|
+
readonly level: "debug";
|
|
60
|
+
readonly ru: "реестр классов перечитан";
|
|
61
|
+
};
|
|
62
|
+
readonly 'session.renew': {
|
|
63
|
+
readonly level: "info";
|
|
64
|
+
readonly ru: "сессия по ключу сервиса истекла — ключ обменян на новую";
|
|
65
|
+
};
|
|
66
|
+
readonly up: {
|
|
67
|
+
readonly level: "info";
|
|
68
|
+
readonly ru: "up() завершён: схема поставлена, обновлена или накатана повторно";
|
|
69
|
+
};
|
|
70
|
+
readonly 'up.step': {
|
|
71
|
+
readonly level: "info";
|
|
72
|
+
readonly ru: "шаг up(): то, что без логгера печатается в консоль";
|
|
73
|
+
};
|
|
74
|
+
readonly migrate: {
|
|
75
|
+
readonly level: "info";
|
|
76
|
+
readonly ru: "up() обновил ревизию схемы миграциями";
|
|
77
|
+
};
|
|
78
|
+
readonly 'tenant.create': {
|
|
79
|
+
readonly level: "info";
|
|
80
|
+
readonly ru: "арендатор (и его первый пользователь) заведён или найден";
|
|
81
|
+
};
|
|
82
|
+
readonly sync: {
|
|
83
|
+
readonly level: "info";
|
|
84
|
+
readonly ru: "syncModels(): классы созданы, изменены или сверены (сухой прогон)";
|
|
85
|
+
};
|
|
86
|
+
readonly read: {
|
|
87
|
+
readonly level: "debug";
|
|
88
|
+
readonly ru: "терминал чтения цепочки: rows, first, ids, count, paths, versions, агрегаты";
|
|
89
|
+
};
|
|
90
|
+
readonly 'cache.hit': {
|
|
91
|
+
readonly level: "debug";
|
|
92
|
+
readonly ru: "ответ взят из кэша результатов";
|
|
93
|
+
};
|
|
94
|
+
readonly 'cache.miss': {
|
|
95
|
+
readonly level: "debug";
|
|
96
|
+
readonly ru: "ответа нет в кэше результатов — запрос к базе";
|
|
97
|
+
};
|
|
98
|
+
readonly raw: {
|
|
99
|
+
readonly level: "debug";
|
|
100
|
+
readonly ru: "сырой SQL db.sql";
|
|
101
|
+
};
|
|
102
|
+
readonly write: {
|
|
103
|
+
readonly level: "info";
|
|
104
|
+
readonly ru: "запись цепочкой (create, update, upsert, шаги ролей) или батч";
|
|
105
|
+
};
|
|
106
|
+
readonly 'delete.preview': {
|
|
107
|
+
readonly level: "debug";
|
|
108
|
+
readonly ru: "предпросмотр удаления: delete() без confirm, ничего не удалено";
|
|
109
|
+
};
|
|
110
|
+
readonly delete: {
|
|
111
|
+
readonly level: "info";
|
|
112
|
+
readonly ru: "удаление выполнено: состав каскада, сверка с expect";
|
|
113
|
+
};
|
|
114
|
+
readonly restore: {
|
|
115
|
+
readonly level: "info";
|
|
116
|
+
readonly ru: "восстановление выполнено: восстановленные и пропущенные цели";
|
|
117
|
+
};
|
|
118
|
+
readonly load: {
|
|
119
|
+
readonly level: "info";
|
|
120
|
+
readonly ru: "db.load(): массовая загрузка завершена";
|
|
121
|
+
};
|
|
122
|
+
readonly lock: {
|
|
123
|
+
readonly level: "debug";
|
|
124
|
+
readonly ru: "db.lock(): advisory-блокировка в транзакции";
|
|
125
|
+
};
|
|
126
|
+
readonly 'tx.begin': {
|
|
127
|
+
readonly level: "debug";
|
|
128
|
+
readonly ru: "открыта транзакция: db.begin() или db.transaction()";
|
|
129
|
+
};
|
|
130
|
+
readonly 'tx.commit': {
|
|
131
|
+
readonly level: "debug";
|
|
132
|
+
readonly ru: "транзакция зафиксирована; с записью (db.begin()) и у db.transaction() — уровень info и detail.writes: доказательство фиксации событий с тем же tx";
|
|
133
|
+
};
|
|
134
|
+
readonly 'tx.rollback': {
|
|
135
|
+
readonly level: "info";
|
|
136
|
+
readonly ru: "транзакция откачена: явно или из-за ошибки";
|
|
137
|
+
};
|
|
138
|
+
readonly 'tx.retry': {
|
|
139
|
+
readonly level: "warn";
|
|
140
|
+
readonly ru: "повтор операции после конфликта (взаимная блокировка, сериализация, журнал)";
|
|
141
|
+
};
|
|
142
|
+
readonly 'auth.login': {
|
|
143
|
+
readonly level: "info";
|
|
144
|
+
readonly ru: "успешный вход: пароль, ключ, код, привязка";
|
|
145
|
+
};
|
|
146
|
+
readonly 'auth.fail': {
|
|
147
|
+
readonly level: "warn";
|
|
148
|
+
readonly ru: "неудачный вход или неверный второй фактор";
|
|
149
|
+
};
|
|
150
|
+
readonly 'auth.logout': {
|
|
151
|
+
readonly level: "info";
|
|
152
|
+
readonly ru: "выход: гашение текущей сессии";
|
|
153
|
+
};
|
|
154
|
+
readonly 'auth.revoke': {
|
|
155
|
+
readonly level: "info";
|
|
156
|
+
readonly ru: "отзыв: сессии по токену, все сессии аккаунта или кред";
|
|
157
|
+
};
|
|
158
|
+
readonly 'auth.switch': {
|
|
159
|
+
readonly level: "info";
|
|
160
|
+
readonly ru: "auth.switch(): сменён рабочий арендатор сессии";
|
|
161
|
+
};
|
|
162
|
+
readonly 'auth.as': {
|
|
163
|
+
readonly level: "debug";
|
|
164
|
+
readonly ru: "db.as(): фасад от имени другого аккаунта или арендатора";
|
|
165
|
+
};
|
|
166
|
+
readonly 'auth.session': {
|
|
167
|
+
readonly level: "info";
|
|
168
|
+
readonly ru: "сервис выпустил сессию пользователю (sessionFor)";
|
|
169
|
+
};
|
|
170
|
+
readonly 'auth.credential': {
|
|
171
|
+
readonly level: "info";
|
|
172
|
+
readonly ru: "кред заведён или изменён: пароль, ключ, TOTP, код, привязка, флаги";
|
|
173
|
+
};
|
|
174
|
+
readonly 'auth.call': {
|
|
175
|
+
readonly level: "debug";
|
|
176
|
+
readonly ru: "прочие вызовы db.auth: сведения о сессии, кредах, арендаторах";
|
|
177
|
+
};
|
|
178
|
+
readonly 'account.purge': {
|
|
179
|
+
readonly level: "info";
|
|
180
|
+
readonly ru: "аккаунт удалён с данными своего арендатора";
|
|
181
|
+
};
|
|
182
|
+
readonly 'acl.change': {
|
|
183
|
+
readonly level: "info";
|
|
184
|
+
readonly ru: "права изменены: grant, deny, revoke, roles";
|
|
185
|
+
};
|
|
186
|
+
readonly 'acl.check': {
|
|
187
|
+
readonly level: "debug";
|
|
188
|
+
readonly ru: "проверка или список прав";
|
|
189
|
+
};
|
|
190
|
+
readonly 'watch.start': {
|
|
191
|
+
readonly level: "info";
|
|
192
|
+
readonly ru: "подписка watch() открыта";
|
|
193
|
+
};
|
|
194
|
+
readonly 'watch.fetch': {
|
|
195
|
+
readonly level: "debug";
|
|
196
|
+
readonly ru: "подписка прочитала пачку событий журнала";
|
|
197
|
+
};
|
|
198
|
+
readonly 'watch.stop': {
|
|
199
|
+
readonly level: "info";
|
|
200
|
+
readonly ru: "подписка закрыта";
|
|
201
|
+
};
|
|
202
|
+
readonly signal: {
|
|
203
|
+
readonly level: "debug";
|
|
204
|
+
readonly ru: "получен сигнал базы (NOTIFY) или слушатель переподключился";
|
|
205
|
+
};
|
|
206
|
+
readonly 'signal.send': {
|
|
207
|
+
readonly level: "debug";
|
|
208
|
+
readonly ru: "отправлены накопленные сигналы записи";
|
|
209
|
+
};
|
|
210
|
+
readonly maintain: {
|
|
211
|
+
readonly level: "info";
|
|
212
|
+
readonly ru: "maintain(): обслуживание выполнено или пропущено";
|
|
213
|
+
};
|
|
214
|
+
readonly 'mcp.call': {
|
|
215
|
+
readonly level: "info";
|
|
216
|
+
readonly ru: "вызов инструмента MCP";
|
|
217
|
+
};
|
|
218
|
+
readonly warning: {
|
|
219
|
+
readonly level: "warn";
|
|
220
|
+
readonly ru: "предупреждение letopis";
|
|
221
|
+
};
|
|
222
|
+
readonly error: {
|
|
223
|
+
readonly level: "error";
|
|
224
|
+
readonly ru: "ошибка операции letopis: код, ключ каталога, подробности, причина; штатный отказ (exists, conflict, target_not_found, нарушения данных и т. п.) — уровень warn; у ошибки PostgreSQL — только SQLSTATE и имена объектов схемы";
|
|
225
|
+
};
|
|
226
|
+
readonly sql: {
|
|
227
|
+
readonly level: "debug";
|
|
228
|
+
readonly ru: "SQL-запрос: текст без значений параметров, время, число строк";
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
/** Имя события логирования. */
|
|
232
|
+
export type LogEventName = keyof typeof LOG_EVENTS;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
export const log = {
|
|
2
|
+
// log.ts, makeLog: logLevel не из списка; value — как передан (строка — в кавычках)
|
|
3
|
+
'log.bad_level': {
|
|
4
|
+
code: 'invalid_data',
|
|
5
|
+
ru: "logLevel {value}: ожидается 'debug', 'info', 'warn', 'error' или 'off'",
|
|
6
|
+
hint: "передать logLevel одной из строк 'debug', 'info', 'warn', 'error', 'off' (по умолчанию 'info')",
|
|
7
|
+
},
|
|
8
|
+
// log.ts, makeLog: log — не функция и не объект с методами уровней
|
|
9
|
+
'log.bad_logger': {
|
|
10
|
+
code: 'invalid_data',
|
|
11
|
+
ru: 'log: ожидается функция (событие) => void или объект с методами debug, info, warn, error (pino, console)',
|
|
12
|
+
hint: 'передать в log функцию или объект логгера (pino, console)',
|
|
13
|
+
},
|
|
14
|
+
// log.ts, makeLog: redact — не массив строк
|
|
15
|
+
'log.bad_redact': {
|
|
16
|
+
code: 'invalid_data',
|
|
17
|
+
ru: 'redact: ожидается массив имён полей (строк)',
|
|
18
|
+
hint: "передать redact списком имён полей, например ['email', 'phone']",
|
|
19
|
+
},
|
|
20
|
+
// log.ts, errorFields и causeOf: ошибка PostgreSQL в событии — только SQLSTATE и имена объектов схемы; её текст,
|
|
21
|
+
// DETAIL, WHERE и HINT могут нести значения параметров и данных и в журнал не идут (полный текст — у самой ошибки)
|
|
22
|
+
'log.db_error': {
|
|
23
|
+
code: 'internal',
|
|
24
|
+
ru: 'ошибка PostgreSQL {sqlstate} (текст, DETAIL, WHERE и HINT базы в журнал не пишутся — они у самой ошибки)',
|
|
25
|
+
},
|
|
26
|
+
// log.ts, deliver: исключение в логгере приложения — один раз на процесс в stderr; операция не прерывается
|
|
27
|
+
'log.logger_failed': {
|
|
28
|
+
code: 'internal',
|
|
29
|
+
ru: 'логгер бросил исключение на событии {event}: {message} — событие пропущено, операции это не мешает',
|
|
30
|
+
},
|
|
31
|
+
// index.ts, Notifier: отправка сигналов не удалась — предупреждение (warning); повтор — следующим интервалом
|
|
32
|
+
'log.notify_failed': {
|
|
33
|
+
code: 'internal',
|
|
34
|
+
ru: 'сигналы не отправлены: {message} — повтор следующим интервалом',
|
|
35
|
+
},
|
|
36
|
+
// index.ts, ctx.renew: обмен ключа сервиса на новую сессию не удался — предупреждение (warning)
|
|
37
|
+
'log.renew_failed': {
|
|
38
|
+
code: 'no_session',
|
|
39
|
+
ru: 'сессия по ключу сервиса истекла, а обмен ключа на новую не удался',
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Каталог событий логирования — объект (не массив): имя события → `{ level, ru }`, где `level` — уровень события по
|
|
44
|
+
* умолчанию (`debug`, `info`, `warn`, `error`), `ru` — что значит событие. Тип — `Readonly<Record<LogEventName,
|
|
45
|
+
* LogEventInfo>>`: `LOG_EVENTS.write.level` — `'info'`, список имён — `Object.keys(LOG_EVENTS)`. Основные события:
|
|
46
|
+
* connect, close, up, migrate, sync, read, cache.hit, cache.miss, write, delete.preview, delete, restore, tx.*,
|
|
47
|
+
* auth.login, auth.logout, auth.revoke, auth.switch, watch.start, watch.stop, signal, maintain, warning, error, sql;
|
|
48
|
+
* остальные — дополнительные.
|
|
49
|
+
*/
|
|
50
|
+
export const LOG_EVENTS = {
|
|
51
|
+
// подключение
|
|
52
|
+
'connect': { level: 'info', ru: 'connect() готов: схема, режим сигналов, кэш, способ входа' },
|
|
53
|
+
'close': { level: 'info', ru: 'db.close(): пул, подписки и таймеры закрыты' },
|
|
54
|
+
'registry.refresh': { level: 'debug', ru: 'реестр классов перечитан' },
|
|
55
|
+
'session.renew': { level: 'info', ru: 'сессия по ключу сервиса истекла — ключ обменян на новую' },
|
|
56
|
+
// установка
|
|
57
|
+
'up': { level: 'info', ru: 'up() завершён: схема поставлена, обновлена или накатана повторно' },
|
|
58
|
+
'up.step': { level: 'info', ru: 'шаг up(): то, что без логгера печатается в консоль' },
|
|
59
|
+
'migrate': { level: 'info', ru: 'up() обновил ревизию схемы миграциями' },
|
|
60
|
+
'tenant.create': { level: 'info', ru: 'арендатор (и его первый пользователь) заведён или найден' },
|
|
61
|
+
'sync': { level: 'info', ru: 'syncModels(): классы созданы, изменены или сверены (сухой прогон)' },
|
|
62
|
+
// чтение
|
|
63
|
+
'read': { level: 'debug', ru: 'терминал чтения цепочки: rows, first, ids, count, paths, versions, агрегаты' },
|
|
64
|
+
'cache.hit': { level: 'debug', ru: 'ответ взят из кэша результатов' },
|
|
65
|
+
'cache.miss': { level: 'debug', ru: 'ответа нет в кэше результатов — запрос к базе' },
|
|
66
|
+
'raw': { level: 'debug', ru: 'сырой SQL db.sql' },
|
|
67
|
+
// запись
|
|
68
|
+
'write': { level: 'info', ru: 'запись цепочкой (create, update, upsert, шаги ролей) или батч' },
|
|
69
|
+
'delete.preview': { level: 'debug', ru: 'предпросмотр удаления: delete() без confirm, ничего не удалено' },
|
|
70
|
+
'delete': { level: 'info', ru: 'удаление выполнено: состав каскада, сверка с expect' },
|
|
71
|
+
'restore': { level: 'info', ru: 'восстановление выполнено: восстановленные и пропущенные цели' },
|
|
72
|
+
'load': { level: 'info', ru: 'db.load(): массовая загрузка завершена' },
|
|
73
|
+
'lock': { level: 'debug', ru: 'db.lock(): advisory-блокировка в транзакции' },
|
|
74
|
+
// транзакции
|
|
75
|
+
'tx.begin': { level: 'debug', ru: 'открыта транзакция: db.begin() или db.transaction()' },
|
|
76
|
+
'tx.commit': { level: 'debug', ru: 'транзакция зафиксирована; с записью (db.begin()) и у db.transaction() — уровень info и detail.writes: доказательство фиксации событий с тем же tx' },
|
|
77
|
+
'tx.rollback': { level: 'info', ru: 'транзакция откачена: явно или из-за ошибки' },
|
|
78
|
+
'tx.retry': { level: 'warn', ru: 'повтор операции после конфликта (взаимная блокировка, сериализация, журнал)' },
|
|
79
|
+
// вход и права
|
|
80
|
+
'auth.login': { level: 'info', ru: 'успешный вход: пароль, ключ, код, привязка' },
|
|
81
|
+
'auth.fail': { level: 'warn', ru: 'неудачный вход или неверный второй фактор' },
|
|
82
|
+
'auth.logout': { level: 'info', ru: 'выход: гашение текущей сессии' },
|
|
83
|
+
'auth.revoke': { level: 'info', ru: 'отзыв: сессии по токену, все сессии аккаунта или кред' },
|
|
84
|
+
'auth.switch': { level: 'info', ru: 'auth.switch(): сменён рабочий арендатор сессии' },
|
|
85
|
+
'auth.as': { level: 'debug', ru: 'db.as(): фасад от имени другого аккаунта или арендатора' },
|
|
86
|
+
'auth.session': { level: 'info', ru: 'сервис выпустил сессию пользователю (sessionFor)' },
|
|
87
|
+
'auth.credential': { level: 'info', ru: 'кред заведён или изменён: пароль, ключ, TOTP, код, привязка, флаги' },
|
|
88
|
+
'auth.call': { level: 'debug', ru: 'прочие вызовы db.auth: сведения о сессии, кредах, арендаторах' },
|
|
89
|
+
'account.purge': { level: 'info', ru: 'аккаунт удалён с данными своего арендатора' },
|
|
90
|
+
'acl.change': { level: 'info', ru: 'права изменены: grant, deny, revoke, roles' },
|
|
91
|
+
'acl.check': { level: 'debug', ru: 'проверка или список прав' },
|
|
92
|
+
// время
|
|
93
|
+
'watch.start': { level: 'info', ru: 'подписка watch() открыта' },
|
|
94
|
+
'watch.fetch': { level: 'debug', ru: 'подписка прочитала пачку событий журнала' },
|
|
95
|
+
'watch.stop': { level: 'info', ru: 'подписка закрыта' },
|
|
96
|
+
'signal': { level: 'debug', ru: 'получен сигнал базы (NOTIFY) или слушатель переподключился' },
|
|
97
|
+
'signal.send': { level: 'debug', ru: 'отправлены накопленные сигналы записи' },
|
|
98
|
+
'maintain': { level: 'info', ru: 'maintain(): обслуживание выполнено или пропущено' },
|
|
99
|
+
// MCP
|
|
100
|
+
'mcp.call': { level: 'info', ru: 'вызов инструмента MCP' },
|
|
101
|
+
// общее
|
|
102
|
+
'warning': { level: 'warn', ru: 'предупреждение letopis' },
|
|
103
|
+
'error': { level: 'error', ru: 'ошибка операции letopis: код, ключ каталога, подробности, причина; штатный отказ (exists, conflict, target_not_found, нарушения данных и т. п.) — уровень warn; у ошибки PostgreSQL — только SQLSTATE и имена объектов схемы' },
|
|
104
|
+
'sql': { level: 'debug', ru: 'SQL-запрос: текст без значений параметров, время, число строк' },
|
|
105
|
+
};
|
package/dist/messages/mcp.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Неизвестное имя класса, алиаса или роли: агенту доступна не db.registry, а letopis_model. */
|
|
2
2
|
const NAME_HINT = 'проверить имя: похожие названы в тексте и в similar, классы, алиасы и концы — letopis_model';
|
|
3
|
-
/** Удаление сорвалось после
|
|
4
|
-
const PREVIEW_HINT = 'посмотреть
|
|
3
|
+
/** Удаление сорвалось после предпросмотра: предпросмотр — заново. */
|
|
4
|
+
const PREVIEW_HINT = 'посмотреть предпросмотр заново (delete без confirm) и повторить удаление с confirm: true';
|
|
5
5
|
/** Неверная опция createMcpServer. */
|
|
6
6
|
const OPTION_HINT = 'исправить опцию createMcpServer: допустимые значения названы в тексте';
|
|
7
7
|
export const mcp = {
|
|
@@ -300,7 +300,7 @@ export const mcp = {
|
|
|
300
300
|
// mcp.ts, write: код операции агента не совпал с превью (detail.operation — нынешний)
|
|
301
301
|
'mcp.delete_operation_changed': {
|
|
302
302
|
code: 'confirmation_required',
|
|
303
|
-
ru: 'letopis_write: операция изменилась после
|
|
303
|
+
ru: 'letopis_write: операция изменилась после предпросмотра — посмотрите предпросмотр заново',
|
|
304
304
|
hint: PREVIEW_HINT,
|
|
305
305
|
},
|
|
306
306
|
// mcp.ts, write: целей удаления не видно
|
|
@@ -308,10 +308,10 @@ export const mcp = {
|
|
|
308
308
|
code: 'target_not_found',
|
|
309
309
|
ru: 'letopis_write: удалять нечего — целей не видно',
|
|
310
310
|
},
|
|
311
|
-
// mcp.ts, write: в превью есть $action restrict (detail.preview)
|
|
311
|
+
// mcp.ts, write: в превью есть $action restrict или сводка скрытых строк $hidden restrict (detail.preview)
|
|
312
312
|
'mcp.delete_restricted': {
|
|
313
313
|
code: 'delete_restricted',
|
|
314
|
-
ru: 'letopis_write: удалению мешают строки с $action: restrict',
|
|
314
|
+
ru: 'letopis_write: удалению мешают строки с $action: restrict (или скрытые правами — сводка $hidden: restrict)',
|
|
315
315
|
},
|
|
316
316
|
// mcp.ts, confirmDelete (stateError): requestState не той операции, не того пользователя или подделан
|
|
317
317
|
'mcp.delete_foreign_answer': {
|
|
@@ -321,7 +321,7 @@ export const mcp = {
|
|
|
321
321
|
// mcp.ts, confirmDelete (stateError): срок requestState истёк
|
|
322
322
|
'mcp.delete_answer_expired': {
|
|
323
323
|
code: 'confirmation_required',
|
|
324
|
-
ru: 'letopis_write: удаление не выполнено — подтверждение устарело — посмотрите
|
|
324
|
+
ru: 'letopis_write: удаление не выполнено — подтверждение устарело — посмотрите предпросмотр и подтвердите удаление заново',
|
|
325
325
|
hint: PREVIEW_HINT,
|
|
326
326
|
},
|
|
327
327
|
// mcp.ts, confirmDelete: человек отказал или закрыл окно
|
|
@@ -337,7 +337,7 @@ export const mcp = {
|
|
|
337
337
|
// mcp.ts, write: повторное превью в транзакции разошлось с подтверждённым
|
|
338
338
|
'mcp.delete_data_changed': {
|
|
339
339
|
code: 'confirmation_required',
|
|
340
|
-
ru: 'letopis_write: данные изменились после подтверждения — посмотрите
|
|
340
|
+
ru: 'letopis_write: данные изменились после подтверждения — посмотрите предпросмотр заново',
|
|
341
341
|
hint: PREVIEW_HINT,
|
|
342
342
|
},
|
|
343
343
|
// mcp.ts, limitsOf: maxRows, maxBytes — не целое из диапазона
|
package/dist/messages/model.d.ts
CHANGED
|
@@ -136,11 +136,19 @@ export declare const model: {
|
|
|
136
136
|
code: "invalid_data";
|
|
137
137
|
ru: string;
|
|
138
138
|
};
|
|
139
|
+
'model.issue_additional': {
|
|
140
|
+
code: "invalid_data";
|
|
141
|
+
ru: string;
|
|
142
|
+
};
|
|
139
143
|
'model.issue_date': {
|
|
140
144
|
code: "invalid_data";
|
|
141
145
|
ru: string;
|
|
142
146
|
};
|
|
143
|
-
'model.
|
|
147
|
+
'model.issue_string_too_short': {
|
|
148
|
+
code: "invalid_data";
|
|
149
|
+
ru: string;
|
|
150
|
+
};
|
|
151
|
+
'model.issue_string_too_long': {
|
|
144
152
|
code: "invalid_data";
|
|
145
153
|
ru: string;
|
|
146
154
|
};
|
|
@@ -165,6 +173,16 @@ export declare const model: {
|
|
|
165
173
|
ru: string;
|
|
166
174
|
hint: string;
|
|
167
175
|
};
|
|
176
|
+
'model.end_role_system': {
|
|
177
|
+
code: "invalid_class";
|
|
178
|
+
ru: string;
|
|
179
|
+
hint: string;
|
|
180
|
+
};
|
|
181
|
+
'model.end_role_taken': {
|
|
182
|
+
code: "invalid_class";
|
|
183
|
+
ru: string;
|
|
184
|
+
hint: string;
|
|
185
|
+
};
|
|
168
186
|
'model.models_cycle': {
|
|
169
187
|
code: "invalid_class";
|
|
170
188
|
ru: string;
|
|
@@ -226,8 +244,29 @@ export declare const model: {
|
|
|
226
244
|
code: "invalid_query";
|
|
227
245
|
ru: string;
|
|
228
246
|
};
|
|
247
|
+
'model.cli_unknown_flag': {
|
|
248
|
+
code: "invalid_query";
|
|
249
|
+
ru: string;
|
|
250
|
+
};
|
|
251
|
+
'model.cli_flag_needs_value': {
|
|
252
|
+
code: "invalid_query";
|
|
253
|
+
ru: string;
|
|
254
|
+
};
|
|
255
|
+
'model.cli_flag_no_value': {
|
|
256
|
+
code: "invalid_query";
|
|
257
|
+
ru: string;
|
|
258
|
+
};
|
|
259
|
+
'model.cli_unexpected_arg': {
|
|
260
|
+
code: "invalid_query";
|
|
261
|
+
ru: string;
|
|
262
|
+
};
|
|
229
263
|
'model.types_header': {
|
|
230
264
|
code: "invalid_query";
|
|
231
265
|
ru: string;
|
|
232
266
|
};
|
|
267
|
+
'model.transform_unsupported': {
|
|
268
|
+
code: "invalid_class";
|
|
269
|
+
ru: string;
|
|
270
|
+
hint: string;
|
|
271
|
+
};
|
|
233
272
|
};
|
package/dist/messages/model.js
CHANGED
|
@@ -168,15 +168,25 @@ export const model = {
|
|
|
168
168
|
// validate.ts, compileValidator: сообщения нарушений issues[].message — тексты не для ошибки (lmsg), те же, что у базы
|
|
169
169
|
'model.issue_enum': {
|
|
170
170
|
code: 'invalid_data',
|
|
171
|
-
ru: 'значение не из
|
|
171
|
+
ru: 'значение не из перечисления: допустимо {values}',
|
|
172
|
+
},
|
|
173
|
+
// лишний ключ объекта (additionalProperties: false); keys — имена лишних ключей через запятую
|
|
174
|
+
'model.issue_additional': {
|
|
175
|
+
code: 'invalid_data',
|
|
176
|
+
ru: 'лишний ключ {keys}',
|
|
172
177
|
},
|
|
173
178
|
'model.issue_date': {
|
|
174
179
|
code: 'invalid_data',
|
|
175
180
|
ru: 'такой даты не бывает',
|
|
176
181
|
},
|
|
177
|
-
|
|
182
|
+
// minLength, maxLength: limit — граница из описания (длина в символах)
|
|
183
|
+
'model.issue_string_too_short': {
|
|
178
184
|
code: 'invalid_data',
|
|
179
|
-
ru: 'длина строки
|
|
185
|
+
ru: 'длина строки меньше {limit}',
|
|
186
|
+
},
|
|
187
|
+
'model.issue_string_too_long': {
|
|
188
|
+
code: 'invalid_data',
|
|
189
|
+
ru: 'длина строки больше {limit}',
|
|
180
190
|
},
|
|
181
191
|
'model.issue_unique_items': {
|
|
182
192
|
code: 'invalid_data',
|
|
@@ -202,6 +212,20 @@ export const model = {
|
|
|
202
212
|
ru: 'syncModels: имя хаба {name} занято методом цепочки или корня db — шаг с таким именем до класса не дойдёт',
|
|
203
213
|
hint: 'дать классу другое имя: зарезервированные имена — в README, «Справочник API → Зарезервированные имена»',
|
|
204
214
|
},
|
|
215
|
+
// sync.ts, syncModels: роль конца модели занята системным классом (member: User, Tenant → Account; rule: Group,
|
|
216
|
+
// Object → Resource) и ведёт на другой класс — отказ до записи (база отклонила бы sql-write.end_other_class)
|
|
217
|
+
'model.end_role_system': {
|
|
218
|
+
code: 'invalid_class',
|
|
219
|
+
ru: 'syncModels: имя роли {end} в классе {model} занято системным классом {cls} (там {end} ведёт на {target}) — выберите другое имя роли, например Team вместо Group',
|
|
220
|
+
hint: 'переименовать роль конца: имена ролей User, Tenant (системный класс member, ведут на Account), Group, Object (системный класс rule, ведут на Resource) можно брать, только если конец ведёт туда же; список — в README, «Зарезервированные имена»',
|
|
221
|
+
},
|
|
222
|
+
// sync.ts, syncModels: роль конца модели уже ведёт на другой класс в другом классе арендатора (или в другой модели
|
|
223
|
+
// того же вызова) — отказ до записи (база отклонила бы sql-write.end_other_class)
|
|
224
|
+
'model.end_role_taken': {
|
|
225
|
+
code: 'invalid_class',
|
|
226
|
+
ru: 'syncModels: роль {end} в классе {model} ведёт на {mine}, а в классе {cls} — на {target}: имя роли одно на арендатора (это имя шага цепочки)',
|
|
227
|
+
hint: 'дать роли другое имя или направить её на тот же класс, что и в другом классе',
|
|
228
|
+
},
|
|
205
229
|
// sync.ts, syncModels: родители замыкают круг; cycle — имена моделей через стрелку
|
|
206
230
|
'model.models_cycle': {
|
|
207
231
|
code: 'invalid_class',
|
|
@@ -275,9 +299,34 @@ export const model = {
|
|
|
275
299
|
code: 'invalid_query',
|
|
276
300
|
ru: 'правило {kind} в {path} проверяется только в библиотеке — в базе его нет',
|
|
277
301
|
},
|
|
302
|
+
// cli.ts, main: ошибка разбора аргументов (node:util parseArgs) — текст по-русски вместо английского текста Node (lmsg,
|
|
303
|
+
// код не печатается; выход с кодом 2). flag — флаг, как его передали (--aply, -x); arg — лишний аргумент
|
|
304
|
+
'model.cli_unknown_flag': {
|
|
305
|
+
code: 'invalid_query',
|
|
306
|
+
ru: 'неизвестный флаг {flag}; см. letopis --help',
|
|
307
|
+
},
|
|
308
|
+
'model.cli_flag_needs_value': {
|
|
309
|
+
code: 'invalid_query',
|
|
310
|
+
ru: 'флагу {flag} нужно значение: {flag} <значение> или {flag}=<значение>; см. letopis --help',
|
|
311
|
+
},
|
|
312
|
+
'model.cli_flag_no_value': {
|
|
313
|
+
code: 'invalid_query',
|
|
314
|
+
ru: 'флаг {flag} не принимает значения — уберите «=…» после него; см. letopis --help',
|
|
315
|
+
},
|
|
316
|
+
'model.cli_unexpected_arg': {
|
|
317
|
+
code: 'invalid_query',
|
|
318
|
+
ru: 'лишний аргумент {arg}; см. letopis --help',
|
|
319
|
+
},
|
|
278
320
|
// sync.ts, generateTypes: пометка в первой строке файла типов (после «// ») — текст не для ошибки
|
|
279
321
|
'model.types_header': {
|
|
280
322
|
code: 'invalid_query',
|
|
281
323
|
ru: 'Сгенерировано letopis types — не править руками.',
|
|
282
324
|
},
|
|
325
|
+
// sync.ts, syncModels: в модели есть преобразование Zod (.trim(), .toLowerCase(), .transform(), z.preprocess …) — база
|
|
326
|
+
// и валидатор letopis его не исполняют, данные записались бы как есть; rules — пути и виды через запятую
|
|
327
|
+
'model.transform_unsupported': {
|
|
328
|
+
code: 'invalid_class',
|
|
329
|
+
ru: 'в модели есть преобразования Zod, а при записи их никто не исполняет — значение записалось бы как есть; поля с преобразованием: {rules}',
|
|
330
|
+
hint: 'уберите из модели .trim(), .toLowerCase(), .transform(), z.preprocess() и .pipe() и приводите значение в коде сервиса до записи (например, name.trim()); проверку без изменения значения дают .regex(), .min(), .refine()',
|
|
331
|
+
},
|
|
283
332
|
};
|
package/dist/messages/query.d.ts
CHANGED
|
@@ -3,6 +3,11 @@ export declare const query: {
|
|
|
3
3
|
code: "invalid_query";
|
|
4
4
|
ru: string;
|
|
5
5
|
};
|
|
6
|
+
'query.sort_field_data': {
|
|
7
|
+
code: "invalid_query";
|
|
8
|
+
ru: string;
|
|
9
|
+
hint: string;
|
|
10
|
+
};
|
|
6
11
|
'query.unknown_field': {
|
|
7
12
|
code: "invalid_query";
|
|
8
13
|
ru: string;
|
|
@@ -124,6 +129,11 @@ export declare const query: {
|
|
|
124
129
|
code: "invalid_query";
|
|
125
130
|
ru: string;
|
|
126
131
|
};
|
|
132
|
+
'query.bad_uuid': {
|
|
133
|
+
code: "invalid_query";
|
|
134
|
+
ru: string;
|
|
135
|
+
hint: string;
|
|
136
|
+
};
|
|
127
137
|
'query.agg_field': {
|
|
128
138
|
code: "invalid_query";
|
|
129
139
|
ru: string;
|
package/dist/messages/query.js
CHANGED
|
@@ -4,6 +4,12 @@ export const query = {
|
|
|
4
4
|
code: 'invalid_query',
|
|
5
5
|
ru: "sort: поле 'at', 'rev', 'id' или 'data.<путь>', а не '{field}'",
|
|
6
6
|
},
|
|
7
|
+
// sql.ts, sortSpec: поле sort() похоже на имя поля данных без префикса data. (sort('code'))
|
|
8
|
+
'query.sort_field_data': {
|
|
9
|
+
code: 'invalid_query',
|
|
10
|
+
ru: "sort: поле 'at', 'rev', 'id' или 'data.<путь>', а не '{field}' — может быть, data.{field}?",
|
|
11
|
+
hint: "поле данных в sort() — с префиксом data.: sort('data.code'); колонки строки — 'at' (время версии), 'rev', 'id'",
|
|
12
|
+
},
|
|
7
13
|
// sql.ts, checkField: поле фильтра, sort() или агрегата не описано ни в одном классе шага (в 1.5 — предупреждение, с 2.0 —
|
|
8
14
|
// отказ); where — шаг или вызов, как в коде: Shop({ nmae }), sort('data.nmae'), sum('data.nmae')
|
|
9
15
|
'query.unknown_field': {
|
|
@@ -150,6 +156,13 @@ export const query = {
|
|
|
150
156
|
code: 'invalid_query',
|
|
151
157
|
ru: 'after(cursor) требует sort(поле)',
|
|
152
158
|
},
|
|
159
|
+
// sql.ts, compileFilter: id шага, фильтра { id } или конца — не uuid (раньше — сырая ошибка PostgreSQL 22P02, у
|
|
160
|
+
// null — TypeError); value — значение, как в коде
|
|
161
|
+
'query.bad_uuid': {
|
|
162
|
+
code: 'invalid_query',
|
|
163
|
+
ru: '{where}: {value} — не uuid',
|
|
164
|
+
hint: 'id — строка uuid (row.id из ответа или db.idOf(…)); проверьте переменную: undefined и null — не id',
|
|
165
|
+
},
|
|
153
166
|
// sql.ts, buildRead: агрегат не по полю данных
|
|
154
167
|
'query.agg_field': {
|
|
155
168
|
code: 'invalid_query',
|
|
@@ -11,6 +11,11 @@ export declare const sqlCore: {
|
|
|
11
11
|
code: "acl_denied";
|
|
12
12
|
ru: string;
|
|
13
13
|
};
|
|
14
|
+
'sql-core.impersonation_no_account': {
|
|
15
|
+
code: "target_not_found";
|
|
16
|
+
ru: string;
|
|
17
|
+
hint: string;
|
|
18
|
+
};
|
|
14
19
|
'sql-core.impersonation_denied': {
|
|
15
20
|
code: "acl_denied";
|
|
16
21
|
ru: string;
|
|
@@ -22,6 +27,7 @@ export declare const sqlCore: {
|
|
|
22
27
|
'sql-core.bad_api_key': {
|
|
23
28
|
code: "no_session";
|
|
24
29
|
ru: string;
|
|
30
|
+
hint: string;
|
|
25
31
|
};
|
|
26
32
|
'sql-core.pattern_trailing_backslash': {
|
|
27
33
|
code: "invalid_class";
|
|
@@ -83,7 +89,11 @@ export declare const sqlCore: {
|
|
|
83
89
|
code: "invalid_class";
|
|
84
90
|
ru: string;
|
|
85
91
|
};
|
|
86
|
-
'sql-core.
|
|
92
|
+
'sql-core.issue_string_too_short': {
|
|
93
|
+
code: "invalid_data";
|
|
94
|
+
ru: string;
|
|
95
|
+
};
|
|
96
|
+
'sql-core.issue_string_too_long': {
|
|
87
97
|
code: "invalid_data";
|
|
88
98
|
ru: string;
|
|
89
99
|
};
|
|
@@ -103,6 +113,10 @@ export declare const sqlCore: {
|
|
|
103
113
|
code: "invalid_data";
|
|
104
114
|
ru: string;
|
|
105
115
|
};
|
|
116
|
+
'sql-core.issue_additional': {
|
|
117
|
+
code: "invalid_data";
|
|
118
|
+
ru: string;
|
|
119
|
+
};
|
|
106
120
|
'sql-core.issue_rule': {
|
|
107
121
|
code: "invalid_data";
|
|
108
122
|
ru: string;
|