@getstrata/core 2.2.21 → 2.2.22

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @getstrata/core changelog
2
2
 
3
+ ## 2.2.22
4
+
5
+ Preserve caller auth, credential sources, request metadata and application async stores through cold/queued native transaction callbacks. Serialize Postgres privilege grants with full provisioning using atomic database-scoped batches, retaining delegated-admin permissions and rollback/retry safety. Add real constrained-pool JSON/HTML bearer/session-CSRF and concurrent grant/atomicity regressions; no automatic workers, auth bypass or production runtime provisioning.
6
+
3
7
  ## 2.2.21
4
8
 
5
9
  Make registered queue/outbox workers discoverable in CLI help and generated startup guidance. Announce polling after boot and when it stops without claiming dependency health, printing secrets, or starting workers automatically. Preserve explicit process ownership, delivery semantics and graceful lifecycle; cover idle, boot/runtime/cleanup failures and real SIGTERM draining.
@@ -221,6 +221,7 @@ var init_tenancyConfig = __esm(() => {
221
221
 
222
222
  // ../../src/core/tenant/tenantDatabaseScope.ts
223
223
  import { getDefaultDatabasePool } from "@getstrata/core/database/defaultConnection";
224
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
224
225
  async function applyTenantContextToTransaction(transaction, tenantId) {
225
226
  await transaction.unsafe(`SELECT set_config('app.tenant_id', $1, true)`, [String(tenantId)]);
226
227
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, ["false"]);
@@ -243,12 +244,12 @@ async function runWithTenantDatabase(tenant, callback) {
243
244
  throw new Error("RLS tenant scope requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
244
245
  }
245
246
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
246
- return await begin.bind(pool)(async (transaction) => {
247
+ return await begin.bind(pool)(AsyncLocalStorage2.bind(async (transaction) => {
247
248
  await applyTenantContextToTransaction(transaction, tenant.id);
248
249
  return await runWithDatabaseConnection(transaction, async () => {
249
250
  return await runWithTransactionScope(async () => commitOrRollbackScope(await runWithTenant(tenant, callback)));
250
251
  });
251
- });
252
+ }));
252
253
  }));
253
254
  }
254
255
  function isInsideTenantDatabaseScope(tenantId = currentTenant()?.id) {
@@ -717,6 +718,7 @@ var init_repositoryConnection = __esm(() => {
717
718
  });
718
719
 
719
720
  // ../../src/core/database/transaction.ts
721
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
720
722
  async function runInSavepoint(connection, operation) {
721
723
  const inherited = transactionFrame.getStore();
722
724
  let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
@@ -776,9 +778,9 @@ async function runInTransaction(operation, options = {}) {
776
778
  signal?.throwIfAborted();
777
779
  if (!supportsTransactions(connection))
778
780
  throw new Error("Reserved database connection does not support transactions.");
779
- return await connection.begin(async (transaction) => {
781
+ return await connection.begin(AsyncLocalStorage3.bind(async (transaction) => {
780
782
  return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(createDatabaseConnection(transaction))))));
781
- });
783
+ }));
782
784
  } finally {
783
785
  await reserved?.release();
784
786
  }
@@ -800,6 +802,7 @@ var init_transaction = __esm(() => {
800
802
 
801
803
  // ../../src/core/tenant/databaseTenantContext.ts
802
804
  import { getDefaultDatabasePool as getDefaultDatabasePool3 } from "@getstrata/core/database/defaultConnection";
805
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
803
806
  async function applyBypassToTransaction(transaction, bypass) {
804
807
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, [
805
808
  bypass ? "true" : "false"
@@ -851,10 +854,10 @@ async function runWithScopedTenantTransaction(apply, callback) {
851
854
  throw new Error("RLS migration bypass requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
852
855
  }
853
856
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
854
- return await begin.bind(pool)(async (transaction) => {
857
+ return await begin.bind(pool)(AsyncLocalStorage4.bind(async (transaction) => {
855
858
  await apply(transaction);
856
859
  return await runWithDatabaseConnection(transaction, () => runWithTransactionScope(async () => commitOrRollbackScope(await callback())));
857
- });
860
+ }));
858
861
  }));
859
862
  }
860
863
  async function runWithMigrationBypass(callback) {
@@ -673,6 +673,7 @@ var init_repositoryConnection = __esm(() => {
673
673
  });
674
674
 
675
675
  // ../../src/core/database/transaction.ts
676
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
676
677
  async function runInSavepoint(connection, operation) {
677
678
  const inherited = transactionFrame.getStore();
678
679
  let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
@@ -732,9 +733,9 @@ async function runInTransaction(operation, options = {}) {
732
733
  signal?.throwIfAborted();
733
734
  if (!supportsTransactions(connection))
734
735
  throw new Error("Reserved database connection does not support transactions.");
735
- return await connection.begin(async (transaction) => {
736
+ return await connection.begin(AsyncLocalStorage2.bind(async (transaction) => {
736
737
  return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(createDatabaseConnection(transaction))))));
737
- });
738
+ }));
738
739
  } finally {
739
740
  await reserved?.release();
740
741
  }
@@ -756,6 +757,7 @@ var init_transaction = __esm(() => {
756
757
 
757
758
  // ../../src/core/tenant/databaseTenantContext.ts
758
759
  import { getDefaultDatabasePool as getDefaultDatabasePool2 } from "@getstrata/core/database/defaultConnection";
760
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
759
761
  async function applyBypassToTransaction(transaction, bypass) {
760
762
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, [
761
763
  bypass ? "true" : "false"
@@ -807,10 +809,10 @@ async function runWithScopedTenantTransaction(apply, callback) {
807
809
  throw new Error("RLS migration bypass requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
808
810
  }
809
811
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
810
- return await begin.bind(pool)(async (transaction) => {
812
+ return await begin.bind(pool)(AsyncLocalStorage3.bind(async (transaction) => {
811
813
  await apply(transaction);
812
814
  return await runWithDatabaseConnection(transaction, () => runWithTransactionScope(async () => commitOrRollbackScope(await callback())));
813
- });
815
+ }));
814
816
  }));
815
817
  }
816
818
  async function runWithMigrationBypass(callback) {
@@ -830,6 +832,7 @@ var init_databaseTenantContext = __esm(() => {
830
832
 
831
833
  // ../../src/core/tenant/tenantDatabaseScope.ts
832
834
  import { getDefaultDatabasePool as getDefaultDatabasePool3 } from "@getstrata/core/database/defaultConnection";
835
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
833
836
  async function applyTenantContextToTransaction(transaction, tenantId) {
834
837
  await transaction.unsafe(`SELECT set_config('app.tenant_id', $1, true)`, [String(tenantId)]);
835
838
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, ["false"]);
@@ -852,12 +855,12 @@ async function runWithTenantDatabase(tenant, callback) {
852
855
  throw new Error("RLS tenant scope requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
853
856
  }
854
857
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
855
- return await begin.bind(pool)(async (transaction) => {
858
+ return await begin.bind(pool)(AsyncLocalStorage4.bind(async (transaction) => {
856
859
  await applyTenantContextToTransaction(transaction, tenant.id);
857
860
  return await runWithDatabaseConnection(transaction, async () => {
858
861
  return await runWithTransactionScope(async () => commitOrRollbackScope(await runWithTenant(tenant, callback)));
859
862
  });
860
- });
863
+ }));
861
864
  }));
862
865
  }
863
866
  function isInsideTenantDatabaseScope(tenantId = currentTenant()?.id) {
@@ -221,6 +221,7 @@ var init_tenancyConfig = __esm(() => {
221
221
 
222
222
  // ../../src/core/tenant/tenantDatabaseScope.ts
223
223
  import { getDefaultDatabasePool } from "@getstrata/core/database/defaultConnection";
224
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
224
225
  async function applyTenantContextToTransaction(transaction, tenantId) {
225
226
  await transaction.unsafe(`SELECT set_config('app.tenant_id', $1, true)`, [String(tenantId)]);
226
227
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, ["false"]);
@@ -243,12 +244,12 @@ async function runWithTenantDatabase(tenant, callback) {
243
244
  throw new Error("RLS tenant scope requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
244
245
  }
245
246
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
246
- return await begin.bind(pool)(async (transaction) => {
247
+ return await begin.bind(pool)(AsyncLocalStorage2.bind(async (transaction) => {
247
248
  await applyTenantContextToTransaction(transaction, tenant.id);
248
249
  return await runWithDatabaseConnection(transaction, async () => {
249
250
  return await runWithTransactionScope(async () => commitOrRollbackScope(await runWithTenant(tenant, callback)));
250
251
  });
251
- });
252
+ }));
252
253
  }));
253
254
  }
254
255
  function isInsideTenantDatabaseScope(tenantId = currentTenant()?.id) {
@@ -717,6 +718,7 @@ var init_repositoryConnection = __esm(() => {
717
718
  });
718
719
 
719
720
  // ../../src/core/database/transaction.ts
721
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
720
722
  async function runInSavepoint(connection, operation) {
721
723
  const inherited = transactionFrame.getStore();
722
724
  let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
@@ -776,9 +778,9 @@ async function runInTransaction(operation, options = {}) {
776
778
  signal?.throwIfAborted();
777
779
  if (!supportsTransactions(connection))
778
780
  throw new Error("Reserved database connection does not support transactions.");
779
- return await connection.begin(async (transaction) => {
781
+ return await connection.begin(AsyncLocalStorage3.bind(async (transaction) => {
780
782
  return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(createDatabaseConnection(transaction))))));
781
- });
783
+ }));
782
784
  } finally {
783
785
  await reserved?.release();
784
786
  }
@@ -800,6 +802,7 @@ var init_transaction = __esm(() => {
800
802
 
801
803
  // ../../src/core/tenant/databaseTenantContext.ts
802
804
  import { getDefaultDatabasePool as getDefaultDatabasePool3 } from "@getstrata/core/database/defaultConnection";
805
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
803
806
  async function applyBypassToTransaction(transaction, bypass) {
804
807
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, [
805
808
  bypass ? "true" : "false"
@@ -851,10 +854,10 @@ async function runWithScopedTenantTransaction(apply, callback) {
851
854
  throw new Error("RLS migration bypass requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
852
855
  }
853
856
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
854
- return await begin.bind(pool)(async (transaction) => {
857
+ return await begin.bind(pool)(AsyncLocalStorage4.bind(async (transaction) => {
855
858
  await apply(transaction);
856
859
  return await runWithDatabaseConnection(transaction, () => runWithTransactionScope(async () => commitOrRollbackScope(await callback())));
857
- });
860
+ }));
858
861
  }));
859
862
  }
860
863
  async function runWithMigrationBypass(callback) {
@@ -531,6 +531,7 @@ var init_tenancyConfig = __esm(() => {
531
531
 
532
532
  // ../../src/core/tenant/databaseTenantContext.ts
533
533
  import { getDefaultDatabasePool as getDefaultDatabasePool2 } from "@getstrata/core/database/defaultConnection";
534
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
534
535
  async function applyBypassToTransaction(transaction, bypass) {
535
536
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, [
536
537
  bypass ? "true" : "false"
@@ -582,10 +583,10 @@ async function runWithScopedTenantTransaction(apply, callback) {
582
583
  throw new Error("RLS migration bypass requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
583
584
  }
584
585
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
585
- return await begin.bind(pool)(async (transaction) => {
586
+ return await begin.bind(pool)(AsyncLocalStorage2.bind(async (transaction) => {
586
587
  await apply(transaction);
587
588
  return await runWithDatabaseConnection(transaction, () => runWithTransactionScope(async () => commitOrRollbackScope(await callback())));
588
- });
589
+ }));
589
590
  }));
590
591
  }
591
592
  async function runWithMigrationBypass(callback) {
@@ -605,6 +606,7 @@ var init_databaseTenantContext = __esm(() => {
605
606
 
606
607
  // ../../src/core/tenant/tenantDatabaseScope.ts
607
608
  import { getDefaultDatabasePool as getDefaultDatabasePool3 } from "@getstrata/core/database/defaultConnection";
609
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
608
610
  async function applyTenantContextToTransaction(transaction, tenantId) {
609
611
  await transaction.unsafe(`SELECT set_config('app.tenant_id', $1, true)`, [String(tenantId)]);
610
612
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, ["false"]);
@@ -627,12 +629,12 @@ async function runWithTenantDatabase(tenant, callback) {
627
629
  throw new Error("RLS tenant scope requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
628
630
  }
629
631
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
630
- return await begin.bind(pool)(async (transaction) => {
632
+ return await begin.bind(pool)(AsyncLocalStorage3.bind(async (transaction) => {
631
633
  await applyTenantContextToTransaction(transaction, tenant.id);
632
634
  return await runWithDatabaseConnection(transaction, async () => {
633
635
  return await runWithTransactionScope(async () => commitOrRollbackScope(await runWithTenant(tenant, callback)));
634
636
  });
635
- });
637
+ }));
636
638
  }));
637
639
  }
638
640
  function isInsideTenantDatabaseScope(tenantId = currentTenant()?.id) {
@@ -791,6 +793,7 @@ function createDatabaseConnection(source) {
791
793
  var init_connection = () => {};
792
794
 
793
795
  // ../../src/core/database/transaction.ts
796
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
794
797
  async function runInSavepoint(connection, operation) {
795
798
  const inherited = transactionFrame.getStore();
796
799
  let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
@@ -850,9 +853,9 @@ async function runInTransaction(operation, options = {}) {
850
853
  signal?.throwIfAborted();
851
854
  if (!supportsTransactions(connection))
852
855
  throw new Error("Reserved database connection does not support transactions.");
853
- return await connection.begin(async (transaction) => {
856
+ return await connection.begin(AsyncLocalStorage4.bind(async (transaction) => {
854
857
  return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(createDatabaseConnection(transaction))))));
855
- });
858
+ }));
856
859
  } finally {
857
860
  await reserved?.release();
858
861
  }
@@ -221,6 +221,7 @@ var init_tenancyConfig = __esm(() => {
221
221
 
222
222
  // ../../src/core/tenant/tenantDatabaseScope.ts
223
223
  import { getDefaultDatabasePool } from "@getstrata/core/database/defaultConnection";
224
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
224
225
  async function applyTenantContextToTransaction(transaction, tenantId) {
225
226
  await transaction.unsafe(`SELECT set_config('app.tenant_id', $1, true)`, [String(tenantId)]);
226
227
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, ["false"]);
@@ -243,12 +244,12 @@ async function runWithTenantDatabase(tenant, callback) {
243
244
  throw new Error("RLS tenant scope requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
244
245
  }
245
246
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
246
- return await begin.bind(pool)(async (transaction) => {
247
+ return await begin.bind(pool)(AsyncLocalStorage2.bind(async (transaction) => {
247
248
  await applyTenantContextToTransaction(transaction, tenant.id);
248
249
  return await runWithDatabaseConnection(transaction, async () => {
249
250
  return await runWithTransactionScope(async () => commitOrRollbackScope(await runWithTenant(tenant, callback)));
250
251
  });
251
- });
252
+ }));
252
253
  }));
253
254
  }
254
255
  function isInsideTenantDatabaseScope(tenantId = currentTenant()?.id) {
@@ -717,6 +718,7 @@ var init_repositoryConnection = __esm(() => {
717
718
  });
718
719
 
719
720
  // ../../src/core/database/transaction.ts
721
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
720
722
  async function runInSavepoint(connection, operation) {
721
723
  const inherited = transactionFrame.getStore();
722
724
  let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
@@ -776,9 +778,9 @@ async function runInTransaction(operation, options = {}) {
776
778
  signal?.throwIfAborted();
777
779
  if (!supportsTransactions(connection))
778
780
  throw new Error("Reserved database connection does not support transactions.");
779
- return await connection.begin(async (transaction) => {
781
+ return await connection.begin(AsyncLocalStorage3.bind(async (transaction) => {
780
782
  return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(createDatabaseConnection(transaction))))));
781
- });
783
+ }));
782
784
  } finally {
783
785
  await reserved?.release();
784
786
  }
@@ -800,6 +802,7 @@ var init_transaction = __esm(() => {
800
802
 
801
803
  // ../../src/core/tenant/databaseTenantContext.ts
802
804
  import { getDefaultDatabasePool as getDefaultDatabasePool3 } from "@getstrata/core/database/defaultConnection";
805
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
803
806
  async function applyBypassToTransaction(transaction, bypass) {
804
807
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, [
805
808
  bypass ? "true" : "false"
@@ -851,10 +854,10 @@ async function runWithScopedTenantTransaction(apply, callback) {
851
854
  throw new Error("RLS migration bypass requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
852
855
  }
853
856
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
854
- return await begin.bind(pool)(async (transaction) => {
857
+ return await begin.bind(pool)(AsyncLocalStorage4.bind(async (transaction) => {
855
858
  await apply(transaction);
856
859
  return await runWithDatabaseConnection(transaction, () => runWithTransactionScope(async () => commitOrRollbackScope(await callback())));
857
- });
860
+ }));
858
861
  }));
859
862
  }
860
863
  async function runWithMigrationBypass(callback) {
@@ -191,15 +191,11 @@ BEGIN
191
191
  END
192
192
  $$`;
193
193
  }
194
- function postgresAppRoleSql(options) {
194
+ var POSTGRES_PRIVILEGE_LOCK_SQL = "SELECT pg_advisory_xact_lock(hashtext('strata:postgres-privileges'), hashtext(current_database()))";
195
+ function postgresAppRolePrivilegeSql(options) {
195
196
  const database = assertSafeSqlIdentifier(options.database, "database name");
196
197
  const role = assertSafeSqlIdentifier(options.role ?? POSTGRES_APP_ROLE, "role name");
197
- return `-- Application login role. FORCE RLS applies because this role is NOSUPERUSER and NOBYPASSRLS.
198
- -- Superuser remains for CREATE ROLE / CREATE DATABASE / GRANT / migrate / migrate:fresh DROP.
199
- -- This script is repeatable on an already-existing volume (not only docker-entrypoint-initdb.d).
200
- ${postgresAppRoleCreateSql(options)};
201
-
202
- GRANT CONNECT ON DATABASE ${database} TO ${role};
198
+ return `GRANT CONNECT ON DATABASE ${database} TO ${role};
203
199
  GRANT USAGE, CREATE ON SCHEMA public TO ${role};
204
200
  GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ${role};
205
201
  GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO ${role};
@@ -209,17 +205,21 @@ ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO ${role};
209
205
  ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT EXECUTE ON FUNCTIONS TO ${role};
210
206
  `;
211
207
  }
208
+ function postgresAppRoleSql(options) {
209
+ const privileges = postgresAppRolePrivilegeSql(options);
210
+ return `-- Application login role. FORCE RLS applies because this role is NOSUPERUSER and NOBYPASSRLS.
211
+ -- Superuser remains for CREATE ROLE / CREATE DATABASE / GRANT / migrate / migrate:fresh DROP.
212
+ -- This script is repeatable on an already-existing volume (not only docker-entrypoint-initdb.d).
213
+ ${POSTGRES_PRIVILEGE_LOCK_SQL};
214
+ ${postgresAppRoleCreateSql(options)};
215
+
216
+ ${privileges}
217
+ `;
218
+ }
212
219
  async function grantPostgresAppRolePrivileges(sql, options) {
213
- const database = assertSafeSqlIdentifier(options.database, "database name");
214
- const role = assertSafeSqlIdentifier(options.role ?? POSTGRES_APP_ROLE, "role name");
215
- await sql.unsafe(`GRANT CONNECT ON DATABASE ${database} TO ${role}`);
216
- await sql.unsafe(`GRANT USAGE, CREATE ON SCHEMA public TO ${role}`);
217
- await sql.unsafe(`GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ${role}`);
218
- await sql.unsafe(`GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO ${role}`);
219
- await sql.unsafe(`GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO ${role}`);
220
- await sql.unsafe(`ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO ${role}`);
221
- await sql.unsafe(`ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO ${role}`);
222
- await sql.unsafe(`ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT EXECUTE ON FUNCTIONS TO ${role}`);
220
+ const privileges = postgresAppRolePrivilegeSql(options);
221
+ await sql.unsafe(`${POSTGRES_PRIVILEGE_LOCK_SQL};
222
+ ${privileges}`);
223
223
  }
224
224
  async function ensurePostgresAppRole(sql, options) {
225
225
  await sql.unsafe(postgresAppRoleSql(options));
@@ -651,6 +651,7 @@ var init_repositoryConnection = __esm(() => {
651
651
  });
652
652
 
653
653
  // ../../src/core/database/transaction.ts
654
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
654
655
  async function runInSavepoint(connection, operation) {
655
656
  const inherited = transactionFrame.getStore();
656
657
  let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
@@ -710,9 +711,9 @@ async function runInTransaction(operation, options = {}) {
710
711
  signal?.throwIfAborted();
711
712
  if (!supportsTransactions(connection))
712
713
  throw new Error("Reserved database connection does not support transactions.");
713
- return await connection.begin(async (transaction) => {
714
+ return await connection.begin(AsyncLocalStorage2.bind(async (transaction) => {
714
715
  return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(createDatabaseConnection(transaction))))));
715
- });
716
+ }));
716
717
  } finally {
717
718
  await reserved?.release();
718
719
  }
@@ -756,6 +757,7 @@ var init_tenancyConfig = __esm(() => {
756
757
 
757
758
  // ../../src/core/tenant/databaseTenantContext.ts
758
759
  import { getDefaultDatabasePool as getDefaultDatabasePool2 } from "@getstrata/core/database/defaultConnection";
760
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
759
761
  async function applyBypassToTransaction(transaction, bypass) {
760
762
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, [
761
763
  bypass ? "true" : "false"
@@ -807,10 +809,10 @@ async function runWithScopedTenantTransaction(apply, callback) {
807
809
  throw new Error("RLS migration bypass requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
808
810
  }
809
811
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
810
- return await begin.bind(pool)(async (transaction) => {
812
+ return await begin.bind(pool)(AsyncLocalStorage3.bind(async (transaction) => {
811
813
  await apply(transaction);
812
814
  return await runWithDatabaseConnection(transaction, () => runWithTransactionScope(async () => commitOrRollbackScope(await callback())));
813
- });
815
+ }));
814
816
  }));
815
817
  }
816
818
  async function runWithMigrationBypass(callback) {
@@ -830,6 +832,7 @@ var init_databaseTenantContext = __esm(() => {
830
832
 
831
833
  // ../../src/core/tenant/tenantDatabaseScope.ts
832
834
  import { getDefaultDatabasePool as getDefaultDatabasePool3 } from "@getstrata/core/database/defaultConnection";
835
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
833
836
  async function applyTenantContextToTransaction(transaction, tenantId) {
834
837
  await transaction.unsafe(`SELECT set_config('app.tenant_id', $1, true)`, [String(tenantId)]);
835
838
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, ["false"]);
@@ -852,12 +855,12 @@ async function runWithTenantDatabase(tenant, callback) {
852
855
  throw new Error("RLS tenant scope requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
853
856
  }
854
857
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
855
- return await begin.bind(pool)(async (transaction) => {
858
+ return await begin.bind(pool)(AsyncLocalStorage4.bind(async (transaction) => {
856
859
  await applyTenantContextToTransaction(transaction, tenant.id);
857
860
  return await runWithDatabaseConnection(transaction, async () => {
858
861
  return await runWithTransactionScope(async () => commitOrRollbackScope(await runWithTenant(tenant, callback)));
859
862
  });
860
- });
863
+ }));
861
864
  }));
862
865
  }
863
866
  function isInsideTenantDatabaseScope(tenantId = currentTenant()?.id) {
package/dist/index.js CHANGED
@@ -807,6 +807,7 @@ function createDatabaseConnection(source) {
807
807
  var init_connection = () => {};
808
808
 
809
809
  // ../../src/core/database/transaction.ts
810
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
810
811
  async function runInSavepoint(connection, operation) {
811
812
  const inherited = transactionFrame.getStore();
812
813
  let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
@@ -866,9 +867,9 @@ async function runInTransaction(operation, options = {}) {
866
867
  signal?.throwIfAborted();
867
868
  if (!supportsTransactions(connection))
868
869
  throw new Error("Reserved database connection does not support transactions.");
869
- return await connection.begin(async (transaction) => {
870
+ return await connection.begin(AsyncLocalStorage2.bind(async (transaction) => {
870
871
  return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(createDatabaseConnection(transaction))))));
871
- });
872
+ }));
872
873
  } finally {
873
874
  await reserved?.release();
874
875
  }
@@ -889,6 +890,7 @@ var init_transaction = __esm(() => {
889
890
  });
890
891
 
891
892
  // ../../src/core/tenant/databaseTenantContext.ts
893
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
892
894
  async function applyBypassToTransaction(transaction, bypass) {
893
895
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, [
894
896
  bypass ? "true" : "false"
@@ -940,10 +942,10 @@ async function runWithScopedTenantTransaction(apply, callback) {
940
942
  throw new Error("RLS migration bypass requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
941
943
  }
942
944
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
943
- return await begin.bind(pool)(async (transaction) => {
945
+ return await begin.bind(pool)(AsyncLocalStorage3.bind(async (transaction) => {
944
946
  await apply(transaction);
945
947
  return await runWithDatabaseConnection(transaction, () => runWithTransactionScope(async () => commitOrRollbackScope(await callback())));
946
- });
948
+ }));
947
949
  }));
948
950
  }
949
951
  async function runWithMigrationBypass(callback) {
@@ -963,6 +965,7 @@ var init_databaseTenantContext = __esm(() => {
963
965
  });
964
966
 
965
967
  // ../../src/core/tenant/tenantDatabaseScope.ts
968
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
966
969
  async function applyTenantContextToTransaction(transaction, tenantId) {
967
970
  await transaction.unsafe(`SELECT set_config('app.tenant_id', $1, true)`, [String(tenantId)]);
968
971
  await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, ["false"]);
@@ -985,12 +988,12 @@ async function runWithTenantDatabase(tenant, callback) {
985
988
  throw new Error("RLS tenant scope requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
986
989
  }
987
990
  return await settleTransaction(() => runWithDeferredModelEvents(async () => {
988
- return await begin.bind(pool)(async (transaction) => {
991
+ return await begin.bind(pool)(AsyncLocalStorage4.bind(async (transaction) => {
989
992
  await applyTenantContextToTransaction(transaction, tenant.id);
990
993
  return await runWithDatabaseConnection(transaction, async () => {
991
994
  return await runWithTransactionScope(async () => commitOrRollbackScope(await runWithTenant(tenant, callback)));
992
995
  });
993
- });
996
+ }));
994
997
  }));
995
998
  }
996
999
  function isInsideTenantDatabaseScope(tenantId = currentTenant()?.id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getstrata/core",
3
- "version": "2.2.21",
3
+ "version": "2.2.22",
4
4
  "description": "Strata Bun framework public API",
5
5
  "type": "module",
6
6
  "license": "MIT",