@stndrds/schema 1.0.0-alpha.185 → 1.0.0-alpha.187

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 (55) hide show
  1. package/dist/{filters-qNc-JmQI.d.ts → filters-DVBn5tov.d.ts} +81 -39
  2. package/dist/{filters-DVbxM2W4.d.mts → filters-HDG4kLoo.d.mts} +81 -39
  3. package/dist/{helpers-g5uHrKfE.d.mts → helpers-BjuFhbQQ.d.mts} +2 -2
  4. package/dist/{helpers-D-_4FAcR.d.ts → helpers-CSuoa3kj.d.ts} +2 -2
  5. package/dist/index.d.mts +185 -56
  6. package/dist/index.d.ts +185 -56
  7. package/dist/index.js +229 -105
  8. package/dist/index.mjs +215 -99
  9. package/dist/{types-CQTltaH_.d.ts → types-Bdlhgrf7.d.ts} +1 -1
  10. package/dist/{types-BTrwWar6.d.mts → types-C5DittlR.d.mts} +1 -1
  11. package/dist/validation/all.d.mts +3 -3
  12. package/dist/validation/all.d.ts +3 -3
  13. package/dist/validation/all.js +8 -8
  14. package/dist/validation/all.mjs +2 -2
  15. package/dist/validation/complex/currency.d.mts +2 -2
  16. package/dist/validation/complex/currency.d.ts +2 -2
  17. package/dist/validation/complex/file.d.mts +2 -2
  18. package/dist/validation/complex/file.d.ts +2 -2
  19. package/dist/validation/complex/location.d.mts +2 -2
  20. package/dist/validation/complex/location.d.ts +2 -2
  21. package/dist/validation/complex/phone.d.mts +2 -2
  22. package/dist/validation/complex/phone.d.ts +2 -2
  23. package/dist/validation/complex/relation.d.mts +2 -2
  24. package/dist/validation/complex/relation.d.ts +2 -2
  25. package/dist/validation/complex/richtext.d.mts +2 -2
  26. package/dist/validation/complex/richtext.d.ts +2 -2
  27. package/dist/validation/complex/select.d.mts +2 -2
  28. package/dist/validation/complex/select.d.ts +2 -2
  29. package/dist/validation/complex/user.d.mts +2 -2
  30. package/dist/validation/complex/user.d.ts +2 -2
  31. package/dist/validation/computed/formula.d.mts +2 -2
  32. package/dist/validation/computed/formula.d.ts +2 -2
  33. package/dist/validation/computed/rollup.d.mts +2 -2
  34. package/dist/validation/computed/rollup.d.ts +2 -2
  35. package/dist/validation/config/index.d.mts +1 -1
  36. package/dist/validation/config/index.d.ts +1 -1
  37. package/dist/validation/core/index.d.mts +3 -3
  38. package/dist/validation/core/index.d.ts +3 -3
  39. package/dist/validation/object/index.d.mts +3 -3
  40. package/dist/validation/object/index.d.ts +3 -3
  41. package/dist/validation/object/index.js +14 -14
  42. package/dist/validation/object/index.mjs +2 -2
  43. package/dist/validation/primitives/checkbox.d.mts +2 -2
  44. package/dist/validation/primitives/checkbox.d.ts +2 -2
  45. package/dist/validation/primitives/date.d.mts +2 -2
  46. package/dist/validation/primitives/date.d.ts +2 -2
  47. package/dist/validation/primitives/number.d.mts +2 -2
  48. package/dist/validation/primitives/number.d.ts +2 -2
  49. package/dist/validation/primitives/rating.d.mts +2 -2
  50. package/dist/validation/primitives/rating.d.ts +2 -2
  51. package/dist/validation/primitives/text.d.mts +2 -2
  52. package/dist/validation/primitives/text.d.ts +2 -2
  53. package/package.json +2 -2
  54. package/dist/{chunk-HG6EF4XD.js → chunk-64R5X3DF.js} +1 -1
  55. package/dist/{chunk-M7ZNKBOE.mjs → chunk-6JEQE4IP.mjs} +1 -1
package/dist/index.mjs CHANGED
@@ -2,8 +2,9 @@ import { generateId } from './chunk-QY6QFRRV.mjs';
2
2
  export { asTenantId, asUserId, deepEqual, generateId, indexBy } from './chunk-QY6QFRRV.mjs';
3
3
  import './chunk-SP3PNHYF.mjs';
4
4
  export { parseAttributeConfig } from './chunk-U4JC7P6D.mjs';
5
- import { createObjectValidator, createAttributeValidator } from './chunk-M7ZNKBOE.mjs';
6
- export { computeRecordStatus, createFormAttributeValidator, validateDraft, validateDraftOrThrow, validateObject, validateObjectOrThrow } from './chunk-M7ZNKBOE.mjs';
5
+ import { createObjectValidator, createAttributeValidator } from './chunk-6JEQE4IP.mjs';
6
+ export { computeRecordStatus, createFormAttributeValidator, validateDraft, validateDraftOrThrow, validateObject, validateObjectOrThrow } from './chunk-6JEQE4IP.mjs';
7
+ import './chunk-TMYBEXBT.mjs';
7
8
  import './chunk-4KRLCWJM.mjs';
8
9
  import './chunk-KNYZH2WD.mjs';
9
10
  import './chunk-RUYUFXNW.mjs';
@@ -13,7 +14,6 @@ import './chunk-SMOHDR6M.mjs';
13
14
  import './chunk-ITTQ4FGR.mjs';
14
15
  import './chunk-IRTRJH37.mjs';
15
16
  import './chunk-OLJLCVNY.mjs';
16
- import './chunk-TMYBEXBT.mjs';
17
17
  import './chunk-TEQNVO7W.mjs';
18
18
  import './chunk-4TC27SMF.mjs';
19
19
  import './chunk-TBYXYSGA.mjs';
@@ -63,6 +63,9 @@ function isAttributeSortable(attr) {
63
63
  return !NON_SORTABLE_TYPES.has(attr.type);
64
64
  }
65
65
 
66
+ // src/types/document-layout.ts
67
+ var MAX_PRESET_DEPTH = 5;
68
+
66
69
  // src/types/documents.ts
67
70
  var DEFAULT_DOCUMENT_SLOT = { name: "file" };
68
71
 
@@ -90,6 +93,15 @@ var SchemaErrorCode = {
90
93
  ACCESS_DENIED: "SCHEMA_ACCESS_DENIED",
91
94
  // Sync
92
95
  SYNC_FAILED: "SCHEMA_SYNC_FAILED",
96
+ SYNC_CONFLICT: "SCHEMA_SYNC_CONFLICT",
97
+ SYNC_CASCADE: "SCHEMA_SYNC_CASCADE",
98
+ ORPHAN_SYSTEM_ATTRIBUTE: "SCHEMA_ORPHAN_SYSTEM_ATTRIBUTE",
99
+ // System Entity Immutability
100
+ SYSTEM_ENTITY_IMMUTABLE: "SCHEMA_SYSTEM_ENTITY_IMMUTABLE",
101
+ // L2 — migration system simplification (2026-05-17)
102
+ DESTRUCTIVE_NOT_ALLOWED: "SCHEMA_DESTRUCTIVE_NOT_ALLOWED",
103
+ MIGRATION_TIMEOUT: "SCHEMA_MIGRATION_TIMEOUT",
104
+ CHANGE_TYPE_NOT_SUPPORTED: "SCHEMA_CHANGE_TYPE_NOT_SUPPORTED",
93
105
  // Duplicates
94
106
  DUPLICATE_OBJECT: "SCHEMA_DUPLICATE_OBJECT",
95
107
  DUPLICATE_ATTRIBUTE: "SCHEMA_DUPLICATE_ATTRIBUTE",
@@ -203,6 +215,115 @@ var SyncError = class extends SchemaError {
203
215
  this.cause = cause;
204
216
  }
205
217
  };
218
+ var SystemEntityImmutableError = class extends SchemaError {
219
+ constructor(entityType, entityName) {
220
+ super(
221
+ `Cannot mutate system ${entityType} "${entityName}". System entities are declared in code and immutable at runtime.`,
222
+ SchemaErrorCode.SYSTEM_ENTITY_IMMUTABLE,
223
+ { entityType, entityName }
224
+ );
225
+ this.name = "SystemEntityImmutableError";
226
+ this.entityType = entityType;
227
+ this.entityName = entityName;
228
+ }
229
+ };
230
+ var SyncConflictError = class extends SchemaError {
231
+ constructor(params) {
232
+ const target = params.attributeName ? `"${params.objectName}.${params.attributeName}"` : `"${params.objectName}"`;
233
+ super(
234
+ `Cannot promote runtime entity ${target}: ${params.reason}. Resolve via: (1) relax the code constraint, (2) migrate runtime values manually, or (3) rename the code declaration.`,
235
+ SchemaErrorCode.SYNC_CONFLICT,
236
+ {
237
+ objectName: params.objectName,
238
+ attributeName: params.attributeName,
239
+ reason: params.reason
240
+ }
241
+ );
242
+ this.name = "SyncConflictError";
243
+ this.objectName = params.objectName;
244
+ this.attributeName = params.attributeName;
245
+ this.reason = params.reason;
246
+ }
247
+ };
248
+ var SyncCascadeError = class extends SchemaError {
249
+ constructor(objectName, conflictingAttributes) {
250
+ super(
251
+ `Cannot demote object "${objectName}": attributes ${conflictingAttributes.join(", ")} are still declared in code. Remove them from code first, or restore the object.`,
252
+ SchemaErrorCode.SYNC_CASCADE,
253
+ { objectName, conflictingAttributes }
254
+ );
255
+ this.name = "SyncCascadeError";
256
+ this.objectName = objectName;
257
+ this.conflictingAttributes = conflictingAttributes;
258
+ }
259
+ };
260
+ var OrphanSystemAttributeError = class extends SchemaError {
261
+ constructor(objectName, attributeName) {
262
+ super(
263
+ `Attribute "${objectName}.${attributeName}" is system:true but its object parent is system:false. This is an invariant violation.`,
264
+ SchemaErrorCode.ORPHAN_SYSTEM_ATTRIBUTE,
265
+ { objectName, attributeName }
266
+ );
267
+ this.name = "OrphanSystemAttributeError";
268
+ this.objectName = objectName;
269
+ this.attributeName = attributeName;
270
+ }
271
+ };
272
+ var DestructiveSyncNotAllowedError = class extends SchemaError {
273
+ constructor(operations) {
274
+ const summary = operations.map((op) => {
275
+ if (op.type === "remove_attribute") {
276
+ return `- remove_attribute "${op.objectName ?? "?"}.${op.name}"`;
277
+ }
278
+ if (op.type === "remove_object") {
279
+ return "- remove_object";
280
+ }
281
+ return `- ${op.type}`;
282
+ }).join("\n");
283
+ super(
284
+ `Destructive schema operations detected (data will be lost):
285
+ ${summary}
286
+
287
+ To allow Standards to apply these automatically, set the environment variable:
288
+ STANDARDS_ALLOW_DESTRUCTIVE_SYNC=1
289
+
290
+ Otherwise, revert your code changes or back up the data first.`,
291
+ SchemaErrorCode.DESTRUCTIVE_NOT_ALLOWED,
292
+ { operations }
293
+ );
294
+ this.name = "DestructiveSyncNotAllowedError";
295
+ this.operations = operations;
296
+ }
297
+ };
298
+ var MigrationTimeoutError = class extends SchemaError {
299
+ constructor(objectName, migrated, total, maxDurationMs) {
300
+ super(
301
+ `Migration for "${objectName}" exceeded the maximum duration (${maxDurationMs}ms). Migrated ${migrated}/${total} records before timeout. Increase STANDARDS_MIGRATION_MAX_DURATION_MS or split the migration into smaller batches.`,
302
+ SchemaErrorCode.MIGRATION_TIMEOUT,
303
+ { objectName, migrated, total, maxDurationMs }
304
+ );
305
+ this.name = "MigrationTimeoutError";
306
+ this.objectName = objectName;
307
+ this.migrated = migrated;
308
+ this.total = total;
309
+ this.maxDurationMs = maxDurationMs;
310
+ }
311
+ };
312
+ var ChangeTypeNotSupportedError = class extends SchemaError {
313
+ constructor(objectName, attributeName) {
314
+ super(
315
+ `Cannot change type of attribute "${objectName}.${attributeName}" via runtime API. Declare a migration in your schema code:
316
+ object("${objectName}").migration(N, (m) =>
317
+ m.changeType("${attributeName}", from, to, { transform: (v) => ... })
318
+ )`,
319
+ SchemaErrorCode.CHANGE_TYPE_NOT_SUPPORTED,
320
+ { objectName, attributeName }
321
+ );
322
+ this.name = "ChangeTypeNotSupportedError";
323
+ this.objectName = objectName;
324
+ this.attributeName = attributeName;
325
+ }
326
+ };
206
327
  var DuplicateError = class extends SchemaError {
207
328
  constructor(resourceType, resourceName) {
208
329
  const code = resourceType === "object" ? SchemaErrorCode.DUPLICATE_OBJECT : SchemaErrorCode.DUPLICATE_ATTRIBUTE;
@@ -426,21 +547,15 @@ var OPERATORS_BY_TYPE = {
426
547
  select: ["is", "is_not", "any_of", "none_of", "is_empty", "is_not_empty"],
427
548
  multiselect: ["contains", "not_contains", "is_empty", "is_not_empty"],
428
549
  location: ["contains", "is_empty", "is_not_empty"],
429
- // Reference attribute types (file, user, relation, document) all route
430
- // through the edge filter resolver, which normalizes is/is_not/any_of/
431
- // none_of/contains/not_contains via `getOperatorPolarity` +
432
- // `normalizeForEdgeRpc`. Keep the operator lists symmetric so the schema
433
- // validation matches what the runtime actually supports.
434
- file: [
435
- "is",
436
- "is_not",
437
- "any_of",
438
- "none_of",
439
- "contains",
440
- "not_contains",
441
- "is_empty",
442
- "is_not_empty"
443
- ],
550
+ // Reference attribute types (user, relation) all route through the edge
551
+ // filter resolver, which normalizes is/is_not/any_of/none_of/contains/
552
+ // not_contains via `getOperatorPolarity` + `normalizeForEdgeRpc`. Keep the
553
+ // operator lists symmetric so the schema validation matches what the runtime
554
+ // actually supports.
555
+ // File and document attributes only expose presence operators — qualified
556
+ // filters (via `.qualifyWith()` on document) keep their own operator set
557
+ // based on the property type.
558
+ file: ["is_empty", "is_not_empty"],
444
559
  user: [
445
560
  "is",
446
561
  "is_not",
@@ -477,17 +592,7 @@ var OPERATORS_BY_TYPE = {
477
592
  "is_empty",
478
593
  "is_not_empty"
479
594
  ],
480
- // Document: same edge-backed operator set as relation / user / file.
481
- document: [
482
- "is",
483
- "is_not",
484
- "any_of",
485
- "none_of",
486
- "contains",
487
- "not_contains",
488
- "is_empty",
489
- "is_not_empty"
490
- ]
595
+ document: ["is_empty", "is_not_empty"]
491
596
  };
492
597
  var NO_VALUE_OPERATORS = [
493
598
  "is_empty",
@@ -581,8 +686,8 @@ var RESERVED_ATTRIBUTE_NAMES = [
581
686
  "values",
582
687
  "metadata",
583
688
  "deletedAt",
584
- "schemaVersion",
585
- "archivedValues"
689
+ "deletedBy",
690
+ "schemaVersion"
586
691
  ];
587
692
 
588
693
  // src/types/permissions.ts
@@ -684,7 +789,6 @@ var SYSTEM_ATTRIBUTES = {
684
789
  system: true,
685
790
  hidden: true,
686
791
  // Hidden from regular form views
687
- multiple: true,
688
792
  icon: "paperclip",
689
793
  description: "Free-form document attachments"
690
794
  }
@@ -1153,7 +1257,9 @@ var SYSTEM_RESOURCES = {
1153
1257
  /** Audit log access */
1154
1258
  AUDIT: "audit",
1155
1259
  /** Programmatic access keys */
1156
- API_KEYS: "api-keys"
1260
+ API_KEYS: "api-keys",
1261
+ /** Agent session visibility — required for an agent actor to read its own sessions */
1262
+ SESSION: "session"
1157
1263
  };
1158
1264
  var ALL_SYSTEM_RESOURCES = [
1159
1265
  SYSTEM_RESOURCES.PEOPLE,
@@ -1165,7 +1271,8 @@ var ALL_SYSTEM_RESOURCES = [
1165
1271
  SYSTEM_RESOURCES.FORMS,
1166
1272
  SYSTEM_RESOURCES.DOCUMENTS,
1167
1273
  SYSTEM_RESOURCES.AUDIT,
1168
- SYSTEM_RESOURCES.API_KEYS
1274
+ SYSTEM_RESOURCES.API_KEYS,
1275
+ SYSTEM_RESOURCES.SESSION
1169
1276
  ];
1170
1277
  var SYSTEM_RESOURCE_LABELS = {
1171
1278
  people: "People",
@@ -1177,7 +1284,8 @@ var SYSTEM_RESOURCE_LABELS = {
1177
1284
  forms: "Forms",
1178
1285
  documents: "Documents",
1179
1286
  audit: "Audit",
1180
- "api-keys": "API keys"
1287
+ "api-keys": "API keys",
1288
+ session: "Agent sessions"
1181
1289
  };
1182
1290
  var DEFAULT_ROLES = {
1183
1291
  /** Full platform access - can manage everything */
@@ -1213,7 +1321,10 @@ var DEFAULT_ROLE_PERMISSIONS = {
1213
1321
  agent_default: {
1214
1322
  system: [
1215
1323
  { target: "documents", actions: ["read", "create", "update"] },
1216
- { target: "files", actions: ["read", "create", "update"] }
1324
+ { target: "files", actions: ["read", "create", "update"] },
1325
+ // Required so the agent actor can read its own sessions when the worker
1326
+ // resumes a queued job under the agent's identity (runAsAgentActor).
1327
+ { target: "session", actions: ["observe"] }
1217
1328
  ],
1218
1329
  object: [{ target: "*", actions: ["read", "create", "update", "delete"] }]
1219
1330
  }
@@ -1366,7 +1477,10 @@ var BaseAttributeBuilder = class {
1366
1477
  name,
1367
1478
  label,
1368
1479
  type,
1369
- required: false
1480
+ required: false,
1481
+ // Default: system entities are declared in code and immutable at runtime.
1482
+ // Use .runtime() to opt out (advanced use only — tests, seeds, fixtures).
1483
+ system: true
1370
1484
  };
1371
1485
  }
1372
1486
  setRequired(value) {
@@ -1407,8 +1521,22 @@ var BaseAttributeBuilder = class {
1407
1521
  asPhantomState() {
1408
1522
  return this;
1409
1523
  }
1410
- system() {
1411
- this.attr.system = true;
1524
+ /**
1525
+ * Marks this attribute as runtime-only (system: false).
1526
+ *
1527
+ * ⚠️ ADVANCED USE ONLY. In production schemas, attributes declared in code are
1528
+ * automatically system:true (immutable at runtime). Use .runtime() ONLY for:
1529
+ * - Test fixtures (`*.test.ts`, `tests/`)
1530
+ * - Seed data (`seeds/`)
1531
+ * - Dev fixtures (`fixtures/`)
1532
+ *
1533
+ * Calling .runtime() in production code creates an attribute that:
1534
+ * - Can be modified or deleted by end users via the admin UI
1535
+ * - Is not part of your code contract
1536
+ * - Will be picked up by `standards diff` as runtime drift
1537
+ */
1538
+ runtime() {
1539
+ this.attr.system = false;
1412
1540
  return this;
1413
1541
  }
1414
1542
  disabled() {
@@ -1994,7 +2122,7 @@ var SingleRelationAttributeBuilder = class extends BaseRelationAttributeBuilder
1994
2122
  isRequired: this.attr.required
1995
2123
  }
1996
2124
  );
1997
- if (this.attr.system) multiBuilder.system();
2125
+ if (this.attr.system === false) multiBuilder.runtime();
1998
2126
  if (this.attr.hidden) multiBuilder.hidden();
1999
2127
  if (this.attr.disabled) multiBuilder.disabled();
2000
2128
  if (this.attr.placeholder) multiBuilder.placeholder(this.attr.placeholder);
@@ -2203,15 +2331,7 @@ var DocumentAttributeBuilder = class extends BaseAttributeBuilder {
2203
2331
  super("document", name, label);
2204
2332
  }
2205
2333
  /**
2206
- * Allow multiple documents.
2207
- * Value becomes string[] instead of string (or Array<{ id; props }> when qualified).
2208
- */
2209
- multiple() {
2210
- this.attr.multiple = true;
2211
- return this;
2212
- }
2213
- /**
2214
- * Maximum number of documents (only applies when multiple: true).
2334
+ * Maximum number of documents.
2215
2335
  */
2216
2336
  maxDocuments(count) {
2217
2337
  this.attr.maxDocuments = count;
@@ -2270,7 +2390,6 @@ var DocumentAttributeBuilder = class extends BaseAttributeBuilder {
2270
2390
  *
2271
2391
  * @example
2272
2392
  * document({ name: "contracts", label: "Contracts" })
2273
- * .multiple()
2274
2393
  * .qualifyWith(
2275
2394
  * select({ name: "kind", label: "Kind" }).options([...]),
2276
2395
  * number({ name: "amount", label: "Amount" }).min(0),
@@ -2610,30 +2729,6 @@ function resolveBuiltInTransform(targetType) {
2610
2729
  };
2611
2730
  return map[targetType];
2612
2731
  }
2613
- function reverseOperation(op) {
2614
- switch (op.type) {
2615
- case "rename_attribute":
2616
- return { type: "rename_attribute", from: op.to, to: op.from };
2617
- case "add_attribute":
2618
- return { type: "remove_attribute", name: op.attribute.name, backup_config: op.attribute };
2619
- case "remove_attribute":
2620
- return { type: "add_attribute", attribute: op.backup_config };
2621
- case "change_type":
2622
- return {
2623
- type: "change_type",
2624
- name: op.name,
2625
- from: op.to,
2626
- to: op.from,
2627
- transform: op.transform ? resolveBuiltInTransform(op.from) : void 0
2628
- };
2629
- case "update_config":
2630
- return { type: "update_config", name: op.name, from: op.to, to: op.from };
2631
- case "rename_object":
2632
- return { type: "rename_object", from: op.to, to: op.from };
2633
- case "remove_object":
2634
- return { type: "remove_object", backup: op.backup };
2635
- }
2636
- }
2637
2732
  var MigrationBuilder = class {
2638
2733
  constructor(version) {
2639
2734
  this.operations = [];
@@ -2719,14 +2814,12 @@ var MigrationBuilder = class {
2719
2814
  // BUILD
2720
2815
  // --------------------------------------------------------------------------
2721
2816
  /**
2722
- * Produce the final MigrationDefinition with auto-generated reverse operations.
2817
+ * Produce the final MigrationDefinition.
2723
2818
  */
2724
2819
  build() {
2725
- const reverse_operations = [...this.operations].reverse().map((op) => reverseOperation(op));
2726
2820
  return {
2727
2821
  version: this.version,
2728
- operations: [...this.operations],
2729
- reverse_operations
2822
+ operations: [...this.operations]
2730
2823
  };
2731
2824
  }
2732
2825
  };
@@ -2740,7 +2833,7 @@ var ObjectBuilder = class {
2740
2833
  name: config.name,
2741
2834
  label: config.label,
2742
2835
  attributes: [],
2743
- system: false
2836
+ system: true
2744
2837
  };
2745
2838
  }
2746
2839
  /**
@@ -2778,11 +2871,21 @@ var ObjectBuilder = class {
2778
2871
  return this;
2779
2872
  }
2780
2873
  /**
2781
- * Mark as system/native object (defined in code, protected)
2782
- * System objects cannot be deleted/modified by clients
2874
+ * Marks this object as runtime-only (system: false).
2875
+ *
2876
+ * ⚠️ ADVANCED USE ONLY. In production schemas, objects declared in code are
2877
+ * automatically system:true (immutable at runtime). Use .runtime() ONLY for:
2878
+ * - Test fixtures (`*.test.ts`, `tests/`)
2879
+ * - Seed data (`seeds/`)
2880
+ * - Dev fixtures (`fixtures/`)
2881
+ *
2882
+ * Calling .runtime() in production code creates an object that:
2883
+ * - Can be modified or deleted by end users via the admin UI
2884
+ * - Is not part of your code contract
2885
+ * - Will be picked up by `standards diff` as runtime drift
2783
2886
  */
2784
- system() {
2785
- this.obj.system = true;
2887
+ runtime() {
2888
+ this.obj.system = false;
2786
2889
  return this;
2787
2890
  }
2788
2891
  /**
@@ -2853,6 +2956,19 @@ var ObjectBuilder = class {
2853
2956
  this._labelExpression = template;
2854
2957
  return this;
2855
2958
  }
2959
+ /**
2960
+ * Attach a document layout convention to this object. Defines named variant
2961
+ * sub-folders and installable preset structures inside a record's drive.
2962
+ */
2963
+ documentLayout(layout) {
2964
+ if (layout.presets) {
2965
+ for (const preset of layout.presets) {
2966
+ validatePresetDepth(preset.structure, 1);
2967
+ }
2968
+ }
2969
+ this.obj.documentLayout = layout;
2970
+ return this;
2971
+ }
2856
2972
  /**
2857
2973
  * Declare a schema migration for this object.
2858
2974
  *
@@ -2953,6 +3069,16 @@ The labelExpression defines how records are displayed in lists and relations.
2953
3069
  function object(config) {
2954
3070
  return new ObjectBuilder(config);
2955
3071
  }
3072
+ function validatePresetDepth(nodes, depth) {
3073
+ if (depth > MAX_PRESET_DEPTH) {
3074
+ throw new Error(`Preset structure exceeds max depth of ${MAX_PRESET_DEPTH}`);
3075
+ }
3076
+ for (const node of nodes) {
3077
+ if (node.children && node.children.length > 0) {
3078
+ validatePresetDepth(node.children, depth + 1);
3079
+ }
3080
+ }
3081
+ }
2956
3082
  var GroupBuilder = class {
2957
3083
  constructor(id, label) {
2958
3084
  this.data = { fields: [] };
@@ -4521,8 +4647,8 @@ var NativeObjectRegistryClass = class {
4521
4647
  * @example
4522
4648
  * ```typescript
4523
4649
  * // No .build() needed - registry auto-builds!
4650
+ * // Objects are system:true by default (immutable at runtime).
4524
4651
  * const PRODUCT = object({ id: "obj-product", name: "products", label: "Product" })
4525
- * .system()
4526
4652
  * .attribute(text({ id: "attr-name", name: "name", label: "Name" }));
4527
4653
  *
4528
4654
  * registry.register(PRODUCT); // ← Auto-builds here
@@ -4550,7 +4676,7 @@ var NativeObjectRegistryClass = class {
4550
4676
  if (!object2.system) {
4551
4677
  throw new Error(
4552
4678
  `[NativeObjectRegistry] Cannot register object "${object2.name}" (id: ${object2.id}): missing system flag.
4553
- Native objects must have system=true. Did you forget to call .system() in your builder?`
4679
+ Native objects must have system=true. Did you call .runtime() on the builder? Remove that call \u2014 objects are system:true by default.`
4554
4680
  );
4555
4681
  }
4556
4682
  if (this.objects.has(object2.name)) {
@@ -5427,7 +5553,6 @@ var OPERATOR_SPECS = {
5427
5553
  "user",
5428
5554
  "multiselect",
5429
5555
  "relation",
5430
- "document",
5431
5556
  "formula"
5432
5557
  ],
5433
5558
  evaluateInMemory: (v, rv) => {
@@ -5436,16 +5561,7 @@ var OPERATOR_SPECS = {
5436
5561
  }
5437
5562
  },
5438
5563
  not_contains: {
5439
- appliesTo: [
5440
- "text",
5441
- "textarea",
5442
- "phone",
5443
- "user",
5444
- "multiselect",
5445
- "relation",
5446
- "document",
5447
- "formula"
5448
- ],
5564
+ appliesTo: ["text", "textarea", "phone", "user", "multiselect", "relation", "formula"],
5449
5565
  evaluateInMemory: (v, rv) => {
5450
5566
  if (Array.isArray(v)) return !v.map(toStr).includes(toStr(rv));
5451
5567
  return !toStr(v).toLowerCase().includes(toStr(rv).toLowerCase());
@@ -5607,7 +5723,7 @@ var OPERATOR_SPECS = {
5607
5723
  },
5608
5724
  // ---- select multi-value ----
5609
5725
  any_of: {
5610
- appliesTo: ["status", "select", "relation", "document"],
5726
+ appliesTo: ["status", "select", "relation"],
5611
5727
  evaluateInMemory: (v, rv) => {
5612
5728
  const ruleArr = toArr(rv).map(toStr);
5613
5729
  const valArr = toArr(v).map(toStr);
@@ -5615,7 +5731,7 @@ var OPERATOR_SPECS = {
5615
5731
  }
5616
5732
  },
5617
5733
  none_of: {
5618
- appliesTo: ["status", "select", "relation", "document"],
5734
+ appliesTo: ["status", "select", "relation"],
5619
5735
  evaluateInMemory: (v, rv) => {
5620
5736
  const ruleArr = toArr(rv).map(toStr);
5621
5737
  const valArr = toArr(v).map(toStr);
@@ -5753,4 +5869,4 @@ function validateQualifiedRule(rule, context) {
5753
5869
  assertOperatorForType(rule.operator, propDef.type, "property");
5754
5870
  }
5755
5871
 
5756
- export { ALLOWED_PROPERTY_TYPES, ALL_ACTIONS, ALL_SYSTEM_RESOURCES, AccessDeniedError, ActivityTabConfig, AttributeInUseError, AttributeNotFoundError, BEHAVIOR_PROPERTIES, ConcurrentModificationError, CustomTabConfig, DB_COLUMN_FIELDS, DEFAULT_DOCUMENT_SLOT, DEFAULT_ROLES, DEFAULT_ROLE_DESCRIPTIONS, DEFAULT_ROLE_LABELS, DEFAULT_ROLE_PERMISSIONS, DOCUMENT_SYSTEM_ATTRIBUTES, DetailViewBuilder, DocumentSlotValidationError, DocumentsTabConfig, DuplicateError, EMPTY_VALUE_PLACEHOLDER, FORM_FORBIDDEN_ATTRIBUTE_TYPES, FlagRegistry, FlagService, ForbiddenError, FormBuilder, FormRegistry, FormRowBuilder, FormStepBuilder, GroupBuilder, IDENTITY_PROPERTIES, InvalidPathError, ListViewBuilder, ListViewTabConfigBuilder, MaxDepthExceededError, MemoryNotFoundError, NO_VALUE_OPERATORS, NoopGeocodingAdapter, NotFoundError, NotImplementedError, OPERATORS_BY_TYPE, OPERATOR_SPECS, ObjectBuilder, ObjectNotFoundError, ObjectReferencedError, PRESENTATION_PROPERTIES, ProtectedResourceError, ProtectedRoleError, QUALIFIED_SEPARATOR, RELATION_TARGET_ANY, RESERVED_ATTRIBUTE_NAMES, RecordNotFoundError, RecordReferencedError, RelationGroupBuilder, RepositoryError, RichtextTabConfig, RoleNotFoundError, STANDARD_SCHEMA_VENDOR, SYSTEM_ATTRIBUTES, SYSTEM_ATTRIBUTE_I18N_KEYS, SYSTEM_FIELD_NAMES, SYSTEM_RESOURCES, SYSTEM_RESOURCE_LABELS, SchemaError, SchemaErrorCode, StorageError, SyncError, TabBuilder, TableTabConfig, USER_STATUSES, ValidationError, accessLevelToActions, actionsToAccessLevel, applyPipes, booleanFlag, buildPropertySchema, buildQualifiedAttribute, checkbox, createFlagRegistry, createFlagService, createStandardSchemaProps, currency, date, detailView, document, evaluateFilterState, evaluateFormula, evaluateFormulaAttribute, evaluateFormulaWithResult, extractAttributeNames, extractFormulaVariables, extractRelationNames, extractRelationReferences, file, flagRegistry, flattenRelationsForEval, form, formRegistry, formatAttributeValue, formatFormulaResult, formula, generateDefaultDetailView, generateDefaultListView, getActiveTab, getErrorMessage, getOperatorPolarity, getPathDepth, getRelationPath, getRollupFilterOperators, getSystemAttributeI18nKey, getSystemAttributeList, getTargetAttributeName, group, hasOptions, hasRelationReferences, inferInverseCardinality, isAttributeInUseError, isAttributeSortable, isBilateralRelation, isDefaultRole, isDetailView, isDocumentAttribute, isEmptyObject, isFieldGroup, isFormDefinition, isFormFieldsRow, isFormFreeFieldRef, isFormHeadingRow, isFormSeparatorRow, isFormSlotFieldRef, isFormTextRow, isLabelExpression, isListView, isNoValueOperator, isNotEmpty, isNotFoundError, isObjectReferencedError, isProtectedResourceError, isRecordReferencedError, isRelationGroup, isSchemaError, isStandardSchema, isUniversalRelation, isValidationError, jsonFlag, listView, location, matchesMime, multiselect, normaliseDocumentSlots, normalizeForEdgeRpc, number, numberFlag, object, parsePath, parseQualifiedAttribute, pathHasManyCardinality, phone, rating, registry, relation, relationGroup, renderLabelExpression, resetViewToDefault, richtext, rollup, select, status, stringFlag, text, textarea, toUndefinedIfEmpty, user, validateAttributeName, validateFormulaExpression, validatePath, validateQualifiedRule, validateSlotAgainstConfig, viewRegistry };
5872
+ export { ALLOWED_PROPERTY_TYPES, ALL_ACTIONS, ALL_SYSTEM_RESOURCES, AccessDeniedError, ActivityTabConfig, AttributeInUseError, AttributeNotFoundError, BEHAVIOR_PROPERTIES, ChangeTypeNotSupportedError, ConcurrentModificationError, CustomTabConfig, DB_COLUMN_FIELDS, DEFAULT_DOCUMENT_SLOT, DEFAULT_ROLES, DEFAULT_ROLE_DESCRIPTIONS, DEFAULT_ROLE_LABELS, DEFAULT_ROLE_PERMISSIONS, DOCUMENT_SYSTEM_ATTRIBUTES, DestructiveSyncNotAllowedError, DetailViewBuilder, DocumentSlotValidationError, DocumentsTabConfig, DuplicateError, EMPTY_VALUE_PLACEHOLDER, FORM_FORBIDDEN_ATTRIBUTE_TYPES, FlagRegistry, FlagService, ForbiddenError, FormBuilder, FormRegistry, FormRowBuilder, FormStepBuilder, GroupBuilder, IDENTITY_PROPERTIES, InvalidPathError, ListViewBuilder, ListViewTabConfigBuilder, MAX_PRESET_DEPTH, MaxDepthExceededError, MemoryNotFoundError, MigrationTimeoutError, NO_VALUE_OPERATORS, NoopGeocodingAdapter, NotFoundError, NotImplementedError, OPERATORS_BY_TYPE, OPERATOR_SPECS, ObjectBuilder, ObjectNotFoundError, ObjectReferencedError, OrphanSystemAttributeError, PRESENTATION_PROPERTIES, ProtectedResourceError, ProtectedRoleError, QUALIFIED_SEPARATOR, RELATION_TARGET_ANY, RESERVED_ATTRIBUTE_NAMES, RecordNotFoundError, RecordReferencedError, RelationGroupBuilder, RepositoryError, RichtextTabConfig, RoleNotFoundError, STANDARD_SCHEMA_VENDOR, SYSTEM_ATTRIBUTES, SYSTEM_ATTRIBUTE_I18N_KEYS, SYSTEM_FIELD_NAMES, SYSTEM_RESOURCES, SYSTEM_RESOURCE_LABELS, SchemaError, SchemaErrorCode, StorageError, SyncCascadeError, SyncConflictError, SyncError, SystemEntityImmutableError, TabBuilder, TableTabConfig, USER_STATUSES, ValidationError, accessLevelToActions, actionsToAccessLevel, applyPipes, booleanFlag, buildPropertySchema, buildQualifiedAttribute, checkbox, createFlagRegistry, createFlagService, createStandardSchemaProps, currency, date, detailView, document, evaluateFilterState, evaluateFormula, evaluateFormulaAttribute, evaluateFormulaWithResult, extractAttributeNames, extractFormulaVariables, extractRelationNames, extractRelationReferences, file, flagRegistry, flattenRelationsForEval, form, formRegistry, formatAttributeValue, formatFormulaResult, formula, generateDefaultDetailView, generateDefaultListView, getActiveTab, getErrorMessage, getOperatorPolarity, getPathDepth, getRelationPath, getRollupFilterOperators, getSystemAttributeI18nKey, getSystemAttributeList, getTargetAttributeName, group, hasOptions, hasRelationReferences, inferInverseCardinality, isAttributeInUseError, isAttributeSortable, isBilateralRelation, isDefaultRole, isDetailView, isDocumentAttribute, isEmptyObject, isFieldGroup, isFormDefinition, isFormFieldsRow, isFormFreeFieldRef, isFormHeadingRow, isFormSeparatorRow, isFormSlotFieldRef, isFormTextRow, isLabelExpression, isListView, isNoValueOperator, isNotEmpty, isNotFoundError, isObjectReferencedError, isProtectedResourceError, isRecordReferencedError, isRelationGroup, isSchemaError, isStandardSchema, isUniversalRelation, isValidationError, jsonFlag, listView, location, matchesMime, multiselect, normaliseDocumentSlots, normalizeForEdgeRpc, number, numberFlag, object, parsePath, parseQualifiedAttribute, pathHasManyCardinality, phone, rating, registry, relation, relationGroup, renderLabelExpression, resetViewToDefault, richtext, rollup, select, status, stringFlag, text, textarea, toUndefinedIfEmpty, user, validateAttributeName, validateFormulaExpression, validatePath, validateQualifiedRule, validateSlotAgainstConfig, viewRegistry };
@@ -1,4 +1,4 @@
1
- import { A as Attribute } from './filters-qNc-JmQI.js';
1
+ import { A as Attribute } from './filters-DVBn5tov.js';
2
2
 
3
3
  /**
4
4
  * Validation messages for Zod validators.
@@ -1,4 +1,4 @@
1
- import { A as Attribute } from './filters-DVbxM2W4.mjs';
1
+ import { A as Attribute } from './filters-HDG4kLoo.mjs';
2
2
 
3
3
  /**
4
4
  * Validation messages for Zod validators.
@@ -1,8 +1,8 @@
1
- export { V as ValidationMessages } from '../types-BTrwWar6.mjs';
1
+ export { V as ValidationMessages } from '../types-C5DittlR.mjs';
2
2
  export { DEFAULT_VALIDATION_MESSAGES, formatZodErrors } from './core/index.mjs';
3
3
  export { parseAttributeConfig } from './config/index.mjs';
4
- export { c as computeRecordStatus, a as createFormAttributeValidator, v as validateDraft, b as validateDraftOrThrow, d as validateObject, e as validateObjectOrThrow } from '../helpers-g5uHrKfE.mjs';
5
- import '../filters-DVbxM2W4.mjs';
4
+ export { c as computeRecordStatus, a as createFormAttributeValidator, v as validateDraft, b as validateDraftOrThrow, d as validateObject, e as validateObjectOrThrow } from '../helpers-BjuFhbQQ.mjs';
5
+ import '../filters-HDG4kLoo.mjs';
6
6
  import '@stndrds/constants';
7
7
  import '../utils.mjs';
8
8
  import 'zod';
@@ -1,8 +1,8 @@
1
- export { V as ValidationMessages } from '../types-CQTltaH_.js';
1
+ export { V as ValidationMessages } from '../types-Bdlhgrf7.js';
2
2
  export { DEFAULT_VALIDATION_MESSAGES, formatZodErrors } from './core/index.js';
3
3
  export { parseAttributeConfig } from './config/index.js';
4
- export { c as computeRecordStatus, a as createFormAttributeValidator, v as validateDraft, b as validateDraftOrThrow, d as validateObject, e as validateObjectOrThrow } from '../helpers-D-_4FAcR.js';
5
- import '../filters-qNc-JmQI.js';
4
+ export { c as computeRecordStatus, a as createFormAttributeValidator, v as validateDraft, b as validateDraftOrThrow, d as validateObject, e as validateObjectOrThrow } from '../helpers-CSuoa3kj.js';
5
+ import '../filters-DVBn5tov.js';
6
6
  import '@stndrds/constants';
7
7
  import '../utils.js';
8
8
  import 'zod';
@@ -2,7 +2,8 @@
2
2
 
3
3
  require('../chunk-PGERPYDR.js');
4
4
  var chunkYQROI4IE_js = require('../chunk-YQROI4IE.js');
5
- var chunkHG6EF4XD_js = require('../chunk-HG6EF4XD.js');
5
+ var chunk64R5X3DF_js = require('../chunk-64R5X3DF.js');
6
+ require('../chunk-MAKSIK3P.js');
6
7
  require('../chunk-J5HRK3WD.js');
7
8
  require('../chunk-TKN73433.js');
8
9
  require('../chunk-D7WFIGXW.js');
@@ -12,7 +13,6 @@ require('../chunk-EZHMVZQ4.js');
12
13
  require('../chunk-VXOTYFEW.js');
13
14
  require('../chunk-OAQWRMTP.js');
14
15
  require('../chunk-ACQ3TUFK.js');
15
- require('../chunk-MAKSIK3P.js');
16
16
  require('../chunk-DC7YYE3U.js');
17
17
  require('../chunk-ROAZLZA2.js');
18
18
  require('../chunk-CCB4OY2O.js');
@@ -28,27 +28,27 @@ Object.defineProperty(exports, "parseAttributeConfig", {
28
28
  });
29
29
  Object.defineProperty(exports, "computeRecordStatus", {
30
30
  enumerable: true,
31
- get: function () { return chunkHG6EF4XD_js.computeRecordStatus; }
31
+ get: function () { return chunk64R5X3DF_js.computeRecordStatus; }
32
32
  });
33
33
  Object.defineProperty(exports, "createFormAttributeValidator", {
34
34
  enumerable: true,
35
- get: function () { return chunkHG6EF4XD_js.createFormAttributeValidator; }
35
+ get: function () { return chunk64R5X3DF_js.createFormAttributeValidator; }
36
36
  });
37
37
  Object.defineProperty(exports, "validateDraft", {
38
38
  enumerable: true,
39
- get: function () { return chunkHG6EF4XD_js.validateDraft; }
39
+ get: function () { return chunk64R5X3DF_js.validateDraft; }
40
40
  });
41
41
  Object.defineProperty(exports, "validateDraftOrThrow", {
42
42
  enumerable: true,
43
- get: function () { return chunkHG6EF4XD_js.validateDraftOrThrow; }
43
+ get: function () { return chunk64R5X3DF_js.validateDraftOrThrow; }
44
44
  });
45
45
  Object.defineProperty(exports, "validateObject", {
46
46
  enumerable: true,
47
- get: function () { return chunkHG6EF4XD_js.validateObject; }
47
+ get: function () { return chunk64R5X3DF_js.validateObject; }
48
48
  });
49
49
  Object.defineProperty(exports, "validateObjectOrThrow", {
50
50
  enumerable: true,
51
- get: function () { return chunkHG6EF4XD_js.validateObjectOrThrow; }
51
+ get: function () { return chunk64R5X3DF_js.validateObjectOrThrow; }
52
52
  });
53
53
  Object.defineProperty(exports, "DEFAULT_VALIDATION_MESSAGES", {
54
54
  enumerable: true,
@@ -1,6 +1,7 @@
1
1
  import '../chunk-SP3PNHYF.mjs';
2
2
  export { parseAttributeConfig } from '../chunk-U4JC7P6D.mjs';
3
- export { computeRecordStatus, createFormAttributeValidator, validateDraft, validateDraftOrThrow, validateObject, validateObjectOrThrow } from '../chunk-M7ZNKBOE.mjs';
3
+ export { computeRecordStatus, createFormAttributeValidator, validateDraft, validateDraftOrThrow, validateObject, validateObjectOrThrow } from '../chunk-6JEQE4IP.mjs';
4
+ import '../chunk-TMYBEXBT.mjs';
4
5
  import '../chunk-4KRLCWJM.mjs';
5
6
  import '../chunk-KNYZH2WD.mjs';
6
7
  import '../chunk-RUYUFXNW.mjs';
@@ -10,7 +11,6 @@ import '../chunk-SMOHDR6M.mjs';
10
11
  import '../chunk-ITTQ4FGR.mjs';
11
12
  import '../chunk-IRTRJH37.mjs';
12
13
  import '../chunk-OLJLCVNY.mjs';
13
- import '../chunk-TMYBEXBT.mjs';
14
14
  import '../chunk-TEQNVO7W.mjs';
15
15
  import '../chunk-4TC27SMF.mjs';
16
16
  import '../chunk-TBYXYSGA.mjs';
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { C as CurrencyAttribute } from '../../filters-DVbxM2W4.mjs';
3
- import { V as ValidationMessages } from '../../types-BTrwWar6.mjs';
2
+ import { C as CurrencyAttribute } from '../../filters-HDG4kLoo.mjs';
3
+ import { V as ValidationMessages } from '../../types-C5DittlR.mjs';
4
4
  import '@stndrds/constants';
5
5
  import '../../utils.mjs';
6
6
 
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { C as CurrencyAttribute } from '../../filters-qNc-JmQI.js';
3
- import { V as ValidationMessages } from '../../types-CQTltaH_.js';
2
+ import { C as CurrencyAttribute } from '../../filters-DVBn5tov.js';
3
+ import { V as ValidationMessages } from '../../types-Bdlhgrf7.js';
4
4
  import '@stndrds/constants';
5
5
  import '../../utils.js';
6
6