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 == 0in a creating action makes "create twice" impossible;+ 1on each change makes history readable. - Record who did what.
reviewed_by,approved_by,paid_byare cheap and answer most questions later. - Money in minor units (
amount_minor: Int) with acurrencyfield 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
andchains give vague refusals. - Make states explicit. A
statuswith a few known values, and actions that check the current one (state.status == "approved"beforePay), is the clearest workflow. - Use delegation for organisations. Take
owner,writerand adelegationargument, and observe it (seestd.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
mergefor every action you expect from several devices. The defaultexclusiveis 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 withref > $afterandtake 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.