v2026.10.15
Quotes, invoices, payments and receipts are also kept as rows, and each is checked to the cent against what was issued.
AI agents and tools can read these release notes as plain Markdown.
This release covers 62 pull requests.
Highlights
- Quotes, invoices, payments and receipts are also kept as rows, and each is checked to the cent against what was issued. (#8, #11, #33)
- An invoice takes its number (INV-YYYY-M-N) when it is finalised, and an issued invoice is corrected by a credit note and a new invoice, never changed in place. (#39, #45, #47)
- One email can carry several issued documents, Send can be undone for 10 seconds, and the job lists every email as it went out. (#59, #64, #67, #69)
- Sentry reports errors, frustration and slow screens, and it never receives customer data, document numbers or money amounts. (#42, #62, #83)
- Owners connect Field to their own Xero app with a 4-step wizard in Settings, Integrations, and each issued invoice makes a matching draft in Xero with Field's PDF. (#94, #96, #107, #115, #132, #134)
- Milestone defaults and caps come from account rules by region and contract value. (#106)
- Field publishes verifiable releases to npm, GHCR and GitHub Releases, and an operator can run a pinned release that refuses to install unless it verifies. (#120, #121, #136)
Changes
- The business profile comes from configuration, so a production installation can deploy from this repository. (#9)
- Every quote version is also rows, verified to the cent. (#8)
- Quote documents and totals come from the quote rows. (#11)
- Issued documents can also be kept in a locked R2 bucket. (#13)
- The business trading name is optional; documents use the legal name without one. (#23)
- Invoices, payments and receipts are also rows, verified against what was issued. (#33)
- Sentry reports every error, frustration and slow screen without customer data. (#42)
- Invoices are issued from the sequence (INV-YYYY-M-N) when they are finalised. (#39)
- An issued invoice is corrected by a credit note and a new invoice, never revised in place. (#45)
- Milestone invoices are tax invoices with one claim line per milestone; receipts take RCT-YYYY-M-N. (#47)
- One email carries several of the job's issued documents, by uid. (#59)
- The email composer follows Field's design system, with a preview built by the send. (#64)
- Send can be undone for 10 seconds, drafts are kept on the server, and the job lists every email as it went out. (#67)
- Replacement invoices attach their adjustment note by default, and follow-ups join the earlier Gmail conversation. (#69)
- Owners settle legacy invoice amounts on a screen, not the browser console. (#88)
- Owners connect Field to their own Xero app in Settings, Integrations. (#94)
- A Replit publish only builds a commit that passed GitHub CI, and main requires passing checks. (#111)
- Issued invoices create matching drafts in the owner's Xero, with Field's PDF. (#96)
- Field's invoice prints its job and quote, as its Xero invoice's reference does. (#107)
- Owners enter integration credentials in Settings, stored encrypted per organisation. (#115)
- A new installation has no business identity by default. (#123)
- Field publishes verifiable CalVer releases to npm, GHCR and GitHub Releases. (#120)
- Operators run a pinned Field release that refuses to install unless it verifies. (#121)
- FIELD_SECRETS_KEY can be a 40-character password from a password generator. (#126)
- Field's releases are named and channelled as openclaw/openclaw's are. (#136)
- Connect Xero is a 4-step wizard that makes the encryption key in the browser. (#132)
- Settings, Integrations is a catalogue of cards; Xero opens its wizard or Configure. (#134)
- Milestone defaults and caps come from account rules by region and contract value. (#106)
Fixes
- GST rounds up on exactly half a cent. (#3)
- Databases sharing a PostgreSQL server migrate at the same time. (#5)
- A catalogue write queued behind another reads the clock after it. (#19)
- Npm installs from the lockfile's URLs, so Replit builds don't 404. (#25)
- The jobs board shows each quote's real total. (#31)
- Every job on disk appears on the jobs board. (#34)
- The Replit workspace pulls main without a GitHub token. (#37)
- Production backfills quote and invoice rows at boot, and owners dry-run data migrations in the app. (#38)
- Sentry never receives a request's query string from a traced request. (#62)
- Legacy invoices take the amounts Field emailed, and an owner settles the rest. (#61)
- Scripts/backfill-db.js runs again, importing server/db/job-backfill.js. (#49)
- Sentry no longer receives document numbers or money amounts. (#83)
- People can pinch-zoom Field on a phone. (#85)
- Scripts/backfill-db.js --apply refuses Field's own database. (#53)
- An owner can settle a superseded legacy invoice that was paid after its revision. (#86)
- The invoice backfill takes a missing issue time from the job's records, and the dry run shows why a milestone is refused. (#90)
- A Replit publish deploys GitHub main, not the workspace files. (#92)
- Email rendering and the client have no known high advisory in shipped code, and Dependabot raises updates. (#95)
- The jobs board answers when one job's files cannot be read in time. (#109)
- Reading a job no longer re-hashes every file of every generation it has. (#110)
- Publish fetches arcforgelabs/field, the repository's new home, not the old name's redirect. (#114)
Contribution record
CHANGELOG/records/2026.10.15.md lists every pull request in this release once, with its related issues and thanks.