Стенд 5 — руководство ведущего (DID/VC)

Как поднять стенд, что показывать на каждой станции по методичке «Цифровое взаимодействие организаций и агент с ограниченным мандатом», где обмен с BIMAR и что на стенде смоделировано.

1. Запуск

make build # bin/did, bin/vc, bin/didsign, bin/agentmanifest, bin/agentmcp cp docs/stand5/custody.example.json custody.json # заменить seed и token у трёх организаций export IDENTITY_SYSTEM_KEY=$(bin/didsign keygen | sed -n 's/^seed: //p') DID_OPERATION_PROOF=required VC_PROOF=required DID_ANCHOR=log \ docker compose -f docker-compose.yml -f docs/stand5/docker-compose.stand5.yml up -d --build node scripts/stand5-flow.mjs http://localhost:8081 custody.json # проверка: сквозной прогон, 10 проверок

custody.json — учебные организации, ключи которых хранит платформа: изготовитель, сертифицирующая организация, покупатель. vc-svc сам регистрирует их DID и карточки при старте (в логе — custody organization ready). Токен организации выдаётся рабочему месту станции и BIMAR этой станции. Тот же seed — тот же DID: файл не менять между прогонами, иначе это другие организации.

Что

Адрес

Портал станций

/portal (#vzlet, #register, #oiltim — сразу нужная станция)

Скан метки

/scan, /s/<DID> (из QR)

Печатный паспорт

/p/<DID> — прибор или блок, «🖨 Печать / PDF»

Консоль сценариев

/console (ключи в браузере, без токенов)

API

/swagger (VC), :8080/swagger (DID)

На каждом рабочем месте: /portal#<станция> → «Станция стенда — ключ у платформы» → токен станции. Вкладку можно переподключить ключом в браузере («сменить») — для показа подписи в браузере; это будет другая организация.

2. Станции и шаги методички

Станция 1 — изготовитель (раздел 8)

Шаг методички

В портале

1–2. Экземпляры и паспорта

«📐 Типы приборов» → тип модели: строки характеристик, единицы, обязательность. «📟 Приборы» → «+ Новый прибор» → паспорт: тип подставит модель и характеристики; обязательные реестр проверит (missing_characteristic)

3. Метки

«🏷 Метка» → QR, PNG, печать. QR ведёт на /s/<DID>

4. Публикация

паспорт подписан и в реестре; повторное чтение — «🔍» (скан) или «🖨»

5. Сертификата ещё нет

скан: ⚠️ «паспорт ещё не связан с сертификатом»; после выдачи сертификата на станции 2 — «🔗 Связать с сертификатом» (новая версия паспорта, прежняя отзывается)

6. Обратная видимость

станция 2: «📜 Сертификаты» → «Кого касается» — два конкретных экземпляра

7. Передача

«🤝 Передать» → получатель становится контроллером: может оформить акт, но владельцем ещё не стал

8–9. Результат контроля

«📥 Сообщения покупателей»: решение, причина, чек-лист, ссылка на фото (файл — у покупателя)

10. Второй экземпляр

его собственные метка и паспорт; принят — уходит из «Приборов» изготовителя, но сообщения по нему остаются

Сертификат выдаётся только в области: если в сертификате перечислены модели, паспорт другой модели на него не сошлётся (out_of_scope). Сам себе изготовитель сертификат не выдаст (self_certification).

Станция 2 — сертифицирующая организация и агент (раздел 9)

Сертификат: «📜 Сертификаты» → «+ Выдать сертификат» (модели в области, НД, схема, протокол), «Кого касается» (приборы, владельцы, блоки), «Отозвать».

Агент: «🤖 Агент» → «Зарегистрировать агента». Ключ агента — в браузере, DID did:ru:agent:… из ключа, владелец — организация; она подписывает мандат: какие документы агент вправе выпускать (карточка сертификата, заключение), маршруты API, закреплённая конфигурация запуска (модель, seed, AGENTS.md) и что только предупреждает (по умолчанию model.temperature).

Деловой опыт. Агент готовит по исходнику карточку сертификата (CertificateCardCredential) — это не сертификат. Нечитаемое на скане (год окончания срока, коды ОКПД2/ТН ВЭД) агент перечисляет в «не найдено в исходнике». Человек открывает карточку → «✍️ Проверить и подписать сертификат» — сертификат со ссылкой basedOn. Затем «Кого касается» — паспорта в области.

Защитный опыт.

Условие

Реакция платформы

Повторное чтение

штатный запуск

запись разрешена

карточек +1

temperature 0.2 → 0.7 (рекомендательный)

⚠️ записано с предупреждением model.temperature: 0.2 → 0.7

карточек +1

seed 42 → 7 (закреплён)

⛔ runtime_not_approved: model.seed: 42 → 7

карточек без изменений

выпуск сертификата агентом

⛔ type_not_allowed

—

отзыв сертификата агентом

⛔ отзывает только издатель

статус сертификата «active»

В портале это кнопки «🎛 Моделируемый запуск» (те же вызовы платформы, без модели). Настоящий агент — MCP-сервер:

bin/agentmcp init -vc http://localhost:8081 -token <токен станции 2> -dir ./agent # DID агента + мандат bin/agentmcp -config ./agent/agent.json # подключить в MCP-клиент модели bin/agentmcp -config ./agent/agent.json call mandate # без модели: любой инструмент

Инструменты: mandate, list_source_documents, read_source_document, find_organization, prepare_certificate_card, list_certificates, find_certificate_passports, issue_certificate и revoke_certificate (оба — для защитного опыта: платформа откажет). Рабочий каталог agent/workspace: AGENTS.md, навык, исходник certificate-N00020-24.md (расшифровка присланного скана). Защитный опыт — правка model.seed в agent.json: агент сам отчитается о запуске перед записью, vc-svc откажет. Восстановление — вернуть значение (или подписать новый мандат). Правка AGENTS.md тоже меняет запуск: дайджест входит в мандат.

Поручение для модели: «По документу certificate-N00020-24.md подготовь карточку сертификата. Покажи заполненные поля и неизвестные значения. После моего подтверждения запиши карточку и покажи её идентификатор. Затем покажи приборы и паспорта, относящиеся к сертификату».

Станция 3 — покупатель и комплектатор (раздел 10)

Шаг методички

В портале

1–3. Поступление, скан

«🤝 Передачи и входной контроль» → «🔍 Скан»; сканирование открывает карточку и ничего не записывает

4–7. Три проверки

«📋 Входной контроль»: соответствие заказу, сертификат (подставлен из скана), физический осмотр, чек-лист, фото (ссылка, SHA-256 по файлу) — каждое основание отдельным полем

8–12. Дефект

решение «не принят» + причина → акт подписан и сразу виден изготовителю; «↩ Отказаться» — прибор остаётся за изготовителем

14–15. Второй прибор

акт «принят» → «✍️ Принять» (своей подписью — владелец)

16–18. Паспорт блока

«🧱 Блоки» → «+ Новый блок» → позиции: прибор, «установлен» / «проектная позиция». Установленным реестр примет только прибор, который покупатель принял по акту (not_accepted). Скан блока: позиция → прибор → паспорт → сертификат → акт

Скан прибора показывает акты входного контроля и блоки, куда он входит; при последнем акте «не принят» — ⚠️.

3. Обмен с BIMAR (токены организаций)

BIMAR работает от имени станции её токеном; платформа подписывает ключом организации. Все правила те же, что для подписанных запросов. Пример — scripts/stand5-flow.mjs (весь сценарий двумя приборами).

Действие

Запрос

Кто я

GET /api/v1/custody/me

Прибор (+ карточка BIMAR)

POST /api/v1/custody/devices {"service":[{"id":"#bimar","type":"BimarCard","serviceEndpoint":"https://…"}]}

Ссылка на карточку BIMAR позже

PUT /api/v1/custody/dids/{did}/services {"id":"#bimar","type":"BimarCard","serviceEndpoint":"…"}

Любой документ

POST /api/v1/custody/credentials {"type":["IncomeInspectionCredential"],"credentialSubject":{…}}

Паспорт с маркером BIMAR

InstrumentPassportCredential: externalId (siId BIMAR), marker (номер наклейки), documents[] {type,title,url,sha256}

Пул маркеров организации

MarkerPoolCredential {"id": <DID организации>, "family1", "family2", "from", "to", "issuedBy": "BIMAR"} — выпускает сама организация; пулы разных организаций не пересекаются; пока у организации есть пул, новый маркер прибора должен лежать в нём

Прибор по маркеру

GET /api/v1/credentials/search?type=InstrumentPassportCredential&status=active&claim=marker:<маркер> → credentialSubject.id — DID

Отзыв своего документа

POST /api/v1/custody/credentials/{id}/revoke

Передача / приёмка / отказ

POST /api/v1/custody/dids/{did}/transfer {"to":"did:ru:org:…"}, …/accept, …/decline

Чтение

GET /api/v1/scan?did=… (паспорт, сертификат, акты, блоки), GET /api/v1/credentials?subject=…, GET /api/v1/credentials/events?after=… (лента для синхронизации), GET /api/v1/schemas (поля)

Состав полей: GET /api/v1/schemas/{тип} — JSON Schema. Ошибка — code и field: missing_characteristic, out_of_scope, not_accepted, passport_exists (паспорт надо заменять: replaces), not_subject_authority, marker_taken (маркер уже на действующем паспорте другого прибора), marker_not_in_pool (маркер в чужом пуле или вне своих пулов), pool_overlap (пул пересекается с пулом другой организации).

Соответствие вопросам BIMAR к SCADA DEMO API:

SCADA DEMO API

Здесь

POST /si (Manufacturer)

POST /custody/devices + паспорт (InstrumentPassportCredential)

GET /si/{id}/passport

GET /scan?did= или печатный /p/<DID>

/si/checkups IncomeCheck (Laboratory)

акт IncomeInspectionCredential — подписывает получатель (контроллер во время передачи), не лаборатория; причина — reason, срока нет

PATCH ownerId

transfer → accept (только подписью получателя) или decline

/si/moves Installation

позиция installed в BlockPassportCredential

история по прибору

GET /scan?did= (акты, паспорта, блоки), /p/<DID> (формуляр)

4. Повторные круги

Данные не удаляются. Каждая группа заводит свои приборы и блок — у них новые DID, круги не мешают друг другу; общий сертификат и организации — те же. Сертификат на время положительной ветви другой группы не отзывать (или выдать группе свой). Сброс базы (POST /api/debug/reset-db, только с DEBUG=TRUE) стирает всё у всех.

5. Что смоделировано

  • Подпись — Ed25519 ключом организации (в браузере или у платформы по токену), не УКЭП. Название организации — самозаявленное, до подтверждения по сертификату ключа ЮЛ.

  • Реестр: ревизии DID «якорятся» в журнал (DID_ANCHOR=log), не в HLF; статусы VC — в базе vc-svc.

  • Агент в портале — моделируемый запуск (те же вызовы платформы, без модели); настоящий — agentmcp с моделью ведущего. Конфигурацию запуска агент сообщает сам: подпись отчёта доказывает, кто сообщил, а не что именно исполнялось.

  • Фото не загружаются в платформу: ссылка и SHA-256.

  • Расчёт после приёмки, метрологический учёт и нормативная проверка блока — вне стенда.

Журнал изменений

Дата

Перечень изменений

Автор

2026-11-05

Перенесён из архива DID-VC-итоги-2026-11-03 без изменения содержания.

Дис