@coopenomics/extension-kit 2026.8.18-2

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.
@@ -0,0 +1,1516 @@
1
+ import * as _nestjs_passport from '@nestjs/passport';
2
+ import * as _nestjs_common from '@nestjs/common';
3
+ import { ExecutionContext, CanActivate, OnModuleInit, Provider, HttpException, HttpStatus } from '@nestjs/common';
4
+ import { Reflector } from '@nestjs/core';
5
+ import { Observable } from 'rxjs';
6
+ import { ZodObject } from 'zod';
7
+ import { Cooperative } from 'cooptypes';
8
+
9
+ /**
10
+ * Пути внутри объекта, по которым пайщик признаётся «своим» для поля.
11
+ *
12
+ * Записываются от корня самого объекта: `trustee.username` — одно значение,
13
+ * `trusted[].username` — значения из массива. Если хотя бы одно совпало с
14
+ * именем аккаунта запрашивающего, поле отдаётся ему независимо от роли в
15
+ * кооперативе.
16
+ */
17
+ interface AuthRolesOptions {
18
+ self?: string[];
19
+ }
20
+ /**
21
+ * Ограничение доступа к резолверу или к отдельному полю объекта.
22
+ *
23
+ * Роли — это капабилити уровня кооператива (`chairman`, `member`, `user`).
24
+ * Их недостаточно там, где данные принадлежат самому пайщику: председатель
25
+ * кооперативного участка для кооператива — обычный пайщик, и по ролям он не
26
+ * может прочитать даже собственный участок.
27
+ *
28
+ * Для таких полей задаётся `self`: пути внутри объекта, по которым проверяется
29
+ * принадлежность. Это тот же принцип, что квалификаторы `:own` / `:own-KU` в
30
+ * матрице доступа расширений, — роль отвечает за «такой род данных вообще
31
+ * доступен», а принадлежность проверяется по самим данным.
32
+ *
33
+ * Метаданные читает `RolesGuard`, директива `@auth` попадает в схему как
34
+ * документация.
35
+ *
36
+ * ```ts
37
+ * // председатель кооператива и совет видят состав любого участка,
38
+ * // а председатель участка и его доверенные — состав своего
39
+ * @AuthRoles(['chairman', 'member'], { self: ['trustee.username', 'trusted[].username'] })
40
+ * public readonly trusted: IndividualDTO[];
41
+ * ```
42
+ */
43
+ declare function AuthRoles(roles: string[], options?: AuthRolesOptions): PropertyDecorator & MethodDecorator & ClassDecorator;
44
+ /** Текущий пользователь запроса. Бросает, если запрос не авторизован. */
45
+ declare const CurrentUser: (...dataOrPipes: unknown[]) => ParameterDecorator;
46
+ /**
47
+ * Текущий пользователь либо `null`, если запрос гостевой. В паре с
48
+ * `OptionalGqlJwtAuthGuard`: не бросает, не требует авторизации. Для ручек,
49
+ * открытых и гостю, где ответ зависит от того, кто спрашивает.
50
+ */
51
+ declare const OptionalCurrentUser: (...dataOrPipes: unknown[]) => ParameterDecorator;
52
+
53
+ declare const GqlJwtAuthGuard_base: _nestjs_passport.Type<_nestjs_passport.IAuthGuard>;
54
+ /** JWT-гард для GraphQL. При валидном `server-secret` проверка не выполняется. */
55
+ declare class GqlJwtAuthGuard extends GqlJwtAuthGuard_base {
56
+ getRequest(context: ExecutionContext): any;
57
+ canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean>;
58
+ }
59
+ declare const OptionalGqlJwtAuthGuard_base: _nestjs_passport.Type<_nestjs_passport.IAuthGuard>;
60
+ /**
61
+ * Опциональный JWT-гард для GraphQL: НЕ бросает при отсутствии или невалидности
62
+ * токена, оставляет `request.user` пустым. Для запросов, доступных и гостю,
63
+ * и пайщику, где состав ответа зависит от того, кто спрашивает.
64
+ */
65
+ declare class OptionalGqlJwtAuthGuard extends OptionalGqlJwtAuthGuard_base {
66
+ getRequest(context: ExecutionContext): any;
67
+ handleRequest(_err: any, user: any): any;
68
+ }
69
+ declare const HttpJwtAuthGuard_base: _nestjs_passport.Type<_nestjs_passport.IAuthGuard>;
70
+ /** JWT-гард для обычных HTTP-ручек (не GraphQL). */
71
+ declare class HttpJwtAuthGuard extends HttpJwtAuthGuard_base {
72
+ getRequest(context: ExecutionContext): any;
73
+ canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean>;
74
+ }
75
+ /**
76
+ * Проверка доступа по ролям из `@AuthRoles`.
77
+ *
78
+ * 1. Валидный `server-secret` — доступ разрешён.
79
+ * 2. Роли не заданы — доступ открыт.
80
+ * 3. Пользователь обращается к своим ресурсам (`username` вложенный в `data`/`filter`
81
+ * либо плоским аргументом совпадает с `user.username`) — разрешено.
82
+ * 4. У пользователя есть одна из разрешённых ролей — разрешено.
83
+ * 5. Иначе — отказ.
84
+ */
85
+ declare class RolesGuard implements CanActivate {
86
+ private reflector;
87
+ constructor(reflector: Reflector);
88
+ canActivate(context: ExecutionContext): boolean;
89
+ }
90
+ /**
91
+ * Разрешает доступ только пайщикам в статусе `active`.
92
+ * При валидном `server-secret` проверка не выполняется — как в `RolesGuard`.
93
+ */
94
+ declare class ActiveUserStatusGuard implements CanActivate {
95
+ canActivate(context: ExecutionContext): boolean;
96
+ }
97
+
98
+ interface ExtensionAuthOptions {
99
+ /** Значение заголовка `server-secret`, дающего межсервисный доступ. */
100
+ serverSecret: string;
101
+ }
102
+ declare function configureExtensionAuth(options: ExtensionAuthOptions): void;
103
+ /**
104
+ * Совпадает ли заголовок запроса с настроенным секретом.
105
+ * Пока `configureExtensionAuth` не вызван, обхода нет — это безопасный дефолт:
106
+ * забытая настройка приводит к отказу в доступе, а не к его выдаче.
107
+ */
108
+ declare function hasServerSecret(headers: Record<string, any> | undefined): boolean;
109
+
110
+ /**
111
+ * Установленное расширение: имя, включённость, конфиг и версия схемы конфига.
112
+ * Конфиг типизируется расширением через `TConfig` (обычно `z.infer<typeof Schema>`).
113
+ */
114
+ interface ExtensionDomainInterface<TConfig = any> {
115
+ name: string;
116
+ enabled: boolean;
117
+ config: TConfig;
118
+ schema_version?: number;
119
+ created_at?: Date;
120
+ updated_at?: Date;
121
+ }
122
+ declare class ExtensionDomainEntity<TConfig = any> implements ExtensionDomainInterface<TConfig> {
123
+ readonly name: string;
124
+ readonly enabled: boolean;
125
+ readonly config: TConfig;
126
+ readonly created_at: Date;
127
+ readonly updated_at: Date;
128
+ readonly schema_version: number;
129
+ constructor(name: string, enabled: boolean, config: TConfig, created_at: Date, updated_at: Date, schema_version?: number);
130
+ }
131
+
132
+ /**
133
+ * Базовый класс расширения. От него наследуется класс `<X>Extension` каждого расширения:
134
+ * он объявляет имя, схему и дефолты конфига и получает установленную запись расширения.
135
+ */
136
+ declare abstract class BaseExtensionModule implements OnModuleInit {
137
+ abstract name: string;
138
+ abstract extension: ExtensionDomainEntity<any>;
139
+ configSchemas: ZodObject<any>;
140
+ abstract defaultConfig: Record<string, any>;
141
+ onModuleInit(): Promise<void>;
142
+ abstract initialize(): Promise<void>;
143
+ }
144
+
145
+ /**
146
+ * Сумма платежа в разбивке на тело и комиссию — то, что способ оплаты выдаёт
147
+ * пайщику вместе с реквизитами.
148
+ *
149
+ * Форма намеренно повторяет `InnerPaymentDetails` из `@coopenomics/innercoop`,
150
+ * а не импортируется оттуда: пакеты ортогональны и друг от друга не зависят
151
+ * (INV-007). Совместимость структурная — так же сделаны `ISyncLogger` и
152
+ * `SignedDigitalDocumentInputDTO`.
153
+ */
154
+ interface PaymentDetails {
155
+ /** Реквизиты, QR-код или токен провайдера — форма зависит от способа оплаты. */
156
+ data: any;
157
+ amount_plus_fee: string;
158
+ amount_without_fee: string;
159
+ fee_amount: string;
160
+ fee_percent: number;
161
+ fact_fee_percent: number;
162
+ tolerance_percent: number;
163
+ }
164
+ /**
165
+ * Базовый класс расширения-способа оплаты.
166
+ *
167
+ * Наследуется расширением, которое умеет выставлять счёт: эквайринг, СБП,
168
+ * касса банка. Само расширение кладёт себя в реестр способов оплаты при
169
+ * запуске, а расчётный контур ядра вызывает у него `createPayment`, когда
170
+ * пайщик выбрал этот способ.
171
+ *
172
+ * `tolerance_percent` — допустимое отклонение пришедшей суммы от ожидаемой:
173
+ * банк может округлить или удержать свою комиссию, и платёж на копейку меньше
174
+ * обязан приниматься. `fee_percent` — комиссия способа оплаты, она добавляется
175
+ * к сумме и оплачивается сверх.
176
+ */
177
+ declare abstract class PaymentProvider extends BaseExtensionModule {
178
+ abstract tolerance_percent: number;
179
+ abstract fee_percent: number;
180
+ abstract createPayment(hash: string): Promise<PaymentDetails>;
181
+ }
182
+ /**
183
+ * Способ оплаты, который узнаёт о зачислении опросом, а не уведомлением банка.
184
+ *
185
+ * Так устроен приём по банковской выписке: банк ничего не присылает, и
186
+ * расширение само периодически сверяет выписку с ожидающими платежами.
187
+ * `sync` вызывается по расписанию и обязан быть безопасным при наложении
188
+ * запусков — очередной опрос может начаться, пока предыдущий не закончился.
189
+ */
190
+ declare abstract class PollingProvider extends PaymentProvider {
191
+ abstract sync(): Promise<void>;
192
+ }
193
+ /**
194
+ * Способ оплаты, которому банк сам присылает уведомление о зачислении.
195
+ *
196
+ * Маршрут для уведомления расширение открывает само; форма запроса своя у
197
+ * каждого банка, поэтому здесь она не описана. Уведомление приходит без
198
+ * гарантии однократности — банк повторяет его, пока не получит подтверждения,
199
+ * поэтому `handleIPN` обязан быть идемпотентным.
200
+ */
201
+ declare abstract class IPNProvider extends PaymentProvider {
202
+ abstract handleIPN(request: any): Promise<void>;
203
+ }
204
+
205
+ /**
206
+ * Объявление хранилища файлов, которое заводит себе расширение.
207
+ *
208
+ * Форма намеренно повторяет `InnerFileStorageBucketSpec` из
209
+ * `@coopenomics/innercoop`, а не импортируется оттуда: пакеты ортогональны
210
+ * (INV-007), совместимость структурная — как у `PaymentDetails`.
211
+ */
212
+ interface BucketSpec {
213
+ /** Логическое имя в виде `<расширение>:<назначение>`. */
214
+ name: string;
215
+ /** Предел размера одного файла, байт. */
216
+ maxBytes: number;
217
+ /** Разрешённые типы содержимого; всё остальное отвергается на записи. */
218
+ allowedMime: readonly string[];
219
+ /** Какие метаданные обязательны, а какие нет: проверяется при записи. */
220
+ metadataSchema?: Readonly<Record<string, 'required' | 'optional'>>;
221
+ /** Срок жизни ссылки на чтение по умолчанию, секунды. */
222
+ defaultUrlTtlSeconds?: number;
223
+ }
224
+ interface RegisteredBucket {
225
+ readonly cls: {
226
+ readonly name: string;
227
+ };
228
+ readonly spec: BucketSpec;
229
+ }
230
+ /**
231
+ * Реестр объявленных хранилищ. Наполняется декоратором при загрузке модулей,
232
+ * читается ядром, когда оно создаёт сами хранилища.
233
+ *
234
+ * Один сервис — одно хранилище: повторное объявление под другим именем
235
+ * запрещено, иначе файлы одного сервиса разъехались бы по двум местам, и
236
+ * прочитать записанное вчера стало бы нечем.
237
+ */
238
+ declare const BucketRegistry: {
239
+ add(cls: {
240
+ name: string;
241
+ }, spec: BucketSpec): void;
242
+ get(cls: {
243
+ name: string;
244
+ }): BucketSpec | undefined;
245
+ list(): readonly RegisteredBucket[];
246
+ /** Только для тестов: очистка реестра между сценариями. */
247
+ _resetForTests(): void;
248
+ };
249
+ /** DI-токен хранилища конкретного сервиса. */
250
+ declare function bucketTokenFor(cls: {
251
+ name: string;
252
+ }): string;
253
+ /**
254
+ * Объявить хранилище сервиса.
255
+ *
256
+ * @example
257
+ * ```ts
258
+ * @UseBucket({ name: 'stol-zakazov:images', maxBytes: 10 * MB, allowedMime: ['image/jpeg'] })
259
+ * @Injectable()
260
+ * export class OrderImagesService {
261
+ * constructor(@InjectBucket() private readonly bucket: InnerFileStorageBucket) {}
262
+ * }
263
+ * ```
264
+ */
265
+ declare function UseBucket(spec: BucketSpec): ClassDecorator;
266
+ /** Получить объявленное хранилище в конструкторе сервиса. */
267
+ declare function InjectBucket(): ParameterDecorator;
268
+
269
+ /**
270
+ * Источник хранилищ — та сторона, что умеет создать хранилище по объявлению.
271
+ * Описан структурно, а не импортом `IFileStoragePort` из `@coopenomics/innercoop`:
272
+ * пакеты ортогональны (INV-007), совместимость проверяется по форме.
273
+ */
274
+ interface BucketSource {
275
+ getBucket(spec: BucketSpec): unknown;
276
+ }
277
+ /**
278
+ * Провайдеры хранилищ для сервисов, объявивших их через `@UseBucket`.
279
+ *
280
+ * Расширение кладёт результат прямо в `providers` своего модуля — рядом с самими
281
+ * сервисами, — и каждый из них получает своё хранилище через `@InjectBucket()`.
282
+ * Раньше ту же связку делал динамический модуль ядра (`forFeature`), то есть
283
+ * расширению приходилось знать путь внутрь монолита; теперь всё, что для этого
284
+ * нужно, лежит в каркасе, а токен порта расширение передаёт само — оно и так
285
+ * зависит от контракта, а каркас про контракт по-прежнему не знает.
286
+ *
287
+ * @param fileStoragePortToken токен стороны, создающей хранилища (`FILE_STORAGE_PORT`).
288
+ * @param consumers классы, помеченные `@UseBucket`.
289
+ *
290
+ * @example
291
+ * ```ts
292
+ * @Module({
293
+ * providers: [
294
+ * ...bucketProvidersFor(FILE_STORAGE_PORT, [OrderImagesService]),
295
+ * OrderImagesService,
296
+ * ],
297
+ * })
298
+ * ```
299
+ */
300
+ declare function bucketProvidersFor(fileStoragePortToken: symbol | string, consumers: ReadonlyArray<{
301
+ name: string;
302
+ }>): Provider[];
303
+
304
+ declare class SignatureInfoInputDTO {
305
+ readonly id: number;
306
+ readonly signer: string;
307
+ readonly public_key: string;
308
+ readonly signature: string;
309
+ readonly signed_at: string;
310
+ readonly signed_hash: string;
311
+ readonly meta: string;
312
+ }
313
+ declare class SignedDigitalDocumentInputDTO {
314
+ readonly version: string;
315
+ readonly hash: string;
316
+ readonly doc_hash: string;
317
+ readonly meta_hash: string;
318
+ readonly meta: any;
319
+ readonly signatures: SignatureInfoInputDTO[];
320
+ constructor(data: SignedDigitalDocumentInputDTO);
321
+ /**
322
+ * Преобразует подписанный документ DTO в формат IChainDocument для блокчейна
323
+ */
324
+ toDocument(): Cooperative.Document.IChainDocument2;
325
+ }
326
+
327
+ /** Язык, на котором формируется документ. */
328
+ declare enum LangType {
329
+ ru = "ru"
330
+ }
331
+
332
+ declare class MetaDocumentInputDTO implements Cooperative.Document.IMetaDocument {
333
+ title: string;
334
+ registry_id: number;
335
+ lang: LangType;
336
+ generator: string;
337
+ version: string;
338
+ coopname: string;
339
+ username: string;
340
+ created_at: string;
341
+ block_num: number;
342
+ timezone: string;
343
+ links: string[];
344
+ }
345
+
346
+ declare class GenerateMetaDocumentInputDTO implements Cooperative.Document.IGenerate {
347
+ title?: string;
348
+ registry_id: number;
349
+ coopname: string;
350
+ username: string;
351
+ lang?: LangType;
352
+ generator?: string;
353
+ version?: string;
354
+ created_at?: string;
355
+ block_num?: number;
356
+ timezone?: string;
357
+ links?: string[];
358
+ }
359
+
360
+ type Action = Cooperative.Registry.ExpenseProposalStatement.Action;
361
+ type ItemAction = Cooperative.Registry.ExpenseProposalStatement.IExpenseItem;
362
+ type HeaderAction = Cooperative.Registry.ExpenseProposalStatement.IExpenseProposalHeader;
363
+ /**
364
+ * Позиция-вход генерации СЗ-документа. Приватные поля (имя/реквизиты/назначение)
365
+ * — это вход для фабрики: сервер сохраняет их off-chain в doc_data и публикует
366
+ * в meta только `doc_data_hash`. На on-chain эти поля НЕ попадают.
367
+ */
368
+ declare class ExpenseProposalItemInputDTO {
369
+ number: string;
370
+ description: string;
371
+ amount: string;
372
+ recipient_type: 'SELF' | 'MEMBER' | 'ORG';
373
+ mechanics: 'ADVANCE' | 'DIRECT';
374
+ recipient_name?: string;
375
+ requisites?: string;
376
+ payment_purpose?: string;
377
+ payment_method_id?: string;
378
+ recipient_username?: string;
379
+ }
380
+ /**
381
+ * Публичная позиция подписанной meta — ровно то, что публикуется on-chain.
382
+ * Без имени/реквизитов/назначения платежа (они off-chain в doc_data).
383
+ */
384
+ declare class ExpenseProposalSignedItemInputDTO implements ItemAction {
385
+ number: string;
386
+ description: string;
387
+ amount: string;
388
+ recipient_type: 'SELF' | 'MEMBER' | 'ORG';
389
+ mechanics: 'ADVANCE' | 'DIRECT';
390
+ }
391
+ declare class ExpenseProposalHeaderInputDTO implements HeaderAction {
392
+ description: string;
393
+ total_amount: string;
394
+ items_count: number;
395
+ source_wallet: string;
396
+ deadline: string;
397
+ fund_name?: string;
398
+ }
399
+ /**
400
+ * База ВХОДА генерации — богатые позиции (приватные поля уйдут в doc_data на
401
+ * сервере). `doc_data_hash` здесь нет: его вычисляет сервер при генерации.
402
+ */
403
+ declare class BaseExpenseProposalStatementGenerateMetaDocumentInputDTO {
404
+ proposal_hash: string;
405
+ proposal: ExpenseProposalHeaderInputDTO;
406
+ items: ExpenseProposalItemInputDTO[];
407
+ }
408
+ /**
409
+ * База ПОДПИСАННОЙ meta — ровно то, что подписывается и едет on-chain:
410
+ * публичные позиции + `doc_data_hash` (реквизиты off-chain).
411
+ */
412
+ declare class BaseExpenseProposalStatementSignedMetaDocumentInputDTO implements Omit<Action, 'coopname' | 'username' | 'registry_id' | 'block_num' | 'lang' | 'title' | 'generator' | 'version' | 'created_at' | 'timezone' | 'links'> {
413
+ proposal_hash: string;
414
+ proposal: ExpenseProposalHeaderInputDTO;
415
+ items: ExpenseProposalSignedItemInputDTO[];
416
+ doc_data_hash: string;
417
+ }
418
+ declare const ExpenseProposalStatementGenerateDocumentInputDTO_base: _nestjs_common.Type<BaseExpenseProposalStatementGenerateMetaDocumentInputDTO & Omit<GenerateMetaDocumentInputDTO, "registry_id">>;
419
+ /**
420
+ * Input генерации документа СЗ-заявления (registry 2010).
421
+ * Backend через factory собирает PDF, возвращает `IGeneratedDocument` (без подписей).
422
+ */
423
+ declare class ExpenseProposalStatementGenerateDocumentInputDTO extends ExpenseProposalStatementGenerateDocumentInputDTO_base {
424
+ registry_id: number;
425
+ }
426
+ declare const ExpenseProposalStatementSignedMetaDocumentInputDTO_base: _nestjs_common.Type<BaseExpenseProposalStatementSignedMetaDocumentInputDTO & MetaDocumentInputDTO>;
427
+ declare class ExpenseProposalStatementSignedMetaDocumentInputDTO extends ExpenseProposalStatementSignedMetaDocumentInputDTO_base {
428
+ }
429
+ /**
430
+ * Подписанный документ СЗ-заявления (registry 2010).
431
+ */
432
+ declare class ExpenseProposalStatementSignedDocumentInputDTO extends SignedDigitalDocumentInputDTO {
433
+ readonly meta: ExpenseProposalStatementSignedMetaDocumentInputDTO;
434
+ }
435
+
436
+ /**
437
+ * Состояние заявки на вступление.
438
+ *
439
+ * Перечень и форма кандидата живут в каркасе: заявку показывает и ядро, и
440
+ * расширения, а `CapitalCandidate` от этой формы наследуется — базовый класс
441
+ * инъекцией не подменить, он обязан лежать в пакете.
442
+ */
443
+ declare enum CandidateStatus {
444
+ PENDING = "pending",
445
+ REGISTERED = "registered",
446
+ FAILED = "failed"
447
+ }
448
+ declare class CandidateOutputDTO {
449
+ username: string;
450
+ username_display_name?: string;
451
+ coopname: string;
452
+ braname?: string;
453
+ status: CandidateStatus;
454
+ type: string;
455
+ created_at: Date;
456
+ registered_at?: Date;
457
+ referer?: string;
458
+ referer_display_name?: string;
459
+ public_key: string;
460
+ program_key?: string;
461
+ }
462
+
463
+ declare class CandidateFilterInputDTO {
464
+ referer?: string;
465
+ }
466
+
467
+ /**
468
+ * Срок, отпущенный расширению на подключение к кооперативу.
469
+ *
470
+ * Совет проходит шаги подключения не за один присест, поэтому у начатого
471
+ * подключения есть срок годности: по его истечении расширение считает
472
+ * подключение просроченным и предлагает начать заново. Политика общая для всех
473
+ * расширений — раньше срок был захардкожен в двух модулях порознь и рисковал
474
+ * разойтись.
475
+ */
476
+ declare const ONBOARDING_EXPIRY_DAYS = 30;
477
+ declare const ONBOARDING_EXPIRY_MS: number;
478
+ /**
479
+ * Момент истечения, отсчитанный от начала подключения. Возвращает строку ISO:
480
+ * в настройке расширения срок хранится строкой.
481
+ */
482
+ declare function computeOnboardingExpiresAt(startedAt: Date): string;
483
+
484
+ /** Запись журнала расширения: произвольные данные `TLog`, привязанные к установленному расширению. */
485
+ interface LogExtensionDomainInterface<TLog = any> {
486
+ id: number;
487
+ name: string;
488
+ extension_local_id: number;
489
+ data: TLog;
490
+ created_at: Date;
491
+ updated_at: Date;
492
+ }
493
+ interface LogExtensionFilter {
494
+ name?: string;
495
+ createdFrom?: Date;
496
+ createdTo?: Date;
497
+ }
498
+ interface LogExtensionPaginationOptions {
499
+ page?: number;
500
+ limit?: number;
501
+ sortBy?: string;
502
+ sortOrder?: 'ASC' | 'DESC';
503
+ }
504
+ declare class LogExtensionDomainEntity<TLog = any> implements LogExtensionDomainInterface {
505
+ readonly id: number;
506
+ readonly name: string;
507
+ readonly extension_local_id: number;
508
+ readonly data: TLog;
509
+ readonly created_at: Date;
510
+ readonly updated_at: Date;
511
+ constructor(id: number, name: string, extension_local_id: number, data: TLog, created_at: Date, updated_at: Date);
512
+ }
513
+ interface LogExtensionPaginationResult<TLog = any> {
514
+ items: LogExtensionDomainEntity<TLog>[];
515
+ totalCount: number;
516
+ totalPages: number;
517
+ currentPage: number;
518
+ }
519
+
520
+ interface ExtensionDomainRepository<TConfig = any> {
521
+ findByName(name: string): Promise<ExtensionDomainEntity<TConfig> | null>;
522
+ deleteByName(name: string): Promise<boolean>;
523
+ create(data: Partial<ExtensionDomainEntity<TConfig>>): Promise<ExtensionDomainEntity<TConfig>>;
524
+ find(filter?: Partial<ExtensionDomainEntity<TConfig>>): Promise<ExtensionDomainEntity<TConfig>[]>;
525
+ update(data: Partial<ExtensionDomainEntity<TConfig>>): Promise<ExtensionDomainEntity<TConfig>>;
526
+ /**
527
+ * Атомарно мёржит `patch` в jsonb-колонку `config` одним UPDATE (`config || patch`),
528
+ * без чтения-изменения-записи всего объекта в памяти приложения. Конкурентные вызовы
529
+ * с разными ключами patch не теряют изменения друг друга (в отличие от `update()`,
530
+ * который перезаписывает весь config целиком и подвержен lost update при гонке).
531
+ */
532
+ patchConfig(name: string, patch: Partial<TConfig>): Promise<ExtensionDomainEntity<TConfig>>;
533
+ }
534
+ /**
535
+ * DI-токен репозитория расширений. Реализацию подставляет ядро контроллера.
536
+ *
537
+ * `Symbol.for`, а не `Symbol()`: расширение и ядро резолвят токен из своих копий пакета,
538
+ * и совпасть они обязаны по глобальному реестру символов, иначе DI молча не найдёт провайдера.
539
+ */
540
+ declare const EXTENSION_REPOSITORY: unique symbol;
541
+
542
+ interface LogExtensionDomainRepository<TLog = any> {
543
+ push(name: string, data: TLog): Promise<LogExtensionDomainEntity<TLog>>;
544
+ get(): Promise<LogExtensionDomainEntity<TLog>[]>;
545
+ getWithFilter(filter?: LogExtensionFilter, options?: LogExtensionPaginationOptions): Promise<LogExtensionPaginationResult<TLog>>;
546
+ }
547
+ /** DI-токен журнала расширений. См. пояснение про `Symbol.for` в `EXTENSION_REPOSITORY`. */
548
+ declare const LOG_EXTENSION_REPOSITORY: unique symbol;
549
+
550
+ /**
551
+ * Контекст опциональной фазы миграции данных (PG, вызовы репозиториев и т.д.).
552
+ * `resolve` — Nest `get()` по токену провайдера.
553
+ */
554
+ interface ExtensionSchemaMigrationAfterContext {
555
+ /** Токен Nest DI (строка, symbol или класс вроде DataSource — у конструкторов свои параметры, поэтому `any[]`). */
556
+ resolve: <T = unknown>(typeOrToken: string | symbol | (new (...args: any[]) => any)) => T;
557
+ logInfo: (message: string) => void;
558
+ logWarn: (message: string) => void;
559
+ logError: (message: string, error?: unknown) => void;
560
+ }
561
+ /** Миграция схемы конфига расширения. */
562
+ interface IExtensionSchemaMigration<TOldConfig = any, TNewConfig = any> {
563
+ /** Уникальное имя расширения. */
564
+ extensionName: string;
565
+ /** Версия миграции — задаёт порядок применения. */
566
+ version: number;
567
+ /**
568
+ * Преобразует старую конфигурацию в новую.
569
+ * @param oldConfig Старая конфигурация из базы данных
570
+ * @param defaultConfig Дефолтная конфигурация новой схемы
571
+ */
572
+ migrate(oldConfig: TOldConfig, defaultConfig: TNewConfig): TNewConfig;
573
+ /**
574
+ * Вызывается до записи новой `schema_version` в БД. При ошибке версия не повышается —
575
+ * миграция повторится при следующем старте.
576
+ */
577
+ afterMigrate?: (ctx: ExtensionSchemaMigrationAfterContext) => Promise<void>;
578
+ }
579
+
580
+ /** Событие: расширение снято с запуска (terminate / uninstall / выключение). Слушатели — инфраструктура расширений. */
581
+ declare const EXTENSION_APP_TERMINATE_EVENT: "extension.app.terminate";
582
+ interface ExtensionAppTerminatePayload {
583
+ appName: string;
584
+ }
585
+
586
+ /**
587
+ * Политика конфигурационного параметра расширения: кто его заполняет и можно ли
588
+ * показывать его значение.
589
+ *
590
+ * Zod-схема отвечает на вопрос «какой у параметра тип и что считается валидным».
591
+ * Она не отвечает на два других, от которых зависит безопасность: **видно ли
592
+ * значение снаружи** и **чьё оно вообще**. Раньше ответа не было, и потому
593
+ * `getExtensions` отдавал конфиг целиком — вместе с секретным ключом кассы
594
+ * ЮKassa. Политика закрывает этот пробел, оставаясь рядом со схемой, а не
595
+ * внутри неё: замена валидатора не должна уносить с собой признак секретности.
596
+ */
597
+ /** Кто поставляет значение параметра. */
598
+ declare enum ExtensionConfigSuppliedBy {
599
+ /**
600
+ * Кооператив. Председатель вводит значение при установке или в настройках
601
+ * расширения; хранится в записи установки.
602
+ */
603
+ COOPERATIVE = "cooperative",
604
+ /**
605
+ * Провайдер поставки. Значение приходит из конфигурации узла и в записи
606
+ * установки не хранится вовсе. Председатель его не вводит и не видит: это
607
+ * инфраструктура поставки, а не настройка кооператива.
608
+ */
609
+ PROVIDER = "provider"
610
+ }
611
+ interface ExtensionConfigFieldPolicy {
612
+ /**
613
+ * Значение не покидает сервер. Наружу уходит только признак «задано», сам
614
+ * параметр редактируется в выдаче и в логах.
615
+ */
616
+ secret?: boolean;
617
+ /** Кто заполняет. По умолчанию — кооператив. */
618
+ suppliedBy?: ExtensionConfigSuppliedBy;
619
+ }
620
+ /**
621
+ * Политика по параметрам расширения. Ключ — путь до поля в конфиге, точкой для
622
+ * вложенных: `'secret'`, `'matrix.admin_password'`. Параметры без записи ведут
623
+ * себя как несекретные и кооперативные — то есть ровно как сегодня.
624
+ */
625
+ type ExtensionConfigPolicy = Record<string, ExtensionConfigFieldPolicy>;
626
+ /**
627
+ * Что подставляется вместо секретного значения в выдаче.
628
+ *
629
+ * Отдавать пустую строку нельзя: интерфейс не отличил бы «не задано» от
630
+ * «задано, но скрыто», а председателю нужно видеть разницу — иначе он не
631
+ * поймёт, работает расширение или ждёт ключа. Маркер также служит защитой при
632
+ * сохранении формы: пришедшее обратно значение, равное маркеру, означает
633
+ * «параметр не трогали», и сохранённый секрет остаётся на месте.
634
+ */
635
+ declare const EXTENSION_SECRET_SET = "__secret_set__";
636
+ declare const EXTENSION_SECRET_UNSET = "";
637
+ /**
638
+ * Заменить секретные значения маркерами перед отдачей наружу.
639
+ *
640
+ * Возвращает новый объект: исходный конфиг остаётся нетронутым, потому что тем
641
+ * же объектом пользуется работающее расширение.
642
+ */
643
+ declare function redactSecretConfig<TConfig extends Record<string, any>>(config: TConfig, policy: ExtensionConfigPolicy | undefined): TConfig;
644
+ /**
645
+ * Собрать конфиг для сохранения: секретные параметры, пришедшие маркером
646
+ * «задано», заменить на уже сохранённое значение.
647
+ *
648
+ * Без этого шага любое сохранение формы затирало бы секреты: интерфейс получил
649
+ * маркер вместо значения и его же вернул бы обратно.
650
+ */
651
+ declare function mergeSecretConfig<TConfig extends Record<string, any>>(incoming: TConfig, stored: TConfig | undefined, policy: ExtensionConfigPolicy | undefined): TConfig;
652
+ /** Пути параметров, которые поставляет провайдер, — их не хранит запись установки. */
653
+ declare function providerSuppliedPaths(policy: ExtensionConfigPolicy | undefined): string[];
654
+
655
+ /**
656
+ * Контракт записи реестра расширений. Сам реестр (`AppRegistry` с перечислением
657
+ * конкретных расширений) остаётся в контроллере — это composition root; сюда вынесена
658
+ * только форма записи, чтобы расширение могло её типизировать.
659
+ */
660
+ /** Конфигурация рабочего стола, который предоставляет расширение. */
661
+ interface IDesktopConfig {
662
+ name: string;
663
+ title: string;
664
+ icon?: string;
665
+ defaultRoute?: string;
666
+ }
667
+ /**
668
+ * В каких сетях расширение разрешено ставить.
669
+ *
670
+ * Переключатель обкатки: приложение сначала открывают на тестовом контуре
671
+ * (`NON_MAINNET_ONLY`), а когда оно готово к боевой эксплуатации — здесь же,
672
+ * в реестре, переводят в `EVERYWHERE`.
673
+ */
674
+ declare enum ExtensionAvailability {
675
+ /** Доступно в любой сети, включая основную. */
676
+ EVERYWHERE = "everywhere",
677
+ /** Доступно только вне основной сети — тестовый и локальный контуры. */
678
+ NON_MAINNET_ONLY = "non_mainnet_only",
679
+ /** Недоступно нигде — расширение ещё не открыто для установки. */
680
+ NOWHERE = "nowhere"
681
+ }
682
+ /** Вычисляет доступность расширения для сети, в которой работает узел. */
683
+ declare function isExtensionAvailable(availability: ExtensionAvailability, isMainnet: boolean): boolean;
684
+ /**
685
+ * Описание расширения в реестре.
686
+ * Поля readme/instructions живут здесь, а не в сущности расширения, чтобы не тащить
687
+ * презентационные данные в домен.
688
+ */
689
+ interface IRegistryExtension {
690
+ is_builtin: boolean;
691
+ availability: ExtensionAvailability;
692
+ is_internal: boolean;
693
+ desktops?: IDesktopConfig[];
694
+ external_url?: string;
695
+ title: string;
696
+ description: string;
697
+ image: string;
698
+ class: any;
699
+ extensionClass: any;
700
+ schema: any;
701
+ /**
702
+ * Политика по параметрам конфига: что секретно и кто заполняет.
703
+ * Необязательна — расширение без политики ведёт себя как раньше.
704
+ */
705
+ configPolicy?: ExtensionConfigPolicy;
706
+ /**
707
+ * Таблицы, которыми расширение владеет, — классы сущностей TypeORM.
708
+ *
709
+ * Состав объявляется здесь, а не выводится из положения файлов на диске:
710
+ * расширение, установленное пакетом в `node_modules`, ни под какой глоб по
711
+ * `src/` не попадёт, и его таблицы просто не создадутся. Пустой список у
712
+ * расширения, которое своих таблиц не держит, — нормальное состояние.
713
+ */
714
+ entities?: ReadonlyArray<new (...args: any[]) => any>;
715
+ /**
716
+ * Миграции схемы конфига расширения — в порядке применения.
717
+ *
718
+ * Версии своего конфига расширение ведёт само: ядру незачем знать, что у
719
+ * какого-то расширения была v2, а потом v18. Порядок задаётся порядком в
720
+ * списке.
721
+ */
722
+ migrations?: ReadonlyArray<IExtensionSchemaMigration>;
723
+ /**
724
+ * Как расширение ставится в новом кооперативе.
725
+ *
726
+ * Отсутствие поля означает «само не ставится»: пайщик выбирает его в каталоге
727
+ * приложений. Дефолты конфига берутся отсюда же — ядро не обязано знать, из
728
+ * чего состоит конфиг чужого расширения.
729
+ */
730
+ defaults?: {
731
+ /** Включать ли сразу после установки. Выключенное стоит, но не работает. */
732
+ enabled: boolean;
733
+ /** Начальные значения конфига — те же, что объявлены схемой расширения. */
734
+ config: Record<string, any>;
735
+ };
736
+ /**
737
+ * Capability-заявка расширения: какие порты контура оно просит (ADR-16).
738
+ *
739
+ * Это не права пайщика — те проверяются на границе API самого расширения,
740
+ * внутри уже авторизованного сценария. Здесь другой вопрос: что этому
741
+ * расширению вообще позволено просить у кооператива. Ответ на него нужен
742
+ * один раз, при запуске, а не на каждом вызове порта.
743
+ *
744
+ * Обязательный порт без реализации — отказ на старте с внятной причиной.
745
+ * Необязательный может отсутствовать: расширение работает, часть
746
+ * возможностей выключена.
747
+ */
748
+ ports?: {
749
+ required: ReadonlyArray<symbol>;
750
+ optional: ReadonlyArray<symbol>;
751
+ };
752
+ tags?: string[];
753
+ readme: Promise<string>;
754
+ instructions: Promise<string>;
755
+ /** Обратная совместимость: наличие desktops означает, что это desktop-расширение. */
756
+ get is_desktop(): boolean;
757
+ }
758
+ /** Запись реестра с уже вычисленной под текущую сеть доступностью — её потребляет DTO витрины. */
759
+ type IResolvedRegistryExtension = Omit<IRegistryExtension, 'availability'> & {
760
+ is_available: boolean;
761
+ };
762
+
763
+ interface DeserializedDescriptionOfExtension {
764
+ /**
765
+ * Название или метка, которая будет отображаться как подпись к полю ввода.
766
+ * Обязательное поле.
767
+ */
768
+ label: string;
769
+ /**
770
+ * Примечание или дополнительная информация, связанная с полем.
771
+ * Отображается как подсказка или вспомогательный текст рядом с полем.
772
+ * Необязательное поле.
773
+ */
774
+ note?: string;
775
+ /**
776
+ * Управляет видимостью поля. Если установлено в `false`, поле будет скрыто.
777
+ * По умолчанию `true` (поле видимо).
778
+ * Необязательное поле.
779
+ */
780
+ visible?: boolean;
781
+ /**
782
+ * Набор правил валидации, определенных как строковые выражения, например `['val > 0']`.
783
+ * Эти выражения интерпретируются как логические проверки, применяемые к значению поля.
784
+ * Необязательное поле.
785
+ */
786
+ rules?: string[];
787
+ /**
788
+ * Маска для ввода, которая ограничивает допустимые символы и формат поля ввода.
789
+ * Используется для ограничения ввода, например, к числам или специфическим форматам.
790
+ * Необязательное поле.
791
+ */
792
+ mask?: string;
793
+ /**
794
+ * Определяет, будет ли маска заполняться автоматически, когда значение не полностью введено.
795
+ * Обычно используется с `mask`, чтобы показать пользователю заполненный шаблон.
796
+ * Необязательное поле.
797
+ */
798
+ fillMask?: boolean;
799
+ /**
800
+ * Минимальная длина строки для текстовых полей.
801
+ * Проверяется валидацией, чтобы гарантировать, что ввод соответствует минимальной длине.
802
+ * Необязательное поле.
803
+ */
804
+ minLength?: number;
805
+ /**
806
+ * Максимальная длина строки для текстовых полей.
807
+ * Проверяется валидацией, чтобы гарантировать, что ввод не превышает максимальную длину.
808
+ * Необязательное поле.
809
+ */
810
+ maxLength?: number;
811
+ /**
812
+ * Максимальное количество строк для многострочных текстовых полей.
813
+ * Если указано, поле ввода будет отображаться как многострочное (`textarea`).
814
+ * Необязательное поле.
815
+ */
816
+ maxRows?: number;
817
+ /**
818
+ * Добавляет текст после значения поля в интерфейсе (например, символ валюты).
819
+ * Необязательное поле.
820
+ */
821
+ append?: string;
822
+ /**
823
+ * Добавляет текст перед значением поля в интерфейсе (например, символ валюты).
824
+ * Необязательное поле.
825
+ */
826
+ prepend?: string;
827
+ /**
828
+ * Определяет, будет ли поле только для чтения.
829
+ * Если установлено в `true`, поле будет отображаться как только для чтения.
830
+ * Необязательное поле.
831
+ */
832
+ readonly?: boolean;
833
+ /**
834
+ * Определяет, будет ли поле паролем.
835
+ * Если установлено в `true`, поле будет отображаться как пароль.
836
+ * Необязательное поле.
837
+ */
838
+ password?: boolean;
839
+ /**
840
+ * Тип генератора значения для поля.
841
+ * Если указан, при установке расширения (когда значение пустое) будет автоматически
842
+ * сгенерировано значение указанного типа.
843
+ * Поддерживаемые типы:
844
+ * - 'randomSecret' - генерирует криптографически стойкую случайную строку (64 hex символа)
845
+ * Необязательное поле.
846
+ */
847
+ generator?: 'randomSecret';
848
+ /**
849
+ * Значение по умолчанию для поля.
850
+ * Может быть статическим значением или значением, переданным с бэкенда.
851
+ * Отображается в форме как предустановленное значение при установке расширения.
852
+ * Необязательное поле.
853
+ */
854
+ default?: string;
855
+ /**
856
+ * Показывать ли кнопку копирования значения поля.
857
+ * В режиме установки кнопка копирования показывается всегда для полей с generator или copyable: true.
858
+ * Необязательное поле.
859
+ */
860
+ copyable?: boolean;
861
+ }
862
+
863
+ /**
864
+ * Состав таблиц установленных расширений — то, что контроллер обязан отдать
865
+ * TypeORM при подключении к базе.
866
+ *
867
+ * Каждое расширение объявляет свои сущности в записи реестра
868
+ * (`IRegistryExtension.entities`), composition root складывает их сюда одним
869
+ * вызовом, а подключение к базе читает готовый список. Прежний способ — глоб
870
+ * `src/extensions/ ** /entities/*entity.ts` — привязывал расширение к его месту
871
+ * на диске и не нашёл бы ни одной таблицы у расширения, установленного пакетом.
872
+ *
873
+ * Список задаётся один раз, до инициализации подключения. Повторный вызов —
874
+ * ошибка: он означал бы, что состав таблиц меняется на ходу, а TypeORM после
875
+ * инициализации новые сущности уже не примет.
876
+ */
877
+ type ExtensionEntityClass = new (...args: any[]) => any;
878
+ /** Объявить состав таблиц установленных расширений. Вызывает composition root. */
879
+ declare function registerExtensionEntities(list: ReadonlyArray<ExtensionEntityClass>): void;
880
+ /**
881
+ * Прочитать состав таблиц расширений.
882
+ *
883
+ * До объявления возвращает пустой список, а не бросает: подключение к базе
884
+ * поднимается и в контурах без единого расширения (миграции, генератор схемы).
885
+ */
886
+ declare function extensionEntities(): ReadonlyArray<ExtensionEntityClass>;
887
+ /** Сбросить состав. Только для тестов, которые поднимают граф модулей заново. */
888
+ declare function resetExtensionEntities(): void;
889
+
890
+ /**
891
+ * Входные параметры для пагинации и сортировки
892
+ */
893
+ declare class PaginationInputDTO {
894
+ page: number;
895
+ limit: number;
896
+ sortBy?: string;
897
+ sortOrder: 'ASC' | 'DESC';
898
+ }
899
+ /**
900
+ * Результат пагинации (универсальный для TypeScript)
901
+ */
902
+ declare class PaginationResult<T> {
903
+ items: T[];
904
+ totalCount: number;
905
+ totalPages: number;
906
+ currentPage: number;
907
+ }
908
+ /**
909
+ * Создание объекта GraphQL для результата пагинации
910
+ * @param name - Имя объекта GraphQL
911
+ * @param ItemType - Класс элемента списка
912
+ */
913
+ declare function createPaginationResult<T>(ItemType: new (...args: any[]) => T, name: string): abstract new () => {
914
+ items: T[];
915
+ totalCount: number;
916
+ totalPages: number;
917
+ currentPage: number;
918
+ };
919
+ /**
920
+ * Сборка `PaginationResult<U>` для consumer'ов, читающих через порт innercoop
921
+ * (нет своего Repository.findAndCount, доступен только raw `{items, totalCount}`).
922
+ *
923
+ * Зачем: вычисление `totalPages`/`currentPage` из `PaginationInputDTO` — общая
924
+ * детерминированная логика; дублировать её в каждом consumer'е = canon-долг.
925
+ */
926
+ declare function buildPaginationResult<T, U>(raw: {
927
+ items: T[];
928
+ totalCount: number;
929
+ }, options: PaginationInputDTO | undefined, mapItem: (it: T) => U): PaginationResult<U>;
930
+ /**
931
+ * Расчёт параметров пагинации для репозиториев, считающих выборку сами
932
+ * (TypeORM `findAndCount` и прямой SQL).
933
+ *
934
+ * Типизирован на `PaginationInputDTO`, но принимает любой объект той же формы:
935
+ * связь структурная, номинального `implements` между пакетом и ядром нет.
936
+ */
937
+ declare class PaginationUtils {
938
+ /** Собрать результат из выборки репозитория и параметров запроса. */
939
+ static createPaginationResult<T>(items: T[], totalCount: number, options: PaginationInputDTO): PaginationResult<T>;
940
+ /** Перевести номер страницы в `LIMIT`/`OFFSET`. */
941
+ static getSqlPaginationParams(options: PaginationInputDTO): {
942
+ limit: number;
943
+ offset: number;
944
+ };
945
+ /**
946
+ * Проверить параметры и подставить умолчания.
947
+ *
948
+ * Верхняя граница `limit` — защита от выгрузки всей таблицы одним запросом,
949
+ * поэтому проверка живёт здесь, а не в каждом репозитории.
950
+ */
951
+ static validatePaginationOptions(options: PaginationInputDTO): PaginationInputDTO;
952
+ }
953
+ /**
954
+ * Канон-конверсия `PaginationInputDTO` → `{limit, offset, sortBy, sortOrder}`
955
+ * для адаптеров портов innercoop / внешних read API, не принимающих page-form.
956
+ */
957
+ declare function paginationInputToOffset(options?: PaginationInputDTO): {
958
+ limit?: number;
959
+ offset?: number;
960
+ sortBy?: string;
961
+ sortOrder?: 'ASC' | 'DESC';
962
+ };
963
+
964
+ /**
965
+ * Часть полей `T` обязательна, остальные — нет.
966
+ *
967
+ * Применяется к формам частичного обновления: клиент присылает произвольный
968
+ * набор полей, но ключ, по которому запись ищется, обязан быть.
969
+ */
970
+ type RequireFields<T, K> = Partial<T> & Required<Pick<T, Extract<K & keyof T, keyof T>>>;
971
+
972
+ /**
973
+ * DTO для результата транзакции.
974
+ */
975
+ declare class TransactionDTO {
976
+ chain?: any;
977
+ request?: any;
978
+ resolved?: any;
979
+ response?: any;
980
+ returns?: any;
981
+ revisions?: any;
982
+ signatures?: any;
983
+ signer?: any;
984
+ transaction?: any;
985
+ }
986
+
987
+ /**
988
+ * Настройки контура, одинаковые для всех расширений и не содержащие секретов.
989
+ *
990
+ * Расширение обязано знать, в каком кооперативе оно работает и по какому адресу
991
+ * его открывают, — иначе оно не соберёт ни ссылку в уведомлении, ни имя счёта.
992
+ * Раньше за этим шли прямо в `~/config/config` контроллера, то есть по пути,
993
+ * которого за пределами монолита не существует.
994
+ *
995
+ * **Здесь только то, что не жалко отдать любому расширению.** Ни ключей, ни
996
+ * паролей, ни реквизитов доступа тут нет и быть не должно. Именно поэтому
997
+ * настройки раздаются простой функцией, а не портом с DI: гейт capability
998
+ * (какому расширению что доступно) имеет смысл ровно там, где есть что
999
+ * закрывать. Имя кооператива закрывать не от кого — оно нужно всем и не
1000
+ * является тайной.
1001
+ *
1002
+ * Секретное и инфраструктурное — ключи Matrix, LiveKit, OpenAI, токен GitHub —
1003
+ * через этот канал не проходит принципиально. Им положен явный порт под
1004
+ * capability-гейтом, и до его появления они остаются там, где лежат.
1005
+ */
1006
+ interface PlatformBlockchainSettings {
1007
+ /** Символ базового токена управления кооператива, например `RUB`. */
1008
+ rootGovernSymbol: string;
1009
+ /** Точность базового токена — знаков после запятой. */
1010
+ rootGovernPrecision: number;
1011
+ /** Символ системного токена цепи, например `AXON`. */
1012
+ rootSymbol: string;
1013
+ /** Точность системного токена — знаков после запятой. */
1014
+ rootPrecision: number;
1015
+ /**
1016
+ * Пауза перед чтением таблиц цепи сразу после успешной мутации, мс.
1017
+ *
1018
+ * На узле-последователе строка появляется в состоянии с задержкой
1019
+ * относительно ответа RPC, и величина этой задержки зависит от узла контура,
1020
+ * а не от расширения.
1021
+ */
1022
+ postTransactChainReadDelayMs: number;
1023
+ /**
1024
+ * Идентификатор цепи контура. Входит в подписываемую транзакцию, поэтому
1025
+ * подпись, собранная для одной цепи, в другой недействительна — расширение
1026
+ * обязано брать его отсюда, а не хранить у себя.
1027
+ */
1028
+ chainId: string;
1029
+ }
1030
+ interface PlatformSettings {
1031
+ /** Учётное имя кооператива в цепи, например `voskhod`. */
1032
+ coopname: string;
1033
+ /** Адрес, по которому пайщик открывает кооператив; основа для ссылок в уведомлениях. */
1034
+ frontendUrl: string;
1035
+ /** Адрес API контура. */
1036
+ backendUrl: string;
1037
+ /** Часовая зона кооператива в формате IANA, например `Europe/Moscow`. */
1038
+ timezone: string;
1039
+ /**
1040
+ * Режим контура: `production` у рабочего кооператива, иначе — стенд.
1041
+ * Расширение сверяется с ним, когда поведение обязано отличаться (не слать
1042
+ * настоящие письма, не ходить во внешний сервис), а не чтобы прятать ошибки.
1043
+ */
1044
+ environment: string;
1045
+ blockchain: PlatformBlockchainSettings;
1046
+ }
1047
+ /**
1048
+ * Задать настройки контура. Вызывается composition root'ом один раз при старте,
1049
+ * до того как приложение начнёт принимать запросы.
1050
+ */
1051
+ declare function configurePlatformSettings(value: PlatformSettings): void;
1052
+ /**
1053
+ * Прочитать настройки контура.
1054
+ *
1055
+ * Бросает, если настройки не заданы. Молчаливый возврат пустых значений был бы
1056
+ * хуже: расширение построило бы ссылку на несуществующий адрес или создало
1057
+ * запись с пустым именем кооператива, и разбирались бы мы уже с последствиями.
1058
+ */
1059
+ declare function platformSettings(): PlatformSettings;
1060
+
1061
+ type GeneratedDocumentDomainInterface = Omit<Cooperative.Document.IGeneratedDocument, 'binary'> & {
1062
+ binary: string;
1063
+ };
1064
+
1065
+ declare class GeneratedDocumentDTO implements GeneratedDocumentDomainInterface {
1066
+ full_title: string;
1067
+ html: string;
1068
+ hash: string;
1069
+ meta: any;
1070
+ binary: string;
1071
+ constructor(data?: GeneratedDocumentDomainInterface);
1072
+ }
1073
+
1074
+ declare class GenerateDocumentOptionsInputDTO implements Cooperative.Document.IGenerationOptions {
1075
+ skip_save?: boolean;
1076
+ lang?: string;
1077
+ }
1078
+
1079
+ /**
1080
+ * Убрать из формы документа поля, которые проставляет реестр, а не заявитель.
1081
+ *
1082
+ * `coopname`, `username` и `registry_id` есть у каждого документа и приходят из
1083
+ * контекста запроса, поэтому в специфичной части формы они лишние.
1084
+ */
1085
+ type ExcludeCommonProps<T> = Omit<T, 'coopname' | 'username' | 'registry_id'>;
1086
+
1087
+ declare const GenerateDocumentInputDTO_base: _nestjs_common.Type<Omit<GenerateMetaDocumentInputDTO, "registry_id">>;
1088
+ /**
1089
+ * То же, что `GenerateMetaDocumentInputDTO`, но реестр обязателен на уровне
1090
+ * типов TypeScript.
1091
+ *
1092
+ * `registry_id` намеренно без `@Field`: в схеме у `GenerateDocumentInput` этого
1093
+ * поля нет и не было — реестр проставляет сервер по вызванной мутации, а не
1094
+ * клиент. Добавить `@Field` значило бы завести новое обязательное поле во
1095
+ * входном типе и сломать всех клиентов.
1096
+ */
1097
+ declare class GenerateDocumentInputDTO extends GenerateDocumentInputDTO_base {
1098
+ registry_id: number;
1099
+ constructor();
1100
+ }
1101
+
1102
+ /** Реквизиты одной подписи под документом. */
1103
+ declare class SignatureInfoDTO {
1104
+ readonly id: number;
1105
+ readonly signer: string;
1106
+ readonly public_key: string;
1107
+ readonly signature: string;
1108
+ readonly signed_at: string;
1109
+ readonly signed_hash: string;
1110
+ readonly meta: any;
1111
+ readonly is_valid?: boolean;
1112
+ }
1113
+ /**
1114
+ * Подписанный документ целиком.
1115
+ *
1116
+ * Конструктор переносит подписи как есть, не пересобирая их: поля совпадают по
1117
+ * именам, а всё, что ядро добавило сверх контракта (тот самый сертификат),
1118
+ * доезжает до его собственного резолвера нетронутым.
1119
+ */
1120
+ declare class SignedDigitalDocumentDTO {
1121
+ readonly version: string;
1122
+ readonly hash: string;
1123
+ readonly doc_hash: string;
1124
+ readonly meta_hash: string;
1125
+ readonly meta: any;
1126
+ readonly signatures: SignatureInfoDTO[];
1127
+ constructor(data: {
1128
+ version: string;
1129
+ hash: string;
1130
+ doc_hash: string;
1131
+ meta_hash: string;
1132
+ meta: any;
1133
+ signatures: readonly any[];
1134
+ });
1135
+ }
1136
+
1137
+ declare class DocumentAggregateDTO {
1138
+ hash: string;
1139
+ document: SignedDigitalDocumentDTO;
1140
+ rawDocument?: GeneratedDocumentDTO;
1141
+ /**
1142
+ * Принимает любой агрегат нужной формы: и доменный из ядра, и результат
1143
+ * `IDocumentPort.buildAggregate`. Номинальной связи с ними нет — каркас не
1144
+ * зависит ни от контроллера, ни от `@coopenomics/innercoop` (INV-007).
1145
+ */
1146
+ constructor(data?: {
1147
+ hash: string;
1148
+ document: any;
1149
+ rawDocument?: any;
1150
+ });
1151
+ }
1152
+
1153
+ /**
1154
+ * Сверка подписанного документа с черновиком, который ему предшествовал.
1155
+ *
1156
+ * Пайщик подписывает то, что увидел на экране, а расширение принимает подпись
1157
+ * отдельным вызовом — между этими двумя моментами содержимое можно подменить.
1158
+ * Поэтому расширение обязано найти свой же черновик по хэшу и сверить его с
1159
+ * подписанным, а не верить присланному. Правило одно для всех, кто принимает
1160
+ * подписи, поэтому живёт в каркасе в единственном экземпляре.
1161
+ *
1162
+ * Формы документов описаны структурно, а не импортом из
1163
+ * `@coopenomics/innercoop`: пакеты ортогональны (INV-007).
1164
+ */
1165
+ /** Режим сравнения `signed.meta[field]` с ожидаемым значением. */
1166
+ type SignedDocumentMetaCompareMode = 'currency_amount' | 'string_trim' | 'hex_case_insensitive';
1167
+ interface SignedDocumentMetaVerification {
1168
+ /** Имя поля в объекте `signed.meta`. */
1169
+ field: string;
1170
+ /** Ожидаемое значение — из мутации либо доменного ввода. */
1171
+ expected: string;
1172
+ /** Как сравнивать. */
1173
+ mode: SignedDocumentMetaCompareMode;
1174
+ }
1175
+ /** Подписанный документ: отсюда берутся хэш черновика и метаданные подписи. */
1176
+ interface SignedDocumentToVerify {
1177
+ doc_hash: string;
1178
+ meta: unknown;
1179
+ }
1180
+ /** Черновик, сохранённый при генерации. */
1181
+ interface GeneratedDocumentDraft {
1182
+ hash: string;
1183
+ }
1184
+ /** Загрузка сохранённого черновика по `doc_hash` подписанного документа. */
1185
+ type LoadGeneratedDocumentByDocHash = (docHash: string) => Promise<GeneratedDocumentDraft | null>;
1186
+ /**
1187
+ * 1) Находит черновик по `signed.doc_hash`.
1188
+ * 2) Сверяет подписанный документ с черновиком через `Classes.Document.compareDocuments`.
1189
+ * 3) Опционально сверяет поля `signed.meta` с ожидаемыми значениями.
1190
+ *
1191
+ * Бросает `HttpApiError` с 400, если черновик не найден, содержимое разошлось
1192
+ * или метаданные не совпали: всё это — признаки подмены, а не ошибки ввода.
1193
+ */
1194
+ declare function verifySignedDocumentAgainstStoredDraft(loadGeneratedByDocHash: LoadGeneratedDocumentByDocHash, signed: SignedDocumentToVerify, metaVerifications?: SignedDocumentMetaVerification[]): Promise<void>;
1195
+
1196
+ declare class DomainToBlockchainUtils {
1197
+ /** Доменный подписанный документ → форма для отправки в цепь. */
1198
+ convertSignedDocumentToBlockchainFormat(document: Cooperative.Document.ISignedDocument2): Cooperative.Document.IChainDocument2;
1199
+ /** Документ из цепи → доменная форма. */
1200
+ convertBlockchainDocumentToDomainFormat(chainDoc: Cooperative.Document.IChainDocument2): Cooperative.Document.ISignedDocument2;
1201
+ /**
1202
+ * Свернуть checksum256 и учётное имя в один uint128-ключ — так составной
1203
+ * индекс задан в контракте (`combine_checksum_ids`), и поиск по таблице
1204
+ * обязан считать ключ ровно так же.
1205
+ */
1206
+ combineChecksumAndUsername(hash: string, username: string): bigint;
1207
+ /** Дата → строка `time_point_sec`, как её принимает цепь. */
1208
+ convertDateToBlockchainFormat(date: Date | string): string;
1209
+ /**
1210
+ * Привести строку `«число символ»` к точности, объявленной для этого символа.
1211
+ *
1212
+ * Символ сверяется с настройками контура намеренно: цепь отвергает asset с
1213
+ * чужой точностью, и поймать это лучше здесь, чем в отказе транзакции.
1214
+ */
1215
+ formatQuantityWithPrecision(quantity: string): string;
1216
+ /** Числовая строка + точность + символ → asset-строка цепи. */
1217
+ formatNumericStringToAssetString(numericString: string, precision: number, symbol: string): string;
1218
+ static convertChainDocumentToSignedDocument2(chainDoc: Cooperative.Document.IChainDocument2): Cooperative.Document.ISignedDocument2;
1219
+ /**
1220
+ * Документ из цепи → доменная форма.
1221
+ *
1222
+ * `meta` в цепи хранится строкой JSON, а пустая строка означает «мета нет»:
1223
+ * `JSON.parse('')` на ней бросил бы.
1224
+ */
1225
+ static convertChainDocumentToDomainFormat(chainDoc: Cooperative.Document.IChainDocument2): Cooperative.Document.ISignedDocument2;
1226
+ static getEmptyHash(): string;
1227
+ }
1228
+
1229
+ /**
1230
+ * Утилиты для работы с ассетами в формате "AMOUNT SYMBOL" (например, "100.0000 RUB")
1231
+ */
1232
+ declare class AssetUtils {
1233
+ /**
1234
+ * Парсит строку ассета и возвращает числовое значение и символ
1235
+ * @param asset Строка формата "100.0000 RUB"
1236
+ * @returns { amount: number, symbol: string } или { amount: 0, symbol: '' } если парсинг не удался
1237
+ */
1238
+ static parseAsset(asset: string | undefined): {
1239
+ amount: number;
1240
+ symbol: string;
1241
+ };
1242
+ /**
1243
+ * Форматирует числовое значение и символ обратно в строку ассета
1244
+ * @param amount Числовое значение
1245
+ * @param symbol Символ валюты
1246
+ * @param precision Количество знаков после запятой (по умолчанию 4)
1247
+ * @returns Строка формата "100.0000 RUB"
1248
+ */
1249
+ static formatAsset(amount: number, symbol: string, precision?: number): string;
1250
+ /**
1251
+ * Складывает два ассета
1252
+ * @param asset1 Первый ассет в формате "100.0000 RUB"
1253
+ * @param asset2 Второй ассет в формате "50.0000 RUB"
1254
+ * @returns Результат сложения в формате "150.0000 RUB"
1255
+ * @throws Error если символы валют не совпадают
1256
+ */
1257
+ static addAssets(asset1: string | undefined, asset2: string | undefined): string;
1258
+ /**
1259
+ * Складывает массив ассетов
1260
+ * @param assets Массив ассетов в формате "100.0000 RUB"
1261
+ * @returns Результат сложения в формате "150.0000 RUB"
1262
+ * @throws Error если символы валют не совпадают
1263
+ */
1264
+ static sumAssets(assets: (string | undefined)[]): string;
1265
+ }
1266
+
1267
+ /**
1268
+ * Утилиты для форматирования сумм в человекочитаемый вид
1269
+ * (уведомления, печатные документы, UI-тексты).
1270
+ *
1271
+ * Канон отображения: 2 знака после запятой, группировка разрядов,
1272
+ * запятая как десятичный разделитель (ru-RU) —
1273
+ * «1000.0000 RUB» → «1 000,00 RUB».
1274
+ */
1275
+ declare class AmountFormatterUtils {
1276
+ /**
1277
+ * Форматирует сумму в читаемый формат.
1278
+ * @param amountStr Строка «число» или «число валюта»
1279
+ * (например, «1000.0000», «1000.0000 RUB»)
1280
+ * @returns «1 000,00» или «1 000,00 RUB»
1281
+ * @throws Error если формат некорректный
1282
+ */
1283
+ static formatAmount(amountStr: string): string;
1284
+ /**
1285
+ * То же, что {@link formatAmount}, но без throw: при сбое возвращает
1286
+ * исходную строку. Для non-blocking путей (уведомления), где ошибка
1287
+ * форматирования не должна рвать доставку.
1288
+ */
1289
+ static formatAmountSafe(amountStr: string | undefined | null): string;
1290
+ }
1291
+
1292
+ /**
1293
+ * Общие константы проекта
1294
+ */
1295
+ /**
1296
+ * Пустой хэш SHA-256 (все нули)
1297
+ */
1298
+ declare const EMPTY_HASH = "0000000000000000000000000000000000000000000000000000000000000000";
1299
+ /**
1300
+ * Версия документа по умолчанию
1301
+ */
1302
+ declare const DEFAULT_DOCUMENT_VERSION = "1.0.0";
1303
+
1304
+ declare function getAmountPlusFee(amount: number, fee: number): number;
1305
+ declare function checkPaymentSymbol(incomeSymbol: string, extectedSymbol: string): {
1306
+ status: string;
1307
+ message: string;
1308
+ };
1309
+ declare function checkPaymentAmount(incomeAmount: number, expectedAmount: number, tolerancePercentage: number): {
1310
+ status: string;
1311
+ message: string;
1312
+ };
1313
+
1314
+ /**
1315
+ * Утилиты для работы с количествами и символами в платежной системе
1316
+ */
1317
+ declare class QuantityUtils {
1318
+ /**
1319
+ * Проверяет, поддерживается ли символ системой
1320
+ * @param symbol Символ для проверки
1321
+ * @returns true если символ поддерживается
1322
+ */
1323
+ static isSupportedSymbol(symbol: string): boolean;
1324
+ /**
1325
+ * Получает precision для конкретного символа
1326
+ * @param symbol Символ валюты
1327
+ * @returns Precision для символа
1328
+ */
1329
+ static getPrecisionForSymbol(symbol: string): number;
1330
+ /**
1331
+ * Валидирует символ и выбрасывает ошибку если не поддерживается
1332
+ * @param symbol Символ для валидации
1333
+ */
1334
+ static validateSymbol(symbol: string): void;
1335
+ /**
1336
+ * Форматирует количество с символом для блокчейна
1337
+ * @param amount Числовое значение
1338
+ * @param symbol Символ валюты
1339
+ * @returns Отформатированная строка quantity для блокчейна
1340
+ */
1341
+ static formatQuantityForBlockchain(amount: number, symbol: string): string;
1342
+ /**
1343
+ * Форматирует количество с символом из числа и строки символа в единую строку
1344
+ * @param amount Числовое значение
1345
+ * @param symbol Символ валюты
1346
+ * @returns Строка в формате "число символ"
1347
+ */
1348
+ static combineQuantityAndSymbol(amount: number, symbol: string): string;
1349
+ /**
1350
+ * Парсит строку quantity в число и символ
1351
+ * @param quantity Строка в формате "число символ"
1352
+ * @returns Объект с числом и символом
1353
+ */
1354
+ static parseQuantityString(quantity: string): {
1355
+ amount: number;
1356
+ symbol: string;
1357
+ };
1358
+ }
1359
+
1360
+ /**
1361
+ * Утилита для работы с датами с учетом часового пояса
1362
+ * Реализована на базе библиотеки moment-timezone
1363
+ */
1364
+ declare class DateUtils {
1365
+ /**
1366
+ * Преобразует UTC дату в локальную дату согласно временной зоне из конфигурации
1367
+ */
1368
+ static convertUtcToLocalTime(date: Date | string): Date;
1369
+ /**
1370
+ * Форматирует дату в локальном формате с учетом временной зоны
1371
+ */
1372
+ static formatLocalDate(date: Date | string, format?: string): string;
1373
+ /**
1374
+ * Форматирует время в локальном формате с учетом временной зоны
1375
+ */
1376
+ static formatLocalTime(date: Date | string, format?: string): string;
1377
+ /**
1378
+ * Форматирует дату в локальном формате (дд.мм.гггг)
1379
+ */
1380
+ static formatLocalDateWithoutTimezone(dateString: string): string;
1381
+ /**
1382
+ * Форматирует время в локальном формате (чч:мм)
1383
+ */
1384
+ static formatLocalTimeWithoutTimezone(dateString: string): string;
1385
+ /**
1386
+ * Определяет, наступило ли уже указанное время с учетом временной зоны
1387
+ */
1388
+ static isTimeReached(targetDate: Date | string): boolean;
1389
+ /**
1390
+ * Вычисляет дату за указанное количество дней до целевой даты
1391
+ */
1392
+ static getDaysBeforeDate(targetDate: Date | string, days: number): Date;
1393
+ /**
1394
+ * Форматирует разницу во времени в человекочитаемый вид на русском языке (например, 'через 3 дня')
1395
+ */
1396
+ static formatDurationHumanizeRu(minutes: number): string;
1397
+ }
1398
+
1399
+ /**
1400
+ * Пауза перед чтением таблиц блокчейна сразу после успешной мутации (push_transaction).
1401
+ * На узле-последователе строка может появиться в chain state с задержкой относительно ответа RPC.
1402
+ */
1403
+ declare function waitAfterTransactBeforeChainTableRead(): Promise<void>;
1404
+
1405
+ /**
1406
+ * Форма ответа, из которой берётся номер блока. Описана здесь, а не взята из
1407
+ * SDK цепи: утилиту зовут и с результатом `IChainPort`, у которого типа SDK
1408
+ * нет, — а нужно от него ровно одно поле.
1409
+ */
1410
+ interface TransactResultWithResponse {
1411
+ response?: {
1412
+ processed?: {
1413
+ block_num?: unknown;
1414
+ };
1415
+ [key: string]: any;
1416
+ } | null;
1417
+ [key: string]: any;
1418
+ }
1419
+ /**
1420
+ * Номер блока, в котором транзакция была применена.
1421
+ *
1422
+ * WHY: `transactResult.transaction` — это подписанная транзакция, и её `ref_block_num` относится
1423
+ * к TaPoS: младшие 16 бит номера блока, на который транзакция ссылается для защиты от повторов.
1424
+ * Это не блок применения и даже не полный номер блока — значение всегда лежит в диапазоне
1425
+ * 0..65535 (в проде наблюдалось 60852 вместо 128 641 857). Записанный в БД как `block_num`, он
1426
+ * ломает версионирование и откат по форку: `deleteByBlockNumGreaterThan` такие строки не заденет.
1427
+ *
1428
+ * Реальный блок приходит в ответе API после broadcast — `response.processed.block_num`.
1429
+ * Если транзакция не броадкастилась (или узел не вернул `processed`), отдаём 0: по канону
1430
+ * сущность с нулевым `block_num` считается не привязанной к синхронизации и не откатывается
1431
+ * форком, что честнее правдоподобного, но неверного номера.
1432
+ */
1433
+ declare function getAppliedBlockNum(transactResult?: TransactResultWithResponse | null): number;
1434
+
1435
+ /**
1436
+ * Хэши, которыми расширение помечает свои сущности.
1437
+ *
1438
+ * Уникальный хэш нужен там, где идентификатор придумывается до записи в цепь:
1439
+ * платёж, черновик документа, заявка. Хэш от строки — там, где идентификатор
1440
+ * обязан воспроизводиться: два одинаковых входа дают один результат, и
1441
+ * повторный вызов не заводит вторую сущность.
1442
+ */
1443
+ /** Уникальный хэш: время плюс случайное число. Воспроизвести его нельзя. */
1444
+ declare function generateUniqueHash(): string;
1445
+ /** То же, что `generateUniqueHash`; имя сохранено, потому что так его зовут в коде. */
1446
+ declare function generateRandomHash(): string;
1447
+ /** Воспроизводимый хэш от строки — для идемпотентности. */
1448
+ declare function generateHashFromString(input: string): string;
1449
+
1450
+ /**
1451
+ * Утилитарный класс для валидации валютных сумм
1452
+ * Проверяет соответствие символа валюты конфигурации системы
1453
+ */
1454
+ declare class CurrencyValidationUtil {
1455
+ /**
1456
+ * Проверяет, что сумма содержит правильный символ валюты
1457
+ * @param amount Сумма в формате "число символ" (например, "1000 RUB")
1458
+ * @returns boolean - true если символ валюты правильный
1459
+ */
1460
+ static hasValidCurrencySymbol(amount: string): boolean;
1461
+ /**
1462
+ * Валидирует сумму и выбрасывает ошибку, если символ валюты неправильный
1463
+ * @param amount Сумма в формате "число символ" (например, "1000 RUB")
1464
+ * @param fieldName Название поля для сообщения об ошибке (по умолчанию "сумма")
1465
+ * @throws Error если символ валюты неправильный
1466
+ */
1467
+ static validateCurrencySymbol(amount: string, fieldName?: string): void;
1468
+ /**
1469
+ * Извлекает символ валюты из суммы
1470
+ * @param amount Сумма в формате "число символ"
1471
+ * @returns string - символ валюты или пустая строка, если не найден
1472
+ */
1473
+ static extractCurrencySymbol(amount: string): string;
1474
+ /**
1475
+ * Извлекает числовое значение из суммы
1476
+ * @param amount Сумма в формате "число символ"
1477
+ * @returns number - числовое значение или NaN, если не удалось распарсить
1478
+ */
1479
+ static extractAmountValue(amount: string): number;
1480
+ /**
1481
+ * Форматирует сумму с правильным символом валюты
1482
+ * @param value Числовое значение
1483
+ * @param precision Количество знаков после запятой (по умолчанию из конфига)
1484
+ * @returns string - отформатированная сумма
1485
+ */
1486
+ static formatAmount(value: number, precision?: number): string;
1487
+ }
1488
+
1489
+ /**
1490
+ * Ошибка API с кодом состояния HTTP.
1491
+ *
1492
+ * Переехала из `~/utils/httpApiError` контроллера: расширения бросают её
1493
+ * напрямую, а этого пути за пределами монолита нет.
1494
+ *
1495
+ * `isOperational` отделяет ожидаемый отказ (нет прав, не найдено, конфликт) от
1496
+ * сбоя: первый — нормальный ответ пайщику, второй должен попасть в трассировку.
1497
+ * `subcode` — доменный код отказа для клиента, когда одного статуса мало.
1498
+ */
1499
+ declare class HttpApiError extends HttpException {
1500
+ readonly isOperational: boolean;
1501
+ readonly subcode: any;
1502
+ constructor(statusCode: HttpStatus, message: string, isOperational?: boolean, stack?: string, subcode?: any);
1503
+ }
1504
+
1505
+ /**
1506
+ * Пробросить отказ цепи человеку.
1507
+ *
1508
+ * `eosio::check` возвращает сообщение обёрнутым в `assertion failure with
1509
+ * message: ...`; пайщику нужна причина, а не обёртка виртуальной машины.
1510
+ * Живёт в каркасе, потому что в цепь ходит не одно расширение: вторая копия
1511
+ * этой чистки разошлась бы с первой на первом же новом формате ошибки.
1512
+ */
1513
+ declare function rethrowChainError(error: unknown): never;
1514
+
1515
+ export { ActiveUserStatusGuard, AmountFormatterUtils, AssetUtils, AuthRoles, BaseExtensionModule, BucketRegistry, CandidateFilterInputDTO, CandidateOutputDTO, CandidateStatus, CurrencyValidationUtil, CurrentUser, DEFAULT_DOCUMENT_VERSION, DateUtils, DocumentAggregateDTO, DomainToBlockchainUtils, EMPTY_HASH, EXTENSION_APP_TERMINATE_EVENT, EXTENSION_REPOSITORY, EXTENSION_SECRET_SET, EXTENSION_SECRET_UNSET, ExpenseProposalStatementGenerateDocumentInputDTO, ExpenseProposalStatementSignedDocumentInputDTO, ExpenseProposalStatementSignedMetaDocumentInputDTO, ExtensionAvailability, ExtensionConfigSuppliedBy, ExtensionDomainEntity, GenerateDocumentInputDTO, GenerateDocumentOptionsInputDTO, GenerateMetaDocumentInputDTO, GeneratedDocumentDTO, GqlJwtAuthGuard, HttpApiError, HttpJwtAuthGuard, IPNProvider, InjectBucket, LOG_EXTENSION_REPOSITORY, LangType, LogExtensionDomainEntity, MetaDocumentInputDTO, ONBOARDING_EXPIRY_DAYS, ONBOARDING_EXPIRY_MS, OptionalCurrentUser, OptionalGqlJwtAuthGuard, PaginationInputDTO, PaginationResult, PaginationUtils, PaymentProvider, PollingProvider, QuantityUtils, RolesGuard, SignatureInfoDTO, SignatureInfoInputDTO, SignedDigitalDocumentDTO, SignedDigitalDocumentInputDTO, TransactionDTO, UseBucket, bucketProvidersFor, bucketTokenFor, buildPaginationResult, checkPaymentAmount, checkPaymentSymbol, computeOnboardingExpiresAt, configureExtensionAuth, configurePlatformSettings, createPaginationResult, extensionEntities, generateHashFromString, generateRandomHash, generateUniqueHash, getAmountPlusFee, getAppliedBlockNum, hasServerSecret, isExtensionAvailable, mergeSecretConfig, paginationInputToOffset, platformSettings, providerSuppliedPaths, redactSecretConfig, registerExtensionEntities, resetExtensionEntities, rethrowChainError, verifySignedDocumentAgainstStoredDraft, waitAfterTransactBeforeChainTableRead };
1516
+ export type { AuthRolesOptions, BucketSource, BucketSpec, DeserializedDescriptionOfExtension, ExcludeCommonProps, ExtensionAppTerminatePayload, ExtensionAuthOptions, ExtensionConfigFieldPolicy, ExtensionConfigPolicy, ExtensionDomainInterface, ExtensionDomainRepository, ExtensionEntityClass, ExtensionSchemaMigrationAfterContext, GeneratedDocumentDomainInterface, GeneratedDocumentDraft, IDesktopConfig, IExtensionSchemaMigration, IRegistryExtension, IResolvedRegistryExtension, LoadGeneratedDocumentByDocHash, LogExtensionDomainInterface, LogExtensionDomainRepository, LogExtensionFilter, LogExtensionPaginationOptions, LogExtensionPaginationResult, PaymentDetails, PlatformBlockchainSettings, PlatformSettings, RegisteredBucket, RequireFields, SignedDocumentMetaCompareMode, SignedDocumentMetaVerification, SignedDocumentToVerify, TransactResultWithResponse };