fabbr@site:~/projects/magellan/contract$

contract

// ~/projects/magellan/contract.ts
const contract = {
  status: "active",
  started: "2026-09-20",
  tags: ["typescript", "zod", "openapi"],
  repo: "https://github.com/fabbrito/magellan-cloud/tree/master/packages/contract",
};

The device and the cloud live in separate repositories, built and deployed apart. They share no code and no database. What they share is the contract: three routes, a manifest, a batch and a heartbeat.

clouddeviceloop[readings queued]loop[hourly]PUT manifestits hashPOST batchstatus classPOST heartbeat

Why one seam

Each side can change freely as long as the contract holds. The device can be rewritten without a cloud deploy, and the cloud can change its storage without touching a board in the field.

Decisions

  • Written once, read twice. The cloud defines the contract, and publishes a document derived from the code that actually parses it. The device reads that document and writes its own parser. Generating one side from the other would make a wrong shape look right to both.
  • The answer is the policy. The device reads only the class of a reply: committed, rejected, or try again later. Outage handling is part of the contract, not something each side guesses at.
  • Exact numbers. A value travels as a whole number plus a decimal scale, the way money does, so nothing is rounded between the sensor and the chart.
  • One way only. Data flows from device to cloud. No remote commands, no configuration push.