Cookwala / حزمة التطوير والسيناريوهات / 055

Hash a recipe and compare it with the hash field the file carries

A published recipe carries its own content hash. Compute the hash of the koshari file, fetch the hub's copy and read the field inside it, and hash that copy too: all three agree.

الفئة: recipe publisher · الهدف: صحة أفضل للناس · المستوى: beginner

اقرأ أولًا: /docs/CORE/ /docs/HUB/

الخطوات

  1. Hash the koshari file from the repository. hash

  2. Fetch the hub's copy; its hash field carries the same value. getRecipe

  3. Hash the fetched copy. The hash and signature fields are excluded from the computation, so a document can carry its own hash. hash

النتيجة

You can check that a recipe file is the revision it says it is. Next: scenario 047 shows the hub refusing a request whose hash does not match.

سطر الأوامر

cookwala hash examples/koshari.cookwala.json
grep '"hash"' examples/koshari.cookwala.json

المخرجات المسجلة

الحالة: ok

[1] hash: {"hash": "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45"}
[2] getRecipe: {"$schema": "https://cookwala.ai/v1/schemas/recipe.schema.json", "cookwala": "0.2.0", "id": "example-koshari", "revision": 1, "updated": "2026-10-04", "verification": {"level": "V1", "evidence": {"simulatorRuns": 0, "humanReviews": 1, "fieldReports": 0}, "reviewedBy": "cookwala.ai editorial (structure only)", "notes": "Example recipe written to exercise the standard: structured steps, end conditions, hazards and critical control points. Not simulated and not field-verified; values are typical home-cooking values, not measurements."}, "dish": {"names": {"en": "Koshari", "ar": "كشري"}, "cuisine"…
[3] hash: {"hash": "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45"}

الكود

التشغيل: python scenarios/out/055-hash-a-recipe-and-compare-with-its-hash-field/python.py

# Scenario 055: Hash a recipe and compare it with the hash field the file carries
# A published recipe carries its own content hash. Compute the hash of the koshari file, fetch the hub's copy and read the field inside it, and hash that copy too: all three agree.
# 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: Hash the koshari file from the repository.
file = c.hash(load("examples/koshari.cookwala.json"))
assert pick(file, "hash") == "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45", pick(file, "hash")
print("ok", "hash", "=", "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45")

# Step 2: Fetch the hub's copy; its hash field carries the same value.
recipe = c.get_recipe("koshari")
assert pick(recipe, "hash") == "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45", pick(recipe, "hash")
print("ok", "hash", "=", "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45")
assert pick(recipe, "id") == "example-koshari", pick(recipe, "id")
print("ok", "id", "=", "example-koshari")

# Step 3: Hash the fetched copy. The hash and signature fields are excluded from the computation, so a document can carry its own hash.
again = c.hash(recipe)
assert pick(again, "hash") == "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45", pick(again, "hash")
print("ok", "hash", "=", "sha256:f7fc3745af51465fb7a849faa5b5927eeaa44030a703318bb293381fef8b3f45")

print("scenario complete")

scenarios/055-hash-a-recipe-and-compare-with-its-hash-field.json

السابق: 054 التالي: 056