Cookwala Humanitarian Profile (draft 0.2)
Status: draft for review by food banks, relief programs and food-safety and nutrition professionals. It is not reviewed or endorsed by WFP, WHO, FAO, the Global FoodBanking Network or any other organization named here.
Files:
- schema: [
schemas/humanitarian.schema.json](../schemas/humanitarian.schema.json) - examples: [
examples/humanitarian/](../examples/humanitarian) - rule packs: [
basic-nutrition-food-safety](../profiles/humanitarian/basic-nutrition-food-safety.rulepack.json) (all), [care-vulnerable-groups](../profiles/humanitarian/care-vulnerable-groups.rulepack.json), [school-meals-basic](../profiles/humanitarian/school-meals-basic.rulepack.json), [sodium-reduction](../profiles/humanitarian/sodium-reduction.rulepack.json) (RFC-0004; all drafts awaiting professional review, see [docs/health/REVIEW-TEMPLATE.md](health/REVIEW-TEMPLATE.md)) - API: [
api/humanitarian.openapi.yaml](../api/humanitarian.openapi.yaml) - worked flows: [
examples/humanitarian/flows/](../examples/humanitarian/flows) (food bank in Cairo, school meals, disaster kitchen, robot kitchen), each with a computedImpactSummary - pilot protocol: [
docs/humanitarian/PILOT-PROTOCOL.md](humanitarian/PILOT-PROTOCOL.md) - spreadsheet and SMS templates: [
profiles/humanitarian/templates/](../profiles/humanitarian/templates) - reference checker: [
tools/humanitarian_check.py](../tools/humanitarian_check.py)
0. What 0.2 adds (RFC-0003, RFC-0004) #
Additive over 0.1; readers accept both.
- Farm to plate:
Item.origin(farm,processor,wholesale,retail,food_service,kitchen) andItem.harvestedAt; rolesfarm,caterer,robot_kitchen; the SMS wordFARM. - Care rules:
Item.foodClassesandDistribution.menu.foodClasses(raw egg, unpasteurized dairy, whole nuts, cooked rice…), rule kindfood_class,Rule.audienceGroup,Distribution.audienceGroups; three new draft packs. - Reviews:
RulePack.reviewsrecords the profession, organization, date, scope and outcome of each review;status: reviewedneeds an approved review. - Impact:
ImpactSummarywith nine measures, each carryingmethod(measured, modelled, assumed, not recorded), computed bytools/humanitarian_check.py --summary. - Time to claim:
Offer.createdAt,Claim.claimedAt;Handover.legso kilograms rescued count once. - Program types on the
Manifest.
1. Purpose #
A small, strict, personal-data-free part of Cookwala for organizations that feed people: food banks, community kitchens, school-meal programs, relief programs, donors (grocers, restaurants, farms, caterers), transporters and cold stores. It covers four jobs:
- Offering surplus food and claiming it, quickly and fairly.
- Recording each handover of custody, with a temperature check (cold-chain check).
- Reporting what was served as aggregate counts only.
- Checking menus and handovers against machine-readable nutrition and food-safety rules.
It works without robots, apps or internet. Levels H0 and H1 run on spreadsheets, SMS and basic phones. Robots, hubs and agents are optional consumers of the same documents.
2. Principles #
- Do no harm. Collect nothing that could identify, locate or profile a person or household. In fragile settings, data about beneficiaries is a protection risk.
- Humanitarian principles (humanity, neutrality, impartiality, independence): no commercial branding on aid, and no use of data for marketing.
- Strict and small. Every object rejects unknown fields (except
x-extensions), so typos and extra personal fields fail validation. - Exact units: kilograms, degrees Celsius, absolute tolerances, and money as decimal strings.
- Local rules win. Rule packs are replaceable by national food-safety and donation law.
- Open: royalty-free spec, open-source tools. The profile is designed to meet the Digital Public Goods Standard and the Principles for Digital Development.
3. Conformance levels #
| Level | What a participant does | Needs |
|---|---|---|
| H0 — Paper & SMS | Records offers, handovers and distributions in the CSV templates (with HXL hashtag rows) or by SMS (section 8.3) | A spreadsheet or a basic phone |
| H1 — Rescue | Exchanges Offer, Claim, Handover and Distribution documents over the API; follows the state machine (section 5) | Any HTTP client |
| H2 — Safety & nutrition | Applies a RulePack to every handover and menu, and records findings | The reference checker or an equivalent |
| H3 — Interoperability | Exports aggregates to HXL, DHIS2 and the core Cookwala ImpactReport; uses GS1 identifiers | Integration work |
A participant publishes a Manifest at /.well-known/cookwala-humanitarian.json that declares its levels, rule packs, endpoints and personalData: "none".
4. Documents #
| Document | Who writes it | Purpose |
|---|---|---|
Offer | Donor | Surplus food available for collection: items (kg, storage, date marks, allergens), window, site, temperatures |
Claim | Food bank, kitchen, program | Claims all or part of an offer, with a pickup time and vehicle type |
Handover | Receiver of custody | One per leg: temperatures, kg accepted or rejected with a reason code, and rule findings |
Distribution | Kitchen, food bank, school | Aggregate meals and people served at a site on a day; optional menu nutrients and costs |
RulePack | Program or authority | Versioned nutrition and food-safety rules (section 6) |
Manifest | Every participant | Capabilities and data-protection declaration |
The core Cookwala relief documents (Program, Need, Pledge, Allocation, ImpactReport in relief.schema.json) remain available for planning. This profile handles the operational flow.
5. Offer lifecycle #
| From | Allowed next states |
|---|---|
offered | claimed, expired, withdrawn |
claimed | collected, offered (the claim lapsed), expired, withdrawn |
collected | delivered, rejected |
delivered | distributed, rejected |
distributed, expired, withdrawn, rejected | none (final) |
Rules for state changes:
- Every change increments
version. Writers sendIf-Match: <version>; a mismatch returns 409, and the writer re-reads and retries. - An illegal transition returns 409 with the allowed transitions.
- Offers move to
expiredautomatically atwindow.to. - Claims lapse at
pickupByplus a grace period the program sets (default 30 minutes).
Fair claiming. By default, claims are first-come within a priority tier the program sets: for example, kitchens serving children first, then other kitchens, then food banks. Tiers and any rotation rules must be published in the program's Manifest or website.
6. Food safety and nutrition rule packs #
A RulePack holds rules of six kinds:
temperature: chilled ≤ 5 °C, hot-held ≥ 60 °C, frozen ≤ −18 °C;time: cooked food out of temperature control for at most 2 h;date_mark: use-by blocks, best-before warns;allergen: undeclared allergens block;nutrient: amounts per person-day or per meal;energy_share: share of energy from free sugars, fat, saturated fat, trans fat or protein.
Each rule is either block (do not accept or serve) or warn (allowed, recorded as a finding).
The default pack [email protected] is a draft derived from public guidance: WHO's healthy-diet, sodium, sugars and fats guidance, the WHO Five Keys to Safer Food, Codex labelling and frozen-food codes, and Sphere's minimum ration planning figures. It is simplified, not medical advice, excludes infant and therapeutic feeding, and must be reviewed by qualified staff. Programs should copy and adapt it, set jurisdiction, and record who reviewed it in reviewedBy.
Receivers at level H2 run the pack at every handover and on every menu, and record rule ids in findings. The reference checker reports where declared and computed findings disagree.
7. Data protection #
The profile carries no personal data. Documents MUST NOT contain:
- names, phone numbers, emails, or national, refugee or biometric identifiers of any person;
- household-level records, or locations of homes or individuals;
- health, disability, religion or nationality of any person.
What it carries instead:
- Organizations only. Every party is an organization identified by
did:web, a GS1 Global Location Number (GLN) or a registry id. People appear only as roles (checkedBy: "trained_staff"). - Aggregates only.
Distribution.peopleholds counts by group, and any count under 10 is reported as"<10". - Sites only. A
Siteis an organization's premises or an administrative area (OCHA P-codes), never a household. - Short notes. Free text is limited to 280-character operational notes and must not contain personal data. Implementations should scan notes for phone numbers and ids before storing them.
Retention and audit:
- Retention: each participant declares
retentionDaysin itsManifestand deletes documents after it. - **Audit (optional,
hash_only):** one sequencer per program (normally the food bank or program operator) appends the SHA-256 hash of each document's RFC 8785 canonical JSON. Contents are stored separately and remain deletable. A partner organization counter-signs a checkpoint each day, so history can't be rewritten silently. A single sequencer avoids forks in the chain. - Hosting should be in-country where the law or the program requires it.
8. Transport #
8.1 API (level H1) #
| Method | Path | Notes |
|---|---|---|
POST | /offers | Creates an offer (state: offered) |
GET | /offers?status=offered&admin2=…&storage=… | Open offers near a receiver |
POST | /offers/{id}/claims | Claims an offer; If-Match required; 409 when already claimed |
POST | /offers/{id}/transitions | { "to": "collected" }; If-Match required |
POST | /handovers | Records a handover |
POST | /distributions | Records a distribution |
GET | /reports?from=…&to=… | Aggregates for a period |
Request and transport rules:
- Idempotency: every
POSTcarries anIdempotency-Key. Servers keep keys for at least 24 h and return the original response for repeats. - Authentication: OAuth 2.1 client credentials, one client per organization.
- Webhooks (
offer.created,offer.claimed,offer.expired,handover.recorded) are delivered at least once, with an eventidfor deduplication and a per-offer sequence number for ordering.
8.2 Spreadsheets (level H0) #
Use the CSV templates in profiles/humanitarian/templates/. Their second row holds HXL hashtags, so humanitarian data tools can read them directly.
8.3 SMS (level H0) #
OFFER 36KG YOGURT C 4C UB0511 → reply: OFFER A7K open until 08:00
FARM 120KG TOMATO A HV0411 → an offer with origin farm, harvested 4 November (0.2)
CLAIM A7K ALL → reply: CLAIMED A7K pickup by 20:30
HAND A7K 36 T4.6 → accepted 36 kg at 4.6 °C
HAND A7K 30 REJ 6 PACK T4.6 → accepted 30 kg, rejected 6 kg, packaging_damaged (0.2)
HAND A7K 0 REJ 18 TEMP T52 → rejected 18 kg, temp_out_of_range
DIST 410 MEALS 410 PEOPLE 96KG → distribution for today at the sender's site
MENU D12 KCAL650 SODIUM540 FV95 → per-meal nutrients for distribution D12 (0.2)
HELP · CANCEL A7KThe grammar is implemented in tools/cookwala_ref.py (parse_sms) and tested by conformance/profiles/sms.json. Keywords are English; Arabic-Indic (٠-٩) and Persian (۰-۹) digits are accepted wherever a digit is, so a phone set to either keyboard works.
Storage codes: A ambient, C chilled, F frozen, H hot-held. Date marks: UB use-by, BB best-before, HV harvested, as DDMM. Reject reason codes: TEMP temp_out_of_range, DATE past_use_by, PACK packaging_damaged, ALLERG allergen_unlabelled, QTY quantity_mismatch, PEST pests_or_contamination, SPACE no_capacity, TRANSPORT no_transport, LATE arrived_late, OTHER; any other word is recorded as other. The HELP reply MUST be one example per command, plain ASCII, under 160 characters.
A gateway MUST apply these checks before it writes a document (sms_storage_findings in the reference; ids are block findings):
| Finding | When |
|---|---|
safety.temp_not_recorded | a HAND on a chilled, frozen or hot-held line carries no T reading: reply asking for it, write nothing |
safety.hot_hold_min | an OFFER with storage H below 60 °C: refuse to list it |
safety.storage_class_mismatch | the item words imply dairy, meat, poultry, fish, egg or cooked food and storage is A: refuse to list it |
safety.chilled_max, safety.frozen_max | readings above 5 °C or above −18 °C on offer or handover |
Offers of hot-held food close after two hours (one hour for cooked rice); a gateway never stores a placeholder reading. The gateway maps the sender's registered number to an organization, never to a person in the documents.
9. Interoperability #
| System | Mapping |
|---|---|
| HXL | CSV templates; Distribution → #reached+…, #adm1+name, #value+meals |
| GS1 | Item.gtin (products); Site.gln and OrgId gln: (locations) |
| Certifications (RFC-0010) | Item.certifications[] points at signed Certification documents (halal, kosher, organic…) by hash; a program verifies them against the authority's key, never from the message text |
| OCHA common operational datasets | Site.pcode |
| DHIS2 | Aggregate data values per site and period from Distribution (meals, people by group, kg, incidents) |
| WFP SCOPE and other beneficiary systems | Aggregates only. No beneficiary records cross into or out of this profile |
| Food-rescue apps | Adapters map their listings to Offer and their pickups to Claim and Handover |
| Core Cookwala | Item.ingredientId and menu.recipes link to the recipe index; relief.ImpactReport sums Distributions |
10. Pilot metrics (defined so sites can be compared) #
Computed into an ImpactSummary by python tools/humanitarian_check.py --summary DIR. How a pilot is run and judged: [humanitarian/PILOT-PROTOCOL.md](humanitarian/PILOT-PROTOCOL.md).
| Metric | Definition |
|---|---|
| Kg rescued | Sum of Handover.kgAccepted on the first leg from donors |
| Claim rate | Offers that reach claimed ÷ offers created |
| Time to claim | Median minutes from Offer creation to the claimed state |
| Rejection by reason | Sum of kgRejected by reason |
| Meals served | Sum of Distribution.meals |
| Nutrition pass rate | Distributions with menus and no nutrition.* findings ÷ distributions with menus |
| Cost per meal | (food + transport + staff + energy) ÷ meals |
| Volunteer minutes per 100 kg | volunteerMinutes ÷ (kg used ÷ 100) |
| Safety | Count of safety.* block findings, and safetyIncidents |
11. Security #
- Signatures are optional at H1 and required for cross-organization audit at H3 (EdDSA, keys published at the organization's
did:web). - Notes and names in documents are untrusted data. Software and AI agents must never treat them as instructions.
- Rule packs are versioned and pinned (
id@version) in every finding, so results are reproducible.
12. Deliberately left out #
- Beneficiary registration, eligibility and targeting (these belong to the program's own protected systems).
- Payments: Cookwala never moves money.
- Recipes and robot execution (the core spec). The profile only names recipes and reports nutrients.
- Medical and therapeutic nutrition.
13. How to review #
Please open issues on amado2k5/cookwala with the label humanitarian. These reviews are the most useful:
- food-safety staff checking the rule pack and the reject reasons;
- food-bank operators checking the lifecycle and the SMS flow;
- data-protection officers checking section 7.