OpenStampsfor industry

Declare the requirement first. The receipt cannot skip a check.

A buyer writes down what a submission must contain, as a small versioned policy in a closed vocabulary. The supplier submits originals. The receipt names the policy and its digest, every input's digest, every attempted check with its outcome, what was missing and what only a person can decide. The policy travels inside the receipt, so a reader sees what was asked, not only what was found, and a second reader can replay the checks offline.

What a receipt establishes: that these checks ran against this policy and these bytes, with these outcomes. What it does not establish: that an undisclosed document exists, that any declaration in a record is true, or who submitted the pack. A stamp fixes bytes and a time bracket, not the truth of what a record says. Faces: ◆ produced · ◔ not checked · ◇ not refuted · ✕ refuted.

  1. Open the labelled sample: a real stamped harvest record, a synthetic permit that names another supplier, a shipment. Read the receipt.
  2. Replace the permit with the corrected one. The checks that read the permit run again, and so does freshness, which reads the clock; the rest are carried and marked. The first receipt stays in the list.
  3. Export the receipt as JSON. Each receipt in the list also exports the pack it was made from.
  4. Replay it in a second reader: the receipt and its pack go back in, the checks run again, and the page says whether the findings are the same.

Replay in a second reader

Give this reader an exported receipt and the pack it was made from. It re-runs the receipt's own embedded policy against the pack, on this device, at the receipt's evaluation time, and compares check by check. A different outcome, a different input digest or a policy that no longer digests to the receipt's digest is a difference.

Your own files

A policy in the vocabulary (the sample policy is the template) and a pack in the openstamps-unit/1 shape (the sample pack). Both stay on this device; nothing is uploaded. Envelopes are checked with the same offline engine the verify page uses.

The vocabulary ten kinds, no code

A policy is { schema: "osfp-acceptance-policy/1", id, version, title, notice?, requires: [ … ] }. Each requirement has a unique slug id, a kind, an optional title for a person, and only the fields its kind allows.

record code — the record is present; if stamped, its envelope must hold and bind the original bytes.
field code, path, pattern? — a non-empty value at a dotted path; pattern is one of date, iso2, nonempty.
consistency code, path, otherCode, otherPath — the two values are equal.
freshness code, maxAgeDays — capturedAt within that many days of the evaluation.
binding code — the stamp holds and its digest is the digest of the submitted original.
human title, code? — a person decides; always ◔ and listed under unsupported.
geo-in-country code, country, bbox? — the plot's declared country is the one the policy requires. ⚠ It compares a declaration: no border geometry is held here, so ◇ never means "the plot is in that country". Give a bbox — [minLon, minLat, maxLon, maxLat], your own declared bound, digested with the policy — and a coordinate outside it is ✕. Outside a box is outside the country; inside a box is only not contradicted.
date-order code, path, otherCode, otherPath — the first date is at or before the second. A date this reader cannot order is ✕.
in-list code, path, values — the value is one of the values the policy names.
attachment-digest code, path — the SHA-256 the record names belongs to bytes actually submitted in the pack, digested here. A station's own sha256 field never counts: that is the publisher's claim, and a claim cannot corroborate itself.

Every requirement appears in the receipt once, in policy order. The policy travels inside the receipt with its digest.

Source