Cookwala / حزمة التطوير والسيناريوهات / 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.
اقرأ أولًا: /docs/CORE/ /docs/QUICKSTART/
الخطوات
Fetch the shakshuka example from the hub.
getRecipeHash the fetched document.
hashHash the same recipe read from the repository checkout: the same bytes in a different order still give the same hash.
hashAnother recipe gives another hash; a changed byte anywhere would too.
hashThe two shakshuka hashes are identical and equal the recipeHash in the ExecuteRequest example.
النتيجة
You can compute the hash an ExecuteRequest must carry. Next: scenario 018 sends a request with the wrong hash and reads the refusal.
سطر الأوامر
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)}"المخرجات المسجلة
الحالة: 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"}الكود
التشغيل: 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")