@blokjs/runner 0.2.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/dist/Blok.d.ts +19 -0
- package/dist/Blok.js +184 -0
- package/dist/Blok.js.map +1 -0
- package/dist/BlokResponse.d.ts +16 -0
- package/dist/BlokResponse.js +28 -0
- package/dist/BlokResponse.js.map +1 -0
- package/dist/Configuration.d.ts +37 -0
- package/dist/Configuration.js +248 -0
- package/dist/Configuration.js.map +1 -0
- package/dist/ConfigurationResolver.d.ts +7 -0
- package/dist/ConfigurationResolver.js +15 -0
- package/dist/ConfigurationResolver.js.map +1 -0
- package/dist/DefaultLogger.d.ts +65 -0
- package/dist/DefaultLogger.js +101 -0
- package/dist/DefaultLogger.js.map +1 -0
- package/dist/LocalStorage.d.ts +7 -0
- package/dist/LocalStorage.js +56 -0
- package/dist/LocalStorage.js.map +1 -0
- package/dist/MemoryUsage.d.ts +22 -0
- package/dist/MemoryUsage.js +83 -0
- package/dist/MemoryUsage.js.map +1 -0
- package/dist/NodeMap.d.ts +7 -0
- package/dist/NodeMap.js +13 -0
- package/dist/NodeMap.js.map +1 -0
- package/dist/ResolverBase.d.ts +8 -0
- package/dist/ResolverBase.js +18 -0
- package/dist/ResolverBase.js.map +1 -0
- package/dist/Runner.d.ts +25 -0
- package/dist/Runner.js +32 -0
- package/dist/Runner.js.map +1 -0
- package/dist/RunnerNode.d.ts +9 -0
- package/dist/RunnerNode.js +8 -0
- package/dist/RunnerNode.js.map +1 -0
- package/dist/RunnerNodeBase.d.ts +4 -0
- package/dist/RunnerNodeBase.js +3 -0
- package/dist/RunnerNodeBase.js.map +1 -0
- package/dist/RunnerSteps.d.ts +14 -0
- package/dist/RunnerSteps.js +110 -0
- package/dist/RunnerSteps.js.map +1 -0
- package/dist/RuntimeAdapterNode.d.ts +19 -0
- package/dist/RuntimeAdapterNode.js +87 -0
- package/dist/RuntimeAdapterNode.js.map +1 -0
- package/dist/RuntimeRegistry.d.ts +61 -0
- package/dist/RuntimeRegistry.js +87 -0
- package/dist/RuntimeRegistry.js.map +1 -0
- package/dist/TriggerBase.d.ts +119 -0
- package/dist/TriggerBase.js +413 -0
- package/dist/TriggerBase.js.map +1 -0
- package/dist/adapters/BunRuntimeAdapter.d.ts +38 -0
- package/dist/adapters/BunRuntimeAdapter.js +169 -0
- package/dist/adapters/BunRuntimeAdapter.js.map +1 -0
- package/dist/adapters/DockerRuntimeAdapter.d.ts +85 -0
- package/dist/adapters/DockerRuntimeAdapter.js +298 -0
- package/dist/adapters/DockerRuntimeAdapter.js.map +1 -0
- package/dist/adapters/HttpRuntimeAdapter.d.ts +58 -0
- package/dist/adapters/HttpRuntimeAdapter.js +152 -0
- package/dist/adapters/HttpRuntimeAdapter.js.map +1 -0
- package/dist/adapters/NodeJsRuntimeAdapter.d.ts +23 -0
- package/dist/adapters/NodeJsRuntimeAdapter.js +67 -0
- package/dist/adapters/NodeJsRuntimeAdapter.js.map +1 -0
- package/dist/adapters/RuntimeAdapter.d.ts +42 -0
- package/dist/adapters/RuntimeAdapter.js +2 -0
- package/dist/adapters/RuntimeAdapter.js.map +1 -0
- package/dist/adapters/WasmRuntimeAdapter.d.ts +69 -0
- package/dist/adapters/WasmRuntimeAdapter.js +279 -0
- package/dist/adapters/WasmRuntimeAdapter.js.map +1 -0
- package/dist/cache/NodeResultCache.d.ts +286 -0
- package/dist/cache/NodeResultCache.js +499 -0
- package/dist/cache/NodeResultCache.js.map +1 -0
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/index.js +2 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cost/CostEstimator.d.ts +57 -0
- package/dist/cost/CostEstimator.js +171 -0
- package/dist/cost/CostEstimator.js.map +1 -0
- package/dist/cost/index.d.ts +4 -0
- package/dist/cost/index.js +3 -0
- package/dist/cost/index.js.map +1 -0
- package/dist/cost/pricing.d.ts +24 -0
- package/dist/cost/pricing.js +169 -0
- package/dist/cost/pricing.js.map +1 -0
- package/dist/defineNode.d.ts +155 -0
- package/dist/defineNode.js +191 -0
- package/dist/defineNode.js.map +1 -0
- package/dist/graphql/GraphQLSchemaGenerator.d.ts +129 -0
- package/dist/graphql/GraphQLSchemaGenerator.js +425 -0
- package/dist/graphql/GraphQLSchemaGenerator.js.map +1 -0
- package/dist/hmr/FileWatcher.d.ts +62 -0
- package/dist/hmr/FileWatcher.js +185 -0
- package/dist/hmr/FileWatcher.js.map +1 -0
- package/dist/hmr/HmrDevConsole.d.ts +13 -0
- package/dist/hmr/HmrDevConsole.js +46 -0
- package/dist/hmr/HmrDevConsole.js.map +1 -0
- package/dist/hmr/HotReloadManager.d.ts +84 -0
- package/dist/hmr/HotReloadManager.js +195 -0
- package/dist/hmr/HotReloadManager.js.map +1 -0
- package/dist/hmr/index.d.ts +39 -0
- package/dist/hmr/index.js +38 -0
- package/dist/hmr/index.js.map +1 -0
- package/dist/index.d.ts +107 -0
- package/dist/index.js +107 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/APMIntegration.d.ts +141 -0
- package/dist/integrations/APMIntegration.js +212 -0
- package/dist/integrations/APMIntegration.js.map +1 -0
- package/dist/integrations/AzureMonitorIntegration.d.ts +118 -0
- package/dist/integrations/AzureMonitorIntegration.js +254 -0
- package/dist/integrations/AzureMonitorIntegration.js.map +1 -0
- package/dist/integrations/CloudWatchIntegration.d.ts +135 -0
- package/dist/integrations/CloudWatchIntegration.js +293 -0
- package/dist/integrations/CloudWatchIntegration.js.map +1 -0
- package/dist/integrations/SentryIntegration.d.ts +153 -0
- package/dist/integrations/SentryIntegration.js +200 -0
- package/dist/integrations/SentryIntegration.js.map +1 -0
- package/dist/integrations/index.d.ts +19 -0
- package/dist/integrations/index.js +16 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/marketplace/RuntimeAutoScaler.d.ts +148 -0
- package/dist/marketplace/RuntimeAutoScaler.js +366 -0
- package/dist/marketplace/RuntimeAutoScaler.js.map +1 -0
- package/dist/marketplace/RuntimeCatalog.d.ts +174 -0
- package/dist/marketplace/RuntimeCatalog.js +339 -0
- package/dist/marketplace/RuntimeCatalog.js.map +1 -0
- package/dist/marketplace/RuntimeDiscovery.d.ts +86 -0
- package/dist/marketplace/RuntimeDiscovery.js +219 -0
- package/dist/marketplace/RuntimeDiscovery.js.map +1 -0
- package/dist/marketplace/RuntimeHealthMonitor.d.ts +100 -0
- package/dist/marketplace/RuntimeHealthMonitor.js +241 -0
- package/dist/marketplace/RuntimeHealthMonitor.js.map +1 -0
- package/dist/marketplace/RuntimeMetricsDashboard.d.ts +113 -0
- package/dist/marketplace/RuntimeMetricsDashboard.js +293 -0
- package/dist/marketplace/RuntimeMetricsDashboard.js.map +1 -0
- package/dist/monitoring/CircuitBreaker.d.ts +107 -0
- package/dist/monitoring/CircuitBreaker.js +238 -0
- package/dist/monitoring/CircuitBreaker.js.map +1 -0
- package/dist/monitoring/DistributedTracer.d.ts +125 -0
- package/dist/monitoring/DistributedTracer.js +230 -0
- package/dist/monitoring/DistributedTracer.js.map +1 -0
- package/dist/monitoring/HealthCheck.d.ts +54 -0
- package/dist/monitoring/HealthCheck.js +102 -0
- package/dist/monitoring/HealthCheck.js.map +1 -0
- package/dist/monitoring/PerformanceProfiler.d.ts +63 -0
- package/dist/monitoring/PerformanceProfiler.js +229 -0
- package/dist/monitoring/PerformanceProfiler.js.map +1 -0
- package/dist/monitoring/PrometheusBootstrap.d.ts +30 -0
- package/dist/monitoring/PrometheusBootstrap.js +71 -0
- package/dist/monitoring/PrometheusBootstrap.js.map +1 -0
- package/dist/monitoring/PrometheusMetricsBridge.d.ts +60 -0
- package/dist/monitoring/PrometheusMetricsBridge.js +216 -0
- package/dist/monitoring/PrometheusMetricsBridge.js.map +1 -0
- package/dist/monitoring/RateLimiter.d.ts +58 -0
- package/dist/monitoring/RateLimiter.js +128 -0
- package/dist/monitoring/RateLimiter.js.map +1 -0
- package/dist/monitoring/StructuredLogger.d.ts +131 -0
- package/dist/monitoring/StructuredLogger.js +207 -0
- package/dist/monitoring/StructuredLogger.js.map +1 -0
- package/dist/monitoring/TracingBootstrap.d.ts +69 -0
- package/dist/monitoring/TracingBootstrap.js +129 -0
- package/dist/monitoring/TracingBootstrap.js.map +1 -0
- package/dist/monitoring/TriggerMetricsCollector.d.ts +94 -0
- package/dist/monitoring/TriggerMetricsCollector.js +174 -0
- package/dist/monitoring/TriggerMetricsCollector.js.map +1 -0
- package/dist/monitoring/index.d.ts +9 -0
- package/dist/monitoring/index.js +10 -0
- package/dist/monitoring/index.js.map +1 -0
- package/dist/openapi/OpenAPIGenerator.d.ts +192 -0
- package/dist/openapi/OpenAPIGenerator.js +373 -0
- package/dist/openapi/OpenAPIGenerator.js.map +1 -0
- package/dist/openapi/index.d.ts +20 -0
- package/dist/openapi/index.js +20 -0
- package/dist/openapi/index.js.map +1 -0
- package/dist/security/ABAC.d.ts +224 -0
- package/dist/security/ABAC.js +380 -0
- package/dist/security/ABAC.js.map +1 -0
- package/dist/security/AuditLogger.d.ts +242 -0
- package/dist/security/AuditLogger.js +317 -0
- package/dist/security/AuditLogger.js.map +1 -0
- package/dist/security/AuthMiddleware.d.ts +163 -0
- package/dist/security/AuthMiddleware.js +274 -0
- package/dist/security/AuthMiddleware.js.map +1 -0
- package/dist/security/EncryptionAtRest.d.ts +206 -0
- package/dist/security/EncryptionAtRest.js +236 -0
- package/dist/security/EncryptionAtRest.js.map +1 -0
- package/dist/security/OAuthProvider.d.ts +334 -0
- package/dist/security/OAuthProvider.js +719 -0
- package/dist/security/OAuthProvider.js.map +1 -0
- package/dist/security/PIIDetector.d.ts +233 -0
- package/dist/security/PIIDetector.js +354 -0
- package/dist/security/PIIDetector.js.map +1 -0
- package/dist/security/RBAC.d.ts +143 -0
- package/dist/security/RBAC.js +285 -0
- package/dist/security/RBAC.js.map +1 -0
- package/dist/security/SecretManager.d.ts +652 -0
- package/dist/security/SecretManager.js +1146 -0
- package/dist/security/SecretManager.js.map +1 -0
- package/dist/security/TLSConfig.d.ts +305 -0
- package/dist/security/TLSConfig.js +550 -0
- package/dist/security/TLSConfig.js.map +1 -0
- package/dist/security/index.d.ts +79 -0
- package/dist/security/index.js +80 -0
- package/dist/security/index.js.map +1 -0
- package/dist/testing/TestHarness.d.ts +189 -0
- package/dist/testing/TestHarness.js +272 -0
- package/dist/testing/TestHarness.js.map +1 -0
- package/dist/testing/TestLogger.d.ts +103 -0
- package/dist/testing/TestLogger.js +153 -0
- package/dist/testing/TestLogger.js.map +1 -0
- package/dist/testing/WorkflowTestRunner.d.ts +172 -0
- package/dist/testing/WorkflowTestRunner.js +355 -0
- package/dist/testing/WorkflowTestRunner.js.map +1 -0
- package/dist/testing/index.d.ts +21 -0
- package/dist/testing/index.js +22 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/tracing/InMemoryRunStore.d.ts +44 -0
- package/dist/tracing/InMemoryRunStore.js +341 -0
- package/dist/tracing/InMemoryRunStore.js.map +1 -0
- package/dist/tracing/PostgresRunStore.d.ts +82 -0
- package/dist/tracing/PostgresRunStore.js +640 -0
- package/dist/tracing/PostgresRunStore.js.map +1 -0
- package/dist/tracing/RunStore.d.ts +38 -0
- package/dist/tracing/RunStore.js +2 -0
- package/dist/tracing/RunStore.js.map +1 -0
- package/dist/tracing/RunTracker.d.ts +75 -0
- package/dist/tracing/RunTracker.js +374 -0
- package/dist/tracing/RunTracker.js.map +1 -0
- package/dist/tracing/SqliteRunStore.d.ts +53 -0
- package/dist/tracing/SqliteRunStore.js +703 -0
- package/dist/tracing/SqliteRunStore.js.map +1 -0
- package/dist/tracing/TraceRouter.d.ts +47 -0
- package/dist/tracing/TraceRouter.js +904 -0
- package/dist/tracing/TraceRouter.js.map +1 -0
- package/dist/tracing/TracingLogger.d.ts +21 -0
- package/dist/tracing/TracingLogger.js +62 -0
- package/dist/tracing/TracingLogger.js.map +1 -0
- package/dist/tracing/createStore.d.ts +30 -0
- package/dist/tracing/createStore.js +75 -0
- package/dist/tracing/createStore.js.map +1 -0
- package/dist/tracing/index.d.ts +13 -0
- package/dist/tracing/index.js +9 -0
- package/dist/tracing/index.js.map +1 -0
- package/dist/tracing/sanitize.d.ts +7 -0
- package/dist/tracing/sanitize.js +95 -0
- package/dist/tracing/sanitize.js.map +1 -0
- package/dist/tracing/types.d.ts +178 -0
- package/dist/tracing/types.js +3 -0
- package/dist/tracing/types.js.map +1 -0
- package/dist/types/Average.d.ts +11 -0
- package/dist/types/Average.js +2 -0
- package/dist/types/Average.js.map +1 -0
- package/dist/types/Condition.d.ts +8 -0
- package/dist/types/Condition.js +2 -0
- package/dist/types/Condition.js.map +1 -0
- package/dist/types/Conditions.d.ts +5 -0
- package/dist/types/Conditions.js +2 -0
- package/dist/types/Conditions.js.map +1 -0
- package/dist/types/Config.d.ts +12 -0
- package/dist/types/Config.js +2 -0
- package/dist/types/Config.js.map +1 -0
- package/dist/types/Flow.d.ts +5 -0
- package/dist/types/Flow.js +2 -0
- package/dist/types/Flow.js.map +1 -0
- package/dist/types/GlobalOptions.d.ts +11 -0
- package/dist/types/GlobalOptions.js +2 -0
- package/dist/types/GlobalOptions.js.map +1 -0
- package/dist/types/Inputs.d.ts +5 -0
- package/dist/types/Inputs.js +2 -0
- package/dist/types/Inputs.js.map +1 -0
- package/dist/types/JsonLikeObject.d.ts +3 -0
- package/dist/types/JsonLikeObject.js +2 -0
- package/dist/types/JsonLikeObject.js.map +1 -0
- package/dist/types/Mapper.d.ts +5 -0
- package/dist/types/Mapper.js +2 -0
- package/dist/types/Mapper.js.map +1 -0
- package/dist/types/Node.d.ts +10 -0
- package/dist/types/Node.js +2 -0
- package/dist/types/Node.js.map +1 -0
- package/dist/types/ParamsDictionary.d.ts +3 -0
- package/dist/types/ParamsDictionary.js +2 -0
- package/dist/types/ParamsDictionary.js.map +1 -0
- package/dist/types/Properties.d.ts +5 -0
- package/dist/types/Properties.js +2 -0
- package/dist/types/Properties.js.map +1 -0
- package/dist/types/Targets.d.ts +5 -0
- package/dist/types/Targets.js +2 -0
- package/dist/types/Targets.js.map +1 -0
- package/dist/types/Trigger.d.ts +5 -0
- package/dist/types/Trigger.js +2 -0
- package/dist/types/Trigger.js.map +1 -0
- package/dist/types/TriggerHttp.d.ts +7 -0
- package/dist/types/TriggerHttp.js +2 -0
- package/dist/types/TriggerHttp.js.map +1 -0
- package/dist/types/TriggerResponse.d.ts +6 -0
- package/dist/types/TriggerResponse.js +2 -0
- package/dist/types/TriggerResponse.js.map +1 -0
- package/dist/types/Triggers.d.ts +5 -0
- package/dist/types/Triggers.js +2 -0
- package/dist/types/Triggers.js.map +1 -0
- package/dist/types/TryCatch.d.ts +6 -0
- package/dist/types/TryCatch.js +2 -0
- package/dist/types/TryCatch.js.map +1 -0
- package/dist/visualization/NodeDependencyGraph.d.ts +76 -0
- package/dist/visualization/NodeDependencyGraph.js +418 -0
- package/dist/visualization/NodeDependencyGraph.js.map +1 -0
- package/dist/visualization/WorkflowVisualizer.d.ts +144 -0
- package/dist/visualization/WorkflowVisualizer.js +446 -0
- package/dist/visualization/WorkflowVisualizer.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication Middleware for Blok Triggers
|
|
3
|
+
*
|
|
4
|
+
* Provides pluggable authentication for all trigger types:
|
|
5
|
+
* - JWT Bearer token verification (RS256, HS256)
|
|
6
|
+
* - API Key verification (header, query param)
|
|
7
|
+
* - Custom auth provider support
|
|
8
|
+
*
|
|
9
|
+
* Integrates with TriggerBase via composition.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const auth = new AuthMiddleware({
|
|
14
|
+
* providers: [
|
|
15
|
+
* new JWTAuthProvider({ secret: process.env.JWT_SECRET! }),
|
|
16
|
+
* new APIKeyAuthProvider({
|
|
17
|
+
* keys: new Map([["my-api-key", { name: "service-a", roles: ["admin"] }]]),
|
|
18
|
+
* }),
|
|
19
|
+
* ],
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // In Express middleware
|
|
23
|
+
* app.use(auth.expressMiddleware());
|
|
24
|
+
*
|
|
25
|
+
* // Or manually
|
|
26
|
+
* const identity = await auth.authenticate(request);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export interface AuthIdentity {
|
|
30
|
+
/** Unique identifier for the authenticated entity */
|
|
31
|
+
sub: string;
|
|
32
|
+
/** Display name */
|
|
33
|
+
name?: string;
|
|
34
|
+
/** Email address */
|
|
35
|
+
email?: string;
|
|
36
|
+
/** Assigned roles */
|
|
37
|
+
roles: string[];
|
|
38
|
+
/** Additional claims/metadata */
|
|
39
|
+
claims: Record<string, unknown>;
|
|
40
|
+
/** Authentication provider that verified this identity */
|
|
41
|
+
provider: string;
|
|
42
|
+
/** When the token/key was issued */
|
|
43
|
+
issuedAt?: number;
|
|
44
|
+
/** When the token/key expires */
|
|
45
|
+
expiresAt?: number;
|
|
46
|
+
}
|
|
47
|
+
export interface AuthRequest {
|
|
48
|
+
headers: Record<string, string | string[] | undefined>;
|
|
49
|
+
query?: Record<string, string | string[] | undefined>;
|
|
50
|
+
path?: string;
|
|
51
|
+
method?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface AuthResult {
|
|
54
|
+
authenticated: boolean;
|
|
55
|
+
identity?: AuthIdentity;
|
|
56
|
+
error?: string;
|
|
57
|
+
statusCode?: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Base interface for authentication providers
|
|
61
|
+
*/
|
|
62
|
+
export interface AuthProvider {
|
|
63
|
+
/** Unique name for this provider */
|
|
64
|
+
readonly name: string;
|
|
65
|
+
/** Try to authenticate the request */
|
|
66
|
+
authenticate(request: AuthRequest): Promise<AuthResult>;
|
|
67
|
+
}
|
|
68
|
+
export interface AuthMiddlewareConfig {
|
|
69
|
+
/** Authentication providers to use (tried in order) */
|
|
70
|
+
providers: AuthProvider[];
|
|
71
|
+
/** Paths to exclude from authentication (e.g., ["/health-check", "/metrics"]) */
|
|
72
|
+
excludePaths?: string[];
|
|
73
|
+
/** Whether authentication is required (default: true) */
|
|
74
|
+
required?: boolean;
|
|
75
|
+
/** Custom error handler */
|
|
76
|
+
onAuthFailure?: (result: AuthResult, request: AuthRequest) => void;
|
|
77
|
+
}
|
|
78
|
+
export declare class AuthMiddleware {
|
|
79
|
+
private config;
|
|
80
|
+
constructor(config: AuthMiddlewareConfig);
|
|
81
|
+
/**
|
|
82
|
+
* Authenticate a request against all registered providers.
|
|
83
|
+
* Returns the first successful authentication result.
|
|
84
|
+
*/
|
|
85
|
+
authenticate(request: AuthRequest): Promise<AuthResult>;
|
|
86
|
+
/**
|
|
87
|
+
* Express-compatible middleware function
|
|
88
|
+
*/
|
|
89
|
+
expressMiddleware(): (req: {
|
|
90
|
+
headers: Record<string, string>;
|
|
91
|
+
query: Record<string, string>;
|
|
92
|
+
path: string;
|
|
93
|
+
method: string;
|
|
94
|
+
auth?: AuthIdentity;
|
|
95
|
+
}, res: {
|
|
96
|
+
status: (code: number) => {
|
|
97
|
+
json: (body: unknown) => void;
|
|
98
|
+
};
|
|
99
|
+
}, next: () => void) => Promise<void>;
|
|
100
|
+
private isExcludedPath;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* JWT Authentication Provider
|
|
104
|
+
*
|
|
105
|
+
* Verifies JWT tokens from the Authorization: Bearer header.
|
|
106
|
+
* Supports HS256 (shared secret) out of the box.
|
|
107
|
+
*/
|
|
108
|
+
export interface JWTAuthProviderConfig {
|
|
109
|
+
/** Secret key for HS256 verification */
|
|
110
|
+
secret: string;
|
|
111
|
+
/** Expected issuer (iss claim) */
|
|
112
|
+
issuer?: string;
|
|
113
|
+
/** Expected audience (aud claim) */
|
|
114
|
+
audience?: string;
|
|
115
|
+
/** Header name to read token from (default: "authorization") */
|
|
116
|
+
headerName?: string;
|
|
117
|
+
/** Clock tolerance in seconds for exp/nbf validation (default: 30) */
|
|
118
|
+
clockToleranceSec?: number;
|
|
119
|
+
/** Map JWT claims to roles (claim name → role mapping function) */
|
|
120
|
+
rolesClaim?: string;
|
|
121
|
+
}
|
|
122
|
+
export declare class JWTAuthProvider implements AuthProvider {
|
|
123
|
+
readonly name = "jwt";
|
|
124
|
+
private config;
|
|
125
|
+
constructor(config: JWTAuthProviderConfig);
|
|
126
|
+
authenticate(request: AuthRequest): Promise<AuthResult>;
|
|
127
|
+
/**
|
|
128
|
+
* Verify JWT token using HS256
|
|
129
|
+
*/
|
|
130
|
+
private verifyToken;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* API Key Authentication Provider
|
|
134
|
+
*
|
|
135
|
+
* Verifies API keys from headers or query parameters.
|
|
136
|
+
*/
|
|
137
|
+
export interface APIKeyInfo {
|
|
138
|
+
/** Name/label for this API key */
|
|
139
|
+
name: string;
|
|
140
|
+
/** Roles assigned to this key */
|
|
141
|
+
roles: string[];
|
|
142
|
+
/** Additional metadata */
|
|
143
|
+
metadata?: Record<string, unknown>;
|
|
144
|
+
/** Expiration timestamp (Unix seconds) */
|
|
145
|
+
expiresAt?: number;
|
|
146
|
+
}
|
|
147
|
+
export interface APIKeyAuthProviderConfig {
|
|
148
|
+
/** Map of API key → key info */
|
|
149
|
+
keys: Map<string, APIKeyInfo>;
|
|
150
|
+
/** Header name to read key from (default: "x-api-key") */
|
|
151
|
+
headerName?: string;
|
|
152
|
+
/** Query parameter name to read key from (default: "api_key") */
|
|
153
|
+
queryParam?: string;
|
|
154
|
+
/** Custom key validation function (e.g., for database lookups) */
|
|
155
|
+
validate?: (key: string) => Promise<APIKeyInfo | null>;
|
|
156
|
+
}
|
|
157
|
+
export declare class APIKeyAuthProvider implements AuthProvider {
|
|
158
|
+
readonly name = "api-key";
|
|
159
|
+
private config;
|
|
160
|
+
constructor(config: APIKeyAuthProviderConfig);
|
|
161
|
+
authenticate(request: AuthRequest): Promise<AuthResult>;
|
|
162
|
+
private buildResult;
|
|
163
|
+
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication Middleware for Blok Triggers
|
|
3
|
+
*
|
|
4
|
+
* Provides pluggable authentication for all trigger types:
|
|
5
|
+
* - JWT Bearer token verification (RS256, HS256)
|
|
6
|
+
* - API Key verification (header, query param)
|
|
7
|
+
* - Custom auth provider support
|
|
8
|
+
*
|
|
9
|
+
* Integrates with TriggerBase via composition.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const auth = new AuthMiddleware({
|
|
14
|
+
* providers: [
|
|
15
|
+
* new JWTAuthProvider({ secret: process.env.JWT_SECRET! }),
|
|
16
|
+
* new APIKeyAuthProvider({
|
|
17
|
+
* keys: new Map([["my-api-key", { name: "service-a", roles: ["admin"] }]]),
|
|
18
|
+
* }),
|
|
19
|
+
* ],
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // In Express middleware
|
|
23
|
+
* app.use(auth.expressMiddleware());
|
|
24
|
+
*
|
|
25
|
+
* // Or manually
|
|
26
|
+
* const identity = await auth.authenticate(request);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
30
|
+
export class AuthMiddleware {
|
|
31
|
+
config;
|
|
32
|
+
constructor(config) {
|
|
33
|
+
this.config = {
|
|
34
|
+
excludePaths: ["/health-check", "/metrics", "/health", "/liveness", "/readiness"],
|
|
35
|
+
required: true,
|
|
36
|
+
...config,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Authenticate a request against all registered providers.
|
|
41
|
+
* Returns the first successful authentication result.
|
|
42
|
+
*/
|
|
43
|
+
async authenticate(request) {
|
|
44
|
+
// Check excluded paths
|
|
45
|
+
if (request.path && this.isExcludedPath(request.path)) {
|
|
46
|
+
return {
|
|
47
|
+
authenticated: true,
|
|
48
|
+
identity: {
|
|
49
|
+
sub: "anonymous",
|
|
50
|
+
roles: ["public"],
|
|
51
|
+
claims: {},
|
|
52
|
+
provider: "excluded-path",
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// Try each provider in order
|
|
57
|
+
for (const provider of this.config.providers) {
|
|
58
|
+
const result = await provider.authenticate(request);
|
|
59
|
+
if (result.authenticated) {
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// No provider authenticated the request
|
|
64
|
+
if (!this.config.required) {
|
|
65
|
+
return {
|
|
66
|
+
authenticated: true,
|
|
67
|
+
identity: {
|
|
68
|
+
sub: "anonymous",
|
|
69
|
+
roles: ["public"],
|
|
70
|
+
claims: {},
|
|
71
|
+
provider: "anonymous",
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const result = {
|
|
76
|
+
authenticated: false,
|
|
77
|
+
error: "Authentication required",
|
|
78
|
+
statusCode: 401,
|
|
79
|
+
};
|
|
80
|
+
if (this.config.onAuthFailure) {
|
|
81
|
+
this.config.onAuthFailure(result, request);
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Express-compatible middleware function
|
|
87
|
+
*/
|
|
88
|
+
expressMiddleware() {
|
|
89
|
+
return async (req, res, next) => {
|
|
90
|
+
const result = await this.authenticate({
|
|
91
|
+
headers: req.headers,
|
|
92
|
+
query: req.query,
|
|
93
|
+
path: req.path,
|
|
94
|
+
method: req.method,
|
|
95
|
+
});
|
|
96
|
+
if (!result.authenticated) {
|
|
97
|
+
res.status(result.statusCode || 401).json({
|
|
98
|
+
error: result.error || "Unauthorized",
|
|
99
|
+
});
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// Attach identity to request
|
|
103
|
+
req.auth = result.identity;
|
|
104
|
+
next();
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
isExcludedPath(path) {
|
|
108
|
+
return (this.config.excludePaths || []).some((excluded) => path === excluded || path.startsWith(`${excluded}/`));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export class JWTAuthProvider {
|
|
112
|
+
name = "jwt";
|
|
113
|
+
config;
|
|
114
|
+
constructor(config) {
|
|
115
|
+
this.config = {
|
|
116
|
+
headerName: "authorization",
|
|
117
|
+
clockToleranceSec: 30,
|
|
118
|
+
rolesClaim: "roles",
|
|
119
|
+
...config,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async authenticate(request) {
|
|
123
|
+
const headerValue = request.headers[this.config.headerName || "authorization"];
|
|
124
|
+
if (!headerValue) {
|
|
125
|
+
return { authenticated: false, error: "No authorization header" };
|
|
126
|
+
}
|
|
127
|
+
const token = String(headerValue).replace(/^Bearer\s+/i, "");
|
|
128
|
+
if (!token || token === String(headerValue)) {
|
|
129
|
+
return { authenticated: false, error: "Invalid Bearer token format" };
|
|
130
|
+
}
|
|
131
|
+
try {
|
|
132
|
+
const payload = this.verifyToken(token);
|
|
133
|
+
if (!payload) {
|
|
134
|
+
return { authenticated: false, error: "Invalid token signature", statusCode: 401 };
|
|
135
|
+
}
|
|
136
|
+
// Validate expiry
|
|
137
|
+
const now = Math.floor(Date.now() / 1000);
|
|
138
|
+
const tolerance = this.config.clockToleranceSec || 30;
|
|
139
|
+
const exp = typeof payload.exp === "number" ? payload.exp : undefined;
|
|
140
|
+
const nbf = typeof payload.nbf === "number" ? payload.nbf : undefined;
|
|
141
|
+
if (exp && exp + tolerance < now) {
|
|
142
|
+
return { authenticated: false, error: "Token expired", statusCode: 401 };
|
|
143
|
+
}
|
|
144
|
+
if (nbf && nbf - tolerance > now) {
|
|
145
|
+
return { authenticated: false, error: "Token not yet valid", statusCode: 401 };
|
|
146
|
+
}
|
|
147
|
+
// Validate issuer
|
|
148
|
+
if (this.config.issuer && payload.iss !== this.config.issuer) {
|
|
149
|
+
return { authenticated: false, error: "Invalid token issuer", statusCode: 401 };
|
|
150
|
+
}
|
|
151
|
+
// Validate audience
|
|
152
|
+
if (this.config.audience) {
|
|
153
|
+
const aud = Array.isArray(payload.aud) ? payload.aud : [payload.aud];
|
|
154
|
+
if (!aud.includes(this.config.audience)) {
|
|
155
|
+
return { authenticated: false, error: "Invalid token audience", statusCode: 401 };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Extract roles
|
|
159
|
+
const rolesClaim = this.config.rolesClaim || "roles";
|
|
160
|
+
const roles = Array.isArray(payload[rolesClaim])
|
|
161
|
+
? payload[rolesClaim]
|
|
162
|
+
: typeof payload[rolesClaim] === "string"
|
|
163
|
+
? [payload[rolesClaim]]
|
|
164
|
+
: [];
|
|
165
|
+
const iat = typeof payload.iat === "number" ? payload.iat : undefined;
|
|
166
|
+
return {
|
|
167
|
+
authenticated: true,
|
|
168
|
+
identity: {
|
|
169
|
+
sub: typeof payload.sub === "string" ? payload.sub : "unknown",
|
|
170
|
+
name: payload.name,
|
|
171
|
+
email: payload.email,
|
|
172
|
+
roles,
|
|
173
|
+
claims: payload,
|
|
174
|
+
provider: "jwt",
|
|
175
|
+
issuedAt: iat,
|
|
176
|
+
expiresAt: exp,
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
return {
|
|
182
|
+
authenticated: false,
|
|
183
|
+
error: `Token verification failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
184
|
+
statusCode: 401,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Verify JWT token using HS256
|
|
190
|
+
*/
|
|
191
|
+
verifyToken(token) {
|
|
192
|
+
const parts = token.split(".");
|
|
193
|
+
if (parts.length !== 3)
|
|
194
|
+
return null;
|
|
195
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
196
|
+
// Verify signature (HS256)
|
|
197
|
+
const expectedSignature = createHmac("sha256", this.config.secret)
|
|
198
|
+
.update(`${headerB64}.${payloadB64}`)
|
|
199
|
+
.digest("base64url");
|
|
200
|
+
const signatureBuffer = Buffer.from(signatureB64, "base64url");
|
|
201
|
+
const expectedBuffer = Buffer.from(expectedSignature, "base64url");
|
|
202
|
+
if (signatureBuffer.length !== expectedBuffer.length)
|
|
203
|
+
return null;
|
|
204
|
+
if (!timingSafeEqual(signatureBuffer, expectedBuffer))
|
|
205
|
+
return null;
|
|
206
|
+
// Decode payload
|
|
207
|
+
try {
|
|
208
|
+
const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString("utf-8"));
|
|
209
|
+
return payload;
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
export class APIKeyAuthProvider {
|
|
217
|
+
name = "api-key";
|
|
218
|
+
config;
|
|
219
|
+
constructor(config) {
|
|
220
|
+
this.config = {
|
|
221
|
+
headerName: "x-api-key",
|
|
222
|
+
queryParam: "api_key",
|
|
223
|
+
...config,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
async authenticate(request) {
|
|
227
|
+
// Try header first
|
|
228
|
+
let apiKey = request.headers[this.config.headerName || "x-api-key"];
|
|
229
|
+
if (Array.isArray(apiKey))
|
|
230
|
+
apiKey = apiKey[0];
|
|
231
|
+
// Then try query param
|
|
232
|
+
if (!apiKey && request.query) {
|
|
233
|
+
let queryKey = request.query[this.config.queryParam || "api_key"];
|
|
234
|
+
if (Array.isArray(queryKey))
|
|
235
|
+
queryKey = queryKey[0];
|
|
236
|
+
apiKey = queryKey;
|
|
237
|
+
}
|
|
238
|
+
if (!apiKey) {
|
|
239
|
+
return { authenticated: false, error: "No API key provided" };
|
|
240
|
+
}
|
|
241
|
+
// Try custom validator first
|
|
242
|
+
if (this.config.validate) {
|
|
243
|
+
const info = await this.config.validate(apiKey);
|
|
244
|
+
if (info) {
|
|
245
|
+
return this.buildResult(apiKey, info);
|
|
246
|
+
}
|
|
247
|
+
return { authenticated: false, error: "Invalid API key", statusCode: 401 };
|
|
248
|
+
}
|
|
249
|
+
// Check static keys
|
|
250
|
+
const info = this.config.keys.get(apiKey);
|
|
251
|
+
if (!info) {
|
|
252
|
+
return { authenticated: false, error: "Invalid API key", statusCode: 401 };
|
|
253
|
+
}
|
|
254
|
+
return this.buildResult(apiKey, info);
|
|
255
|
+
}
|
|
256
|
+
buildResult(key, info) {
|
|
257
|
+
// Check expiry
|
|
258
|
+
if (info.expiresAt && info.expiresAt < Math.floor(Date.now() / 1000)) {
|
|
259
|
+
return { authenticated: false, error: "API key expired", statusCode: 401 };
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
authenticated: true,
|
|
263
|
+
identity: {
|
|
264
|
+
sub: info.name,
|
|
265
|
+
name: info.name,
|
|
266
|
+
roles: info.roles,
|
|
267
|
+
claims: info.metadata || {},
|
|
268
|
+
provider: "api-key",
|
|
269
|
+
expiresAt: info.expiresAt,
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=AuthMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthMiddleware.js","sourceRoot":"","sources":["../../src/security/AuthMiddleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encryption at Rest for Blok Framework
|
|
3
|
+
*
|
|
4
|
+
* Provides AES-256-GCM encryption and decryption for data at rest:
|
|
5
|
+
* - Symmetric encryption using AES-256-GCM (authenticated encryption)
|
|
6
|
+
* - Key derivation via PBKDF2 with configurable iterations and salt length
|
|
7
|
+
* - JSON object encryption/decryption with type safety
|
|
8
|
+
* - Key rotation support for seamless secret re-keying
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { EncryptionAtRest } from "@blokjs/runner";
|
|
13
|
+
*
|
|
14
|
+
* const encryption = new EncryptionAtRest({
|
|
15
|
+
* algorithm: "aes-256-gcm",
|
|
16
|
+
* keyDerivation: { iterations: 100_000, saltLength: 16, digest: "sha512" },
|
|
17
|
+
* encoding: "base64",
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Encrypt a string
|
|
21
|
+
* const payload = encryption.encrypt("sensitive data", "my-secret-key");
|
|
22
|
+
*
|
|
23
|
+
* // Decrypt it back
|
|
24
|
+
* const plaintext = encryption.decrypt(payload, "my-secret-key");
|
|
25
|
+
*
|
|
26
|
+
* // Encrypt/decrypt JSON objects
|
|
27
|
+
* const encrypted = encryption.encryptObject({ userId: 42, email: "a@b.com" }, "key");
|
|
28
|
+
* const obj = encryption.decryptObject<{ userId: number; email: string }>(encrypted, "key");
|
|
29
|
+
*
|
|
30
|
+
* // Rotate encryption key
|
|
31
|
+
* const reEncrypted = encryption.rotateKey(encrypted, "old-key", "new-key");
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Encrypted payload containing all data needed for decryption.
|
|
36
|
+
*
|
|
37
|
+
* This is a self-describing structure: it includes the algorithm and
|
|
38
|
+
* initialization vector so that the correct decryption parameters can be
|
|
39
|
+
* reconstructed without external metadata.
|
|
40
|
+
*/
|
|
41
|
+
export interface EncryptedPayload {
|
|
42
|
+
/** Base64- or hex-encoded initialization vector */
|
|
43
|
+
iv: string;
|
|
44
|
+
/** Base64- or hex-encoded ciphertext */
|
|
45
|
+
ciphertext: string;
|
|
46
|
+
/** Base64- or hex-encoded GCM authentication tag */
|
|
47
|
+
tag: string;
|
|
48
|
+
/** Algorithm used for encryption (e.g. "aes-256-gcm") */
|
|
49
|
+
algorithm: string;
|
|
50
|
+
/** Optional identifier for the key that was used */
|
|
51
|
+
keyId?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* PBKDF2 key derivation settings.
|
|
55
|
+
*/
|
|
56
|
+
export interface KeyDerivationConfig {
|
|
57
|
+
/** Number of PBKDF2 iterations (recommended >= 100 000) */
|
|
58
|
+
iterations: number;
|
|
59
|
+
/** Length of the random salt in bytes (default 16) */
|
|
60
|
+
saltLength: number;
|
|
61
|
+
/** Hash digest algorithm (default "sha512") */
|
|
62
|
+
digest: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Configuration for the {@link EncryptionAtRest} class.
|
|
66
|
+
*/
|
|
67
|
+
export interface EncryptionConfig {
|
|
68
|
+
/**
|
|
69
|
+
* Cipher algorithm to use.
|
|
70
|
+
* @default "aes-256-gcm"
|
|
71
|
+
*/
|
|
72
|
+
algorithm?: string;
|
|
73
|
+
/**
|
|
74
|
+
* PBKDF2 key derivation settings.
|
|
75
|
+
* @default { iterations: 100_000, saltLength: 16, digest: "sha512" }
|
|
76
|
+
*/
|
|
77
|
+
keyDerivation?: Partial<KeyDerivationConfig>;
|
|
78
|
+
/**
|
|
79
|
+
* Output encoding for binary values in {@link EncryptedPayload}.
|
|
80
|
+
* @default "base64"
|
|
81
|
+
*/
|
|
82
|
+
encoding?: BufferEncoding;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Provides AES-256-GCM encryption and decryption for data at rest.
|
|
86
|
+
*
|
|
87
|
+
* All encrypted payloads are self-describing: they embed the IV, auth tag,
|
|
88
|
+
* and algorithm so that decryption does not require out-of-band metadata.
|
|
89
|
+
*
|
|
90
|
+
* Keys are derived from a passphrase via PBKDF2 with a per-encryption random
|
|
91
|
+
* salt. The salt is prepended to the ciphertext so it can be recovered
|
|
92
|
+
* during decryption.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* const enc = new EncryptionAtRest();
|
|
97
|
+
* const payload = enc.encrypt("hello", "passphrase");
|
|
98
|
+
* const plain = enc.decrypt(payload, "passphrase");
|
|
99
|
+
* console.log(plain); // "hello"
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare class EncryptionAtRest {
|
|
103
|
+
private readonly algorithm;
|
|
104
|
+
private readonly keyDerivation;
|
|
105
|
+
private readonly encoding;
|
|
106
|
+
/**
|
|
107
|
+
* Create a new EncryptionAtRest instance.
|
|
108
|
+
*
|
|
109
|
+
* @param config - Optional configuration overrides
|
|
110
|
+
*/
|
|
111
|
+
constructor(config?: EncryptionConfig);
|
|
112
|
+
/**
|
|
113
|
+
* Encrypt a plaintext string using AES-256-GCM.
|
|
114
|
+
*
|
|
115
|
+
* A fresh random IV and PBKDF2 salt are generated for every call, meaning
|
|
116
|
+
* encrypting the same plaintext twice with the same key will produce
|
|
117
|
+
* different ciphertexts.
|
|
118
|
+
*
|
|
119
|
+
* @param plaintext - The string to encrypt
|
|
120
|
+
* @param key - Passphrase from which the encryption key is derived
|
|
121
|
+
* @returns An {@link EncryptedPayload} containing everything needed for decryption
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```typescript
|
|
125
|
+
* const payload = encryption.encrypt("my secret", "passphrase");
|
|
126
|
+
* // payload.ciphertext, payload.iv, payload.tag are all present
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
encrypt(plaintext: string, key: string): EncryptedPayload;
|
|
130
|
+
/**
|
|
131
|
+
* Decrypt an {@link EncryptedPayload} back to the original plaintext.
|
|
132
|
+
*
|
|
133
|
+
* @param payload - The encrypted payload produced by {@link encrypt}
|
|
134
|
+
* @param key - The same passphrase that was used for encryption
|
|
135
|
+
* @returns The original plaintext string
|
|
136
|
+
* @throws {Error} If the key is wrong or the payload has been tampered with
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* const plaintext = encryption.decrypt(payload, "passphrase");
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
decrypt(payload: EncryptedPayload, key: string): string;
|
|
144
|
+
/**
|
|
145
|
+
* Encrypt a JSON-serializable object.
|
|
146
|
+
*
|
|
147
|
+
* The object is serialized to JSON and then encrypted. The result is a
|
|
148
|
+
* single Base64/hex string that encodes the full {@link EncryptedPayload}
|
|
149
|
+
* as JSON.
|
|
150
|
+
*
|
|
151
|
+
* @typeParam T - Type of the object being encrypted
|
|
152
|
+
* @param obj - The object to encrypt
|
|
153
|
+
* @param key - Passphrase from which the encryption key is derived
|
|
154
|
+
* @returns A single encoded string representing the encrypted object
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```typescript
|
|
158
|
+
* const token = encryption.encryptObject({ userId: 1 }, "key");
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
encryptObject<T>(obj: T, key: string): string;
|
|
162
|
+
/**
|
|
163
|
+
* Decrypt a string produced by {@link encryptObject} back to the original
|
|
164
|
+
* typed object.
|
|
165
|
+
*
|
|
166
|
+
* @typeParam T - Expected type of the decrypted object
|
|
167
|
+
* @param ciphertext - The encoded string produced by {@link encryptObject}
|
|
168
|
+
* @param key - The same passphrase that was used for encryption
|
|
169
|
+
* @returns The original object
|
|
170
|
+
* @throws {Error} If decryption or JSON parsing fails
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* const obj = encryption.decryptObject<{ userId: number }>(token, "key");
|
|
175
|
+
* console.log(obj.userId); // 1
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
decryptObject<T>(ciphertext: string, key: string): T;
|
|
179
|
+
/**
|
|
180
|
+
* Re-encrypt data with a new key (key rotation).
|
|
181
|
+
*
|
|
182
|
+
* This is a convenience method that decrypts with the old key and
|
|
183
|
+
* re-encrypts with the new key in a single call. It works with the
|
|
184
|
+
* encoded strings produced by {@link encryptObject}.
|
|
185
|
+
*
|
|
186
|
+
* @param data - The encoded ciphertext string to re-encrypt
|
|
187
|
+
* @param oldKey - The current passphrase
|
|
188
|
+
* @param newKey - The new passphrase to encrypt with
|
|
189
|
+
* @returns A new encoded ciphertext string encrypted under the new key
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```typescript
|
|
193
|
+
* const rotated = encryption.rotateKey(existingCiphertext, "old-pass", "new-pass");
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
rotateKey(data: string, oldKey: string, newKey: string): string;
|
|
197
|
+
/**
|
|
198
|
+
* Derive a fixed-length encryption key from a passphrase and salt using
|
|
199
|
+
* PBKDF2.
|
|
200
|
+
*
|
|
201
|
+
* @param passphrase - The user-supplied passphrase
|
|
202
|
+
* @param salt - Random salt bytes
|
|
203
|
+
* @returns A Buffer of {@link KEY_LENGTH_BYTES} bytes
|
|
204
|
+
*/
|
|
205
|
+
private deriveKey;
|
|
206
|
+
}
|