@burdenoff/be-sdk 2026.510.79

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 (220) hide show
  1. package/README.md +173 -0
  2. package/configs/eslint/index.js +492 -0
  3. package/configs/tsconfig/tsconfig.json +53 -0
  4. package/dist/EventQueueFactory-6NMSGECR.js +8 -0
  5. package/dist/EventQueueFactory-6NMSGECR.js.map +1 -0
  6. package/dist/auth/index.d.ts +66 -0
  7. package/dist/auth/index.js +8 -0
  8. package/dist/auth/index.js.map +1 -0
  9. package/dist/cache/index.d.ts +2 -0
  10. package/dist/cache/index.js +6 -0
  11. package/dist/cache/index.js.map +1 -0
  12. package/dist/captcha/index.d.ts +1 -0
  13. package/dist/captcha/index.js +4 -0
  14. package/dist/captcha/index.js.map +1 -0
  15. package/dist/chunk-2HANKZZM.js +245 -0
  16. package/dist/chunk-2HANKZZM.js.map +1 -0
  17. package/dist/chunk-2SD5L2F2.js +816 -0
  18. package/dist/chunk-2SD5L2F2.js.map +1 -0
  19. package/dist/chunk-3O2RQOPV.js +1068 -0
  20. package/dist/chunk-3O2RQOPV.js.map +1 -0
  21. package/dist/chunk-4B43DZIS.js +560 -0
  22. package/dist/chunk-4B43DZIS.js.map +1 -0
  23. package/dist/chunk-4XAEES25.js +2444 -0
  24. package/dist/chunk-4XAEES25.js.map +1 -0
  25. package/dist/chunk-4XGGWW36.js +1405 -0
  26. package/dist/chunk-4XGGWW36.js.map +1 -0
  27. package/dist/chunk-5LXDPGDH.js +245 -0
  28. package/dist/chunk-5LXDPGDH.js.map +1 -0
  29. package/dist/chunk-AI7L22ZJ.js +472 -0
  30. package/dist/chunk-AI7L22ZJ.js.map +1 -0
  31. package/dist/chunk-CBZNP6RF.js +286 -0
  32. package/dist/chunk-CBZNP6RF.js.map +1 -0
  33. package/dist/chunk-ELLX3K54.js +613 -0
  34. package/dist/chunk-ELLX3K54.js.map +1 -0
  35. package/dist/chunk-F5XEAGHQ.js +1875 -0
  36. package/dist/chunk-F5XEAGHQ.js.map +1 -0
  37. package/dist/chunk-FNZEQOJY.js +628 -0
  38. package/dist/chunk-FNZEQOJY.js.map +1 -0
  39. package/dist/chunk-GTEMQXCA.js +516 -0
  40. package/dist/chunk-GTEMQXCA.js.map +1 -0
  41. package/dist/chunk-HIWTWIGQ.js +226 -0
  42. package/dist/chunk-HIWTWIGQ.js.map +1 -0
  43. package/dist/chunk-IYE2NTRX.js +764 -0
  44. package/dist/chunk-IYE2NTRX.js.map +1 -0
  45. package/dist/chunk-J26YGR2U.js +1484 -0
  46. package/dist/chunk-J26YGR2U.js.map +1 -0
  47. package/dist/chunk-JG2FTZPI.js +509 -0
  48. package/dist/chunk-JG2FTZPI.js.map +1 -0
  49. package/dist/chunk-JVBTNSPG.js +1551 -0
  50. package/dist/chunk-JVBTNSPG.js.map +1 -0
  51. package/dist/chunk-L7ZMN2FJ.js +12 -0
  52. package/dist/chunk-L7ZMN2FJ.js.map +1 -0
  53. package/dist/chunk-M5IMU3US.js +473 -0
  54. package/dist/chunk-M5IMU3US.js.map +1 -0
  55. package/dist/chunk-MLW2HPS5.js +1267 -0
  56. package/dist/chunk-MLW2HPS5.js.map +1 -0
  57. package/dist/chunk-MNCGUYLJ.js +269 -0
  58. package/dist/chunk-MNCGUYLJ.js.map +1 -0
  59. package/dist/chunk-MOCUBSTW.js +373 -0
  60. package/dist/chunk-MOCUBSTW.js.map +1 -0
  61. package/dist/chunk-NGMEI42S.js +103 -0
  62. package/dist/chunk-NGMEI42S.js.map +1 -0
  63. package/dist/chunk-NUB5GQTU.js +270 -0
  64. package/dist/chunk-NUB5GQTU.js.map +1 -0
  65. package/dist/chunk-OVSYMNCI.js +145 -0
  66. package/dist/chunk-OVSYMNCI.js.map +1 -0
  67. package/dist/chunk-QLVKMWFA.js +94 -0
  68. package/dist/chunk-QLVKMWFA.js.map +1 -0
  69. package/dist/chunk-SAG6ZYWQ.js +89 -0
  70. package/dist/chunk-SAG6ZYWQ.js.map +1 -0
  71. package/dist/chunk-SAK2JCA7.js +198 -0
  72. package/dist/chunk-SAK2JCA7.js.map +1 -0
  73. package/dist/chunk-SBS4S2PJ.js +100 -0
  74. package/dist/chunk-SBS4S2PJ.js.map +1 -0
  75. package/dist/chunk-SNEOLWXT.js +148 -0
  76. package/dist/chunk-SNEOLWXT.js.map +1 -0
  77. package/dist/chunk-TKBD2ONF.js +564 -0
  78. package/dist/chunk-TKBD2ONF.js.map +1 -0
  79. package/dist/chunk-UBXFIIAW.js +127 -0
  80. package/dist/chunk-UBXFIIAW.js.map +1 -0
  81. package/dist/chunk-VI4VSNTI.js +57 -0
  82. package/dist/chunk-VI4VSNTI.js.map +1 -0
  83. package/dist/chunk-VWCN5PMD.js +268 -0
  84. package/dist/chunk-VWCN5PMD.js.map +1 -0
  85. package/dist/chunk-XC2YD6CF.js +913 -0
  86. package/dist/chunk-XC2YD6CF.js.map +1 -0
  87. package/dist/chunk-XE4OXN2W.js +10 -0
  88. package/dist/chunk-XE4OXN2W.js.map +1 -0
  89. package/dist/chunk-YMZEUTD2.js +110 -0
  90. package/dist/chunk-YMZEUTD2.js.map +1 -0
  91. package/dist/chunk-Z4IRLBWO.js +758 -0
  92. package/dist/chunk-Z4IRLBWO.js.map +1 -0
  93. package/dist/client/internal-client.d.ts +7 -0
  94. package/dist/client/internal-client.js +5 -0
  95. package/dist/client/internal-client.js.map +1 -0
  96. package/dist/client-CSjIrYKS.d.ts +77 -0
  97. package/dist/config-UKE2E3BW.js +4 -0
  98. package/dist/config-UKE2E3BW.js.map +1 -0
  99. package/dist/crypto/index.d.ts +1 -0
  100. package/dist/crypto/index.js +4 -0
  101. package/dist/crypto/index.js.map +1 -0
  102. package/dist/database/index.d.ts +117 -0
  103. package/dist/database/index.js +7 -0
  104. package/dist/database/index.js.map +1 -0
  105. package/dist/dataloader/index.d.ts +1 -0
  106. package/dist/dataloader/index.js +4 -0
  107. package/dist/dataloader/index.js.map +1 -0
  108. package/dist/esm-K6H7EIWK.js +1450 -0
  109. package/dist/esm-K6H7EIWK.js.map +1 -0
  110. package/dist/event-queue/index.d.ts +6 -0
  111. package/dist/event-queue/index.js +10 -0
  112. package/dist/event-queue/index.js.map +1 -0
  113. package/dist/export/index.d.ts +2 -0
  114. package/dist/export/index.js +9 -0
  115. package/dist/export/index.js.map +1 -0
  116. package/dist/feature-flags/index.d.ts +1 -0
  117. package/dist/feature-flags/index.js +4 -0
  118. package/dist/feature-flags/index.js.map +1 -0
  119. package/dist/gateway/index.d.ts +4 -0
  120. package/dist/gateway/index.js +8 -0
  121. package/dist/gateway/index.js.map +1 -0
  122. package/dist/gateway/security/index.d.ts +2 -0
  123. package/dist/gateway/security/index.js +5 -0
  124. package/dist/gateway/security/index.js.map +1 -0
  125. package/dist/graph/index.d.ts +9 -0
  126. package/dist/graph/index.js +13 -0
  127. package/dist/graph/index.js.map +1 -0
  128. package/dist/graph-emitter-Bk0FqD53.d.ts +47 -0
  129. package/dist/graphql/index.d.ts +2 -0
  130. package/dist/graphql/index.js +7 -0
  131. package/dist/graphql/index.js.map +1 -0
  132. package/dist/graphql/services/index.d.ts +24 -0
  133. package/dist/graphql/services/index.js +5 -0
  134. package/dist/graphql/services/index.js.map +1 -0
  135. package/dist/graphql-BAVrUgBF.d.ts +22 -0
  136. package/dist/i18n/index.d.ts +2 -0
  137. package/dist/i18n/index.js +5 -0
  138. package/dist/i18n/index.js.map +1 -0
  139. package/dist/i18n-DA6IPnYy.d.ts +101 -0
  140. package/dist/index-4gKQKZ2B.d.ts +71 -0
  141. package/dist/index-B18rrFru.d.ts +42 -0
  142. package/dist/index-B70b5mYS.d.ts +33 -0
  143. package/dist/index-BMq3lFjj.d.ts +247 -0
  144. package/dist/index-BODgvRtL.d.ts +316 -0
  145. package/dist/index-BS2idbnr.d.ts +874 -0
  146. package/dist/index-BV3G48cH.d.ts +124 -0
  147. package/dist/index-CHbVw5M7.d.ts +73 -0
  148. package/dist/index-Cq_xNjcv.d.ts +602 -0
  149. package/dist/index-CrQgidpx.d.ts +77 -0
  150. package/dist/index-CyVEg86m.d.ts +309 -0
  151. package/dist/index-DOcBnmMe.d.ts +166 -0
  152. package/dist/index-DSOpj8DI.d.ts +17 -0
  153. package/dist/index-DW9q22GH.d.ts +75 -0
  154. package/dist/index-DlFDFyWD.d.ts +55 -0
  155. package/dist/index-DoK0bjhH.d.ts +607 -0
  156. package/dist/index-Dtf6FBaD.d.ts +199 -0
  157. package/dist/index-KVWGHMbS.d.ts +415 -0
  158. package/dist/index-PaojfSdd.d.ts +71 -0
  159. package/dist/index-RU_M5c74.d.ts +163 -0
  160. package/dist/index-UhkH2eaB.d.ts +192 -0
  161. package/dist/index-e_18DzAg.d.ts +18 -0
  162. package/dist/index-jOuh_TKn.d.ts +59 -0
  163. package/dist/index.d.ts +584 -0
  164. package/dist/index.js +2626 -0
  165. package/dist/index.js.map +1 -0
  166. package/dist/init/index.d.ts +2 -0
  167. package/dist/init/index.js +12 -0
  168. package/dist/init/index.js.map +1 -0
  169. package/dist/instrumentation/index.d.ts +3 -0
  170. package/dist/instrumentation/index.js +5 -0
  171. package/dist/instrumentation/index.js.map +1 -0
  172. package/dist/layer/index.d.ts +2 -0
  173. package/dist/layer/index.js +6 -0
  174. package/dist/layer/index.js.map +1 -0
  175. package/dist/layer-DDip18KY.d.ts +67 -0
  176. package/dist/logger/index.d.ts +2 -0
  177. package/dist/logger/index.js +4 -0
  178. package/dist/logger/index.js.map +1 -0
  179. package/dist/middleware/index.d.ts +3 -0
  180. package/dist/middleware/index.js +5 -0
  181. package/dist/middleware/index.js.map +1 -0
  182. package/dist/notifications/index.d.ts +4 -0
  183. package/dist/notifications/index.js +7 -0
  184. package/dist/notifications/index.js.map +1 -0
  185. package/dist/observability/index.d.ts +3 -0
  186. package/dist/observability/index.js +5 -0
  187. package/dist/observability/index.js.map +1 -0
  188. package/dist/pino-logger-RYLGXPHZ.js +5 -0
  189. package/dist/pino-logger-RYLGXPHZ.js.map +1 -0
  190. package/dist/prisma/generator/index.d.ts +1 -0
  191. package/dist/prisma/generator/index.js +228 -0
  192. package/dist/prisma/generator/index.js.map +1 -0
  193. package/dist/prisma/index.d.ts +5 -0
  194. package/dist/prisma/index.js +12 -0
  195. package/dist/prisma/index.js.map +1 -0
  196. package/dist/prisma-extension-krXnYnrN.d.ts +30 -0
  197. package/dist/rbac/index.d.ts +116 -0
  198. package/dist/rbac/index.js +7 -0
  199. package/dist/rbac/index.js.map +1 -0
  200. package/dist/sdk-THO3IWEE.js +136 -0
  201. package/dist/sdk-THO3IWEE.js.map +1 -0
  202. package/dist/server/index.d.ts +359 -0
  203. package/dist/server/index.js +884 -0
  204. package/dist/server/index.js.map +1 -0
  205. package/dist/telemetry/index.d.ts +83 -0
  206. package/dist/telemetry/index.js +209 -0
  207. package/dist/telemetry/index.js.map +1 -0
  208. package/dist/temporal/index.d.ts +148 -0
  209. package/dist/temporal/index.js +6 -0
  210. package/dist/temporal/index.js.map +1 -0
  211. package/dist/tracker/index.d.ts +5 -0
  212. package/dist/tracker/index.js +9 -0
  213. package/dist/tracker/index.js.map +1 -0
  214. package/dist/types-Bo2wkjSP.d.ts +35 -0
  215. package/dist/utils/index.d.ts +1 -0
  216. package/dist/utils/index.js +4 -0
  217. package/dist/utils/index.js.map +1 -0
  218. package/dist/workspace-guard-LHBNK4TG.js +5 -0
  219. package/dist/workspace-guard-LHBNK4TG.js.map +1 -0
  220. package/package.json +241 -0
@@ -0,0 +1,53 @@
1
+ {
2
+ "compileOnSave": true,
3
+ "compilerOptions": {
4
+ /* Language and Environment */
5
+ "target": "ES2022",
6
+ "lib": ["ES2022"],
7
+ "experimentalDecorators": true,
8
+ "emitDecoratorMetadata": true,
9
+ "useUnknownInCatchVariables": true,
10
+
11
+ /* Modules */
12
+ "module": "ESNext",
13
+ "moduleResolution": "bundler",
14
+ "resolveJsonModule": true,
15
+ "allowJs": true,
16
+
17
+ /* Emit */
18
+ "declaration": true,
19
+ "declarationMap": true,
20
+ "sourceMap": true,
21
+ "removeComments": true,
22
+ "composite": true,
23
+ "noEmitOnError": false,
24
+
25
+ /* Interop Constraints */
26
+ "esModuleInterop": true,
27
+ "allowSyntheticDefaultImports": true,
28
+ "forceConsistentCasingInFileNames": true,
29
+
30
+ /* Type Checking - Strict Mode */
31
+ "strict": true,
32
+ "alwaysStrict": true,
33
+ "noImplicitAny": true,
34
+ "strictFunctionTypes": true,
35
+
36
+ /* Type Checking - Enhanced */
37
+ "noUncheckedIndexedAccess": true,
38
+ "noImplicitReturns": true,
39
+ "noFallthroughCasesInSwitch": true,
40
+ "noImplicitOverride": true,
41
+ // noUnusedLocals disabled - ESLint handles this with proper ignores for generated files
42
+ // TypeScript doesn't support per-file overrides, so we use ESLint for unused var checking
43
+ "noUnusedLocals": false,
44
+ "noUnusedParameters": false,
45
+
46
+ /* Performance Optimizations */
47
+ "skipLibCheck": true,
48
+ "skipDefaultLibCheck": true,
49
+
50
+ /* Constants */
51
+ "preserveConstEnums": true
52
+ }
53
+ }
@@ -0,0 +1,8 @@
1
+ export { EventQueueFactory } from './chunk-3O2RQOPV.js';
2
+ import './chunk-L7ZMN2FJ.js';
3
+ import './chunk-OVSYMNCI.js';
4
+ import './chunk-NGMEI42S.js';
5
+ import './chunk-CBZNP6RF.js';
6
+ import './chunk-XE4OXN2W.js';
7
+ //# sourceMappingURL=EventQueueFactory-6NMSGECR.js.map
8
+ //# sourceMappingURL=EventQueueFactory-6NMSGECR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"EventQueueFactory-6NMSGECR.js"}
@@ -0,0 +1,66 @@
1
+ import { B as BurdenoffGraphQLClient } from '../graphql-BAVrUgBF.js';
2
+ import { S as SDKContext } from '../index-CHbVw5M7.js';
3
+ import 'graphql-request';
4
+
5
+ interface CookieOptions {
6
+ name: string;
7
+ value: string;
8
+ maxAge?: number;
9
+ domain?: string;
10
+ path?: string;
11
+ httpOnly?: boolean;
12
+ secure?: boolean;
13
+ sameSite?: 'Strict' | 'Lax' | 'None';
14
+ }
15
+
16
+ interface CookieContext {
17
+ responseHeaders?: Headers;
18
+ [key: string]: unknown;
19
+ }
20
+ declare const AuthCookieHelper: {
21
+ setAuthCookies(context: CookieContext, tokens: {
22
+ accessToken: string;
23
+ refreshToken: string;
24
+ }, options?: {
25
+ rememberMe?: boolean;
26
+ }): void;
27
+ clearAuthCookies(context: CookieContext): void;
28
+ };
29
+ interface TokenPayload {
30
+ jti: string;
31
+ sub: string;
32
+ user_id: string;
33
+ workspace_id?: string;
34
+ org_id?: string;
35
+ tenant_endpoint?: string;
36
+ iat: number;
37
+ exp: number;
38
+ scope?: string;
39
+ }
40
+ interface VerifyTokenResult {
41
+ valid: boolean;
42
+ payload?: TokenPayload;
43
+ error?: string;
44
+ }
45
+ interface RefreshTokenResult {
46
+ accessToken: string;
47
+ refreshToken: string;
48
+ expiresIn: number;
49
+ }
50
+
51
+ declare class AuthModule {
52
+ private client;
53
+ private context;
54
+ constructor(client: BurdenoffGraphQLClient, context: SDKContext);
55
+ verifyToken(token: string): Promise<VerifyTokenResult>;
56
+ decodeToken(token: string): TokenPayload | null;
57
+ refreshToken(refreshToken: string): Promise<RefreshTokenResult>;
58
+ validatePermission(userId: string, permission: string, resourceId?: string): Promise<boolean>;
59
+ isTokenValid(token: string): boolean;
60
+ getUserIdFromToken(token: string): string | null;
61
+ getWorkspaceIdFromToken(token: string): string | null;
62
+ getTokenClaims(token: string): Record<string, unknown> | null;
63
+ willExpireSoon(token: string, withinSeconds?: number): boolean;
64
+ }
65
+
66
+ export { AuthCookieHelper, AuthModule, type CookieOptions, type RefreshTokenResult, type TokenPayload, type VerifyTokenResult };
@@ -0,0 +1,8 @@
1
+ export { AuthCookieHelper, AuthModule } from '../chunk-SAK2JCA7.js';
2
+ import '../chunk-MOCUBSTW.js';
3
+ import '../chunk-SAG6ZYWQ.js';
4
+ import '../chunk-NGMEI42S.js';
5
+ import '../chunk-CBZNP6RF.js';
6
+ import '../chunk-XE4OXN2W.js';
7
+ //# sourceMappingURL=index.js.map
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,2 @@
1
+ export { B as BaseCacheConfig, a as BatchCacheOptions, C as CacheConfig, b as CacheEntry, c as CacheFactory, d as CacheHealthCheckResult, e as CacheOptions, f as CacheProviderType, g as CacheProviderTypeLiteral, h as CacheStatistics, I as ICache, j as ICacheProvider, M as MemcachedCacheConfig, k as MemoryCacheConfig, l as MemoryCacheProvider, P as PatternOptions, m as PatternResult, V as ValkeyCacheConfig, n as ValkeyGlideClient, o as ValkeyGlideConfig, p as ValkeyGlideProvider, q as closeAllCaches, r as createCache, s as getCache, t as getValkeyClient } from '../index-BODgvRtL.js';
2
+ import '../layer-DDip18KY.js';
@@ -0,0 +1,6 @@
1
+ export { CacheFactory, CacheProviderType, MemoryCacheProvider, ValkeyGlideProvider, closeAllCaches, createCache, getCache, getValkeyClient } from '../chunk-4XGGWW36.js';
2
+ import '../chunk-NGMEI42S.js';
3
+ import '../chunk-CBZNP6RF.js';
4
+ import '../chunk-XE4OXN2W.js';
5
+ //# sourceMappingURL=index.js.map
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1 @@
1
+ export { R as RecaptchaVerifyOptions, a as RecaptchaVerifyResult, V as VerifyCaptchaInput, d as VerifyCaptchaResult, b as isCaptchaEnabled, v as verifyCaptcha, c as verifyCaptchaIfEnabled } from '../index-B70b5mYS.js';
@@ -0,0 +1,4 @@
1
+ export { isCaptchaEnabled, verifyCaptcha, verifyCaptchaIfEnabled } from '../chunk-YMZEUTD2.js';
2
+ import '../chunk-XE4OXN2W.js';
3
+ //# sourceMappingURL=index.js.map
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,245 @@
1
+ import { logger } from './chunk-CBZNP6RF.js';
2
+ import { __export, __name } from './chunk-XE4OXN2W.js';
3
+ import crypto from 'crypto';
4
+ import { Elysia } from 'elysia';
5
+
6
+ // src/middleware/index.ts
7
+ var middleware_exports = {};
8
+ __export(middleware_exports, {
9
+ cleanupExpiredTokens: () => cleanupExpiredTokens,
10
+ createSecurityPlugin: () => createSecurityPlugin
11
+ });
12
+ var csrfTokens = /* @__PURE__ */ new Map();
13
+ var MAX_CSRF_TOKENS = 1e5;
14
+ var DEFAULT_CSRF_SKIP_ROUTES = [
15
+ "/graphql",
16
+ "/webhook/",
17
+ "/upload/",
18
+ "/oidc/",
19
+ "/interaction/"
20
+ ];
21
+ var DEFAULT_LOGIN_ENDPOINTS = [
22
+ "/interaction/",
23
+ "/oidc/token",
24
+ "/api/auth/login"
25
+ ];
26
+ function generateCSRFToken() {
27
+ return crypto.randomBytes(32).toString("hex");
28
+ }
29
+ __name(generateCSRFToken, "generateCSRFToken");
30
+ function constantTimeCompare(a, b) {
31
+ if (a.length !== b.length) {
32
+ return false;
33
+ }
34
+ let result = 0;
35
+ for (let i = 0; i < a.length; i++) {
36
+ result |= a.charCodeAt(i) ^ b.charCodeAt(i);
37
+ }
38
+ return result === 0;
39
+ }
40
+ __name(constantTimeCompare, "constantTimeCompare");
41
+ function getSessionId(request) {
42
+ const cookieHeader = request.headers.get("cookie");
43
+ if (!cookieHeader) return null;
44
+ const cookies = cookieHeader.split(";").reduce((acc, cookie) => {
45
+ const [key, value] = cookie.trim().split("=");
46
+ if (key && value) {
47
+ acc[key] = value;
48
+ }
49
+ return acc;
50
+ }, {});
51
+ return cookies["_session"] || null;
52
+ }
53
+ __name(getSessionId, "getSessionId");
54
+ function getCSRFTokenFromRequest(request, body) {
55
+ const headerToken = request.headers.get("x-csrf-token");
56
+ if (headerToken) {
57
+ return headerToken;
58
+ }
59
+ if (body && typeof body === "object") {
60
+ const bodyToken = body["_csrf"];
61
+ if (bodyToken && typeof bodyToken === "string") {
62
+ return bodyToken;
63
+ }
64
+ }
65
+ return null;
66
+ }
67
+ __name(getCSRFTokenFromRequest, "getCSRFTokenFromRequest");
68
+ function pruneCSRFTokenStore(maxEntries = MAX_CSRF_TOKENS) {
69
+ cleanupExpiredTokens();
70
+ while (csrfTokens.size > maxEntries) {
71
+ const oldestEntry = csrfTokens.keys().next();
72
+ if (oldestEntry.done) {
73
+ break;
74
+ }
75
+ csrfTokens.delete(oldestEntry.value);
76
+ }
77
+ }
78
+ __name(pruneCSRFTokenStore, "pruneCSRFTokenStore");
79
+ function shouldSkipCSRF(request, skipRoutes) {
80
+ const url = new URL(request.url);
81
+ const pathname = url.pathname;
82
+ if ([
83
+ "GET",
84
+ "HEAD",
85
+ "OPTIONS"
86
+ ].includes(request.method)) {
87
+ return true;
88
+ }
89
+ const shouldSkip = skipRoutes.some((route) => pathname.startsWith(route));
90
+ if (pathname.includes("/interaction/")) {
91
+ logger.debug("CSRF Debug:", {
92
+ url: pathname,
93
+ shouldSkip,
94
+ method: request.method
95
+ });
96
+ }
97
+ return shouldSkip;
98
+ }
99
+ __name(shouldSkipCSRF, "shouldSkipCSRF");
100
+ function isLoginEndpoint(request, loginEndpoints) {
101
+ const url = new URL(request.url);
102
+ return loginEndpoints.some((path) => url.pathname.includes(path));
103
+ }
104
+ __name(isLoginEndpoint, "isLoginEndpoint");
105
+ function buildSecurityHeaders(isProduction) {
106
+ const headers = {
107
+ "X-Content-Type-Options": "nosniff",
108
+ "X-Frame-Options": "DENY",
109
+ "X-XSS-Protection": "1; mode=block",
110
+ "Referrer-Policy": "strict-origin-when-cross-origin"
111
+ };
112
+ const cspDirectives = [
113
+ "default-src 'self'",
114
+ `script-src 'self' ${!isProduction ? "'unsafe-inline' 'unsafe-eval'" : ""} https://js.stripe.com https://checkout.razorpay.com https://unpkg.com`.trim(),
115
+ `style-src 'self' ${!isProduction ? "'unsafe-inline'" : ""} https://fonts.googleapis.com https://unpkg.com`.trim(),
116
+ "img-src 'self' data: https: blob: *.amazonaws.com *.algoshred.com",
117
+ // eslint-disable-next-line sonarjs/no-clear-text-protocols -- http://localhost:* is only used in development
118
+ `connect-src 'self' wss: https: ${!isProduction ? "http://localhost:*" : ""} https://*.algoshred.com https://api.stripe.com https://api.razorpay.com`.trim(),
119
+ "font-src 'self' https://fonts.gstatic.com",
120
+ "frame-src 'self' https://js.stripe.com https://hooks.stripe.com https://api.razorpay.com",
121
+ "frame-ancestors 'none'",
122
+ "base-uri 'self'",
123
+ "form-action 'self'"
124
+ ];
125
+ if (isProduction) {
126
+ cspDirectives.push("upgrade-insecure-requests");
127
+ }
128
+ headers["Content-Security-Policy"] = cspDirectives.join("; ");
129
+ return headers;
130
+ }
131
+ __name(buildSecurityHeaders, "buildSecurityHeaders");
132
+ function createSecurityPlugin(config) {
133
+ const finalConfig = {
134
+ csrfSkipRoutes: config?.csrfSkipRoutes || DEFAULT_CSRF_SKIP_ROUTES,
135
+ loginEndpoints: config?.loginEndpoints || DEFAULT_LOGIN_ENDPOINTS,
136
+ cspDirectives: config?.cspDirectives || {},
137
+ enableCSRF: config?.enableCSRF ?? false,
138
+ enableSessionSecurity: config?.enableSessionSecurity ?? false,
139
+ csrfTokenExpiry: config?.csrfTokenExpiry || 60 * 60 * 1e3,
140
+ helmetConfig: config?.helmetConfig || {
141
+ }
142
+ };
143
+ const nodeEnv = process.env["NODE_ENV"];
144
+ const isProduction = nodeEnv === "production";
145
+ const securityHeaders = buildSecurityHeaders(isProduction);
146
+ return new Elysia({
147
+ name: "security"
148
+ }).onAfterHandle(({ set }) => {
149
+ for (const [key, value] of Object.entries(securityHeaders)) {
150
+ set.headers[key] = value;
151
+ }
152
+ }).get("/api/csrf-token", ({ request, set }) => {
153
+ const sessionId = getSessionId(request);
154
+ if (!sessionId) {
155
+ set.status = 401;
156
+ return {
157
+ error: "No session found"
158
+ };
159
+ }
160
+ const csrfToken = generateCSRFToken();
161
+ const expires = Date.now() + finalConfig.csrfTokenExpiry;
162
+ if (!csrfTokens.has(sessionId)) {
163
+ pruneCSRFTokenStore(MAX_CSRF_TOKENS - 1);
164
+ }
165
+ if (!csrfTokens.has(sessionId) && csrfTokens.size >= MAX_CSRF_TOKENS) {
166
+ set.status = 429;
167
+ return {
168
+ error: "CSRF token capacity exceeded"
169
+ };
170
+ }
171
+ csrfTokens.set(sessionId, {
172
+ token: csrfToken,
173
+ expires
174
+ });
175
+ return {
176
+ csrfToken
177
+ };
178
+ }).onBeforeHandle(({ request, body, set }) => {
179
+ if (!finalConfig.enableCSRF) {
180
+ return void 0;
181
+ }
182
+ if (shouldSkipCSRF(request, finalConfig.csrfSkipRoutes)) {
183
+ return void 0;
184
+ }
185
+ const sessionId = getSessionId(request);
186
+ const providedToken = getCSRFTokenFromRequest(request, body);
187
+ if (!sessionId || !providedToken) {
188
+ set.status = 403;
189
+ return {
190
+ error: "CSRF token required",
191
+ code: "CSRF_TOKEN_MISSING"
192
+ };
193
+ }
194
+ const storedTokenData = csrfTokens.get(sessionId);
195
+ if (!storedTokenData || storedTokenData.expires < Date.now()) {
196
+ csrfTokens.delete(sessionId);
197
+ set.status = 403;
198
+ return {
199
+ error: "CSRF token expired",
200
+ code: "CSRF_TOKEN_EXPIRED"
201
+ };
202
+ }
203
+ if (!constantTimeCompare(providedToken, storedTokenData.token)) {
204
+ set.status = 403;
205
+ return {
206
+ error: "Invalid CSRF token",
207
+ code: "CSRF_TOKEN_INVALID"
208
+ };
209
+ }
210
+ return void 0;
211
+ }).onAfterHandle(({ request, set }) => {
212
+ if (!finalConfig.enableSessionSecurity) {
213
+ return;
214
+ }
215
+ const url = new URL(request.url);
216
+ if (url.pathname.includes("/interaction/") || url.pathname.includes("/oidc/")) {
217
+ set.headers["Cache-Control"] = "no-cache, no-store, must-revalidate";
218
+ set.headers["Pragma"] = "no-cache";
219
+ set.headers["Expires"] = "0";
220
+ }
221
+ if (isLoginEndpoint(request, finalConfig.loginEndpoints)) {
222
+ logger.debug("[Security] Login endpoint accessed", {
223
+ path: url.pathname
224
+ });
225
+ }
226
+ });
227
+ }
228
+ __name(createSecurityPlugin, "createSecurityPlugin");
229
+ function cleanupExpiredTokens() {
230
+ const now = Date.now();
231
+ for (const [sessionId, tokenData] of csrfTokens.entries()) {
232
+ if (tokenData.expires < now) {
233
+ csrfTokens.delete(sessionId);
234
+ }
235
+ }
236
+ }
237
+ __name(cleanupExpiredTokens, "cleanupExpiredTokens");
238
+ setInterval(() => {
239
+ cleanupExpiredTokens();
240
+ }, 10 * 60 * 1e3);
241
+ logger.debug("[Security] Security middleware module loaded");
242
+
243
+ export { cleanupExpiredTokens, createSecurityPlugin, middleware_exports };
244
+ //# sourceMappingURL=chunk-2HANKZZM.js.map
245
+ //# sourceMappingURL=chunk-2HANKZZM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware/index.ts","../src/middleware/security.ts"],"names":["csrfTokens","Map","MAX_CSRF_TOKENS","DEFAULT_CSRF_SKIP_ROUTES","DEFAULT_LOGIN_ENDPOINTS","generateCSRFToken","crypto","randomBytes","toString","constantTimeCompare","a","b","length","result","i","charCodeAt","getSessionId","request","cookieHeader","headers","get","cookies","split","reduce","acc","cookie","key","value","trim","getCSRFTokenFromRequest","body","headerToken","bodyToken","pruneCSRFTokenStore","maxEntries","cleanupExpiredTokens","size","oldestEntry","keys","next","done","delete","shouldSkipCSRF","skipRoutes","url","URL","pathname","includes","method","shouldSkip","some","route","startsWith","logger","debug","isLoginEndpoint","loginEndpoints","path","buildSecurityHeaders","isProduction","cspDirectives","push","join","createSecurityPlugin","config","finalConfig","csrfSkipRoutes","enableCSRF","enableSessionSecurity","csrfTokenExpiry","helmetConfig","nodeEnv","process","env","securityHeaders","Elysia","name","onAfterHandle","set","Object","entries","sessionId","status","error","csrfToken","expires","Date","now","has","token","onBeforeHandle","undefined","providedToken","code","storedTokenData","tokenData","setInterval"],"mappings":"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","file":"chunk-2HANKZZM.js","sourcesContent":["/**\n * Middleware Module\n *\n * Centralized middleware for Elysia applications.\n * Provides reusable, configurable middleware as Elysia plugins:\n * - Security (CSP, CSRF, session security)\n *\n * **Note:** Metrics middleware is exported from the observability module.\n *\n * @module middleware\n */\n\n// Export security middleware plugin\nexport { createSecurityPlugin, cleanupExpiredTokens } from './security.js';\n\n// Export types\nexport type { CSPDirectives, MetricsMiddlewareConfig, MiddlewareConfig, SecurityMiddlewareConfig } from './types.js';\n","/**\n * Security Middleware for Elysia\n *\n * Comprehensive security middleware for Elysia applications.\n * Provides application-level security features including:\n * - Security headers (CSP, X-Frame-Options, etc.)\n * - CSRF protection\n * - Session security\n *\n * **Note:** Rate limiting, DDoS protection, and infrastructure security\n * should be handled at the API Gateway level.\n *\n * @example\n * ```typescript\n * import { createSecurityPlugin } from '@burdenoff/be-sdk';\n *\n * const app = new Elysia()\n * .use(createSecurityPlugin({\n * csrfSkipRoutes: ['/graphql', '/webhook/'],\n * loginEndpoints: ['/auth/login', '/oidc/token'],\n * enableCSRF: true,\n * enableSessionSecurity: true,\n * }));\n * ```\n */\nimport crypto from 'node:crypto';\nimport { Elysia, type AnyElysia } from 'elysia';\n\nimport { logger } from '../logger/index.js';\nimport type { SecurityMiddlewareConfig } from './types.js';\n\n// CSRF Token storage (in production, use Redis or database)\nconst csrfTokens = new Map<string, { token: string; expires: number }>();\nconst MAX_CSRF_TOKENS = 100_000;\n\n/**\n * Default CSRF skip routes\n * These routes typically have alternative authentication or CSRF protection\n */\nconst DEFAULT_CSRF_SKIP_ROUTES = [\n '/graphql', // GraphQL has its own security\n '/webhook/', // Webhook endpoints\n '/upload/', // File upload endpoints\n '/oidc/', // OIDC provider handles its own CSRF\n '/interaction/', // OIDC interaction endpoints use OAuth state for CSRF protection\n];\n\n/**\n * Default login endpoint patterns\n */\nconst DEFAULT_LOGIN_ENDPOINTS = ['/interaction/', '/oidc/token', '/api/auth/login'];\n\n/**\n * Generate a cryptographically secure CSRF token\n */\nfunction generateCSRFToken(): string {\n return crypto.randomBytes(32).toString('hex');\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks\n */\nfunction constantTimeCompare(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n\n return result === 0;\n}\n\n/**\n * Get session ID from request cookies\n */\nfunction getSessionId(request: Request): string | null {\n const cookieHeader = request.headers.get('cookie');\n if (!cookieHeader) return null;\n\n const cookies = cookieHeader.split(';').reduce(\n (acc, cookie) => {\n const [key, value] = cookie.trim().split('=');\n if (key && value) {\n acc[key] = value;\n }\n return acc;\n },\n {} as Record<string, string>\n );\n\n return cookies['_session'] || null;\n}\n\n/**\n * Extract CSRF token from request\n */\nfunction getCSRFTokenFromRequest(request: Request, body: unknown): string | null {\n // Check X-CSRF-Token header\n const headerToken = request.headers.get('x-csrf-token');\n if (headerToken) {\n return headerToken;\n }\n\n // Check form body for _csrf field\n if (body && typeof body === 'object') {\n const bodyToken = (body as Record<string, unknown>)['_csrf'];\n if (bodyToken && typeof bodyToken === 'string') {\n return bodyToken;\n }\n }\n\n return null;\n}\n\nexport function clearCSRFTokenStoreForTesting(): void {\n csrfTokens.clear();\n}\n\nexport function getCSRFTokenStoreSize(): number {\n return csrfTokens.size;\n}\n\nexport function setCSRFTokenForTesting(sessionId: string, token: string, expires: number): void {\n csrfTokens.set(sessionId, { token, expires });\n}\n\nexport function pruneCSRFTokenStore(maxEntries: number = MAX_CSRF_TOKENS): void {\n cleanupExpiredTokens();\n\n while (csrfTokens.size > maxEntries) {\n const oldestEntry = csrfTokens.keys().next();\n if (oldestEntry.done) {\n break;\n }\n\n csrfTokens.delete(oldestEntry.value);\n }\n}\n\n/**\n * Check if CSRF validation should be skipped\n */\nfunction shouldSkipCSRF(request: Request, skipRoutes: string[]): boolean {\n const url = new URL(request.url);\n const pathname = url.pathname;\n\n // Skip for safe HTTP methods\n if (['GET', 'HEAD', 'OPTIONS'].includes(request.method)) {\n return true;\n }\n\n // Skip for configured routes\n const shouldSkip = skipRoutes.some((route) => pathname.startsWith(route));\n\n // Debug logging for interaction endpoints\n if (pathname.includes('/interaction/')) {\n logger.debug('CSRF Debug:', {\n url: pathname,\n shouldSkip,\n method: request.method,\n });\n }\n\n return shouldSkip;\n}\n\n/**\n * Check if this is a login endpoint\n */\nfunction isLoginEndpoint(request: Request, loginEndpoints: string[]): boolean {\n const url = new URL(request.url);\n return loginEndpoints.some((path) => url.pathname.includes(path));\n}\n\n/**\n * Build security headers based on environment\n */\nfunction buildSecurityHeaders(isProduction: boolean): Record<string, string> {\n const headers: Record<string, string> = {\n 'X-Content-Type-Options': 'nosniff',\n 'X-Frame-Options': 'DENY',\n 'X-XSS-Protection': '1; mode=block',\n 'Referrer-Policy': 'strict-origin-when-cross-origin',\n };\n\n // Build CSP directives\n const cspDirectives: string[] = [\n \"default-src 'self'\",\n `script-src 'self' ${!isProduction ? \"'unsafe-inline' 'unsafe-eval'\" : ''} https://js.stripe.com https://checkout.razorpay.com https://unpkg.com`.trim(),\n `style-src 'self' ${!isProduction ? \"'unsafe-inline'\" : ''} https://fonts.googleapis.com https://unpkg.com`.trim(),\n \"img-src 'self' data: https: blob: *.amazonaws.com *.algoshred.com\",\n // eslint-disable-next-line sonarjs/no-clear-text-protocols -- http://localhost:* is only used in development\n `connect-src 'self' wss: https: ${!isProduction ? 'http://localhost:*' : ''} https://*.algoshred.com https://api.stripe.com https://api.razorpay.com`.trim(),\n \"font-src 'self' https://fonts.gstatic.com\",\n \"frame-src 'self' https://js.stripe.com https://hooks.stripe.com https://api.razorpay.com\",\n \"frame-ancestors 'none'\",\n \"base-uri 'self'\",\n \"form-action 'self'\",\n ];\n\n if (isProduction) {\n cspDirectives.push('upgrade-insecure-requests');\n }\n\n headers['Content-Security-Policy'] = cspDirectives.join('; ');\n\n return headers;\n}\n\n/**\n * Create Elysia security plugin\n *\n * @param config Security configuration options\n * @returns Elysia plugin instance\n */\nexport function createSecurityPlugin(config?: SecurityMiddlewareConfig): AnyElysia {\n const finalConfig: Required<SecurityMiddlewareConfig> = {\n csrfSkipRoutes: config?.csrfSkipRoutes || DEFAULT_CSRF_SKIP_ROUTES,\n loginEndpoints: config?.loginEndpoints || DEFAULT_LOGIN_ENDPOINTS,\n cspDirectives: config?.cspDirectives || {},\n enableCSRF: config?.enableCSRF ?? false, // Disabled by default for GraphQL services\n enableSessionSecurity: config?.enableSessionSecurity ?? false,\n csrfTokenExpiry: config?.csrfTokenExpiry || 60 * 60 * 1000, // 1 hour\n helmetConfig: config?.helmetConfig || {\n crossOriginEmbedderPolicy: false,\n crossOriginResourcePolicy: false,\n },\n };\n\n const nodeEnv = process.env['NODE_ENV'];\n const isProduction = nodeEnv === 'production';\n const securityHeaders = buildSecurityHeaders(isProduction);\n\n return (\n new Elysia({ name: 'security' })\n // Add security headers to all responses\n .onAfterHandle(({ set }) => {\n for (const [key, value] of Object.entries(securityHeaders)) {\n set.headers[key] = value;\n }\n })\n // CSRF token generation endpoint\n .get('/api/csrf-token', ({ request, set }) => {\n const sessionId = getSessionId(request);\n\n if (!sessionId) {\n set.status = 401;\n return { error: 'No session found' };\n }\n\n const csrfToken = generateCSRFToken();\n const expires = Date.now() + finalConfig.csrfTokenExpiry;\n\n if (!csrfTokens.has(sessionId)) {\n pruneCSRFTokenStore(MAX_CSRF_TOKENS - 1);\n }\n\n if (!csrfTokens.has(sessionId) && csrfTokens.size >= MAX_CSRF_TOKENS) {\n set.status = 429;\n return { error: 'CSRF token capacity exceeded' };\n }\n\n csrfTokens.set(sessionId, { token: csrfToken, expires });\n\n return { csrfToken };\n })\n // CSRF validation for state-changing operations\n .onBeforeHandle(({ request, body, set }): { error: string; code: string } | undefined => {\n if (!finalConfig.enableCSRF) {\n return undefined;\n }\n\n // Skip CSRF for safe methods and specific routes\n if (shouldSkipCSRF(request, finalConfig.csrfSkipRoutes)) {\n return undefined;\n }\n\n const sessionId = getSessionId(request);\n const providedToken = getCSRFTokenFromRequest(request, body);\n\n if (!sessionId || !providedToken) {\n set.status = 403;\n return {\n error: 'CSRF token required',\n code: 'CSRF_TOKEN_MISSING',\n };\n }\n\n const storedTokenData = csrfTokens.get(sessionId);\n\n if (!storedTokenData || storedTokenData.expires < Date.now()) {\n csrfTokens.delete(sessionId);\n set.status = 403;\n return {\n error: 'CSRF token expired',\n code: 'CSRF_TOKEN_EXPIRED',\n };\n }\n\n if (!constantTimeCompare(providedToken, storedTokenData.token)) {\n set.status = 403;\n return {\n error: 'Invalid CSRF token',\n code: 'CSRF_TOKEN_INVALID',\n };\n }\n\n return undefined;\n })\n // Session security headers for sensitive endpoints\n .onAfterHandle(({ request, set }) => {\n if (!finalConfig.enableSessionSecurity) {\n return;\n }\n\n const url = new URL(request.url);\n if (url.pathname.includes('/interaction/') || url.pathname.includes('/oidc/')) {\n set.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate';\n set.headers['Pragma'] = 'no-cache';\n set.headers['Expires'] = '0';\n }\n\n // Log successful login endpoints for audit\n if (isLoginEndpoint(request, finalConfig.loginEndpoints)) {\n logger.debug('[Security] Login endpoint accessed', {\n path: url.pathname,\n });\n }\n })\n );\n}\n\n/**\n * Clean up expired CSRF tokens (should be called periodically)\n */\nexport function cleanupExpiredTokens(): void {\n const now = Date.now();\n for (const [sessionId, tokenData] of csrfTokens.entries()) {\n if (tokenData.expires < now) {\n csrfTokens.delete(sessionId);\n }\n }\n}\n\n/**\n * Cleanup expired CSRF tokens every 10 minutes\n * This prevents memory leaks from accumulating expired tokens\n */\nsetInterval(\n () => {\n cleanupExpiredTokens();\n },\n 10 * 60 * 1000\n);\n\n// Log when security middleware is loaded\nlogger.debug('[Security] Security middleware module loaded');\n"]}