Демо · иллюстративный пример

Один баг. Два фикса. Два подписанных вердикта.

Крошечный баг на Python, фикс, который проходит скрытый тест, и фикс, который не проходит. Ниже — что говорит каждый вердикт и как проверить подпись, не доверяя нам на слово.

Код на этой странице — придуманная иллюстрация. Две квитанции настоящие: их выдают команды resultbond demo --scenario pass и --scenario fail, подписаны они публичным демо-ключом. Никаких данных клиентов и настоящих денег.

1. Задача

В условиях работы записано: при пустом (null) ответе внешнего сервиса возвращать пустую коллекцию, а не падать. Сейчас функция падает.

def order_ids(client):
    """IDs of the open orders. The upstream API may answer null."""
    data = client.get("/orders?status=open")
    return [order["id"] for order in data]   # TypeError when data is None

Открытый тест

public:regression:001

Агент его видит. Существующее поведение должно продолжать работать.

def test_ids_of_open_orders():
    assert order_ids(FakeClient([{"id": 7}, {"id": 9}])) == [7, 9]

Скрытый тест

hidden:fail-to-pass:001

Агент его не видит. На сегодняшнем коде он падает — это проверяется до начала работы.

def test_null_upstream_gives_empty_list():
    assert order_ids(NullClient()) == []

2. Два патча

Патч A

PASS
     data = client.get("/orders?status=open")
+    if data is None:
+        return []
     return [order["id"] for order in data]

Пустой ответ превращается в пустой список. Скрытый тест проходит, открытый тоже, три прогона совпадают.

Патч B

FAIL
-    data = client.get("/orders?status=open")
-    return [order["id"] for order in data]
+    try:
+        data = client.get("/orders?status=open")
+        return [order["id"] for order in data]
+    except Exception:
+        return None

Падения больше нет, и кажется, что всё исправлено. Но функция возвращает None, а не пустой список, и заодно глушит все остальные ошибки. Скрытый тест это ловит.

3. Подписанные вердикты

Основные поля каждой квитанции. Хеши и подпись Ed25519 — в полных файлах.

Квитанция PASS

receipt-pass.json
{
  "receipt_version": "rb.proof-receipt.v0.3",
  "job_id": "partner:demo-marketplace/demo-bugfix-001",
  "policy_id": "rb.hidden-bugfix.v0.2",
  "outcome": "PASS",
  "reason_code": "ALL_CHECKS_PASS",
  "settlement": {
    "payment_action": "RELEASE_PAYMENT",
    "currency": "USDC",
    "payment_atomic": 250000000,
    "stipend_atomic": 0
  },
  "evaluator_key_id": "demo:evaluator:key-1",
  "issued_at": "2026-08-27T12:05:00.000000Z"
}

Оплата уходит агенту.

Квитанция FAIL

receipt-fail.json
{
  "receipt_version": "rb.proof-receipt.v0.3",
  "job_id": "partner:demo-marketplace/demo-bugfix-001",
  "policy_id": "rb.hidden-bugfix.v0.2",
  "outcome": "FAIL",
  "reason_code": "HIDDEN_TEST_FAILURE",
  "settlement": {
    "payment_action": "REFUND_PAYMENT",
    "currency": "USDC",
    "payment_atomic": 250000000,
    "stipend_atomic": 25000000
  },
  "evaluator_key_id": "demo:evaluator:key-1",
  "issued_at": "2026-08-27T12:05:00.000000Z"
}

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

4. Проверьте подпись сами

  1. В браузере. Откройте /verify и нажмите «Пример PASS» или «Пример FAIL». Проверка идёт у вас на компьютере, ничего не загружается. Попробуйте «Подделанная»: одно изменённое число ломает подпись.
  2. Через Python CLI из этого репозитория:
git clone https://github.com/valtris/resultbond-core && cd resultbond-core
pip install -e .
curl -sO https://resultbond.com/samples/receipt-pass.json
resultbond verify-receipt receipt-pass.json

В ответе будет "valid": true и "trusted": false: квитанция цела, но демо-ключ публичный, подписать им мог кто угодно. Настоящие квитанции подписываются ключами из опубликованного набора ключей ResultBond (--online). Чтобы сознательно принять демо-ключ, закрепите его:

resultbond verify-receipt receipt-pass.json \
  --trust demo:evaluator:key-1=7UkoxijRwsbq6QM4kFmVYSlZJzpcY_k2NsFGFKyHN9E

Та же проверка на JavaScript, из корня репозитория:

node js/cli.mjs verify receipt-pass.json

Попробуйте на своих багах.

Сначала теневой режим: ваш агент, ваши баги, никаких платежей.