@objectstack/driver-sql 10.2.0 → 10.3.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.
package/dist/index.mjs CHANGED
@@ -1047,6 +1047,37 @@ var SqlDriver = class {
1047
1047
  this.assertSchemaMutable("dropTable");
1048
1048
  await this.knex.schema.dropTableIfExists(object);
1049
1049
  }
1050
+ /**
1051
+ * Resolve the per-table tenant-isolation column for a schema, honoring an
1052
+ * explicit tenancy opt-out. Single source of truth for both {@link initObjects}
1053
+ * and {@link registerExternalObject} (they previously inlined this logic and
1054
+ * drifted).
1055
+ *
1056
+ * Precedence:
1057
+ * 1. `tenancy.enabled === false` → `null` (NO driver-level org scope), even
1058
+ * when the object carries an `organization_id` column. Platform-global
1059
+ * objects (e.g. `sys_license`) keep an optional, often-NULL org FK but must
1060
+ * NOT be tenant-scoped: otherwise an authenticated caller's active-org
1061
+ * `DriverOptions.tenantId` injects `WHERE organization_id = <org>` and every
1062
+ * NULL-org / cross-org row silently disappears (the platform admin then
1063
+ * reads zero licenses while an unscoped/anonymous read still sees them).
1064
+ * The declarative branch below already respected `enabled !== false`; the
1065
+ * implicit `organization_id` fallback did not — this closes that gap.
1066
+ * 2. Declared `tenancy.tenantField` (when that field exists on the object).
1067
+ * 3. Implicit `organization_id` column detection (legacy objects whose
1068
+ * multi-tenant column was injected by the kernel without a spec migration).
1069
+ */
1070
+ computeTenantField(schema) {
1071
+ const tenancyDecl = schema?.tenancy;
1072
+ if (tenancyDecl?.enabled === false) return null;
1073
+ const fields = schema?.fields;
1074
+ if (tenancyDecl?.tenantField) {
1075
+ const declared = String(tenancyDecl.tenantField);
1076
+ if (fields && Object.prototype.hasOwnProperty.call(fields, declared)) return declared;
1077
+ }
1078
+ if (fields && Object.prototype.hasOwnProperty.call(fields, "organization_id")) return "organization_id";
1079
+ return null;
1080
+ }
1050
1081
  /**
1051
1082
  * Batch-initialise tables from an array of object definitions.
1052
1083
  */
@@ -1098,18 +1129,7 @@ var SqlDriver = class {
1098
1129
  const dateCols = [];
1099
1130
  const datetimeCols = [];
1100
1131
  const autoNumberCols = [];
1101
- const tenancyDecl = schema?.tenancy;
1102
- let tenantField = null;
1103
- if (tenancyDecl && tenancyDecl.enabled !== false && tenancyDecl.tenantField) {
1104
- const declared = String(tenancyDecl.tenantField);
1105
- if (schema.fields && Object.prototype.hasOwnProperty.call(schema.fields, declared)) {
1106
- tenantField = declared;
1107
- }
1108
- }
1109
- if (!tenantField) {
1110
- const hasOrgField = !!(schema.fields && Object.prototype.hasOwnProperty.call(schema.fields, "organization_id"));
1111
- tenantField = hasOrgField ? "organization_id" : null;
1112
- }
1132
+ const tenantField = this.computeTenantField(schema);
1113
1133
  if (schema.fields) {
1114
1134
  for (const [name, field] of Object.entries(schema.fields)) {
1115
1135
  const type = field.type || "string";
@@ -1147,18 +1167,7 @@ var SqlDriver = class {
1147
1167
  const booleanCols = [];
1148
1168
  const numericCols = [];
1149
1169
  const autoNumberCols = [];
1150
- const tenancyDecl = obj?.tenancy;
1151
- let tenantField = null;
1152
- if (tenancyDecl && tenancyDecl.enabled !== false && tenancyDecl.tenantField) {
1153
- const declared = String(tenancyDecl.tenantField);
1154
- if (obj.fields && Object.prototype.hasOwnProperty.call(obj.fields, declared)) {
1155
- tenantField = declared;
1156
- }
1157
- }
1158
- if (!tenantField) {
1159
- const hasOrgField = !!(obj.fields && Object.prototype.hasOwnProperty.call(obj.fields, "organization_id"));
1160
- tenantField = hasOrgField ? "organization_id" : null;
1161
- }
1170
+ const tenantField = this.computeTenantField(obj);
1162
1171
  if (obj.fields) {
1163
1172
  for (const [name, field] of Object.entries(obj.fields)) {
1164
1173
  const type = field.type || "string";