Настоящие мобильные callbacks: прочитать свой счет и подтвердить удаление

Учебные задачи

Создайте новый собственный пакет реальным Promise PutAsync, затем изучите передачу4 параметров чтения и2 параметров удаления через настоящие ОписаниеОповещения.

Где и как запускать

Собственный новый Android ARM64 developer mobile-platform app; только МобильноеПриложениеКлиент и локальный МобильноеПриложениеСервер для scalar guard. Ни desktop, ни mobile-client fallback; действительная версия показана отдельно.

Подготовка

  1. Будущий ручной опыт — только собственная новая изолированная лаборатория: отдельное Android ARM64 устройство, не личный телефон, и своя новая Windows-VM с подготовленным IIS. Здесь устройство, CF, публикация, установка и хранилище не запускались. Изучение кода само ничего не записывает.

  2. Создайте с нуля собственную конфигурацию УчебныйСейф85 без прикладных данных. Версия конфигурации ровно 58dd39ee-7b27-40aa-9bcb-552ea90cf15c; режим совместимости Не использовать; назначение использования Приложение для мобильной платформы. Метка — учебная идентификация пакета, не криптографическое доказательство и не UUID ИБ/пользователя.

  3. Общие → Общие формы: создайте ровно три управляемые формы ГлавнаяСейфа85, ПультСейфаАсинх85, ПультСейфаОповещения85. У главной формы создайте команды ОткрытьАсинх85 и ОткрытьОповещения85 с одноименными обработчиками; выведите две кнопки этих команд. Вставьте приведенный полный модуль главной формы. Поместите ГлавнаяСейфа85 в рабочую область начальной страницы конфигурации; это навигация, не автоматический запуск опыта.

  4. У каждой формы пульта создайте реквизиты СогласенНаОпыт85 (Булево, исходно Ложь), ВерсияRuntime85/Состояние85/История85 (Строка неограниченной длины), Сумма85 (Число15,2). Выведите флажок согласия и поля наблюдения; поля наблюдения ТолькоПросмотр=Да. Создайте ровно свою команду ПройтиОпыт85, обработчик ПройтиОпыт85(Команда), кнопку этой команды. В свойствах события формы ПриОткрытии назначьте ПриОткрытии(Отказ); не вызывайте обработчики сами.

  5. Полный MAIN модуль вставьте только в форму, названную в расположении соответствующей карточки. Другой пульт имеет другой полный MAIN модуль и отдельные внутренние переменные/согласие/ключ. Поддерживающий модуль ГлавнаяСейфа85 одинаков для двух карточек. Серверный helper находится внутри каждой формы, &НаСервереБезКонтекста: только МобильноеПриложениеСервер, возвращает Булево, opaque менеджер/данные/nonce через RPC не передаются.

  6. Проверка конфигурации: Мобильное приложение — клиент и Мобильное приложение — сервер, целостность, ссылки и неподдерживаемые функции. При ошибках STOP. Путь поставки: Конфигурация → Мобильное приложение → Публиковать…; только собственный новый виртуальный каталог OwnSafePackets85_<ownGUID> и собственная папка своей VM/IIS, без автоматического обновления. Публикация создает каталог/мобильную конфигурацию и может предложить обновление только своей новой ИБ; не подключайте рабочую базу. Это не сборщик APK/IPA.

  7. Для собственного Android ARM64 вручную используйте официальный пакет мобильной платформы разработчика 1cem-arm64.apk из своего фактически полученного мобильного дистрибутива. Не 1cem-client-arm64.apk и не 1cem-standalone-arm64.apk: это другие среды. Наличие Windows8.5.1.1343 не доказывает доступность/установку мобильного бинарного runtime8.5.1.1343. Здесь ничего не скачано и не установлено; неподходящий фактический пакет — STOP.

  8. После самостоятельной установки developer-платформы в пустом списке приложений нажмите +, в Address задайте реальный URL своей private VM и точное имя своей публикации, нажмите Load, задайте имя УчебныйСейф85 и завершите создание (OK/Done), затем откройте свое приложение из списка. Не localhost телефона, не file://, не выдуманный готовый URL. Android должен видеть только свою VM в лабораторной локальной сети; публичный сервер/рабочая ИБ не нужны. Не включайте auto-restart, auto-update или debugging ради этого опыта. Данные desktop-ИБ не считаются перенесенными: счет создается самим кодом на устройстве.

  9. Официальная инструкция поставки: https://1c-dn.com/library/publishing_of_1c_mobile_application/ ; вариант ARM64 и добавление приложения: https://1c-dn.com/library/tutorials/1c_enterprise_development_tools_user_guide/ ; собственная локальная мобильная ИБ и проверка конфигурации: https://1c-dn.com/library/tutorials/first_application_mobile_platform/ . Это документированный будущий путь, не подтверждение текущей установки.

  10. На своем лабораторном устройстве заранее настройте блокировку экрана; PIN/пароль не выводите и не задавайте пароль по умолчанию. Native capability ScreenUnlockRequired проверяется до каждого этапа, False означает STOP без понижения до Нет. Четвертый обязательный аргумент PutAsync — СпособДополнительнойПроверкиПользователя.БиометрическаяИлиВводПароля; в выбранном режиме он игнорируется, это не обещание биометрического успеха.

  11. Откройте только выбранный пульт. Поле ВерсияRuntime85 показывает реальную версию мобильного приложения; код требует формат8.x.x.x и минимум8.3.18 для Promise API, но это не runtime-тест конкретного устройства. Другой контекст, изменившаяся версия, ошибка API/guard/capability — STOP. Никакого запуска в desktop или замены безопасного хранилища массивом.

  12. До нажатия прочитайте весь lifecycle. Каждая форма имеет отдельное согласие, изначально False; поставьте свой флажок и один раз нажмите ПройтиОпыт85. Код сразу потребляет согласие и создает один свежий UUID ключа в своей области AWAIT или CALLBACK. Записи будущего опыта: первая форма3, вторая1; каждая удаляет ровно свой1 ключ. Данные не секретные: OWN85, UUID, коды ROW-A/ROW-B и две числовые суммы. Посторонние ключи не перечисляются, не читаются и не удаляются.

  13. При отмене, ошибке, чужом результате или неожидаемом этапе форма остается STOP/неизвестно. Нет автоматического retry/rollback/delete/cleanup. Не закрывайте и не открывайте пульт заново ради уборки: внутреннее состояние формы не обещано сохраняющимся после закрытия/перезапуска приложения. Сначала вручную выясните фактический исход только собственного ключа; инструкция не дает полномочий на чужое хранилище.

&НаКлиенте
Перем СогласиеИспользовано85, Остановка85, Неизвестно85, Этап85, Токен85,
    Ключ85, Менеджер85, Способ85, ДопПроверка85, ОжидаемыйПакет85;

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Если СогласиеИспользовано85 <> Неопределено Или Остановка85 <> Неопределено Тогда
        Отказ = Истина;
        Возврат;
    КонецЕсли;
    СогласиеИспользовано85 = Ложь;
    Остановка85 = Истина;
    Неизвестно85 = Истина;
    СогласенНаОпыт85 = Ложь;
    Сумма85 = 0;
    История85 = "";
    Этап85 = "Подготовка";
    Попытка
        ВерсияRuntime85 = ПроверитьМобильнуюВерсию85();
        Остановка85 = Ложь;
        Неизвестно85 = Ложь;
        Этап85 = "Готов";
        Состояние85 = "Версия проверена. Прочитайте последствия и отдельно поставьте флажок согласия";
    Исключение
        Остановить85(ОписаниеОшибки());
        Отказ = Истина;
    КонецПопытки;
КонецПроцедуры

&НаКлиенте
Процедура Остановить85(Причина)
    Остановка85 = Истина;
    Неизвестно85 = Истина;
    СогласенНаОпыт85 = Ложь;
    Этап85 = "STOP";
    Состояние85 = "STOP. Исход неизвестен; повтор и автоматическая уборка запрещены. " + Причина;
КонецПроцедуры

&НаКлиенте
Процедура ПодготовитьОпыт85(Команда, Префикс)
    #Если МобильноеПриложениеКлиент Тогда
        Если ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда <> Команды.Найти("ПройтиОпыт85")
            Или СогласиеИспользовано85 <> Ложь Или Остановка85 <> Ложь Или Неизвестно85 <> Ложь
            Или Этап85 <> "Готов" Или СогласенНаОпыт85 <> Истина Тогда
            ВызватьИсключение "Нужна собственная команда и отдельное неиспользованное согласие; повтор запрещен";
        КонецЕсли;
        СогласиеИспользовано85 = Истина;
        СогласенНаОпыт85 = Ложь;
        Неизвестно85 = Истина;
        Этап85 = "Подготовка";
        Если Префикс <> "OWN_SAFE_PACKETS_85:AWAIT:" И Префикс <> "OWN_SAFE_PACKETS_85:CALLBACK:" Тогда
            ВызватьИсключение "Разрешены только две собственные учебные области ключей";
        КонецЕсли;
        Токен85 = Новый УникальныйИдентификатор;
        Ключ85 = Префикс + Строка(Токен85);
        Менеджер85 = БезопасноеХранилище;
        Способ85 = СпособЗащитыДоступаБезопасногоХранилища.ТребуетсяРазблокировкаЭкрана;
        ДопПроверка85 = СпособДополнительнойПроверкиПользователя.БиометрическаяИлиВводПароля;
        ПроверитьСостояние85("Подготовка");
        ПроверитьЗанятость85(Ложь);
        ОжидаемыйПакет85 = СоздатьПакет85(750, 250);
    #Иначе
        ВызватьИсключение "Нет мобильного клиентского контекста; хранилище не вызывается";
    #КонецЕсли
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьСостояние85(ОжидаемыйЭтап)
    #Если МобильноеПриложениеКлиент Тогда
        Если Остановка85 <> Ложь Или СогласиеИспользовано85 <> Истина
            Или СогласенНаОпыт85 <> Ложь Или Этап85 <> ОжидаемыйЭтап
            Или ТипЗнч(Неизвестно85) <> Тип("Булево")
            Или ТипЗнч(Токен85) <> Тип("УникальныйИдентификатор")
            Или ТипЗнч(Ключ85) <> Тип("Строка")
            Или (Ключ85 <> "OWN_SAFE_PACKETS_85:AWAIT:" + Строка(Токен85)
                И Ключ85 <> "OWN_SAFE_PACKETS_85:CALLBACK:" + Строка(Токен85))
            Или ТипЗнч(Менеджер85) <> Тип("МенеджерБезопасногоХранилища")
            Или Способ85 <> СпособЗащитыДоступаБезопасногоХранилища.ТребуетсяРазблокировкаЭкрана
            Или ДопПроверка85 <> СпособДополнительнойПроверкиПользователя.БиометрическаяИлиВводПароля
            Или ПроверитьМобильнуюВерсию85() <> ВерсияRuntime85 Тогда
            ВызватьИсключение "Изменились контекст, версия, собственный ключ или этап; STOP";
        КонецЕсли;
        Поддерживается = Менеджер85.ПоддерживаетсяЗащитаДоступа(Способ85, ДопПроверка85);
        Если ТипЗнч(Поддерживается) <> Тип("Булево") Или Поддерживается <> Истина Тогда
            ВызватьИсключение "ScreenUnlockRequired не поддержан; защита не понижается";
        КонецЕсли;
    #Иначе
        ВызватьИсключение "Запрещен вызов мобильного хранилища из иной среды";
    #КонецЕсли
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьЗанятость85(Ожидается)
    #Если МобильноеПриложениеКлиент Тогда
        Занят = Менеджер85.СодержитКлюч(Ключ85);
        Если ТипЗнч(Занят) <> Тип("Булево") Или Занят <> Ожидается Тогда
            ВызватьИсключение "Фактическая занятость собственного ключа не совпала";
        КонецЕсли;
    #Иначе
        ВызватьИсключение "Проверка ключа допустима только в мобильном приложении";
    #КонецЕсли
КонецПроцедуры

&НаКлиенте
Функция СоздатьПакет85(ПерваяСумма, ВтораяСумма)
    Если ТипЗнч(ПерваяСумма) <> Тип("Число") Или ТипЗнч(ВтораяСумма) <> Тип("Число")
        Или (ПерваяСумма <> 750 И ПерваяСумма <> 250) Или ВтораяСумма <> 250 Тогда
        ВызватьИсключение "В этом конечном учебном пакете допустимы только 750/250 или 250/250";
    КонецЕсли;
    Возврат "OWN85|" + Строка(Токен85) + "|ROW-A|" + Формат(ПерваяСумма, "ЧГ=0;ЧДЦ=0")
        + "|ROW-B|" + Формат(ВтораяСумма, "ЧГ=0;ЧДЦ=0");
КонецФункции

&НаКлиенте
Функция ПроверитьПолныйПакет85(Данные, ПерваяСумма, ВтораяСумма)
    Если Данные = Неопределено Тогда
        ВызватьИсключение "Нет подтвержденных данных: возможна отмена; STOP";
    КонецЕсли;
    Если ТипЗнч(Данные) <> Тип("Строка") Тогда
        ВызватьИсключение "Ожидалась настоящая строка собственного пакета";
    КонецЕсли;
    Если Данные <> ОжидаемыйПакет85 Или Данные <> СоздатьПакет85(ПерваяСумма, ВтораяСумма) Тогда
        ВызватьИсключение "Не совпала вся фактически прочитанная строка";
    КонецЕсли;
    Части = СтрРазделить(Данные, "|", Истина);
    Если Части.Количество() <> 6 Или Части[0] <> "OWN85"
        Или Части[1] <> Строка(Токен85) Или Части[2] <> "ROW-A" Или Части[4] <> "ROW-B" Тогда
        ВызватьИсключение "Не совпали число частей, nonce или оба кода строк";
    КонецЕсли;
    Первая = Число(Части[3]);
    Вторая = Число(Части[5]);
    Если ТипЗнч(Первая) <> Тип("Число") Или ТипЗнч(Вторая) <> Тип("Число")
        Или Первая <> ПерваяСумма Или Вторая <> ВтораяСумма Тогда
        ВызватьИсключение "Не совпали обе фактически разобранные числовые суммы";
    КонецЕсли;
    Возврат Первая + Вторая;
КонецФункции

&НаКлиенте
Процедура ПроверитьОтсутствиеОтмены85(Результат)
    Если ТипЗнч(Результат) <> Тип("Булево") Или Результат <> Ложь Тогда
        ВызватьИсключение "Отмена или неизвестный результат native операции; STOP";
    КонецЕсли;
КонецПроцедуры
&НаКлиенте
Функция ПроверитьМобильнуюВерсию85()
    #Если МобильноеПриложениеКлиент Тогда
        Информация = Новый СистемнаяИнформация;
        Версия = Информация.ВерсияПриложения;
        Если ПроверитьСвойПакетНаСервере85() <> Истина Тогда
            ВызватьИсключение "Локальный сервер не подтвердил метку собственного пакета";
        КонецЕсли;
        Возврат Версия;
    #Иначе
        ВызватьИсключение "Этот урок запускается только в мобильном приложении, не в desktop или мобильном клиенте";
    #КонецЕсли
КонецФункции
&НаКлиенте
Асинх Процедура ПройтиОпыт85(Команда)
    Попытка
        #Если МобильноеПриложениеКлиент Тогда
            ПодготовитьОпыт85(Команда, "OWN_SAFE_PACKETS_85:CALLBACK:");
            Этап85 = "НачальнаяЗапись";
            ПроверитьСостояние85("НачальнаяЗапись");
            Неизвестно85 = Истина;
            Операция = Менеджер85.ПоместитьДанныеАсинх(Ключ85, ОжидаемыйПакет85, Способ85, ДопПроверка85);
            Если ТипЗнч(Операция) <> Тип("Обещание") Тогда
                ВызватьИсключение "Callback producer PutAsync не вернул обещание";
            КонецЕсли;
            Результат = Ждать Операция;
            ПроверитьСостояние85("НачальнаяЗапись");
            ПроверитьОтсутствиеОтмены85(Результат);
            ПроверитьЗанятость85(Истина);
            Этап85 = "ЧтениеCallback";
            ПроверитьСостояние85("ЧтениеCallback");
            Неизвестно85 = Истина;
            Обработчик = Новый ОписаниеОповещения("Получено85", ЭтотОбъект, Токен85);
            Состояние85 = "Ожидается настоящий callback чтения; повтор запрещен";
            Менеджер85.НачатьПолучениеДанных(Ключ85, Обработчик, "Проверить весь собственный учебный счет");
        #Иначе
            ВызватьИсключение "Callback опыт не запускается в другой среде";
        #КонецЕсли
    Исключение
        Остановить85(ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

&НаКлиенте
Процедура Получено85(ОтмененоПользователем, Ключ, Данные, ДополнительныеПараметры) Экспорт
    Попытка
        #Если МобильноеПриложениеКлиент Тогда
            ПроверитьСостояние85("ЧтениеCallback");
            Если Неизвестно85 <> Истина Тогда
                ВызватьИсключение "Нет ожидаемого незавершенного callback чтения";
            КонецЕсли;
            ПроверитьОтсутствиеОтмены85(ОтмененоПользователем);
            Если ТипЗнч(Ключ) <> Тип("Строка") Или Ключ <> Ключ85
                Или ТипЗнч(ДополнительныеПараметры) <> Тип("УникальныйИдентификатор")
                Или ДополнительныеПараметры <> Токен85 Тогда
                ВызватьИсключение "Callback не соответствует собственному точному ключу и nonce";
            КонецЕсли;
            Сумма85 = ПроверитьПолныйПакет85(Данные, 750, 250);
            Если Сумма85 <> 1000 Тогда ВызватьИсключение "Callback счет не равен 1000"; КонецЕсли;
            ПроверитьЗанятость85(Истина);
            Неизвестно85 = Ложь;
            История85 = "1000";
            Этап85 = "УдалениеCallback";
            ПроверитьСостояние85("УдалениеCallback");
            Неизвестно85 = Истина;
            Обработчик = Новый ОписаниеОповещения("Удалено85", ЭтотОбъект, Токен85);
            Состояние85 = "Полный счет прочитан; ожидается настоящий callback удаления своего ключа";
            Менеджер85.НачатьУдалениеДанных(Ключ85, Обработчик);
        #Иначе
            ВызватьИсключение "Native callback запрещен в другой среде";
        #КонецЕсли
    Исключение
        Остановить85(ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

&НаКлиенте
Процедура Удалено85(Ключ, ДополнительныеПараметры) Экспорт
    Попытка
        #Если МобильноеПриложениеКлиент Тогда
            ПроверитьСостояние85("УдалениеCallback");
            Если Неизвестно85 <> Истина Тогда
                ВызватьИсключение "Нет ожидаемого незавершенного callback удаления";
            КонецЕсли;
            Если ТипЗнч(Ключ) <> Тип("Строка") Или Ключ <> Ключ85
                Или ТипЗнч(ДополнительныеПараметры) <> Тип("УникальныйИдентификатор")
                Или ДополнительныеПараметры <> Токен85 Тогда
                ВызватьИсключение "Callback удаления не соответствует собственному ключу и nonce";
            КонецЕсли;
            ПроверитьЗанятость85(Ложь);
            Неизвестно85 = Ложь;
            Этап85 = "Завершен";
            Состояние85 = "Native callbacks подтвердили счет 1000 и отсутствие только собственного ключа";
        #Иначе
            ВызватьИсключение "Native callback удаления запрещен в другой среде";
        #КонецЕсли
    Исключение
        Остановить85(ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПроверитьСвойПакетНаСервере85()
    #Если МобильноеПриложениеСервер Тогда
        Если Метаданные.ОбщиеФормы.Количество() <> 3 Или Метаданные.ОбщиеФормы.Найти("ГлавнаяСейфа85") = Неопределено Или Метаданные.ОбщиеФормы.Найти("ПультСейфаАсинх85") = Неопределено Или Метаданные.ОбщиеФормы.Найти("ПультСейфаОповещения85") = Неопределено Тогда
            ВызватьИсключение "Не совпадает собственный новый мобильный учебный пакет";
        КонецЕсли;
        Возврат Истина;
    #Иначе
        ВызватьИсключение "Нужен локальный сервер собственного мобильного приложения, не desktop ИБ";
    #КонецЕсли
КонецФункции
Полный модуль собственной начальной формы: две настоящие команды без автоматического опыта

Своя CF → Общие → Общие формы → ГлавнаяСейфа85 → полный управляемый модуль

МобильноеПриложениеКлиент; серверный helper только МобильноеПриложениеСервер. Сначала своя метка и фактическая версия, затем ОткрытьФорму своей общей формы; записи/чтения сейфа не выполняются.

&НаКлиенте
Процедура ОткрытьАсинх85(Команда)
    Если ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда <> Команды.Найти("ОткрытьАсинх85") Тогда
        ВызватьИсключение "Нужна собственная команда главной формы";
    КонецЕсли;
    ПроверитьМобильнуюВерсию85();
    ОткрытьФорму("ОбщаяФорма.ПультСейфаАсинх85");
КонецПроцедуры

&НаКлиенте
Процедура ОткрытьОповещения85(Команда)
    Если ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда <> Команды.Найти("ОткрытьОповещения85") Тогда
        ВызватьИсключение "Нужна собственная команда главной формы оповещений";
    КонецЕсли;
    ПроверитьМобильнуюВерсию85();
    ОткрытьФорму("ОбщаяФорма.ПультСейфаОповещения85");
КонецПроцедуры
&НаКлиенте
Функция ПроверитьМобильнуюВерсию85()
    #Если МобильноеПриложениеКлиент Тогда
        Информация = Новый СистемнаяИнформация;
        Версия = Информация.ВерсияПриложения;
        Если ПроверитьСвойПакетНаСервере85() <> Истина Тогда
            ВызватьИсключение "Локальный сервер не подтвердил метку собственного пакета";
        КонецЕсли;
        Возврат Версия;
    #Иначе
        ВызватьИсключение "Этот урок запускается только в мобильном приложении, не в desktop или мобильном клиенте";
    #КонецЕсли
КонецФункции
&НаСервереБезКонтекста
Функция ПроверитьСвойПакетНаСервере85()
    #Если МобильноеПриложениеСервер Тогда
        Если Метаданные.ОбщиеФормы.Количество() <> 3 Или Метаданные.ОбщиеФормы.Найти("ГлавнаяСейфа85") = Неопределено Или Метаданные.ОбщиеФормы.Найти("ПультСейфаАсинх85") = Неопределено Или Метаданные.ОбщиеФормы.Найти("ПультСейфаОповещения85") = Неопределено Тогда
            ВызватьИсключение "Не совпадает собственный новый мобильный учебный пакет";
        КонецЕсли;
        Возврат Истина;
    #Иначе
        ВызватьИсключение "Нужен локальный сервер собственного мобильного приложения, не desktop ИБ";
    #КонецЕсли
КонецФункции

Разбор по шагам

  1. В отдельном пульте отдельно согласитесь на одну запись и одно удаление своего свежего nonce-ключа.

  2. Реальный Promise PutAsync создает пакет750+250: BoolFalse, затем ContainsKeyTrue. Противоречивый BeginPut не вызывается.

  3. Создайте ОписаниеОповещения для экспортного Получено85 своей формы и своего UUID; вызовите native НачатьПолучениеДанных с3 аргументами.

  4. Платформа, не учебный код, вызывает Получено85 с4 формалами. Проверьте отсутствие отмены, ключ, nonce, весь фактический пакет, обе суммы и1000.

  5. Сразу после полного собственного callback результата и свежих guard вызывается native НачатьУдалениеДанных с2 аргументами.

  6. Платформа вызывает Удалено85 с2 формалами; после точного ключа/nonce и ContainsKeyFalse опыт завершен. Обработчики никогда не вызываются вручную.

Как проверить результат

  1. MAIN получает настоящий МенеджерБезопасногоХранилища через readonly global; объект не создается выдуманным конструктором.

  2. После каждого Ждать/callback проверяются текущий этап, типы, версия, метка собственной CF и native capability; неизвестный исход не разрешает новую операцию.

  3. Каждое фактическое чтение сравнивает всю строку,6 частей, свой UUID, оба кода и обе преобразованные числовые суммы.

  4. Before replacement/restoration/deletion источник прочитан заново; чужой либо изменившийся пакет вызывает STOP.

  5. Каждый опыт имеет собственный consumed-consent и свой новый nonce-ключ. Никаких чужих ключей, ручных событий и автоматического восстановления.

Ожидаемый результат

Ожидаемый ручной результат: native callback чтения дал Сумма85=1000; native callback удаления подтвердил отсутствие ровно своего ключа. Runtime и доставка callbacks здесь не проверены.

На что обратить внимание

  1. BoolFalse у Put/DeleteAsync — признак отсутствия отмены, не доказательство сохранения/удаления: нужны реальные контрольные чтения.

  2. GetAsync документирует Promise или прямое Неопределено; неопределенные конечные данные тоже STOP, поскольку свой producer никогда не сохраняет Неопределено.

  3. ContainsKey означает только занятость конкретного ключа и не выполняет пользовательскую проверку. Он не доказывает пустоту всего сейфа.

  4. BeginPut исключен: установленная справка противоречит сама себе в типе четвертого аргумента. Не угадываем другой enum или отсутствующий обязательный параметр.

  5. Sticky STOP и consumed-consent относятся к текущему экземпляру формы; нет обещания сохранения состояния после закрытия/переустановки.

  6. Чтение с последующей записью не является атомарным CAS или доказательством отсутствия гонки; используйте только свой отдельный стенд и единственного оператора.

  7. Будущий ручной код действительно использует защищенное хранилище, ОС I/O и возможные системные проверки. Здесь не было runtime и криптографического теста.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.