COOPENOMICS  v1
Кооперативная Экономика
Действия

Функции

void apps::cleanup (eosio::name package_id)
 Ручной cleanup TTL-просроченных superseded-записей пакета. Подробнее...
 
void apps::expsub (eosio::name coopname, eosio::name subscriber, eosio::name package_id)
 Деактивировать подписку (active=false); row не удаляется (нужен для аудита истечения). Подробнее...
 
void apps::reactivate (eosio::name coopname, eosio::name package_id, std::string version)
 Реактивировать предыдущую версию пакета (FR43). Подробнее...
 
void apps::regcoop (eosio::name coopname, eosio::checksum256 chain_id, eosio::name subnet_label, eosio::public_key signing_key)
 Зарегистрировать кооператив в каталоге. Подробнее...
 
void apps::regpackage (eosio::name coopname, eosio::name package_id, std::string package_name, eosio::name owner, std::vector< eosio::name > compatible_subnets)
 Зарегистрировать новый пакет в каталоге. Подробнее...
 
void apps::regsub (eosio::name coopname, eosio::name subscriber, eosio::name package_id, eosio::checksum256 chain_id, eosio::name plan, eosio::time_point_sec start_at, eosio::time_point_sec end_at)
 Зарегистрировать или продлить подписку кооператива на пакет. Подробнее...
 
void apps::setcoop (eosio::name coopname, std::optional< eosio::checksum256 > chain_id, std::optional< eosio::name > subnet_label, std::optional< eosio::public_key > signing_key, std::optional< bool > active)
 Обновить параметры кооператива (ротация ключа, перенос подсети, деактивация). Подробнее...
 
void apps::setrelease (eosio::name coopname, eosio::name package_id, std::string version, Apps::scope_t scope, eosio::checksum256 tarball_sha256, eosio::name moderated_by, std::string meta)
 Опубликовать новый release пакета. Подробнее...
 
void apps::transferpkg (eosio::name coopname, eosio::name package_id, eosio::name new_owner)
 Передать владение пакетом другому пользователю (FR3). Подробнее...
 
void apps::withdraw (eosio::name coopname, eosio::name package_id, std::string version, std::string reason)
 Отозвать релиз (CVE / нарушение / юридический отзыв). Подробнее...
 

Подробное описание

Функции

◆ cleanup()

void apps::cleanup ( eosio::name  package_id)

Ручной cleanup TTL-просроченных superseded-записей пакета.

Удаляет до CLEANUP_BUDGET_PER_CALL записей с superseded_at < now - RELEASE_RETENTION_SECS. Идемпотентен.

Заметки
Без авторизации: операция доброкачественная, удаляет только уже невидимые в продакшене записи. Любой может вызвать (и заплатить за CPU).

Используется когда setrelease для пакета давно не вызывался, и inline-cleanup в нём не подметает хвост. Удаляет до CLEANUP_BUDGET_PER_CALL записей с status=superseded и superseded_at < now - RELEASE_RETENTION_SECS.

Идемпотентно. Многократные вызовы безопасны: каждый вызов чистит свой batch до budget'а.

Заметки
БЕЗ авторизации: операция доброкачественная, удаляет только уже невидимые в продакшене записи, не меняет логику. Любой может вызвать (и заплатить за CPU). Это снижает оперативную нагрузку на оператора каталога.

◆ expsub()

void apps::expsub ( eosio::name  coopname,
eosio::name  subscriber,
eosio::name  package_id 
)

Деактивировать подписку (active=false); row не удаляется (нужен для аудита истечения).

Деактивировать подписку.

Заметки
Авторизация: coopname @ active.

Ставит active=false. Запись остаётся в таблице — она нужна для аудита истечения и для повторной активации (если кооператив снова подпишется, пойдёт через тот же row через regsub-upsert).

Cleanup физически просроченных записей (например, истёкших год назад и более не нужных в RAM) — задача отдельного периодического действия. Вне scope MVP.

Заметки
Авторизация: coopname @ active.

◆ reactivate()

void apps::reactivate ( eosio::name  coopname,
eosio::name  package_id,
std::string  version 
)

Реактивировать предыдущую версию пакета (FR43).

Находит release по (package_id, version); ставит ему status=active, superseded_at=0. Текущий active с тем же scope → superseded. Если scope=all — обновляет packages.last_active_version.

Заметки
Авторизация: coopname @ active.

Используется для отката broken release без full re-publish:

  • Находит существующий release (package_id, version) со статусом superseded или withdrawn.
  • Текущий active с тем же scopesuperseded.
  • Найденный release → active, superseded_at=0.
  • Если scope=all — обновляется packages.last_active_version.

Окно реактивации ограничено TTL retention (90 дней): за пределами окна superseded-записи уже удалены, и реактивация не возможна — нужен полноценный re-publish.

Заметки
Авторизация: coopname @ active.

◆ regcoop()

void apps::regcoop ( eosio::name  coopname,
eosio::checksum256  chain_id,
eosio::name  subnet_label,
eosio::public_key  signing_key 
)

Зарегистрировать кооператив в каталоге.

Регистрация кооператива в каталоге.

Этот action — часть процесса подключения коопа к каталогу приложений на Восходе (вне scope текущего MVP). Кооператив сам подписывает транзакцию (require_auth(coopname)), подтверждая, что владеет приватной частью signing_key.

Аргументы
coopnameкооператив, который регистрируется.
chain_idподсеть, к которой принадлежит коопе.
subnet_labelhuman-label подсети ("ru","by",...).
signing_keysubnet-signing-key (отдельный от @ active).
Заметки
Авторизация: coopname @ active. Идемпотентность: фейл, если уже зарегистрирован — для обновления использовать setcoop.

Кооператив сам подписывает транзакцию своим @active-ключом и передаёт публичную часть signing_key (отдельный ключ для подписи signed-request'ов от DC-оркестратора в CA-auth).

Идемпотентность: если такой coopname уже зарегистрирован — фейл. Для обновления полей — setcoop.

Заметки
Контекст: этот action — часть процесса подключения кооператива к каталогу приложений на Восходе (вне scope текущего MVP apps-catalog). Реальный flow: кабинет ВОСХОД проводит onboarding, генерирует/принимает signing keypair, подписывает и отправляет эту транзакцию.
Авторизация: coopname @ active.

◆ regpackage()

void apps::regpackage ( eosio::name  coopname,
eosio::name  package_id,
std::string  package_name,
eosio::name  owner,
std::vector< eosio::name >  compatible_subnets 
)

Зарегистрировать новый пакет в каталоге.

Регистрация нового пакета в каталоге.

Аргументы
coopnameпровайдер каталога (тот, кто подписал транзакцию).
package_idкодовое имя пакета (Antelope name, ≤12 chars).
package_nameвнешнее имя (npm/go/oci) — может содержать @scope/name.
ownerusername владельца пакета.
compatible_subnetshuman-labels подсетей, в которых пакет совместим.
Заметки
Авторизация: coopname @ active. Идемпотентность: фейл, если package_id уже зарегистрирован (нужен явный transferpkg/withdraw перед re-регистрацией).

Контракт операции:

  • PK = package_id. Если такой уже существует — фейлим («имя занято»).
  • package_name — внешнее имя; не уникально (теоретически два пакета могут иметь одинаковое npm-имя, но разные package_id; на практике это ловится UI/правилами кабинета ВОСХОД).
  • compatible_subnets — может быть пустой; в этом случае пакет считается совместимым со всеми подсетями (resolver на стороне CA обрабатывает пустой набор как «нет ограничений»).
  • last_active_version инициализируется пустой строкой; заполнится первым setrelease со scope=all.
Заметки
Авторизация: coopname @ active.

◆ regsub()

void apps::regsub ( eosio::name  coopname,
eosio::name  subscriber,
eosio::name  package_id,
eosio::checksum256  chain_id,
eosio::name  plan,
eosio::time_point_sec  start_at,
eosio::time_point_sec  end_at 
)

Зарегистрировать или продлить подписку кооператива на пакет.

Регистрация или продление подписки кооператива на пакет.

Idempotent по (coopname, package_id):

  • row не существует → создаём с active=true.
  • row существует → обновляем plan, end_at = max(текущее, новое), active=true, chain_id (на случай переноса между подсетями).
    Аргументы
    coopnameпровайдер каталога (тот, кто выписывает подписку).
    subscriberкооператив-подписчик.
    chain_idподсеть, в которой действует подписка.
    Заметки
    Авторизация: coopname @ active.
    Idempotent по (subscriber, package_id):

Row нет → создаём с active=true, start_at, end_at, plan, chain_id.

  • Row есть → обновляем plan, end_at = max(текущее, новое), active=true, chain_id (на случай миграции коопа между подсетями), start_at оставляем как был (это маркер «когда вообще началась подписка»).

Это поведение специально сознательное: биллинг кабинета ВОСХОД при retry / повторной отправке не должен бояться дубликатов. История выписки подписок остаётся в blockchain trace'ах (Antelope action history), а не в таблице subs.

Аргументы
coopnameпровайдер каталога (тот, кто выписывает подписку).
subscriberкооператив-подписчик.
chain_idподсеть, в которой действует подписка.
Заметки
Авторизация: coopname @ active. Проверки chain_id против coops.chain_id НЕ делаем, потому что: 1) coops row может ещё не существовать при первой выдаче подписки; 2) подписка теоретически может быть выдана коопу из другой подсети (миграция). Лучше доверять биллингу.

◆ setcoop()

void apps::setcoop ( eosio::name  coopname,
std::optional< eosio::checksum256 >  chain_id,
std::optional< eosio::name >  subnet_label,
std::optional< eosio::public_key >  signing_key,
std::optional< bool >  active 
)

Обновить параметры кооператива (ротация ключа, перенос подсети, деактивация).

Обновление параметров кооператива.

Все параметры опциональны — обновляются только переданные. При смене signing_key обновляется key_rotated_at=now. Ранее выпущенные JWT (TTL 14 дней) остаются валидны; новые signed-request'ы должны идти от нового приват-ключа.

Заметки
Авторизация: coopname @ active.

Все параметры опциональны — обновляются только переданные. Сценарии использования:

  • Ротация подписи: setcoop(coopname, signing_key=<new>). Меняет signing_key и key_rotated_at=now.
  • Деактивация: setcoop(coopname, active=false). CA-auth перестанет отвечать на запросы от этого коопа.
  • Миграция между подсетями: setcoop(coopname, chain_id=<new>, subnet_label=<new>).
  • Обновление human-label: setcoop(coopname, subnet_label=<new>).
Заметки
Ранее выпущенные JWT (TTL 14 дней в CA-auth) остаются валидны после ротации signing_key. Только новые signed-request'ы должны идти от нового приват-ключа. Это даёт zero-downtime ротации.
Авторизация: coopname @ active. Если @active-ключ коопаккаунта скомпрометирован, эта операция не доступна злоумышленнику — сначала кооператив должен ротировать @active через eosio::updateauth (это отдельная операция, владелец-ключ).

◆ setrelease()

void apps::setrelease ( eosio::name  coopname,
eosio::name  package_id,
std::string  version,
Apps::scope_t  scope,
eosio::checksum256  tarball_sha256,
eosio::name  moderated_by,
std::string  meta 
)

Опубликовать новый release пакета.

Опубликовать новый release пакета — атомарный transition.

Атомарно (FR8 «approve → release.ACTIVE»):

  1. Создаёт row в releases со status=active, superseded_at=0.
  2. Любой существующий active с тем же (package_id, scope)superseded, superseded_at=now.
  3. Если scope.kind == "all" — обновляет packages.last_active_version.
  4. Inline-cleanup: удаляет до CLEANUP_BUDGET_PER_CALL самых старых superseded-записей с superseded_at < now - RELEASE_RETENTION_SECS.
Аргументы
scopeобласть видимости (см. scope_t).
Заметки
Авторизация: coopname @ active.

Алгоритм (выполняется в одной транзакции):

  1. Проверки: пакет существует; статус — известный; scope согласован (kind=all → targets пустой; kind=subnet/canary → targets непустой).
  2. Выполнить supersede предыдущего active с тем же scope (точное совпадение kind + targets). Записывается superseded_at=now. Если кто-то уже superseded — пропускаем.
  3. Создать новый row со status=active, superseded_at=0.
  4. Если scope.kind == "all"_n — обновить packages.last_active_version.
  5. Inline-cleanup: пройтись по bysuperseded-индексу для этого пакета и удалить до CLEANUP_BUDGET_PER_CALL записей с superseded_at < now - RELEASE_RETENTION_SECS.

Это ядро «atomic moderation approve» (FR8): индекс CA + KE.releases — либо обе, либо ни одна. Со стороны blockchain'а — гарантия атомарности в пределах одной транзакции.

Заметки
Re-publish одной и той же version запрещён: если releases уже содержит row для (package_id, version) — фейл. Версии публикуются монотонно вверх; для отката используется reactivate(version=старая).
Авторизация: coopname @ active.

◆ transferpkg()

void apps::transferpkg ( eosio::name  coopname,
eosio::name  package_id,
eosio::name  new_owner 
)

Передать владение пакетом другому пользователю (FR3).

Передача владения пакетом другому пользователю (FR3).

Заметки
Авторизация: coopname @ active.

Меняет owner на new_owner. Прав на сами релизы это не меняет — setrelease всё равно выполняется провайдером каталога (coopname), owner — это поле для аудита и UI «чей это пакет».

Заметки
Авторизация: coopname @ active.

◆ withdraw()

void apps::withdraw ( eosio::name  coopname,
eosio::name  package_id,
std::string  version,
std::string  reason 
)

Отозвать релиз (CVE / нарушение / юридический отзыв).

Ставит status=withdrawn. Если это был active со scope=all — packages.last_active_version обнуляется ("") до следующего setrelease/reactivate.

Заметки
Авторизация: coopname @ active.

Семантика отзыва:

  • Релиз становится withdrawn и НЕ может быть установлен через CA-auth.
  • Запись остаётся в таблице — TTL на withdrawn не действует.
  • Если withdrawn-релиз был active со scope=all, last_active_version обнуляется ("") — UI должен показать «нет активной версии», пока оператор не выпустит новый setrelease или не реактивирует старую.
  • Если был active со scope=subnet/canary, last_active_version не трогается — она показывает версию для основной массы кооперативов.
Заметки
Авторизация: coopname @ active.