Diese Seite wurde maschinell übersetzt und wurde noch nicht von einer Person überprüft. Englisch ist die Referenz; Korrekturen auf GitHub sind willkommen. GitHub

Cookwala / SDK und Szenarien / 004

Hash a recipe and see that the same document always gives the same hash

An executor cooks exactly one revision of a recipe and refuses any other. The hash is SHA-256 over RFC 8785 canonical JSON, without the hash and signature fields, so the hub, the CLI and every SDK agree on it.

Zielgruppe: developer · Ziel: Roboter für Menschen · Level: beginner

Zuerst lesen: /docs/CORE/ /docs/QUICKSTART/

Schritte

  1. Fetch the shakshuka example from the hub. getRecipe

  2. Hash the fetched document. hash

  3. Hash the same recipe read from the repository checkout: the same bytes in a different order still give the same hash. hash

  4. Another recipe gives another hash; a changed byte anywhere would too. hash

  5. The two shakshuka hashes are identical and equal the recipeHash in the ExecuteRequest example.

Ergebnis

You can compute the hash an ExecuteRequest must carry. Next: scenario 018 sends a request with the wrong hash and reads the refusal.

Kommandozeile

cookwala hash examples/shakshuka.cookwala.json
cookwala hash examples/kofta-oven.cookwala.json
curl -s -X POST http://localhost:7878/v1/tools/hash -H 'Content-Type: application/json' -d "{\"doc\": $(cat examples/shakshuka.cookwala.json)}"

Aufgezeichnete Ausgabe

Status: ok

[1] getRecipe: {"$schema": "https://cookwala.ai/v1/schemas/recipe.schema.json", "cookwala": "0.1.0", "id": "example-shakshuka", "revision": 2, "updated": "2026-10-03", "hash": "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", "verification": {"level": "V2", "evidence": {"simulatorRuns": 1, "humanReviews": 1, "fieldReports": 0}, "reviewedBy": "fifi.cooking editorial", "notes": "Illustrative example for the spec; values are realistic but not field-verified."}, "dish": {"names": {"en": "Shakshuka", "ar": "شكشوكة", "fr": "Chakchouka"}, "cuisine": ["TN", "MA", "DZ", "LY"], "course": "main…
[2] hash: {"hash": "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841"}
[3] hash: {"hash": "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841"}
[4] hash: {"hash": "sha256:932c364ad759aa2d27905c30c198be08ea9a7ac80ac3b60068895818cbdb4720"}

Code

Ausführen: python scenarios/out/004-hash-a-recipe/python.py

# Scenario 004: Hash a recipe and see that the same document always gives the same hash
# An executor cooks exactly one revision of a recipe and refuses any other. The hash is SHA-256 over RFC 8785 canonical JSON, without the hash and signature fields, so the hub, the CLI and every SDK agree on it.
# Run a hub first: python hub/cookwala_hub.py --recipes examples
import json, os
from cookwala.client import CookwalaClient, CookwalaProblem

def load(path):
    with open(path, encoding="utf-8") as f:
        return json.load(f)

def pick(obj, path):
    for part in path.replace("]", "").replace("[", ".").split("."):
        obj = obj[int(part)] if part.isdigit() else (len(obj) if part == "length" else obj.get(part))
    return obj

c = CookwalaClient(os.environ.get("COOKWALA_HUB", "http://localhost:7878"))


# Step 1: Fetch the shakshuka example from the hub.
recipe = c.get_recipe("shakshuka")
assert pick(recipe, "id") == "example-shakshuka", pick(recipe, "id")
print("ok", "id", "=", "example-shakshuka")
assert pick(recipe, "revision") == 2, pick(recipe, "revision")
print("ok", "revision", "=", 2)

# Step 2: Hash the fetched document.
fromHub = c.hash(recipe)
assert pick(fromHub, "hash") == "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", pick(fromHub, "hash")
print("ok", "hash", "=", "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841")

# Step 3: Hash the same recipe read from the repository checkout: the same bytes in a different order still give the same hash.
fromFile = c.hash(load("examples/shakshuka.cookwala.json"))
assert pick(fromFile, "hash") == "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", pick(fromFile, "hash")
print("ok", "hash", "=", "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841")

# Step 4: Another recipe gives another hash; a changed byte anywhere would too.
kofta = c.hash(load("examples/kofta-oven.cookwala.json"))
assert pick(kofta, "hash") == "sha256:932c364ad759aa2d27905c30c198be08ea9a7ac80ac3b60068895818cbdb4720", pick(kofta, "hash")
print("ok", "hash", "=", "sha256:932c364ad759aa2d27905c30c198be08ea9a7ac80ac3b60068895818cbdb4720")

# Step 5: The two shakshuka hashes are identical and equal the recipeHash in the ExecuteRequest example.
assert pick(fromHub, "hash") == "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", pick(fromHub, "hash")
print("ok", "hash", "=", "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841")
assert pick(fromFile, "hash") == "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841", pick(fromFile, "hash")
print("ok", "hash", "=", "sha256:2ea6fab93cc673fc6784f9bc9fe401d2387bb7779dc537df97286b73807c8841")

print("scenario complete")

scenarios/004-hash-a-recipe.json

Zurück: 003 Weiter: 005