@getstrata/core 0.5.79 → 0.5.81

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 (40) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/dist/core/auth/intendedUrlCookie.d.ts +10 -0
  4. package/dist/core/runtime/appKeyPrefix.d.ts +3 -1
  5. package/dist/entries/audit/exportAuditLogs.js +6 -0
  6. package/dist/entries/audit/siemFormatter.js +6 -0
  7. package/dist/entries/auth/intendedUrlCookie.js +176 -0
  8. package/dist/entries/auth/oauth/providers.js +6 -0
  9. package/dist/entries/auth/oauth/samlProvider.js +6 -0
  10. package/dist/entries/auth/passwordConfirmCookie.js +58 -2
  11. package/dist/entries/auth/sessionCookie.js +58 -2
  12. package/dist/entries/auth/sessionGuard.js +58 -2
  13. package/dist/entries/auth/tokenHash.js +58 -2
  14. package/dist/entries/cache/createCacheStore.js +6 -0
  15. package/dist/entries/facades.js +6 -0
  16. package/dist/entries/http/csrfMiddleware.js +56 -2
  17. package/dist/entries/http/csrfToken.js +56 -2
  18. package/dist/entries/http/flashMiddleware.js +58 -2
  19. package/dist/entries/http/flashSession.js +58 -2
  20. package/dist/entries/http/loginThrottleMiddleware.js +6 -0
  21. package/dist/entries/http/memoryThrottleMiddleware.js +6 -0
  22. package/dist/entries/http/requireVerifiedMiddleware.js +7 -1
  23. package/dist/entries/http/scimThrottleMiddleware.js +6 -0
  24. package/dist/entries/http/securityHeadersMiddleware.js +6 -0
  25. package/dist/entries/http/signedUrl.js +57 -1
  26. package/dist/entries/http/throttleMiddleware.js +6 -0
  27. package/dist/entries/jobs/exportAuditLogsJob.js +6 -0
  28. package/dist/entries/mail/mailer.js +6 -0
  29. package/dist/entries/openapi/generator.js +6 -0
  30. package/dist/entries/queue/createAppQueue.js +6 -0
  31. package/dist/entries/queue/publicQueue.js +6 -0
  32. package/dist/entries/queue/queueMetrics.js +6 -0
  33. package/dist/entries/queue/redisQueue.js +6 -0
  34. package/dist/entries/runtime/appKeyPrefix.js +8 -0
  35. package/dist/entries/security/oauthState.js +57 -1
  36. package/dist/entries/security/safeFetch.js +6 -0
  37. package/dist/entries/tracing/tracingMiddleware.js +6 -0
  38. package/dist/entries/view.js +58 -4
  39. package/dist/index.js +11 -7
  40. package/package.json +7 -2
@@ -5,6 +5,60 @@ import { ForbiddenError } from "@getstrata/core/errors/http";
5
5
  // ../../src/core/http/csrfToken.ts
6
6
  import { timingSafeEqual } from "crypto";
7
7
 
8
+ // ../../src/core/runtime/appKeyPrefix.ts
9
+ function appKeyPrefix() {
10
+ return process.env.APP_KEY_PREFIX?.trim() || "workhub";
11
+ }
12
+ function appCookieName(kind) {
13
+ return `${appKeyPrefix()}_${kind}`;
14
+ }
15
+ function appDevSecret(kind) {
16
+ return `${appKeyPrefix()}-dev-${kind}`;
17
+ }
18
+ function namespacedRedisKey(kind) {
19
+ return `${appKeyPrefix()}:${kind}`;
20
+ }
21
+ function smtpEhloHost() {
22
+ const raw = process.env.MAIL_EHLO?.trim() || `${appKeyPrefix()}.local`;
23
+ const safe = raw.replace(/[^a-zA-Z0-9.-]/g, "");
24
+ return safe || "strata.local";
25
+ }
26
+ function siemEventType() {
27
+ return process.env.SIEM_EVENT_TYPE?.trim() || `${appKeyPrefix()}.audit`;
28
+ }
29
+ function appUserAgent() {
30
+ return process.env.APP_USER_AGENT?.trim() || appKeyPrefix();
31
+ }
32
+ function otelServiceName() {
33
+ return process.env.OTEL_SERVICE_NAME?.trim() || `${appKeyPrefix()}-api`;
34
+ }
35
+ function webhookSignatureHeader() {
36
+ return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
37
+ }
38
+ function appDisplayName() {
39
+ return process.env.APP_NAME?.trim() || "WorkHub";
40
+ }
41
+ function appEnv() {
42
+ return process.env.APP_ENV?.trim() || "local";
43
+ }
44
+ function appUrl() {
45
+ return (process.env.APP_URL?.trim() || "http://localhost:3000").replace(/\/$/, "");
46
+ }
47
+ function apiPrefix() {
48
+ const raw = process.env.API_PREFIX?.trim() || "/api/v1";
49
+ const withSlash = raw.startsWith("/") ? raw : `/${raw}`;
50
+ const trimmed = withSlash.replace(/\/+$/, "");
51
+ return trimmed || "/api/v1";
52
+ }
53
+ function sdkClientClassName() {
54
+ const override = process.env.APP_SDK_CLASS?.trim();
55
+ if (override && /^[A-Za-z_][A-Za-z0-9_]*$/.test(override)) {
56
+ return override;
57
+ }
58
+ const fromName = appDisplayName().replace(/[^A-Za-z0-9]/g, "");
59
+ return fromName ? `${fromName}Client` : "AppClient";
60
+ }
61
+
8
62
  // ../../src/core/http/cookies.ts
9
63
  function readRequestCookie(request, name) {
10
64
  const cookies = request.cookies;
@@ -63,10 +117,10 @@ function currentRequestMeta() {
63
117
  var CSRF_COOKIE = "workhub_csrf";
64
118
  var CSRF_TTL_MS = 60 * 60 * 1000;
65
119
  function csrfCookieName() {
66
- return process.env.CSRF_COOKIE_NAME?.trim() || CSRF_COOKIE;
120
+ return process.env.CSRF_COOKIE_NAME?.trim() || appCookieName("csrf");
67
121
  }
68
122
  function resolveCsrfSecret() {
69
- return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || process.env.ADMIN_API_TOKEN?.trim() || "workhub-dev-csrf-secret";
123
+ return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || process.env.ADMIN_API_TOKEN?.trim() || appDevSecret("csrf-secret");
70
124
  }
71
125
  function csrfVerifyOptions() {
72
126
  return { secret: resolveCsrfSecret(), maxAge: CSRF_TTL_MS };
@@ -2,6 +2,60 @@
2
2
  // ../../src/core/http/csrfToken.ts
3
3
  import { timingSafeEqual } from "crypto";
4
4
 
5
+ // ../../src/core/runtime/appKeyPrefix.ts
6
+ function appKeyPrefix() {
7
+ return process.env.APP_KEY_PREFIX?.trim() || "workhub";
8
+ }
9
+ function appCookieName(kind) {
10
+ return `${appKeyPrefix()}_${kind}`;
11
+ }
12
+ function appDevSecret(kind) {
13
+ return `${appKeyPrefix()}-dev-${kind}`;
14
+ }
15
+ function namespacedRedisKey(kind) {
16
+ return `${appKeyPrefix()}:${kind}`;
17
+ }
18
+ function smtpEhloHost() {
19
+ const raw = process.env.MAIL_EHLO?.trim() || `${appKeyPrefix()}.local`;
20
+ const safe = raw.replace(/[^a-zA-Z0-9.-]/g, "");
21
+ return safe || "strata.local";
22
+ }
23
+ function siemEventType() {
24
+ return process.env.SIEM_EVENT_TYPE?.trim() || `${appKeyPrefix()}.audit`;
25
+ }
26
+ function appUserAgent() {
27
+ return process.env.APP_USER_AGENT?.trim() || appKeyPrefix();
28
+ }
29
+ function otelServiceName() {
30
+ return process.env.OTEL_SERVICE_NAME?.trim() || `${appKeyPrefix()}-api`;
31
+ }
32
+ function webhookSignatureHeader() {
33
+ return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
34
+ }
35
+ function appDisplayName() {
36
+ return process.env.APP_NAME?.trim() || "WorkHub";
37
+ }
38
+ function appEnv() {
39
+ return process.env.APP_ENV?.trim() || "local";
40
+ }
41
+ function appUrl() {
42
+ return (process.env.APP_URL?.trim() || "http://localhost:3000").replace(/\/$/, "");
43
+ }
44
+ function apiPrefix() {
45
+ const raw = process.env.API_PREFIX?.trim() || "/api/v1";
46
+ const withSlash = raw.startsWith("/") ? raw : `/${raw}`;
47
+ const trimmed = withSlash.replace(/\/+$/, "");
48
+ return trimmed || "/api/v1";
49
+ }
50
+ function sdkClientClassName() {
51
+ const override = process.env.APP_SDK_CLASS?.trim();
52
+ if (override && /^[A-Za-z_][A-Za-z0-9_]*$/.test(override)) {
53
+ return override;
54
+ }
55
+ const fromName = appDisplayName().replace(/[^A-Za-z0-9]/g, "");
56
+ return fromName ? `${fromName}Client` : "AppClient";
57
+ }
58
+
5
59
  // ../../src/core/http/cookies.ts
6
60
  function readRequestCookie(request, name) {
7
61
  const cookies = request.cookies;
@@ -60,10 +114,10 @@ function currentRequestMeta() {
60
114
  var CSRF_COOKIE = "workhub_csrf";
61
115
  var CSRF_TTL_MS = 60 * 60 * 1000;
62
116
  function csrfCookieName() {
63
- return process.env.CSRF_COOKIE_NAME?.trim() || CSRF_COOKIE;
117
+ return process.env.CSRF_COOKIE_NAME?.trim() || appCookieName("csrf");
64
118
  }
65
119
  function resolveCsrfSecret() {
66
- return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || process.env.ADMIN_API_TOKEN?.trim() || "workhub-dev-csrf-secret";
120
+ return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || process.env.ADMIN_API_TOKEN?.trim() || appDevSecret("csrf-secret");
67
121
  }
68
122
  function csrfVerifyOptions() {
69
123
  return { secret: resolveCsrfSecret(), maxAge: CSRF_TTL_MS };
@@ -1,13 +1,69 @@
1
1
  // @bun
2
2
  // ../../src/core/http/flashSession.ts
3
3
  import { createHmac, timingSafeEqual } from "crypto";
4
+
5
+ // ../../src/core/runtime/appKeyPrefix.ts
6
+ function appKeyPrefix() {
7
+ return process.env.APP_KEY_PREFIX?.trim() || "workhub";
8
+ }
9
+ function appCookieName(kind) {
10
+ return `${appKeyPrefix()}_${kind}`;
11
+ }
12
+ function appDevSecret(kind) {
13
+ return `${appKeyPrefix()}-dev-${kind}`;
14
+ }
15
+ function namespacedRedisKey(kind) {
16
+ return `${appKeyPrefix()}:${kind}`;
17
+ }
18
+ function smtpEhloHost() {
19
+ const raw = process.env.MAIL_EHLO?.trim() || `${appKeyPrefix()}.local`;
20
+ const safe = raw.replace(/[^a-zA-Z0-9.-]/g, "");
21
+ return safe || "strata.local";
22
+ }
23
+ function siemEventType() {
24
+ return process.env.SIEM_EVENT_TYPE?.trim() || `${appKeyPrefix()}.audit`;
25
+ }
26
+ function appUserAgent() {
27
+ return process.env.APP_USER_AGENT?.trim() || appKeyPrefix();
28
+ }
29
+ function otelServiceName() {
30
+ return process.env.OTEL_SERVICE_NAME?.trim() || `${appKeyPrefix()}-api`;
31
+ }
32
+ function webhookSignatureHeader() {
33
+ return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
34
+ }
35
+ function appDisplayName() {
36
+ return process.env.APP_NAME?.trim() || "WorkHub";
37
+ }
38
+ function appEnv() {
39
+ return process.env.APP_ENV?.trim() || "local";
40
+ }
41
+ function appUrl() {
42
+ return (process.env.APP_URL?.trim() || "http://localhost:3000").replace(/\/$/, "");
43
+ }
44
+ function apiPrefix() {
45
+ const raw = process.env.API_PREFIX?.trim() || "/api/v1";
46
+ const withSlash = raw.startsWith("/") ? raw : `/${raw}`;
47
+ const trimmed = withSlash.replace(/\/+$/, "");
48
+ return trimmed || "/api/v1";
49
+ }
50
+ function sdkClientClassName() {
51
+ const override = process.env.APP_SDK_CLASS?.trim();
52
+ if (override && /^[A-Za-z_][A-Za-z0-9_]*$/.test(override)) {
53
+ return override;
54
+ }
55
+ const fromName = appDisplayName().replace(/[^A-Za-z0-9]/g, "");
56
+ return fromName ? `${fromName}Client` : "AppClient";
57
+ }
58
+
59
+ // ../../src/core/http/flashSession.ts
4
60
  var FLASH_COOKIE = "workhub_flash";
5
61
  var FLASH_TTL_MS = 60 * 1000;
6
62
  function flashCookieName() {
7
- return process.env.FLASH_COOKIE_NAME?.trim() || FLASH_COOKIE;
63
+ return process.env.FLASH_COOKIE_NAME?.trim() || appCookieName("flash");
8
64
  }
9
65
  function resolveFlashSecret() {
10
- return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || "workhub-dev-flash-secret";
66
+ return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || appDevSecret("flash-secret");
11
67
  }
12
68
  function signFlashPayload(payload, issuedAt) {
13
69
  const signature = createHmac("sha256", resolveFlashSecret()).update(`${payload}.${issuedAt}`).digest("hex");
@@ -1,13 +1,69 @@
1
1
  // @bun
2
2
  // ../../src/core/http/flashSession.ts
3
3
  import { createHmac, timingSafeEqual } from "crypto";
4
+
5
+ // ../../src/core/runtime/appKeyPrefix.ts
6
+ function appKeyPrefix() {
7
+ return process.env.APP_KEY_PREFIX?.trim() || "workhub";
8
+ }
9
+ function appCookieName(kind) {
10
+ return `${appKeyPrefix()}_${kind}`;
11
+ }
12
+ function appDevSecret(kind) {
13
+ return `${appKeyPrefix()}-dev-${kind}`;
14
+ }
15
+ function namespacedRedisKey(kind) {
16
+ return `${appKeyPrefix()}:${kind}`;
17
+ }
18
+ function smtpEhloHost() {
19
+ const raw = process.env.MAIL_EHLO?.trim() || `${appKeyPrefix()}.local`;
20
+ const safe = raw.replace(/[^a-zA-Z0-9.-]/g, "");
21
+ return safe || "strata.local";
22
+ }
23
+ function siemEventType() {
24
+ return process.env.SIEM_EVENT_TYPE?.trim() || `${appKeyPrefix()}.audit`;
25
+ }
26
+ function appUserAgent() {
27
+ return process.env.APP_USER_AGENT?.trim() || appKeyPrefix();
28
+ }
29
+ function otelServiceName() {
30
+ return process.env.OTEL_SERVICE_NAME?.trim() || `${appKeyPrefix()}-api`;
31
+ }
32
+ function webhookSignatureHeader() {
33
+ return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
34
+ }
35
+ function appDisplayName() {
36
+ return process.env.APP_NAME?.trim() || "WorkHub";
37
+ }
38
+ function appEnv() {
39
+ return process.env.APP_ENV?.trim() || "local";
40
+ }
41
+ function appUrl() {
42
+ return (process.env.APP_URL?.trim() || "http://localhost:3000").replace(/\/$/, "");
43
+ }
44
+ function apiPrefix() {
45
+ const raw = process.env.API_PREFIX?.trim() || "/api/v1";
46
+ const withSlash = raw.startsWith("/") ? raw : `/${raw}`;
47
+ const trimmed = withSlash.replace(/\/+$/, "");
48
+ return trimmed || "/api/v1";
49
+ }
50
+ function sdkClientClassName() {
51
+ const override = process.env.APP_SDK_CLASS?.trim();
52
+ if (override && /^[A-Za-z_][A-Za-z0-9_]*$/.test(override)) {
53
+ return override;
54
+ }
55
+ const fromName = appDisplayName().replace(/[^A-Za-z0-9]/g, "");
56
+ return fromName ? `${fromName}Client` : "AppClient";
57
+ }
58
+
59
+ // ../../src/core/http/flashSession.ts
4
60
  var FLASH_COOKIE = "workhub_flash";
5
61
  var FLASH_TTL_MS = 60 * 1000;
6
62
  function flashCookieName() {
7
- return process.env.FLASH_COOKIE_NAME?.trim() || FLASH_COOKIE;
63
+ return process.env.FLASH_COOKIE_NAME?.trim() || appCookieName("flash");
8
64
  }
9
65
  function resolveFlashSecret() {
10
- return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || "workhub-dev-flash-secret";
66
+ return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || appDevSecret("flash-secret");
11
67
  }
12
68
  function signFlashPayload(payload, issuedAt) {
13
69
  const signature = createHmac("sha256", resolveFlashSecret()).update(`${payload}.${issuedAt}`).digest("hex");
@@ -6,6 +6,12 @@ var {RedisClient } = globalThis.Bun;
6
6
  function appKeyPrefix() {
7
7
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
8
8
  }
9
+ function appCookieName(kind) {
10
+ return `${appKeyPrefix()}_${kind}`;
11
+ }
12
+ function appDevSecret(kind) {
13
+ return `${appKeyPrefix()}-dev-${kind}`;
14
+ }
9
15
  function namespacedRedisKey(kind) {
10
16
  return `${appKeyPrefix()}:${kind}`;
11
17
  }
@@ -3,6 +3,12 @@
3
3
  function appKeyPrefix() {
4
4
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
5
5
  }
6
+ function appCookieName(kind) {
7
+ return `${appKeyPrefix()}_${kind}`;
8
+ }
9
+ function appDevSecret(kind) {
10
+ return `${appKeyPrefix()}-dev-${kind}`;
11
+ }
6
12
  function namespacedRedisKey(kind) {
7
13
  return `${appKeyPrefix()}:${kind}`;
8
14
  }
@@ -5,6 +5,7 @@ import {
5
5
  hasVerifiedEmail,
6
6
  isEmailVerificationRequired
7
7
  } from "@getstrata/core/auth/emailVerification";
8
+ import { createIntendedUrlCookieFromRequest } from "@getstrata/core/auth/intendedUrlCookie";
8
9
 
9
10
  // ../../src/core/http/contentNegotiation.ts
10
11
  function requestPrefersJson(request) {
@@ -44,7 +45,12 @@ function createRequireVerifiedMiddleware(auth) {
44
45
  if (requestPrefersJson(request)) {
45
46
  return Response.json({ error: UNVERIFIED_MESSAGE }, { status: 403 });
46
47
  }
47
- return Response.redirect(VERIFY_NOTICE_PATH, 302);
48
+ const headers = new Headers({ Location: VERIFY_NOTICE_PATH });
49
+ const intended = createIntendedUrlCookieFromRequest(request);
50
+ if (intended) {
51
+ headers.append("Set-Cookie", intended);
52
+ }
53
+ return new Response(null, { status: 302, headers });
48
54
  };
49
55
  }
50
56
  export {
@@ -6,6 +6,12 @@ var {RedisClient } = globalThis.Bun;
6
6
  function appKeyPrefix() {
7
7
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
8
8
  }
9
+ function appCookieName(kind) {
10
+ return `${appKeyPrefix()}_${kind}`;
11
+ }
12
+ function appDevSecret(kind) {
13
+ return `${appKeyPrefix()}-dev-${kind}`;
14
+ }
9
15
  function namespacedRedisKey(kind) {
10
16
  return `${appKeyPrefix()}:${kind}`;
11
17
  }
@@ -11,6 +11,12 @@ import { currentRequestMeta, runWithRequestMeta } from "@getstrata/core/http/req
11
11
  function appKeyPrefix() {
12
12
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
13
13
  }
14
+ function appCookieName(kind) {
15
+ return `${appKeyPrefix()}_${kind}`;
16
+ }
17
+ function appDevSecret(kind) {
18
+ return `${appKeyPrefix()}-dev-${kind}`;
19
+ }
14
20
  function namespacedRedisKey(kind) {
15
21
  return `${appKeyPrefix()}:${kind}`;
16
22
  }
@@ -3,8 +3,64 @@
3
3
  import { createHmac } from "crypto";
4
4
  import { ForbiddenError } from "@getstrata/core/errors/http";
5
5
  import { timingSafeCompareString } from "@getstrata/core/security/timingSafeCompare";
6
+
7
+ // ../../src/core/runtime/appKeyPrefix.ts
8
+ function appKeyPrefix() {
9
+ return process.env.APP_KEY_PREFIX?.trim() || "workhub";
10
+ }
11
+ function appCookieName(kind) {
12
+ return `${appKeyPrefix()}_${kind}`;
13
+ }
14
+ function appDevSecret(kind) {
15
+ return `${appKeyPrefix()}-dev-${kind}`;
16
+ }
17
+ function namespacedRedisKey(kind) {
18
+ return `${appKeyPrefix()}:${kind}`;
19
+ }
20
+ function smtpEhloHost() {
21
+ const raw = process.env.MAIL_EHLO?.trim() || `${appKeyPrefix()}.local`;
22
+ const safe = raw.replace(/[^a-zA-Z0-9.-]/g, "");
23
+ return safe || "strata.local";
24
+ }
25
+ function siemEventType() {
26
+ return process.env.SIEM_EVENT_TYPE?.trim() || `${appKeyPrefix()}.audit`;
27
+ }
28
+ function appUserAgent() {
29
+ return process.env.APP_USER_AGENT?.trim() || appKeyPrefix();
30
+ }
31
+ function otelServiceName() {
32
+ return process.env.OTEL_SERVICE_NAME?.trim() || `${appKeyPrefix()}-api`;
33
+ }
34
+ function webhookSignatureHeader() {
35
+ return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
36
+ }
37
+ function appDisplayName() {
38
+ return process.env.APP_NAME?.trim() || "WorkHub";
39
+ }
40
+ function appEnv() {
41
+ return process.env.APP_ENV?.trim() || "local";
42
+ }
43
+ function appUrl() {
44
+ return (process.env.APP_URL?.trim() || "http://localhost:3000").replace(/\/$/, "");
45
+ }
46
+ function apiPrefix() {
47
+ const raw = process.env.API_PREFIX?.trim() || "/api/v1";
48
+ const withSlash = raw.startsWith("/") ? raw : `/${raw}`;
49
+ const trimmed = withSlash.replace(/\/+$/, "");
50
+ return trimmed || "/api/v1";
51
+ }
52
+ function sdkClientClassName() {
53
+ const override = process.env.APP_SDK_CLASS?.trim();
54
+ if (override && /^[A-Za-z_][A-Za-z0-9_]*$/.test(override)) {
55
+ return override;
56
+ }
57
+ const fromName = appDisplayName().replace(/[^A-Za-z0-9]/g, "");
58
+ return fromName ? `${fromName}Client` : "AppClient";
59
+ }
60
+
61
+ // ../../src/core/http/signedUrl.ts
6
62
  function resolveSignedUrlSecret() {
7
- return process.env.SIGNED_URL_SECRET?.trim() || process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || "workhub-dev-signed-url-secret";
63
+ return process.env.SIGNED_URL_SECRET?.trim() || process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || appDevSecret("signed-url-secret");
8
64
  }
9
65
  function resolveSignedUrlOrigin() {
10
66
  return (process.env.APP_URL ?? "http://localhost:3000").replace(/\/$/, "");
@@ -8,6 +8,12 @@ var {RedisClient } = globalThis.Bun;
8
8
  function appKeyPrefix() {
9
9
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
10
10
  }
11
+ function appCookieName(kind) {
12
+ return `${appKeyPrefix()}_${kind}`;
13
+ }
14
+ function appDevSecret(kind) {
15
+ return `${appKeyPrefix()}-dev-${kind}`;
16
+ }
11
17
  function namespacedRedisKey(kind) {
12
18
  return `${appKeyPrefix()}:${kind}`;
13
19
  }
@@ -6,6 +6,12 @@ import { repositoryConnection as db2 } from "@getstrata/core/database/repository
6
6
  function appKeyPrefix() {
7
7
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
8
8
  }
9
+ function appCookieName(kind) {
10
+ return `${appKeyPrefix()}_${kind}`;
11
+ }
12
+ function appDevSecret(kind) {
13
+ return `${appKeyPrefix()}-dev-${kind}`;
14
+ }
9
15
  function namespacedRedisKey(kind) {
10
16
  return `${appKeyPrefix()}:${kind}`;
11
17
  }
@@ -3,6 +3,12 @@
3
3
  function appKeyPrefix() {
4
4
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
5
5
  }
6
+ function appCookieName(kind) {
7
+ return `${appKeyPrefix()}_${kind}`;
8
+ }
9
+ function appDevSecret(kind) {
10
+ return `${appKeyPrefix()}-dev-${kind}`;
11
+ }
6
12
  function namespacedRedisKey(kind) {
7
13
  return `${appKeyPrefix()}:${kind}`;
8
14
  }
@@ -3,6 +3,12 @@
3
3
  function appKeyPrefix() {
4
4
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
5
5
  }
6
+ function appCookieName(kind) {
7
+ return `${appKeyPrefix()}_${kind}`;
8
+ }
9
+ function appDevSecret(kind) {
10
+ return `${appKeyPrefix()}-dev-${kind}`;
11
+ }
6
12
  function namespacedRedisKey(kind) {
7
13
  return `${appKeyPrefix()}:${kind}`;
8
14
  }
@@ -160,6 +160,12 @@ var {RedisClient } = globalThis.Bun;
160
160
  function appKeyPrefix() {
161
161
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
162
162
  }
163
+ function appCookieName(kind) {
164
+ return `${appKeyPrefix()}_${kind}`;
165
+ }
166
+ function appDevSecret(kind) {
167
+ return `${appKeyPrefix()}-dev-${kind}`;
168
+ }
163
169
  function namespacedRedisKey(kind) {
164
170
  return `${appKeyPrefix()}:${kind}`;
165
171
  }
@@ -160,6 +160,12 @@ var {RedisClient } = globalThis.Bun;
160
160
  function appKeyPrefix() {
161
161
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
162
162
  }
163
+ function appCookieName(kind) {
164
+ return `${appKeyPrefix()}_${kind}`;
165
+ }
166
+ function appDevSecret(kind) {
167
+ return `${appKeyPrefix()}-dev-${kind}`;
168
+ }
163
169
  function namespacedRedisKey(kind) {
164
170
  return `${appKeyPrefix()}:${kind}`;
165
171
  }
@@ -163,6 +163,12 @@ var {RedisClient } = globalThis.Bun;
163
163
  function appKeyPrefix() {
164
164
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
165
165
  }
166
+ function appCookieName(kind) {
167
+ return `${appKeyPrefix()}_${kind}`;
168
+ }
169
+ function appDevSecret(kind) {
170
+ return `${appKeyPrefix()}-dev-${kind}`;
171
+ }
166
172
  function namespacedRedisKey(kind) {
167
173
  return `${appKeyPrefix()}:${kind}`;
168
174
  }
@@ -6,6 +6,12 @@ var {RedisClient } = globalThis.Bun;
6
6
  function appKeyPrefix() {
7
7
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
8
8
  }
9
+ function appCookieName(kind) {
10
+ return `${appKeyPrefix()}_${kind}`;
11
+ }
12
+ function appDevSecret(kind) {
13
+ return `${appKeyPrefix()}-dev-${kind}`;
14
+ }
9
15
  function namespacedRedisKey(kind) {
10
16
  return `${appKeyPrefix()}:${kind}`;
11
17
  }
@@ -3,6 +3,12 @@
3
3
  function appKeyPrefix() {
4
4
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
5
5
  }
6
+ function appCookieName(kind) {
7
+ return `${appKeyPrefix()}_${kind}`;
8
+ }
9
+ function appDevSecret(kind) {
10
+ return `${appKeyPrefix()}-dev-${kind}`;
11
+ }
6
12
  function namespacedRedisKey(kind) {
7
13
  return `${appKeyPrefix()}:${kind}`;
8
14
  }
@@ -48,6 +54,8 @@ function sdkClientClassName() {
48
54
  }
49
55
  export {
50
56
  apiPrefix,
57
+ appCookieName,
58
+ appDevSecret,
51
59
  appDisplayName,
52
60
  appEnv,
53
61
  appKeyPrefix,
@@ -1,10 +1,66 @@
1
1
  // @bun
2
2
  // ../../src/core/security/oauthState.ts
3
3
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
4
+
5
+ // ../../src/core/runtime/appKeyPrefix.ts
6
+ function appKeyPrefix() {
7
+ return process.env.APP_KEY_PREFIX?.trim() || "workhub";
8
+ }
9
+ function appCookieName(kind) {
10
+ return `${appKeyPrefix()}_${kind}`;
11
+ }
12
+ function appDevSecret(kind) {
13
+ return `${appKeyPrefix()}-dev-${kind}`;
14
+ }
15
+ function namespacedRedisKey(kind) {
16
+ return `${appKeyPrefix()}:${kind}`;
17
+ }
18
+ function smtpEhloHost() {
19
+ const raw = process.env.MAIL_EHLO?.trim() || `${appKeyPrefix()}.local`;
20
+ const safe = raw.replace(/[^a-zA-Z0-9.-]/g, "");
21
+ return safe || "strata.local";
22
+ }
23
+ function siemEventType() {
24
+ return process.env.SIEM_EVENT_TYPE?.trim() || `${appKeyPrefix()}.audit`;
25
+ }
26
+ function appUserAgent() {
27
+ return process.env.APP_USER_AGENT?.trim() || appKeyPrefix();
28
+ }
29
+ function otelServiceName() {
30
+ return process.env.OTEL_SERVICE_NAME?.trim() || `${appKeyPrefix()}-api`;
31
+ }
32
+ function webhookSignatureHeader() {
33
+ return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
34
+ }
35
+ function appDisplayName() {
36
+ return process.env.APP_NAME?.trim() || "WorkHub";
37
+ }
38
+ function appEnv() {
39
+ return process.env.APP_ENV?.trim() || "local";
40
+ }
41
+ function appUrl() {
42
+ return (process.env.APP_URL?.trim() || "http://localhost:3000").replace(/\/$/, "");
43
+ }
44
+ function apiPrefix() {
45
+ const raw = process.env.API_PREFIX?.trim() || "/api/v1";
46
+ const withSlash = raw.startsWith("/") ? raw : `/${raw}`;
47
+ const trimmed = withSlash.replace(/\/+$/, "");
48
+ return trimmed || "/api/v1";
49
+ }
50
+ function sdkClientClassName() {
51
+ const override = process.env.APP_SDK_CLASS?.trim();
52
+ if (override && /^[A-Za-z_][A-Za-z0-9_]*$/.test(override)) {
53
+ return override;
54
+ }
55
+ const fromName = appDisplayName().replace(/[^A-Za-z0-9]/g, "");
56
+ return fromName ? `${fromName}Client` : "AppClient";
57
+ }
58
+
59
+ // ../../src/core/security/oauthState.ts
4
60
  var OAUTH_STATE_COOKIE = "oauth_state";
5
61
  var OAUTH_STATE_TTL_MS = 10 * 60 * 1000;
6
62
  function resolveOAuthStateSecret() {
7
- return process.env.OAUTH_STATE_SECRET?.trim() || process.env.ADMIN_API_TOKEN?.trim() || "workhub-dev-oauth-state-secret";
63
+ return process.env.OAUTH_STATE_SECRET?.trim() || process.env.ADMIN_API_TOKEN?.trim() || appDevSecret("oauth-state-secret");
8
64
  }
9
65
  function signOAuthState(state, issuedAt) {
10
66
  const payload = `${state}.${issuedAt}`;
@@ -3,6 +3,12 @@
3
3
  function appKeyPrefix() {
4
4
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
5
5
  }
6
+ function appCookieName(kind) {
7
+ return `${appKeyPrefix()}_${kind}`;
8
+ }
9
+ function appDevSecret(kind) {
10
+ return `${appKeyPrefix()}-dev-${kind}`;
11
+ }
6
12
  function namespacedRedisKey(kind) {
7
13
  return `${appKeyPrefix()}:${kind}`;
8
14
  }
@@ -6,6 +6,12 @@ import { randomBytes } from "crypto";
6
6
  function appKeyPrefix() {
7
7
  return process.env.APP_KEY_PREFIX?.trim() || "workhub";
8
8
  }
9
+ function appCookieName(kind) {
10
+ return `${appKeyPrefix()}_${kind}`;
11
+ }
12
+ function appDevSecret(kind) {
13
+ return `${appKeyPrefix()}-dev-${kind}`;
14
+ }
9
15
  function namespacedRedisKey(kind) {
10
16
  return `${appKeyPrefix()}:${kind}`;
11
17
  }