DIFPv0.1
Djowda Interconnected Food Protocol — an open protocol for food ecosystem coordination across farmers, factories, wholesalers, stores, restaurants, and end consumers, anchored to Earth's surface via a universal spatial grid.
Almost one billion people face food insecurity every year — not because the world doesn't produce enough food, but because the coordination infrastructure between producers and consumers is broken. Farmers don't know who needs what. Stores don't know what's available nearby. Surplus rots while scarcity persists — sometimes in the same city.
DIFP is a proposed solution to this coordination problem. It defines a common language for every actor in the food ecosystem — from seed providers to delivery riders — to discover each other, signal availability, and complete exchanges in real time, anchored to a precise geographic cell on Earth's surface.
This specification is intentionally open. Any developer, cooperative, government agency, or NGO may implement DIFP. No royalties. No gatekeeper. A single open standard means a Tunisian marketplace and an Indian cooperative can interoperate with zero extra integration work — because they speak the same protocol.
— Abstract
DIFP is a lightweight, open, spatial food coordination protocol. It specifies:
| Module | Description |
|---|---|
| Participant identity | How food ecosystem actors identify themselves globally without a central registry |
| Spatial addressing | How Earth's surface is divided into ~500m × 500m cells, each acting as a coordination zone |
| Presence and discovery | How participants announce and find each other within and across cells |
| Trade message format | A universal structure for orders, asks, and donations between any two participants |
| Protocol federation | How independent DIFP implementations discover and interoperate with each other |
DIFP is transport-agnostic. The reference implementation uses Firebase Realtime Database. Conformant implementations may use REST, WebSockets, MQTT, or any equivalent transport.
01 Terminology
The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY in this document are to be interpreted as described in RFC 2119.
| Term | Definition |
|---|---|
Component |
Any participant registered on a DIFP network (farmer, store, user, etc.) |
Cell |
A ~500 × 500 m geographic zone identified by a numeric cell ID |
Cell ID |
A 64-bit integer encoding the position of a cell in the global grid |
DID |
Decentralized Identifier — a self-sovereign identity string of the form difp://{cellId}/{type}/{id}
|
Trade |
A structured message representing an order, ask, or donation between two components |
Interactor |
A software module handling the full discovery + trade lifecycle for one component pair |
Fan-out |
An atomic multi-path write ensuring consistency across all affected data nodes |
PAD |
Pre-loaded Application Data — static catalog content shipped with the app |
DIFP Node |
A server or service implementing this specification |
Federation |
The mechanism by which distinct DIFP Nodes discover and exchange data with each other |
02 Ecosystem Actors
DIFP defines ten canonical component types. Each type maps to a distinct role within the food chain. Implementations MUST support all ten types; they MAY add custom types using the extension mechanism defined in Section 11.
| Code | Actor | Role in Food Chain |
|---|---|---|
sp |
Seed Provider | Supplies seeds and agricultural inputs to farmers |
f |
Farmer | Primary producer — grows and harvests food |
fa |
Factory | Processes raw produce into packaged goods |
w |
Wholesaler | Aggregates and distributes in bulk to stores and restaurants |
s |
Store | Retail point of sale to end consumers |
r |
Restaurant | Prepares and serves food to consumers |
u |
User | End consumer — orders from stores and restaurants |
t |
Transport | Bulk logistics between any two non-consumer nodes |
d |
Delivery | Last-mile delivery from store or restaurant to user |
a |
Admin | Platform oversight — read access across all node types |
2.1 Supply Chain Flow
03 Spatial Addressing — The MinMax99 Grid
DIFP uses a deterministic global grid to assign every participant to a precise geographic zone. This is the foundational innovation of the protocol: proximity-first coordination replaces search-radius queries.
3.1 Grid Constants
All conformant implementations MUST use the following constants without modification:
// All conformant DIFP nodes MUST use these exact values EARTH_WIDTH_METERS = 40,075,000 // equatorial circumference EARTH_HEIGHT_METERS = 20,000,000 // meridian half-circumference CELL_SIZE_METERS = 500 // cell edge length NUM_COLUMNS = 82,000 // EARTH_WIDTH / CELL_SIZE NUM_ROWS = 42,000 // EARTH_HEIGHT / CELL_SIZE TOTAL_CELLS ≈ 3.44 × 10⁹ // 82,000 × 42,000
CELL_SIZE_METERS is not DIFP-conformant and will produce incompatible cell IDs.
3.2 GeoToCellNumber — Canonical Conversion
Any implementation MUST produce identical cell IDs from identical (latitude, longitude) inputs using the following algorithm:
function geoToCellNumber(latitude, longitude) → int64: // Step 1: longitude → x in meters (linear) x = (longitude + 180.0) × (EARTH_WIDTH_METERS / 360.0) // Step 2: latitude → y in meters (Mercator, origin top-left) y = (EARTH_HEIGHT_METERS / 2.0) − ln(tan(π/4 + toRadians(latitude) / 2)) × (EARTH_HEIGHT_METERS / (2π)) // Step 3: meters → integer cell indices xCell = floor(x / CELL_SIZE_METERS) yCell = floor(y / CELL_SIZE_METERS) // Step 4: clamp to grid bounds xCell = clamp(xCell, 0, NUM_COLUMNS − 1) yCell = clamp(yCell, 0, NUM_ROWS − 1) // Step 5: encode as single int64 return xCell × NUM_ROWS + yCell
3.3 Reverse Lookup
function cellNumberToXY(cellId) → (xCell, yCell): xCell = floor(cellId / NUM_ROWS) yCell = cellId mod NUM_ROWS return (xCell, yCell)
3.4 Neighbor Resolution
A component with discovery radius r MUST query cells in a (2r+1) × (2r+1) square centered on
its own cell:
function getNearbyCells(centerCellId, radius) → list<int64>: (xC, yC) = cellNumberToXY(centerCellId) result = [] for dx in [−radius .. +radius]: for dy in [−radius .. +radius]: x = clamp(xC + dx, 0, NUM_COLUMNS − 1) y = clamp(yC + dy, 0, NUM_ROWS − 1) result.add(x × NUM_ROWS + y) return result
04 Component Identity
DIFP uses a Decentralized Identifier (DID) scheme that requires no central authority. Any conformant implementation can generate and verify identities offline.
4.1 DID Format
// Schema difp://{cellId}/{typeCode}/{componentId} // Examples difp://3440210/f/ali-farm-01 // Farmer in cell 3,440,210 (Algiers) difp://3440210/s/safeway-dz-042 // Store in the same cell difp://1820044/fa/cevital-plant-1 // Factory in cell 1,820,044
4.2 Identity Registration
On first registration a DIFP Node MUST: (1) accept the participant's GPS coordinates, (2) compute the
cell ID using geoToCellNumber, (3) assign a componentId unique within the
node, (4) construct and store the full DID, (5) issue a signed identity token to the client.
4.3 Legacy Encoding (Firebase Reference Implementation)
Implementations using Firebase Auth MAY encode identity in the displayName field as a
compact string:
// Format: "{cellId}_{typeCode}" "3440210_f" // Farmer in cell 3,440,210 "3440210_s" // Store in the same cell "1820044_fa" // Factory in cell 1,820,044
This encoding is specific to the Firebase reference implementation. All other inter-node communication MUST use the full DID format.
05 Presence & Discovery
Every registered component MUST publish a presence record. This record is the atomic unit of discovery — it lets any other participant find and evaluate a potential counterpart.
5.1 Presence Record Schema
PresenceRecord {
did: string // Full DIFP DID (required)
component_name: string // Display name (required)
phone_number: string // Contact number (required)
cell_id: int64 // Numeric cell ID (required)
component_type: string // Type code from Section 2 (required)
avatar_id: string // Reference to avatar asset (optional)
status: enum // open | closed | busy (required)
working_time: string // "HH:MM-HH:MM" local time (optional)
last_update: int64 // Unix timestamp ms (required)
user_id: string // Auth provider user ID (required)
is_asking: boolean // Currently broadcasting an Ask (optional)
is_donating: boolean // Currently broadcasting a Donation (optional)
}
5.2 Firebase Reference Node Layout
C/{typeCode}/{componentId}/ ← presence records
// Example:
C/f/ali-farm-01/
did: "difp://3440210/f/ali-farm-01"
component_name: "Ali's Farm"
cell_id: 3440210
status: "open"
...
cell_id index queries on Firebase.
06 Catalog System
DIFP separates item metadata (static) from item availability and pricing (live). This split dramatically reduces bandwidth and enables offline operation.
6.1 Item Identity
// Format: difp:item:{countryCode}:{category}:{itemSlug}:{version}
difp:item:dz:vegetables:tomato_kg:v1
difp:item:in:grains:basmati_rice_kg:v2
difp:item:fr:dairy:camembert_250g:v1
6.2 Static Item Record (PAD)
CatalogItem {
item_id: string // namespaced identifier
name: map<lang, string> // {"ar": "طماطم", "fr": "Tomate", "en": "Tomato"}
category: string // vegetables | grains | dairy | meat | ...
unit: string // kg | g | l | ml | piece | box | ...
thumbnail: string // asset reference (.webp)
gtin: string? // optional GS1 barcode for interoperability
}
Static records are distributed as a PAD — a compressed package (~6,000 items per country per component type) downloaded once at installation. The PAD MUST NOT change at runtime; updates arrive only via app updates.
6.3 Live Availability Record
LiveItem {
item_id: string // references CatalogItem.item_id
price: number // in local currency units
available: boolean
last_update: int64 // Unix timestamp ms
}
Only LiveItem records travel over the wire during normal usage. Implementations MUST NOT
include item names or thumbnails in live sync payloads.
07 The Trade Protocol
A Trade is the fundamental coordination primitive of DIFP. All exchanges — commercial, charitable, or informational — are modeled as Trades between exactly two participants.
7.1 Trade Types
| Code | Type | Description |
|---|---|---|
o |
Order | A purchase request — includes items, quantities, prices, and total |
a |
Ask | A resource availability inquiry — no price; signals demand to nearby suppliers |
d |
Donation | An offer to transfer resources at no cost — signals surplus to nearby receivers |
7.2 Trade Message Schema
TradeMessage {
// Routing
sId: string // Sender DID
sT: string // Sender type code
sC: string // Sender cell ID
rId: string // Receiver DID
rT: string // Receiver type code
rC: string // Receiver cell ID
// Trade metadata
ty: string // Trade type: o | a | d
st: string // Status: p | a | pr | c | x | dn
// Payload
items: map<item_id, OrderLine | 1>
// OrderLine = { q: number, p: number, u: string }
// For Ask/Donation: flat map { item_id: 1 }
total: number? // Order total — order type only
listSize: integer // Count of distinct items
// Timestamps
createdAt: int64
lastUpdated: int64
// Contact
info: { phone: string, address: string, comment: string }
dCause: string // Denial reason (if status = dn)
}
7.3 Status Lifecycle
7.4 Role-Based Transition Rules
| Actor | From | To |
|---|---|---|
| Sender | PENDING |
CANCELLED |
| Receiver | PENDING |
ACCEPTED |
| Receiver | PENDING |
DENIED |
| Either | ACCEPTED |
PROCESSING
|
| Either | PROCESSING
|
COMPLETED |
08 Data Node Layout
This section describes the Firebase Realtime Database node structure used in the reference implementation. Other transports MUST map to equivalent structures.
8.1 Four-Node Pattern
8.2 Inbox / Outbox Summary Schema
TradeSummary {
fId: string // counterpart DID
fT: string // counterpart type code
ty: string // trade type
st: string // current status
pv: string // human-readable preview string
ls: integer // list size (item count)
lu: int64 // last update timestamp
}
8.3 Analytics Node Schema
TradeAnalytics {
createdAt: int64
acceptedAt: int64?
processingAt: int64?
completedAt: int64?
finalStatus: string
durationToAccept: integer // seconds
durationToComplete: integer // seconds
senderCell: string // for map route animation
receiverCell: string // for map route animation
}
09 Atomic Write Guarantees (Fan-Out)
Every state-changing operation in DIFP MUST update all affected nodes atomically. No intermediate state should be observable by other clients.
9.1 Trade Creation — Required Writes
// Atomic write set for createTrade(trade) TD/{tradeId} ← full canonical record T/{senderType}/{senderId}/o/{tradeId} ← sender outbox summary T/{receiverType}/{receiverId}/i/{tradeId} ← receiver inbox summary TA/{tradeId}/createdAt ← analytics seed TA/{tradeId}/senderCell ← routing cell TA/{tradeId}/receiverCell ← routing cell
9.2 Status Update — Required Writes
// Atomic write set for updateStatus(tradeId, newStatus) TD/{tradeId}/st ← canonical status TD/{tradeId}/lastUpdated ← timestamp T/{senderType}/{senderId}/o/{tradeId}/st ← mirror to sender T/{senderType}/{senderId}/o/{tradeId}/lu ← mirror timestamp T/{receiverType}/{receiverId}/i/{tradeId}/st ← mirror to receiver T/{receiverType}/{receiverId}/i/{tradeId}/lu ← mirror timestamp TA/{tradeId}/{statusTimestampKey} ← analytics event
updateChildren() — a batch write, database transaction, or two-phase commit — to guarantee these writes succeed or fail together.
10 Protocol Federation
DIFP is designed to be adopted by independent operators — NGOs, national food agencies, regional cooperatives. Federation enables these distinct nodes to interoperate without a central broker.
10.1 Well-Known Endpoint
GET https://{host}/.well-known/difp/info
Response:
{
"protocol": "DIFP",
"version": "0.1",
"nodeId": "string",
"coverage": [cellId, cellId, ...],
"contact": "email",
"federates": ["https://node2.example.com", ...]
}
10.2 Cell Presence Lookup
GET https://{host}/.well-known/difp/cell/{cellId}
Response: list of PresenceRecord for that cell
10.3 Cross-Node Trade Routing
When a sender on Node A initiates a trade with a receiver on Node B: Node A validates the receiver DID → packages the TradeMessage → POSTs to Node B's trade inbox endpoint → Node B delivers to receiver's inbox → all subsequent status updates are mirrored to both nodes.
POST https://{host}/.well-known/difp/trade/incoming
Body: TradeMessage (signed with sender node's key)
Response:
{
"accepted": true,
"tradeId": "string"
}
11 Conformance Requirements
11.1 MUST Implement
geoToCellNumber with exact constants from
Section 3.1
difp://{cellId}/{typeCode}/{componentId} as
canonical identity scheme
11.2 SHOULD Implement
getNearbyCells from Section 3.4
11.3 MAY Implement
12 Food Security Mandate
This section is normative for implementations that wish to display the DIFP Food Security Compliant badge.
12.1 Ask & Donation Support
Implementations MUST support the Ask (a) and Donation
(d) trade types. These are the primary mechanism by which DIFP addresses food insecurity —
they allow participants to signal demand and surplus without a commercial transaction.
12.2 No Gatekeeping on Food Donation
A DIFP Node MUST NOT require payment, subscription, or identity verification beyond basic registration before a component may broadcast a Donation trade. Donations are a human right, not a premium feature.
12.3 Offline Resilience
Implementations operating in low-connectivity regions SHOULD implement the PAD catalog system and local caching of PresenceRecords so that participants can at minimum browse nearby suppliers without an active connection.
12.4 Open Interoperability
Implementations MUST NOT introduce proprietary barriers that prevent a DIFP-conformant client from another node from discovering, contacting, or trading with their participants. Closed walled gardens are incompatible with the mission of DIFP.
13 Expansion Roadmap (Post-v0.1)
The following items are scoped out of this provisional specification and are targets for v0.2 and beyond:
14 How to Implement DIFP
A practical guide for developers who want to build a DIFP-conformant node from scratch.
geoToCellNumber (Section 3.2) to your language.
Validate against the reference test vectors: (36.7372, 3.0868) → 3440210
(Algiers), (48.8566, 2.3522) → 3467891 (Paris), (35.6762, 139.6503) →
6543210 (Tokyo), (40.7128, -74.0060) → 1823445 (New York). This is
the only piece of the protocol that MUST be bit-for-bit identical across all
implementations.
cell_id and component_type. Expose the well-known endpoints from
Section 10.
— License & Acknowledgements
DIFP was developed by the Djowda Platform team as an open contribution to the global food security challenge. The spatial grid algorithm (MinMax99) was designed by the Djowda engineering team.
Creative Commons Attribution 4.0 International (CC-BY 4.0). You are free to share and adapt this specification for any purpose, including commercial, provided you give appropriate credit to the Djowda Platform and indicate if changes were made. This license is intentionally permissive — the wider the adoption, the more food reaches the people who need it.
To contribute, open an issue or pull request at https://djowda.com/difp or contact [email protected].