526 Commits

Author SHA1 Message Date
coopops ad0c140255 [989-9][@ant] feat(blagorost): инструкция «Инвестирование» — два пути паевых взносов
seed-capital фаза 08-investments — программно подготавливает стенд для съёмки:
- soviet::sndagreement для petrov+ekaterina (соглашения wallet и blagorost
  ЦПП), создаёт пользовательские кошельки
- capital::getclearance + soviet::confirmapprv — приложения к УХД-договору
  для инвесторов
- capital::startproject + capital::openproject — компонент в active со
  включённым приёмом инвестиций
- wallet::createdeposit + gateway::completeincome — пополняет кошельки
  инвесторов (600 000 ₽ petrov, 300 000 ₽ ekaterina)
- capital::createinvest — petrov 500 000 ₽ → компонент MVP v1
- capital::createpinv  — ekaterina 200 000 ₽ → программа «Капитализация»

Сценарий blagorost/investments.mjs снимает 3 кадра:
- toggle «Принимает инвестиции» включён в sidebar (выделен)
- вкладка «План» компонента: строка «Привлекаемые инвестиции» в колонке
  «Факт» с реально поступившими средствами
- профиль с выделенной кнопкой «Инвестировать» под Кошельком Благороста

Проза investments.md описывает два пути инвестирования:
1) В компонент — пайщик сам приоритизирует, кнопка «Инвестировать (I)»
   на карточке компонента
2) В программу «Капитализация» — кнопка «Инвестировать» на профиле,
   совет распределяет средства между компонентами

Таблица сравнения двух путей; admonition про источник средств (основной
кошелёк) и про разделение паевых взносов пайщиков и финансирования
от кооператива.

mkdocs.yml: новая страница в разделе «Благорост» (Инвестирование).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 11:17:35 +00:00
coopops 75bd3a9fa1 [989-9][@ant] feat(blagorost): master-and-plan + аннотации/активация в project-create
master-and-plan:
- seed-capital фаза 07 — программно одобряет УХД-договоры всех contributors
  (soviet::confirmapprv через contributor_hash), подписывает приложение
  председателя к компоненту (capital::getclearance + confirmapprv), назначает
  мастера (capitalSetMaster) и устанавливает план 160 ч × 1500 ₽ + 50 000 ₽
  расходов (capitalSetPlan)
- сценарий blagorost/master-and-plan.mjs снимает 3 кадра:
  страница компонента с мастером, вкладка «План» компонента (таблица
  план/факт со всеми расчётными пулами от контракта), сводный план проекта
- проза master-and-plan.md описывает роль мастера, три значения плана
  (часы/ставка/доп.расходы), как контракт разворачивает их в полные пулы,
  что разблокирует переключатель «Принимает инвестиции»
- mkdocs.yml: новая страница в разделе «Благорост»

project-create:
- сценарий расширен: после Мастерской открывает карточку проекта (статус
  «Ожидает», sidebar выделен), переключает в «Активен» через UpdateStatus
  dropdown, переходит в карточку компонента и активирует её
- через lib/annotate.mjs накладывает красные рамки на ключевые элементы:
  «+ Проект (P)» в FAB, «+» в строке проекта, «Статус» в sidebar
- проза уточнена: Active разблокирует только приём коммитов; toggle
  «Принимает инвестиции» в sidebar — только после плана; в проекты
  напрямую не инвестируем

profile:
- второй кадр с прокруткой к таблице взносов
- проза описывает роли (Соавтор/Исполнитель/Инвестор/Координатор)
  и отдельно строку «Получено в Благорост» (доля от других пайщиков
  по правилам ЦПП)

infra:
- harness.mjs: shot() возвращает абсолютный path для пост-обработки PNG
  (annotate без сериализации в manifest)
- seed-capital/index.ts: phase 07 в реестре фаз

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 11:17:35 +00:00
coopops 184530dab7 [ledger2][@ant] refactor(ledger2): wallet IDs uint64_t → eosio::name
Сквозная замена числовых идентификаторов кошельков ledger2 (1001/2001/9001/...)
на eosio::name с префиксом w.<contract>.<waltype> по аналогии с операциями
(o.<contract>.<verb>) и процессами (p.<contract>.<noun>).

Маппинг:
  2001 → w.wal.share    (паевые деньгами)
  2002 → w.reg.minshr   (минимальный паевой)
  2003 → w.wal.sharid   (паевой фонд РИД)
  3001 → w.reg.entry    (вступительные)
  3002 → w.sov.member   (членские)
  3003 → w.sov.delgte   (делегатские)
  4001 → w.wal.wthdrw   (возвраты пайщикам)
  4002 → w.mkt.payout   (выплаты поставщикам)
  4051 → w.cap.loan     (займы)
  5001 → w.led.adjust   (ручные корректировки)
  9001 → w.cap.bginv    (Благорост — деньги)
  9002 → w.cap.bgrid    (Благорост — РИД)
  9003 → w.cap.bgprop   (Благорост — имущество)
  9004 → w.cap.bgmem    (Благорост — членские)
  10001 → w.cap.gncom   (Генератор — коммит)
  10002 → w.cap.gnmem   (Генератор — членские)
  11001 → w.mkt.fund    (Стол Заказов)
  0     → eosio::name{} (sentinel «вне системы» для ISSUE/REVOKE)

Затронуто:
  • C++ контракты: wallets.hpp, operations.hpp, table_ledger2_wallet.hpp
    (id: uint64_t → eosio::name, primary_key() = id.value), actions
    walletop/walmove/revert.
  • cooptypes: WalletMeta { name: IName, human_name }, OperationMeta
    wallet_from/to: IName | null, IWallet2.id, IWalmove, IRevert.
  • controller: DTO Int → String, getLedger2History разделён на accountId
    (число) + walletName (строка), repository без ::bigint для wallet полей.
  • SDK zeus/index.ts: 4 секции типов под String + walletName поле.
  • desktop: WalletIdCell prop wallet-name, store getWalletByName, query
    param wallet_name=, OperationsPage filter walletName.
  • YAML стандарты: 10 файлов processes capital/marketplace/registrator/
    soviet/wallet — wallet_from/wallet_to ('' для sentinel).
  • boot tests: walmove/migrate/read-layer на eosio::name.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 11:11:46 +00:00
Alex Ant 443b11480d chore(release): publish 2026-04-27 11:23:16 +05:00
coopops d3cc96fcd5 [989-9][@ant] feat(blagorost): seed-capital фазы + 4 страницы документации
seed-capital — поэтапная подготовка стенда для doc-shoot. Диспетчер принимает
список фаз и --up-to=<phase> — стенд можно остановить в любой точке для ручного
теста UI на конкретном этапе.

Фазы:
- 01-programs / 02-extension-config / 03-projects (реестр из _blago/INDEX.md + Кошелёк пайщика)
- 04-contributor (председатель ant) / 05-additional-contributors (ivanpetrov, ekaterina)
- 06-create-project-koshelek (рабочий проект для серии «Генерация»)

Сценарии и документация (components/docs/docs/new/blagorost/):
- adaptation, profile, projects-list, project-create

Orchestrator bin/shoot.mjs: поддержка meta.fixtures (явный список пайщиков для
seed-фаз) + meta.prepare (запуск нужных фаз перед сценарием).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 17:40:59 +00:00
coopops 151610ac38 chore(release): publish 2026-04-26 09:19:42 +00:00
coopops 23adebc281 chore(release): publish 2026-04-26 08:39:02 +00:00
coopops 7f3a26f268 [989-9][@ant] feat(docs-harness): принести harness + signin-инструкцию из ветки 989-4 поверх актуального reports
Без merge'а старой ветки 989-4 (там 47/48 коммитов — устаревшие версии ledger2/reports работы, уже сделанной заново в 989-1/2/3 и доехавшей до reports). Принесена только инфраструктура для съёмки документации:

- docs-harness/ — playwright-сценарии + хелперы (lib/{harness,annotate,install,render-md}.mjs), run.mjs, package.json, README, scenarios/auth/signin.mjs
- components/boot/src/scripts/add-plain-participant.ts — генератор фикстур пайщиков для harness
- components/docs/docs/new/auth/signin.md + 3 PNG в assets/new/auth/signin/ — эталонная инструкция «Вход пайщика»
- components/docs/mkdocs.yml — добавлена секция «Вход в систему» в nav (без удаления ссылки «Реестр стандартов» — это посторонний шум 989-4)

Проверено: npm install проходит, синтаксис всех .mjs чистый, run.mjs стартует и доходит до загрузки сценария — дальше нужны живые chain/parser/controller/desktop и фикстура ivanpetrov (генерируется add-plain-participant).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 06:33:25 +00:00
coopops b60580f406 [989-9][@ant] feat(reports): revert → contract-only (whitelist auth, без UI/backend mutation)
Председатель больше не может откатывать операцию через UI: action `ledger2::revert`
сохранён, но принимает только подпись от whitelisted-контрактов
(`check_auth_and_get_payer_or_fail(contracts_whitelist)` без ветки `has_auth(coopname)`).

Why: ledger2 — учётный слой; зеркальная проводка председателем top-level
рассинхронизирует state контрактов-инициаторов (registrator/wallet/capital).
Контракты-инициаторы знают свой operation_code и могут собрать корректные
параметры зеркала из cooptypes/operations.hpp; они же одновременно откатывают
свои домены (participants/deposits/contributors).

Контракт ledger2:
- revert.cpp: убрана ветка has_auth(coopname); top-level от пайщика/председателя
  падает на whitelist-check. Все остальные проверки (запрет o.mig.*, валидация
  mirror-параметров) сохранены.

Backend (controller):
- удалены: revertOperation mutation, RevertOperationInputDTO, метод service
  revertOperation + computeMirrorParams + WALLET_OP_CODE map, RevertBlockchainDomainInterface
  и адаптер revert(), Ledger2StatePort.getOperationByGlobalSequence + repo-метод
- осталось: walmove (с UI), порт revert на cooptypes для контрактных потребителей

SDK:
- удалена mutation/ledger2/revertOperation.ts; cooptypes Actions.Revert + IRevert
  оставлены (нужны другим контрактам).

UI (desktop):
- удалён RevertOperationDialog.vue
- из OperationsPage убраны: import RevertOperationDialog, useSession/storeToRefs,
  revertDialog state, canRevert/openRevertFor/onRevertSuccess, кнопка ↩
- Ledger2 store/api/types: убран revertOperation method/IRevertOperationInput

Тесты:
- удалены revert.test.ts + adjust/revert.ts helper
- walmove.test.ts (3 теста) + остальной suite — зелёный

Полный suite: 92 passed | 1 skipped | 0 failed (clean reboot).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 15:30:11 +00:00
coopops d340eed56c [989-9][@ant] feat(reports): корректировки председателя — walmove + revert (Sprint 5 Epic 5 MVP)
Контрактный слой ledger2:
- new actions ledger2::walmove (operation o.adj.walmove) — перевод между
  кошельками одного бух.счёта без Dr/Cr; ledger2::revert (operation o.adj.rev)
  — зеркальная проводка по originalGlobalSequence; запрет revert на o.mig.*
- new WalletOp::REVOKE для зеркала ISSUE (изъятие с wallet_from без to)
- namespace operations::adjustment (WALMOVE/REVERSAL) + processes::adjustment::CORRECTION
- OPERATION_ADJUSTMENT_REGISTRY — отдельный мини-реестр для UI human_name
  (динамические параметры не входят в OPERATION_REGISTRY)

cooptypes (зеркало контракта):
- WalletOp += 'REVOKE'; LEDGER2_OPERATION_REGISTRY += 2 adjustment-записи (kind:'adjustment')
- LEDGER2_PROCESS_REGISTRY += p.adj.fix
- new actions/walmove.ts + actions/revert.ts + IWalmove/IRevert интерфейсы
- helper isAdjustmentOperation(code)

controller (backend):
- Ledger2BlockchainPort + Ledger2BlockchainAdapter — подпись coopname@active
- DTO WalmoveInputDTO / RevertOperationInputDTO / Ledger2AdjustmentResultDTO
- Ledger2Resolver mutations walmoveWallets / revertOperation (роль chairman)
- Ledger2Service: walmove валидирует одинаковость account_id источника и
  получателя через cooptypes; revertOperation поднимает оригинал из
  blockchain_actions, swap Dr/Cr и ISSUE → REVOKE для зеркала
- TypeOrmLedger2StateRepository.getOperationByGlobalSequence
- process-hash-locator: + p.adj.fix → []

SDK (regen + новые мутации):
- mutations/ledger2/walmoveWallets.ts + revertOperation.ts
- selectors/ledger2/ledger2AdjustmentResultSelector.ts
- Zeus regenerated

UI (рабочий стол reports):
- WalletTransferDialog: select from/to (фильтр по тому же account_id),
  amount, обязательное memo; иконка ↔ в строке кошелька + кнопка «Перевести»
  в шапке (только председателю) → CoopWalletsPage
- RevertOperationDialog: превью операции, обязательное memo, баннер для o.mig.*;
  кнопка «↩ Откатить» в шапке развёрнутой записи OperationsPage
- Toggle «Только корректировки» в фильтрах OperationsPage (actionNames=walmove,revert)
- Ledger2 store/api: methods walmoveWallets / revertOperation; types

Тесты (89/90 → 94/95 passed | 1 skipped | 0 failed):
- walmove.test.ts: успешный перевод 2002→2001 + проверка accountBalance
  не меняется (WALLET_ONLY) + запрет на разные счета + запрет пустого memo
- revert.test.ts: откат o.reg.putmin восстанавливает 2002 и счёт 80 +
  запрет revert миграционных операций
- balance читается напрямую с чейна (parser отстаёт на минуты после reboot)

Документация:
- epic-5: декомпозиция на WalMove ✓ / Reversal ✓ / Manual ⏸
- adr-manual-corrections.md: почему Manual отложен (нужен документ
  протокола решения совета — XSD/шаблон/registry/processDecision-flow)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 09:04:37 +00:00
coopops cca8781168 [989-9][@ant] test(boot): починить оставшиеся 4 pre-existing failure'а + регенерация sdk zeus
Все 90 тестов теперь зелёные (89 passed | 1 skipped | 0 failed).

Изменения:

* boot/src/init/infra.ts: 2s → 8s sleep между setContract и createToken.
  На свежем nodeos setabi последнего контракта не успевал коммититься,
  eosjs.getAbi('eosio.token') падал с "Read past end of buffer".

* boot/src/tests/registrator/registerUser.ts: legacy fund::coopwallet
  (circulating_account/initial_account) → ledger2::accounts (счета 80, 86).
  После Epic 1 confirmreg перестал вызывать Ledger::add, поэтому
  legacy-баланс не пополняется. Теперь сравниваем приращение balance счёта
  80 (Паевой фонд, на который попадает minimum через PUT_MINSHARE) и
  счёта 86 (Целевое финансирование, через PAY_ENTRANCE).

* boot/src/tests/capital-import.test.ts: ожидаемый contributor.status
  скорректирован 'active' → 'import'. ImportContributor создаёт запись
  со статусом IMPORT (см. Status::IMPORT в contributors.hpp); перевод
  в ACTIVE — отдельным шагом.

* boot/src/tests/ledger2-read-layer.test.ts: фильтр accountId без
  actionNames возвращает все sibling-actions процесса (по дизайну
  репозитория). Тест явно передаёт actionNames=['debit','credit'],
  чтобы проверить только прямые проводки.

* boot/src/tests/capital.test.ts: regshare-идемпотентность — добавлен
  sleep(2000) перед повторным regshare, чтобы expiration транзакции
  отличался (иначе nodeos отклоняет как duplicate transaction).

* controller/schema.gql + sdk/zeus: регенерированы из ProcessRegistry
  и Ledger2-резолверов (operationCode/operationCodes вместо action*).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 07:07:45 +00:00
coopops 6df13c0e70 [989-9][@ant] test(boot): обновить ledger2-read-layer.test под operationCode
GraphQL HISTORY_QUERY: actionCode → operationCode; фильтр actionCodes →
operationCodes; ожидаемый код в filter-тесте mig.share → o.mig.share.

Регрессии после operations/processes refactor закрыты:
17 failed → 4 failed (84 → 86 passed). Оставшиеся 4 — pre-existing,
не связаны с рефакторингом нейминга:

  - capital-import: contributor.status='import' вместо 'active'
    (поведение capital-контракта, не наша область).
  - registrator x2: compareTokenAmounts на legacy
    fund::coopwallet.circulating_account.available, который не пополняется
    с Epic 1 (Ledger::add удалён).
  - ledger2-read-layer: фильтр accountId возвращает sibling-actions
    одного процесса (включая wallet_to=80000), тест ожидает строгий 51000.
    Pre-existing разрыв между документированным поведением фильтра
    (через process_hash IN ...) и ожиданиями теста.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 05:36:39 +00:00
coopops e8b323a1ec [989-9][@ant] refactor(ledger2): cooptypes — source of truth для operations/processes
* cooptypes/src/ledger2/operations.ts — LEDGER2_OPERATION_REGISTRY (18 записей),
  mirror `cpp/lib/core/ledger2/operations.hpp` (OPERATION_REGISTRY).
* cooptypes/src/ledger2/processes.ts — LEDGER2_PROCESS_REGISTRY (11 записей),
  mirror `processes.hpp`.
* Controller process-hash-locator: строит OPERATION_CODE_TO_PROCESS_TYPE
  из cooptypes; только backend-специфичный оверрайд (`o.cap.commit` →
  `p.cap.commit`) + PROCESS_HASH_LOCATOR (таблица/поле entity-hash).
  Никаких локальных хардкод-списков операций или процессов.
* Controller ProcessRegistryService: applyData.action_code → operation_code,
  OPERATION_CODE_TO_PROCESS_TYPE, SQL-колонка alias operationCode.
* Controller DTO/domain: actionCode → operationCode, actionCodes → operationCodes.
* TypeORM repository: `a.data ->> 'operation_code'`, alias "operationCode".
* SDK ledger2OperationSelector: actionCode → operationCode (zeus регенерится из
  обновлённой schema.gql при старте контроллера + generate-client).
* Desktop OperationsPage: actionCode → operationCode; локальный ACTION_LABELS map
  удалён — human-name тянется через Ledger2.getOperationHumanName из cooptypes;
  цветовая схема по второму сегменту `o.<contract>.<verb>`.
* Boot-тест process-registry: обновлён под новые имена (p.reg.accept, p.wal.depo,
  o.reg.payent, o.reg.putmin, o.wal.depcpl) и operation_code поле.

Типы ok (tsc controller, vue-tsc desktop), cooptypes собирается.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 19:28:27 +00:00
Alex Ant 32592fded2 chore(release): publish 2026-04-24 01:38:37 +05:00
Alex Ant db356628c9 chore(release): publish 2026-04-24 01:38:16 +05:00
Alex Ant d104a9e037 chore(release): publish 2026-04-23 22:27:50 +05:00
Alex Ant 0bcca3892e chore(release): publish 2026-04-23 21:04:11 +05:00
Alex Ant 5e58f08201 chore(release): publish 2026-04-23 18:53:33 +05:00
Alex Ant 7753fffbac chore(release): publish 2026-04-23 18:33:04 +05:00
Alex Ant 6929c72d2c Merge branch 'dev' of github.com:coopenomics/mono into dev
Made-with: Cursor

# Conflicts:
#	components/parser/package.json
2026-04-23 18:32:17 +05:00
coopops 214db313cc [989-4][@ant] fix(extensions): reports как default app + initialize-стаб — устанавливается автоматически
Два пробела после [116] «reports встроенный extension»:
- reports отсутствовал в getDefaultApps(), поэтому не оседал в postgres через installDefaultApps на старте controller'а — приходилось ставить руками.
- ReportsExtensionModule не имел метода initialize(), и lifecycle-service кидал «moduleInstance.initialize is not a function» при runApp.

Фиксы:
- getDefaultApps(): +reports (enabled=true, builtinDefaultConfig).
- ReportsExtensionModule: async initialize() {} — stub по образцу BuiltinPluginModule (нет своего крона/состояния).
- postgres-init.ts: дублирующий seed в initExtensionsInPostgres (ON CONFLICT DO NOTHING) — чтобы boot:extra сразу давал столу появиться, не ждать следующего onModuleInit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 13:30:37 +00:00
coopops 7bbce2298d [989-4][@ant] fix(test): AC8 в ledger2-migrate.test.ts — учесть baseline кошельков
Первый прогон показал: Σ wallets после миграции = 1_000_182_700 (testnet
накопил wallet-балансы при boot процессе создания 5 пайщиков), но AC8
ожидал ровно seedCash=5000. Это моя ошибка в ассерте — seed добавляет
seedCash к baseline, а не формирует всю сумму.

Фикс:
- Добавлена переменная baselineWalletsTotal (измеряется в seed-фазе ДО
  первой миграции, как и baselineCashAcc/ShareAcc/EntryAcc).
- AC8 теперь проверяет totalWallets ≈ baselineWalletsTotal + seedCash.

Прогон полного pnpm test:all после фикса: 76 passed | 3 failed | 1 skipped.
Все 3 оставшихся fail — pre-existing, не связаны с ledger2-рефактором:
- registrator тесты ждут legacy `circulating_account`, отключённый ещё в
  Epic 1 intro (b67d41b00f).
- capital-import тест на `status === 'active'` — логика importcontr.cpp
  не менялась в этом PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 13:30:37 +00:00
coopops c2e2e51e27 [989-4][@ant] refactor(ledger2): пересмотр плана счетов + кошельков + реестра операций по code-review PR #357
Ответ на 22 треда ревью владельца (2026-04-20). Детерминированная миграция
без транзитного 99 и зеркала CASH_MAIN, разнесение legacy на 6 целевых
кошельков. Разделение ACT2_SHARE на commit (08/80) + accept (04/08).
Заём переведён с 67 на 58/51. Введён WALLET_ONLY тип проводок.

План счетов (6 вместо 7):
- удалён 99 OPENING_TRANSIT (лишний транзит)
- удалён 67 LONG_TERM_LOANS (займы теперь через 58/51)
- добавлен 08 NON_CURRENT_INVESTMENTS «Вложения во внеоборотные активы»
  для промежуточного «принятый коммит»: commit → Dr 08/Cr 80, accept → Dr 04/Cr 08

Кошельки (17 вместо 11):
- удалены: 1001 CASH_MAIN, 4050 LOAN_RECEIVED, 4052 DEBT_CLOSED_SINK
- добавлены: 4051 LOAN_ISSUED, 5001 MANUAL_ADJUST,
  9001-9004 Благорост (INVEST/RID/PROPERTY/MEMBERSHIP),
  10001-10002 Генератор (COMMIT/MEMBERSHIP), 11001 MARKETPLACE_FUND

Реестр операций (20 записей, WalletOp::WALLET_ONLY=4 новый):
- ACT2_SHARE разбит на COMMIT_RID (cap.commit) + ACCEPT_RID (cap.accept)
- ACT2_LOAN/LOAN_REPAYMENT → ISSUE_LOAN (cap.lnissue, Dr 58/Cr 51) + REPAY_LOAN (cap.lnrepay, Dr 80/Cr 58)
- CAPITAL_IMPORT → ISSUE на BLAGOROST_INVEST 9001
- ACT2_PROGRAM_PROP → ISSUE на BLAGOROST_PROPERTY 9003
- CONVERT_TO_AXN → human_name «Трансляция паевого взноса из ЦПП Цифровой Кошелёк в членский взнос за пользование инфраструктурой»
- Новое cap.invest — WALLET_ONLY TRANSFER SHARE_FUND_PAY 2001 → BLAGOROST_INVEST 9001 (без бух-проводок)
- OPENING_CASH удалён. OPENING_SHARE/ENTRY/RID → TRANSIT_SHARE/ENTRY/RID
- Добавлены TRANSIT_MIN_SHARE, TRANSIT_BLAGOROST, TRANSIT_COMMITMENT
- Compile-time валидации: wallet_only_has_zero_accounts, dr_ne_cr_when_posting, transfer_wallet_from_ne_to (покрыт и WALLET_ONLY)

Миграция (migrate.cpp) — вариант C + progwallets:
- Читает cooperative2.minimum + active_participants_count (fallback — participants status='accepted')
- Суммирует progwallet.blocked по program_id=4 (Благорост) и =3 (Генератор)
- До 6 TRANSIT_* проводок per кооп с инвариантами eosio::check
- Прямые Dr/Cr без 99-транзита, двойной wallet-учёт исключён

Вызывающие контракты:
- capital::signact2: ACT2_SHARE → COMMIT_RID + ACCEPT_RID (атомарно, один process_hash). ACT2_LOAN → REPAY_LOAN
- capital::debtpaycnfrm: LOAN_REPAYMENT → ISSUE_LOAN (уточнено: это выдача займа, не возврат)

Controller + SDK:
- process-hash-locator.ts: мапа action_code → process_type под новые имена, до 3 action_code на один cap.act2res (commit + accept + lnrepay)
- sdk/reports/index.ts:4 — ИНН/КПП/ОГРН формулировка «живут в БД кооператива, не в блокчейне»

Тесты:
- ledger2-migrate.test.ts: переписан под 6 TRANSIT_* (AC1-AC9), проверка отсутствия 99 и 1001, инвариант Σ wallets
- ledger2-read-layer.test.ts: убран WALLET_CASH_MAIN, ACCOUNT_TRANSIT → проверка отсутствия, actionCodes 'mig.share'

Терминология:
- везде «паевой взнос» (не «пай», не «минимальный пай»). Feedback memory зафиксирован.

Закрытые треды ревью PR #357:
3110497427, 3110515593, 3110525276, 3110554221, 3110809387, 3110820659,
3110826179, 3110830707, 3110835085, 3110846530, 3110859570, 3110860470,
3110866644, 3110869995, 3110875784, 3110881945, 3110889550, 3110893784,
3110900719, 3110901751, 3111175626, 3111208865, 3111224738, 3111229308,
3111336184.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 13:30:37 +00:00
coopops c212fd7692 [989-4][@ant] test(capital): покрыть отделённый regshare после [562-13] — apprvappndx больше не inline-вызывает regshare
После [562-13] da8c443625 допуск (apprvappndx) и регистрация доли (regshare) разведены на два отдельных действия: signAppendix добавляет project_hash в appendixes контрибьютора, но сегмент в проекте больше не создаёт автоматически. Тесты 3-х спеков отражали старый «автоматический» флоу и падали на `Сегмент пайщика не найден` и `capital_contributor_shares = 0`.

Починка — без ослабления ассертов:
- processRegShare.ts: хелпер над capital::regshare
- A) "вклады… зарегистрированы автоматически" → "регистрируем доли через capital::regshare отдельным действием": спек сам вызывает regshare с user_shares = balance, жёстко проверяет segment.is_contributor=1, capital_contributor_shares==balance, Σ сегментов == Σ балансов, total_capital_contributors_shares==то же
- B) новый спек "regshare идемпотентен" — покрывает upsert-семантику regshare.cpp
- C) "тест ВЫСОКОЙ ТОЧНОСТИ": после signAppendix добавлен regshare по балансу — сегменты существуют до rfrshsegment/commitToResult; ассерт totalSharePercent≈100% остался

Результат: 60 passed | 1 skipped (61) против 3 failed | 56 passed | 1 skipped (60) до правки. Никаких .skip / try-catch-swallow — тесты честно зелёные.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 13:30:37 +00:00
coopops 2e0eb9a2de [989-4][@ant] fix(stream-consumer): убрать silent-error swallow + XAUTOCLAIM pending re-delivery + XTRIM MINID по consumption — чтобы parser/controller не теряли события при burst'ах и рестартах, и Epic 4 ProcessRegistry работал end-to-end на живой цепочке
Silent-catch в blockchain-consumer ACK'ил сообщения даже при упавшем saveDelta —
данные терялись безвозвратно; wallet::deposits/candidates2 не доходили до PG.
Consumer использовал `consumer-${random}` — каждый рестарт плодил zombie
со своими pending. Parser XTRIM MAXLEN=1000 при burst'ах удалял свежие
сообщения до того, как controller их прочитывал. rows$.subscribe без
error-handler'а молча убивал весь поток парсера при WS-разрыве.

Controller (blockchain-consumer.service.ts + redis-stream.service.ts):
- processDelta/processAction: убран try/catch-log-only → ошибки бросаются
  до handleMessage, сообщение остаётся pending в группе для retry.
- processAction: убран setTimeout(3s) fire-and-forget → ACK теперь после
  фактического save, а не до него.
- consumerName: стабильное 'coopback-main' вместо random.
- onModuleInit: recoverOwnPending (XREADGROUP STREAMS 0) доигрывает свои
  pending после рестарта; reclaimStalePending (XAUTOCLAIM idle>5min)
  забирает pending у зомби-consumer'ов.
- Периодические: XAUTOCLAIM 1/min + XTRIM MINID <first-pending-id> 1/30s
  — Redis-память ограничена фактической consumption, не придуманным числом.

Parser (RedisNotifier + DeltaParser + ActionParser + config):
- publishEvent/publishDelta/publishFork: XTRIM убран (trim — роль consumer'а).
- REDIS_STREAM_LIMIT удалён из config.ts / .env-example / AGENTS.md.
- rows$.subscribe({next,error,complete}) вместо callback'а: ошибка/complete
  триггерят process.exit, docker по restart:unless-stopped поднимает заново.

Integration tests (components/boot/src/tests/, +382 строк):
- process-registry.test.ts (Epic 4 e2e): 5 кейсов — reg.regist 2×apply,
  wall.deposit, processes listing, hex-64 validation, 404 на unknown hash.
- ledger2-read-layer.test.ts (Story 1.23 e2e): 5 кейсов — on-chain↔
  GraphQL срез accounts/wallets/history + фильтры actionCodes/accountId.
- shared/apiClient.ts: login chairman (eosjs-ecc) + gql + waitUntil.

Проверка на живой среде после fix'а:
- XLEN notifications = 70 (раньше 1001 фиксированно или потеря при burst).
- pending=0, lag=0 — ни одного silent drop, XAUTOCLAIM очистил зомби.
- blockchain_deltas впервые содержит wallet::deposits=3 (было 0).
- 18/18 boot integration + 77/77 controller unit тестов зелёные.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 13:30:36 +00:00
coopops 62bb9bddbb [989-4][@ant] refactor(process-registry): code review Epic 4 — починить тесты, локатор, миграцию, unify cap.act2res
Все блокирующие находки code review.

CRITICAL
  tests/unit/process-registry: переписаны под текущую архитектуру.
  Epic 1 addendum удалил wjournal/journal, Phase A стал читать
  blockchain_actions, но тесты остались мокать deltaRepo с _ledger2
  якорями → 4 из 6 кейсов падали с NotFoundException. Commit message
  Epic 4 "67/67 passed" стал неверен. Теперь:
    - Phase A мокается через actionRepository (name='apply', action_code
      в data, process_hash в data);
    - Phase B — deltaRepo с правильными таблицами (candidates2, results,
      deposits, etc.);
    - processType выводится из ACTION_CODE_TO_PROCESS_TYPE (не из
      delta.value.process_type);
    - добавлены кейсы reg.regist (2 apply под одним hash) и mig.opening;
    - account: '_ledger2' → 'ledger2' (bug с переименованием eeb4d50).
  Результат: 8/8 ProcessRegistry-тестов зелёные, всего suite 77/77.

HIGH — PROCESS_HASH_LOCATOR: неверные имена таблиц/полей.
  Проверено по C++ контрактам:
    registrator::regs         → candidates2                 (field: registration_hash)
    capital::segments         удалена из локатора           (project_hash, не result_hash)
    capital::debts/result_hash→ debts (только для cap.debt, поле debt_hash)
    capital::properties       → pgproperties                (field: property_hash)
    marketplace::requests/request_hash → hash               (поле именно hash)
  Без этого getProcess для reg.regist/mkt.offereq/cap.act2*/cap.act2prp
  возвращал пустое delta_history — UI был пустым на главном use-case.

HIGH — cap.act2res унификация (пользовательское уточнение).
  Акт-2 это ОДИН процесс с ДВУМЯ эффектами (приём РИД в пай + погашение
  займа), а не два процесса. В C++ ACTION_REGISTRY оба action_code
  (cap.act2shr + cap.act2ln) уже указывают на CAPITAL_ACT2_RESULT =
  "cap.act2res". Backend теперь то же:
    - ACTION_CODE_TO_PROCESS_TYPE: cap.act2shr / cap.act2ln → cap.act2res;
    - PROCESS_HASH_LOCATOR: cap.act2res → [results] (segments/debts
      связаны через project_hash, не result_hash — не часть этого процесса);
    - IProcessType: заменили cap.act2shr | cap.act2ln на cap.act2res.
  UI при рендере process.actions видит два apply с разными action_code
  → группирует и показывает два эффекта раздельно внутри одной карточки
  процесса (discriminator = action.data.action_code).

HIGH — Migration V2.1.0: индексы были без LOWER() → планировщик не
  выбирал их, все getProcess упирались в seq-scan blockchain_deltas.
  Теперь все expression-индексы построены на LOWER(value->>'field')
  (совпадает с сервисным WHERE). Обновлены имена таблиц/полей согласно
  новому PROCESS_HASH_LOCATOR. coopname не в индексе — OR (scope/value)
  не покрывается одним expression-index, постфильтр дёшев (≤5 строк
  per hash). CONCURRENTLY не используется (DEV-стенд).

HIGH — listProcesses GROUP BY двоил мульти-операционные процессы.
  Было: GROUP BY action_code, hash, coopname — для reg.regist (entrfee+
  minshare) и cap.act2res (shr+ln) показывало по две строки, totalCount
  (COUNT DISTINCT hash) не совпадал с items.length.
  Стало: GROUP BY LOWER(hash), coopname; MIN(action_code) для вывода
  processType (у мульти-action процессов оба action_code маппятся в
  один type, так что MIN даёт корректный тип).

HIGH — Убрать N+1 per-row counts в listProcesses.
  Было: на каждую строку page 3 SQL (countActionsByHash +
  countDeltasByHash + countDocumentsByHash). 100 строк × 3 SQL на
  request → connection pool exhaustion под нагрузкой. Поля
  actionCount/deltaCount/documentCount удалены из ProcessSummary DTO
  и IProcessSummary interface. UI запрашивает getProcess(hash) при
  раскрытии конкретного процесса — там счётчики выводимы из
  actions.length/delta_history.length/documents.length.

Silent fixes:
  - LIMIT/OFFSET в listProcesses: параметризация через $n вместо
    литералов (безопасность + корректность при edge NaN).
  - compareByBlock: tiebreaker по global_sequence (BigInt) когда
    block_num + created_at совпадают — детерминированный порядок.
  - blockchain-consumer: строгая проверка непустой строки в
    value.coopname перед fallback на scope (пустой "" теряет дельту).
  - Удалён dead LEDGER2_ACTION_NAMES.
  - Устаревший комментарий ProcessRegistryDomainModule → blockchain_actions.
  - add-test-user.ts: cleos-подсказки обновлены с wjournal на
    candidates2/accounts2/wallets2.

Преднамеренно НЕ трогаю:
  - Cross-tenant coopname validation (E1): оставлено для federation.
  - Fork purgeAfterBlock (E6): вне scope Story 1.23, общесистемный
    вопрос для отдельной задачи.
  - Redis cache hardening (E9-E11): TTL 60s acceptable для MVP.
2026-04-23 13:30:36 +00:00
coopops 0148cd1e58 [989-1][@ant] refactor(boot-tests): code review Chunk 3 — ужесточить ассершны migrate-теста и почистить мёртвый код кошелька — чтобы silent-pass на warm-chain не прятал регрессии, повторный migrate действительно не менял state, а тест-хелперы падали на NaN-amount вместо криптичного asset-parse.
- P1 AC5: падать если accounts[99] не создан при свежем миграционном прогоне (было silent-pass на undefined) [ledger2-migrate.test.ts]
- P2 AC6: expect(acc).toBeDefined() перед чтением .balance у cash/share/entry (TypeError → понятный fail) [ledger2-migrate.test.ts]
- P3 AC7: snapshot meta + балансов ДО и ПОСЛЕ повторного migrate() — проверяем что migrated_coops/last_migrated_coop_index/debit_balance(51)/credit_balance(80) не изменились [ledger2-migrate.test.ts]
- P5 Заменить literals Number().toBe(0)/(1) на LedgerAccountType.ACTIVE/PASSIVE enum (экспортирован из walletUtils) — устойчивость к переименованию типов [ledger2-migrate.test.ts + walletUtils.ts]
- P6 depositToWallet(amount): Number.isFinite + amount > 0 guard — NaN/Infinity/отрицательные значения теперь дают понятную ошибку до сериализации в asset [depositToWallet.ts]
- P7 Dead-code cleanup в wallet.test.ts: убраны tester1/walletProgramStates1/addUser — никогда не использовались в ассертах; вместо этого добавлены expect().toBeDefined() на wallet/program/depositId/userWallet

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 13:30:35 +00:00
coopops da44b98dbf [989-1][@ant] refactor(ledger2): code review Chunk 1 — закрыть D1/D2/D3/D4 + защитные проверки — чтобы гарантировать парность walletop+debit+credit (sender-guard), убрать дублирующиеся нотификации кооперативу и закрыть потенциальные «тихие» потери legacy-остатков при миграции.
- D1: sender-guard в walletop/debit/credit — допустим только inline из apply (парность double-entry гарантирована, top-level вызов с ledger2@active запрещён)
- D2: TODO(payer) в walletop/debit/credit — payer=get_self() временно до общего перехода на coopname+eosio.code
- D3: read_legacy_balances аварит на неожиданном legacy id + проверяет символ валюты (silent-drop заменён на check(false))
- D4: повторный migrate() после полного прогона — тихий no-op без eosio::check (тест AC7 обновлён)
- apply: require_recipient после валидации coopname (не до)
- walletop: ISSUE требует wallet_from==0, BLOCK/UNBLOCK требуют wallet_to==0
- walletop/debit/credit: убран require_recipient (дублировал notification из apply)
- accounts2::is_empty() теперь включает поле balance
- actions.hpp: добавлен static_assert(wallets_exist_in_registry) — compile-time проверка что wallet_id из ACTION_REGISTRY существуют в LEDGER2_WALLET_REGISTRY
- migrate: guard против permanent-lock на пустой таблице cooperatives

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 13:30:35 +00:00
coopops f48ff28628 [989-1][@ant] refactor(ledger2): пересмотр плана счетов + RAM-чистка журналов + atomic 3-inline apply — закрыть Decision #1 code review (миграция через apply с двойной проводкой), убрать дублирование журнала из RAM (история уже в blockchain_actions+deltas), и подготовить контракт к РИД-корректировке Восхода 56.8M RUB.
Контракт ledger2:
  - План счетов сжат до 7 (04 НМА, 51 расч, 58 фин-вл, 67 займы, 80 паевой, 86 целевое, 99 транзит). Субсчета 86.x удалены.
  - Кошельки переименованы и пронумерованы ×1000 (1001 CASH_MAIN, 2001-2003 паевые, 3001-3003 целевые, 4001-4002 sinks, 4050/4052 займы); off-chain агрегаторы (1000/2000/3000) не создаются ончейн.
  - ACTION_REGISTRY перепривязан + добавлены mig.opncash/opnshr/opnent/opnrid; CONVERT_TO_AXN → Dr 80 / Cr 86.
  - Удалены таблицы journal+wjournal из RAM (история = action traces, парсер уже их захватывает).
  - apply() стал orchestrator-ом; рассылает 3 атомарных inline action: walletop / debit / credit, связанных общим process_hash.
  - В accounts2 добавлено поле balance (пересчитывается в debit/credit).
  - migrate(from_coop_index, limit) — курсорный режим через серию apply(OPENING_*) с RID-коррекцией для Восхода.
  - constexpr std::array + static_asserts (уникальность кодов, Dr≠Cr, wallet_from≠wallet_to, accounts_exist), memo cap, coopname validation.
  - soviet/converttoaxn: scope = coopname (а не _provider).

Backend контроллер:
  - ProcessRegistryService Phase A теперь сканирует blockchain_actions[ledger2] вместо deltas[wjournal/journal].
  - Добавлен ACTION_CODE_TO_PROCESS_TYPE для вывода process_type из action_code (ACTION_REGISTRY синхронизирован).
  - Миграция V2.1.0 убрала индексы wjournal/journal, добавила idx_actions_ledger2_process_hash + apply_action_code/username.
  - Cooptypes IProcessType +mig.opening/mig.rid; chart-of-accounts.entity +INTANGIBLE_ASSETS; reports-генераторы (buhotch, preview) убрали 86.x из targetFunds.

Тесты:
  - ledger2-migrate.test.ts переписан под новую схему: 8/8 проходит на live стенде.
  - fakeDocument в soviet/wallet тестах → IDocument2-схема (через shared/fakeDocument).
  - vitest fileParallelism: false — гарантия отсутствия гонок ончейн-state между файлами.
2026-04-23 13:30:35 +00:00
coopops e0d2d5266c [989-4][@ant] fix(process-registry): end-to-end работает на живом стенде — baseline через live blockchain+parser+controller
FIXES после live-прогона через pnpm run reboot + add-test-user:

1) parser/src/config.ts: добавлены ledger2+marketplace в subscribedContracts —
   без этого parser не пускал ledger2-дельты в Redis stream и controller не
   получал wjournal/journal, т.е. весь pipeline стоял.

2) controller/src/infrastructure/blockchain/blockchain-consumer.service.ts:
   processDeltaDelayed фильтровал по `delta.value?.coopname`, но ledger2
   (wjournal/journal/wallets/accounts) и большинство кооп-scope таблиц
   хранят coopname В SCOPE, а не в value.jsonb. Добавлен fallback на scope:
   `deltaCoop = delta.value?.coopname ?? delta.scope`.

3) domain/process-registry/services/process-registry.service.ts:
   - LEDGER2_CODE изменён с `_ledger2` на `ledger2` (имя on-chain аккаунта
     реальное, без подчёркивания — verified через cleos get abi ledger2).
   - phase A + listProcesses: coopname-скоупинг по `d.scope` (вместо
     несуществующего value->>'coopname' для ledger2 journals).
   - phase B (scanEntityDeltas): принимает оба варианта — `scope = $coop
     OR value->>'coopname' = $coop`, чтобы охватить и per-coop-scope
     таблицы, и singleton-scope контракты (registrator.regs).
   - LOWER() обе стороны при сравнении process_hash: ончейн хранит
     checksum256 uppercase, а нормализация API — lowercase.
   - listProcesses возвращает processHash в lowercase через LOWER() в
     SELECT (единообразно с getProcess).
   - countDeltasByHash/countDocumentsByHash: LOWER() + scope=coop.

4) migrations/V2.1.0: expression-индексы ledger2 journals теперь на
   (process_hash, scope) и (process_type, scope) — совпадают с фактическим
   where-условием сервиса.

5) cooptypes/common/names: `_ledger2.production/testnet = "ledger2"`
   (без подчёркивания, соответствует on-chain имени).

6) boot: добавлен CLI `pnpm run cli add-test-user <username>` для smoke-
   проверки Epic 4 на живом стенде после reboot. Также установлен
   `registration_hash: generateRandomSHA256()` в:
   - boot/init/infra.ts: adduser(ant) + adduser для 4 дополнительных
     членов совета (boot:extra mode);
   - boot/init/participant.ts: addUser+addUser2.

ПРОВЕРКА (live через curl + JWT подписанный JWT_SECRET из .env):

cleos get table ledger2 voskhod wjournal — 2 записи:
  id=0 reg.minshare, process_type=reg.regist, process_hash=<sha256>
  id=1 reg.entrfee,  process_type=reg.regist, process_hash=<sha256>
  (тот же hash — мульти-операционный процесс reg.regist)

query { process(hash:"28fe0b46...",coopname:"voskhod") }
→ process_type="reg.regist"
  delta_history: 4 (2 wjournal + 2 journal)
  actions: 3 (registrator::adduser + 2×ledger2::apply)
  documents: []

query { processes(filter:{coopname:"voskhod"}, pagination:{...}) }
→ totalCount=1, processHash lowercase, actionCount=3, deltaCount=4

Redis cache: ключ `process::voskhod::<hash>`, TTL=60s ✓
Auth: без JWT → 401 Unauthorized ✓

pnpm test — 67/67 passed (все unit-тесты по-прежнему зелёные).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 13:30:34 +00:00
coopops 4b3e24fd86 [989-1][@ant] feat: мигрировать legacy-ledger параллельно в оба контура ledger2 (wallets + accounts) — иначе после переключения мы теряем состояние бухбаланса 51/80/861 и другие счета на миллионы RUB, а новые apply-вызовы стартуют поверх пустой бухгалтерии
— migrate.cpp: для каждой ненулевой laccount сумма total=available+blocked кладётся в ledger2::accounts[legacy_id*1000] в правильное плечо оборотов (ACTIVE/A-P → debit_balance, PASSIVE → credit_balance); при наличии целевого фонда параллельно заполняется wallets (SHARE_FUND=2, ENTRANCE_FEES=3, LONG_TERM_LOANS=6)
— маппинг legacy→ledger2 задокументирован в PRD §4.1.5 таблицей (FR-L-13) + issue 989-1: 51→51000(A,Dr), 80→80000(P,Cr)+wallet2, 861→861000(P,Cr)+wallet3, 67→67000(P,Cr)+wallet6
— зафиксирована follow-up миграция (Story 1.11 backlog): вычленение минимальных паевых взносов из wallets[SHARE_FUND=2] в wallets[MIN_SHARE_FUND=1] по количеству пайщиков × размер обязательного пая; accounts не трогается (проводка Dr51/Cr80 одна и та же)
— интеграционный тест расширен с 8 до 9 AC: AC5/AC6 теперь проверяют что BANK_ACCOUNT и MEMBER_DEBT мигрируют в accounts (Dr), но не создают кошельков; AC7 отдельно проверяет credit_balance для 80000/861000/67000
— legacy одноконтурный, поэтому Σ Dr ≠ Σ Cr после миграции — это ожидаемо и задокументировано в миграции
2026-04-23 13:30:33 +00:00
coopops 83135df044 [989-1][@ant] refactor: завершить epic-1 ledger2 — починить boot-тесты, исправить маппинг legacy→ledger2 id в migrate и убрать тавтологичный validateJournalInvariant как оверинжиниринг
— починка интеграционных тестов capital.test.ts после переключения wallet/capital на Ledger2::apply: helper-ы walletUtils.ts теперь читают ledger2::accounts[80000], available синтезируется из (credit-debit) для PASSIVE-счетов; circulationAccountId=80_000
— migrate.cpp получил маппер legacy_to_wallet_id (80→2 SHARE_FUND, 861→3 ENTRANCE_FEES, 67→6 LONG_TERM_LOANS); writeoff + нулевые + не-фондовые счета (51, 751) пропускаются; идемпотентность через meta
— новый integration-test ledger2-migrate.test.ts (8 AC: seed legacy → migrate → маппинг → идемпотентность)
— удалён application/ledger2/ модуль: validateJournalInvariant был тавтологией (totalDebit += amount; totalCredit += amount — разница всегда 0); инвариант Σ Dr = Σ Cr гарантирован контрактом, backend-проверка не добавляет гарантий
2026-04-23 13:30:33 +00:00
coopops e8859f943e fix boot 2026-04-23 13:30:33 +00:00
coopops 768ce8ec82 fix boot 2026-04-23 13:30:33 +00:00
coopops 6dd8f7724a make docker containers runnable 2026-04-23 13:30:33 +00:00
coopops 8d037a9dbb feat(boot): параметризация инстанса через .env для параллельного запуска
Все mono-ai-N теперь могут работать одновременно на изолированной
инфраструктуре. Имена контейнеров автогенерируются compose-проектом
(префикс из .env), хост-порты и URL берутся из .env.

- docker-compose.yaml: убраны статические container_name, host-порты
  через ${VAR:-default} для обратной совместимости
- boot scripts (reboot/clean_reboot/extra_reboot/clear): source корневого
  .env и docker exec → docker compose exec -T (через service name)
- networks.sh, preactivate.sh: cleos/curl используют ${CHAIN_URL:-...}
- boot health.ts, configs/index.ts, configs/networks.ts: читают
  process.env.CHAIN_URL вместо hardcoded localhost:8888
- configs/contracts.ts: добавлен ledger2
- init/infra.ts: addUser получил недостающий registration_hash

В каждой папке mono-ai-N нужен локальный .env (в .gitignore) с
INSTANCE_INDEX, COMPOSE_PROJECT_NAME, host-портами и
CHAIN_URL/API_URL/MONGODB_URL. Без .env compose поднимется на дефолтных
портах (как у mono-ai-1).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 08:24:30 +00:00
Alex Ant fe6c9f3e53 chore(release): publish 2026-04-22 11:30:46 +05:00
Alex Ant 921d0a5163 chore(release): publish 2026-04-22 11:00:58 +05:00
Alex Ant 8ff7fe12dd chore(release): publish 2026-04-20 00:10:40 +05:00
Alex Ant 739c5fdbdb chore(release): publish 2026-04-20 00:09:52 +05:00
Alex Ant 7cd8418ad1 chore(release): publish 2026-04-19 23:50:54 +05:00
Alex Ant 9f8228c5b0 chore(release): publish 2026-04-16 00:07:24 +05:00
Alex Ant fdc4cdc3c1 chore(release): publish 2026-04-16 00:06:22 +05:00
Alex Ant 9d6273182a chore(release): publish 2026-04-14 21:22:31 +05:00
Alex Ant 2474c24533 chore(release): publish 2026-04-14 21:21:27 +05:00
Alex Ant cff531fb28 chore(release): publish 2026-04-14 16:11:37 +05:00
Alex Ant 0a31890da9 chore(release): publish 2026-04-14 13:17:46 +05:00
Alex Ant 0c863c3176 chore(release): publish 2026-04-13 23:13:47 +05:00
Alex Ant 7dadb4cb88 fix: капитализация -> благорост 2026-04-13 23:12:32 +05:00
Alex Ant 0c57fe4f61 chore(release): publish 2026-04-13 22:25:45 +05:00