{
  "markdown": "# FoodBlock\n\nA content-addressable protocol for universal food data.\n\nOne axiom. Three fields. Six base types. Every food industry operation.\n\n```json\n{\n  \"type\": \"substance.product\",\n  \"state\": { \"name\": \"Sourdough\", \"price\": 4.50, \"allergens\": { \"gluten\": true } },\n  \"refs\": { \"seller\": \"a1b2c3...\", \"inputs\": [\"flour_hash\", \"water_hash\", \"yeast_hash\"] }\n}\n```\n\n`id = SHA-256(canonical(type + state + refs))`\n\n## Why\n\nThe food industry spans 14 sectors — farming, processing, distribution, retail, hospitality, regulation, sustainability, and more. Every sector models food data differently. There is no shared primitive.\n\nFoodBlock is that primitive. One data structure that can represent a farm harvest, a restaurant menu item, a food safety certification, a cold chain reading, a grocery order, or a consumer review. Same three fields. Same hashing. Same protocol.\n\n## The Primitive\n\nEvery FoodBlock has exactly three fields:\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `type` | string | What kind of block (dot-notated subtypes) |\n| `state` | object | The block's data (schemaless, any valid JSON) |\n| `refs` | object | Named references to other blocks by hash |\n\nIdentity is derived from content: `SHA-256(canonical(type + state + refs))`. Same content always produces the same hash, regardless of where or when the block is created.\n\n## Six Base Types\n\n**Entities** — things that exist:\n- **actor** — farmer, restaurant, retailer, regulator, consumer, device\n- **place** — farm, factory, store, warehouse, kitchen, vehicle\n- **substance** — ingredient, product, meal, surplus, commodity\n\n**Actions** — things that happen:\n- **transform** — cooking, milling, harvesting, fermenting, composting\n- **transfer** — sale, shipment, donation, booking, subscription\n- **observe** — review, certification, inspection, post, sensor reading\n\nSubtypes via dot notation: `actor.producer`, `substance.product`, `observe.review`, `transfer.order`.\n\n## Install\n\n```bash\nnpm install foodblock\n```\n\n## Quick Start — `fb()`\n\nThe fastest way to use FoodBlock. Describe food in plain English, get structured blocks back.\n\n```javascript\nconst { fb } = require('foodblock')\n\nfb(\"Sourdough bread, $4.50, organic, contains gluten\")\n// => { type: 'substance.product', state: { name: 'Sourdough bread', price: { value: 4.5, unit: 'USD' }, organic: true, allergens: { gluten: true } }, blocks: [...] }\n\nfb(\"Amazing pizza at Luigi's, 5 stars\")\n// => { type: 'observe.review', state: { name: \"Luigi's\", rating: 5, text: \"...\" }, blocks: [...] }\n\nfb(\"Green Acres Farm, 200 acres, organic wheat in Oregon\")\n// => { type: 'actor.producer', state: { name: 'Green Acres Farm', acreage: 200, crop: 'organic wheat', region: 'Oregon' }, blocks: [...] }\n\nfb(\"Walk-in cooler temperature 4 celsius\")\n// => { type: 'observe.reading', state: { temperature: { value: 4, unit: 'celsius' } }, blocks: [...] }\n\nfb(\"Ordered 50kg flour from Stone Mill\")\n// => { type: 'transfer.order', state: { weight: { value: 50, unit: 'kg' } }, blocks: [...] }\n```\n\nNo types to memorize. No schemas to configure. No API calls — `fb()` is pure pattern matching, runs locally, costs nothing.\n\n## Programmatic API\n\n```javascript\nconst fb = require('foodblock')\n\n// Create a farm\nconst farm = fb.create('actor.producer', { name: 'Green Acres Farm' })\n// => { hash: 'e3b0c4...', type: 'actor.producer', state: {...}, refs: {} }\n\n// Create a product with provenance\nconst wheat = fb.create('substance.ingredient', { name: 'Organic Wheat' }, { source: farm.hash })\nconst flour = fb.create('substance.product', { name: 'Stoneground Flour' }, { source: wheat.hash })\nconst bread = fb.create('substance.product', {\n  name: 'Sourdough',\n  price: 4.50\n}, {\n  seller: bakery.hash,\n  inputs: [flour.hash, water.hash, yeast.hash]\n})\n\n// Update (creates new block, old one preserved)\nconst updated = fb.update(bread.hash, 'substance.product', {\n  name: 'Sourdough',\n  price: 5.00\n}, { seller: bakery.hash })\n// updated.refs.updates === bread.hash\n\n// Sign and verify\nconst keys = fb.generateKeypair()\nconst signed = fb.sign(bread, farm.hash, keys.privateKey)\n// signed.protocol_version === '0.4.0'\nconst valid = fb.verify(signed, keys.publicKey) // true\n\n// Provenance chain\nconst history = await fb.chain(updated.hash, resolve)\n// [{ price: 5.00 }, { price: 4.50 }] — newest to oldest\n\n// Validate against schema\nconst errors = fb.validate(bread)  // [] if valid\n\n// Tombstone (GDPR erasure)\nconst ts = fb.tombstone(bread.hash, user.hash, { reason: 'gdpr_erasure' })\n\n// Offline queue\nconst queue = fb.offlineQueue()\nqueue.create('transfer.order', { total: 12.00 }, { seller: farmHash })\nawait queue.sync('https://api.example.com/foodblock')\n\n// --- Human Interface ---\n\n// Aliases: use @names instead of hashes\nconst reg = fb.registry()\nconst myFarm = reg.create('actor.producer', { name: 'Green Acres' }, {}, { alias: 'farm' })\nconst myWheat = reg.create('substance.ingredient', { name: 'Wheat' }, { source: '@farm' })\n// '@farm' resolves to myFarm.hash automatically\n\n// FoodBlock Notation: one-line text format\nconst blocks = fb.parseAll(`\n@farm = actor.producer { \"name\": \"Green Acres Farm\" }\n@wheat = substance.ingredient { \"name\": \"Wheat\" } -> source: @farm\n`)\n\n// Explain: human-readable narrative from graph\nconst story = await fb.explain(bread.hash, resolve)\n// \"Sourdough ($4.50). By Green Acres Bakery. Made from Organic Flour (Green Acres Farm).\"\n\n// URIs: shareable block references\nfb.toURI(bread)                          // 'fb:a1b2c3...'\nfb.toURI(bread, { alias: 'sourdough' })  // 'fb:substance.product/sourdough'\n\n// --- Templates ---\n\n// Use built-in templates for common patterns\nconst chain = fb.fromTemplate(fb.TEMPLATES['supply-chain'], {\n  farm: { state: { name: 'Green Acres Farm' } },\n  crop: { state: { name: 'Organic Wheat' } },\n  processing: { state: { name: 'Stone Milling' } },\n  product: { state: { name: 'Flour', price: 3.20 } }\n})\n// Returns 5 blocks in dependency order, with @alias refs auto-resolved\n\n// Create custom templates\nconst myTemplate = fb.createTemplate('Bakery Review', 'Review a bakery product', [\n  { type: 'actor.venue', alias: 'bakery', required: ['name'] },\n  { type: 'substance.product', alias: 'item', refs: { seller: '@bakery' } },\n  { type: 'observe.review', alias: 'review', refs: { subject: '@item' }, required: ['rating'] }\n])\n\n// --- Federation ---\n\n// Discover another FoodBlock server\nconst info = await fb.discover('https://farm.example.com')\n// { protocol: 'foodblock', version: '0.4.0', types: [...], count: 142 }\n\n// Resolve blocks across multiple servers\nconst resolve = fb.federatedResolver([\n  'http://localhost:3111',\n  'https://farm.example.com',\n  'https://market.example.com'\n])\nconst block = await resolve('a1b2c3...')  // tries each server in order\n```\n\n## Sandbox\n\nTry it locally with zero setup:\n\n```bash\ncd sandbox\nnode server.js\n```\n\n```bash\n# List all blocks\ncurl localhost:3111/blocks\n\n# Filter by type\ncurl localhost:3111/blocks?type=substance.product\n\n# Get head blocks only (latest versions)\ncurl localhost:3111/blocks?type=substance.product&heads=true\n\n# Provenance chain\ncurl localhost:3111/chain/<hash>\n\n# Create a block\ncurl -X POST localhost:3111/blocks \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"type\":\"observe.review\",\"state\":{\"rating\":5,\"text\":\"Amazing\"},\"refs\":{\"subject\":\"<product_hash>\"}}'\n\n# Batch create (offline sync)\ncurl -X POST localhost:3111/blocks/batch \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"blocks\":[...]}'\n\n# Tombstone (content erasure)\ncurl -X DELETE localhost:3111/blocks/<hash>\n\n# Federation discovery\ncurl localhost:3111/.well-known/foodblock\n\n# List templates\ncurl localhost:3111/blocks?type=observe.template\n\n# Natural language entry point\ncurl -X POST localhost:3111/fb \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"text\":\"Sourdough bread, $4.50, organic, contains gluten\"}'\n\n# Forward traversal (what references this block?)\ncurl localhost:3111/forward/<hash>\n\n# Natural language → blocks\ncurl -X POST localhost:3111/fb \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"text\":\"Sourdough bread, $4.50, organic, contains gluten\"}'\n\n# List vocabularies\ncurl localhost:3111/blocks?type=observe.vocabulary\n```\n\nThe sandbox ships preloaded with 47 blocks modelling a complete bakery supply chain — from farm to consumer, including certifications, shipments, cold chain readings, reviews, and operational vocabularies.\n\n## API\n\n### `fb(text) → { blocks, primary, type, state, text }`\n\nThe natural language entry point. Pass any food-related text, get FoodBlocks back. Detects intent (product, review, farm, order, certification, reading, process, venue, ingredient), extracts quantities (price, weight, volume, temperature, rating), flags (organic, gluten-free, kosher, etc.), and relationships (\"from X\", \"at Y\", \"by Z\"). No LLM — pure regex pattern matching against built-in vocabularies.\n\n### `create(type, state, refs) → block`\n\nCreate a new FoodBlock. Returns `{ hash, type, state, refs }`.\n\n### `update(previousHash, type, state, refs) → block`\n\nCreate an update block that supersedes a previous version. Automatically adds `refs.updates`.\n\n### `hash(type, state, refs) → string`\n\nCompute the SHA-256 hash without creating a block object.\n\n### `chain(hash, resolve, opts) → block[]`\n\nFollow the update chain backwards. `resolve` is `async (hash) => block | null`.\n\n### `tree(hash, resolve, opts) → { block, ancestors }`\n\nFollow ALL refs recursively to build the full provenance tree.\n\n### `head(hash, resolveForward) → string`\n\nFind the latest version in an update chain.\n\n### `sign(block, authorHash, privateKey) → wrapper`\n\nSign a block with Ed25519. Returns `{ foodblock, author_hash, signature, protocol_version }`.\n\n### `verify(wrapper, publicKey) → boolean`\n\nVerify a signed block wrapper.\n\n### `generateKeypair() → { publicKey, privateKey }`\n\nGenerate a new Ed25519 keypair for signing.\n\n### `encrypt(value, recipientPublicKeys) → envelope`\n\nEncrypt a value for multiple recipients using envelope encryption (Section 7.2).\n\n### `decrypt(envelope, privateKey, publicKey) → value`\n\nDecrypt an encryption envelope.\n\n### `validate(block, schema?) → string[]`\n\nValidate a block against its declared schema or a provided schema. Returns an array of error messages (empty = valid).\n\n### `tombstone(targetHash, requestedBy, opts?) → block`\n\nCreate a tombstone block for content erasure (Section 5.4).\n\n### `offlineQueue() → Queue`\n\nCreate an offline queue for local-first block creation with batch sync.\n\n### `query(resolve) → Query`\n\nFluent query builder:\n\n```javascript\nconst results = await fb.query(resolver)\n  .type('substance.product')\n  .byRef('seller', bakeryHash)\n  .whereLt('price', 10)\n  .latest()\n  .limit(20)\n  .exec()\n```\n\n### `registry() → Registry`\n\nAlias registry for human-readable references. Use `@name` in refs instead of hashes.\n\n### `parse(line) → { alias, type, state, refs }`\n\nParse a single line of FoodBlock Notation (FBN).\n\n### `parseAll(text) → block[]`\n\nParse multiple lines of FBN.\n\n### `format(block, opts?) → string`\n\nFormat a block as FBN text.\n\n### `explain(hash, resolve) → string`\n\nGenerate a human-readable narrative from a block's provenance graph.\n\n### `toURI(block, opts?) → string`\n\nConvert a block to a `fb:` URI. `toURI(block)` → `fb:<hash>`, `toURI(block, { alias: 'name' })` → `fb:<type>/<alias>`.\n\n### `fromURI(uri) → object`\n\nParse a `fb:` URI into `{ hash }` or `{ type, alias }`.\n\n### `createTemplate(name, description, steps, opts?) → block`\n\nCreate a template block (`observe.template`) that defines a reusable workflow pattern.\n\n### `fromTemplate(template, values) → block[]`\n\nInstantiate a template into real blocks. `values` maps step aliases to `{ state, refs }` overrides. `@alias` references between steps are resolved automatically.\n\n### `TEMPLATES`\n\nBuilt-in templates: `supply-chain`, `review`, `certification`.\n\n### `discover(serverUrl, opts?) → info`\n\nFetch a server's `/.well-known/foodblock` discovery document.\n\n### `federatedResolver(servers, opts?) → resolve`\n\nCreate a resolver that tries multiple servers in priority order. Returns `async (hash) => block | null` with optional caching.\n\n### `createVocabulary(domain, forTypes, fields, opts?) → block`\n\nCreate a vocabulary block (`observe.vocabulary`) defining canonical field names, types, and natural language aliases for a domain.\n\n### `mapFields(text, vocabulary) → { matched, unmatched }`\n\nExtract field values from natural language text using a vocabulary's aliases. Returns matched fields and unmatched terms.\n\n### `VOCABULARIES`\n\nBuilt-in vocabulary definitions: `bakery`, `restaurant`, `farm`, `retail`, `lot`, `units`, `workflow`.\n\n### `quantity(value, unit, type?) → { value, unit }`\n\nCreate a quantity object. Validates unit against the `units` vocabulary if `type` is provided (e.g. `'weight'`, `'volume'`, `'temperature'`).\n\n### `transition(from, to) → boolean`\n\nValidate a workflow state transition against the `workflow` vocabulary's transition map (e.g. `draft→order` is valid, `draft→shipped` is not).\n\n### `nextStatuses(status) → string[]`\n\nGet valid next statuses for a given workflow status.\n\n### `localize(block, locale, fallback?) → block`\n\nExtract locale-specific text from multilingual state fields. Fields using `{ en: \"...\", fr: \"...\" }` nested objects are resolved to the requested locale.\n\n### `forward(hash, resolveForward) → { referencing, count }`\n\nFind all blocks that reference a given hash. Returns blocks grouped by ref role.\n\n### `recall(sourceHash, resolveForward, opts?) → { affected, depth, paths }`\n\nTrace contamination/recall paths downstream via BFS. Starting from a source block, follows all forward references recursively. Supports `types` and `roles` filters.\n\n### `downstream(ingredientHash, resolveForward) → block[]`\n\nFind all downstream substance blocks that use a given ingredient (convenience wrapper around `recall`).\n\n### `merkleize(state) → { root, leaves, tree }`\n\nBuild a Merkle tree from a state object for selective disclosure.\n\n### `selectiveDisclose(state, fieldNames) → { disclosed, proof, root }`\n\nReveal only specific fields with a Merkle proof that they belong to the block.\n\n### `verifyProof(disclosed, proof, root) → boolean`\n\nVerify a selective disclosure proof.\n\n### `merge(hashA, hashB, resolve, opts?) → block`\n\nCreate a merge block resolving a fork between two update chain heads.\n\n### `attest(targetHash, attestorHash, opts?) → block`\n\nCreate an attestation block confirming a claim. `opts.confidence`: `verified`, `probable`, `unverified`.\n\n### `dispute(targetHash, disputerHash, reason) → block`\n\nCreate a dispute block challenging a claim.\n\n### `trustScore(hash, allBlocks) → number`\n\nCompute net trust score: attestations minus disputes.\n\n### `createSnapshot(blocks, opts?) → block`\n\nSummarize a set of blocks into a snapshot with a Merkle root for archival verification.\n\n## The Axiom\n\n**A FoodBlock's identity is its content:** `SHA-256(canonical(type + state + refs))`.\n\nEverything follows from this:\n- **Immutability** — change content, change identity\n- **Determinism** — same content, same hash, anywhere\n- **Deduplication** — identical products resolve to one block\n- **Tamper evidence** — any modification is detectable\n- **Offline validity** — no server needed to create blocks\n- **Provenance** — refs form a directed graph of history\n\nSeven operational rules govern the protocol's use:\n\n1. A FoodBlock has exactly three fields: `type`, `state`, `refs`.\n2. Authentication: `{ foodblock, author_hash, signature, protocol_version }` using Ed25519.\n3. Encrypted state: `_` prefixed keys contain envelope-encrypted values.\n4. Author-scoped updates: only the original author or approved actor may create successors.\n5. Tombstones erase content while preserving graph structure.\n6. Schema declarations are optional.\n7. The protocol is open. No permission required.\n\n## Canonical JSON\n\nDeterministic hashing requires deterministic serialization. Aligns with [RFC 8785 (JSON Canonicalization Scheme)](https://tools.ietf.org/html/rfc8785) for number formatting and key ordering:\n\n- Keys sorted lexicographically at every nesting level\n- No whitespace between tokens\n- Numbers: no trailing zeros, no leading zeros. `-0` normalized to `0`.\n- Strings: Unicode NFC normalization\n- Arrays in `refs`: sorted lexicographically (set semantics)\n- Arrays in `state`: preserve declared order (sequence semantics)\n- Null values: omitted\n- Booleans: `true` or `false`\n\n## Database Schema\n\n```sql\nCREATE TABLE foodblocks (\n    hash             VARCHAR(64) PRIMARY KEY,\n    type             VARCHAR(100) NOT NULL,\n    state            JSONB NOT NULL DEFAULT '{}',\n    refs             JSONB NOT NULL DEFAULT '{}',\n    author_hash      VARCHAR(64),\n    signature        TEXT,\n    protocol_version VARCHAR(10) DEFAULT '0.3',\n    chain_id         VARCHAR(64),\n    is_head          BOOLEAN DEFAULT TRUE,\n    created_at       TIMESTAMP DEFAULT NOW()\n);\n```\n\nFull schema with indexes, author-scoped head trigger, and tombstone trigger: [`sql/schema.sql`](sql/schema.sql)\n\n## Cross-Language Test Vectors\n\n[`test/vectors.json`](test/vectors.json) contains 30 known inputs and expected hashes — including tombstone blocks, schema references, vocabulary blocks, attestation blocks, merge blocks, RFC 8785 number edge cases, and more. Any SDK in any language must produce identical hashes for these inputs. If JavaScript and Python disagree, the protocol is broken.\n\n## Project Structure\n\n```\nfoodblock/\n├── spec/whitepaper.md           Protocol specification (v0.4)\n├── sdk/javascript/              JavaScript SDK (reference implementation)\n│   ├── src/                     block, chain, verify, encrypt, validate, offline, tombstone,\n│   │                            alias, notation, explain, uri, template, federation,\n│   │                            vocabulary, forward, merge, merkle, snapshot, attestation\n│   └── test/                    Test suite (104 tests)\n├── sdk/python/                  Python SDK\n│   ├── foodblock/               block, chain, verify, validate, tombstone,\n│   │                            alias, notation, explain, uri, template, federation,\n│   │                            vocabulary, forward, merge, merkle, snapshot, attestation\n│   └── tests/                   Test suite (80 tests)\n├── sdk/go/                      Go SDK\n│   └── foodblock.go             block, chain, sign/verify, tombstone\n├── sdk/swift/                   Swift SDK\n│   └── Sources/                 block, tombstone\n├── mcp/                         MCP server for AI agent integration (15 tools)\n├── sandbox/                     Local sandbox server\n│   ├── server.js                Zero-dependency HTTP API + federation discovery\n│   └── seed.js                  47-block bakery chain + templates + vocabularies\n├── sql/schema.sql               Postgres schema + triggers\n├── test/vectors.json            Cross-language test vectors (30 vectors)\n└── LICENSE                      MIT\n```\n\n## Sector Coverage\n\nThe six base types cover all fourteen food industry sectors:\n\n| Sector | Key Types |\n|--------|-----------|\n| Primary Production | `actor.producer`, `place.farm`, `transform.harvest` |\n| Processing | `actor.maker`, `transform.process`, `observe.inspection` |\n| Distribution | `actor.distributor`, `transfer.shipment`, `observe.reading` |\n| Retail | `substance.product`, `transfer.order` |\n| Hospitality | `actor.venue`, `transfer.booking`, `observe.review` |\n| Food Service | `observe.plan`, `transform.process` |\n| Waste & Sustainability | `actor.sustainer`, `substance.surplus`, `transfer.donation` |\n| Regulation | `actor.authority`, `observe.certification` |\n| Education & Media | `actor.creator`, `observe.post` |\n| Community | `actor.group`, `observe.event` |\n| Health & Nutrition | `actor.professional`, `observe.assessment` |\n| Finance | `transfer.investment`, `observe.market` |\n| Cultural Food | `observe.certification`, `place.region` |\n| Food Technology | `actor.innovator`, `observe.experiment` |\n\n## License\n\nMIT — use it however you want.\n\n## Links\n\n- [Whitepaper](spec/whitepaper.md) ([PDF](spec/whitepaper.pdf))\n- [Technical Specification](spec/technical-whitepaper.md) ([PDF](spec/technical-whitepaper.pdf))\n- [Test Vectors](test/vectors.json)\n- [Schema](sql/schema.sql)\n- [MCP Server](mcp/README.md)\n",
  "bytes": 20297,
  "sha": "28265df812383c0577836077196a96a6ff6ee5a5858fe203a6f4773a183fff35",
  "repo_slug": "foodxdevelopment/foodblock",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_foodxdevelopment_foodblock_mcp_1d409158/readme"
}