Перейти к содержанию

Фабрика документов

Электронные документы в кооперативе — это юридически-значимые действия. Для них важны одинаковая форма, повторяемость и проверяемость. Фабрика автоматизирует процесс и делает его повторяемым: каждый документ создаётся по одному маршруту, на основе шаблона, версии шаблона и исходных данных, которые можно перепроверить. Это защищает от расхождений между версиями, гарантирует, что контрольная сумма и подпись относятся к тому же содержимому, и самое главное - позволяет автоматизировать работу документами в стандартизированных бизнес-процессах кооператива.

Электронный документ

Электронный документ — файл, который содержит юридически-значимое действие пайщика. Он создан по общему кооперативному стандарту, может быть подписан и передан.

Электронный документ в кооперативной экономике может находится в двух математически-связанных между собой состояниями: полная форма и подписанная форма.

Полная форма документа включает в себя "сырые" данные, доступные для отображения или скачивания в виде PDF-файла. Это тот вид документа, который мы привыкли видеть, и который содержит все данные, которые в нем должны быть - все заполненные поля, доступные для чтения, и т.д..

Интерфейс данных полного документа:

⚠️ Интерфейс GeneratedDocument не найден в typedoc_data

Подписанная форма документа включает в себя контрольную сумму полной формы, следовательно, они математически-взаимосвязаны - из полной формы всегда можно получить контрольную сумму подписанной формы и произвести сверку. В подписанной форме всегда есть контрольная сумма полного документа и мета-данные, которых достаточно для того, чтобы установить того, кто сгенерировал документ, и того, кто его подписал, и сделать это математически-точно и без публичного раскрытия персональных данных.

Интерфейс данных подписанного документа:

⚠️ Интерфейс SignedBlockchainDocument не найден в typedoc_data

Обратное же, т.е. получить полную форму из подписанной может только тот, у кого есть доступ к закрытой информации в базе данных кооператива - обычно это или пайщик, кому принадлежит документ, или член совета.

Для передачи подписей в документах используется следующий интерфейс:

⚠️ Интерфейс SignatureInfoInput не найден в typedoc_data

Он позволяет накладывать на документ и поверх предыдущих подписей неограниченное количество новых подписей. Обычно, нам в наших бизнес-процессах не требуется больше двух подписей на одном документе (например, на акте приёма-передачи требуется две подписи). Но для исключительных случаев мы не ограничены в количестве подписей на одном документе.

Проверка подписей осуществляется на уровне смарт-контрактов блокчейна, требуя наличия подписи от конкретного аккаунта-участника бизнес-действия. Кроме этого, проверку подписей документов осуществляет бэкенд программного комплекса цифрового кооператива каждый раз при запросе документов пайщиком или членом совета.

Подпись документа

Как мы ранее могли обратить внимание, внизу каждого электронного документа на платформе есть блок подписи, давайте взглянем на него еще раз:

подпись документа

Мы видим контрольную сумму документа, а также блок с указанием количества подписей, где каждая подпись указывает на сертификат подписанта. Сертификаты выдаются пайщикам при регистрации и хранятся в базе данных кооператива. Мы извлекли сертификат пайщика на основании имени аккаунта подписанта, которое мы безопасно хранили в блокчейне.

Далее мы видим цифровую подпись. Как мы ранее говорили, она накладывается на контрольную сумму документа с помощью приватного ключа пайщика. А поскольку мы обладаем именем аккаунта пайщика, то мы всегда можем извлечь публичный ключ и произвести математическую сверку корректности подписи и ее принадлежности к указанному аккаунту. Что мы и делаем, когда показываем идентификатор статуса подписи - "Верифицирована".

Глубокая сверка

При необходимости из базы данных кооператива могут быть извлечены исходные данные, которые использовались для генерации полного документа, и использованы для того, чтобы на основании публичных мета-данных произвести глубокую сверку.

При глубокой сверке фабрика документов произведет полную регенерацию документа из исходных данных, заполнив ими шаблон электронного документа заново, и если все в порядке - то получит тот же самый результат в виде полностью идентичной контрольной суммы документа, который и был подписан. Глубокую сверку документов рекомендуется производить у всех документов пайщиков до принятия решений по ним.

Фабрика документов

Итак, что же такое фабрика документов?

Фабрика документов - это архитектурный паттерн, который позволяет производить одинаковым образом разные документы за счет использования шаблонов и общих стандартов генерации.

Фабрика предоставляет конвейеры по производству электронных документов, которые работают в целом одинаково: извлекают шаблон документа из блокчейна, подставляют данные пайщиков, формируют полный документ и возвращает его пайщику. Т.е. фабрика отвечает за генерацию и глубокую сверку документов, а также за резервное хранение полных документов и сертификатов пайщиков с их личными данными с полной историей изменений, на основании которых эти полные документы генерировались.

Таким образом, фабрика способна в любой момент предоставить или полный документ или произвести глубокую сверку документа на основании своих исторических данных.

Мы не будем в данном разделе подробно останавливаться на принципах генерации документов из шаблов, т.к. это продукт стандартов кооперативной экономики и данный материал будет описан на соответствующих страницах сайта https://coopenomics.world.

Реестр шаблонов

id Название SDK GraphQL
1 Согласие с условиями ЦПП «ЦИФРОВОЙ КОШЕЛЕК» ⚠️ 🛠️ SDK: Mutations.Agreements.GenerateWalletAgreement не найден Mutation.generateWalletAgreement
2 Согласие с условиями положения о простой электронной подписи ⚠️ 🛠️ SDK: Mutations.Agreements.GenerateSignatureAgreement не найден Mutation.generateSignatureAgreement
3 Согласие с условиями политики обработки конфиденциальных данных ⚠️ 🛠️ SDK: Mutations.Agreements.GeneratePrivacyAgreement не найден Mutation.generatePrivacyAgreement
4 Согласие с условиями пользовательского соглашения ⚠️ 🛠️ SDK: Mutations.Agreements.GenerateUserAgreement не найден Mutation.generateUserAgreement
50 Пользовательское соглашение (оферта) о присоединении к платформе "Кооперативная Экономика"
51 Заявление о конвертации паевого взноса в членский взнос ⚠️ 🛠️ SDK: Mutations.Provider.GenerateConvertToAxonStatement не найден Mutation.generateConvertToAxonStatement
100 Заявление на вступление в кооператив ⚠️ 🛠️ SDK: Mutations.Participants.GenerateParticipantApplication не найден Mutation.generateParticipantApplication
101 Заявление пайщика о выборе кооперативного участка ⚠️ 🛠️ SDK: Mutations.Branches.GenerateSelectBranchDocument не найден Mutation.generateSelectBranchDocument
300 Предложение повестки дня общего собрания ⚠️ 🛠️ SDK: Mutations.Meet.GenerateAnnualGeneralMeetAgendaDocument не найден Mutation.generateAnnualGeneralMeetAgendaDocument
301 Решение совета о созыве общего собрания ⚠️ 🛠️ SDK: Mutations.Meet.GenerateSovietDecisionOnAnnualMeetDocument не найден Mutation.generateSovietDecisionOnAnnualMeetDocument
302 Уведомление о проведении общего собрания ⚠️ 🛠️ SDK: Mutations.Meet.GenerateAnnualGeneralMeetNotificationDocument не найден Mutation.generateAnnualGeneralMeetNotificationDocument
303 Заявление с бюллетенем для голосования на общем собрании ⚠️ 🛠️ SDK: Mutations.Meet.GenerateBallotForAnnualGeneralMeetDocument не найден Mutation.generateBallotForAnnualGeneralMeetDocument
304 Протокол решения общего собрания ⚠️ 🛠️ SDK: Mutations.Meet.GenerateAnnualGeneralMeetDecisionDocument не найден Mutation.generateAnnualGeneralMeetDecisionDocument
501 Решение совета о приёме пайщика в кооператив ⚠️ 🛠️ SDK: Mutations.Participants.GenerateParticipantApplicationDecision не найден Mutation.generateParticipantApplicationDecision
599 Предложение повестки дня собрания совета ⚠️ 🛠️ SDK: Mutations.FreeDecisions.GenerateProjectOfFreeDecision не найден Mutation.generateProjectOfFreeDecision
600 Протокола решения совета ⚠️ 🛠️ SDK: Mutations.FreeDecisions.GenerateFreeDecision не найден Mutation.generateFreeDecision
699 Согласие с условиями ЦПП «СОСЕДИ»
700 Заявление на паевый взнос имуществом ⚠️ 🛠️ SDK: Mutations.Cooplace.GenerateAssetContributionStatement не найден Mutation.generateAssetContributionStatement
701 Протокол решения совета о форме и стоимости имущества ⚠️ 🛠️ SDK: Mutations.Cooplace.GenerateAssetContributionDecision не найден Mutation.generateAssetContributionDecision
702 Акт приёма-передачи имущества ⚠️ 🛠️ SDK: Mutations.Cooplace.GenerateAssetContributionAct не найден Mutation.generateAssetContributionAct
800 Заявление на возврат паевого взноса имуществом ⚠️ 🛠️ SDK: Mutations.Cooplace.GenerateReturnByAssetStatement не найден Mutation.generateReturnByAssetStatement
801 Протокол решения совета о возврате паевого взноса имуществом по соглашению новации ⚠️ 🛠️ SDK: Mutations.Cooplace.GenerateReturnByAssetDecision не найден Mutation.generateReturnByAssetDecision
802 Акт приёмки-передачи имущества ⚠️ 🛠️ SDK: Mutations.Cooplace.GenerateReturnByAssetAct не найден Mutation.generateReturnByAssetAct
900 Заявление на возврат паевого взноса денежными средствами ⚠️ 🛠️ SDK: Mutations.Wallet.GenerateReturnByMoneyStatementDocument не найден Mutation.generateReturnByMoneyStatementDocument
901 Решение совета о возврате паевого взноса ⚠️ 🛠️ SDK: Mutations.Wallet.GenerateReturnByMoneyDecisionDocument не найден Mutation.generateReturnByMoneyDecisionDocument
1000 Оферта по благороста ⚠️ 🛠️ SDK: Mutations.Capital.GenerateCapitalizationAgreement не найден Mutation.capitalGenerateCapitalizationAgreement
1001 Договор участия в хозяйственной деятельности ⚠️ 🛠️ SDK: Mutations.Capital.GenerateGenerationContract не найден Mutation.capitalGenerateGenerationContract
1002 Приложение к договору участия ⚠️ 🛠️ SDK: Mutations.Capital.GenerateProjectGenerationContract не найден Mutation.capitalGenerateProjectGenerationContract
1010 Заявление о расходах ⚠️ 🛠️ SDK: Mutations.Capital.GenerateExpenseStatement не найден Mutation.capitalGenerateExpenseStatement
1011 Решение совета о расходах ⚠️ 🛠️ SDK: Mutations.Capital.GenerateExpenseDecision не найден Mutation.capitalGenerateExpenseDecision
1020 Заявление об инвестировании денежных средств в генерацию ⚠️ 🛠️ SDK: Mutations.Capital.GenerateGenerationMoneyInvestStatement не найден Mutation.capitalGenerateGenerationMoneyInvestStatement
1025 Заявление о возврате неиспользованных средств генерации ⚠️ 🛠️ SDK: Mutations.Capital.GenerateGenerationMoneyReturnUnusedStatement не найден Mutation.capitalGenerateGenerationMoneyReturnUnusedStatement
1030 Заявление об инвестировании средств в благорост ⚠️ 🛠️ SDK: Mutations.Capital.GenerateCapitalizationMoneyInvestStatement не найден Mutation.capitalGenerateCapitalizationMoneyInvestStatement
1040 Заявление на внесение результата интеллектуальной деятельности ⚠️ 🛠️ SDK: Mutations.Capital.GenerateResultContributionStatement не найден Mutation.capitalGenerateResultContributionStatement
1041 Решение совета об инвестициях по результатам ⚠️ 🛠️ SDK: Mutations.Capital.GenerateResultContributionDecision не найден Mutation.capitalGenerateResultContributionDecision
1042 Акт приема-передачи результата интеллектуальной деятельности ⚠️ 🛠️ SDK: Mutations.Capital.GenerateResultContributionAct не найден Mutation.capitalGenerateResultContributionAct
1050 Заявление на получение займа ⚠️ 🛠️ SDK: Mutations.Capital.GenerateGetLoanStatement не найден Mutation.capitalGenerateGetLoanStatement
1051 Решение совета о предоставлении займа ⚠️ 🛠️ SDK: Mutations.Capital.GenerateGetLoanDecision не найден Mutation.capitalGenerateGetLoanDecision
1060 Заявление об инвестировании имущества в генерацию ⚠️ 🛠️ SDK: Mutations.Capital.GenerateGenerationPropertyInvestStatement не найден Mutation.capitalGenerateGenerationPropertyInvestStatement
1061 Решение совета об инвестировании имущества в генерацию ⚠️ 🛠️ SDK: Mutations.Capital.GenerateGenerationPropertyInvestDecision не найден Mutation.capitalGenerateGenerationPropertyInvestDecision
1062 Акт приема-передачи имущества в генерацию ⚠️ 🛠️ SDK: Mutations.Capital.GenerateGenerationPropertyInvestAct не найден Mutation.capitalGenerateGenerationPropertyInvestAct
1070 Заявление об инвестировании имущества в благорост ⚠️ 🛠️ SDK: Mutations.Capital.GenerateCapitalizationPropertyInvestStatement не найден Mutation.capitalGenerateCapitalizationPropertyInvestStatement
1071 Решение совета об инвестировании имущества в благорост ⚠️ 🛠️ SDK: Mutations.Capital.GenerateCapitalizationPropertyInvestDecision не найден Mutation.capitalGenerateCapitalizationPropertyInvestDecision
1072 Акт приема-передачи имущества в благорост ⚠️ 🛠️ SDK: Mutations.Capital.GenerateCapitalizationPropertyInvestAct не найден Mutation.capitalGenerateCapitalizationPropertyInvestAct
1080 Заявление о конвертации средств генерации в основной кошелек ⚠️ 🛠️ SDK: Mutations.Capital.GenerateGenerationToMainWalletConvertStatement не найден Mutation.capitalGenerateGenerationToMainWalletConvertStatement
1081 Заявление о конвертации средств генерации в проект ⚠️ 🛠️ SDK: Mutations.Capital.GenerateGenerationToProjectConvertStatement не найден Mutation.capitalGenerateGenerationToProjectConvertStatement
1082 Заявление о конвертации средств генерации в благорост ⚠️ 🛠️ SDK: Mutations.Capital.GenerateGenerationToCapitalizationConvertStatement не найден Mutation.capitalGenerateGenerationToCapitalizationConvertStatement
1090 Заявление о конвертации средств благороста в основной кошелек ⚠️ 🛠️ SDK: Mutations.Capital.GenerateCapitalizationToMainWalletConvertStatement не найден Mutation.capitalGenerateCapitalizationToMainWalletConvertStatement

Для разработчиков

Генерация и подпись

Для того, чтобы сгенерировать документ, необходимо передать ему набор обязательных параметров из интерфейса IInput. Обязательные параметры являются частью процесса генерации документа, а не обязательные параметры обычно являются мета-данными документа.

Т.е. в результате генерации документа будет получен объект мета-данных, который можно использовать для глубокой сверки, передав их в качестве опциональных параметров.

Пример: заявление на вступление

⚠️ 🛠️ SDK: Mutations.Participants.GenerateParticipantApplication не найден | Mutation.generateParticipantApplication

⚠️ Описание для Mutations.Participants.GenerateParticipantApplication не найдено

⚠️ Mutations.Participants.GenerateParticipantApplication не найден

Результат:

⚠️ Mutations.Participants.GenerateParticipantApplication не найден

Используем полученный документ в result для создания подписи:

import { Mutations, Classes } from '@coopenomics/sdk'

// 2. Подписываем документ с помощью SDK-класса Document
const signer = new Classes.Document('WIF_PRIVATE_KEY')
const signed = await signer.signDocument(document, 'user1', 1) //1 - это порядковый номер подписи

Тип подписанного документа

⚠️ Описание для SignedBlockchainDocument не найдено

Результат (тип signed):

⚠️ Интерфейс SignedBlockchainDocument не найден в typedoc_data

Полученный signed документ может быть использован для отправки в мутацией согласно бизнес-процессам, которые мы далее рассматриваем по документации.

Важно

Приватный ключ (WIF) должен соответствовать имени пользователя (username), иначе процесс валидации подписи не будет завершен с успехом.

Мультиподпись

Когда необходимо создать дополнительную подпись на документе, то мы это делаем на основе подписанного документа, который уже опубликован в блокчейне. Мы берем его, и создаем еще одну подпись, накладывая её поверх ранее подписанного другим пайщиком документа, указывая порядковый номер подписи следующим.

const signed = await signer.signDocument(document, 'user2', 2)