@getstrata/core 0.5.78 → 0.5.80

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 (38) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/core/auth/sessionCookie.d.ts +8 -2
  3. package/dist/core/contracts/authUserDirectory.d.ts +1 -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/oauth/providers.js +6 -0
  8. package/dist/entries/auth/oauth/samlProvider.js +6 -0
  9. package/dist/entries/auth/passwordConfirmCookie.js +58 -2
  10. package/dist/entries/auth/sessionCookie.js +75 -4
  11. package/dist/entries/auth/sessionGuard.js +79 -7
  12. package/dist/entries/auth/tokenHash.js +58 -2
  13. package/dist/entries/cache/createCacheStore.js +6 -0
  14. package/dist/entries/facades.js +6 -0
  15. package/dist/entries/http/csrfMiddleware.js +56 -2
  16. package/dist/entries/http/csrfToken.js +56 -2
  17. package/dist/entries/http/flashMiddleware.js +58 -2
  18. package/dist/entries/http/flashSession.js +58 -2
  19. package/dist/entries/http/loginThrottleMiddleware.js +6 -0
  20. package/dist/entries/http/memoryThrottleMiddleware.js +6 -0
  21. package/dist/entries/http/scimThrottleMiddleware.js +6 -0
  22. package/dist/entries/http/securityHeadersMiddleware.js +6 -0
  23. package/dist/entries/http/signedUrl.js +57 -1
  24. package/dist/entries/http/throttleMiddleware.js +6 -0
  25. package/dist/entries/jobs/exportAuditLogsJob.js +6 -0
  26. package/dist/entries/mail/mailer.js +6 -0
  27. package/dist/entries/openapi/generator.js +6 -0
  28. package/dist/entries/queue/createAppQueue.js +6 -0
  29. package/dist/entries/queue/publicQueue.js +6 -0
  30. package/dist/entries/queue/queueMetrics.js +6 -0
  31. package/dist/entries/queue/redisQueue.js +6 -0
  32. package/dist/entries/runtime/appKeyPrefix.js +8 -0
  33. package/dist/entries/security/oauthState.js +57 -1
  34. package/dist/entries/security/safeFetch.js +6 -0
  35. package/dist/entries/tracing/tracingMiddleware.js +6 -0
  36. package/dist/entries/view.js +58 -4
  37. package/dist/index.js +11 -7
  38. package/package.json +1 -1
@@ -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
  }
@@ -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
  }
@@ -384,6 +384,60 @@ function resolveAuthUserDirectory(container) {
384
384
  // ../../src/core/http/csrfToken.ts
385
385
  import { timingSafeEqual } from "crypto";
386
386
 
387
+ // ../../src/core/runtime/appKeyPrefix.ts
388
+ function appKeyPrefix() {
389
+ return process.env.APP_KEY_PREFIX?.trim() || "workhub";
390
+ }
391
+ function appCookieName(kind) {
392
+ return `${appKeyPrefix()}_${kind}`;
393
+ }
394
+ function appDevSecret(kind) {
395
+ return `${appKeyPrefix()}-dev-${kind}`;
396
+ }
397
+ function namespacedRedisKey(kind) {
398
+ return `${appKeyPrefix()}:${kind}`;
399
+ }
400
+ function smtpEhloHost() {
401
+ const raw = process.env.MAIL_EHLO?.trim() || `${appKeyPrefix()}.local`;
402
+ const safe = raw.replace(/[^a-zA-Z0-9.-]/g, "");
403
+ return safe || "strata.local";
404
+ }
405
+ function siemEventType() {
406
+ return process.env.SIEM_EVENT_TYPE?.trim() || `${appKeyPrefix()}.audit`;
407
+ }
408
+ function appUserAgent() {
409
+ return process.env.APP_USER_AGENT?.trim() || appKeyPrefix();
410
+ }
411
+ function otelServiceName() {
412
+ return process.env.OTEL_SERVICE_NAME?.trim() || `${appKeyPrefix()}-api`;
413
+ }
414
+ function webhookSignatureHeader() {
415
+ return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
416
+ }
417
+ function appDisplayName() {
418
+ return process.env.APP_NAME?.trim() || "WorkHub";
419
+ }
420
+ function appEnv() {
421
+ return process.env.APP_ENV?.trim() || "local";
422
+ }
423
+ function appUrl() {
424
+ return (process.env.APP_URL?.trim() || "http://localhost:3000").replace(/\/$/, "");
425
+ }
426
+ function apiPrefix() {
427
+ const raw = process.env.API_PREFIX?.trim() || "/api/v1";
428
+ const withSlash = raw.startsWith("/") ? raw : `/${raw}`;
429
+ const trimmed = withSlash.replace(/\/+$/, "");
430
+ return trimmed || "/api/v1";
431
+ }
432
+ function sdkClientClassName() {
433
+ const override = process.env.APP_SDK_CLASS?.trim();
434
+ if (override && /^[A-Za-z_][A-Za-z0-9_]*$/.test(override)) {
435
+ return override;
436
+ }
437
+ const fromName = appDisplayName().replace(/[^A-Za-z0-9]/g, "");
438
+ return fromName ? `${fromName}Client` : "AppClient";
439
+ }
440
+
387
441
  // ../../src/core/http/cookies.ts
388
442
  function readRequestCookie(request, name) {
389
443
  const cookies = request.cookies;
@@ -442,10 +496,10 @@ function currentRequestMeta3() {
442
496
  var CSRF_COOKIE = "workhub_csrf";
443
497
  var CSRF_TTL_MS = 60 * 60 * 1000;
444
498
  function csrfCookieName() {
445
- return process.env.CSRF_COOKIE_NAME?.trim() || CSRF_COOKIE;
499
+ return process.env.CSRF_COOKIE_NAME?.trim() || appCookieName("csrf");
446
500
  }
447
501
  function resolveCsrfSecret() {
448
- return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || process.env.ADMIN_API_TOKEN?.trim() || "workhub-dev-csrf-secret";
502
+ return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || process.env.ADMIN_API_TOKEN?.trim() || appDevSecret("csrf-secret");
449
503
  }
450
504
  function csrfVerifyOptions() {
451
505
  return { secret: resolveCsrfSecret(), maxAge: CSRF_TTL_MS };
@@ -525,10 +579,10 @@ import { createHmac, timingSafeEqual as timingSafeEqual2 } from "crypto";
525
579
  var FLASH_COOKIE = "workhub_flash";
526
580
  var FLASH_TTL_MS = 60 * 1000;
527
581
  function flashCookieName() {
528
- return process.env.FLASH_COOKIE_NAME?.trim() || FLASH_COOKIE;
582
+ return process.env.FLASH_COOKIE_NAME?.trim() || appCookieName("flash");
529
583
  }
530
584
  function resolveFlashSecret() {
531
- return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || "workhub-dev-flash-secret";
585
+ return process.env.SESSION_SECRET?.trim() || process.env.OAUTH_STATE_SECRET?.trim() || appDevSecret("flash-secret");
532
586
  }
533
587
  function signFlashPayload(payload, issuedAt) {
534
588
  const signature = createHmac("sha256", resolveFlashSecret()).update(`${payload}.${issuedAt}`).digest("hex");