@wildo-ai/zod-decorators 1.0.1 → 1.1.0

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 (98) hide show
  1. package/LICENSE +34 -0
  2. package/dist/esm/.builder.pid +9 -0
  3. package/dist/esm/__mocks__/mime.d.ts.map +1 -1
  4. package/dist/esm/__mocks__/mime.js +1 -1
  5. package/dist/esm/__mocks__/mime.js.map +1 -1
  6. package/dist/esm/commons.d.ts.map +1 -1
  7. package/dist/esm/commons.js +1 -1
  8. package/dist/esm/commons.js.map +1 -1
  9. package/dist/esm/companion-exports.d.ts +8 -0
  10. package/dist/esm/companion-exports.d.ts.map +1 -0
  11. package/dist/esm/companion-exports.js +8 -0
  12. package/dist/esm/companion-exports.js.map +1 -0
  13. package/dist/esm/currencies.shared.schemas.d.ts.map +1 -1
  14. package/dist/esm/currencies.shared.schemas.js +1 -1
  15. package/dist/esm/currencies.shared.schemas.js.map +1 -1
  16. package/dist/esm/files/agent-file-formats.d.ts.map +1 -1
  17. package/dist/esm/files/agent-file-formats.js +1 -1
  18. package/dist/esm/files/agent-file-formats.js.map +1 -1
  19. package/dist/esm/files/extension-nature-map.d.ts +1 -1
  20. package/dist/esm/files/extension-nature-map.d.ts.map +1 -1
  21. package/dist/esm/files/extension-nature-map.js +1 -1
  22. package/dist/esm/files/extension-nature-map.js.map +1 -1
  23. package/dist/esm/files/file-extensions.enum.d.ts.map +1 -1
  24. package/dist/esm/files/file-extensions.enum.js +1 -1
  25. package/dist/esm/files/file-extensions.enum.js.map +1 -1
  26. package/dist/esm/files/mime-registry.d.ts +1 -1
  27. package/dist/esm/files/mime-registry.d.ts.map +1 -1
  28. package/dist/esm/files/mime-registry.js +1 -1
  29. package/dist/esm/files/mime-registry.js.map +1 -1
  30. package/dist/esm/files/unified-registry.d.ts +1 -1
  31. package/dist/esm/files/unified-registry.d.ts.map +1 -1
  32. package/dist/esm/files/unified-registry.js +1 -1
  33. package/dist/esm/files/unified-registry.js.map +1 -1
  34. package/dist/esm/index.d.ts +20 -19
  35. package/dist/esm/index.d.ts.map +1 -1
  36. package/dist/esm/index.js +10 -1
  37. package/dist/esm/index.js.map +1 -1
  38. package/dist/esm/install-bigint-json-encoding.d.ts +80 -0
  39. package/dist/esm/install-bigint-json-encoding.d.ts.map +1 -0
  40. package/dist/esm/install-bigint-json-encoding.js +85 -0
  41. package/dist/esm/install-bigint-json-encoding.js.map +1 -0
  42. package/dist/esm/testing/decorated-test-schemas.d.ts +8 -8
  43. package/dist/esm/testing/decorated-test-schemas.d.ts.map +1 -1
  44. package/dist/esm/testing/decorated-test-schemas.js +1 -1
  45. package/dist/esm/testing/decorated-test-schemas.js.map +1 -1
  46. package/dist/esm/testing.d.ts +1 -1
  47. package/dist/esm/testing.d.ts.map +1 -1
  48. package/dist/esm/testing.js +1 -1
  49. package/dist/esm/testing.js.map +1 -1
  50. package/dist/esm/zod-bigdecimal.d.ts +5 -1
  51. package/dist/esm/zod-bigdecimal.d.ts.map +1 -1
  52. package/dist/esm/zod-bigdecimal.js +4 -1
  53. package/dist/esm/zod-bigdecimal.js.map +1 -1
  54. package/dist/esm/zod-code.d.ts +4 -1
  55. package/dist/esm/zod-code.d.ts.map +1 -1
  56. package/dist/esm/zod-code.js +4 -1
  57. package/dist/esm/zod-code.js.map +1 -1
  58. package/dist/esm/zod-color.d.ts.map +1 -1
  59. package/dist/esm/zod-color.js +1 -1
  60. package/dist/esm/zod-color.js.map +1 -1
  61. package/dist/esm/zod-decorators.types.d.ts +1410 -56
  62. package/dist/esm/zod-decorators.types.d.ts.map +1 -1
  63. package/dist/esm/zod-decorators.types.js +662 -16
  64. package/dist/esm/zod-decorators.types.js.map +1 -1
  65. package/dist/esm/zod-duration.d.ts +8 -4
  66. package/dist/esm/zod-duration.d.ts.map +1 -1
  67. package/dist/esm/zod-duration.js +2 -1
  68. package/dist/esm/zod-duration.js.map +1 -1
  69. package/dist/esm/zod-file.d.ts +75 -14
  70. package/dist/esm/zod-file.d.ts.map +1 -1
  71. package/dist/esm/zod-file.js +151 -8
  72. package/dist/esm/zod-file.js.map +1 -1
  73. package/dist/esm/zod-money.d.ts +18 -3
  74. package/dist/esm/zod-money.d.ts.map +1 -1
  75. package/dist/esm/zod-money.js +4 -1
  76. package/dist/esm/zod-money.js.map +1 -1
  77. package/dist/esm/zod-phone.d.ts +37 -1
  78. package/dist/esm/zod-phone.d.ts.map +1 -1
  79. package/dist/esm/zod-phone.js +66 -5
  80. package/dist/esm/zod-phone.js.map +1 -1
  81. package/dist/esm/zod-range.d.ts +4 -1
  82. package/dist/esm/zod-range.d.ts.map +1 -1
  83. package/dist/esm/zod-range.js +4 -1
  84. package/dist/esm/zod-range.js.map +1 -1
  85. package/dist/esm/zod-utils.shared.d.ts +411 -6
  86. package/dist/esm/zod-utils.shared.d.ts.map +1 -1
  87. package/dist/esm/zod-utils.shared.js +624 -9
  88. package/dist/esm/zod-utils.shared.js.map +1 -1
  89. package/dist/esm/zod-versioned.d.ts +1 -1
  90. package/dist/esm/zod-versioned.d.ts.map +1 -1
  91. package/dist/esm/zod-versioned.js +1 -1
  92. package/dist/esm/zod-versioned.js.map +1 -1
  93. package/dist/esm/zod.module-override.d.ts +458 -68
  94. package/dist/esm/zod.module-override.d.ts.map +1 -1
  95. package/dist/esm/zod.module-override.js +1214 -195
  96. package/dist/esm/zod.module-override.js.map +1 -1
  97. package/dist/tsconfig.build.tsbuildinfo +1 -1
  98. package/package.json +20 -11
@@ -1,10 +1,22 @@
1
1
  import type { ComponentType } from 'react';
2
- import { ViewportBreakpoint } from './commons.js';
3
- import { AvailableCurrency, CurrencyAllowed } from './currencies.shared.schemas.js';
2
+ import type { CountryCode as LibPhoneNumberCountryCode } from 'libphonenumber-js';
3
+ import { ViewportBreakpoint } from './commons';
4
+ import { AvailableCurrency, CurrencyAllowed } from './currencies.shared.schemas';
4
5
  import { z } from 'zod';
5
- import { DecoratedPrimitiveZodType } from './zod.module-override.js';
6
- import { ZodBrandedColorInstance } from './zod-color.js';
6
+ import { DecoratedPrimitiveZodType } from './zod.module-override';
7
+ import { ZodBrandedColorInstance } from './zod-color';
8
+ /**
9
+ * @wildo_source:part:start zod.decorators.schema-metadata
10
+ *
11
+ * Internal metadata key used by Wildo's schema decorators.
12
+ *
13
+ * Application schemas obtain this metadata by using the supported decorators
14
+ * and schema factories from `@wildo-ai/zod-decorators`; application code must
15
+ * not write this symbol directly. `Symbol.for()` keeps independently loaded
16
+ * package copies interoperable while the framework reads the schema contract.
17
+ */
7
18
  export declare const SCHEMA_METADATA: symbol;
19
+ /** @wildo_source:part:end zod.decorators.schema-metadata */
8
20
  export declare enum FieldSchemaType {
9
21
  STRING = "string",// String schemas (z.string)
10
22
  NUMBER = "number",// Number schemas (z.number, z.int)
@@ -57,6 +69,81 @@ export declare enum FormFieldComponent {
57
69
  DURATION = "duration",// Duration input (value + unit selector)
58
70
  PHONE = "phone"
59
71
  }
72
+ /**
73
+ * Official HTML autocomplete field identifiers.
74
+ * Excludes `section-*`, `on`, and `off` because the decorator contract here is
75
+ * focused on typed semantic field tokens rather than raw form-level switches.
76
+ */
77
+ export declare enum AutocompleteFieldIdentifier {
78
+ NAME = "name",
79
+ HONORIFIC_PREFIX = "honorific-prefix",
80
+ GIVEN_NAME = "given-name",
81
+ ADDITIONAL_NAME = "additional-name",
82
+ FAMILY_NAME = "family-name",
83
+ HONORIFIC_SUFFIX = "honorific-suffix",
84
+ NICKNAME = "nickname",
85
+ USERNAME = "username",
86
+ NEW_PASSWORD = "new-password",
87
+ CURRENT_PASSWORD = "current-password",
88
+ ONE_TIME_CODE = "one-time-code",
89
+ ORGANIZATION_TITLE = "organization-title",
90
+ ORGANIZATION = "organization",
91
+ STREET_ADDRESS = "street-address",
92
+ ADDRESS_LINE_1 = "address-line1",
93
+ ADDRESS_LINE_2 = "address-line2",
94
+ ADDRESS_LINE_3 = "address-line3",
95
+ ADDRESS_LEVEL_4 = "address-level4",
96
+ ADDRESS_LEVEL_3 = "address-level3",
97
+ ADDRESS_LEVEL_2 = "address-level2",
98
+ ADDRESS_LEVEL_1 = "address-level1",
99
+ COUNTRY = "country",
100
+ COUNTRY_NAME = "country-name",
101
+ POSTAL_CODE = "postal-code",
102
+ CC_NAME = "cc-name",
103
+ CC_GIVEN_NAME = "cc-given-name",
104
+ CC_ADDITIONAL_NAME = "cc-additional-name",
105
+ CC_FAMILY_NAME = "cc-family-name",
106
+ CC_NUMBER = "cc-number",
107
+ CC_EXP = "cc-exp",
108
+ CC_EXP_MONTH = "cc-exp-month",
109
+ CC_EXP_YEAR = "cc-exp-year",
110
+ CC_CSC = "cc-csc",
111
+ CC_TYPE = "cc-type",
112
+ TRANSACTION_CURRENCY = "transaction-currency",
113
+ TRANSACTION_AMOUNT = "transaction-amount",
114
+ LANGUAGE = "language",
115
+ BDAY = "bday",
116
+ BDAY_DAY = "bday-day",
117
+ BDAY_MONTH = "bday-month",
118
+ BDAY_YEAR = "bday-year",
119
+ SEX = "sex",
120
+ URL = "url",
121
+ PHOTO = "photo",
122
+ TEL = "tel",
123
+ TEL_COUNTRY_CODE = "tel-country-code",
124
+ TEL_NATIONAL = "tel-national",
125
+ TEL_AREA_CODE = "tel-area-code",
126
+ TEL_LOCAL = "tel-local",
127
+ TEL_LOCAL_PREFIX = "tel-local-prefix",
128
+ TEL_LOCAL_SUFFIX = "tel-local-suffix",
129
+ TEL_EXTENSION = "tel-extension",
130
+ EMAIL = "email",
131
+ IMPP = "impp"
132
+ }
133
+ /**
134
+ * Official non-`section-*` HTML autocomplete modifiers.
135
+ * Rendering code is responsible for placing them in spec order.
136
+ */
137
+ export declare enum AutocompleteModifier {
138
+ SHIPPING = "shipping",
139
+ BILLING = "billing",
140
+ HOME = "home",
141
+ WORK = "work",
142
+ MOBILE = "mobile",
143
+ FAX = "fax",
144
+ PAGER = "pager",
145
+ WEBAUTHN = "webauthn"
146
+ }
60
147
  /**
61
148
  * Chrome layout mode for display context (detail/read-only views).
62
149
  * Controls how the field wrapper (label, value, description) is arranged.
@@ -64,6 +151,13 @@ export declare enum FormFieldComponent {
64
151
  export declare const DisplayChromeMode: {
65
152
  /** Label above, value below, description below value (default). */
66
153
  readonly STACKED: "stacked";
154
+ /**
155
+ * Label + description inline-start, value inline-end (settings page style).
156
+ * The read-mode counterpart of `EditChromeMode.SETTINGS_ROW` — pairing the two
157
+ * keeps a view→edit drill (e.g. inside the Settings Hub) visually coherent: the
158
+ * value sits where its control will appear.
159
+ */
160
+ readonly SETTINGS_ROW: "settings_row";
67
161
  /** Label and value on the same line. */
68
162
  readonly INLINE: "inline";
69
163
  /** No label/description, just value (dense mode). */
@@ -75,8 +169,6 @@ export type DisplayChromeMode = typeof DisplayChromeMode[keyof typeof DisplayChr
75
169
  /**
76
170
  * Chrome layout mode for edit context (forms).
77
171
  * Superset of DisplayChromeMode with form-specific modes (SETTINGS_ROW, RELAXED).
78
- *
79
- * Also exported as `FormFieldChromeMode` for backward compatibility.
80
172
  */
81
173
  export declare const EditChromeMode: {
82
174
  /** Label above, control below, description + error below control (default). */
@@ -93,23 +185,6 @@ export declare const EditChromeMode: {
93
185
  readonly HIDDEN: "hidden";
94
186
  };
95
187
  export type EditChromeMode = typeof EditChromeMode[keyof typeof EditChromeMode];
96
- /** @deprecated Use `EditChromeMode` directly. Kept as alias for backward compatibility. */
97
- export declare const FormFieldChromeMode: {
98
- /** Label above, control below, description + error below control (default). */
99
- readonly STACKED: "stacked";
100
- /** Label + description left, control + error right (settings page style). */
101
- readonly SETTINGS_ROW: "settings_row";
102
- /** Control left, label + description right (switch/checkbox style). */
103
- readonly INLINE: "inline";
104
- /** Generous spacing, heading-size label (onboarding, OTP, wizard). */
105
- readonly RELAXED: "relaxed";
106
- /** No label/description, just control + error (dense mode). */
107
- readonly COMPACT: "compact";
108
- /** No chrome at all — bare control output. */
109
- readonly HIDDEN: "hidden";
110
- };
111
- /** @deprecated Use `EditChromeMode` directly. */
112
- export type FormFieldChromeMode = EditChromeMode;
113
188
  /**
114
189
  * Responsive chrome mode — either a single mode or per-breakpoint mapping.
115
190
  * When a breakpoint mapping is provided, FormFieldChrome resolves the effective
@@ -264,6 +339,22 @@ export declare enum HorizontalAlign {
264
339
  CENTER = "center",
265
340
  END = "end"
266
341
  }
342
+ /**
343
+ * @wildo_source:part:start zod.decorators.display-edit-modes facet:layer:frontend facet:family:ui facet:surface:form facet:surface:display
344
+ *
345
+ * Frontend UI vocabulary for choosing how a field renders and edits.
346
+ *
347
+ * These values are not the persisted resource semantics themselves. They are
348
+ * consumed by the frontend resource UI behavior layer, typically in
349
+ * files like `frontend/src/modules/<module>/resources/<resource>/<resource>.ui-behavior.tsx`, where the AI
350
+ * calls decorators like `.stringUI()`, `.enumUI()`, `.booleanUI()`, etc. on the
351
+ * schema shape exposed to `resourceUIBehavior(...)`.
352
+ *
353
+ * Keep these mode enums in the framework source as the canonical list of
354
+ * supported display/edit behaviors. Authoring skills and generated knowledge
355
+ * should reference these definitions instead of copying literal mode tables
356
+ * into markdown by hand.
357
+ */
267
358
  /**
268
359
  * Labelling values for boolean fields
269
360
  */
@@ -301,6 +392,16 @@ export declare const StringDisplayMode: {
301
392
  readonly TEXT: "text";
302
393
  readonly TRUNCATE: "truncate";
303
394
  readonly MULTILINE: "multiline";
395
+ /**
396
+ * Render the value as rich markdown (GFM: headings, lists, tables, links,
397
+ * task lists, fenced code). For long-form authored content — descriptions,
398
+ * notes, documentation fields. Headings are demoted for embedded context
399
+ * (a `#` inside a field body never competes with the page title) and every
400
+ * element is styled through the active theme's typography recipes. Pair
401
+ * with `edit.editMode: MARKDOWN` (syntax-tinted source editor) — or plain
402
+ * `TEXTAREA` — the edit side stays markdown SOURCE either way.
403
+ */
404
+ readonly MARKDOWN: "markdown";
304
405
  readonly COLOR: "color";
305
406
  readonly LINK: "link";
306
407
  readonly EMAIL: "email";
@@ -318,6 +419,14 @@ export declare const StringEditMode: {
318
419
  readonly COLOR: "color";
319
420
  readonly PASSWORD: "password";
320
421
  readonly OTP: "otp";
422
+ /**
423
+ * Markdown SOURCE editor (CodeMirror-backed, syntax-tinted, theme-token
424
+ * styled). The stored value stays plain markdown source — display-side
425
+ * rendering remains owned by `StringDisplayMode.MARKDOWN` (Streamdown).
426
+ * This is deliberately NOT a WYSIWYG mode; a rich visual editor is a
427
+ * separate future edit mode/component.
428
+ */
429
+ readonly MARKDOWN: "markdown";
321
430
  };
322
431
  export type StringEditMode = typeof StringEditMode[keyof typeof StringEditMode];
323
432
  /**
@@ -369,7 +478,10 @@ export declare const BigDecimalEditMode: {
369
478
  readonly INPUT: "input";
370
479
  };
371
480
  export type BigDecimalEditMode = typeof BigDecimalEditMode[keyof typeof BigDecimalEditMode];
481
+ /** @wildo_source:part:end zod.decorators.display-edit-modes */
372
482
  /**
483
+ * @wildo_source:part:start zod.decorators.enums.frontend-handling facet:layer:frontend facet:layer:shared facet:family:enum facet:family:ui facet:surface:form facet:surface:display
484
+ *
373
485
  * Enum display modes for rendering enum values
374
486
  */
375
487
  export declare const EnumDisplayMode: {
@@ -438,14 +550,16 @@ export interface EnumValueDisplayConfig {
438
550
  /** Icon for this enum value — React component or StandardIconReference string */
439
551
  icon?: IconLike;
440
552
  }
553
+ /** @wildo_source:part:end zod.decorators.enums.frontend-handling */
441
554
  /**
442
555
  * Updater function accepted by any decorator with object params.
443
556
  *
444
557
  * Receives the current metadata value (or `undefined` if no prior decorator
445
558
  * or if the prior value is the `true` boolean shorthand). Returns the new value.
446
559
  *
447
- * For `{primitive}UI` decorators, the updater bypasses the
448
- * normal merge behavior — the returned value replaces entirely.
560
+ * For mergeable primitive decorators (`{primitive}UI()` and `{primitive}Spec()`),
561
+ * the updater bypasses the normal deep-merge behavior — the returned value
562
+ * replaces entirely.
449
563
  *
450
564
  * @example
451
565
  * ```ts
@@ -464,13 +578,31 @@ export interface EnumValueDisplayConfig {
464
578
  */
465
579
  export type DecoratorUpdater<T> = (current: T | undefined) => T;
466
580
  /**
467
- * Foreign key display mode options
468
- * - ID: Show raw FK ID value
469
- * - LABEL: Show resolved label via getFrontendResourceLabel
470
- * - SUMMARY: Show the referenced resource's summary view (compact card) (default)
581
+ * @wildo_source:part:start zod.decorators.foreign-key-display-mode facet:layer:frontend facet:family:ui facet:surface:display facet:surface:picker
582
+ *
583
+ * Foreign-key reference display vocabulary — how a foreign-key field renders, both
584
+ * as a stored VALUE in read views and as each ROW in the reference picker's
585
+ * dropdown (the picker is shared by forms and collection filters). Authored via
586
+ * `.foreignKeyUI(...)` from `@wildo-ai/zod-decorators` on the FK field:
587
+ * - `display.mode` — how the saved FK value renders in a read view.
588
+ * - `edit.optionDisplayMode` — how each picker dropdown ROW renders while selecting.
589
+ *
590
+ * Modes:
591
+ * - `ID`: the raw FK id string. As a picker row this is treated as `LABEL`.
592
+ * - `LABEL`: a one-line resolved label via `getFrontendResourceLabel`. The default on
593
+ * BOTH surfaces — see {@link DEFAULT_FOREIGN_KEY_DISPLAY_MODE} and
594
+ * {@link DEFAULT_FOREIGN_KEY_OPTION_DISPLAY_MODE}.
595
+ * - `SUMMARY`: the referenced resource's summary view — its summary fields with NO
596
+ * action bar (a compact card). Always an opt-in, on both surfaces.
471
597
  *
472
- * Note: "summary" here is about *FK rendering*, not API data shape (see DataMode.SUMMARY)
473
- * or operation bar density (see ResourceOperationDisplayMode.SUMMARY).
598
+ * "summary" here is about FK RENDERING, not API data shape (`DataMode.SUMMARY`) or
599
+ * operation-bar density (`ResourceOperationDisplayMode.SUMMARY`).
600
+ *
601
+ * @example
602
+ * // Make the picker dropdown rows show the referenced resource's summary card:
603
+ * assigneeUserId: z.string().isForeignKey().foreignKeyUI({
604
+ * edit: { optionDisplayMode: ForeignKeyDisplayMode.SUMMARY },
605
+ * })
474
606
  */
475
607
  export declare const ForeignKeyDisplayMode: {
476
608
  readonly ID: "id";
@@ -478,25 +610,108 @@ export declare const ForeignKeyDisplayMode: {
478
610
  readonly SUMMARY: "summary";
479
611
  };
480
612
  export type ForeignKeyDisplayMode = typeof ForeignKeyDisplayMode[keyof typeof ForeignKeyDisplayMode];
613
+ /**
614
+ * The mode an FK's stored VALUE renders in when the field authors no
615
+ * `.foreignKeyUI({ display: { mode } })`.
616
+ *
617
+ * **This is the single source for that default.** Every site that has to supply a
618
+ * fallback display mode derives from this constant rather than restating a member of
619
+ * {@link ForeignKeyDisplayMode}. It exists because the default was previously declared
620
+ * twice and the two declarations DISAGREED — the metadata reader said `LABEL`, the
621
+ * display preset said `SUMMARY` — so the answer an app author got depended on which
622
+ * resolution path happened to run, and the prose above this enum documented the losing
623
+ * one.
624
+ *
625
+ * `LABEL` is the default because it is the cheap, composable rendering: one resolved
626
+ * line that fits a table cell, a detail row and a dense list alike. `SUMMARY` renders a
627
+ * card of the referenced record's summary fields — appropriate when the parent's
628
+ * details matter AT the point of reference, which is a per-field authoring judgement,
629
+ * not something a framework can assume for every FK in an application.
630
+ *
631
+ * @example
632
+ * // Opt a single field into the card rendering:
633
+ * todoListId: z.string().isForeignKey().foreignKeyUI({
634
+ * display: { mode: ForeignKeyDisplayMode.SUMMARY },
635
+ * })
636
+ */
637
+ export declare const DEFAULT_FOREIGN_KEY_DISPLAY_MODE: ForeignKeyDisplayMode;
638
+ /**
639
+ * The mode each ROW of the reference picker's dropdown renders in when the field
640
+ * authors no `.foreignKeyUI({ edit: { optionDisplayMode } })`.
641
+ *
642
+ * **This is the single source for that default**, and it is deliberately a SEPARATE
643
+ * constant from {@link DEFAULT_FOREIGN_KEY_DISPLAY_MODE}. The two answer different
644
+ * questions — "how does a stored reference read?" versus "how does a candidate read
645
+ * while I am choosing one?" — and a framework that collapsed them would make one
646
+ * surface's default un-tunable without moving the other. They currently coincide on
647
+ * `LABEL`; that agreement is a fact about today's values, not a shared identity.
648
+ */
649
+ export declare const DEFAULT_FOREIGN_KEY_OPTION_DISPLAY_MODE: ForeignKeyDisplayMode;
650
+ /** @wildo_source:part:end zod.decorators.foreign-key-display-mode */
481
651
  /**
482
652
  * Polymorphic FK variant definition.
483
- * Specifies which parent resource variants a polymorphic FK targets.
484
- * Used by the polymorphic factory to derive the correct FK field name per variant.
653
+ *
654
+ * Describes one scope-branch of a polymorphic foreign key. A variant has two
655
+ * complementary roles, depending on whether the FK is renamed-per-holder or
656
+ * shared-with-discriminator (see {@link ForeignKeyStructuralParams.polymorphicVariants}):
657
+ *
658
+ * 1. **Rename role** (`parentResourceType` + `parentFieldIdentifier`): when the
659
+ * FK's HOLDER resource is polymorphically expanded into per-scope variants,
660
+ * the factory uses these to rename the FK field per variant — e.g.
661
+ * `billingAccountId` → `organizationBillingAccountId`.
662
+ * 2. **Discriminated-resolution role** (`discriminatorValue`): when the FK is a
663
+ * single SHARED field on a flat holder that points at a polymorphic branch
664
+ * GROUP, this value links the holder record's discriminator field value to
665
+ * THIS branch. See {@link ForeignKeyStructuralParams.polymorphicDiscriminatorField}.
485
666
  */
486
667
  export interface PolymorphicFkVariant {
487
- /** The parent resource type (e.g., 'organizations') */
668
+ /** The parent (scope-root) resource type, e.g. `'organizations'` / `'users'`. */
488
669
  parentResourceType: string;
489
- /** The parent's field identifier (e.g., 'organizationId') */
670
+ /** The parent's field identifier, e.g. `'organizationId'` / `'userId'`. */
490
671
  parentFieldIdentifier: string;
672
+ /**
673
+ * Value of the FK's `polymorphicDiscriminatorField` (read off the SAME record)
674
+ * that selects this variant's branch. Only meaningful for shared-field
675
+ * discriminated FKs; ignored by the per-variant rename path. E.g. a referral's
676
+ * `referrerScopeType === 'organizations'` selects the organizations variant,
677
+ * whose branch is `organizationBillingAccounts`.
678
+ */
679
+ discriminatorValue?: string;
491
680
  }
492
681
  /**
682
+ * @wildo_source:part:start zod.decorators.shared-structural-params facet:layer:shared facet:family:decorator facet:family:param-surface
683
+ *
493
684
  * Structural FK params — backend/factory-relevant subset.
494
685
  * Stays on `IS_FOREIGN_KEY`. UI-specific params (mode, linkable,
495
686
  * displayPresetOverride) live on `ForeignKeyUIParams` via `.foreignKeyUI()`.
496
687
  */
497
688
  export interface ForeignKeyStructuralParams {
689
+ /**
690
+ * Marks this FK as polymorphic over a set of scope branches.
691
+ *
692
+ * - On a resource that is itself polymorphically expanded, these drive the
693
+ * per-variant FK field RENAME (e.g. `billingAccountId` →
694
+ * `organizationBillingAccountId`).
695
+ * - On a FLAT resource that holds ONE shared FK to a polymorphic branch group
696
+ * (e.g. a referral's `referrerBillingAccountId` → user OR organization
697
+ * billing account), combine with {@link polymorphicDiscriminatorField}: each
698
+ * variant carries a `discriminatorValue`, and the concrete branch is
699
+ * resolved PER RECORD from the discriminator field. The single-valued
700
+ * registry FK→type map keeps a non-authoritative representative for these
701
+ * fields; the per-record resolver is authoritative for display/links.
702
+ */
498
703
  polymorphicVariants?: PolymorphicFkVariant[];
704
+ /**
705
+ * Sibling field name (on the SAME record) whose value selects which
706
+ * {@link polymorphicVariants} branch this record's FK points at. Required to
707
+ * turn `polymorphicVariants` into a per-record discriminated FK; pairs with
708
+ * each variant's `discriminatorValue`. The value is matched against the
709
+ * candidate branches' primary scope, so it typically holds a scope-type enum
710
+ * (e.g. `referrerScopeType`). Without it, `polymorphicVariants` is rename-only.
711
+ */
712
+ polymorphicDiscriminatorField?: string;
499
713
  }
714
+ /** @wildo_source:part:end zod.decorators.shared-structural-params */
500
715
  /**
501
716
  * Supported types for range schemas.
502
717
  */
@@ -684,8 +899,16 @@ export interface DurationSchemaMetadata {
684
899
  /** Maximum value (for the numeric part) */
685
900
  maxValue?: number;
686
901
  }
687
- /** ISO 3166-1 alpha-2 country code (e.g., 'US', 'FR') */
688
- export type PhoneCountryCode = string;
902
+ /**
903
+ * ISO 3166-1 alpha-2 country code (e.g., 'US', 'FR').
904
+ *
905
+ * Narrowed to libphonenumber's `CountryCode` union (not a bare `string`) so an
906
+ * invalid code fails at COMPILE time. The runtime consequence of a bad code is
907
+ * a throw from `getCountryCallingCode` — and since the international phone
908
+ * edit control renders the selected dial code, an invalid authored
909
+ * `defaultCountry` would crash the form at first render, not merely misparse.
910
+ */
911
+ export type PhoneCountryCode = LibPhoneNumberCountryCode;
689
912
  /**
690
913
  * Metadata stored on phone schemas for detection and configuration.
691
914
  * Phone schemas store E.164 strings.
@@ -783,6 +1006,122 @@ export declare enum FileDisplayNature {
783
1006
  DOCUMENT = "document",
784
1007
  GENERIC = "generic"
785
1008
  }
1009
+ /**
1010
+ * Frame shape for an inline media (image) preview — see `FileUIDisplayParams.preview`.
1011
+ * - `ROUNDED` (default): rounded-corner rectangle, aspect preserved (`object-contain`).
1012
+ * - `SQUARE`: sharp-corner rectangle, aspect preserved.
1013
+ * - `CIRCLE`: circular frame; the image is cropped to fill (`object-cover`). Typical
1014
+ * for avatars / profile pictures.
1015
+ */
1016
+ export declare enum FileMediaShape {
1017
+ ROUNDED = "rounded",
1018
+ SQUARE = "square",
1019
+ CIRCLE = "circle"
1020
+ }
1021
+ /**
1022
+ * Rendered size tier for an inline media (image) preview — see
1023
+ * `FileUIDisplayParams.preview`. `XS`–`XL` are fixed dimensions (a `CIRCLE` uses the
1024
+ * value as its diameter; a rectangle uses it as the max width). `FULL` fills the
1025
+ * available column width (the default, container-responsive) — best for cover images,
1026
+ * not avatars.
1027
+ */
1028
+ export declare enum FileMediaSize {
1029
+ XS = "xs",
1030
+ SM = "sm",
1031
+ MD = "md",
1032
+ LG = "lg",
1033
+ XL = "xl",
1034
+ FULL = "full"
1035
+ }
1036
+ /**
1037
+ * How a file field renders AT REST, before any interaction — one of the two
1038
+ * orthogonal axes of the file display policy (the other is
1039
+ * {@link FileActivationPolicy}, what a click does).
1040
+ *
1041
+ * - `CARD` (default): the neutral file card — icon + filename + size. Compact and
1042
+ * nature-agnostic, so a detail view holding several documents stays scannable.
1043
+ * - `THUMBNAIL`: a small rendered preview of the media beside the title (an image
1044
+ * thumbnail, a PDF's rasterised first page). Informative but still compact.
1045
+ * - `FULL`: the media rendered inline at full width — an image, a video player, a
1046
+ * paginated PDF viewer. The heaviest option: for documents it downloads and mounts
1047
+ * the viewer on first paint, so prefer `CARD` + an `OVERLAY` activation unless the
1048
+ * document IS the page.
1049
+ *
1050
+ * `THUMBNAIL` and `FULL` require a displayer for the file's resolved nature; a
1051
+ * request the nature cannot satisfy is refused at registry build (narrow declared
1052
+ * nature) or degraded to `CARD` at runtime (open nature) — never a broken render.
1053
+ */
1054
+ export declare enum FileDisplayPresentation {
1055
+ CARD = "card",
1056
+ THUMBNAIL = "thumbnail",
1057
+ FULL = "full"
1058
+ }
1059
+ /**
1060
+ * What activating (clicking / Enter) a displayed file does — the second axis of the
1061
+ * file display policy. Applies to EVERY file nature, not just images.
1062
+ *
1063
+ * - `NONE`: inert. No cursor affordance, no handler, not focusable as a control.
1064
+ * - `OVERLAY`: open the nature's displayer in an overlay (the generalisation of the
1065
+ * old image-only lightbox). Requires a displayer for the resolved nature.
1066
+ * - `DOWNLOAD`: fetch the bytes over the authenticated serve route and save them.
1067
+ * - `NEW_TAB`: open the authenticated serve URL in a new tab (the browser's own
1068
+ * viewer, with its native print/save affordances).
1069
+ * - `CUSTOM`: run an operation declared on the resource that OWNS this file field —
1070
+ * see {@link FileActivationConfig}.
1071
+ */
1072
+ export declare enum FileActivationPolicy {
1073
+ NONE = "none",
1074
+ OVERLAY = "overlay",
1075
+ DOWNLOAD = "download",
1076
+ NEW_TAB = "new_tab",
1077
+ CUSTOM = "custom"
1078
+ }
1079
+ /**
1080
+ * The authored activation, discriminated on `policy`.
1081
+ *
1082
+ * `CUSTOM` names an operation **by identifier**, never a callback. The reference is
1083
+ * resolved against the resource that owns the file field, so the click inherits that
1084
+ * operation's entire contract for free — `roles` authorization, `enabledCondition`,
1085
+ * i18n label/tooltip, icon, risk level and audit emission — none of which a raw
1086
+ * handler could carry. It also keeps display config serializable, which the
1087
+ * specification layer, the companion and i18n generation all depend on.
1088
+ *
1089
+ * Dispatch follows the referenced operation's own frontend surface: `ADDRESSABLE`
1090
+ * navigates, `EMBEDDED` opens in the overlay host, `API_ONLY` executes directly
1091
+ * (with the standard confirmation for critical operations). The clicked file travels
1092
+ * to the operation as context (`{ fieldName, fileId }`); the operation targets the
1093
+ * owning row. An unresolvable reference fails at registry build, never as a dead control.
1094
+ *
1095
+ * @example
1096
+ * // Click the attachment card to run the owning resource's `send_to_dms` operation.
1097
+ * { policy: FileActivationPolicy.CUSTOM, operationIdentifier: 'send_to_dms' }
1098
+ */
1099
+ export type FileActivationConfig = {
1100
+ policy: FileActivationPolicy.NONE | FileActivationPolicy.OVERLAY | FileActivationPolicy.DOWNLOAD | FileActivationPolicy.NEW_TAB;
1101
+ } | {
1102
+ policy: FileActivationPolicy.CUSTOM;
1103
+ /** Operation identifier declared on the resource owning this file field. */
1104
+ operationIdentifier: string;
1105
+ /** Disambiguates when the operation has several keyed variants. */
1106
+ variantKey?: string;
1107
+ };
1108
+ /**
1109
+ * Presentation detail for a rendered media preview. Applies when
1110
+ * {@link FileUIDisplayParams.presentation} is `THUMBNAIL` or `FULL`; ignored by `CARD`.
1111
+ * All fields are optional with sensible defaults (rounded rectangle, full width,
1112
+ * caption on). An avatar typically sets `{ shape: CIRCLE, size: MD, showCaption: false }`.
1113
+ *
1114
+ * Click behaviour is NOT here — it is the separate `activation` axis, so that every
1115
+ * nature (not only images) can express it.
1116
+ */
1117
+ export interface FileMediaPreviewOptions {
1118
+ /** Frame shape. @default FileMediaShape.ROUNDED */
1119
+ shape?: FileMediaShape;
1120
+ /** Rendered size tier. @default FileMediaSize.FULL */
1121
+ size?: FileMediaSize;
1122
+ /** Show the caption row (filename / size / dimensions / download) under the media. @default true */
1123
+ showCaption?: boolean;
1124
+ }
786
1125
  /**
787
1126
  * Storage providers accepted for file uploads.
788
1127
  */
@@ -924,8 +1263,8 @@ export interface FilePathBinding {
924
1263
  export declare enum FileUploaderEntityType {
925
1264
  USER = "user",
926
1265
  ANONYMOUS_USER = "anonymous_user",
927
- ORGANIZATION_API_KEY = "organization_api_key",
928
- APPLICATION_API_KEY = "application_api_key"
1266
+ ORGANIZATION_MACHINE = "organization_machine",
1267
+ APPLICATION_MACHINE = "application_machine"
929
1268
  }
930
1269
  export type FileUploaderOwnership = {
931
1270
  uploadedBy: string;
@@ -1009,25 +1348,95 @@ export interface FileNatureConstraints_Document {
1009
1348
  minPages?: number;
1010
1349
  }
1011
1350
  /**
1012
- * RAG chunking strategy options for file content indexing.
1351
+ * @wildo_source:part:start zod.decorators.rag-source facet:layer:shared facet:family:decorator facet:family:param-surface facet:kind:api facet:audience:app-developer
1352
+ *
1353
+ * How a RAG-source field's text is split into retrieval chunks.
1354
+ *
1355
+ * Import from `@wildo-ai/zod-decorators`. Every member is a chunking STRATEGY — pick the one that
1356
+ * matches the field's real content shape, because chunk boundaries decide what a retrieval hit can
1357
+ * quote: a heading-aware split over markdown returns a coherent section, while a fixed-size split
1358
+ * over the same text returns whatever fell inside the window.
1359
+ *
1360
+ * **This is the single named home for the chunking vocabulary** (semantic-string-literals rule).
1361
+ * It lives in `zod-decorators` — not `saas-models` — because the dependency arrow points the other
1362
+ * way: `saas-models` depends on this package, while the `.ragSource()` decorator params below could
1363
+ * never import a `saas-models` enum. Chunking is authored ON THE FIELD, through `.ragSource()`;
1364
+ * there is no separate agent-level chunking configuration to keep in step with it.
1365
+ *
1366
+ * - `FIXED_SIZE` — split every `chunkSize` characters/tokens regardless of structure.
1367
+ * - `RECURSIVE` — split on a separator hierarchy (paragraph → sentence → word) down to `chunkSize`.
1368
+ * - `SEMANTIC` — split at embedding-detected topic boundaries.
1369
+ * - `MARKDOWN` — split on markdown structure (headings, lists, code fences).
1370
+ * - `CODE` — split on source-code structure (functions, classes, blocks). Unified in (2026-08-26)
1371
+ * from a second copy of this vocabulary that `saas-models` then carried: the member sets differed
1372
+ * only by this entry, and shrinking the vocabulary to fit the field decorator would have silently
1373
+ * invalidated configurations authored against the wider one — so the union won. That second copy,
1374
+ * and the agent-level RAG configuration schemas around it, were retired on 2026-08-27 as a
1375
+ * pre-capability design the shipped capability superseded; this object is now the only home.
1013
1376
  */
1014
1377
  export declare const RAGChunkingStrategy: {
1015
1378
  readonly FIXED_SIZE: "fixed_size";
1016
1379
  readonly RECURSIVE: "recursive";
1017
1380
  readonly SEMANTIC: "semantic";
1018
1381
  readonly MARKDOWN: "markdown";
1382
+ readonly CODE: "code";
1019
1383
  };
1020
1384
  export type RAGChunkingStrategy = typeof RAGChunkingStrategy[keyof typeof RAGChunkingStrategy];
1021
1385
  /**
1022
- * RAG configuration for file content indexing.
1386
+ * Stored metadata for the RAG-source declaration (`.ragSource()` / `addRagSource()` /
1387
+ * `z_file({ ragSource })`).
1388
+ *
1389
+ * Every knob is optional — `z.string().ragSource()` is a complete declaration that accepts the
1390
+ * framework chunking defaults — and there is deliberately NO `enabled` flag: a field either carries
1391
+ * the decorator (it IS a retrieval-corpus source) or it does not. A boolean that could say
1392
+ * "decorated but disabled" would make every downstream reader (detection, chunk store, erasure
1393
+ * seams) re-ask a question the decorator's presence already answers.
1394
+ *
1395
+ * Validated at decoration time by the `applySingleDecorator` chokepoint (shared by the fluent
1396
+ * method and the escape hatch): `chunkingStrategy` must be a {@link RAGChunkingStrategy} member,
1397
+ * `chunkSize` a positive integer, `chunkOverlap` a non-negative integer strictly smaller than
1398
+ * `chunkSize` when both are present. Read the stored config back with `getRagSourceConfig(schema)`.
1399
+ *
1400
+ * Note the split of concerns with file fields: this object configures CHUNKING — how text becomes
1401
+ * retrieval chunks — and is identical for a plain string field and a file field. How the TEXT is
1402
+ * OBTAINED in the first place is the text provider's concern: trivial for a string field (the value
1403
+ * is the text), file-side config for a file field (`FileSchemaOptions.textExtraction`, e.g. OCR).
1023
1404
  */
1024
- export interface FileRAGConfiguration {
1025
- enabled: boolean;
1026
- extractText?: boolean;
1405
+ export interface RagSourceConfiguration {
1406
+ /** Chunking strategy for this field's text. Omitted = the framework default strategy. */
1027
1407
  chunkingStrategy?: RAGChunkingStrategy;
1408
+ /** Target chunk size. Positive integer; omitted = the strategy's default size. */
1028
1409
  chunkSize?: number;
1410
+ /** Overlap carried between consecutive chunks. Non-negative integer, `< chunkSize` when both are set. */
1029
1411
  chunkOverlap?: number;
1030
1412
  }
1413
+ /** @wildo_source:part:end zod.decorators.rag-source */
1414
+ /**
1415
+ * @wildo_source:part:start zod.decorators.file-generation facet:layer:schema facet:family:pdf-templates
1416
+ *
1417
+ * Generation sources supported by `z_file()`.
1418
+ *
1419
+ * Keep this enum in `zod-decorators` instead of `saas-models` so shared schemas
1420
+ * can mark generated files without creating a dependency cycle back into the
1421
+ * resource/model packages that already consume decorators.
1422
+ */
1423
+ export declare enum FileGenerationSource {
1424
+ PDF_TEMPLATE = "pdfTemplate"
1425
+ }
1426
+ /**
1427
+ * Frontend-safe file generation metadata.
1428
+ *
1429
+ * This is deliberately a stable identifier only. The backend binds that
1430
+ * identifier to an imported `PdfTemplateDefinition` during application startup,
1431
+ * which keeps live functions and React components out of shared schema metadata.
1432
+ */
1433
+ export interface FileGenerationConfig {
1434
+ /** The generation system responsible for materializing the file value. */
1435
+ source: FileGenerationSource.PDF_TEMPLATE;
1436
+ /** Stable id of the backend-bound PDF template definition. */
1437
+ templateId: string;
1438
+ }
1439
+ /** @wildo_source:part:end zod.decorators.file-generation */
1031
1440
  /**
1032
1441
  * File metadata returned by the getMetadata endpoint.
1033
1442
  * This describes the uploaded file's properties.
@@ -1075,6 +1484,8 @@ export declare const FileOnParentDelete: {
1075
1484
  };
1076
1485
  export type FileOnParentDelete = typeof FileOnParentDelete[keyof typeof FileOnParentDelete];
1077
1486
  /**
1487
+ * @wildo_source:part:start zod.decorators.file-schema
1488
+ *
1078
1489
  * Metadata stored on file schemas for detection and configuration.
1079
1490
  * File schemas represent file references with upload capabilities.
1080
1491
  * Structure (single): { fileId: string, updatedAt: Date }
@@ -1101,6 +1512,12 @@ export interface FileSchemaMetadata {
1101
1512
  storageAccepted?: FileStorageAccepted[];
1102
1513
  /** File path binding for structured storage organization */
1103
1514
  filePathBinding?: FilePathBinding;
1515
+ /**
1516
+ * Generation metadata for files materialized by framework operations instead
1517
+ * of user uploads. Generated file fields are readable but omitted from write
1518
+ * DTOs by downstream resource tooling.
1519
+ */
1520
+ generation?: FileGenerationConfig;
1104
1521
  /** Image-specific constraints */
1105
1522
  imageConstraints?: FileNatureConstraints_Image;
1106
1523
  /** Video-specific constraints */
@@ -1109,8 +1526,19 @@ export interface FileSchemaMetadata {
1109
1526
  audioConstraints?: FileNatureConstraints_Audio;
1110
1527
  /** Document-specific constraints */
1111
1528
  documentConstraints?: FileNatureConstraints_Document;
1112
- /** RAG configuration */
1113
- rag?: FileRAGConfiguration;
1529
+ /**
1530
+ * Text-provider configuration for this file field — HOW text is obtained from the file's bytes
1531
+ * when something needs it (today: RAG chunking of a `ragSource` file field; the standalone
1532
+ * text-extraction operation reads it too).
1533
+ *
1534
+ * Deliberately file-side and separate from {@link RagSourceConfiguration}: extraction is a
1535
+ * property of the FILE FIELD (its bytes need decoding — PDF parsing, OCR), while chunking is the
1536
+ * shared RAG-source concern a plain string field carries identically. The former `extractText`
1537
+ * boolean is gone with `z_file({ rag })`: for a `ragSource` file field extraction is implied
1538
+ * (a corpus source whose text is never extracted would be a silent no-op), so the only honest
1539
+ * remaining knobs are the ones that change HOW extraction runs.
1540
+ */
1541
+ textExtraction?: FileTextExtractionOptions;
1114
1542
  /**
1115
1543
  * Antivirus scan policy for this file field.
1116
1544
  * - 'required': always scan after upload, regardless of global config
@@ -1140,6 +1568,27 @@ export interface FileSchemaMetadata {
1140
1568
  consumptionMode?: 'SINGLE_USE' | 'BOUNDED_REUSE';
1141
1569
  };
1142
1570
  }
1571
+ /** @wildo_source:part:end zod.decorators.file-schema */
1572
+ /**
1573
+ * @wildo_source:part:start zod.decorators.file-rag-source facet:layer:shared facet:family:decorator facet:family:file facet:kind:api facet:audience:app-developer
1574
+ *
1575
+ * File-side text-extraction knobs (see {@link FileSchemaMetadata.textExtraction} for why these are
1576
+ * NOT part of {@link RagSourceConfiguration}).
1577
+ *
1578
+ * Import from `@wildo-ai/zod-decorators` and pass under `z_file({ textExtraction })`. Extraction
1579
+ * answers "how are this file's BYTES turned into text"; chunking (`RagSourceConfiguration`) answers
1580
+ * "how is that text split", and is identical for a file field and a plain string field.
1581
+ */
1582
+ export interface FileTextExtractionOptions {
1583
+ /**
1584
+ * Opt into OCR for image-backed content (scanned documents, photos of text). Off by default:
1585
+ * OCR is an external, per-page cost, and most corpus files (PDF with a text layer, plain text,
1586
+ * markdown) never need it.
1587
+ * @default false
1588
+ */
1589
+ ocr?: boolean;
1590
+ }
1591
+ /** @wildo_source:part:end zod.decorators.file-rag-source */
1143
1592
  /**
1144
1593
  * Options for creating a file schema.
1145
1594
  */
@@ -1162,6 +1611,14 @@ export interface FileSchemaOptions {
1162
1611
  storageAccepted?: FileStorageAccepted[];
1163
1612
  /** File path binding for structured storage organization */
1164
1613
  filePathBinding?: FilePathBinding;
1614
+ /**
1615
+ * Marks this file as generated by a framework operation.
1616
+ *
1617
+ * `FileGenerationSource.PDF_TEMPLATE` is v1's only source and is always
1618
+ * single-file PDF output; callers must not combine it with upload-style MIME
1619
+ * broadening or multiple-file semantics.
1620
+ */
1621
+ generation?: FileGenerationConfig;
1165
1622
  /** Image-specific constraints */
1166
1623
  imageConstraints?: FileNatureConstraints_Image;
1167
1624
  /** Video-specific constraints */
@@ -1170,8 +1627,31 @@ export interface FileSchemaOptions {
1170
1627
  audioConstraints?: FileNatureConstraints_Audio;
1171
1628
  /** Document-specific constraints */
1172
1629
  documentConstraints?: FileNatureConstraints_Document;
1173
- /** RAG configuration */
1174
- rag?: FileRAGConfiguration;
1630
+ /**
1631
+ * @wildo_source:part:start zod.decorators.file-rag-source facet:layer:shared facet:family:decorator facet:family:file facet:kind:api facet:audience:app-developer
1632
+ *
1633
+ * Declare this file field a RAG retrieval-corpus source.
1634
+ *
1635
+ * (The two `z_file()` options below are declared on `FileSchemaOptions` — the object literal
1636
+ * `z_file()` accepts.)
1637
+ *
1638
+ * `z_file({ ragSource: {} })` registers the shared {@link ZodDecorator.RAG_SOURCE} decorator on
1639
+ * the schema it returns — the SAME decorator `z.string().ragSource()` uses — so detection and
1640
+ * every downstream seam (chunk store, erasure, re-index) see one uniform declaration. The config
1641
+ * is stored ONLY on the decorator (read it with `getRagSourceConfig`), never duplicated into
1642
+ * {@link FileSchemaMetadata}; how the file's TEXT is obtained is the sibling
1643
+ * {@link FileSchemaOptions.textExtraction} knob.
1644
+ *
1645
+ * Refused with `generation` (a PDF-template output is framework-rendered presentation, not an
1646
+ * authored corpus), and subject to the decorator chokepoint's own refusals (secrets, `.ttl()`).
1647
+ */
1648
+ ragSource?: RagSourceConfiguration;
1649
+ /**
1650
+ * Text-provider configuration for this file field (OCR opt-in). See
1651
+ * {@link FileSchemaMetadata.textExtraction} for the extraction-vs-chunking split.
1652
+ */
1653
+ textExtraction?: FileTextExtractionOptions;
1654
+ /** @wildo_source:part:end zod.decorators.file-rag-source */
1175
1655
  /**
1176
1656
  * Antivirus scan policy for this file field.
1177
1657
  * - 'required': always scan after upload, regardless of global config
@@ -1214,6 +1694,16 @@ export interface FileFieldEndpoints {
1214
1694
  override?: string;
1215
1695
  /** URL to delete a file (optional) */
1216
1696
  delete?: string;
1697
+ /**
1698
+ * Base URL of the resource-integrated file **serve** route for this field, with
1699
+ * parent/resource ids already substituted:
1700
+ * `{apiBase}/api/v1/…/{resourceId}/files/{fieldSegment}`. The display consumer
1701
+ * appends `/{fileId}` and fetches the bytes over the AUTHENTICATED client
1702
+ * (authorization inherits the parent resource's READ). Omitted when no resource
1703
+ * context is available (fail-closed to the neutral file card). This is distinct
1704
+ * from the global `/files/:fileId` download/share surface.
1705
+ */
1706
+ serve?: string;
1217
1707
  }
1218
1708
  /**
1219
1709
  * Metadata stored on versioned schemas for detection and configuration.
@@ -1235,6 +1725,29 @@ export interface VersionedForeignKeySchemaMetadata {
1235
1725
  /** The name of the target resource this foreign key references */
1236
1726
  targetResource?: string;
1237
1727
  }
1728
+ /**
1729
+ * @wildo_source:part:start zod.decorators.structural-lifecycle-params facet:layer:shared facet:layer:backend facet:family:decorator facet:family:lifecycle
1730
+ *
1731
+ * Structural and lifecycle decorator parameter types for shared resource
1732
+ * schemas.
1733
+ *
1734
+ * These shapes belong to the shared schema layer:
1735
+ * `shared-lib/src/modules/<module>/resources/<resource>/<resource>.schemas.ts`.
1736
+ *
1737
+ * They describe field behavior that affects persistence, DTO derivation,
1738
+ * security boundaries, discriminated variants, validation lifecycle, and other
1739
+ * cross-layer mechanics. They are appropriate in the shared Zod schema because
1740
+ * backend and frontend consumers both depend on the resulting metadata.
1741
+ *
1742
+ * Do NOT place per-field UI rendering configuration here. UI decorators such as
1743
+ * `.stringUI()` / `.enumUI()` belong in frontend `*.ui-behavior.tsx` files.
1744
+ * Do NOT place business-semantics prose here. `{primitive}Spec()` decorators
1745
+ * belong in specification overlays.
1746
+ *
1747
+ * When framework knowledge is generated, this anchored block is intended to be
1748
+ * inserted as the deterministic source-of-truth reference for structural
1749
+ * decorator parameters instead of maintaining parallel markdown tables.
1750
+ */
1238
1751
  export interface HiddenFieldParams {
1239
1752
  display?: boolean;
1240
1753
  edit?: boolean;
@@ -1262,6 +1775,8 @@ export declare const InlineEditSaveOn: {
1262
1775
  };
1263
1776
  export type InlineEditSaveOn = typeof InlineEditSaveOn[keyof typeof InlineEditSaveOn];
1264
1777
  /**
1778
+ * @wildo_source:part:start zod.decorators.shared-structural-params facet:layer:shared facet:family:decorator facet:family:param-surface
1779
+ *
1265
1780
  * Parameters for the isBackendOnly decorator.
1266
1781
  * Marks fields that should only exist on the backend and be stripped from API responses.
1267
1782
  */
@@ -1270,13 +1785,96 @@ export interface BackendOnlyFieldParams {
1270
1785
  * If true, the field will be included in the response for CREATE operations only,
1271
1786
  * then stripped from all subsequent READ operations.
1272
1787
  * Useful for secrets, API keys, etc. that should only be returned once.
1788
+ *
1789
+ * This is also the framework's ONLY disclosure-audit trigger: a field that carries it emits one
1790
+ * `FIELD_ACCESS` audit event at the moment it is first (and last) exposed. That pairing is not a
1791
+ * coincidence — first exposure is the only point at which a backend-only field crosses the client
1792
+ * boundary at all, so it is the only point at which "this value left the system" is a true claim.
1793
+ *
1794
+ * Scope limit worth knowing before relying on it: the audit event is raised from the TOP-LEVEL
1795
+ * shape of the response DTO. A single `CREATE` is the reliably covered case; do not assume a
1796
+ * bulk-create response gives you the same guarantee without checking.
1797
+ *
1798
+ * assurance-control: WILDO.SECRETS.DISCLOSURE_AUDIT — first disclosure of server-minted secret
1799
+ * material is attributable.
1273
1800
  */
1274
1801
  isReturnedAtCreation?: boolean;
1802
+ }
1803
+ /**
1804
+ * Parameters for the isWriteOnlySecret decorator.
1805
+ * Marks a user-provided secret that stays in CREATE/UPDATE request DTOs
1806
+ * (client-writable) but is masked to a placeholder on every client-facing
1807
+ * response DTO; the real value is retained for backend internal reads.
1808
+ * Read-side masking and the write-back sentinel are enforced by the framework
1809
+ * at the client-serialization boundary — no per-resource custom implementation
1810
+ * needed.
1811
+ *
1812
+ * Pick the right secret posture by **who owns the value and which direction it
1813
+ * flows** — the three are mutually exclusive on a field:
1814
+ * - `.isWriteOnlySecret()` — the CLIENT supplies the secret and the server keeps
1815
+ * it (e.g. a webhook signing key, an SSO client secret). Client-writable,
1816
+ * masked on read, real value kept for backend use. Re-submitting the mask is
1817
+ * a no-op (the stored value is preserved).
1818
+ * - `.isEphemeral()` — the SERVER mints the secret and hands it to the client
1819
+ * exactly once at creation (e.g. an API key shown in a one-time reveal). Not
1820
+ * client-writable, not re-readable afterwards. A composite decorator (secret
1821
+ * display + one-time reveal + not-editable).
1822
+ * - `.isBackendOnly()` — the field never crosses the client boundary in EITHER
1823
+ * direction. Do NOT use it for a client-provided secret: it strips the field
1824
+ * from the write DTOs too, so the client could never set the value.
1825
+ */
1826
+ export interface WriteOnlySecretFieldParams {
1275
1827
  /**
1276
- * If true, access to this field will be logged for audit purposes.
1277
- * Useful for sensitive data that needs audit trail.
1828
+ * Intentionally empty.
1829
+ *
1830
+ * A write-only secret is masked on EVERY client-facing response, so there is no disclosure to
1831
+ * audit — the real value never crosses the boundary. The parameter bag is kept so the decorator
1832
+ * can gain options later without changing its call shape.
1278
1833
  */
1279
- auditAccess?: boolean;
1834
+ readonly _reserved?: never;
1835
+ }
1836
+ /** @wildo_source:part:end zod.decorators.shared-structural-params */
1837
+ /**
1838
+ * Stored metadata for the impersonalization scrub treatment (`.impersonalizeWith()` /
1839
+ * `addImpersonalizeWith()`).
1840
+ *
1841
+ * This metadata deliberately stays outside the `shared-structural-params` subsection, mirroring
1842
+ * the decorator method itself. Impersonalization has distinct lifecycle and retention semantics,
1843
+ * so it needs dedicated application-facing guidance when the installed runtime exposes it.
1844
+ */
1845
+ export interface ImpersonalizeFieldParams {
1846
+ /**
1847
+ * The scrub treatment — a `RedactionType` value carried as an opaque string (zod-decorators sits
1848
+ * below saas-models and cannot reference the enum type). REQUIRED and non-empty: a field either
1849
+ * declares how it is scrubbed, or carries no treatment at all.
1850
+ */
1851
+ treatment: string;
1852
+ /**
1853
+ * `MASK` only — the literal value written in place of this field, overriding the framework's
1854
+ * default mask constant.
1855
+ *
1856
+ * **Why this exists.** The default mask is an UNCONSTRAINED string, so it cannot be written into
1857
+ * exactly the fields most likely to need masking: a CONSTRAINED string — `z.email()`, `z.uuid()`,
1858
+ * `.min(n)` — rejects it and the boot guard fails the config. Without an override, such a field
1859
+ * can only be erased by widening it to `.nullish()` for a `REMOVE` scrub. For a unique identity
1860
+ * anchor (`User.email` is the motivating case) that trades a permanently weaker type on every
1861
+ * consumer for a state only the audited see-through reader can ever observe, since a retained row
1862
+ * is hidden from every normal read. The override keeps the authored type intact.
1863
+ *
1864
+ * **Contract.** The value must satisfy the field's OWN schema — the boot guard `safeParse`s it
1865
+ * against that schema and fails loud otherwise. It is STATIC: the same value is written to every
1866
+ * row of a scrub batch (the scrub is one `$set`), so choose something meaningless as data and
1867
+ * safe to collide on. For an email, an RFC 2606 reserved `.invalid` address is the honest choice —
1868
+ * that TLD can never be registered or delivered to.
1869
+ *
1870
+ * **Collision is not a concern**, even on a `.isUnique()` field: every unique index on a
1871
+ * retention-governed resource is scoped to NON-RETAINED rows, and the scrub flips the row to
1872
+ * `RETAINED` in the same write, so scrubbed rows leave the index.
1873
+ *
1874
+ * Declaring it alongside a non-`MASK` treatment is a config error — nothing would ever write it.
1875
+ * That check lives in the saas-models boot guard, which is the layer that knows `RedactionType`.
1876
+ */
1877
+ maskValue?: string;
1280
1878
  }
1281
1879
  /**
1282
1880
  * Parameters passed to virtual field calculation functions.
@@ -1329,6 +1927,8 @@ export interface VirtualFieldParams<TObject = any, TResult = any> {
1329
1927
  dependencies?: string[];
1330
1928
  }
1331
1929
  /**
1930
+ * @wildo_source:part:start zod.decorators.shared-structural-params facet:layer:shared facet:family:decorator facet:family:param-surface
1931
+ *
1332
1932
  * Parameters for the isDiscriminator decorator.
1333
1933
  * Marks a field as the discriminator for a discriminated union schema.
1334
1934
  */
@@ -1339,7 +1939,10 @@ export interface DiscriminatorFieldParams {
1339
1939
  */
1340
1940
  baseValues?: string[];
1341
1941
  }
1942
+ /** @wildo_source:part:end zod.decorators.shared-structural-params */
1342
1943
  /**
1944
+ * @wildo_source:part:start zod.decorators.shared-structural-params facet:layer:shared facet:family:decorator facet:family:param-surface
1945
+ *
1343
1946
  * Scope for unique constraint enforcement.
1344
1947
  * - 'global': Unique across the entire collection (default)
1345
1948
  * - 'organization': Unique within an organization (compound index with organizationId)
@@ -1386,8 +1989,76 @@ export interface UniqueFieldParams {
1386
1989
  * @example "This {fieldName} is already taken"
1387
1990
  */
1388
1991
  errorMessage?: string;
1992
+ /**
1993
+ * The custom message reference the API returns when THIS field's unique index is violated.
1994
+ *
1995
+ * Without it, every duplicate-key rejection collapses to one generic conflict code, so an
1996
+ * integrator cannot tell "that slug is taken" from "that invoice number is taken" without
1997
+ * parsing a message. Naming the reference here — next to the constraint that produces it —
1998
+ * keeps one authority: the key and the error it raises cannot drift apart.
1999
+ *
2000
+ * Pass a member of the framework's error-reference vocabulary, never a bare literal.
2001
+ *
2002
+ * @example slug: z.string().isUnique({ conflictMessageReference: ErrorCustomMessageReference.ORGANIZATION_SLUG_EXISTS })
2003
+ */
2004
+ conflictMessageReference?: string;
1389
2005
  }
1390
2006
  /**
2007
+ * Parameters for the object-level `businessKeySet([...])` decorator.
2008
+ *
2009
+ * Declares a **composite business key**: the ordered list of `fields` is the stable identity of a
2010
+ * row, used both by seeding upsert / upgrade / sync passes to find an existing row independently
2011
+ * from its random `_id`, and by the storage adapter to materialize a compound UNIQUE index so the
2012
+ * identity is enforced by the database rather than by a race-prone read-then-write.
2013
+ *
2014
+ * - `fields` must be non-empty and every entry must be a key declared on the
2015
+ * underlying `ZodObject` shape (validated at decoration time).
2016
+ * - This decorator is **mutually exclusive** with field-level `isBusinessKey()`
2017
+ * on the same schema — pick one identity model.
2018
+ *
2019
+ * @example
2020
+ * // "one membership per user per organization"
2021
+ * z.object({ userId: z.string(), organizationId: z.string(), roles: z.array(z.string()) })
2022
+ * .businessKeySet(['userId', 'organizationId'])
2023
+ */
2024
+ export interface BusinessKeySetParams {
2025
+ fields: string[];
2026
+ /**
2027
+ * Fields whose ABSENCE takes a row out of the uniqueness constraint entirely.
2028
+ *
2029
+ * By default a missing member counts as a real value, so two rows that both omit it COLLIDE.
2030
+ * That is the correct default for an identity whose members are always meaningful — two rows
2031
+ * that are "unscoped" in the same way really are the same row.
2032
+ *
2033
+ * It is wrong when a member is optional in the domain sense: "unit code, unique among siblings"
2034
+ * must still allow any number of siblings that carry NO code. Listing that field here scopes the
2035
+ * constraint to the rows that actually have it.
2036
+ *
2037
+ * Every entry must also appear in `fields`. List only the members whose absence means "this row
2038
+ * has no key", never merely "this member happens to be optional" — a field left out of the list
2039
+ * keeps the default null-collides behaviour, which is what most composite keys want.
2040
+ *
2041
+ * @example
2042
+ * // many code-less siblings are fine; two siblings sharing a code are not
2043
+ * .businessKeySet(['organizationId', 'parentUnitId', 'code'], { skipRowsMissing: ['code'] })
2044
+ */
2045
+ skipRowsMissing?: string[];
2046
+ /**
2047
+ * The custom message reference the API returns when THIS key's unique index is violated.
2048
+ *
2049
+ * Without it, every duplicate-key rejection collapses to one generic conflict code, so an
2050
+ * integrator cannot tell which identity was violated without parsing a message. Naming the
2051
+ * reference here — next to the key that produces it — keeps one authority: the key and the error
2052
+ * it raises cannot drift apart.
2053
+ *
2054
+ * Pass a member of the framework's error-reference vocabulary, never a bare literal.
2055
+ */
2056
+ conflictMessageReference?: string;
2057
+ }
2058
+ /** @wildo_source:part:end zod.decorators.shared-structural-params */
2059
+ /**
2060
+ * @wildo_source:part:start zod.decorators.shared-structural-params facet:layer:shared facet:family:decorator facet:family:param-surface
2061
+ *
1391
2062
  * Parameters for the ttl decorator.
1392
2063
  * Marks a Date field for TTL (Time To Live) expiration in MongoDB.
1393
2064
  * MongoDB will automatically delete documents when the TTL expires.
@@ -1414,6 +2085,7 @@ export interface TtlFieldParams {
1414
2085
  */
1415
2086
  expireAfterSeconds: number;
1416
2087
  }
2088
+ /** @wildo_source:part:end zod.decorators.shared-structural-params */
1417
2089
  /**
1418
2090
  * Parameters for the isOtp decorator.
1419
2091
  * Configures the OTP (One-Time Password) input field behavior.
@@ -1436,6 +2108,8 @@ export interface OtpFieldParams {
1436
2108
  maxLength?: number;
1437
2109
  }
1438
2110
  /**
2111
+ * @wildo_source:part:start zod.decorators.shared-structural-params facet:layer:shared facet:family:decorator facet:family:param-surface
2112
+ *
1439
2113
  * Parameters for the isSummaryField decorator.
1440
2114
  * Controls how summary fields are handled, particularly for foreign key population.
1441
2115
  */
@@ -1464,6 +2138,7 @@ export interface SummaryFieldParams {
1464
2138
  */
1465
2139
  populate?: boolean;
1466
2140
  }
2141
+ /** @wildo_source:part:end zod.decorators.shared-structural-params */
1467
2142
  /**
1468
2143
  * Validation mode for form fields.
1469
2144
  * Configures when field validation is triggered.
@@ -1509,7 +2184,10 @@ export interface AutosaveFieldParams {
1509
2184
  */
1510
2185
  debounceMs?: number;
1511
2186
  }
2187
+ /** @wildo_source:part:end zod.decorators.structural-lifecycle-params */
1512
2188
  /**
2189
+ * @wildo_source:part:start zod.decorators.conditional-visibility facet:layer:frontend facet:family:form facet:surface:conditional
2190
+ *
1513
2191
  * FIX-P5-H1: Operator for showWhen condition comparison.
1514
2192
  * - EQUALS: Field value equals the specified value
1515
2193
  * - NOT_EQUALS: Field value does not equal the specified value
@@ -1550,6 +2228,11 @@ export interface ShowWhenCondition {
1550
2228
  * FIX-P5-H1: Parameters for the showWhen decorator.
1551
2229
  * Configures conditional visibility for form fields.
1552
2230
  *
2231
+ * Available on every form-field type — each primitive, plus object and array, plus the `optional` /
2232
+ * `default` / `nullable` wrappers — matching `ZodDecorator_ApplyableType[SHOW_WHEN]`. The bare form
2233
+ * below is the documented one and works as written; before 2026-08-12 it threw, because the
2234
+ * decorator was installed on the wrapper prototypes only.
2235
+ *
1553
2236
  * @example
1554
2237
  * ```ts
1555
2238
  * // Show when 'type' field equals 'advanced'
@@ -1559,7 +2242,12 @@ export interface ShowWhenCondition {
1559
2242
  *
1560
2243
  * // Show when 'type' is one of multiple values
1561
2244
  * featureOption: z.string().showWhen({
1562
- * conditions: { field: 'type', value: ['pro', 'enterprise'], operator: 'in' }
2245
+ * conditions: { field: 'type', value: ['pro', 'enterprise'], operator: ShowWhenOperator.IN }
2246
+ * })
2247
+ *
2248
+ * // On a defaulted field — the shape used by Wonder Todos' `reminder.leadTimeMinutes`
2249
+ * leadTimeMinutes: z.number().int().default(30).showWhen({
2250
+ * conditions: { field: 'enabled', value: true }
1563
2251
  * })
1564
2252
  *
1565
2253
  * // Show when both conditions are met
@@ -1586,6 +2274,7 @@ export interface ShowWhenParams {
1586
2274
  */
1587
2275
  combineWith?: 'and' | 'or';
1588
2276
  }
2277
+ /** @wildo_source:part:end zod.decorators.conditional-visibility */
1589
2278
  /**
1590
2279
  * Parameters for the isDraftable decorator.
1591
2280
  * Configures draft mode behavior at the schema level.
@@ -1638,6 +2327,8 @@ export interface BooleanLabellingCustomParams {
1638
2327
  falseValue: string;
1639
2328
  }
1640
2329
  /**
2330
+ * @wildo_source:part:start zod.decorators.primitive-ui
2331
+ *
1641
2332
  * Display-context base params.
1642
2333
  * Controls chrome, inline editing, and tooltip behavior when a field is rendered in a read-only view.
1643
2334
  */
@@ -1650,6 +2341,23 @@ export interface PrimitiveUIBaseDisplayParams {
1650
2341
  forceHide?: ResponsiveAware<ForceHideDisplayConfig>;
1651
2342
  /** Whether to show a tooltip icon in display chrome. Text comes from i18n. */
1652
2343
  tooltip?: boolean;
2344
+ /**
2345
+ * When `true`, the field is omitted entirely from the DISPLAY (read) surface
2346
+ * whenever its value is empty — null, undefined, an empty string, or an empty
2347
+ * array. The whole row (label + chrome + em-dash placeholder) is removed, not
2348
+ * just the value.
2349
+ *
2350
+ * DISPLAY-ONLY: the edit form always renders the field so an empty value can
2351
+ * still be filled in. This is the field-level counterpart to the section-level
2352
+ * `SectionConfigBase.hideWhenEmpty` and to the surface-policy
2353
+ * `AutoEmptyValue.HIDDEN` — use it to keep optional metadata (a job title, a
2354
+ * secondary contact) from cluttering a read view when unset.
2355
+ *
2356
+ * @example
2357
+ * // Hide the "Title" row on the profile read view until the user sets one:
2358
+ * schemaShape.title.stringUI({ display: { hideWhenEmpty: true } })
2359
+ */
2360
+ hideWhenEmpty?: boolean;
1653
2361
  /**
1654
2362
  * Opt-in for description text below the field value in display mode.
1655
2363
  * When true, the companion generates an i18n key for the description.
@@ -1681,6 +2389,14 @@ export interface PrimitiveUIBaseEditParams {
1681
2389
  tooltip?: boolean;
1682
2390
  /** Auto-focus this field when the form mounts. */
1683
2391
  autoFocus?: boolean;
2392
+ /** Official HTML autocomplete field identifier for browser autofill. */
2393
+ autoComplete?: AutocompleteFieldIdentifier;
2394
+ /**
2395
+ * Optional official HTML autocomplete modifiers.
2396
+ * Supports a single modifier or an array. `section-*` is intentionally excluded
2397
+ * from this typed contract and can be added later via a dedicated API if needed.
2398
+ */
2399
+ autoCompleteModifier?: AutocompleteModifier | AutocompleteModifier[];
1684
2400
  /**
1685
2401
  * Opt-in for description/helper text below the form input in edit mode.
1686
2402
  * When true, the companion generates an i18n key for the description.
@@ -1704,6 +2420,29 @@ export interface PrimitiveUIBaseParams {
1704
2420
  /** Config for Edition context (forms). */
1705
2421
  edit?: PrimitiveUIBaseEditParams;
1706
2422
  }
2423
+ /** @wildo_source:part:end zod.decorators.primitive-ui */
2424
+ /**
2425
+ * @wildo_source:part:start zod.decorators.per-primitive-ui facet:layer:frontend facet:family:ui facet:surface:form facet:surface:display
2426
+ *
2427
+ * Per-primitive frontend UI decorator parameter types.
2428
+ *
2429
+ * These interfaces define the arguments accepted by decorators such as
2430
+ * `.stringUI()`, `.numberUI()`, `.enumUI()`, `.booleanUI()`, `.moneyUI()`,
2431
+ * `.foreignKeyUI()`, etc.
2432
+ *
2433
+ * They belong to the frontend resource behavior layer, not to shared resource
2434
+ * schemas. In application code, they are typically authored in files like:
2435
+ * `frontend/src/modules/<module>/resources/<resource>/<resource>.ui-behavior.tsx`
2436
+ *
2437
+ * The shared schema establishes structural meaning (`isSummaryField`,
2438
+ * `isForeignKey`, `excludeFromUpdate`, ...). These UI parameter types control
2439
+ * presentation concerns such as display widgets, edit widgets, chrome modes,
2440
+ * per-enum colors/icons, inline editing, and layout details.
2441
+ *
2442
+ * Generated framework knowledge should prefer extracting these definitions from
2443
+ * source rather than restating the supported UI parameters in handcrafted
2444
+ * markdown documents.
2445
+ */
1707
2446
  export interface BooleanUIDisplayParams extends PrimitiveUIBaseDisplayParams {
1708
2447
  /** Display renderer. RAW = plain text, CHECKMARK = checkmark/cross, EDIT_LIKE = shows the edit control read-only. */
1709
2448
  displayMode?: BooleanDisplayMode;
@@ -1723,10 +2462,18 @@ export interface BooleanUIParams {
1723
2462
  edit?: BooleanUIEditParams;
1724
2463
  }
1725
2464
  export interface StringUIDisplayParams extends PrimitiveUIBaseDisplayParams {
1726
- /** Display renderer. TEXT | TRUNCATE | MULTILINE | COLOR | LINK | EMAIL | BADGE | COPY | SECRET. */
2465
+ /** Display renderer. TEXT | TRUNCATE | MULTILINE | MARKDOWN | COLOR | LINK | EMAIL | BADGE | COPY | SECRET. */
1727
2466
  displayMode?: StringDisplayMode;
1728
2467
  /** Max characters before truncation (TRUNCATE displayMode only). */
1729
2468
  truncateLength?: number;
2469
+ /**
2470
+ * SECRET displayMode only: render the value revealed (not masked) on first
2471
+ * paint. Defaults to `false` (masked, reveal via the eye toggle) for secrets
2472
+ * shown in persistent surfaces. `.isEphemeral()` sets this `true` because an
2473
+ * ephemeral one-time-reveal exists precisely so the caller can read + copy the
2474
+ * secret immediately; the toggle still lets them re-hide it.
2475
+ */
2476
+ initiallyRevealed?: boolean;
1730
2477
  }
1731
2478
  export interface StringUIEditParams extends PrimitiveUIBaseEditParams {
1732
2479
  /** Edit control. INPUT | TEXTAREA | COLOR | PASSWORD | OTP. */
@@ -1833,7 +2580,28 @@ export interface CodeUIParams {
1833
2580
  summaryOverride?: CodeUIDisplayParams;
1834
2581
  edit?: CodeUIEditParams;
1835
2582
  }
1836
- export type FileUIDisplayParams = PrimitiveUIBaseDisplayParams;
2583
+ export interface FileUIDisplayParams extends PrimitiveUIBaseDisplayParams {
2584
+ /**
2585
+ * How the file renders AT REST — see {@link FileDisplayPresentation}. Media display
2586
+ * is never mandatory: the default is the neutral file card, and `THUMBNAIL`/`FULL`
2587
+ * are opt-in. Rendered media is fetched over the authenticated resource-integrated
2588
+ * serve route (authz inherits the parent READ).
2589
+ * @default FileDisplayPresentation.CARD
2590
+ */
2591
+ presentation?: FileDisplayPresentation;
2592
+ /**
2593
+ * What activating the file does — see {@link FileActivationConfig}. Applies to every
2594
+ * nature. Omit for the nature-derived default: `OVERLAY` when a displayer exists for
2595
+ * the resolved nature, `DOWNLOAD` otherwise.
2596
+ */
2597
+ activation?: FileActivationConfig;
2598
+ /**
2599
+ * Presentation detail for rendered media (shape / size / caption). Applies when
2600
+ * `presentation` is `THUMBNAIL` or `FULL`; ignored by `CARD`.
2601
+ * @example { shape: FileMediaShape.CIRCLE, size: FileMediaSize.MD, showCaption: false } // avatar
2602
+ */
2603
+ preview?: FileMediaPreviewOptions;
2604
+ }
1837
2605
  export type FileUIEditParams = PrimitiveUIBaseEditParams;
1838
2606
  export interface FileUIParams {
1839
2607
  display?: FileUIDisplayParams;
@@ -1896,7 +2664,18 @@ export interface ForeignKeyUIDisplayParams extends PrimitiveUIBaseDisplayParams
1896
2664
  /** Override the preset used to display the referenced resource summary. */
1897
2665
  displayPresetOverride?: string;
1898
2666
  }
1899
- export type ForeignKeyUIEditParams = PrimitiveUIBaseEditParams;
2667
+ export interface ForeignKeyUIEditParams extends PrimitiveUIBaseEditParams {
2668
+ /**
2669
+ * How each RESULT in the reference picker's dropdown renders — applies to both
2670
+ * the form picker and the collection filter picker (they share one component):
2671
+ * - `LABEL` (default): a one-line resource label (via `getFrontendResourceLabel`).
2672
+ * - `SUMMARY`: the referenced resource's summary view — its summary fields with
2673
+ * NO action bar — rendered via `ResourceSummaryDisplayer`.
2674
+ * `ID` is treated as `LABEL` here (a raw id is not a useful picker row). Only the
2675
+ * dropdown options are affected; the selected value still shows as a label.
2676
+ */
2677
+ optionDisplayMode?: ForeignKeyDisplayMode;
2678
+ }
1900
2679
  export interface ForeignKeyUIParams {
1901
2680
  display?: ForeignKeyUIDisplayParams;
1902
2681
  summaryOverride?: ForeignKeyUIDisplayParams;
@@ -1908,6 +2687,38 @@ export interface ArrayUIDisplayParams extends PrimitiveUIBaseDisplayParams {
1908
2687
  /** Max items shown in display (rest truncated). */
1909
2688
  maxItems?: number;
1910
2689
  }
2690
+ /**
2691
+ * How NEW items are added to an array field in an edit / inline-edit surface.
2692
+ *
2693
+ * When unset, the renderer resolves a default by item shape: a SIMPLE item
2694
+ * (a primitive, or an object with a single prominent authored field — e.g. a
2695
+ * checklist `{ label, done }`) defaults to {@link ArrayAddMode.QUICK_ADD}; a
2696
+ * MULTI-field object defaults to {@link ArrayAddMode.APPEND_INLINE}.
2697
+ *
2698
+ * The key distinction is WHEN the new item is validated:
2699
+ * - `APPEND_INLINE` validates AFTER append (a freshly-added required field shows
2700
+ * its error until filled);
2701
+ * - `QUICK_ADD` / `DIALOG` validate BEFORE append (the list never holds a blank
2702
+ * or invalid item).
2703
+ */
2704
+ export declare enum ArrayAddMode {
2705
+ /**
2706
+ * "+ Add" appends a blank, in-place editable item card/row; validated AFTER
2707
+ * it is added. Best for rich objects the author edits in place.
2708
+ */
2709
+ APPEND_INLINE = "append-inline",
2710
+ /**
2711
+ * A single inline add-row (the item's primary field + Enter / "+"). The item
2712
+ * is built from the row and validated BEFORE it is appended, so the list never
2713
+ * holds a blank/invalid item. Best for simple items — checklists.
2714
+ */
2715
+ QUICK_ADD = "quick-add",
2716
+ /**
2717
+ * "+ Add" opens a dialog with the item's form; the item is validated on submit
2718
+ * and then appended. Best for complex, multi-field items.
2719
+ */
2720
+ DIALOG = "dialog"
2721
+ }
1911
2722
  export interface ArrayUIEditParams extends PrimitiveUIBaseEditParams {
1912
2723
  /** Allow reordering via drag-and-drop in edit context. Set via `.isSortable()` convenience or directly. */
1913
2724
  isSortable?: boolean;
@@ -1915,11 +2726,41 @@ export interface ArrayUIEditParams extends PrimitiveUIBaseEditParams {
1915
2726
  dnd?: boolean;
1916
2727
  /** Show up/down manual move buttons. */
1917
2728
  upDownIcons?: boolean;
2729
+ /**
2730
+ * How new items are added (append-inline / quick-add / dialog). When unset,
2731
+ * the renderer picks a default by item shape — see {@link ArrayAddMode}.
2732
+ */
2733
+ addMode?: ArrayAddMode;
2734
+ }
2735
+ /**
2736
+ * How each item of an OBJECT array (`z.array(z.object({...}))`) is framed in
2737
+ * BOTH display and edit surfaces.
2738
+ *
2739
+ * - `CARD` (default) — each item is a framed card (border + padding) with a
2740
+ * floating summary chip and a stacked column of its sub-fields. Best for
2741
+ * rich, multi-field items the author edits in place.
2742
+ * - `ROW` — each item is a compact single-row: its sub-fields render inline
2743
+ * (boolean fields lead as compact toggles — the "☐" of a checklist — then
2744
+ * the primary field fills the row), reorder/remove controls inline, NO card
2745
+ * frame or floating chip. Best for lists of small objects — checklists,
2746
+ * tag/value pairs, key-value rows.
2747
+ *
2748
+ * Applies to object-array items only; primitive arrays already render as rows.
2749
+ */
2750
+ export declare enum ArrayObjectItemLayout {
2751
+ CARD = "card",
2752
+ ROW = "row"
1918
2753
  }
1919
2754
  export interface ArrayUIParams {
1920
2755
  display?: ArrayUIDisplayParams;
1921
2756
  summaryOverride?: ArrayUIDisplayParams;
1922
2757
  edit?: ArrayUIEditParams;
2758
+ /**
2759
+ * How OBJECT-array items are framed (card vs compact row). Governs display
2760
+ * AND edit/inline-edit rendering. Defaults to {@link ArrayObjectItemLayout.CARD}.
2761
+ * No effect on primitive arrays. See {@link ArrayObjectItemLayout}.
2762
+ */
2763
+ objectItemLayout?: ArrayObjectItemLayout;
1923
2764
  }
1924
2765
  export interface ObjectUIDisplayParams extends PrimitiveUIBaseDisplayParams {
1925
2766
  /** Direction for rendering properties in display context. */
@@ -1933,6 +2774,230 @@ export interface ObjectUIParams {
1933
2774
  summaryOverride?: ObjectUIDisplayParams;
1934
2775
  edit?: ObjectUIEditParams;
1935
2776
  }
2777
+ /** @wildo_source:part:end zod.decorators.per-primitive-ui */
2778
+ /**
2779
+ * @wildo_source:part:start zod.decorators.field-spec-params facet:layer:specification facet:family:companion facet:family:semantics
2780
+ *
2781
+ * Semantic specification parameter types for companion/specification overlays.
2782
+ *
2783
+ * These types are intentionally separate from both:
2784
+ * - shared schema structural decorators (`*.schemas.ts`)
2785
+ * - frontend UI decorators (`*.ui-behavior.tsx`)
2786
+ *
2787
+ * `{primitive}Spec()` calls belong in specification-side files such as
2788
+ * `specifications/src/modules/<module>/resources/<resource>.resource.specification.ts`.
2789
+ * They enrich schema fields with business meaning, importance, enum value
2790
+ * semantics, relationship context, and import-oriented symbol references used by
2791
+ * companion-time reasoning and code generation.
2792
+ *
2793
+ * These params should carry meaning that cannot be deterministically inferred
2794
+ * from the Zod type, requiredness, or structural decorators alone.
2795
+ */
2796
+ /**
2797
+ * Relative weight of a semantic entry inside its owning resource.
2798
+ *
2799
+ * Not about technical optionality — tells the AI how central a field is
2800
+ * to understanding the resource:
2801
+ * - PRIMARY: core to understanding or using the resource correctly.
2802
+ * The AI should prioritize these in summaries, forms, and behavior generation.
2803
+ * - CONTEXTUAL: provides useful context but is not central.
2804
+ * The AI can include or omit based on available space/attention.
2805
+ *
2806
+ * Default is CONTEXTUAL — only genuinely important fields should be explicitly
2807
+ * flagged as PRIMARY.
2808
+ */
2809
+ export declare enum FieldSemanticImportance {
2810
+ PRIMARY = "primary",
2811
+ CONTEXTUAL = "contextual"
2812
+ }
2813
+ /**
2814
+ * Base field specification parameters shared by all `{primitive}Spec()` decorators.
2815
+ *
2816
+ * Carries the semantic delta that the Zod schema definition alone cannot convey:
2817
+ * domain meaning, business relevance, and guidance for the AI companion.
2818
+ *
2819
+ * These values are **never rendered in the frontend UI** — they exist on the
2820
+ * schema metadata for companion-time extraction only. The `{primitive}Spec()` calls
2821
+ * happen in the specification overlay (which the frontend never imports), so
2822
+ * the prose is attached to schema instances only in companion/test contexts.
2823
+ *
2824
+ * Do not duplicate information already expressed by the schema type, requiredness,
2825
+ * enum values, or structural decorators. This is for meaning that is not derivable.
2826
+ */
2827
+ export declare enum CodeSymbolKind {
2828
+ SCHEMA = "schema",
2829
+ ENUM = "enum",
2830
+ FACTORY = "factory",
2831
+ FUNCTION = "function",
2832
+ CONFIG = "config",
2833
+ TYPE = "type",
2834
+ COMPONENT = "component",
2835
+ UI_BEHAVIOR = "uiBehavior"
2836
+ }
2837
+ export declare enum CodeDeclarationKind {
2838
+ TYPESCRIPT_ENUM = "typescriptEnum",
2839
+ CONST_OBJECT = "constObject",
2840
+ ZOD_ENUM = "zodEnum",
2841
+ LITERAL_UNION = "literalUnion",
2842
+ ZOD_SCHEMA = "zodSchema",
2843
+ FUNCTION = "function",
2844
+ INTERFACE = "interface",
2845
+ TYPE_ALIAS = "typeAlias",
2846
+ UNKNOWN = "unknown"
2847
+ }
2848
+ /**
2849
+ * Public-import-oriented symbol reference used by semantic specifications.
2850
+ *
2851
+ * Downstream transposers/prompts should prefer these refs over file-path
2852
+ * guesses so generated code imports the right public symbol.
2853
+ */
2854
+ export interface CodeSymbolRef {
2855
+ /** Package name to import from (for example `@wildo-ai/saas-models`). */
2856
+ packageName: string;
2857
+ /** Optional public subpath when the package root is not the import target. */
2858
+ importPath?: string;
2859
+ /** Literal exported symbol name. */
2860
+ exportName: string;
2861
+ /** High-level category of symbol. */
2862
+ symbolKind: CodeSymbolKind;
2863
+ /** More specific declaration family for code-generation handling. */
2864
+ declarationKind?: CodeDeclarationKind;
2865
+ /** Optional local-path hint for companion-side tooling/debugging. */
2866
+ filePathHint?: string;
2867
+ /** Extra caveats or usage notes for downstream prompts. */
2868
+ notes?: string[];
2869
+ }
2870
+ /**
2871
+ * Reference to one member of a declared enum/const-object vocabulary.
2872
+ */
2873
+ export interface CodeEnumMemberRef {
2874
+ /** Declared enum/const-object that owns the member. */
2875
+ enumDeclaration: CodeSymbolRef;
2876
+ /** Literal member name on that declaration (for example `USERS`). */
2877
+ memberName: string;
2878
+ }
2879
+ export declare enum CollectionElementKind {
2880
+ PRIMITIVE = "primitive",
2881
+ ENUM = "enum",
2882
+ FOREIGN_KEY = "foreignKey",
2883
+ OBJECT = "object",
2884
+ SCHEMA_REF = "schemaRef",
2885
+ UNION = "union",
2886
+ UNKNOWN = "unknown"
2887
+ }
2888
+ export declare enum CodePrimitiveKind {
2889
+ STRING = "string",
2890
+ NUMBER = "number",
2891
+ BOOLEAN = "boolean",
2892
+ DATE = "date",
2893
+ DATETIME = "datetime",
2894
+ TIME = "time",
2895
+ MONEY = "money",
2896
+ CODE = "code",
2897
+ FILE = "file",
2898
+ DURATION = "duration",
2899
+ PHONE = "phone",
2900
+ BIGDECIMAL = "bigdecimal",
2901
+ UNKNOWN = "unknown"
2902
+ }
2903
+ /**
2904
+ * Author-only metadata for array elements.
2905
+ *
2906
+ * `elementMeaning` (on `ArraySpecParams`) explains business semantics; this
2907
+ * shape captures the **author-only** overlays that the framework cannot
2908
+ * derive on its own: a public `enumDeclaration` for ENUM/UNION-of-ENUM
2909
+ * branches and free-form `notes`.
2910
+ *
2911
+ * This shape intentionally excludes `kind`, `primitiveType`,
2912
+ * `schemaDeclaration` and `foreignKeyTargetResource`. The schema and
2913
+ * relationship declarations already provide those structural facts, so
2914
+ * repeating them here would create two sources of truth.
2915
+ *
2916
+ * Authors keep `enumDeclaration` so the companion can render `Use member X
2917
+ * from ENUM_NAME imported via PACKAGE` lines without re-walking the enum
2918
+ * to find its public symbol — there is no Zod-side metadata that carries
2919
+ * the public import path. UNION branches that are themselves enums also
2920
+ * reuse the parent `enumDeclaration` (the dominant vocabulary).
2921
+ */
2922
+ export interface ArrayElementTypeSpec {
2923
+ /** Named enum/const-object declaration when elements use a vocabulary. */
2924
+ enumDeclaration?: CodeSymbolRef;
2925
+ /** Extra caveats for downstream coding prompts. */
2926
+ notes?: string[];
2927
+ }
2928
+ export interface FieldSpecBaseParams {
2929
+ /** Business meaning of the field: what it represents in the domain. */
2930
+ meaning: string;
2931
+ /** Why the AI should care about this field when authoring behavior or UI. */
2932
+ whyItMatters?: string;
2933
+ /** Relative weight of this field in the resource understanding. */
2934
+ importance?: FieldSemanticImportance;
2935
+ }
2936
+ export interface StringSpecParams extends FieldSpecBaseParams {
2937
+ /** Semantic role of the string content in the domain. */
2938
+ semanticRole?: 'identifier' | 'name' | 'description' | 'content' | 'label' | 'code' | 'uri';
2939
+ }
2940
+ export interface NumberSpecParams extends FieldSpecBaseParams {
2941
+ /** Business unit of the numeric value (e.g., "days", "percentage", "count"). */
2942
+ unit?: string;
2943
+ }
2944
+ export type BooleanSpecParams = FieldSpecBaseParams;
2945
+ export interface DateSpecParams extends FieldSpecBaseParams {
2946
+ /** Temporal semantic role (e.g., deadline, creation timestamp, expiration). */
2947
+ temporalRole?: 'deadline' | 'creation' | 'expiration' | 'scheduled' | 'occurred' | 'modified';
2948
+ }
2949
+ export type DateTimeSpecParams = DateSpecParams;
2950
+ export type TimeSpecParams = FieldSpecBaseParams;
2951
+ /** Per-value semantic meaning for an enum field. */
2952
+ export interface EnumValueSpecConfig {
2953
+ /** What this enum value means in business terms. */
2954
+ meaning: string;
2955
+ }
2956
+ export interface EnumSpecParams extends FieldSpecBaseParams {
2957
+ /** Per-value business semantics — keyed by enum value. */
2958
+ values?: Record<string, EnumValueSpecConfig>;
2959
+ /** Public declaration that owns the enum vocabulary. */
2960
+ enumDeclaration?: CodeSymbolRef;
2961
+ }
2962
+ export type MoneySpecParams = FieldSpecBaseParams;
2963
+ export type CodeSpecParams = FieldSpecBaseParams;
2964
+ export type FileSpecParams = FieldSpecBaseParams;
2965
+ export type DurationSpecParams = FieldSpecBaseParams;
2966
+ export type PhoneSpecParams = FieldSpecBaseParams;
2967
+ export interface BigDecimalSpecParams extends FieldSpecBaseParams {
2968
+ /** Business unit of the value (e.g., "currency", "weight", "rate"). */
2969
+ unit?: string;
2970
+ }
2971
+ export interface ForeignKeySpecParams extends FieldSpecBaseParams {
2972
+ /** Business meaning of the relationship this FK represents. */
2973
+ relationshipContext?: string;
2974
+ }
2975
+ export interface ArraySpecParams extends FieldSpecBaseParams {
2976
+ /** Business meaning of each element in the collection. */
2977
+ elementMeaning?: string;
2978
+ /** Structural/code-handling description of each array element. */
2979
+ elementType?: ArrayElementTypeSpec;
2980
+ }
2981
+ /**
2982
+ * Object-spec params are intentionally identical to the base shape.
2983
+ *
2984
+ * The decorator keeps a distinct semantic identity (an `objectSpec()` call
2985
+ * marks a nested structure as field-spec-bearing for completeness checks),
2986
+ * but it carries no extra structural metadata: nested-structure shape and
2987
+ * any `schemaDeclaration` are derivable from the Zod object itself, and
2988
+ * `structureRole` overlapped with the base `meaning` field with no clear
2989
+ * delineation.
2990
+ *
2991
+ * The type intentionally adds no separate structural metadata: duplicating
2992
+ * the base semantics would make nested-object authoring ambiguous.
2993
+ */
2994
+ export type ObjectSpecParams = FieldSpecBaseParams;
2995
+ /** @wildo_source:part:end zod.decorators.field-spec-params */
2996
+ /**
2997
+ * @wildo_source:part:start zod.decorators.decorator-vocabulary
2998
+ *
2999
+ * Canonical string identifiers for framework Zod field decorators (`ZodDecorator` enum).
3000
+ */
1936
3001
  export declare enum ZodDecorator {
1937
3002
  IS_DB_INDEXED = "isDBIndexed",
1938
3003
  IS_FOREIGN_KEY = "isForeignKey",
@@ -1940,12 +3005,168 @@ export declare enum ZodDecorator {
1940
3005
  IS_NOT_EDITABLE = "isNotEditable",
1941
3006
  IS_SUMMARY_FIELD = "isSummaryField",
1942
3007
  IS_BACKEND_ONLY = "isBackendOnly",
3008
+ IS_WRITE_ONLY_SECRET = "isWriteOnlySecret",
3009
+ /**
3010
+ * Impersonalization: per-field erasure-scrub treatment — a `RedactionType` value (string),
3011
+ * read by the saas-models impersonalize writer. NOT the anonymous-user concept.
3012
+ *
3013
+ * Authored fluently: `z.string().nullish().impersonalizeWith(RedactionType.REMOVE)`. The
3014
+ * treatment is REQUIRED and must be a non-empty string — a blank/missing value throws at
3015
+ * decoration time rather than silently leaving the field untreated (an unscrubbed personal
3016
+ * field). `addImpersonalizeWith(schema, treatment)` is the equivalent programmatic escape hatch;
3017
+ * read the treatment back with `getImpersonalizeTreatment(schema)`.
3018
+ *
3019
+ * A `MASK` treatment may carry a field-specific mask value —
3020
+ * `addImpersonalizeWith(schema, RedactionType.MASK, { maskValue: 'erased@erased.invalid' })` —
3021
+ * for a CONSTRAINED string the default mask constant cannot satisfy; read it back with
3022
+ * `getImpersonalizeMaskValue(schema)`. Both authoring doors normalize to
3023
+ * {@link ImpersonalizeFieldParams}, which is what this decorator stores.
3024
+ */
3025
+ IMPERSONALIZE_WITH = "impersonalizeWith",
3026
+ /**
3027
+ * Portability: where this field's value CAME FROM — a `DataPortabilityProvenance` value (string),
3028
+ * read by the subject-export orchestrator to decide GDPR Art. 20 scope.
3029
+ *
3030
+ * Authored fluently: `z.string().portabilityProvenance(DataPortabilityProvenance.SUBJECT_PROVIDED)`.
3031
+ * The value is REQUIRED and must be a non-empty string — a blank/missing value throws at
3032
+ * decoration time rather than storing an undeclared provenance, which an Art. 20 export treats as
3033
+ * a REFUSAL rather than guessing. `addPortabilityProvenance(schema, provenance)` is the equivalent
3034
+ * programmatic escape hatch; read it back with `getPortabilityProvenance(schema)`.
3035
+ *
3036
+ * A field that carries no declaration inherits its resource's `portabilityPolicy.defaultProvenance`;
3037
+ * only fields differing from that default need this decorator.
3038
+ *
3039
+ * ⚠️ NOT a redaction or scrub concept, and NOT the anonymous-user concept. This says where a value
3040
+ * ORIGINATED, for a DISCLOSURE decision. What happens to a value on ERASURE is
3041
+ * {@link ZodDecorator.IMPERSONALIZE_WITH}, an orthogonal axis — a field is commonly both
3042
+ * `SUBJECT_PROVIDED` and masked on erasure.
3043
+ */
3044
+ PORTABILITY_PROVENANCE = "portabilityProvenance",
3045
+ /**
3046
+ * Data categories: WHICH KINDS of personal data this field holds — one or more
3047
+ * `PersonalDataCategory` values (strings), read by the compliance fact producer to answer the
3048
+ * privacy-notice question "which categories of personal data do you process".
3049
+ *
3050
+ * Authored fluently: `email: z.email().dataCategories(PersonalDataCategory.CONTACT_DETAILS)`, or
3051
+ * with an array when a field genuinely spans two —
3052
+ * `.dataCategories([PersonalDataCategory.USER_CONTENT, PersonalDataCategory.SPECIAL_CATEGORY_HEALTH])`.
3053
+ * The chokepoint normalizes either form to a deduped array, so every reader sees one shape.
3054
+ * At least one category is REQUIRED and each must be a non-empty string: a blank declaration
3055
+ * would read back as declared-but-meaningless, which is worse than absent, because absence is
3056
+ * what the gap report is looking for. `addDataCategories(schema, categories)` is the equivalent
3057
+ * programmatic escape hatch; read them back with `getDataCategories(schema)`.
3058
+ *
3059
+ * WHETHER each value is a real `PersonalDataCategory` member is checked by the resource factory's
3060
+ * boot guard, which owns the enum — this layer knows only that non-empty strings were declared.
3061
+ *
3062
+ * ⚠️ Four adjacent axes, none of them this one. {@link ZodDecorator.IMPERSONALIZE_WITH} says what
3063
+ * happens to the value on ERASURE; {@link ZodDecorator.PORTABILITY_PROVENANCE} says where it CAME
3064
+ * FROM; `Compliance_DataClassification` is a SENSITIVITY ladder for flows-actors config; a
3065
+ * retention class says HOW LONG it is kept. A single field is routinely all five at once, and
3066
+ * none of the other four can answer "what kind of personal data is this".
3067
+ *
3068
+ * ⚠️ Do NOT declare a category on a field merely because its NAME suggests one. The decorator
3069
+ * exists precisely so categories are never derived from identifiers: `email`, `phone` and
3070
+ * `dateOfBirth` are suggestive while `notes` is not, and an inventory assembled by
3071
+ * pattern-matching names is a guess whose misses are silently undisclosed. `CREDENTIALS` is the
3072
+ * one category the producer derives, and it derives it from `.isPassword()` / `.isOtp()` /
3073
+ * `.isWriteOnlySecret()` — markers the author wrote, not names it read.
3074
+ *
3075
+ * assurance-control: WILDO.PRIVACY.PERSONAL_DATA_INVENTORY — the application declares which
3076
+ * categories of personal data each field holds
3077
+ */
3078
+ DATA_CATEGORIES = "dataCategories",
3079
+ /**
3080
+ * Audit evidence: this field's BEFORE/AFTER VALUES are recorded when a resource operation
3081
+ * mutates it, on the `resource_operation_performed` audit event.
3082
+ *
3083
+ * Authored fluently: `appRoles: z.array(z.string()).isAuditEvidence()`. A pure marker — no
3084
+ * parameters, no implied decorators. `addAuditEvidence(schema)` is the equivalent programmatic
3085
+ * escape hatch; read it back with `isAuditEvidenceField(schema)`.
3086
+ *
3087
+ * **Mark the fields whose VALUES are the evidence, and only those.** The audit event always
3088
+ * records the NAMES of every changed field (a field name is not personal data). This marker adds
3089
+ * the values, and values are the part that must be justified: audit rows replicate to the per-org
3090
+ * SIEM and to the immutable ledger, and the ledger cannot be scrubbed — so marking a personal-data
3091
+ * field manufactures an unerasable copy of it, defeating the impersonalization/retention
3092
+ * capability. Mark authority (`appRoles`, `roles`), lifecycle state (`status`), and scope-bearing
3093
+ * fields; do NOT mark names, contact details, addresses, free text, or anything a data subject
3094
+ * could ask to have erased.
3095
+ *
3096
+ * ⚠️ This is a WRITE-side claim — "when this field CHANGES, the change itself is evidence" — and
3097
+ * is independent of the READ-side disclosure trail. The only disclosure trigger the framework has
3098
+ * is `isBackendOnly({ isReturnedAtCreation: true })`, which fires one `FIELD_ACCESS` event when a
3099
+ * server-minted secret is first exposed. A field can carry either, both, or neither. There is no
3100
+ * general "audit every read of this field" marker — do not go looking for one.
3101
+ *
3102
+ * assurance-control: WILDO.SECRETS.DISCLOSURE_AUDIT
3103
+ */
3104
+ IS_AUDIT_EVIDENCE = "isAuditEvidence",
3105
+ /**
3106
+ * RAG source: this field's TEXT is a retrieval-corpus source. The framework chunks the value
3107
+ * (extracting text first for file fields), stores the chunks in the application's OWN datastore
3108
+ * (pgvector on PostgreSQL, `$vectorSearch` on MongoDB — never a third store), and erases them
3109
+ * with the row: chunks are a derived-data tier keyed `(resourceType, resourceId, fieldName)`,
3110
+ * so row deletion, field impersonalization, and subject erasure all reach them.
3111
+ *
3112
+ * Authored fluently: `z.string().ragSource()` or `z.string().ragSource({ chunkingStrategy:
3113
+ * RAGChunkingStrategy.MARKDOWN, chunkSize: 1200, chunkOverlap: 150 })`. All params are optional
3114
+ * and there is NO `enabled` flag — presence of the decorator IS the declaration (see
3115
+ * {@link RagSourceConfiguration}). `addRagSource(schema, config?)` is the equivalent programmatic
3116
+ * escape hatch; read the config back with `getRagSourceConfig(schema)`.
3117
+ *
3118
+ * **File fields are one text provider, not a separate mechanism.** `z_file({ ragSource: {...} })`
3119
+ * registers THIS decorator on the schema it returns, so detection is uniform across plain-text
3120
+ * and file-backed sources; file-only extraction knobs (OCR) live file-side in
3121
+ * `FileSchemaOptions.textExtraction`, never here.
3122
+ *
3123
+ * **Refused companions, enforced in BOTH application orders at the decorator chokepoint:**
3124
+ * - {@link ZodDecorator.IS_PASSWORD}, {@link ZodDecorator.IS_OTP},
3125
+ * {@link ZodDecorator.IS_WRITE_ONLY_SECRET}, {@link ZodDecorator.IS_EPHEMERAL} — a secret or
3126
+ * ephemeral value must never enter a retrieval corpus.
3127
+ * - {@link ZodDecorator.TTL} — MongoDB honours `.ttl()` natively: rows vanish with NO application
3128
+ * code running, so derived chunks of a TTL row could never be erased with their parent (plan
3129
+ * `resource-rag-capability` DL3). The refusal lifts when a sweep-cascade reconciles chunk rows
3130
+ * against vanished parents.
3131
+ *
3132
+ * {@link ZodDecorator.IS_BACKEND_ONLY} composes: a backend-only field can be a corpus source —
3133
+ * retrieval access is governed by the resource's own access binding, not by field visibility.
3134
+ * {@link ZodDecorator.IMPERSONALIZE_WITH} composes too: an impersonalize decision deletes the
3135
+ * field's chunks in the same decision.
3136
+ */
3137
+ RAG_SOURCE = "ragSource",
1943
3138
  IS_VIRTUAL = "isVirtual",
1944
3139
  IS_DISCRIMINATOR = "isDiscriminator",
1945
3140
  EXCLUDE_FROM_CREATE = "excludeFromCreate",
1946
3141
  EXCLUDE_FROM_UPDATE = "excludeFromUpdate",
1947
3142
  IS_UNIQUE = "isUnique",
1948
3143
  IS_PRIMARY_KEY = "isPrimaryKey",
3144
+ /**
3145
+ * Marks a field as a stable, declaration-side **business key** —
3146
+ * an identity independent from the random `_id` (`isPrimaryKey`).
3147
+ *
3148
+ * Used by data seeding to safely upsert, upgrade and synchronize seeded rows.
3149
+ * Unlike `isPrimaryKey`,
3150
+ * a business key is mutable by users (renames are handled by a per-seed
3151
+ * `renames: [{ from, to }]` migrator), and it carries no implicit
3152
+ * decorators (`isPrimaryKey` is composite — `isBusinessKey` is purely
3153
+ * a marker so it can co-exist with whatever editing semantics the field
3154
+ * already has).
3155
+ *
3156
+ * Composite scope-aware identity uses the object-level
3157
+ * `OBJECT_BUSINESS_KEY_SET` decorator on the schema root.
3158
+ */
3159
+ IS_BUSINESS_KEY = "isBusinessKey",
3160
+ /**
3161
+ * Object-level decorator declaring a **composite business key** for the
3162
+ * schema (e.g. `(organizationId, templateKey)`). Schema-level analog of
3163
+ * `IS_BUSINESS_KEY`. Used by the data-seeding subsystem.
3164
+ *
3165
+ * Field-level `IS_BUSINESS_KEY` and object-level `OBJECT_BUSINESS_KEY_SET`
3166
+ * are **mutually exclusive** on the same schema — pick one identity model
3167
+ * (single field vs composite). Mixing is rejected at decoration time.
3168
+ */
3169
+ OBJECT_BUSINESS_KEY_SET = "businessKeySet",
1949
3170
  TTL = "ttl",
1950
3171
  IS_PASSWORD = "isPassword",
1951
3172
  IS_OTP = "isOtp",
@@ -1970,7 +3191,23 @@ export declare enum ZodDecorator {
1970
3191
  BIGDECIMAL_UI = "bigDecimalUI",
1971
3192
  FOREIGN_KEY_UI = "foreignKeyUI",
1972
3193
  ARRAY_UI = "arrayUI",
1973
- OBJECT_UI = "objectUI"
3194
+ OBJECT_UI = "objectUI",
3195
+ STRING_SPEC = "stringSpec",
3196
+ NUMBER_SPEC = "numberSpec",
3197
+ BOOLEAN_SPEC = "booleanSpec",
3198
+ DATE_SPEC = "dateSpec",
3199
+ DATETIME_SPEC = "dateTimeSpec",
3200
+ TIME_SPEC = "timeSpec",
3201
+ ENUM_SPEC = "enumSpec",
3202
+ MONEY_SPEC = "moneySpec",
3203
+ CODE_SPEC = "codeSpec",
3204
+ FILE_SPEC = "fileSpec",
3205
+ DURATION_SPEC = "durationSpec",
3206
+ PHONE_SPEC = "phoneSpec",
3207
+ BIGDECIMAL_SPEC = "bigDecimalSpec",
3208
+ FOREIGN_KEY_SPEC = "foreignKeySpec",
3209
+ ARRAY_SPEC = "arraySpec",
3210
+ OBJECT_SPEC = "objectSpec"
1974
3211
  }
1975
3212
  export type ZodDecorator_ParamsType = {
1976
3213
  [ZodDecorator.IS_DB_INDEXED]: undefined;
@@ -1979,12 +3216,43 @@ export type ZodDecorator_ParamsType = {
1979
3216
  [ZodDecorator.IS_NOT_EDITABLE]: NotEditableFieldParams | DecoratorUpdater<NotEditableFieldParams> | undefined;
1980
3217
  [ZodDecorator.IS_SUMMARY_FIELD]: SummaryFieldParams | DecoratorUpdater<SummaryFieldParams> | undefined;
1981
3218
  [ZodDecorator.IS_BACKEND_ONLY]: BackendOnlyFieldParams | DecoratorUpdater<BackendOnlyFieldParams> | undefined;
3219
+ [ZodDecorator.IS_WRITE_ONLY_SECRET]: WriteOnlySecretFieldParams | DecoratorUpdater<WriteOnlySecretFieldParams> | undefined;
3220
+ /**
3221
+ * The field's impersonalization treatment. Accepts BOTH authored forms — a bare `RedactionType`
3222
+ * value (the common case) or the full {@link ImpersonalizeFieldParams} object when a `MASK` needs
3223
+ * a field-specific `maskValue`. The decorator chokepoint normalizes either to the params object.
3224
+ * The treatment is typed as a plain string at this layer (zod-decorators sits below saas-models
3225
+ * and cannot import `RedactionType`).
3226
+ */
3227
+ [ZodDecorator.IMPERSONALIZE_WITH]: string | ImpersonalizeFieldParams;
3228
+ /**
3229
+ * The field's portability provenance — a `DataPortabilityProvenance` value, typed as a plain
3230
+ * string at this layer (zod-decorators sits below saas-models and cannot import the enum). One
3231
+ * datum, so unlike {@link ZodDecorator.IMPERSONALIZE_WITH} there is no object authoring form to
3232
+ * normalize; if a second axis is ever needed the chokepoint widens exactly as that one did.
3233
+ */
3234
+ [ZodDecorator.PORTABILITY_PROVENANCE]: string;
3235
+ /**
3236
+ * The field's personal-data categories — `PersonalDataCategory` values, typed as plain strings at
3237
+ * this layer (zod-decorators sits below saas-models and cannot import the enum). Accepts a single
3238
+ * value (the common case) or an array; the chokepoint normalizes either to a deduped array.
3239
+ */
3240
+ [ZodDecorator.DATA_CATEGORIES]: string | readonly string[];
3241
+ [ZodDecorator.IS_AUDIT_EVIDENCE]: undefined;
3242
+ /**
3243
+ * RAG-source declaration. The config object is optional — `.ragSource()` with no argument is a
3244
+ * complete declaration — and the chokepoint normalizes an omitted config to `{}` so every reader
3245
+ * sees one stored shape (see {@link ZodDecorator_Types}).
3246
+ */
3247
+ [ZodDecorator.RAG_SOURCE]: RagSourceConfiguration | undefined;
1982
3248
  [ZodDecorator.IS_VIRTUAL]: VirtualFieldParams | DecoratorUpdater<VirtualFieldParams>;
1983
3249
  [ZodDecorator.IS_DISCRIMINATOR]: DiscriminatorFieldParams | DecoratorUpdater<DiscriminatorFieldParams> | undefined;
1984
3250
  [ZodDecorator.EXCLUDE_FROM_CREATE]: undefined;
1985
3251
  [ZodDecorator.EXCLUDE_FROM_UPDATE]: undefined;
1986
3252
  [ZodDecorator.IS_UNIQUE]: UniqueFieldParams | DecoratorUpdater<UniqueFieldParams> | undefined;
1987
3253
  [ZodDecorator.IS_PRIMARY_KEY]: undefined;
3254
+ [ZodDecorator.IS_BUSINESS_KEY]: undefined;
3255
+ [ZodDecorator.OBJECT_BUSINESS_KEY_SET]: BusinessKeySetParams | DecoratorUpdater<BusinessKeySetParams>;
1988
3256
  [ZodDecorator.TTL]: TtlFieldParams | DecoratorUpdater<TtlFieldParams>;
1989
3257
  [ZodDecorator.IS_PASSWORD]: undefined;
1990
3258
  [ZodDecorator.IS_OTP]: OtpFieldParams | DecoratorUpdater<OtpFieldParams> | undefined;
@@ -2010,6 +3278,22 @@ export type ZodDecorator_ParamsType = {
2010
3278
  [ZodDecorator.FOREIGN_KEY_UI]: ForeignKeyUIParams | DecoratorUpdater<ForeignKeyUIParams> | undefined;
2011
3279
  [ZodDecorator.ARRAY_UI]: ArrayUIParams | DecoratorUpdater<ArrayUIParams> | undefined;
2012
3280
  [ZodDecorator.OBJECT_UI]: ObjectUIParams | DecoratorUpdater<ObjectUIParams> | undefined;
3281
+ [ZodDecorator.STRING_SPEC]: StringSpecParams | DecoratorUpdater<StringSpecParams> | undefined;
3282
+ [ZodDecorator.NUMBER_SPEC]: NumberSpecParams | DecoratorUpdater<NumberSpecParams> | undefined;
3283
+ [ZodDecorator.BOOLEAN_SPEC]: BooleanSpecParams | DecoratorUpdater<BooleanSpecParams> | undefined;
3284
+ [ZodDecorator.DATE_SPEC]: DateSpecParams | DecoratorUpdater<DateSpecParams> | undefined;
3285
+ [ZodDecorator.DATETIME_SPEC]: DateTimeSpecParams | DecoratorUpdater<DateTimeSpecParams> | undefined;
3286
+ [ZodDecorator.TIME_SPEC]: TimeSpecParams | DecoratorUpdater<TimeSpecParams> | undefined;
3287
+ [ZodDecorator.ENUM_SPEC]: EnumSpecParams | DecoratorUpdater<EnumSpecParams> | undefined;
3288
+ [ZodDecorator.MONEY_SPEC]: MoneySpecParams | DecoratorUpdater<MoneySpecParams> | undefined;
3289
+ [ZodDecorator.CODE_SPEC]: CodeSpecParams | DecoratorUpdater<CodeSpecParams> | undefined;
3290
+ [ZodDecorator.FILE_SPEC]: FileSpecParams | DecoratorUpdater<FileSpecParams> | undefined;
3291
+ [ZodDecorator.DURATION_SPEC]: DurationSpecParams | DecoratorUpdater<DurationSpecParams> | undefined;
3292
+ [ZodDecorator.PHONE_SPEC]: PhoneSpecParams | DecoratorUpdater<PhoneSpecParams> | undefined;
3293
+ [ZodDecorator.BIGDECIMAL_SPEC]: BigDecimalSpecParams | DecoratorUpdater<BigDecimalSpecParams> | undefined;
3294
+ [ZodDecorator.FOREIGN_KEY_SPEC]: ForeignKeySpecParams | DecoratorUpdater<ForeignKeySpecParams> | undefined;
3295
+ [ZodDecorator.ARRAY_SPEC]: ArraySpecParams | DecoratorUpdater<ArraySpecParams> | undefined;
3296
+ [ZodDecorator.OBJECT_SPEC]: ObjectSpecParams | DecoratorUpdater<ObjectSpecParams> | undefined;
2013
3297
  };
2014
3298
  export type ZodDecorator_Types = {
2015
3299
  [ZodDecorator.IS_DB_INDEXED]: boolean;
@@ -2018,12 +3302,35 @@ export type ZodDecorator_Types = {
2018
3302
  [ZodDecorator.IS_NOT_EDITABLE]: NotEditableFieldParams | true;
2019
3303
  [ZodDecorator.IS_SUMMARY_FIELD]: SummaryFieldParams | true;
2020
3304
  [ZodDecorator.IS_BACKEND_ONLY]: BackendOnlyFieldParams | true;
3305
+ [ZodDecorator.IS_WRITE_ONLY_SECRET]: WriteOnlySecretFieldParams | true;
3306
+ /** Impersonalization scrub params — the treatment (a `RedactionType` value carried as an opaque
3307
+ * `string`, since zod-decorators sits below saas-models) plus an optional `MASK` override value.
3308
+ * ALWAYS the normalized object: the chokepoint widens a bare-string authoring form on the way in,
3309
+ * so every reader sees one shape. */
3310
+ [ZodDecorator.IMPERSONALIZE_WITH]: ImpersonalizeFieldParams;
3311
+ /** Portability provenance — a `DataPortabilityProvenance` value carried as an opaque `string`
3312
+ * (zod-decorators sits below saas-models). Stored exactly as authored; the chokepoint only
3313
+ * rejects blanks. */
3314
+ [ZodDecorator.PORTABILITY_PROVENANCE]: string;
3315
+ /** Personal-data categories — `PersonalDataCategory` values carried as opaque `string`s
3316
+ * (zod-decorators sits below saas-models). ALWAYS the normalized array, deduped and non-empty:
3317
+ * the chokepoint widens a bare single-value authoring form on the way in, so every reader sees
3318
+ * one shape and `getDataCategories` can answer "is this field categorized?" by presence alone. */
3319
+ [ZodDecorator.DATA_CATEGORIES]: readonly string[];
3320
+ /** Audit-evidence marker — stored as the bare `true` sentinel (parameterless, like IS_BUSINESS_KEY). */
3321
+ [ZodDecorator.IS_AUDIT_EVIDENCE]: true;
3322
+ /** RAG-source config — ALWAYS the normalized object ( `{}` when authored with no argument): the
3323
+ * chokepoint validates and normalizes on the way in, so every reader sees one shape and
3324
+ * `getRagSourceConfig` can answer "is this field a source?" by presence alone. */
3325
+ [ZodDecorator.RAG_SOURCE]: RagSourceConfiguration;
2021
3326
  [ZodDecorator.IS_VIRTUAL]: VirtualFieldParams;
2022
3327
  [ZodDecorator.IS_DISCRIMINATOR]: DiscriminatorFieldParams | true;
2023
3328
  [ZodDecorator.EXCLUDE_FROM_CREATE]: true;
2024
3329
  [ZodDecorator.EXCLUDE_FROM_UPDATE]: true;
2025
3330
  [ZodDecorator.IS_UNIQUE]: UniqueFieldParams | true;
2026
3331
  [ZodDecorator.IS_PRIMARY_KEY]: true;
3332
+ [ZodDecorator.IS_BUSINESS_KEY]: true;
3333
+ [ZodDecorator.OBJECT_BUSINESS_KEY_SET]: BusinessKeySetParams;
2027
3334
  [ZodDecorator.TTL]: TtlFieldParams;
2028
3335
  [ZodDecorator.IS_PASSWORD]: true;
2029
3336
  [ZodDecorator.IS_OTP]: OtpFieldParams | true;
@@ -2049,7 +3356,29 @@ export type ZodDecorator_Types = {
2049
3356
  [ZodDecorator.FOREIGN_KEY_UI]: ForeignKeyUIParams;
2050
3357
  [ZodDecorator.ARRAY_UI]: ArrayUIParams;
2051
3358
  [ZodDecorator.OBJECT_UI]: ObjectUIParams;
3359
+ [ZodDecorator.STRING_SPEC]: StringSpecParams;
3360
+ [ZodDecorator.NUMBER_SPEC]: NumberSpecParams;
3361
+ [ZodDecorator.BOOLEAN_SPEC]: BooleanSpecParams;
3362
+ [ZodDecorator.DATE_SPEC]: DateSpecParams;
3363
+ [ZodDecorator.DATETIME_SPEC]: DateTimeSpecParams;
3364
+ [ZodDecorator.TIME_SPEC]: TimeSpecParams;
3365
+ [ZodDecorator.ENUM_SPEC]: EnumSpecParams;
3366
+ [ZodDecorator.MONEY_SPEC]: MoneySpecParams;
3367
+ [ZodDecorator.CODE_SPEC]: CodeSpecParams;
3368
+ [ZodDecorator.FILE_SPEC]: FileSpecParams;
3369
+ [ZodDecorator.DURATION_SPEC]: DurationSpecParams;
3370
+ [ZodDecorator.PHONE_SPEC]: PhoneSpecParams;
3371
+ [ZodDecorator.BIGDECIMAL_SPEC]: BigDecimalSpecParams;
3372
+ [ZodDecorator.FOREIGN_KEY_SPEC]: ForeignKeySpecParams;
3373
+ [ZodDecorator.ARRAY_SPEC]: ArraySpecParams;
3374
+ [ZodDecorator.OBJECT_SPEC]: ObjectSpecParams;
2052
3375
  };
3376
+ /** @wildo_source:part:end zod.decorators.decorator-vocabulary */
3377
+ /**
3378
+ * @wildo_source:part:start zod.decorators.schema-metadata
3379
+ *
3380
+ * Per-field decorator metadata bag stored on schema instances under `SCHEMA_METADATA`.
3381
+ */
2053
3382
  export interface CustomFieldMetadata {
2054
3383
  [ZodDecorator.IS_DB_INDEXED]?: ZodDecorator_Types[ZodDecorator.IS_DB_INDEXED];
2055
3384
  [ZodDecorator.IS_FOREIGN_KEY]?: ZodDecorator_Types[ZodDecorator.IS_FOREIGN_KEY];
@@ -2057,12 +3386,20 @@ export interface CustomFieldMetadata {
2057
3386
  [ZodDecorator.IS_NOT_EDITABLE]?: ZodDecorator_Types[ZodDecorator.IS_NOT_EDITABLE];
2058
3387
  [ZodDecorator.IS_SUMMARY_FIELD]?: ZodDecorator_Types[ZodDecorator.IS_SUMMARY_FIELD];
2059
3388
  [ZodDecorator.IS_BACKEND_ONLY]?: ZodDecorator_Types[ZodDecorator.IS_BACKEND_ONLY];
3389
+ [ZodDecorator.IS_WRITE_ONLY_SECRET]?: ZodDecorator_Types[ZodDecorator.IS_WRITE_ONLY_SECRET];
3390
+ [ZodDecorator.IMPERSONALIZE_WITH]?: ZodDecorator_Types[ZodDecorator.IMPERSONALIZE_WITH];
3391
+ [ZodDecorator.PORTABILITY_PROVENANCE]?: ZodDecorator_Types[ZodDecorator.PORTABILITY_PROVENANCE];
3392
+ [ZodDecorator.DATA_CATEGORIES]?: ZodDecorator_Types[ZodDecorator.DATA_CATEGORIES];
3393
+ [ZodDecorator.IS_AUDIT_EVIDENCE]?: ZodDecorator_Types[ZodDecorator.IS_AUDIT_EVIDENCE];
3394
+ [ZodDecorator.RAG_SOURCE]?: ZodDecorator_Types[ZodDecorator.RAG_SOURCE];
2060
3395
  [ZodDecorator.IS_VIRTUAL]?: ZodDecorator_Types[ZodDecorator.IS_VIRTUAL];
2061
3396
  [ZodDecorator.IS_DISCRIMINATOR]?: ZodDecorator_Types[ZodDecorator.IS_DISCRIMINATOR];
2062
3397
  [ZodDecorator.EXCLUDE_FROM_CREATE]?: ZodDecorator_Types[ZodDecorator.EXCLUDE_FROM_CREATE];
2063
3398
  [ZodDecorator.EXCLUDE_FROM_UPDATE]?: ZodDecorator_Types[ZodDecorator.EXCLUDE_FROM_UPDATE];
2064
3399
  [ZodDecorator.IS_UNIQUE]?: ZodDecorator_Types[ZodDecorator.IS_UNIQUE];
2065
3400
  [ZodDecorator.IS_PRIMARY_KEY]?: ZodDecorator_Types[ZodDecorator.IS_PRIMARY_KEY];
3401
+ [ZodDecorator.IS_BUSINESS_KEY]?: ZodDecorator_Types[ZodDecorator.IS_BUSINESS_KEY];
3402
+ [ZodDecorator.OBJECT_BUSINESS_KEY_SET]?: ZodDecorator_Types[ZodDecorator.OBJECT_BUSINESS_KEY_SET];
2066
3403
  [ZodDecorator.TTL]?: ZodDecorator_Types[ZodDecorator.TTL];
2067
3404
  [ZodDecorator.IS_PASSWORD]?: ZodDecorator_Types[ZodDecorator.IS_PASSWORD];
2068
3405
  [ZodDecorator.IS_OTP]?: ZodDecorator_Types[ZodDecorator.IS_OTP];
@@ -2088,6 +3425,22 @@ export interface CustomFieldMetadata {
2088
3425
  [ZodDecorator.FOREIGN_KEY_UI]?: ZodDecorator_Types[ZodDecorator.FOREIGN_KEY_UI];
2089
3426
  [ZodDecorator.ARRAY_UI]?: ZodDecorator_Types[ZodDecorator.ARRAY_UI];
2090
3427
  [ZodDecorator.OBJECT_UI]?: ZodDecorator_Types[ZodDecorator.OBJECT_UI];
3428
+ [ZodDecorator.STRING_SPEC]?: ZodDecorator_Types[ZodDecorator.STRING_SPEC];
3429
+ [ZodDecorator.NUMBER_SPEC]?: ZodDecorator_Types[ZodDecorator.NUMBER_SPEC];
3430
+ [ZodDecorator.BOOLEAN_SPEC]?: ZodDecorator_Types[ZodDecorator.BOOLEAN_SPEC];
3431
+ [ZodDecorator.DATE_SPEC]?: ZodDecorator_Types[ZodDecorator.DATE_SPEC];
3432
+ [ZodDecorator.DATETIME_SPEC]?: ZodDecorator_Types[ZodDecorator.DATETIME_SPEC];
3433
+ [ZodDecorator.TIME_SPEC]?: ZodDecorator_Types[ZodDecorator.TIME_SPEC];
3434
+ [ZodDecorator.ENUM_SPEC]?: ZodDecorator_Types[ZodDecorator.ENUM_SPEC];
3435
+ [ZodDecorator.MONEY_SPEC]?: ZodDecorator_Types[ZodDecorator.MONEY_SPEC];
3436
+ [ZodDecorator.CODE_SPEC]?: ZodDecorator_Types[ZodDecorator.CODE_SPEC];
3437
+ [ZodDecorator.FILE_SPEC]?: ZodDecorator_Types[ZodDecorator.FILE_SPEC];
3438
+ [ZodDecorator.DURATION_SPEC]?: ZodDecorator_Types[ZodDecorator.DURATION_SPEC];
3439
+ [ZodDecorator.PHONE_SPEC]?: ZodDecorator_Types[ZodDecorator.PHONE_SPEC];
3440
+ [ZodDecorator.BIGDECIMAL_SPEC]?: ZodDecorator_Types[ZodDecorator.BIGDECIMAL_SPEC];
3441
+ [ZodDecorator.FOREIGN_KEY_SPEC]?: ZodDecorator_Types[ZodDecorator.FOREIGN_KEY_SPEC];
3442
+ [ZodDecorator.ARRAY_SPEC]?: ZodDecorator_Types[ZodDecorator.ARRAY_SPEC];
3443
+ [ZodDecorator.OBJECT_SPEC]?: ZodDecorator_Types[ZodDecorator.OBJECT_SPEC];
2091
3444
  /** Range schema type (only present for range schemas) */
2092
3445
  rangeType?: RangeType;
2093
3446
  /** Full range schema configuration (only present for range schemas) */
@@ -2109,6 +3462,7 @@ export interface CustomFieldMetadata {
2109
3462
  /** Versioned foreign key configuration (only present for versioned foreign key schemas) */
2110
3463
  versionedForeignKeyConfig?: VersionedForeignKeySchemaMetadata;
2111
3464
  }
3465
+ /** @wildo_source:part:end zod.decorators.schema-metadata */
2112
3466
  type ZodenumInstance = ReturnType<typeof z.enum>;
2113
3467
  export type PrimitiveZodType = z.ZodString | z.ZodNumber | z.ZodBoolean | z.ZodDate | z.ZodEnum<any> | ZodenumInstance | ZodBrandedColorInstance | DecoratedPrimitiveZodType<z.ZodString> | DecoratedPrimitiveZodType<z.ZodNumber> | DecoratedPrimitiveZodType<z.ZodBoolean> | DecoratedPrimitiveZodType<z.ZodDate> | DecoratedPrimitiveZodType<z.ZodEnum<any>> | DecoratedPrimitiveZodType<ZodenumInstance>;
2114
3468
  export type SerializableZodSchema = {