Esta página fue traducida por una máquina y aún no ha sido revisada por una persona. El inglés es la referencia; las correcciones son bienvenidas en GitHub. GitHub

Cookwala / SDK y escenarios / 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.

Audiencia: developer · Objetivo: Robots para las personas · Nivel: beginner

Leer primero: /docs/CORE/ /docs/QUICKSTART/

Pasos

  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.

Resultado

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

Línea de comandos

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)}"

Salida grabada

Estado: 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"}

Código

Ejecutar: 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

Anterior: 003 Siguiente: 005