@getstrata/core 1.0.3 → 1.0.5

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 (51) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +1 -1
  3. package/dist/core/runtime/appEnv.d.ts +16 -2
  4. package/dist/core/runtime/appKeyPrefix.d.ts +8 -1
  5. package/dist/entries/audit/exportAuditLogs.js +83 -18
  6. package/dist/entries/audit/siemFormatter.js +32 -3
  7. package/dist/entries/auth/intendedUrlCookie.js +33 -4
  8. package/dist/entries/auth/jwt.js +36 -4
  9. package/dist/entries/auth/jwtGuard.js +36 -4
  10. package/dist/entries/auth/oauth/providers.js +32 -3
  11. package/dist/entries/auth/oauth/samlProvider.js +32 -3
  12. package/dist/entries/auth/passwordConfirmCookie.js +35 -6
  13. package/dist/entries/auth/sessionCookie.js +35 -6
  14. package/dist/entries/auth/sessionGuard.js +35 -6
  15. package/dist/entries/auth/tokenHash.js +33 -4
  16. package/dist/entries/cache/createCacheStore.js +32 -3
  17. package/dist/entries/database/mysqlConnection.js +1 -132
  18. package/dist/entries/facades.js +32 -3
  19. package/dist/entries/http/corsMiddleware.js +16 -1
  20. package/dist/entries/http/csrfMiddleware.js +34 -5
  21. package/dist/entries/http/csrfToken.js +34 -5
  22. package/dist/entries/http/flashMiddleware.js +33 -4
  23. package/dist/entries/http/flashSession.js +33 -4
  24. package/dist/entries/http/loginThrottleMiddleware.js +1 -373
  25. package/dist/entries/http/memoryThrottleMiddleware.js +32 -58
  26. package/dist/entries/http/response.js +16 -56
  27. package/dist/entries/http/scimThrottleMiddleware.js +32 -3
  28. package/dist/entries/http/securityHeadersMiddleware.js +32 -3
  29. package/dist/entries/http/signedUrl.js +33 -4
  30. package/dist/entries/http/throttleMiddleware.js +32 -58
  31. package/dist/entries/http/webErrorResponse.js +1 -401
  32. package/dist/entries/jobs/exportAuditLogsJob.js +83 -18
  33. package/dist/entries/lifecycle/gracefulShutdown.js +1 -50
  34. package/dist/entries/mail/mailer.js +32 -3
  35. package/dist/entries/openapi/generator.js +32 -3
  36. package/dist/entries/queue/createAppQueue.js +32 -3
  37. package/dist/entries/queue/publicQueue.js +32 -3
  38. package/dist/entries/queue/queueMetrics.js +32 -3
  39. package/dist/entries/queue/redisQueue.js +32 -3
  40. package/dist/entries/runtime/appEnv.js +18 -1
  41. package/dist/entries/runtime/appKeyPrefix.js +1 -70
  42. package/dist/entries/security/oauthState.js +33 -4
  43. package/dist/entries/security/safeFetch.js +32 -9
  44. package/dist/entries/security/safeUrl.js +1 -105
  45. package/dist/entries/security/totp.js +32 -3
  46. package/dist/entries/tenant/databaseTenantContext.js +48 -6
  47. package/dist/entries/tracing/tracingMiddleware.js +32 -3
  48. package/dist/entries/view.js +1 -778
  49. package/dist/framework/public-api.d.ts +28 -19
  50. package/dist/index.js +448 -53
  51. package/package.json +2 -2
@@ -1,6 +1,32 @@
1
1
  // @bun
2
2
  // ../../src/core/tenant/databaseTenantContext.ts
3
- import { repositoryConnection as db } from "@getstrata/core/database/repositoryConnection";
3
+ import { getDefaultDatabasePool } from "@getstrata/core/database/defaultConnection";
4
+
5
+ // ../../src/core/runtime/asyncContextStore.ts
6
+ import { AsyncLocalStorage } from "async_hooks";
7
+ function createAsyncContextStore(key) {
8
+ const symbol = Symbol.for(key);
9
+ const globalRecord = globalThis;
10
+ const existing = globalRecord[symbol];
11
+ if (existing) {
12
+ return existing;
13
+ }
14
+ const store = new AsyncLocalStorage;
15
+ globalRecord[symbol] = store;
16
+ return store;
17
+ }
18
+
19
+ // ../../src/core/database/connectionContext.ts
20
+ var activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
21
+ function runWithDatabaseConnection(connection, callback) {
22
+ return activeConnection.run(connection, callback);
23
+ }
24
+ function getActiveDatabaseConnection(fallback) {
25
+ return activeConnection.getStore() ?? fallback;
26
+ }
27
+ function hasActiveDatabaseConnection() {
28
+ return activeConnection.getStore() !== undefined;
29
+ }
4
30
 
5
31
  // ../../src/core/tenant/tenancyConfig.ts
6
32
  var TENANCY_DRIVERS = ["rls", "column", "none"];
@@ -22,16 +48,32 @@ function isRlsTenancy(env = process.env) {
22
48
  }
23
49
 
24
50
  // ../../src/core/tenant/databaseTenantContext.ts
51
+ async function applyBypassToTransaction(transaction, bypass) {
52
+ await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, [
53
+ bypass ? "true" : "false"
54
+ ]);
55
+ }
25
56
  async function runWithMigrationBypass(callback) {
26
57
  if (!isRlsTenancy()) {
27
58
  return await callback();
28
59
  }
29
- await db`SELECT set_config('app.bypass_rls', 'true', false)`;
30
- try {
31
- return await callback();
32
- } finally {
33
- await db`SELECT set_config('app.bypass_rls', 'false', false)`;
60
+ if (hasActiveDatabaseConnection()) {
61
+ const activeConnection = getActiveDatabaseConnection(getDefaultDatabasePool());
62
+ await applyBypassToTransaction(activeConnection, true);
63
+ try {
64
+ return await callback();
65
+ } finally {
66
+ await applyBypassToTransaction(activeConnection, false);
67
+ }
68
+ }
69
+ const pool = getDefaultDatabasePool();
70
+ if (typeof pool.begin !== "function") {
71
+ throw new Error("RLS migration bypass requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
34
72
  }
73
+ return await pool.begin(async (transaction) => {
74
+ await applyBypassToTransaction(transaction, true);
75
+ return await runWithDatabaseConnection(transaction, callback);
76
+ });
35
77
  }
36
78
  export {
37
79
  runWithMigrationBypass
@@ -2,6 +2,26 @@
2
2
  // ../../src/core/tracing/otel.ts
3
3
  import { randomBytes } from "crypto";
4
4
 
5
+ // ../../src/core/runtime/appEnv.ts
6
+ var NON_PRODUCTION_APP_ENVS = new Set(["local", "development", "dev", "test", "testing", "ci"]);
7
+ function normalizeEnvValue(value) {
8
+ return (value ?? "").trim().toLowerCase();
9
+ }
10
+ function isProductionEnv(env = process.env) {
11
+ const appEnv = normalizeEnvValue(env.APP_ENV);
12
+ const nodeEnv = normalizeEnvValue(env.NODE_ENV);
13
+ if (appEnv === "production" || nodeEnv === "production") {
14
+ return true;
15
+ }
16
+ if (appEnv === "") {
17
+ return false;
18
+ }
19
+ return !NON_PRODUCTION_APP_ENVS.has(appEnv);
20
+ }
21
+ function envFlagEnabled(value) {
22
+ return value === "true";
23
+ }
24
+
5
25
  // ../../src/core/runtime/appKeyPrefix.ts
6
26
  function appKeyPrefix() {
7
27
  return process.env.APP_KEY_PREFIX?.trim() || "strata";
@@ -12,6 +32,18 @@ function appCookieName(kind) {
12
32
  function appDevSecret(kind) {
13
33
  return `${appKeyPrefix()}-dev-${kind}`;
14
34
  }
35
+ function requireConfiguredSecret(names, devKind, env = process.env) {
36
+ for (const name of names) {
37
+ const value = env[name]?.trim();
38
+ if (value) {
39
+ return value;
40
+ }
41
+ }
42
+ if (isProductionEnv(env)) {
43
+ throw new Error(`${names[0]} must be set outside development. Do not derive secrets from the app name.`);
44
+ }
45
+ return appDevSecret(devKind);
46
+ }
15
47
  function namespacedRedisKey(kind) {
16
48
  return `${appKeyPrefix()}:${kind}`;
17
49
  }
@@ -29,9 +61,6 @@ function appUserAgent() {
29
61
  function otelServiceName() {
30
62
  return process.env.OTEL_SERVICE_NAME?.trim() || `${appKeyPrefix()}-api`;
31
63
  }
32
- function webhookSignatureHeader() {
33
- return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
34
- }
35
64
  function appDisplayName() {
36
65
  return process.env.APP_NAME?.trim() || "Strata";
37
66
  }