@digilogiclabs/platform-core 1.3.0 → 1.5.0
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.
- package/README.md +79 -3
- package/dist/{ConsoleEmail-hUDFsKoA.d.mts → ConsoleEmail-ubSVWgTa.d.mts} +187 -1
- package/dist/{ConsoleEmail-hUDFsKoA.d.ts → ConsoleEmail-ubSVWgTa.d.ts} +187 -1
- package/dist/index.d.mts +1583 -130
- package/dist/index.d.ts +1583 -130
- package/dist/index.js +1978 -169
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1922 -162
- package/dist/index.mjs.map +1 -1
- package/dist/migrate.js +3 -2
- package/dist/migrate.js.map +1 -1
- package/dist/security-headers.d.mts +75 -0
- package/dist/security-headers.d.ts +75 -0
- package/dist/security-headers.js +137 -0
- package/dist/security-headers.js.map +1 -0
- package/dist/security-headers.mjs +111 -0
- package/dist/security-headers.mjs.map +1 -0
- package/dist/testing.d.mts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +196 -15
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +200 -14
- package/dist/testing.mjs.map +1 -1
- package/package.json +16 -11
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/security-headers.ts"],"sourcesContent":["/**\n * Shared Security Headers Utility\n * Generates consistent security headers for all Next.js apps.\n * Zero heavy dependencies — pure utility function.\n */\n\n// ═══════════════════════════════════════════════════════════════\n// TYPES\n// ═══════════════════════════════════════════════════════════════\n\nexport interface SecurityHeadersConfig {\n /** Enable Content-Security-Policy (default: true) */\n csp?: boolean;\n /** Additional allowed script-src domains */\n cspScriptSrc?: string[];\n /** Additional allowed connect-src domains */\n cspConnectSrc?: string[];\n /** Additional allowed frame-src domains */\n cspFrameSrc?: string[];\n /** Additional allowed style-src domains */\n cspStyleSrc?: string[];\n /** Additional allowed img-src domains */\n cspImgSrc?: string[];\n /** X-Frame-Options value (default: 'DENY') */\n frameOptions?: \"DENY\" | \"SAMEORIGIN\";\n /** Enable HSTS in production (default: true) */\n hsts?: boolean;\n /** HSTS max-age in seconds (default: 31536000 = 1 year) */\n hstsMaxAge?: number;\n /** Whether this is a production build (default: auto-detect from NODE_ENV) */\n isProduction?: boolean;\n}\n\nexport interface NextHeaderEntry {\n source: string;\n headers: Array<{ key: string; value: string }>;\n}\n\n// ═══════════════════════════════════════════════════════════════\n// PRESETS\n// ═══════════════════════════════════════════════════════════════\n\nexport const SecurityHeaderPresets = {\n /** Minimal: basic headers only, no CSP */\n minimal: {\n csp: false,\n hsts: false,\n } satisfies SecurityHeadersConfig,\n\n /** Standard: full CSP + HSTS for most apps */\n standard: {\n csp: true,\n hsts: true,\n frameOptions: \"DENY\",\n } satisfies SecurityHeadersConfig,\n\n /** Strict: deny all permissions, strict CSP, no frame embedding */\n strict: {\n csp: true,\n hsts: true,\n hstsMaxAge: 63072000, // 2 years\n frameOptions: \"DENY\",\n } satisfies SecurityHeadersConfig,\n} as const;\n\n// ═══════════════════════════════════════════════════════════════\n// MAIN FUNCTION\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Generate security headers array compatible with Next.js `headers()` config.\n *\n * Usage in next.config.mjs:\n * ```js\n * const { generateSecurityHeaders } = require('@digilogiclabs/platform-core');\n *\n * module.exports = {\n * async headers() {\n * return generateSecurityHeaders({\n * isProduction: process.env.NODE_ENV === 'production',\n * cspScriptSrc: ['https://js.stripe.com'],\n * cspConnectSrc: ['https://api.stripe.com'],\n * });\n * },\n * };\n * ```\n */\nexport function generateSecurityHeaders(\n config: SecurityHeadersConfig = {},\n): NextHeaderEntry[] {\n const isProduction =\n config.isProduction ?? process.env.NODE_ENV === \"production\";\n const frameOptions = config.frameOptions ?? \"DENY\";\n const enableCsp = config.csp ?? true;\n const enableHsts = config.hsts ?? true;\n const hstsMaxAge = config.hstsMaxAge ?? 31536000;\n\n // Base headers applied to all routes in all environments\n const baseHeaders: Array<{ key: string; value: string }> = [\n { key: \"X-Frame-Options\", value: frameOptions },\n { key: \"X-Content-Type-Options\", value: \"nosniff\" },\n // Modern browsers use CSP, not XSS-Protection. Value '0' disables the\n // legacy filter which can itself introduce vulnerabilities.\n { key: \"X-XSS-Protection\", value: \"0\" },\n {\n key: \"Referrer-Policy\",\n value: \"strict-origin-when-cross-origin\",\n },\n {\n key: \"Permissions-Policy\",\n value: \"camera=(), microphone=(), geolocation=()\",\n },\n ];\n\n const entries: NextHeaderEntry[] = [\n { source: \"/:path*\", headers: baseHeaders },\n ];\n\n // Production-only headers\n if (isProduction) {\n const prodHeaders: Array<{ key: string; value: string }> = [];\n\n // HSTS\n if (enableHsts) {\n prodHeaders.push({\n key: \"Strict-Transport-Security\",\n value: `max-age=${hstsMaxAge}; includeSubDomains`,\n });\n }\n\n // Content-Security-Policy\n if (enableCsp) {\n const csp = buildCsp(config);\n prodHeaders.push({ key: \"Content-Security-Policy\", value: csp });\n }\n\n if (prodHeaders.length > 0) {\n entries.push({ source: \"/:path*\", headers: prodHeaders });\n }\n }\n\n return entries;\n}\n\n// ═══════════════════════════════════════════════════════════════\n// CSP BUILDER\n// ═══════════════════════════════════════════════════════════════\n\nfunction buildCsp(config: SecurityHeadersConfig): string {\n const scriptSrc = [\n \"'self'\",\n \"'unsafe-inline'\",\n \"'unsafe-eval'\",\n ...(config.cspScriptSrc ?? []),\n ];\n\n const styleSrc = [\n \"'self'\",\n \"'unsafe-inline'\",\n \"https://fonts.googleapis.com\",\n ...(config.cspStyleSrc ?? []),\n ];\n\n const imgSrc = [\n \"'self'\",\n \"data:\",\n \"https:\",\n \"blob:\",\n ...(config.cspImgSrc ?? []),\n ];\n\n const fontSrc = [\"'self'\", \"data:\", \"https://fonts.gstatic.com\"];\n\n const connectSrc = [\"'self'\", ...(config.cspConnectSrc ?? [])];\n\n const frameSrc = [...(config.cspFrameSrc ?? [])];\n\n const directives = [\n `default-src 'self'`,\n `script-src ${scriptSrc.join(\" \")}`,\n `style-src ${styleSrc.join(\" \")}`,\n `img-src ${imgSrc.join(\" \")}`,\n `font-src ${fontSrc.join(\" \")}`,\n `connect-src ${connectSrc.join(\" \")}`,\n ];\n\n if (frameSrc.length > 0) {\n directives.push(`frame-src ${frameSrc.join(\" \")}`);\n }\n\n directives.push(\n `object-src 'none'`,\n `base-uri 'self'`,\n `form-action 'self'`,\n `frame-ancestors 'none'`,\n );\n\n return directives.join(\"; \");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0CO,IAAM,wBAAwB;AAAA;AAAA,EAEnC,SAAS;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AAAA;AAAA,EAGA,UAAU;AAAA,IACR,KAAK;AAAA,IACL,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA;AAAA,EAGA,QAAQ;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA;AAAA,IACZ,cAAc;AAAA,EAChB;AACF;AAwBO,SAAS,wBACd,SAAgC,CAAC,GACd;AACnB,QAAM,eACJ,OAAO,gBAAgB,QAAQ,IAAI,aAAa;AAClD,QAAM,eAAe,OAAO,gBAAgB;AAC5C,QAAM,YAAY,OAAO,OAAO;AAChC,QAAM,aAAa,OAAO,QAAQ;AAClC,QAAM,aAAa,OAAO,cAAc;AAGxC,QAAM,cAAqD;AAAA,IACzD,EAAE,KAAK,mBAAmB,OAAO,aAAa;AAAA,IAC9C,EAAE,KAAK,0BAA0B,OAAO,UAAU;AAAA;AAAA;AAAA,IAGlD,EAAE,KAAK,oBAAoB,OAAO,IAAI;AAAA,IACtC;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,UAA6B;AAAA,IACjC,EAAE,QAAQ,WAAW,SAAS,YAAY;AAAA,EAC5C;AAGA,MAAI,cAAc;AAChB,UAAM,cAAqD,CAAC;AAG5D,QAAI,YAAY;AACd,kBAAY,KAAK;AAAA,QACf,KAAK;AAAA,QACL,OAAO,WAAW,UAAU;AAAA,MAC9B,CAAC;AAAA,IACH;AAGA,QAAI,WAAW;AACb,YAAM,MAAM,SAAS,MAAM;AAC3B,kBAAY,KAAK,EAAE,KAAK,2BAA2B,OAAO,IAAI,CAAC;AAAA,IACjE;AAEA,QAAI,YAAY,SAAS,GAAG;AAC1B,cAAQ,KAAK,EAAE,QAAQ,WAAW,SAAS,YAAY,CAAC;AAAA,IAC1D;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,SAAS,QAAuC;AACvD,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,OAAO,gBAAgB,CAAC;AAAA,EAC9B;AAEA,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,OAAO,eAAe,CAAC;AAAA,EAC7B;AAEA,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,OAAO,aAAa,CAAC;AAAA,EAC3B;AAEA,QAAM,UAAU,CAAC,UAAU,SAAS,2BAA2B;AAE/D,QAAM,aAAa,CAAC,UAAU,GAAI,OAAO,iBAAiB,CAAC,CAAE;AAE7D,QAAM,WAAW,CAAC,GAAI,OAAO,eAAe,CAAC,CAAE;AAE/C,QAAM,aAAa;AAAA,IACjB;AAAA,IACA,cAAc,UAAU,KAAK,GAAG,CAAC;AAAA,IACjC,aAAa,SAAS,KAAK,GAAG,CAAC;AAAA,IAC/B,WAAW,OAAO,KAAK,GAAG,CAAC;AAAA,IAC3B,YAAY,QAAQ,KAAK,GAAG,CAAC;AAAA,IAC7B,eAAe,WAAW,KAAK,GAAG,CAAC;AAAA,EACrC;AAEA,MAAI,SAAS,SAAS,GAAG;AACvB,eAAW,KAAK,aAAa,SAAS,KAAK,GAAG,CAAC,EAAE;AAAA,EACnD;AAEA,aAAW;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO,WAAW,KAAK,IAAI;AAC7B;","names":[]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// src/security-headers.ts
|
|
2
|
+
var SecurityHeaderPresets = {
|
|
3
|
+
/** Minimal: basic headers only, no CSP */
|
|
4
|
+
minimal: {
|
|
5
|
+
csp: false,
|
|
6
|
+
hsts: false
|
|
7
|
+
},
|
|
8
|
+
/** Standard: full CSP + HSTS for most apps */
|
|
9
|
+
standard: {
|
|
10
|
+
csp: true,
|
|
11
|
+
hsts: true,
|
|
12
|
+
frameOptions: "DENY"
|
|
13
|
+
},
|
|
14
|
+
/** Strict: deny all permissions, strict CSP, no frame embedding */
|
|
15
|
+
strict: {
|
|
16
|
+
csp: true,
|
|
17
|
+
hsts: true,
|
|
18
|
+
hstsMaxAge: 63072e3,
|
|
19
|
+
// 2 years
|
|
20
|
+
frameOptions: "DENY"
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
function generateSecurityHeaders(config = {}) {
|
|
24
|
+
const isProduction = config.isProduction ?? process.env.NODE_ENV === "production";
|
|
25
|
+
const frameOptions = config.frameOptions ?? "DENY";
|
|
26
|
+
const enableCsp = config.csp ?? true;
|
|
27
|
+
const enableHsts = config.hsts ?? true;
|
|
28
|
+
const hstsMaxAge = config.hstsMaxAge ?? 31536e3;
|
|
29
|
+
const baseHeaders = [
|
|
30
|
+
{ key: "X-Frame-Options", value: frameOptions },
|
|
31
|
+
{ key: "X-Content-Type-Options", value: "nosniff" },
|
|
32
|
+
// Modern browsers use CSP, not XSS-Protection. Value '0' disables the
|
|
33
|
+
// legacy filter which can itself introduce vulnerabilities.
|
|
34
|
+
{ key: "X-XSS-Protection", value: "0" },
|
|
35
|
+
{
|
|
36
|
+
key: "Referrer-Policy",
|
|
37
|
+
value: "strict-origin-when-cross-origin"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
key: "Permissions-Policy",
|
|
41
|
+
value: "camera=(), microphone=(), geolocation=()"
|
|
42
|
+
}
|
|
43
|
+
];
|
|
44
|
+
const entries = [
|
|
45
|
+
{ source: "/:path*", headers: baseHeaders }
|
|
46
|
+
];
|
|
47
|
+
if (isProduction) {
|
|
48
|
+
const prodHeaders = [];
|
|
49
|
+
if (enableHsts) {
|
|
50
|
+
prodHeaders.push({
|
|
51
|
+
key: "Strict-Transport-Security",
|
|
52
|
+
value: `max-age=${hstsMaxAge}; includeSubDomains`
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (enableCsp) {
|
|
56
|
+
const csp = buildCsp(config);
|
|
57
|
+
prodHeaders.push({ key: "Content-Security-Policy", value: csp });
|
|
58
|
+
}
|
|
59
|
+
if (prodHeaders.length > 0) {
|
|
60
|
+
entries.push({ source: "/:path*", headers: prodHeaders });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return entries;
|
|
64
|
+
}
|
|
65
|
+
function buildCsp(config) {
|
|
66
|
+
const scriptSrc = [
|
|
67
|
+
"'self'",
|
|
68
|
+
"'unsafe-inline'",
|
|
69
|
+
"'unsafe-eval'",
|
|
70
|
+
...config.cspScriptSrc ?? []
|
|
71
|
+
];
|
|
72
|
+
const styleSrc = [
|
|
73
|
+
"'self'",
|
|
74
|
+
"'unsafe-inline'",
|
|
75
|
+
"https://fonts.googleapis.com",
|
|
76
|
+
...config.cspStyleSrc ?? []
|
|
77
|
+
];
|
|
78
|
+
const imgSrc = [
|
|
79
|
+
"'self'",
|
|
80
|
+
"data:",
|
|
81
|
+
"https:",
|
|
82
|
+
"blob:",
|
|
83
|
+
...config.cspImgSrc ?? []
|
|
84
|
+
];
|
|
85
|
+
const fontSrc = ["'self'", "data:", "https://fonts.gstatic.com"];
|
|
86
|
+
const connectSrc = ["'self'", ...config.cspConnectSrc ?? []];
|
|
87
|
+
const frameSrc = [...config.cspFrameSrc ?? []];
|
|
88
|
+
const directives = [
|
|
89
|
+
`default-src 'self'`,
|
|
90
|
+
`script-src ${scriptSrc.join(" ")}`,
|
|
91
|
+
`style-src ${styleSrc.join(" ")}`,
|
|
92
|
+
`img-src ${imgSrc.join(" ")}`,
|
|
93
|
+
`font-src ${fontSrc.join(" ")}`,
|
|
94
|
+
`connect-src ${connectSrc.join(" ")}`
|
|
95
|
+
];
|
|
96
|
+
if (frameSrc.length > 0) {
|
|
97
|
+
directives.push(`frame-src ${frameSrc.join(" ")}`);
|
|
98
|
+
}
|
|
99
|
+
directives.push(
|
|
100
|
+
`object-src 'none'`,
|
|
101
|
+
`base-uri 'self'`,
|
|
102
|
+
`form-action 'self'`,
|
|
103
|
+
`frame-ancestors 'none'`
|
|
104
|
+
);
|
|
105
|
+
return directives.join("; ");
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
SecurityHeaderPresets,
|
|
109
|
+
generateSecurityHeaders
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=security-headers.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/security-headers.ts"],"sourcesContent":["/**\n * Shared Security Headers Utility\n * Generates consistent security headers for all Next.js apps.\n * Zero heavy dependencies — pure utility function.\n */\n\n// ═══════════════════════════════════════════════════════════════\n// TYPES\n// ═══════════════════════════════════════════════════════════════\n\nexport interface SecurityHeadersConfig {\n /** Enable Content-Security-Policy (default: true) */\n csp?: boolean;\n /** Additional allowed script-src domains */\n cspScriptSrc?: string[];\n /** Additional allowed connect-src domains */\n cspConnectSrc?: string[];\n /** Additional allowed frame-src domains */\n cspFrameSrc?: string[];\n /** Additional allowed style-src domains */\n cspStyleSrc?: string[];\n /** Additional allowed img-src domains */\n cspImgSrc?: string[];\n /** X-Frame-Options value (default: 'DENY') */\n frameOptions?: \"DENY\" | \"SAMEORIGIN\";\n /** Enable HSTS in production (default: true) */\n hsts?: boolean;\n /** HSTS max-age in seconds (default: 31536000 = 1 year) */\n hstsMaxAge?: number;\n /** Whether this is a production build (default: auto-detect from NODE_ENV) */\n isProduction?: boolean;\n}\n\nexport interface NextHeaderEntry {\n source: string;\n headers: Array<{ key: string; value: string }>;\n}\n\n// ═══════════════════════════════════════════════════════════════\n// PRESETS\n// ═══════════════════════════════════════════════════════════════\n\nexport const SecurityHeaderPresets = {\n /** Minimal: basic headers only, no CSP */\n minimal: {\n csp: false,\n hsts: false,\n } satisfies SecurityHeadersConfig,\n\n /** Standard: full CSP + HSTS for most apps */\n standard: {\n csp: true,\n hsts: true,\n frameOptions: \"DENY\",\n } satisfies SecurityHeadersConfig,\n\n /** Strict: deny all permissions, strict CSP, no frame embedding */\n strict: {\n csp: true,\n hsts: true,\n hstsMaxAge: 63072000, // 2 years\n frameOptions: \"DENY\",\n } satisfies SecurityHeadersConfig,\n} as const;\n\n// ═══════════════════════════════════════════════════════════════\n// MAIN FUNCTION\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Generate security headers array compatible with Next.js `headers()` config.\n *\n * Usage in next.config.mjs:\n * ```js\n * const { generateSecurityHeaders } = require('@digilogiclabs/platform-core');\n *\n * module.exports = {\n * async headers() {\n * return generateSecurityHeaders({\n * isProduction: process.env.NODE_ENV === 'production',\n * cspScriptSrc: ['https://js.stripe.com'],\n * cspConnectSrc: ['https://api.stripe.com'],\n * });\n * },\n * };\n * ```\n */\nexport function generateSecurityHeaders(\n config: SecurityHeadersConfig = {},\n): NextHeaderEntry[] {\n const isProduction =\n config.isProduction ?? process.env.NODE_ENV === \"production\";\n const frameOptions = config.frameOptions ?? \"DENY\";\n const enableCsp = config.csp ?? true;\n const enableHsts = config.hsts ?? true;\n const hstsMaxAge = config.hstsMaxAge ?? 31536000;\n\n // Base headers applied to all routes in all environments\n const baseHeaders: Array<{ key: string; value: string }> = [\n { key: \"X-Frame-Options\", value: frameOptions },\n { key: \"X-Content-Type-Options\", value: \"nosniff\" },\n // Modern browsers use CSP, not XSS-Protection. Value '0' disables the\n // legacy filter which can itself introduce vulnerabilities.\n { key: \"X-XSS-Protection\", value: \"0\" },\n {\n key: \"Referrer-Policy\",\n value: \"strict-origin-when-cross-origin\",\n },\n {\n key: \"Permissions-Policy\",\n value: \"camera=(), microphone=(), geolocation=()\",\n },\n ];\n\n const entries: NextHeaderEntry[] = [\n { source: \"/:path*\", headers: baseHeaders },\n ];\n\n // Production-only headers\n if (isProduction) {\n const prodHeaders: Array<{ key: string; value: string }> = [];\n\n // HSTS\n if (enableHsts) {\n prodHeaders.push({\n key: \"Strict-Transport-Security\",\n value: `max-age=${hstsMaxAge}; includeSubDomains`,\n });\n }\n\n // Content-Security-Policy\n if (enableCsp) {\n const csp = buildCsp(config);\n prodHeaders.push({ key: \"Content-Security-Policy\", value: csp });\n }\n\n if (prodHeaders.length > 0) {\n entries.push({ source: \"/:path*\", headers: prodHeaders });\n }\n }\n\n return entries;\n}\n\n// ═══════════════════════════════════════════════════════════════\n// CSP BUILDER\n// ═══════════════════════════════════════════════════════════════\n\nfunction buildCsp(config: SecurityHeadersConfig): string {\n const scriptSrc = [\n \"'self'\",\n \"'unsafe-inline'\",\n \"'unsafe-eval'\",\n ...(config.cspScriptSrc ?? []),\n ];\n\n const styleSrc = [\n \"'self'\",\n \"'unsafe-inline'\",\n \"https://fonts.googleapis.com\",\n ...(config.cspStyleSrc ?? []),\n ];\n\n const imgSrc = [\n \"'self'\",\n \"data:\",\n \"https:\",\n \"blob:\",\n ...(config.cspImgSrc ?? []),\n ];\n\n const fontSrc = [\"'self'\", \"data:\", \"https://fonts.gstatic.com\"];\n\n const connectSrc = [\"'self'\", ...(config.cspConnectSrc ?? [])];\n\n const frameSrc = [...(config.cspFrameSrc ?? [])];\n\n const directives = [\n `default-src 'self'`,\n `script-src ${scriptSrc.join(\" \")}`,\n `style-src ${styleSrc.join(\" \")}`,\n `img-src ${imgSrc.join(\" \")}`,\n `font-src ${fontSrc.join(\" \")}`,\n `connect-src ${connectSrc.join(\" \")}`,\n ];\n\n if (frameSrc.length > 0) {\n directives.push(`frame-src ${frameSrc.join(\" \")}`);\n }\n\n directives.push(\n `object-src 'none'`,\n `base-uri 'self'`,\n `form-action 'self'`,\n `frame-ancestors 'none'`,\n );\n\n return directives.join(\"; \");\n}\n"],"mappings":";AA0CO,IAAM,wBAAwB;AAAA;AAAA,EAEnC,SAAS;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AAAA;AAAA,EAGA,UAAU;AAAA,IACR,KAAK;AAAA,IACL,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA;AAAA,EAGA,QAAQ;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA;AAAA,IACZ,cAAc;AAAA,EAChB;AACF;AAwBO,SAAS,wBACd,SAAgC,CAAC,GACd;AACnB,QAAM,eACJ,OAAO,gBAAgB,QAAQ,IAAI,aAAa;AAClD,QAAM,eAAe,OAAO,gBAAgB;AAC5C,QAAM,YAAY,OAAO,OAAO;AAChC,QAAM,aAAa,OAAO,QAAQ;AAClC,QAAM,aAAa,OAAO,cAAc;AAGxC,QAAM,cAAqD;AAAA,IACzD,EAAE,KAAK,mBAAmB,OAAO,aAAa;AAAA,IAC9C,EAAE,KAAK,0BAA0B,OAAO,UAAU;AAAA;AAAA;AAAA,IAGlD,EAAE,KAAK,oBAAoB,OAAO,IAAI;AAAA,IACtC;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,UAA6B;AAAA,IACjC,EAAE,QAAQ,WAAW,SAAS,YAAY;AAAA,EAC5C;AAGA,MAAI,cAAc;AAChB,UAAM,cAAqD,CAAC;AAG5D,QAAI,YAAY;AACd,kBAAY,KAAK;AAAA,QACf,KAAK;AAAA,QACL,OAAO,WAAW,UAAU;AAAA,MAC9B,CAAC;AAAA,IACH;AAGA,QAAI,WAAW;AACb,YAAM,MAAM,SAAS,MAAM;AAC3B,kBAAY,KAAK,EAAE,KAAK,2BAA2B,OAAO,IAAI,CAAC;AAAA,IACjE;AAEA,QAAI,YAAY,SAAS,GAAG;AAC1B,cAAQ,KAAK,EAAE,QAAQ,WAAW,SAAS,YAAY,CAAC;AAAA,IAC1D;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,SAAS,QAAuC;AACvD,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,OAAO,gBAAgB,CAAC;AAAA,EAC9B;AAEA,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,OAAO,eAAe,CAAC;AAAA,EAC7B;AAEA,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,OAAO,aAAa,CAAC;AAAA,EAC3B;AAEA,QAAM,UAAU,CAAC,UAAU,SAAS,2BAA2B;AAE/D,QAAM,aAAa,CAAC,UAAU,GAAI,OAAO,iBAAiB,CAAC,CAAE;AAE7D,QAAM,WAAW,CAAC,GAAI,OAAO,eAAe,CAAC,CAAE;AAE/C,QAAM,aAAa;AAAA,IACjB;AAAA,IACA,cAAc,UAAU,KAAK,GAAG,CAAC;AAAA,IACjC,aAAa,SAAS,KAAK,GAAG,CAAC;AAAA,IAC/B,WAAW,OAAO,KAAK,GAAG,CAAC;AAAA,IAC3B,YAAY,QAAQ,KAAK,GAAG,CAAC;AAAA,IAC7B,eAAe,WAAW,KAAK,GAAG,CAAC;AAAA,EACrC;AAEA,MAAI,SAAS,SAAS,GAAG;AACvB,eAAW,KAAK,aAAa,SAAS,KAAK,GAAG,CAAC,EAAE;AAAA,EACnD;AAEA,aAAW;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO,WAAW,KAAK,IAAI;AAC7B;","names":[]}
|
package/dist/testing.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { I as IPlatform, M as MemoryDatabase, a as MemoryCache, b as MemoryStorage, c as MemoryEmail, d as MemoryQueue, e as IDatabase } from './ConsoleEmail-
|
|
2
|
-
export { C as ConsoleEmail, h as ConsoleLogger, t as EmailMessage, E as EnvSecrets, l as ICache, n as IEmail, p as ILogger, q as IMetrics, k as IQueryBuilder, o as IQueue, r as ISecrets, m as IStorage, J as Job, s as JobOptions, i as MemoryMetrics, f as MemorySecrets, N as NoopLogger, j as NoopMetrics, Q as QueryResult, S as StorageFile, g as createPlatform } from './ConsoleEmail-
|
|
1
|
+
import { I as IPlatform, M as MemoryDatabase, a as MemoryCache, b as MemoryStorage, c as MemoryEmail, d as MemoryQueue, e as IDatabase } from './ConsoleEmail-ubSVWgTa.mjs';
|
|
2
|
+
export { C as ConsoleEmail, h as ConsoleLogger, t as EmailMessage, E as EnvSecrets, l as ICache, n as IEmail, p as ILogger, q as IMetrics, k as IQueryBuilder, o as IQueue, r as ISecrets, m as IStorage, J as Job, s as JobOptions, i as MemoryMetrics, f as MemorySecrets, N as NoopLogger, j as NoopMetrics, Q as QueryResult, S as StorageFile, g as createPlatform } from './ConsoleEmail-ubSVWgTa.mjs';
|
|
3
3
|
import 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { I as IPlatform, M as MemoryDatabase, a as MemoryCache, b as MemoryStorage, c as MemoryEmail, d as MemoryQueue, e as IDatabase } from './ConsoleEmail-
|
|
2
|
-
export { C as ConsoleEmail, h as ConsoleLogger, t as EmailMessage, E as EnvSecrets, l as ICache, n as IEmail, p as ILogger, q as IMetrics, k as IQueryBuilder, o as IQueue, r as ISecrets, m as IStorage, J as Job, s as JobOptions, i as MemoryMetrics, f as MemorySecrets, N as NoopLogger, j as NoopMetrics, Q as QueryResult, S as StorageFile, g as createPlatform } from './ConsoleEmail-
|
|
1
|
+
import { I as IPlatform, M as MemoryDatabase, a as MemoryCache, b as MemoryStorage, c as MemoryEmail, d as MemoryQueue, e as IDatabase } from './ConsoleEmail-ubSVWgTa.js';
|
|
2
|
+
export { C as ConsoleEmail, h as ConsoleLogger, t as EmailMessage, E as EnvSecrets, l as ICache, n as IEmail, p as ILogger, q as IMetrics, k as IQueryBuilder, o as IQueue, r as ISecrets, m as IStorage, J as Job, s as JobOptions, i as MemoryMetrics, f as MemorySecrets, N as NoopLogger, j as NoopMetrics, Q as QueryResult, S as StorageFile, g as createPlatform } from './ConsoleEmail-ubSVWgTa.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/testing.js
CHANGED
|
@@ -363,10 +363,11 @@ var init_IAI = __esm({
|
|
|
363
363
|
});
|
|
364
364
|
|
|
365
365
|
// src/interfaces/IRAG.ts
|
|
366
|
-
var ChunkingPresets, MemoryRAG;
|
|
366
|
+
var import_crypto6, ChunkingPresets, MemoryRAG;
|
|
367
367
|
var init_IRAG = __esm({
|
|
368
368
|
"src/interfaces/IRAG.ts"() {
|
|
369
369
|
"use strict";
|
|
370
|
+
import_crypto6 = require("crypto");
|
|
370
371
|
ChunkingPresets = {
|
|
371
372
|
default: {
|
|
372
373
|
strategy: "recursive",
|
|
@@ -492,7 +493,7 @@ var init_IRAG = __esm({
|
|
|
492
493
|
}
|
|
493
494
|
async ingestOne(collection, document, options) {
|
|
494
495
|
const startTime = Date.now();
|
|
495
|
-
const docId = `doc_${Date.now()}_${
|
|
496
|
+
const docId = `doc_${Date.now()}_${(0, import_crypto6.randomBytes)(4).toString("hex")}`;
|
|
496
497
|
const now = /* @__PURE__ */ new Date();
|
|
497
498
|
try {
|
|
498
499
|
const col = await this.getCollection(collection);
|
|
@@ -1399,6 +1400,7 @@ var MemoryEmail = class {
|
|
|
1399
1400
|
};
|
|
1400
1401
|
|
|
1401
1402
|
// src/interfaces/IQueue.ts
|
|
1403
|
+
var import_crypto = require("crypto");
|
|
1402
1404
|
function calculateBackoff(attempt, options) {
|
|
1403
1405
|
if (options.type === "fixed") {
|
|
1404
1406
|
return options.delay;
|
|
@@ -1409,19 +1411,20 @@ function calculateBackoff(attempt, options) {
|
|
|
1409
1411
|
}
|
|
1410
1412
|
function generateJobId() {
|
|
1411
1413
|
const timestamp = Date.now().toString(36);
|
|
1412
|
-
const random =
|
|
1414
|
+
const random = (0, import_crypto.randomBytes)(4).toString("hex");
|
|
1413
1415
|
return `job_${timestamp}_${random}`;
|
|
1414
1416
|
}
|
|
1415
1417
|
|
|
1416
1418
|
// src/context/CorrelationContext.ts
|
|
1417
1419
|
var import_async_hooks = require("async_hooks");
|
|
1420
|
+
var import_crypto2 = require("crypto");
|
|
1418
1421
|
var CorrelationContextManager = class {
|
|
1419
1422
|
storage = new import_async_hooks.AsyncLocalStorage();
|
|
1420
1423
|
idGenerator;
|
|
1421
1424
|
constructor() {
|
|
1422
1425
|
this.idGenerator = () => {
|
|
1423
1426
|
const timestamp = Date.now().toString(36);
|
|
1424
|
-
const random =
|
|
1427
|
+
const random = (0, import_crypto2.randomBytes)(4).toString("hex");
|
|
1425
1428
|
return `${timestamp}-${random}`;
|
|
1426
1429
|
};
|
|
1427
1430
|
}
|
|
@@ -2027,10 +2030,11 @@ var MemoryQueue = class {
|
|
|
2027
2030
|
};
|
|
2028
2031
|
|
|
2029
2032
|
// src/adapters/console/ConsoleEmail.ts
|
|
2033
|
+
var import_crypto3 = require("crypto");
|
|
2030
2034
|
var ConsoleEmail = class {
|
|
2031
2035
|
sentEmails = [];
|
|
2032
2036
|
async send(message) {
|
|
2033
|
-
const id = `console_${Date.now()}_${
|
|
2037
|
+
const id = `console_${Date.now()}_${(0, import_crypto3.randomBytes)(4).toString("hex")}`;
|
|
2034
2038
|
console.log("\n" + "=".repeat(60));
|
|
2035
2039
|
console.log("\u{1F4E7} EMAIL SENT (Console Adapter)");
|
|
2036
2040
|
console.log("=".repeat(60));
|
|
@@ -2105,6 +2109,7 @@ var ConsoleEmail = class {
|
|
|
2105
2109
|
};
|
|
2106
2110
|
|
|
2107
2111
|
// src/interfaces/ISecrets.ts
|
|
2112
|
+
var import_crypto4 = require("crypto");
|
|
2108
2113
|
var EnvSecrets = class {
|
|
2109
2114
|
prefix;
|
|
2110
2115
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -2305,12 +2310,7 @@ var MemorySecrets = class {
|
|
|
2305
2310
|
return true;
|
|
2306
2311
|
}
|
|
2307
2312
|
generateSecureValue(length = 32) {
|
|
2308
|
-
|
|
2309
|
-
let result = "";
|
|
2310
|
-
for (let i = 0; i < length; i++) {
|
|
2311
|
-
result += chars[Math.floor(Math.random() * chars.length)];
|
|
2312
|
-
}
|
|
2313
|
-
return result;
|
|
2313
|
+
return (0, import_crypto4.randomBytes)(length).toString("base64url").slice(0, length);
|
|
2314
2314
|
}
|
|
2315
2315
|
/**
|
|
2316
2316
|
* Clear all secrets (for testing)
|
|
@@ -2520,6 +2520,27 @@ var RAGConfigSchema = import_zod.z.object({
|
|
|
2520
2520
|
message: "Pinecone requires apiKey and indexName; Weaviate requires host"
|
|
2521
2521
|
}
|
|
2522
2522
|
);
|
|
2523
|
+
var CryptoConfigSchema = import_zod.z.object({
|
|
2524
|
+
enabled: import_zod.z.boolean().default(false).describe("Enable field-level encryption"),
|
|
2525
|
+
masterKey: import_zod.z.string().optional().describe("256-bit master key as hex (64 chars). Required when enabled."),
|
|
2526
|
+
hmacKey: import_zod.z.string().optional().describe(
|
|
2527
|
+
"HMAC key for deterministic hashing (derived from master key if not provided)"
|
|
2528
|
+
)
|
|
2529
|
+
}).refine(
|
|
2530
|
+
(data) => {
|
|
2531
|
+
if (data.enabled) {
|
|
2532
|
+
return data.masterKey && data.masterKey.length >= 64;
|
|
2533
|
+
}
|
|
2534
|
+
return true;
|
|
2535
|
+
},
|
|
2536
|
+
{
|
|
2537
|
+
message: "Crypto requires a 256-bit master key (64 hex characters) when enabled"
|
|
2538
|
+
}
|
|
2539
|
+
);
|
|
2540
|
+
var SecurityConfigSchema = import_zod.z.object({
|
|
2541
|
+
enforceTls: import_zod.z.boolean().default(true).describe("Enforce TLS for production connections"),
|
|
2542
|
+
tlsWarnOnly: import_zod.z.boolean().default(false).describe("Warn instead of throwing when TLS is missing in production")
|
|
2543
|
+
});
|
|
2523
2544
|
var RetryConfigSchema = import_zod.z.object({
|
|
2524
2545
|
enabled: import_zod.z.boolean().default(true).describe("Enable retry for failed operations"),
|
|
2525
2546
|
maxAttempts: import_zod.z.number().int().min(1).max(10).default(3).describe("Maximum retry attempts"),
|
|
@@ -2609,6 +2630,10 @@ var PlatformConfigSchema = import_zod.z.object({
|
|
|
2609
2630
|
// AI configurations
|
|
2610
2631
|
ai: AIConfigSchema.default({ enabled: false }),
|
|
2611
2632
|
rag: RAGConfigSchema.default({ enabled: false }),
|
|
2633
|
+
// Crypto configuration
|
|
2634
|
+
crypto: CryptoConfigSchema.default({ enabled: false }),
|
|
2635
|
+
// Security configuration
|
|
2636
|
+
security: SecurityConfigSchema.default({}),
|
|
2612
2637
|
// Resilience configuration
|
|
2613
2638
|
resilience: ResilienceConfigSchema.default({}),
|
|
2614
2639
|
// Observability configuration
|
|
@@ -2686,6 +2711,15 @@ function loadConfig() {
|
|
|
2686
2711
|
embeddingApiKey: process.env.EMBEDDING_API_KEY || process.env.OPENAI_API_KEY,
|
|
2687
2712
|
embeddingModel: process.env.EMBEDDING_MODEL
|
|
2688
2713
|
},
|
|
2714
|
+
crypto: {
|
|
2715
|
+
enabled: process.env.CRYPTO_ENABLED === "true",
|
|
2716
|
+
masterKey: process.env.CRYPTO_MASTER_KEY,
|
|
2717
|
+
hmacKey: process.env.CRYPTO_HMAC_KEY
|
|
2718
|
+
},
|
|
2719
|
+
security: {
|
|
2720
|
+
enforceTls: process.env.SECURITY_ENFORCE_TLS !== "false",
|
|
2721
|
+
tlsWarnOnly: process.env.SECURITY_TLS_WARN_ONLY === "true"
|
|
2722
|
+
},
|
|
2689
2723
|
resilience: {
|
|
2690
2724
|
retry: {
|
|
2691
2725
|
enabled: process.env.RESILIENCE_RETRY_ENABLED !== "false",
|
|
@@ -2736,6 +2770,7 @@ function loadConfig() {
|
|
|
2736
2770
|
}
|
|
2737
2771
|
|
|
2738
2772
|
// src/interfaces/ITracing.ts
|
|
2773
|
+
var import_crypto5 = require("crypto");
|
|
2739
2774
|
var MemorySpan = class {
|
|
2740
2775
|
name;
|
|
2741
2776
|
context;
|
|
@@ -2755,7 +2790,7 @@ var MemorySpan = class {
|
|
|
2755
2790
|
};
|
|
2756
2791
|
}
|
|
2757
2792
|
generateSpanId() {
|
|
2758
|
-
return
|
|
2793
|
+
return (0, import_crypto5.randomBytes)(8).toString("hex");
|
|
2759
2794
|
}
|
|
2760
2795
|
setAttribute(key, value) {
|
|
2761
2796
|
this._attributes[key] = value;
|
|
@@ -2815,7 +2850,7 @@ var MemoryTracing = class {
|
|
|
2815
2850
|
this.traceId = this.generateTraceId();
|
|
2816
2851
|
}
|
|
2817
2852
|
generateTraceId() {
|
|
2818
|
-
return
|
|
2853
|
+
return (0, import_crypto5.randomBytes)(16).toString("hex");
|
|
2819
2854
|
}
|
|
2820
2855
|
startSpan(name, options) {
|
|
2821
2856
|
const span = new MemorySpan(
|
|
@@ -3255,6 +3290,147 @@ var NoopMetrics = class {
|
|
|
3255
3290
|
// src/factory.ts
|
|
3256
3291
|
init_IAI();
|
|
3257
3292
|
init_IRAG();
|
|
3293
|
+
|
|
3294
|
+
// src/adapters/memory/MemoryCrypto.ts
|
|
3295
|
+
var import_crypto7 = require("crypto");
|
|
3296
|
+
var MemoryCrypto = class {
|
|
3297
|
+
keys = /* @__PURE__ */ new Map();
|
|
3298
|
+
activeKeyId;
|
|
3299
|
+
hmacKey;
|
|
3300
|
+
constructor(options) {
|
|
3301
|
+
const masterKeyBuf = options?.masterKey ? Buffer.from(options.masterKey, "hex") : (0, import_crypto7.randomBytes)(32);
|
|
3302
|
+
this.hmacKey = options?.hmacKey ? Buffer.from(options.hmacKey, "hex") : (0, import_crypto7.randomBytes)(32);
|
|
3303
|
+
const keyId = this.generateKeyId();
|
|
3304
|
+
this.keys.set(keyId, {
|
|
3305
|
+
id: keyId,
|
|
3306
|
+
key: masterKeyBuf,
|
|
3307
|
+
status: "active",
|
|
3308
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
3309
|
+
});
|
|
3310
|
+
this.activeKeyId = keyId;
|
|
3311
|
+
}
|
|
3312
|
+
async encrypt(plaintext, options) {
|
|
3313
|
+
const keyId = options?.keyId || this.activeKeyId;
|
|
3314
|
+
const stored = this.keys.get(keyId);
|
|
3315
|
+
if (!stored) {
|
|
3316
|
+
throw new Error(`Key not found: ${keyId}`);
|
|
3317
|
+
}
|
|
3318
|
+
if (stored.status === "retired") {
|
|
3319
|
+
throw new Error(`Key is retired: ${keyId}`);
|
|
3320
|
+
}
|
|
3321
|
+
if (stored.status === "decrypt-only" && !options?.keyId) {
|
|
3322
|
+
throw new Error(`Key is decrypt-only: ${keyId}`);
|
|
3323
|
+
}
|
|
3324
|
+
const iv = (0, import_crypto7.randomBytes)(12);
|
|
3325
|
+
const cipher = (0, import_crypto7.createCipheriv)("aes-256-gcm", stored.key, iv);
|
|
3326
|
+
if (options?.aad) {
|
|
3327
|
+
cipher.setAAD(Buffer.from(options.aad, "utf8"));
|
|
3328
|
+
}
|
|
3329
|
+
const encrypted = Buffer.concat([
|
|
3330
|
+
cipher.update(plaintext, "utf8"),
|
|
3331
|
+
cipher.final()
|
|
3332
|
+
]);
|
|
3333
|
+
const tag = cipher.getAuthTag();
|
|
3334
|
+
return {
|
|
3335
|
+
ciphertext: encrypted.toString("base64"),
|
|
3336
|
+
iv: iv.toString("base64"),
|
|
3337
|
+
tag: tag.toString("base64"),
|
|
3338
|
+
keyId,
|
|
3339
|
+
algorithm: "aes-256-gcm",
|
|
3340
|
+
version: 1
|
|
3341
|
+
};
|
|
3342
|
+
}
|
|
3343
|
+
async decrypt(field, options) {
|
|
3344
|
+
const stored = this.keys.get(field.keyId);
|
|
3345
|
+
if (!stored) {
|
|
3346
|
+
throw new Error(`Key not found: ${field.keyId}`);
|
|
3347
|
+
}
|
|
3348
|
+
if (stored.status === "retired") {
|
|
3349
|
+
throw new Error(`Key is retired and cannot decrypt: ${field.keyId}`);
|
|
3350
|
+
}
|
|
3351
|
+
const decipher = (0, import_crypto7.createDecipheriv)(
|
|
3352
|
+
"aes-256-gcm",
|
|
3353
|
+
stored.key,
|
|
3354
|
+
Buffer.from(field.iv, "base64")
|
|
3355
|
+
);
|
|
3356
|
+
decipher.setAuthTag(Buffer.from(field.tag, "base64"));
|
|
3357
|
+
if (options?.aad) {
|
|
3358
|
+
decipher.setAAD(Buffer.from(options.aad, "utf8"));
|
|
3359
|
+
}
|
|
3360
|
+
const decrypted = Buffer.concat([
|
|
3361
|
+
decipher.update(Buffer.from(field.ciphertext, "base64")),
|
|
3362
|
+
decipher.final()
|
|
3363
|
+
]);
|
|
3364
|
+
return decrypted.toString("utf8");
|
|
3365
|
+
}
|
|
3366
|
+
async encryptDeterministic(plaintext, options) {
|
|
3367
|
+
const hash = await this.computeHash(plaintext);
|
|
3368
|
+
const encrypted = await this.encrypt(plaintext, options);
|
|
3369
|
+
return { hash, encrypted };
|
|
3370
|
+
}
|
|
3371
|
+
async computeHash(plaintext) {
|
|
3372
|
+
return (0, import_crypto7.createHmac)("sha256", this.hmacKey).update(plaintext, "utf8").digest("hex");
|
|
3373
|
+
}
|
|
3374
|
+
async encryptBatch(fields, options) {
|
|
3375
|
+
const result = {};
|
|
3376
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
3377
|
+
result[key] = await this.encrypt(value, options);
|
|
3378
|
+
}
|
|
3379
|
+
return result;
|
|
3380
|
+
}
|
|
3381
|
+
async decryptBatch(fields, options) {
|
|
3382
|
+
const result = {};
|
|
3383
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
3384
|
+
result[key] = await this.decrypt(value, options);
|
|
3385
|
+
}
|
|
3386
|
+
return result;
|
|
3387
|
+
}
|
|
3388
|
+
async rotateKey() {
|
|
3389
|
+
const previousKeyId = this.activeKeyId;
|
|
3390
|
+
const currentKey = this.keys.get(previousKeyId);
|
|
3391
|
+
if (currentKey) {
|
|
3392
|
+
currentKey.status = "decrypt-only";
|
|
3393
|
+
}
|
|
3394
|
+
const newKeyId = this.generateKeyId();
|
|
3395
|
+
this.keys.set(newKeyId, {
|
|
3396
|
+
id: newKeyId,
|
|
3397
|
+
key: (0, import_crypto7.randomBytes)(32),
|
|
3398
|
+
status: "active",
|
|
3399
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
3400
|
+
});
|
|
3401
|
+
this.activeKeyId = newKeyId;
|
|
3402
|
+
return { newKeyId, previousKeyId };
|
|
3403
|
+
}
|
|
3404
|
+
async reEncrypt(field, options) {
|
|
3405
|
+
const plaintext = await this.decrypt(field);
|
|
3406
|
+
return this.encrypt(plaintext, options);
|
|
3407
|
+
}
|
|
3408
|
+
async listKeys() {
|
|
3409
|
+
return Array.from(this.keys.values()).map((k) => ({
|
|
3410
|
+
keyId: k.id,
|
|
3411
|
+
createdAt: k.createdAt,
|
|
3412
|
+
status: k.status
|
|
3413
|
+
}));
|
|
3414
|
+
}
|
|
3415
|
+
async getActiveKeyId() {
|
|
3416
|
+
return this.activeKeyId;
|
|
3417
|
+
}
|
|
3418
|
+
async healthCheck() {
|
|
3419
|
+
try {
|
|
3420
|
+
const testPlain = "health-check-test";
|
|
3421
|
+
const encrypted = await this.encrypt(testPlain);
|
|
3422
|
+
const decrypted = await this.decrypt(encrypted);
|
|
3423
|
+
return decrypted === testPlain;
|
|
3424
|
+
} catch {
|
|
3425
|
+
return false;
|
|
3426
|
+
}
|
|
3427
|
+
}
|
|
3428
|
+
generateKeyId() {
|
|
3429
|
+
return `key_${(0, import_crypto7.randomBytes)(8).toString("hex")}`;
|
|
3430
|
+
}
|
|
3431
|
+
};
|
|
3432
|
+
|
|
3433
|
+
// src/factory.ts
|
|
3258
3434
|
function createLogger(config) {
|
|
3259
3435
|
if (!config.observability.logging) {
|
|
3260
3436
|
return new NoopLogger();
|
|
@@ -3289,6 +3465,7 @@ function createPlatform(config) {
|
|
|
3289
3465
|
const tracing = finalConfig.observability.tracing.provider === "memory" ? new MemoryTracing() : new NoopTracing();
|
|
3290
3466
|
const ai = finalConfig.ai.enabled ? new MemoryAI() : null;
|
|
3291
3467
|
const rag = finalConfig.rag.enabled ? new MemoryRAG() : null;
|
|
3468
|
+
const crypto2 = finalConfig.crypto.enabled ? new MemoryCrypto() : null;
|
|
3292
3469
|
return createPlatformFromAdapters(
|
|
3293
3470
|
db,
|
|
3294
3471
|
cache,
|
|
@@ -3299,10 +3476,11 @@ function createPlatform(config) {
|
|
|
3299
3476
|
metrics,
|
|
3300
3477
|
tracing,
|
|
3301
3478
|
ai,
|
|
3302
|
-
rag
|
|
3479
|
+
rag,
|
|
3480
|
+
crypto2
|
|
3303
3481
|
);
|
|
3304
3482
|
}
|
|
3305
|
-
function createPlatformFromAdapters(db, cache, storage, email, queue, logger, metrics, tracing, ai, rag) {
|
|
3483
|
+
function createPlatformFromAdapters(db, cache, storage, email, queue, logger, metrics, tracing, ai, rag, crypto2) {
|
|
3306
3484
|
const platform = {
|
|
3307
3485
|
db,
|
|
3308
3486
|
cache,
|
|
@@ -3356,6 +3534,9 @@ function createPlatformFromAdapters(db, cache, storage, email, queue, logger, me
|
|
|
3356
3534
|
if (rag) {
|
|
3357
3535
|
platform.rag = rag;
|
|
3358
3536
|
}
|
|
3537
|
+
if (crypto2) {
|
|
3538
|
+
platform.crypto = crypto2;
|
|
3539
|
+
}
|
|
3359
3540
|
return platform;
|
|
3360
3541
|
}
|
|
3361
3542
|
function deepMerge(target, source) {
|