From 33e0a5188264508dd042e5204b5e011fab27acc4 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Aug 2026 17:21:18 +0000 Subject: [PATCH] =?UTF-8?q?docs(data-modeling):=20state=20the=20autonumber?= =?UTF-8?q?=20contract=20=E2=80=94=20unique=20and=20monotonic,=20not=20gap?= =?UTF-8?q?less?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The autonumber contract ruled on #8283 (Option 1: unique + monotonic per scope, NOT gapless) existed only in the SQL driver's TSDoc, which no app author or AI writing an ObjectStack app ever reads. Adds the contract as the authoritative statement in the Field Type Gallery's `autonumber` entry (field-types.mdx), with a pointer from schema-design.mdx's worked `autonumber` example — the page most likely to be copied straight into a business-identifier field (invoice/account numbers) without a detour through the reference page. Fixes #8479 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Jqe56GnYFddggeAyfkZFVz --- content/docs/data-modeling/field-types.mdx | 15 +++++++++++++++ content/docs/data-modeling/schema-design.mdx | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/content/docs/data-modeling/field-types.mdx b/content/docs/data-modeling/field-types.mdx index 2a9438337b..d5eb9f9182 100644 --- a/content/docs/data-modeling/field-types.mdx +++ b/content/docs/data-modeling/field-types.mdx @@ -483,6 +483,21 @@ Auto-incrementing number with format template. { name: 'ticket_number', label: 'Ticket #', type: 'autonumber', autonumberFormat: 'TKT-{0000}' } ``` + +**An autonumber is unique and monotonic per scope — it is not gapless.** Any +write that gets rejected after the number was reserved — a unique violation on +another field, a failed validation rule, a `beforeInsert` hook that throws — +still consumes that number, and it is never reissued. `TKT-0001` succeeding and +`TKT-0002` failing means the next row is `TKT-0003`; `TKT-0002` will not exist. + +This is a decided property of the counter, not a bug to work around. If you are +building an invoice, contract, or receipt sequence on an `autonumber` field, +design for gaps: an autonumber guarantees a unique, ever-increasing business +identifier, but it is **not** a legally gapless document number. Treat that +guarantee as a separate requirement to satisfy explicitly, not something +`autonumber` already gives you. + + --- ## Embedded Structured Types diff --git a/content/docs/data-modeling/schema-design.mdx b/content/docs/data-modeling/schema-design.mdx index 9ad5025117..15b333f210 100644 --- a/content/docs/data-modeling/schema-design.mdx +++ b/content/docs/data-modeling/schema-design.mdx @@ -218,6 +218,13 @@ Field.autonumber({ // no separate reset config. A fixed prefix like 'INV-{000}' keeps one global counter. ``` +The counter is unique and monotonic per scope, **not gapless** — a rejected +write (a unique violation on another field, a failed validation rule, a +throwing `beforeInsert`) still consumes the number it reserved. Before wiring +an `autonumber` field to an invoice, contract, or receipt sequence, see the +[full contract](/docs/data-modeling/field-types#autonumber) in the Field Type +Gallery. + ### User Fields Pick a person — the equivalent of Airtable's *Collaborator* or Salesforce's