@wildo-ai/zod-decorators 1.1.9 → 1.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/esm/index.d.ts +1 -0
  2. package/dist/esm/index.d.ts.map +1 -1
  3. package/dist/esm/index.js +1 -0
  4. package/dist/esm/index.js.map +1 -1
  5. package/dist/esm/testing/decorated-test-schemas.d.ts +1 -1
  6. package/dist/esm/zod-bigdecimal.d.ts +16 -7
  7. package/dist/esm/zod-bigdecimal.d.ts.map +1 -1
  8. package/dist/esm/zod-bigdecimal.js.map +1 -1
  9. package/dist/esm/zod-code.d.ts +17 -8
  10. package/dist/esm/zod-code.d.ts.map +1 -1
  11. package/dist/esm/zod-code.js.map +1 -1
  12. package/dist/esm/zod-decorators.types.d.ts +339 -39
  13. package/dist/esm/zod-decorators.types.d.ts.map +1 -1
  14. package/dist/esm/zod-decorators.types.js +155 -13
  15. package/dist/esm/zod-decorators.types.js.map +1 -1
  16. package/dist/esm/zod-document-sequence.d.ts +119 -0
  17. package/dist/esm/zod-document-sequence.d.ts.map +1 -0
  18. package/dist/esm/zod-document-sequence.js +212 -0
  19. package/dist/esm/zod-document-sequence.js.map +1 -0
  20. package/dist/esm/zod-duration.d.ts +22 -13
  21. package/dist/esm/zod-duration.d.ts.map +1 -1
  22. package/dist/esm/zod-duration.js.map +1 -1
  23. package/dist/esm/zod-file.d.ts +0 -4
  24. package/dist/esm/zod-file.d.ts.map +1 -1
  25. package/dist/esm/zod-file.js +9 -20
  26. package/dist/esm/zod-file.js.map +1 -1
  27. package/dist/esm/zod-money.d.ts +22 -13
  28. package/dist/esm/zod-money.d.ts.map +1 -1
  29. package/dist/esm/zod-money.js.map +1 -1
  30. package/dist/esm/zod-phone.d.ts +22 -14
  31. package/dist/esm/zod-phone.d.ts.map +1 -1
  32. package/dist/esm/zod-phone.js.map +1 -1
  33. package/dist/esm/zod-range.d.ts.map +1 -1
  34. package/dist/esm/zod-range.js +5 -1
  35. package/dist/esm/zod-range.js.map +1 -1
  36. package/dist/esm/zod-utils.shared.d.ts +108 -2
  37. package/dist/esm/zod-utils.shared.d.ts.map +1 -1
  38. package/dist/esm/zod-utils.shared.js +228 -10
  39. package/dist/esm/zod-utils.shared.js.map +1 -1
  40. package/dist/esm/zod.module-override.d.ts +179 -53
  41. package/dist/esm/zod.module-override.d.ts.map +1 -1
  42. package/dist/esm/zod.module-override.js +473 -56
  43. package/dist/esm/zod.module-override.js.map +1 -1
  44. package/dist/tsconfig.build.tsbuildinfo +1 -0
  45. package/package.json +1 -1
@@ -5,6 +5,7 @@ import { AvailableCurrency, CurrencyAllowed } from './currencies.shared.schemas'
5
5
  import { z } from 'zod';
6
6
  import { DecoratedPrimitiveZodType } from './zod.module-override';
7
7
  import { ZodBrandedColorInstance } from './zod-color';
8
+ import type { DocumentSequenceParams } from './zod-document-sequence';
8
9
  /**
9
10
  * @wildo_source:part:start zod.decorators.schema-metadata
10
11
  *
@@ -146,9 +147,14 @@ export declare enum AutocompleteModifier {
146
147
  PAGER = "pager",
147
148
  WEBAUTHN = "webauthn"
148
149
  }
150
+ /** @wildo_source:part:start zod.decorators.chrome-modes facet:layer:frontend facet:family:ui facet:surface:form facet:surface:display facet:audience:app-developer */
149
151
  /**
150
152
  * Chrome layout mode for display context (detail/read-only views).
151
153
  * Controls how the field wrapper (label, value, description) is arranged.
154
+ *
155
+ * Import from `@wildo-ai/zod-decorators`. Declared per field (`display.chromeMode` in its `…UI()`), per
156
+ * layout (`layout.defaultChromeMode.display`) or per section; a `<FieldTiles>` host sets TILE for the fields
157
+ * placed in it. Every mode may be given per breakpoint ({@link ResponsiveAware}).
152
158
  */
153
159
  export declare const DisplayChromeMode: {
154
160
  /** Label above, value below, description below value (default). */
@@ -166,11 +172,32 @@ export declare const DisplayChromeMode: {
166
172
  readonly COMPACT: "compact";
167
173
  /** No chrome at all — bare value output. */
168
174
  readonly HIDDEN: "hidden";
175
+ /**
176
+ * A FACT TILE: the name small and quiet above, the value below, on a bounded tile
177
+ * (`SurfaceVariant.TILE`) — the shape of a record's facts laid out as a grid, which is how they are
178
+ * read: scanned by name, compared by value.
179
+ *
180
+ * Hosted by `<FieldTiles>`, which lays the tiles on a grid and gives its fields this chrome by
181
+ * default; a field that declares its own `chromeMode` (a description declaring HIDDEN) keeps it and
182
+ * takes a whole row of the grid in that chrome. Wide values — lists, objects, files, long text, a
183
+ * reference shown as its record's summary card — take a whole row. A tile shows no description line;
184
+ * a description the field declares rides in the tile's tooltip.
185
+ *
186
+ * Not the SETTINGS_ROW read chrome, which stays the shape of a SETTINGS pane: there the value sits
187
+ * where its control will appear. On a record the row placed a value up to 300px from its name, and a
188
+ * record is not a settings pane.
189
+ */
190
+ readonly TILE: "tile";
169
191
  };
170
192
  export type DisplayChromeMode = typeof DisplayChromeMode[keyof typeof DisplayChromeMode];
171
193
  /**
172
194
  * Chrome layout mode for edit context (forms).
173
- * Superset of DisplayChromeMode with form-specific modes (SETTINGS_ROW, RELAXED).
195
+ *
196
+ * NOT a superset of {@link DisplayChromeMode}, though most members share a name and a value: RELAXED
197
+ * exists only here (a form's generous onboarding spacing), and TILE exists only on the display side (a
198
+ * record's facts read as tiles; a form control is never a tile). A shared name is not always a shared
199
+ * geometry — edit INLINE puts the control BEFORE its label (a switch, a checkbox), display INLINE puts the
200
+ * name before its value — so read each member's own line.
174
201
  */
175
202
  export declare const EditChromeMode: {
176
203
  /** Label above, control below, description + error below control (default). */
@@ -198,6 +225,7 @@ export type ResponsiveChromeMode = EditChromeMode | Partial<Record<ViewportBreak
198
225
  * Used for chromeMode, forceHide, and other properties that may vary by viewport.
199
226
  */
200
227
  export type ResponsiveAware<T> = T | Partial<Record<ViewportBreakpoint, T>>;
228
+ /** @wildo_source:part:end zod.decorators.chrome-modes */
201
229
  export type FormFieldSchemaTypeComponents = {
202
230
  [K in FieldSchemaType]: K extends FieldSchemaType.STRING ? FormFieldComponent.INPUT | FormFieldComponent.TEXTAREA | FormFieldComponent.SELECT | FormFieldComponent.RADIO_GROUP | FormFieldComponent.DATE | FormFieldComponent.TIME | FormFieldComponent.DATETIME : K extends FieldSchemaType.NUMBER ? FormFieldComponent.INPUT | FormFieldComponent.SLIDER | FormFieldComponent.SELECT | FormFieldComponent.RADIO_GROUP : K extends FieldSchemaType.BIGINT ? FormFieldComponent.INPUT : K extends FieldSchemaType.BOOLEAN ? FormFieldComponent.SWITCH | FormFieldComponent.CHECKBOX | FormFieldComponent.SELECT | FormFieldComponent.RADIO_GROUP : K extends FieldSchemaType.ENUM ? FormFieldComponent.SELECT | FormFieldComponent.RADIO_GROUP : K extends FieldSchemaType.DATE ? FormFieldComponent.DATE | FormFieldComponent.DATETIME | FormFieldComponent.INPUT : K extends FieldSchemaType.TIME ? FormFieldComponent.TIME | FormFieldComponent.INPUT : K extends FieldSchemaType.DATETIME ? FormFieldComponent.DATETIME | FormFieldComponent.INPUT : K extends FieldSchemaType.RANGE_NUMBER ? FormFieldComponent.RANGE_SLIDER : K extends FieldSchemaType.RANGE_DATE ? FormFieldComponent.DATE_RANGE : K extends FieldSchemaType.RANGE_DATETIME ? FormFieldComponent.DATETIME_RANGE : K extends FieldSchemaType.RANGE_TIME ? FormFieldComponent.TIME_RANGE : K extends FieldSchemaType.RANGE_BIGDECIMAL ? FormFieldComponent.BIGDECIMAL_RANGE : K extends FieldSchemaType.RANGE_MONEY ? FormFieldComponent.MONEY_RANGE : K extends FieldSchemaType.MONEY ? FormFieldComponent.INPUT : K extends FieldSchemaType.DURATION ? FormFieldComponent.DURATION : K extends FieldSchemaType.PHONE ? FormFieldComponent.PHONE : K extends FieldSchemaType.ADDRESS ? FormFieldComponent.ADDRESS : K extends FieldSchemaType.BIGDECIMAL ? FormFieldComponent.INPUT : K extends FieldSchemaType.CODE ? FormFieldComponent.TEXTAREA : K extends FieldSchemaType.FILE ? FormFieldComponent.INPUT : K extends FieldSchemaType.ARRAY ? FormFieldComponent.CHECKBOX_GROUP | FormFieldComponent.SELECT : K extends FieldSchemaType.SET ? FormFieldComponent.INPUT | FormFieldComponent.CHECKBOX_GROUP | FormFieldComponent.SELECT : K extends FieldSchemaType.TUPLE ? FormFieldComponent.INPUT : K extends FieldSchemaType.UNKNOWN ? FormFieldComponent.INPUT : never;
203
231
  };
@@ -249,7 +277,8 @@ export type DefaultDisplayComponentForSchemaType<T extends FieldSchemaType> = Di
249
277
  * - DEFAULT: Standard section with border and padding
250
278
  * - CARD: Wrapped in a card container with shadow
251
279
  * - GHOST: Minimal container without visual styling
252
- * - COLLAPSIBLE: Expandable/collapsible section with trigger
280
+ * - COLLAPSIBLE: ONE section behind its own open/close trigger. `defaultFocus={false}` starts it
281
+ * closed — the mode for an aside a reader reveals on request
253
282
  *
254
283
  * **Container modes** (sections sharing the same mode are grouped together,
255
284
  * rendered at the position of the first occurrence):
@@ -264,9 +293,12 @@ export type DefaultDisplayComponentForSchemaType<T extends FieldSchemaType> = Di
264
293
  * - VERTICAL_TABS: Vertical tabs (side navigation)
265
294
  * - PILLS: Pill/segment navigation (compact)
266
295
  *
267
- * @category Expandable (toggle section visibility)
268
- * - ACCORDION: Each section independently collapsible
269
- * - EXPANDABLE: "Show more" button reveals additional sections
296
+ * @category Disclosure over a GROUP of sections
297
+ * - ACCORDION: one trigger per section; single-open unless `allowMultiple`
298
+ * - EXPANDABLE: truncation, not a toggle — the first `initialVisibleCount` (default 3) sections of
299
+ * the group show, and one "Show more" button reveals the rest. A group of `initialVisibleCount`
300
+ * sections or fewer never truncates, so EXPANDABLE over a single section renders it always open
301
+ * with no button: to hide one section until asked, use COLLAPSIBLE (#2197)
270
302
  *
271
303
  * @category Guided (sequential, with indicators)
272
304
  * - STEPPER: Step-by-step with step indicators
@@ -498,11 +530,32 @@ export declare const StringEditMode: {
498
530
  * `/application-config` (`organizationRoles`). Each option reads as the role's word from the `roles` labels. Use it
499
531
  * for any string field that names ONE role a setting admits (a reader role, a routing role), so an administrator
500
532
  * picks a role that exists instead of typing a key exactly. Falls back to a text input when the backend publishes no
501
- * table. The server remains the control: it decides what holding the role grants.
533
+ * table. An operation's `requestFieldOffers` narrows the roles further (#2778), and `organizationRoleTable:
534
+ * ANOTHER_ORGANIZATION` (see {@link OrganizationRoleTable}) makes it a role held in another organization, offered from
535
+ * the operation's offer alone. The server remains the control: it decides what holding the role grants.
502
536
  */
503
537
  readonly ORGANIZATION_ROLE: "organization_role";
504
538
  };
505
539
  export type StringEditMode = typeof StringEditMode[keyof typeof StringEditMode];
540
+ /**
541
+ * WHOSE role table an `ORGANIZATION_ROLE` picker reads (#2778).
542
+ *
543
+ * - `CURRENT_ORGANIZATION` (the default): the role is one of the organization being administered, so the picker offers
544
+ * that organization's table (the application's organization roles as its type narrows them).
545
+ * - `ANOTHER_ORGANIZATION`: the role names a role in ANOTHER organization, such as the role a representing organization
546
+ * proposes to hold in the granting one. The current organization's table is then the wrong population, so the picker
547
+ * offers only the values its operation's request field offer gives (`requestFieldOffers`), and is a text input
548
+ * while there is no offer.
549
+ *
550
+ * A const object, not an enum, like every edit- and display-mode vocabulary it sits among (`StringEditMode` above):
551
+ * these values are written inside `stringUI({ edit })` literals, and one vocabulary of the family declared differently
552
+ * would be the one a reader trips on. Converting the family is one decision for all of them, not a per-member one.
553
+ */
554
+ export declare const OrganizationRoleTable: {
555
+ readonly CURRENT_ORGANIZATION: "current_organization";
556
+ readonly ANOTHER_ORGANIZATION: "another_organization";
557
+ };
558
+ export type OrganizationRoleTable = typeof OrganizationRoleTable[keyof typeof OrganizationRoleTable];
506
559
  /**
507
560
  * Number display modes for rendering number values
508
561
  */
@@ -559,10 +612,28 @@ export type BigDecimalEditMode = typeof BigDecimalEditMode[keyof typeof BigDecim
559
612
  * Enum display modes for rendering enum values
560
613
  */
561
614
  export declare const EnumDisplayMode: {
615
+ /** The value's word alone, in the voice of the text around it — for a value with no colour to carry. */
562
616
  readonly TEXT: "text";
617
+ /** A soft pill in the value's colour. A value with no icon of its own leads with a state dot. */
563
618
  readonly BADGE: "badge";
619
+ /**
620
+ * The value's icon alone, on a pill in its colour; the word is read to assistive technology and shown on
621
+ * hover. The compact form for a summary line (`summaryOverride: { displayMode: ICON }`) where the icon is
622
+ * already known to the reader. A value with no `icon` of its own shows a dot in its colour instead.
623
+ */
564
624
  readonly ICON: "icon";
625
+ /** The word on a small card of its own — for a value that is the subject of a surface, not one fact among several. */
565
626
  readonly CARD: "card";
627
+ /**
628
+ * A tone dot and the label, with no chip around them — the QUIET form of a coloured value.
629
+ *
630
+ * For the second coloured value beside a status: priority next to status, severity next to state.
631
+ * Two filled pills side by side compete for the same attention; one pill and one dot keep the
632
+ * status as the thing that is read first. The dot fills with the value's colour at full strength and
633
+ * the label takes the same tone, so the value still reads without the chip. A value whose colour is
634
+ * the neutral one renders its dot and label muted.
635
+ */
636
+ readonly DOT: "dot";
566
637
  };
567
638
  export type EnumDisplayMode = typeof EnumDisplayMode[keyof typeof EnumDisplayMode];
568
639
  /**
@@ -859,7 +930,7 @@ export declare enum RangeType {
859
930
  export type RangeTypeMapping = {
860
931
  [RangeType.NUMBER]: number;
861
932
  [RangeType.DATE]: Date;
862
- [RangeType.DATETIME]: string;
933
+ [RangeType.DATETIME]: Date;
863
934
  [RangeType.TIME]: string;
864
935
  [RangeType.BIGDECIMAL]: string;
865
936
  [RangeType.MONEY]: {
@@ -1372,10 +1443,15 @@ export interface FileMultipleFilePolicy {
1372
1443
  * <scope>/<scopeId>/ ← the tenant segments (organizations/<id>, user_self/<id>,
1373
1444
  * or application/<applicationId>)
1374
1445
  * [folderPath(ctx)/] ← dynamic folder path
1375
- * <fileName(ctx) | fileId> ← explicit name or UUID fallback
1446
+ * [<fileId>/]<fileName(ctx)> | <fileId> ← explicit name under the file's own id, or the id alone
1376
1447
  * ```
1377
1448
  *
1378
- * Only the last two lines are authored here. Everything above them is derived by the framework and
1449
+ * A name is display metadata, never the identity of the stored object (#2901): when a name is resolved, the file's id
1450
+ * is the level directly above it, so two files of one field never share a key, whatever the name says. A static
1451
+ * `fileName` once gave every file of the field one key, and a regenerated file was written over the bytes its
1452
+ * predecessor still pointed at.
1453
+ *
1454
+ * Only `folderPath` and the name are authored here. Everything above them is derived by the framework and
1379
1455
  * is identical on every path-based provider, because `<scope>/<scopeId>` is what makes one tenant's
1380
1456
  * blobs a PREFIX — the unit erasure, orphan sweeps and per-tenant listing operate on.
1381
1457
  *
@@ -1420,8 +1496,8 @@ export interface FilePathBinding {
1420
1496
  */
1421
1497
  folderPath?: string | ((context: FilePathBindingContext) => string);
1422
1498
  /**
1423
- * File name for single `z_file()` fields (non-multiple).
1424
- * When omitted, falls back to the fileId (UUID-based, legacy behavior).
1499
+ * File name for single `z_file()` fields (non-multiple): the stored object's last segment, placed under the file's own
1500
+ * id, so a static name is safe (#2901). When omitted, the key is the fileId alone.
1425
1501
  *
1426
1502
  * - `string` — static name; can include `{ext}` placeholder.
1427
1503
  * - `function` — receives binding context and returns the file name.
@@ -2163,6 +2239,44 @@ export interface ImpersonalizeFieldParams {
2163
2239
  */
2164
2240
  maskValue?: string;
2165
2241
  }
2242
+ /**
2243
+ * The optional second argument of `.dataCategories(categories, options)` (#2119).
2244
+ *
2245
+ * Kept as an options bag, like `impersonalizeWith(treatment, options)`, so a second qualifier lands
2246
+ * here instead of as a new positional argument.
2247
+ */
2248
+ export interface DataCategoriesOptions {
2249
+ /**
2250
+ * The condition under which this field's value is personal data at all — a `PersonalDataCondition`
2251
+ * value carried as an opaque string (zod-decorators sits below saas-models and cannot reference
2252
+ * the enum). Absent means the field is personal data on every row.
2253
+ *
2254
+ * The case it exists for: a field naming the PARTY a row describes — a tenant organization, a
2255
+ * customer account — is a natural person's data when that party is an individual (a sole trader)
2256
+ * and not when it is a company. Declaring the categories with this condition lets a privacy
2257
+ * notice say "where the customer is an individual" instead of choosing between two false
2258
+ * sentences. Whether the value is a real member is checked by the saas-models boot guard.
2259
+ */
2260
+ personalOnlyWhen?: string;
2261
+ /**
2262
+ * `true` when the field names a party OTHER than the one the row is about: a copy of another organization's name kept
2263
+ * on a cost aggregate, a relationship, a membership or an access grant (#2535). Absent on a field naming the row's own
2264
+ * party, such as an organization's or a customer account's own name.
2265
+ *
2266
+ * WHOSE data a field is, which is a different question from WHEN it is personal (`personalOnlyWhen`), so it is
2267
+ * declared separately. Only one reader asks it: the `RETAIN_ONLY` contradiction guard, which admits a conditional copy
2268
+ * of another party's name on a resource stating "no personal data about its own subject", and still refuses the row's
2269
+ * own party's name there. Every other reader (erasure, export, the notice) counts the field exactly as before.
2270
+ */
2271
+ aboutAnotherParty?: boolean;
2272
+ }
2273
+ /**
2274
+ * What `.dataCategories()` STORES: the normalized form of either authoring shape. The categories
2275
+ * are always a deduped, non-empty array; the condition is present only when one was declared.
2276
+ */
2277
+ export interface DataCategoriesFieldParams extends DataCategoriesOptions {
2278
+ categories: readonly string[];
2279
+ }
2166
2280
  /**
2167
2281
  * Parameters passed to virtual field calculation functions.
2168
2282
  * The `utils` is typed as `any` in shared-lib but will be properly typed at runtime in backend-lib.
@@ -2187,16 +2301,56 @@ export interface VirtualFieldCalculationParams<TObject = any, TContext = any, TU
2187
2301
  */
2188
2302
  utils: any;
2189
2303
  }
2304
+ /**
2305
+ * Parameters passed to a virtual field's BATCHED calculation ({@link VirtualFieldParams.calculateMany}): the rows of
2306
+ * one list, in the order the list returns them.
2307
+ */
2308
+ export interface VirtualFieldBatchCalculationParams<TObject = any> {
2309
+ /** The rows to compute the field for, in list order. */
2310
+ currentObjects: readonly TObject[];
2311
+ /** The execution context of the request listing them. */
2312
+ executionContext: any;
2313
+ /** The same utility services as {@link VirtualFieldCalculationParams.utils}. */
2314
+ utils: any;
2315
+ }
2190
2316
  /**
2191
2317
  * Parameters for the isVirtual decorator.
2192
2318
  * Virtual fields are computed at runtime and not stored in the database.
2193
2319
  */
2194
2320
  export interface VirtualFieldParams<TObject = any, TResult = any> {
2195
2321
  /**
2196
- * The calculation function that computes this virtual field's value.
2197
- * Called at runtime by VirtualFieldsBackendService with injected utilities.
2322
+ * The calculation function that computes this virtual field's value for ONE row.
2323
+ * Called at runtime by VirtualFieldsBackendService with injected utilities: on a READ, and on a list row when the
2324
+ * field declares no {@link calculateMany}.
2198
2325
  */
2199
2326
  calculate: (params: VirtualFieldCalculationParams<TObject>) => TResult | Promise<TResult>;
2327
+ /**
2328
+ * The BATCHED form: computes the field for every row of a list in ONE call (#2631). Declare it when the field reads
2329
+ * another resource, so a page of N rows reads that resource once (one query over the rows' keys) instead of N times.
2330
+ *
2331
+ * - Return one value per row, in the same order: an array exactly as long as `currentObjects`. Any other length is
2332
+ * treated as a failure of the whole batch, like a throw.
2333
+ * - A failing batch gives every row `undefined` when the computation is fault-tolerant (the list default) and throws
2334
+ * otherwise, exactly as a failing `calculate` does for its one row.
2335
+ * - Used wherever several rows are computed together: a LIST or SEARCH page, and a relationship's children in a
2336
+ * resource context. One row (a READ) still goes through `calculate`, so the two must give the same value for the same row:
2337
+ * write the derivation once and call it from both.
2338
+ * - Ignored for a field that declares `needsObjectContext` or `needsUserContext`: those contexts are resolved per
2339
+ * row, so such a field is computed by `calculate` alone.
2340
+ *
2341
+ * @example
2342
+ * ```ts
2343
+ * tenantStatus: z.string().optional().isVirtual({
2344
+ * dependencies: ['organizationId'],
2345
+ * calculate: async ({ currentObject, utils }) => (await statusesOf(utils, [currentObject.organizationId])).get(currentObject.organizationId),
2346
+ * calculateMany: async ({ currentObjects, utils }) => {
2347
+ * const statuses = await statusesOf(utils, currentObjects.map((row) => row.organizationId));
2348
+ * return currentObjects.map((row) => statuses.get(row.organizationId));
2349
+ * },
2350
+ * }),
2351
+ * ```
2352
+ */
2353
+ calculateMany?: (params: VirtualFieldBatchCalculationParams<TObject>) => readonly TResult[] | Promise<readonly TResult[]>;
2200
2354
  /**
2201
2355
  * If true, the objectContext (parent/child relationships) will be passed to calculate().
2202
2356
  * Setting this to true has a performance cost as it requires fetching related resources.
@@ -2208,8 +2362,8 @@ export interface VirtualFieldParams<TObject = any, TResult = any> {
2208
2362
  */
2209
2363
  needsUserContext?: boolean;
2210
2364
  /**
2211
- * Optional list of field names this virtual field depends on.
2212
- * Used for documentation and potential future optimizations.
2365
+ * The stored fields this virtual field reads from its row. The repository adds them to the read projection, so
2366
+ * `calculate` / `calculateMany` receive them even on a SUMMARY row where they are not themselves summary fields.
2213
2367
  */
2214
2368
  dependencies?: string[];
2215
2369
  }
@@ -2265,8 +2419,14 @@ export interface UniqueFieldParams {
2265
2419
  */
2266
2420
  compoundWith?: string;
2267
2421
  /**
2268
- * Whether to allow null values without triggering uniqueness.
2269
- * MongoDB unique indexes exclude null by default when sparse is true.
2422
+ * Whether a row WITHOUT a value (the field absent or `null`) is left out of the uniqueness, so any number of such rows
2423
+ * may coexist. PostgreSQL plans it as a unique constraint whose NULLs are distinct. MongoDB builds it as a partial
2424
+ * filter that bounds the field from below in its own type (`{ field: { $gte: '' } }` for a string), which leaves out a
2425
+ * null as well as a missing value (#2582): MongoDB's own `sparse: true` would still index a stored null. The one
2426
+ * exception is a field whose type has no lowest value (an array, a free-form value), whose filter is
2427
+ * `{ $exists: true }` and so indexes a stored null.
2428
+ *
2429
+ * `false` makes rows without a value collide with each other on both stores (`NULLS NOT DISTINCT` on PostgreSQL).
2270
2430
  * @default true
2271
2431
  */
2272
2432
  sparse?: boolean;
@@ -2336,6 +2496,29 @@ export interface BusinessKeySetParams {
2336
2496
  */
2337
2497
  conflictMessageReference?: string;
2338
2498
  }
2499
+ /**
2500
+ * Parameters for the object-level `isResourceReference({ targetSet })` decorator (#2471).
2501
+ *
2502
+ * The decorated object names ONE row of a resource whose type is not fixed: its `resourceType` member is the
2503
+ * resource's name and its `resourceId` member the row's id. Unlike `.isForeignKey()` it declares no relationship
2504
+ * and changes nothing about storage: the two members stay plain strings, and the referenced resource is only
2505
+ * known at run time. It is what lets a form offer the resource types first and then the rows of the chosen one.
2506
+ *
2507
+ * `targetSet` names WHICH resource types the reference may name. It is a member of a vocabulary owned by the
2508
+ * layer that knows the types (`ResourceReferenceTargetSet` in `@wildo-ai/saas-models`), and the backend publishes
2509
+ * each set's members on `/application-config` (`resourceReferenceTargets`), derived from what the application
2510
+ * declares. A string here because this package sits below that vocabulary, as `dataCategories` does.
2511
+ *
2512
+ * The server stays the control: a reference is accepted only where the service that owns the field admits it.
2513
+ *
2514
+ * @example
2515
+ * export const WorkUnitRefSchema = z.strictObject({ resourceType: z.string(), resourceId: z.string() })
2516
+ * .isResourceReference({ targetSet: ResourceReferenceTargetSet.WORK_UNIT_CASES });
2517
+ */
2518
+ export interface ResourceReferenceParams {
2519
+ /** The set of resource types the reference may name. */
2520
+ targetSet: string;
2521
+ }
2339
2522
  /** @wildo_source:part:end zod.decorators.shared-structural-params */
2340
2523
  /**
2341
2524
  * @wildo_source:part:start zod.decorators.shared-structural-params facet:layer:shared facet:family:decorator facet:family:param-surface
@@ -2354,7 +2537,7 @@ export interface BusinessKeySetParams {
2354
2537
  * enforced on both. Do NOT read the MongoDB index as the mechanism and conclude the declaration is
2355
2538
  * inert elsewhere.
2356
2539
  *
2357
- * Two consequences worth knowing before you declare one:
2540
+ * Consequences worth knowing before you declare one:
2358
2541
  * - the sweep is deliberately bounded per run, so a table receiving rows faster than they expire
2359
2542
  * stays above its target until the rate changes; it reports when it stops early;
2360
2543
  * - a resource CANNOT declare both a lifetime and retrieval-source fields (`.ragSource()`). That
@@ -2363,7 +2546,16 @@ export interface BusinessKeySetParams {
2363
2546
  * - a resource scoped to an ORGANIZATION cannot declare a lifetime at all. For the same reason
2364
2547
  * no legal hold could suspend the deletion, and a hold on an organization covers every row of
2365
2548
  * it. A lifetime is for application-level plumbing; tenant data binds a retention class
2366
- * (`retentionBinding`), whose sweep deletes through the service layer and skips held rows.
2549
+ * (`retentionBinding`), whose sweep deletes through the service layer and skips held rows;
2550
+ * - a resource that another resource's ENABLED `onParentDelete` edge points at cannot declare a lifetime, whatever the
2551
+ * strategy (DELETE, IMPERSONALIZE_AND_RETAIN, REFUSE_WHILE_CHILDREN_EXIST) or mode (IMMEDIATE, LAZY). It is refused at startup: an expired
2552
+ * row leaves with none of its lifecycle running, so its children would outlive it, keep their personal data, or be
2553
+ * walked past. Bind a retention class instead; its sweep deletes through the service layer, which runs the edges;
2554
+ * - the field must be a TOP-LEVEL field of the main schema (always an object) or of an inheritance level: a lifetime on
2555
+ * a nested field is refused, since every guard above reads top-level fields while MongoDB would expire rows by the
2556
+ * nested path natively. An inheritance variant MAY give its rows their own lifetime, on a field only it declares;
2557
+ * one field has one lifetime, so a field declared with a `.ttl()` in one schema and differently in another (another
2558
+ * window, or none) is refused (MongoDB keeps one TTL index per path).
2367
2559
  *
2368
2560
  * This is unrelated to `retentionPolicy`, which decides what an ERASURE does to a row that must
2369
2561
  * SURVIVE. This one decides whether the row lives at all.
@@ -2434,7 +2626,7 @@ export interface SummaryFieldParams {
2434
2626
  * // Field definition:
2435
2627
  * userId: z.string().isForeignKey().isSummaryField({ populate: true })
2436
2628
  *
2437
- * // LIST/SEARCH response will include:
2629
+ * // A LIST or SEARCH response will include:
2438
2630
  * {
2439
2631
  * _id: "123",
2440
2632
  * userId: "user-456",
@@ -2665,9 +2857,9 @@ export interface PrimitiveUIBaseDisplayParams {
2665
2857
  tooltip?: boolean;
2666
2858
  /**
2667
2859
  * When `true`, the field is omitted entirely from the DISPLAY (read) surface
2668
- * whenever its value is empty — null, undefined, an empty string, or an empty
2669
- * array. The whole row (label + chrome + em-dash placeholder) is removed, not
2670
- * just the value.
2860
+ * whenever its value is empty — null, undefined, a blank string, an empty array or
2861
+ * an empty plain object. `false` and `0` are answers, never empty, and so is a date.
2862
+ * The whole row (label + chrome + em-dash placeholder) is removed, not just the value.
2671
2863
  *
2672
2864
  * DISPLAY-ONLY: the edit form always renders the field so an empty value can
2673
2865
  * still be filled in. This is the field-level counterpart to the section-level
@@ -2675,9 +2867,21 @@ export interface PrimitiveUIBaseDisplayParams {
2675
2867
  * `AutoEmptyValue.HIDDEN` — use it to keep optional metadata (a job title, a
2676
2868
  * secondary contact) from cluttering a read view when unset.
2677
2869
  *
2870
+ * UNSET means `true` inside a `<FieldTiles>` host (a record's facts — an empty tile
2871
+ * is clutter there, and the generated read view uses the host when the layout
2872
+ * declares no `defaultChromeMode.display`) and `false` everywhere else. So a field
2873
+ * whose emptiness is itself worth seeing on a record ("this contact has no email")
2874
+ * declares `hideWhenEmpty: false` explicitly. A field the reader can edit IN PLACE
2875
+ * keeps its empty tile without saying so — hiding it would remove the only way to
2876
+ * fill it there. And the default reaches only the fields placed in the host: the
2877
+ * items of a list and the members of an object a tile shows are its content, not
2878
+ * facts of the grid, and follow their own decorators.
2879
+ *
2678
2880
  * @example
2679
2881
  * // Hide the "Title" row on the profile read view until the user sets one:
2680
2882
  * schemaShape.title.stringUI({ display: { hideWhenEmpty: true } })
2883
+ * // Keep an empty email visible as a tile — the gap is the information:
2884
+ * schemaShape.email.stringUI({ display: { hideWhenEmpty: false } })
2681
2885
  */
2682
2886
  hideWhenEmpty?: boolean;
2683
2887
  /**
@@ -2811,6 +3015,8 @@ export interface StringUIEditParams extends PrimitiveUIBaseEditParams {
2811
3015
  editMode?: StringEditMode;
2812
3016
  /** Number of rows for TEXTAREA editMode. */
2813
3017
  textareaRows?: number;
3018
+ /** ORGANIZATION_ROLE editMode: whose role table the picker reads. Default `CURRENT_ORGANIZATION`. See {@link OrganizationRoleTable}. */
3019
+ organizationRoleTable?: OrganizationRoleTable;
2814
3020
  }
2815
3021
  export interface StringUIParams {
2816
3022
  display?: StringUIDisplayParams;
@@ -2847,7 +3053,7 @@ export interface NumberUIParams {
2847
3053
  edit?: NumberUIEditParams;
2848
3054
  }
2849
3055
  export interface EnumUIDisplayParams extends PrimitiveUIBaseDisplayParams {
2850
- /** Display renderer. TEXT | BADGE | ICON | CARD. */
3056
+ /** Display renderer — one of {@link EnumDisplayMode}, whose members each say when they are the right one. */
2851
3057
  displayMode?: EnumDisplayMode;
2852
3058
  }
2853
3059
  export interface EnumUIEditParams extends PrimitiveUIBaseEditParams {
@@ -3102,12 +3308,15 @@ export interface ForeignKeyUIParams {
3102
3308
  edit?: ForeignKeyUIEditParams;
3103
3309
  }
3104
3310
  /**
3105
- * List marker treatment for a PRIMITIVE array's display items.
3311
+ * How each item of an array's display announces itself as one of several: bare lines, bullets, a rule
3312
+ * between object entries, or a wrapping row of chips. The members apply to different entries (primitive
3313
+ * lines, object entries, strings), which each member's own line states.
3106
3314
  *
3107
- * Its own enum rather than a new `DisplayDirection` member on purpose: direction answers "which
3108
- * axis do items flow on", marker style answers "does each item announce itself as one of several" —
3109
- * merging them would make `BULLETS × horizontal` an unrepresentable-but-meaningful combination and
3110
- * overload an enum that alignment code also reads.
3315
+ * Its own enum rather than a new `DisplayDirection` member on purpose: direction answers "which axis do
3316
+ * items flow on", list style answers "how is each item set apart" — merging them would make
3317
+ * `BULLETS × horizontal` an unrepresentable-but-meaningful combination and overload an enum that
3318
+ * alignment code also reads. The one member that decides the flow itself is CHIPS: chips always wrap on
3319
+ * a line, so it ignores `displayMode`.
3111
3320
  */
3112
3321
  export declare enum ArrayListStyle {
3113
3322
  /** Bare stacked values — the historical default. */
@@ -3123,7 +3332,17 @@ export declare enum ArrayListStyle {
3123
3332
  * bounded region, a card per entry is a third frame around content that has two. Unlike
3124
3333
  * {@link ArrayListStyle.BULLETS}, which is for primitive lines, this is for entries.
3125
3334
  */
3126
- SEPARATED = "separated"
3335
+ SEPARATED = "separated",
3336
+ /**
3337
+ * Each entry a small neutral chip, the chips wrapping on one line — the shape of TAGS, labels and
3338
+ * keywords: short, unordered, read as a set.
3339
+ *
3340
+ * Applies to STRING entries. A list of enum values already renders each value in its own display
3341
+ * mode (a badge, a dot), so a chip around it would be a frame around a frame; any other entry type
3342
+ * falls back to the horizontal flow. Without it, two tags under `SEPARATED` stacked one above the
3343
+ * other at the right edge of a settings row, 81px tall for two words.
3344
+ */
3345
+ CHIPS = "chips"
3127
3346
  }
3128
3347
  export interface ArrayUIDisplayParams extends PrimitiveUIBaseDisplayParams {
3129
3348
  /** Direction for rendering items in display context. */
@@ -3131,9 +3350,10 @@ export interface ArrayUIDisplayParams extends PrimitiveUIBaseDisplayParams {
3131
3350
  /** Max items shown in display (rest truncated). */
3132
3351
  maxItems?: number;
3133
3352
  /**
3134
- * Marker treatment for PRIMITIVE items (see {@link ArrayListStyle}). No effect on object arrays —
3135
- * their items are cards/rows, not list lines — and no effect on horizontal flow, where markers
3136
- * have no line to anchor to.
3353
+ * How each item announces itself as one of several (see {@link ArrayListStyle}, whose members each
3354
+ * state the entries they apply to): PLAIN and BULLETS mark primitive lines, SEPARATED rules object
3355
+ * entries, CHIPS renders string entries as a wrapping row of chips and so decides the flow itself.
3356
+ * The line markers have no effect on horizontal flow, where there is no line to anchor to.
3137
3357
  */
3138
3358
  listStyle?: ArrayListStyle;
3139
3359
  }
@@ -3548,6 +3768,11 @@ export declare enum ZodDecorator {
3548
3768
  * WHETHER each value is a real `PersonalDataCategory` member is checked by the resource factory's
3549
3769
  * boot guard, which owns the enum — this layer knows only that non-empty strings were declared.
3550
3770
  *
3771
+ * An optional second argument, `{ personalOnlyWhen }` ({@link DataCategoriesOptions}), says the
3772
+ * field is personal data only under a `PersonalDataCondition` — the field naming a customer
3773
+ * organization, which is a person's data only when that customer is a sole trader (#2119). The
3774
+ * field still counts as personal for every guard; only the privacy notice words it conditionally.
3775
+ *
3551
3776
  * ⚠️ Four adjacent axes, none of them this one. {@link ZodDecorator.IMPERSONALIZE_WITH} says what
3552
3777
  * happens to the value on ERASURE; {@link ZodDecorator.PORTABILITY_PROVENANCE} says where it CAME
3553
3778
  * FROM; `Compliance_DataClassification` is a SENSITIVITY ladder for flows-actors config; a
@@ -3593,6 +3818,35 @@ export declare enum ZodDecorator {
3593
3818
  * assurance-control: WILDO.SECRETS.DISCLOSURE_AUDIT
3594
3819
  */
3595
3820
  IS_AUDIT_EVIDENCE = "isAuditEvidence",
3821
+ /**
3822
+ * Last-action record: this field holds what the MOST RECENT action on the row said about ITSELF — the
3823
+ * reason a person gave for a decision, the justification typed for a reassignment — not state the next
3824
+ * action starts from.
3825
+ *
3826
+ * Authored fluently on the ROW schema: `decisionReason: z.string().optional().isLastActionRecord()`. A pure
3827
+ * marker. Read it back with `isLastActionRecordField(schema)`.
3828
+ *
3829
+ * What it changes: a form that starts from the row (an update-like verb's form starts from the record it
3830
+ * acts on, so "Set disclosure" opens on the current disclosure) never offers this field's value as the
3831
+ * starting value of the next action. Without it, a verb whose request names the same field opened with the
3832
+ * previous decision's words already typed in: "Suspend" prefilled with the reason an acceptance was given,
3833
+ * which a person who submits without reading records as the reason for the suspension (#2192).
3834
+ *
3835
+ * Mark a field when an action REPLACES it with words about that action. Do not mark a setting an action
3836
+ * edits from its current value (a disclosure level, a list of admitted agents): starting from the current
3837
+ * value is what makes such a form safe to submit.
3838
+ */
3839
+ IS_LAST_ACTION_RECORD = "isLastActionRecord",
3840
+ /**
3841
+ * Decider: this field records WHICH PERSON decided something on the row: who approved, accepted, placed or released
3842
+ * (`decidedByUserId`, `acceptedByUserId`, `placedByUserId`). A pure marker, read back with `isDeciderField(schema)`.
3843
+ *
3844
+ * What it changes: a decider field records a person's decision, so the declaration of a verb that writes it names it
3845
+ * (`approvalSeal.decides`, CAPTURED or NONE with a reason, #2906). The engine's source check, a test over the
3846
+ * engine's own resources, refuses a decider field no declaration names and flags a field NAMED like a decider that is
3847
+ * not marked. No check runs over an application's resources yet: there the marker documents the field.
3848
+ */
3849
+ IS_DECIDER = "isDecider",
3596
3850
  /**
3597
3851
  * RAG source: this field's TEXT is a retrieval-corpus source. The framework chunks the value
3598
3852
  * (extracting text first for file fields), stores the chunks in the application's OWN datastore
@@ -3648,6 +3902,11 @@ export declare enum ZodDecorator {
3648
3902
  * `OBJECT_BUSINESS_KEY_SET` decorator on the schema root.
3649
3903
  */
3650
3904
  IS_BUSINESS_KEY = "isBusinessKey",
3905
+ /**
3906
+ * A server-allocated document number (`INV-2026-00042`), consecutive and gapless per scope. Composite: implies
3907
+ * `excludeFromCreate`, `excludeFromUpdate` and a unique index in the sequence's scope. See `DocumentSequenceParams`.
3908
+ */
3909
+ DOCUMENT_SEQUENCE = "documentSequence",
3651
3910
  /**
3652
3911
  * Object-level decorator declaring a **composite business key** for the
3653
3912
  * schema (e.g. `(organizationId, templateKey)`). Schema-level analog of
@@ -3658,6 +3917,11 @@ export declare enum ZodDecorator {
3658
3917
  * (single field vs composite). Mixing is rejected at decoration time.
3659
3918
  */
3660
3919
  OBJECT_BUSINESS_KEY_SET = "businessKeySet",
3920
+ /**
3921
+ * Object-level: the object (`{ resourceType, resourceId }`) names one row of a resource whose type is chosen at
3922
+ * run time from a published target set. See {@link ResourceReferenceParams}.
3923
+ */
3924
+ RESOURCE_REFERENCE = "isResourceReference",
3661
3925
  TTL = "ttl",
3662
3926
  IS_PASSWORD = "isPassword",
3663
3927
  IS_OTP = "isOtp",
@@ -3672,6 +3936,23 @@ export declare enum ZodDecorator {
3672
3936
  NUMBER_UI = "numberUI",
3673
3937
  ENUM_UI = "enumUI",
3674
3938
  DATE_UI = "dateUI",
3939
+ /**
3940
+ * A `Date` field that holds a CALENDAR DAY — a due date, a birthday, an invoice date — rather than an
3941
+ * instant. Declared with `z.date().isCalendarDate()`; read with `isCalendarDateSchema()`.
3942
+ *
3943
+ * A JavaScript `Date` is an instant, and an instant falls on different days in different time zones: a due
3944
+ * date picked as 3 Oct in Paris, stored as that browser's midnight, read 2 Oct in New York. A calendar day
3945
+ * has no zone. So a calendar date is held as UTC MIDNIGHT of its day, every reader sees that same day, and
3946
+ * the picker writes and reads the day itself. "Tomorrow" still means tomorrow in the READER's zone.
3947
+ *
3948
+ * Undeclared, a `Date` stays an instant (`createdAt`, `expiresAt`, `completedAt`…), shown in the reader's
3949
+ * configured time zone. A date RANGE (`z_range('date')`) is a range of calendar days without declaring it.
3950
+ *
3951
+ * It cannot be combined with `dateTimeUI()`, which declares a moment with a time of day: applying the second of
3952
+ * the two throws. "Today" for a calendar day, in its relative words, its picker, a new item's default and a
3953
+ * preset filter window alike, is today in the reader's resolved time zone.
3954
+ */
3955
+ IS_CALENDAR_DATE = "isCalendarDate",
3675
3956
  DATETIME_UI = "dateTimeUI",
3676
3957
  TIME_UI = "timeUI",
3677
3958
  MONEY_UI = "moneyUI",
@@ -3726,10 +4007,14 @@ export type ZodDecorator_ParamsType = {
3726
4007
  /**
3727
4008
  * The field's personal-data categories — `PersonalDataCategory` values, typed as plain strings at
3728
4009
  * this layer (zod-decorators sits below saas-models and cannot import the enum). Accepts a single
3729
- * value (the common case) or an array; the chokepoint normalizes either to a deduped array.
4010
+ * value (the common case) or an array, or the full {@link DataCategoriesFieldParams} object when
4011
+ * the fluent method's `options` argument was given; the chokepoint normalizes all three to that
4012
+ * object.
3730
4013
  */
3731
- [ZodDecorator.DATA_CATEGORIES]: string | readonly string[];
4014
+ [ZodDecorator.DATA_CATEGORIES]: string | readonly string[] | DataCategoriesFieldParams;
3732
4015
  [ZodDecorator.IS_AUDIT_EVIDENCE]: undefined;
4016
+ [ZodDecorator.IS_LAST_ACTION_RECORD]: undefined;
4017
+ [ZodDecorator.IS_DECIDER]: undefined;
3733
4018
  /**
3734
4019
  * RAG-source declaration. The config object is optional — `.ragSource()` with no argument is a
3735
4020
  * complete declaration — and the chokepoint normalizes an omitted config to `{}` so every reader
@@ -3743,7 +4028,9 @@ export type ZodDecorator_ParamsType = {
3743
4028
  [ZodDecorator.IS_UNIQUE]: UniqueFieldParams | DecoratorUpdater<UniqueFieldParams> | undefined;
3744
4029
  [ZodDecorator.IS_PRIMARY_KEY]: undefined;
3745
4030
  [ZodDecorator.IS_BUSINESS_KEY]: undefined;
4031
+ [ZodDecorator.DOCUMENT_SEQUENCE]: DocumentSequenceParams;
3746
4032
  [ZodDecorator.OBJECT_BUSINESS_KEY_SET]: BusinessKeySetParams | DecoratorUpdater<BusinessKeySetParams>;
4033
+ [ZodDecorator.RESOURCE_REFERENCE]: ResourceReferenceParams;
3747
4034
  [ZodDecorator.TTL]: TtlFieldParams | DecoratorUpdater<TtlFieldParams>;
3748
4035
  [ZodDecorator.IS_PASSWORD]: undefined;
3749
4036
  [ZodDecorator.IS_OTP]: OtpFieldParams | DecoratorUpdater<OtpFieldParams> | undefined;
@@ -3758,6 +4045,7 @@ export type ZodDecorator_ParamsType = {
3758
4045
  [ZodDecorator.NUMBER_UI]: NumberUIParams | DecoratorUpdater<NumberUIParams> | undefined;
3759
4046
  [ZodDecorator.ENUM_UI]: EnumUIParams | DecoratorUpdater<EnumUIParams> | undefined;
3760
4047
  [ZodDecorator.DATE_UI]: DateUIParams | DecoratorUpdater<DateUIParams> | undefined;
4048
+ [ZodDecorator.IS_CALENDAR_DATE]: undefined;
3761
4049
  [ZodDecorator.DATETIME_UI]: DateTimeUIParams | DecoratorUpdater<DateTimeUIParams> | undefined;
3762
4050
  [ZodDecorator.TIME_UI]: TimeUIParams | DecoratorUpdater<TimeUIParams> | undefined;
3763
4051
  [ZodDecorator.MONEY_UI]: MoneyUIParams | DecoratorUpdater<MoneyUIParams> | undefined;
@@ -3804,12 +4092,16 @@ export type ZodDecorator_Types = {
3804
4092
  * rejects blanks. */
3805
4093
  [ZodDecorator.PORTABILITY_PROVENANCE]: string;
3806
4094
  /** Personal-data categories — `PersonalDataCategory` values carried as opaque `string`s
3807
- * (zod-decorators sits below saas-models). ALWAYS the normalized array, deduped and non-empty:
3808
- * the chokepoint widens a bare single-value authoring form on the way in, so every reader sees
3809
- * one shape and `getDataCategories` can answer "is this field categorized?" by presence alone. */
3810
- [ZodDecorator.DATA_CATEGORIES]: readonly string[];
4095
+ * (zod-decorators sits below saas-models), plus the optional `personalOnlyWhen` condition (#2119).
4096
+ * ALWAYS the normalized object, its `categories` deduped and non-empty: the chokepoint widens the
4097
+ * bare-value and array authoring forms on the way in, so every reader sees one shape and
4098
+ * `getDataCategories` can answer "is this field categorized?" by presence alone. */
4099
+ [ZodDecorator.DATA_CATEGORIES]: DataCategoriesFieldParams;
3811
4100
  /** Audit-evidence marker — stored as the bare `true` sentinel (parameterless, like IS_BUSINESS_KEY). */
3812
4101
  [ZodDecorator.IS_AUDIT_EVIDENCE]: true;
4102
+ /** Last-action-record marker — stored as the bare `true` sentinel (parameterless, like IS_AUDIT_EVIDENCE). */
4103
+ [ZodDecorator.IS_LAST_ACTION_RECORD]: true;
4104
+ [ZodDecorator.IS_DECIDER]: true;
3813
4105
  /** RAG-source config — ALWAYS the normalized object ( `{}` when authored with no argument): the
3814
4106
  * chokepoint validates and normalizes on the way in, so every reader sees one shape and
3815
4107
  * `getRagSourceConfig` can answer "is this field a source?" by presence alone. */
@@ -3821,7 +4113,9 @@ export type ZodDecorator_Types = {
3821
4113
  [ZodDecorator.IS_UNIQUE]: UniqueFieldParams | true;
3822
4114
  [ZodDecorator.IS_PRIMARY_KEY]: true;
3823
4115
  [ZodDecorator.IS_BUSINESS_KEY]: true;
4116
+ [ZodDecorator.DOCUMENT_SEQUENCE]: DocumentSequenceParams;
3824
4117
  [ZodDecorator.OBJECT_BUSINESS_KEY_SET]: BusinessKeySetParams;
4118
+ [ZodDecorator.RESOURCE_REFERENCE]: ResourceReferenceParams;
3825
4119
  [ZodDecorator.TTL]: TtlFieldParams;
3826
4120
  [ZodDecorator.IS_PASSWORD]: true;
3827
4121
  [ZodDecorator.IS_OTP]: OtpFieldParams | true;
@@ -3836,6 +4130,7 @@ export type ZodDecorator_Types = {
3836
4130
  [ZodDecorator.NUMBER_UI]: NumberUIParams;
3837
4131
  [ZodDecorator.ENUM_UI]: EnumUIParams;
3838
4132
  [ZodDecorator.DATE_UI]: DateUIParams;
4133
+ [ZodDecorator.IS_CALENDAR_DATE]: true;
3839
4134
  [ZodDecorator.DATETIME_UI]: DateTimeUIParams;
3840
4135
  [ZodDecorator.TIME_UI]: TimeUIParams;
3841
4136
  [ZodDecorator.MONEY_UI]: MoneyUIParams;
@@ -3882,6 +4177,8 @@ export interface CustomFieldMetadata {
3882
4177
  [ZodDecorator.PORTABILITY_PROVENANCE]?: ZodDecorator_Types[ZodDecorator.PORTABILITY_PROVENANCE];
3883
4178
  [ZodDecorator.DATA_CATEGORIES]?: ZodDecorator_Types[ZodDecorator.DATA_CATEGORIES];
3884
4179
  [ZodDecorator.IS_AUDIT_EVIDENCE]?: ZodDecorator_Types[ZodDecorator.IS_AUDIT_EVIDENCE];
4180
+ [ZodDecorator.IS_LAST_ACTION_RECORD]?: ZodDecorator_Types[ZodDecorator.IS_LAST_ACTION_RECORD];
4181
+ [ZodDecorator.IS_DECIDER]?: ZodDecorator_Types[ZodDecorator.IS_DECIDER];
3885
4182
  [ZodDecorator.RAG_SOURCE]?: ZodDecorator_Types[ZodDecorator.RAG_SOURCE];
3886
4183
  [ZodDecorator.IS_VIRTUAL]?: ZodDecorator_Types[ZodDecorator.IS_VIRTUAL];
3887
4184
  [ZodDecorator.IS_DISCRIMINATOR]?: ZodDecorator_Types[ZodDecorator.IS_DISCRIMINATOR];
@@ -3890,7 +4187,9 @@ export interface CustomFieldMetadata {
3890
4187
  [ZodDecorator.IS_UNIQUE]?: ZodDecorator_Types[ZodDecorator.IS_UNIQUE];
3891
4188
  [ZodDecorator.IS_PRIMARY_KEY]?: ZodDecorator_Types[ZodDecorator.IS_PRIMARY_KEY];
3892
4189
  [ZodDecorator.IS_BUSINESS_KEY]?: ZodDecorator_Types[ZodDecorator.IS_BUSINESS_KEY];
4190
+ [ZodDecorator.DOCUMENT_SEQUENCE]?: ZodDecorator_Types[ZodDecorator.DOCUMENT_SEQUENCE];
3893
4191
  [ZodDecorator.OBJECT_BUSINESS_KEY_SET]?: ZodDecorator_Types[ZodDecorator.OBJECT_BUSINESS_KEY_SET];
4192
+ [ZodDecorator.RESOURCE_REFERENCE]?: ZodDecorator_Types[ZodDecorator.RESOURCE_REFERENCE];
3894
4193
  [ZodDecorator.TTL]?: ZodDecorator_Types[ZodDecorator.TTL];
3895
4194
  [ZodDecorator.IS_PASSWORD]?: ZodDecorator_Types[ZodDecorator.IS_PASSWORD];
3896
4195
  [ZodDecorator.IS_OTP]?: ZodDecorator_Types[ZodDecorator.IS_OTP];
@@ -3905,6 +4204,7 @@ export interface CustomFieldMetadata {
3905
4204
  [ZodDecorator.NUMBER_UI]?: ZodDecorator_Types[ZodDecorator.NUMBER_UI];
3906
4205
  [ZodDecorator.ENUM_UI]?: ZodDecorator_Types[ZodDecorator.ENUM_UI];
3907
4206
  [ZodDecorator.DATE_UI]?: ZodDecorator_Types[ZodDecorator.DATE_UI];
4207
+ [ZodDecorator.IS_CALENDAR_DATE]?: ZodDecorator_Types[ZodDecorator.IS_CALENDAR_DATE];
3908
4208
  [ZodDecorator.DATETIME_UI]?: ZodDecorator_Types[ZodDecorator.DATETIME_UI];
3909
4209
  [ZodDecorator.TIME_UI]?: ZodDecorator_Types[ZodDecorator.TIME_UI];
3910
4210
  [ZodDecorator.MONEY_UI]?: ZodDecorator_Types[ZodDecorator.MONEY_UI];