@happyvertical/smrt-core 0.54.1 → 0.54.3

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 (138) hide show
  1. package/AGENTS.md +6 -1
  2. package/README.md +8 -0
  3. package/agents/change-feed.md +7 -12
  4. package/agents/generators.md +13 -0
  5. package/agents/object-runtime.md +8 -0
  6. package/agents/schema-paths.md +14 -0
  7. package/dist/audit-context.d.ts +4 -0
  8. package/dist/audit-context.d.ts.map +1 -0
  9. package/dist/audit-context.js +16 -0
  10. package/dist/audit-context.js.map +1 -0
  11. package/dist/audit.d.ts +34 -0
  12. package/dist/audit.d.ts.map +1 -0
  13. package/dist/audit.js +63 -0
  14. package/dist/audit.js.map +1 -0
  15. package/dist/browser.d.ts +2 -1
  16. package/dist/browser.d.ts.map +1 -1
  17. package/dist/browser.js +4 -3
  18. package/dist/cascade.d.ts +1 -1
  19. package/dist/cascade.d.ts.map +1 -1
  20. package/dist/cascade.js +10 -7
  21. package/dist/cascade.js.map +1 -1
  22. package/dist/change-feed.js +1 -1
  23. package/dist/collection.d.ts +9 -2
  24. package/dist/collection.d.ts.map +1 -1
  25. package/dist/collection.js +59 -4
  26. package/dist/collection.js.map +1 -1
  27. package/dist/embedded-write-queue.d.ts +2 -0
  28. package/dist/embedded-write-queue.d.ts.map +1 -1
  29. package/dist/embedded-write-queue.js +12 -5
  30. package/dist/embedded-write-queue.js.map +1 -1
  31. package/dist/generators/changes-route.js +1 -1
  32. package/dist/generators/mcp-runtime-template.d.ts +2 -0
  33. package/dist/generators/mcp-runtime-template.d.ts.map +1 -1
  34. package/dist/generators/mcp-runtime-template.js +18 -16
  35. package/dist/generators/mcp-runtime-template.js.map +1 -1
  36. package/dist/generators/mcp-tool-name.d.ts +6 -0
  37. package/dist/generators/mcp-tool-name.d.ts.map +1 -1
  38. package/dist/generators/mcp-tool-name.js.map +1 -1
  39. package/dist/generators/mcp.d.ts +34 -1
  40. package/dist/generators/mcp.d.ts.map +1 -1
  41. package/dist/generators/mcp.js +148 -110
  42. package/dist/generators/mcp.js.map +1 -1
  43. package/dist/generators/rest.d.ts.map +1 -1
  44. package/dist/generators/rest.js +16 -7
  45. package/dist/generators/rest.js.map +1 -1
  46. package/dist/index.d.ts +3 -1
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +9 -7
  49. package/dist/junction.d.ts +29 -10
  50. package/dist/junction.d.ts.map +1 -1
  51. package/dist/junction.js +31 -12
  52. package/dist/junction.js.map +1 -1
  53. package/dist/knowledge.js +1 -1
  54. package/dist/knowledge.js.map +1 -1
  55. package/dist/manifest/manifest-loader.d.ts.map +1 -1
  56. package/dist/manifest/manifest-loader.js +1 -1
  57. package/dist/manifest/manifest-loader.js.map +1 -1
  58. package/dist/manifest/static-manifest.d.ts.map +1 -1
  59. package/dist/manifest/static-manifest.js +106 -9
  60. package/dist/manifest/static-manifest.js.map +1 -1
  61. package/dist/manifest/store.d.ts +8 -0
  62. package/dist/manifest/store.d.ts.map +1 -1
  63. package/dist/manifest/store.js +12 -2
  64. package/dist/manifest/store.js.map +1 -1
  65. package/dist/manifest.json +119 -9
  66. package/dist/migrations/differ.d.ts +3 -3
  67. package/dist/migrations/differ.d.ts.map +1 -1
  68. package/dist/migrations/differ.js +8 -4
  69. package/dist/migrations/differ.js.map +1 -1
  70. package/dist/object.d.ts +1 -0
  71. package/dist/object.d.ts.map +1 -1
  72. package/dist/object.js +19 -7
  73. package/dist/object.js.map +1 -1
  74. package/dist/registry/class-registration.d.ts.map +1 -1
  75. package/dist/registry/class-registration.js +75 -10
  76. package/dist/registry/class-registration.js.map +1 -1
  77. package/dist/registry/collection-resolution.d.ts +2 -2
  78. package/dist/registry/collection-resolution.d.ts.map +1 -1
  79. package/dist/registry/collection-resolution.js +2 -1
  80. package/dist/registry/collection-resolution.js.map +1 -1
  81. package/dist/registry/collision-policy.d.ts +8 -0
  82. package/dist/registry/collision-policy.d.ts.map +1 -1
  83. package/dist/registry/collision-policy.js +2 -2
  84. package/dist/registry/collision-policy.js.map +1 -1
  85. package/dist/registry/framework-base-classes.d.ts.map +1 -1
  86. package/dist/registry/framework-base-classes.js +2 -1
  87. package/dist/registry/framework-base-classes.js.map +1 -1
  88. package/dist/registry/schema-builder.d.ts.map +1 -1
  89. package/dist/registry/schema-builder.js +33 -4
  90. package/dist/registry/schema-builder.js.map +1 -1
  91. package/dist/registry/shared-state.d.ts +6 -0
  92. package/dist/registry/shared-state.d.ts.map +1 -1
  93. package/dist/registry/shared-state.js +12 -1
  94. package/dist/registry/shared-state.js.map +1 -1
  95. package/dist/registry/types.d.ts +7 -1
  96. package/dist/registry/types.d.ts.map +1 -1
  97. package/dist/registry.d.ts +7 -1
  98. package/dist/registry.d.ts.map +1 -1
  99. package/dist/registry.js +25 -3
  100. package/dist/registry.js.map +1 -1
  101. package/dist/scanner/manifest-generator.d.ts.map +1 -1
  102. package/dist/scanner/manifest-generator.js +5 -1
  103. package/dist/scanner/manifest-generator.js.map +1 -1
  104. package/dist/scanner/types.d.ts +8 -0
  105. package/dist/scanner/types.d.ts.map +1 -1
  106. package/dist/scanner/types.js.map +1 -1
  107. package/dist/schema/ddl/duckdb-strategy.d.ts.map +1 -1
  108. package/dist/schema/ddl/duckdb-strategy.js +1 -0
  109. package/dist/schema/ddl/duckdb-strategy.js.map +1 -1
  110. package/dist/schema/ddl/null-equal-index.d.ts.map +1 -1
  111. package/dist/schema/ddl/null-equal-index.js +4 -2
  112. package/dist/schema/ddl/null-equal-index.js.map +1 -1
  113. package/dist/schema/generator.d.ts +3 -0
  114. package/dist/schema/generator.d.ts.map +1 -1
  115. package/dist/schema/generator.js +38 -0
  116. package/dist/schema/generator.js.map +1 -1
  117. package/dist/smrt-knowledge.json +74 -20
  118. package/dist/sync/apply.d.ts +2 -0
  119. package/dist/sync/apply.d.ts.map +1 -1
  120. package/dist/sync/apply.js +7 -3
  121. package/dist/sync/apply.js.map +1 -1
  122. package/dist/utils/scanner-module.d.ts +9 -0
  123. package/dist/utils/scanner-module.d.ts.map +1 -1
  124. package/dist/vite-plugin/index.d.ts +14 -0
  125. package/dist/vite-plugin/index.d.ts.map +1 -1
  126. package/dist/vite-plugin/index.js +58 -18
  127. package/dist/vite-plugin/index.js.map +1 -1
  128. package/dist/vite-plugin/package-stamp.d.ts +41 -0
  129. package/dist/vite-plugin/package-stamp.d.ts.map +1 -0
  130. package/dist/vite-plugin/package-stamp.js +33 -0
  131. package/dist/vite-plugin/package-stamp.js.map +1 -0
  132. package/dist/vite-plugin/sveltekit-generator.js +5 -3
  133. package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
  134. package/dist/vite-plugin/sync-apply-route.d.ts.map +1 -1
  135. package/dist/vite-plugin/sync-apply-route.js +10 -0
  136. package/dist/vite-plugin/sync-apply-route.js.map +1 -1
  137. package/dist/vite-plugin.js +2 -2
  138. package/package.json +10 -10
@@ -1 +1 @@
1
- {"version":3,"file":"class-registration.d.ts","sourceRoot":"","sources":["../../src/registry/class-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAKV,qBAAqB,EAGtB,MAAM,qBAAqB,CAAC;AAqD7B,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAkDpB;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAS3E;AA4BD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAeT;AA2oBD;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,OAAO,UAAU,EACvB,MAAM,GAAE,iBAAsB,GAC7B,IAAI,CASN;AAomCD,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAMlB,qBAAqB,EAAE,WAAW,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC,GAC3E,IAAI,CAeN;AA+BD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACpC,kBAAkB,EAAE,eAAe,CAAC,oBAAoB,CAAC,GAAG,SAAS,GACpE,IAAI,CAyCN;AAoHD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,eAAe,EACzB,gBAAgB,CAAC,EAAE;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACA,IAAI,CA4CN;AAmLD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,qBAAqB,EAChC,mBAAmB,CAAC,EAAE,MAAM,GAC3B,IAAI,CAUN"}
1
+ {"version":3,"file":"class-registration.d.ts","sourceRoot":"","sources":["../../src/registry/class-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAwBH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAKV,qBAAqB,EAGtB,MAAM,qBAAqB,CAAC;AAsD7B,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAkDpB;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAS3E;AA4BD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAeT;AAstBD;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,OAAO,UAAU,EACvB,MAAM,GAAE,iBAAsB,GAC7B,IAAI,CASN;AA8nCD,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAMlB,qBAAqB,EAAE,WAAW,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC,GAC3E,IAAI,CAeN;AA+BD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACpC,kBAAkB,EAAE,eAAe,CAAC,oBAAoB,CAAC,GAAG,SAAS,GACpE,IAAI,CAyCN;AAoHD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,eAAe,EACzB,gBAAgB,CAAC,EAAE;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACA,IAAI,CA4CN;AA0LD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,qBAAqB,EAChC,mBAAmB,CAAC,EAAE,MAAM,GAC3B,IAAI,CAUN"}
@@ -1,16 +1,16 @@
1
1
  import { ConfigurationError } from "../errors.js";
2
2
  import { toSnakeCase } from "../utils/naming.js";
3
3
  import { declareChangeFeedSensitiveTable, setChangeFeedSensitiveClassResolver } from "../change-feed-sensitivity.js";
4
+ import { tableNameFromClass } from "../utils.js";
4
5
  import { bumpRegistryGeneration } from "./generation.js";
5
6
  import { createQualifiedName, isQualifiedName, parseQualifiedName } from "../utils/qualified-names.js";
6
- import { getClasses, getCollections, getConstructorFieldDecorators, getConstructorIndex, getConstructorTenantScopedDeclarations, getInheritanceCache, getLegacyFieldDecorators, getSourceFileFromStack, getStiSiblingsLoaded, verboseLog } from "./shared-state.js";
7
- import { cloneManifestSchemaColumns, findWorkspaceRootSync, getLocalTestManifestCache, getManifestCache, getNodeBuiltins, getStaticManifestCache, getTestManifestCache } from "../manifest/store.js";
7
+ import { getClasses, getCollections, getConstructorFieldDecorators, getConstructorIndex, getConstructorTenantScopedDeclarations, getInheritanceCache, getLegacyFieldDecorators, getSourceFileFromStack, getStampedPackageName, getStiSiblingsLoaded, verboseLog } from "./shared-state.js";
8
+ import { cloneManifestSchemaColumns, findWorkspaceRootSync, getLocalTestManifestCache, getManifestCache, getNodeBuiltins, getStaticManifestCache, getTestManifestCache, packageStampsConstructors } from "../manifest/store.js";
8
9
  import { discoverManifestSync, discoverSTISiblingsSync, getPackageName, lookupInManifest, readProjectManifestSync } from "../manifest/manifest-loader.js";
9
10
  import { assertQualifiedNameAliasesAvailable } from "./qualified-name-aliases.js";
10
11
  import { findClass, findClassesByName, getCanonicalClassName, hasClassCaseInsensitive, qualifyExtendsName } from "./name-resolver.js";
11
12
  import { buildInheritanceChain } from "./inheritance-resolver.js";
12
13
  import { compileValidators } from "./validator.js";
13
- import { tableNameFromClass } from "../utils.js";
14
14
  import { SmrtObject } from "../object.js";
15
15
  import { decideCollisionPolicy } from "./collision-policy.js";
16
16
  import { isFrameworkBaseClass } from "./framework-base-classes.js";
@@ -199,7 +199,8 @@ function buildDecoratorCollisionInputs(args) {
199
199
  hasManifestContent: false,
200
200
  registrationKeyDiffersFromExistingKey: false,
201
201
  existingHasNoPackage: !existing.packageName,
202
- declaresDifferentTable: !!newDeclaredTableName && !!existingTableName && newDeclaredTableName !== existingTableName
202
+ declaresDifferentTable: !!newDeclaredTableName && !!existingTableName && newDeclaredTableName !== existingTableName,
203
+ existingPackageStampsConstructors: !!existing.packageName && packageStampsConstructors(existing.packageName)
203
204
  };
204
205
  }
205
206
  /**
@@ -270,7 +271,8 @@ function buildManifestCollisionInputs(args) {
270
271
  hasManifestContent: !!(objectDef.fields || objectDef.methods || objectDef.schema || objectDef.decoratorConfig),
271
272
  registrationKeyDiffersFromExistingKey: registrationKey !== existingKey,
272
273
  existingHasNoPackage: !existing.packageName,
273
- declaresDifferentTable: false
274
+ declaresDifferentTable: false,
275
+ existingPackageStampsConstructors: false
274
276
  };
275
277
  }
276
278
  /**
@@ -378,6 +380,55 @@ function validateIsolatedRegistrationManifest(manifest, manifestKey, name, packa
378
380
  function anySensitive(...configs) {
379
381
  return configs.some((config) => config?.sensitive === true);
380
382
  }
383
+ /** Validate ancestry too: a raw child manifest may not carry an inherited table name. */
384
+ function assertStiSensitivity(config, qualifiedName, extendsName, schemaTableName) {
385
+ if (config.tableStrategy === "cti") return;
386
+ const incoming = {
387
+ config,
388
+ qualifiedName,
389
+ extends: extendsName,
390
+ schema: schemaTableName ? { tableName: schemaTableName } : void 0
391
+ };
392
+ const resolve = (name) => {
393
+ if (name === qualifiedName) return incoming;
394
+ const existing = findClass(name);
395
+ if (existing?.qualifiedName === qualifiedName) return incoming;
396
+ if (existing) return existing;
397
+ return name === qualifiedName.split(":").at(-1) ? incoming : void 0;
398
+ };
399
+ const rootOf = (node) => {
400
+ let root;
401
+ const visited = /* @__PURE__ */ new Set();
402
+ let current = node;
403
+ while (current && !visited.has(current.qualifiedName ?? "")) {
404
+ visited.add(current.qualifiedName ?? "");
405
+ if (current.config.tableStrategy === "cti") return void 0;
406
+ if (current.config.tableStrategy === "sti") root = current;
407
+ current = current.extends ? resolve(current.extends) : void 0;
408
+ }
409
+ return root;
410
+ };
411
+ const incomingRoot = rootOf(incoming);
412
+ if (!incomingRoot) return;
413
+ const canonicalName = (node) => node.qualifiedName ?? ("name" in node ? node.name : qualifiedName);
414
+ const rootName = canonicalName(incomingRoot);
415
+ const belongsToHierarchy = (node) => {
416
+ const root = rootOf(node);
417
+ return root !== void 0 && canonicalName(root) === rootName;
418
+ };
419
+ for (const existing of getClasses().values()) {
420
+ const root = rootOf(existing);
421
+ if (!root || !belongsToHierarchy(existing)) continue;
422
+ if (canonicalName(existing) === canonicalName(incoming)) continue;
423
+ if (existing.config.sensitive === true !== (config.sensitive === true)) {
424
+ for (const member of [incoming, ...getClasses().values()]) {
425
+ if (!belongsToHierarchy(member)) continue;
426
+ for (const table of [member.schema?.tableName, member.config.tableName]) if (table) declareChangeFeedSensitiveTable(table);
427
+ }
428
+ throw new ConfigurationError(`STI hierarchy ${root.qualifiedName} has mixed sensitivity; mark every class sensitive or use separate tables.`, "CONFIG_STI_MIXED_SENSITIVITY");
429
+ }
430
+ }
431
+ }
381
432
  function declareSensitiveTable(config, ...tableNames) {
382
433
  if (config.sensitive !== true) return;
383
434
  for (const tableName of tableNames) if (tableName) declareChangeFeedSensitiveTable(tableName);
@@ -438,7 +489,7 @@ function register(ctor, config = {}) {
438
489
  }
439
490
  function registerUntracked(ctor, config = {}) {
440
491
  const name = config.name || ctor.name;
441
- const explicitPackageName = config.packageName;
492
+ const explicitPackageName = config.packageName ?? getStampedPackageName(ctor);
442
493
  let promotedCollectionConstructor;
443
494
  let promotedRuntimeConfig;
444
495
  let promotedReplacementAncestry;
@@ -452,6 +503,11 @@ function registerUntracked(ctor, config = {}) {
452
503
  function upsertExistingEntry(existingKey, existing) {
453
504
  const nextPackageName = explicitPackageName || existing.packageName;
454
505
  const nextKey = nextPackageName ? createQualifiedName(nextPackageName, name) : name;
506
+ assertStiSensitivity({
507
+ ...existing.config,
508
+ ...config,
509
+ ...anySensitive(existing.config, config) ? { sensitive: true } : {}
510
+ }, nextKey, existing.extends, existing.schema?.tableName);
455
511
  const previousIdentity = {
456
512
  name: existing.name,
457
513
  qualifiedName: existing.qualifiedName
@@ -482,6 +538,7 @@ function registerUntracked(ctor, config = {}) {
482
538
  tableName: nextTableName,
483
539
  ...anySensitive(existing.config, config) ? { sensitive: true } : {}
484
540
  };
541
+ existing.collection = existing.config.collection ?? existing.collection;
485
542
  if (!existing.schema) existing.schema = {
486
543
  ddl: "",
487
544
  indexes: [],
@@ -620,6 +677,7 @@ function registerUntracked(ctor, config = {}) {
620
677
  if (findClassesByName(name).some((candidate) => !!candidate.packageName && candidate.packageName !== newPackageName)) return;
621
678
  const entry = discoverManifestSync(name);
622
679
  if (!(!!entry?.packageName && entry.packageName !== newPackageName)) return entry;
680
+ if (entry?.packageName && packageStampsConstructors(entry.packageName)) return;
623
681
  if (isSameSourcePath(newSourceFile, entry?.filePath)) return entry;
624
682
  if (ownPackageDeclaresClass) return void 0;
625
683
  const entryTable = entry?.schema?.tableName || entry?.decoratorConfig?.tableName;
@@ -813,6 +871,7 @@ function registerUntracked(ctor, config = {}) {
813
871
  tableName,
814
872
  ...anySensitive(promotedRuntimeConfig, manifestEntry?.decoratorConfig, config) ? { sensitive: true } : {}
815
873
  };
874
+ assertStiSensitivity(mergedConfig, packageName ? `${packageName}:${name}` : name, getConstructorIndex().get(Object.getPrototypeOf(ctor)) ?? extendsClass, schema?.tableName);
816
875
  declareSensitiveTable(mergedConfig, tableName, schema?.tableName, manifestEntry?.schema?.tableName);
817
876
  const qualifiedName = packageName ? createQualifiedName(packageName, name) : void 0;
818
877
  const visibility = config.visibility || manifestEntry?.visibility || "public";
@@ -828,7 +887,7 @@ function registerUntracked(ctor, config = {}) {
828
887
  validators,
829
888
  validationRules,
830
889
  tools: manifestEntry?.tools,
831
- collection: manifestEntry?.collection ?? inheritedStiCollection(ctor) ?? pluralizeCollection(name),
890
+ collection: config.collection ?? manifestEntry?.collection ?? inheritedStiCollection(ctor) ?? pluralizeCollection(name),
832
891
  collectionConstructor: promotedCollectionConstructor,
833
892
  replacedQualifiedNames: promotedReplacementAncestry,
834
893
  packageName,
@@ -1032,12 +1091,14 @@ function mergeManifestIntoExistingRegistration(existing, objectDef, packageName)
1032
1091
  const runtimeTenantScopedDeclaration = getConstructorTenantScopedDeclarations().get(existing.constructor);
1033
1092
  if (existing.tenantScopedConfigSource !== "explicit" && normalizeTenantScopedConfig(manifestConfig.tenantScoped) === void 0 && runtimeTenantScopedDeclaration) throw new ConfigurationError(`Manifest for '${existing.qualifiedName || existing.name}' omits or disables tenantScoped but its runtime constructor is decorated with @TenantScoped(). Regenerate the manifest so tenancy schema and runtime enforcement agree.`, "CONFIG_TENANT_MANIFEST_CONFLICT");
1034
1093
  const manifestTableName = objectDef.schema?.tableName || manifestConfig.tableName || existing.schema?.tableName || existing.config.tableName || tableNameFromClass(existing.constructor);
1035
- existing.config = {
1094
+ const nextConfig = {
1036
1095
  ...manifestConfig,
1037
1096
  ...existing.config,
1038
1097
  tableName: manifestTableName,
1039
1098
  ...anySensitive(manifestConfig, existing.config) ? { sensitive: true } : {}
1040
1099
  };
1100
+ assertStiSensitivity(nextConfig, existing.qualifiedName || existing.name, objectDef.extendsQualified ?? existing.extends ?? objectDef.extends, objectDef.schema?.tableName ?? existing.schema?.tableName);
1101
+ existing.config = nextConfig;
1041
1102
  declareSensitiveTable(existing.config, manifestTableName, objectDef.schema?.tableName, existing.schema?.tableName);
1042
1103
  if (objectDef.fields) for (const [fieldName, fd] of Object.entries(objectDef.fields)) {
1043
1104
  if (!existing.fields.has(fieldName)) {
@@ -1114,7 +1175,7 @@ function mergeManifestIntoExistingRegistration(existing, objectDef, packageName)
1114
1175
  const manifestParent = objectDef.extendsQualified ?? objectDef.extends;
1115
1176
  if (manifestParent) existing.extends = packageName ? qualifyExtendsName(manifestParent, packageName) : manifestParent;
1116
1177
  if (!existing.sourceFilePath && objectDef.filePath) existing.sourceFilePath = objectDef.filePath;
1117
- if (objectDef.collection) existing.collection = objectDef.collection;
1178
+ if (objectDef.collection) existing.collection = existing.config.collection ?? objectDef.collection;
1118
1179
  existing.visibility = objectDef.visibility || manifestConfig.visibility || existing.visibility;
1119
1180
  invalidateInheritanceEntries(existing);
1120
1181
  }
@@ -1178,6 +1239,10 @@ function registerFromManifestUntracked(name, objectDef, manifestPackageName) {
1178
1239
  if (objectDef.methods) for (const [methodName, methodDef] of Object.entries(objectDef.methods)) methods.set(methodName, methodDef);
1179
1240
  const config = objectDef.decoratorConfig || {};
1180
1241
  const tableName = config.tableName || tableNameFromClass(stubConstructor);
1242
+ assertStiSensitivity({
1243
+ ...config,
1244
+ tableName
1245
+ }, qualifiedNameEarly || name, objectDef.extendsQualified ?? objectDef.extends, objectDef.schema?.tableName);
1181
1246
  declareSensitiveTable(config, tableName, objectDef.schema?.tableName);
1182
1247
  let schema;
1183
1248
  if (objectDef.schema) {
@@ -1235,7 +1300,7 @@ function registerFromManifestUntracked(name, objectDef, manifestPackageName) {
1235
1300
  validators,
1236
1301
  validationRules,
1237
1302
  tools: objectDef.tools,
1238
- collection: objectDef.collection ?? pluralizeCollection(simpleClassName),
1303
+ collection: config.collection ?? objectDef.collection ?? pluralizeCollection(simpleClassName),
1239
1304
  packageName,
1240
1305
  sourceFilePath: objectDef.filePath,
1241
1306
  replacedQualifiedNames: [...replacedQualifiedNames],