Changes and records
A Startup changes its definitions through Changes and writes its facts directly; both run as Actions, and nothing is ever purged.
A Startup writes in two ways: a Change for its definitions, and a direct write for its facts. Both run as Actions, and no write ever purges a record.
Two ways to write
| What | Written by | Examples |
|---|---|---|
| Definitions | A Change, reviewed and merged | Offers, Pages, Templates, Permissions, Nouns, Verbs, Policies, code |
| Facts | A direct write, one Action each | Contacts, Orders, Leaseline's Lease records, Events, Tasks |
Where the line falls is a Setting per Noun. Two writes always go through a Change, whatever the Setting says: widening a Permission and moving money.
A Change
A Change is drafted against a base Version. Its branch holds only the rows it touches, and its preview reads them over live data. Leaseline sees a new notice on its real Lease records before any resident does.
import { $ } from 'startup-builder'
await $.Change.review({ change: 'change_3Ex8uVSOyQ' })
const { version } = await $.Change.merge({ change: 'change_3Ex8uVSOyQ' })- Change.review runs every Evaluator on the preview. A Change above the Startup's stakes threshold waits for an Approval; a low-stakes Change merges without one.
- Change.merge is three-way and field-level. A field changed on both sides since the base sends the Change back to review. A definition changed on both sides waits for a rebase.
- Change.revert writes a new Change and a superseding Decision. Nothing is deleted.
Versions
A Version is an immutable build of a definition at a fingerprint. Which Version serves is a pointer that merge and Version.deploy move. An Order keeps the Offer Version it bought, so a price change never rewrites a past sale.
Records
A fact is written with the Thing Verbs that every Noun inherits: create, get, list, update and delete.
- A write may name
ifVersion, the Version of the Thing it read, sent asIf-Matchon the API. When the Thing has moved past it, the write is refused and nothing changes. - Every durable write takes an idempotency key, so a retry runs the Verb once.
- A delete is soft. The Thing leaves every list and keeps its history, and
Thing.restorebrings it back. - Action.undo removes the records a done Action created, each restorable. Money returns through a new Action, such as a refund.
Further shapes
Each shape below has status planned, so an agent never offers it.
| Shape | What it adds |
|---|---|
Change.ops, Change.write | Typed operations on paths: set, add, remove, rename, move. A rename rewrites every reference, and a batch that changes nothing writes no Version |
| Version history | parent, author, source, ops, changes, issues and actionId on every Version |
Version.compare | A field-by-field diff of two Versions, in the words a founder reads |
Change.revert by path | paths and toVersion: restore part of a definition to an earlier Version |
| Field preconditions | An expected value per field; a stale write answers 409 with the current value and who changed it |
| Insert once | A create with a fixed id that returns inserted: or false |
| Delete preview | Thing.delete honors each Relationship's onDelete and previews what it removes; list takes a deleted filter |
| Field diffs | Each Event carries the fields it changed, from and to |
| Number floors | An auto-number is never given twice, even after a delete |
| Partial apply | A Change applies its fresh writes, skips the stale ones and expires at expiresAt |
| Guarded Noun edits | Noun.update refuses to remove a field another Noun, Verb or Workflow still reads |