DHL best practices

Model

  • One record per thing that changes on its own. A list and its items, an order and its lines: separate records, linked by references. They merge and scale better.
  • Give each record a stable ref. Derive the subject from something natural (the supplier and invoice number), so the same invoice received twice is recorded once.
  • Keep a revision. state.revision == 0 in a creating action makes "create twice" impossible; + 1 on each change makes history readable.
  • Record who did what. reviewed_by, approved_by, paid_by are cheap and answer most questions later.
  • Money in minor units (amount_minor: Int) with a currency field beside it.

Rules

  • Check the signer in every action. context.signer == writer, and that the writer may act on this record (writer == state.owner, or a delegation it observes).
  • Write one condition per validation line. Each line becomes a rule with its own refusal message; long and chains give vague refusals.
  • Make states explicit. A status with a few known values, and actions that check the current one (state.status == "approved" before Pay), is the clearest workflow.
  • Use delegation for organisations. Take owner, writer and a delegation argument, and observe it (see std.business.payable), rather than trusting whoever signs.
  • Refuse past an end. If a grant or an offer can expire, compare with context.clock.milliseconds.

Sync and durability

  • Declare merge for every action you expect from several devices. The default exclusive is safe but turns every concurrent change into a conflict.
  • Never buffer money, stock, identity or approvals — the compiler enforces it, but design for it from the start.

Queries

  • Filter by owner first (where owner == $owner), sort by a stable key and page with ref > $after and take 100.
  • Return a row struct with subject as id, so clients and your accomplice can act on a row.

People

  • Write prose around the blocks. A contract is read by people (and your accomplice) deciding what it allows.
  • Add a UI file for labels, money, statuses and refusal sentences. It costs nothing to the rules.
  • Try both sides in the Workbench: an accepted step and a refused one for every rule.