@getstrata/core 0.5.55 → 0.5.57

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 (118) hide show
  1. package/README.md +3 -1
  2. package/dist/{domain/abilities.d.ts → core/auth/abilityCatalog.d.ts} +9 -1
  3. package/dist/core/auth/accessControl.d.ts +1 -1
  4. package/dist/core/auth/membershipContext.d.ts +6 -4
  5. package/dist/core/auth/membershipService.d.ts +5 -6
  6. package/dist/core/contracts/authUserDirectory.d.ts +11 -0
  7. package/dist/core/contracts/membership.d.ts +20 -0
  8. package/dist/core/http/clientIp.d.ts +3 -0
  9. package/dist/core/jobs/dispatchWebhookJob.d.ts +2 -0
  10. package/dist/core/media/imageTransform.d.ts +13 -0
  11. package/dist/core/scheduler/osCron.d.ts +14 -0
  12. package/dist/core/tenant/tenancyConfig.d.ts +5 -0
  13. package/dist/core/tenant/tenantMiddleware.d.ts +1 -1
  14. package/dist/core/terminal/runShell.d.ts +6 -0
  15. package/dist/core/view/assertEtaHtmlSource.d.ts +5 -0
  16. package/dist/core/view/etaViewEngine.d.ts +4 -0
  17. package/dist/entries/audit/exportAuditLogs.js +2 -2
  18. package/dist/entries/audit/siemFormatter.js +2 -2
  19. package/dist/entries/auth/accessControl.js +4 -4
  20. package/dist/entries/auth/membershipMiddleware.js +21 -161
  21. package/dist/entries/auth/membershipScope.js +26 -166
  22. package/dist/entries/auth/membershipService.js +21 -161
  23. package/dist/entries/auth/oauth/providers.js +2 -2
  24. package/dist/entries/auth/password.js +2 -2
  25. package/dist/entries/auth/policy.js +2 -2
  26. package/dist/entries/auth/scimAuthMiddleware.js +22 -4
  27. package/dist/entries/auth/sessionCookie.js +4 -4
  28. package/dist/entries/auth/sessionGuard.js +12 -349
  29. package/dist/entries/auth/tokenHash.js +2 -2
  30. package/dist/entries/config/envSchema.js +2 -2
  31. package/dist/entries/contracts/container.js +2 -2
  32. package/dist/entries/contracts/di.js +2 -2
  33. package/dist/entries/contracts/serviceTokens.js +6 -6
  34. package/dist/entries/crypto/fieldEncryption.js +8 -8
  35. package/dist/entries/crypto/mfaSecret.js +2 -2
  36. package/dist/entries/database/errors.js +2 -2
  37. package/dist/entries/database/migrations.js +8 -8
  38. package/dist/entries/database/model.js +5 -5
  39. package/dist/entries/database/query.js +19 -19
  40. package/dist/entries/database/relationships.js +13 -13
  41. package/dist/entries/database/schema.js +13 -13
  42. package/dist/entries/database/seeders.js +2 -2
  43. package/dist/entries/facades.js +8 -8
  44. package/dist/entries/http/authMiddleware.js +2 -2
  45. package/dist/entries/http/bodySizeLimitMiddleware.js +2 -2
  46. package/dist/entries/http/clientIp.js +19 -0
  47. package/dist/entries/http/cookies.js +2 -2
  48. package/dist/entries/http/csrfMiddleware.js +2 -1
  49. package/dist/entries/http/csrfProtection.js +2 -2
  50. package/dist/entries/http/csrfToken.js +8 -7
  51. package/dist/entries/http/etag.js +8 -8
  52. package/dist/entries/http/flashSession.js +4 -4
  53. package/dist/entries/http/formRequest.js +2 -2
  54. package/dist/entries/http/loginThrottleMiddleware.js +20 -3
  55. package/dist/entries/http/memoryThrottleMiddleware.js +16 -1
  56. package/dist/entries/http/metricsMiddleware.js +2 -2
  57. package/dist/entries/http/pagination.js +4 -4
  58. package/dist/entries/http/parseFormBody.js +2 -2
  59. package/dist/entries/http/parseMultipartUpload.js +2 -2
  60. package/dist/entries/http/resources.js +2 -2
  61. package/dist/entries/http/response.js +214 -395
  62. package/dist/entries/http/scimThrottleMiddleware.js +40 -1
  63. package/dist/entries/http/securedRouteModelBinding.js +2 -2
  64. package/dist/entries/http/throttleMiddleware.js +20 -3
  65. package/dist/entries/http/validation.js +13 -13
  66. package/dist/entries/http/webErrorResponse.js +212 -393
  67. package/dist/entries/jobs/dispatchWebhookJob.js +111 -5
  68. package/dist/entries/lifecycle/gracefulShutdown.js +3 -3
  69. package/dist/entries/logging/logger.js +2 -2
  70. package/dist/entries/logging/requestLoggingMiddleware.js +16 -1
  71. package/dist/entries/mail/mailer.js +6 -6
  72. package/dist/entries/mail/markdownMail.js +3 -3
  73. package/dist/entries/mail/markdownMailable.js +2 -2
  74. package/dist/entries/media/imageTransform.js +40 -0
  75. package/dist/entries/metrics/prometheus.js +2 -2
  76. package/dist/entries/openapi/generator.js +2 -2
  77. package/dist/entries/queue/createAppQueue.js +4 -4
  78. package/dist/entries/queue/publicQueue.js +10 -10
  79. package/dist/entries/queue/queueMetrics.js +2 -2
  80. package/dist/entries/queue/redisQueue.js +7 -7
  81. package/dist/entries/queue.js +3 -3
  82. package/dist/entries/scheduler/osCron.js +27 -0
  83. package/dist/entries/scheduler/schedule.js +2 -2
  84. package/dist/entries/security/oauthState.js +3 -3
  85. package/dist/entries/security/publicReads.js +2 -2
  86. package/dist/entries/security/safeFetch.js +2 -2
  87. package/dist/entries/security/safeUrl.js +5 -5
  88. package/dist/entries/security/scimTenantTokens.js +3 -6
  89. package/dist/entries/security/totp.js +2 -2
  90. package/dist/entries/storage/storage.js +7 -7
  91. package/dist/entries/tenant/tenancyConfig.js +12 -0
  92. package/dist/entries/tenant/tenantDatabaseScope.js +13 -2
  93. package/dist/entries/terminal/runShell.js +18 -0
  94. package/dist/entries/validation/rules.js +12 -12
  95. package/dist/entries/view.js +212 -393
  96. package/dist/framework/public-api.d.ts +4 -1
  97. package/dist/index.js +2591 -2686
  98. package/package.json +27 -2
  99. package/dist/config/database.d.ts +0 -10
  100. package/dist/db/connection/createConnection.d.ts +0 -6
  101. package/dist/db/connection/index.d.ts +0 -11
  102. package/dist/domain/auth.d.ts +0 -4
  103. package/dist/domain/scim.d.ts +0 -9
  104. package/dist/modules/organization/memberRepository.d.ts +0 -14
  105. package/dist/modules/organization/memberTypes.d.ts +0 -9
  106. package/dist/modules/user/apiTokenRepository.d.ts +0 -8
  107. package/dist/modules/user/apiTokenTable.d.ts +0 -3
  108. package/dist/modules/user/authService.d.ts +0 -23
  109. package/dist/modules/user/notificationRepository.d.ts +0 -6
  110. package/dist/modules/user/notificationService.d.ts +0 -25
  111. package/dist/modules/user/notificationTable.d.ts +0 -3
  112. package/dist/modules/user/notificationTypes.d.ts +0 -12
  113. package/dist/modules/user/oauthIdentityRepository.d.ts +0 -9
  114. package/dist/modules/user/provider.d.ts +0 -11
  115. package/dist/modules/user/repository.d.ts +0 -13
  116. package/dist/modules/user/table.d.ts +0 -3
  117. package/dist/modules/user/tokenService.d.ts +0 -29
  118. package/dist/modules/user/types.d.ts +0 -46
@@ -1,10 +1,44 @@
1
1
  // @bun
2
2
  // ../../src/core/http/scimThrottleMiddleware.ts
3
3
  var {RedisClient } = globalThis.Bun;
4
+
5
+ // ../../src/core/http/clientIp.ts
6
+ function trustForwardedFor(env = process.env) {
7
+ return (env.TRUST_FORWARDED_FOR ?? "false") === "true";
8
+ }
9
+ function readClientIp(request, env = process.env) {
10
+ if (!trustForwardedFor(env)) {
11
+ return;
12
+ }
13
+ const forwarded = request.headers.get("x-forwarded-for")?.split(",")[0]?.trim();
14
+ if (forwarded) {
15
+ return forwarded;
16
+ }
17
+ return request.headers.get("x-real-ip")?.trim() || undefined;
18
+ }
19
+
20
+ // ../../src/core/http/scimThrottleMiddleware.ts
21
+ var memoryBuckets = new Map;
22
+ function resolveScimIdentity(request) {
23
+ return request.headers.get("authorization")?.slice("Bearer ".length, "Bearer ".length + 16) ?? readClientIp(request) ?? "unknown";
24
+ }
25
+ function throttleFromMemory(key, maxAttempts, decaySeconds) {
26
+ const now = Date.now();
27
+ const existing = memoryBuckets.get(key);
28
+ if (!existing || existing.resetAt <= now) {
29
+ memoryBuckets.set(key, { count: 1, resetAt: now + decaySeconds * 1000 });
30
+ return null;
31
+ }
32
+ existing.count += 1;
33
+ if (existing.count > maxAttempts) {
34
+ return Response.json({ error: "Too many SCIM requests." }, { status: 429, headers: { "retry-after": String(decaySeconds) } });
35
+ }
36
+ return null;
37
+ }
4
38
  function createScimThrottleMiddleware(options) {
5
39
  const client = options.redisUrl ? new RedisClient(options.redisUrl) : null;
6
40
  return async (request, next) => {
7
- const identity = request.headers.get("authorization")?.slice("Bearer ".length, "Bearer ".length + 16) ?? request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ?? "unknown";
41
+ const identity = resolveScimIdentity(request);
8
42
  const key = `workhub:scim-throttle:${identity}`;
9
43
  if (client) {
10
44
  const attempts = Number(await client.incr(key));
@@ -14,6 +48,11 @@ function createScimThrottleMiddleware(options) {
14
48
  if (attempts > options.maxAttempts) {
15
49
  return Response.json({ error: "Too many SCIM requests." }, { status: 429, headers: { "retry-after": String(options.decaySeconds) } });
16
50
  }
51
+ return await next();
52
+ }
53
+ const limited = throttleFromMemory(key, options.maxAttempts, options.decaySeconds);
54
+ if (limited) {
55
+ return limited;
17
56
  }
18
57
  return await next();
19
58
  };
@@ -282,6 +282,6 @@ function securedBindRouteModelByKey(param, resolver, authorization, handler) {
282
282
  };
283
283
  }
284
284
  export {
285
- securedBindRouteModelByKey,
286
- securedBindRouteModel
285
+ securedBindRouteModel,
286
+ securedBindRouteModelByKey
287
287
  };
@@ -3,6 +3,23 @@
3
3
  import { currentAuthUser } from "@getstrata/core/auth/authContext";
4
4
  import { currentTenant, rateLimitMultiplierForPlan } from "@getstrata/core/tenant/tenantContext";
5
5
  var {RedisClient } = globalThis.Bun;
6
+
7
+ // ../../src/core/http/clientIp.ts
8
+ function trustForwardedFor(env = process.env) {
9
+ return (env.TRUST_FORWARDED_FOR ?? "false") === "true";
10
+ }
11
+ function readClientIp(request, env = process.env) {
12
+ if (!trustForwardedFor(env)) {
13
+ return;
14
+ }
15
+ const forwarded = request.headers.get("x-forwarded-for")?.split(",")[0]?.trim();
16
+ if (forwarded) {
17
+ return forwarded;
18
+ }
19
+ return request.headers.get("x-real-ip")?.trim() || undefined;
20
+ }
21
+
22
+ // ../../src/core/http/throttleMiddleware.ts
6
23
  function resolveThrottleIdentity(request) {
7
24
  const user = currentAuthUser();
8
25
  if (user?.tokenId !== undefined) {
@@ -11,7 +28,7 @@ function resolveThrottleIdentity(request) {
11
28
  if (user) {
12
29
  return `user:${user.id}`;
13
30
  }
14
- return request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ?? "unknown";
31
+ return readClientIp(request) ?? "unknown";
15
32
  }
16
33
  function createThrottleMiddleware(options) {
17
34
  const client = new RedisClient(options.redisUrl);
@@ -37,6 +54,6 @@ function createThrottleMiddleware(options) {
37
54
  };
38
55
  }
39
56
  export {
40
- resolveThrottleIdentity,
41
- createThrottleMiddleware
57
+ createThrottleMiddleware,
58
+ resolveThrottleIdentity
42
59
  };
@@ -128,18 +128,18 @@ function parsePositiveIntParam(value, name = "id") {
128
128
  return parsed;
129
129
  }
130
130
  export {
131
- readRequiredString,
132
- readRequiredPositiveInt,
133
- readRequiredEnum,
134
- readOptionalString,
135
- readOptionalPositiveInt,
136
- readOptionalEnum,
137
- parsePositiveIntParam,
138
- parseOptionalPositiveIntQueryParam,
139
- parseOptionalEnumQueryParam,
140
- parseOptionalBooleanQueryParam,
141
- parseJsonBody,
142
- getQueryParams,
131
+ buildRequestCacheKey,
143
132
  expectObject,
144
- buildRequestCacheKey
133
+ getQueryParams,
134
+ parseJsonBody,
135
+ parseOptionalBooleanQueryParam,
136
+ parseOptionalEnumQueryParam,
137
+ parseOptionalPositiveIntQueryParam,
138
+ parsePositiveIntParam,
139
+ readOptionalEnum,
140
+ readOptionalPositiveInt,
141
+ readOptionalString,
142
+ readRequiredEnum,
143
+ readRequiredPositiveInt,
144
+ readRequiredString
145
145
  };