@gravito/echo 3.0.1 → 3.1.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.
Files changed (173) hide show
  1. package/README.md +211 -0
  2. package/dist/atlas/src/DB.d.ts +301 -0
  3. package/dist/atlas/src/OrbitAtlas.d.ts +9 -0
  4. package/dist/atlas/src/config/defineConfig.d.ts +14 -0
  5. package/dist/atlas/src/config/index.d.ts +7 -0
  6. package/dist/atlas/src/config/loadConfig.d.ts +48 -0
  7. package/dist/atlas/src/connection/Connection.d.ts +108 -0
  8. package/dist/atlas/src/connection/ConnectionManager.d.ts +111 -0
  9. package/dist/atlas/src/drivers/BunSQLDriver.d.ts +32 -0
  10. package/dist/atlas/src/drivers/BunSQLPreparedStatement.d.ts +118 -0
  11. package/dist/atlas/src/drivers/MongoDBDriver.d.ts +36 -0
  12. package/dist/atlas/src/drivers/MySQLDriver.d.ts +66 -0
  13. package/dist/atlas/src/drivers/PostgresDriver.d.ts +83 -0
  14. package/dist/atlas/src/drivers/RedisDriver.d.ts +43 -0
  15. package/dist/atlas/src/drivers/SQLiteDriver.d.ts +45 -0
  16. package/dist/atlas/src/drivers/types.d.ts +260 -0
  17. package/dist/atlas/src/errors/index.d.ts +45 -0
  18. package/dist/atlas/src/grammar/Grammar.d.ts +342 -0
  19. package/dist/atlas/src/grammar/MongoGrammar.d.ts +47 -0
  20. package/dist/atlas/src/grammar/MySQLGrammar.d.ts +54 -0
  21. package/dist/atlas/src/grammar/NullGrammar.d.ts +35 -0
  22. package/dist/atlas/src/grammar/PostgresGrammar.d.ts +62 -0
  23. package/dist/atlas/src/grammar/SQLiteGrammar.d.ts +32 -0
  24. package/dist/atlas/src/index.d.ts +67 -0
  25. package/dist/atlas/src/migration/Migration.d.ts +64 -0
  26. package/dist/atlas/src/migration/MigrationRepository.d.ts +65 -0
  27. package/dist/atlas/src/migration/Migrator.d.ts +110 -0
  28. package/dist/atlas/src/migration/index.d.ts +6 -0
  29. package/dist/atlas/src/observability/AtlasMetrics.d.ts +11 -0
  30. package/dist/atlas/src/observability/AtlasObservability.d.ts +15 -0
  31. package/dist/atlas/src/observability/AtlasTracer.d.ts +12 -0
  32. package/dist/atlas/src/observability/index.d.ts +9 -0
  33. package/dist/atlas/src/orm/index.d.ts +5 -0
  34. package/dist/atlas/src/orm/model/DirtyTracker.d.ts +121 -0
  35. package/dist/atlas/src/orm/model/Model.d.ts +449 -0
  36. package/dist/atlas/src/orm/model/ModelRegistry.d.ts +20 -0
  37. package/dist/atlas/src/orm/model/concerns/HasAttributes.d.ts +136 -0
  38. package/dist/atlas/src/orm/model/concerns/HasEvents.d.ts +36 -0
  39. package/dist/atlas/src/orm/model/concerns/HasPersistence.d.ts +87 -0
  40. package/dist/atlas/src/orm/model/concerns/HasRelationships.d.ts +117 -0
  41. package/dist/atlas/src/orm/model/concerns/HasSerialization.d.ts +64 -0
  42. package/dist/atlas/src/orm/model/concerns/applyMixins.d.ts +15 -0
  43. package/dist/atlas/src/orm/model/concerns/index.d.ts +12 -0
  44. package/dist/atlas/src/orm/model/decorators.d.ts +109 -0
  45. package/dist/atlas/src/orm/model/errors.d.ts +52 -0
  46. package/dist/atlas/src/orm/model/index.d.ts +10 -0
  47. package/dist/atlas/src/orm/model/relationships.d.ts +207 -0
  48. package/dist/atlas/src/orm/model/types.d.ts +12 -0
  49. package/dist/atlas/src/orm/schema/SchemaRegistry.d.ts +123 -0
  50. package/dist/atlas/src/orm/schema/SchemaSniffer.d.ts +54 -0
  51. package/dist/atlas/src/orm/schema/index.d.ts +6 -0
  52. package/dist/atlas/src/orm/schema/types.d.ts +85 -0
  53. package/dist/atlas/src/query/Expression.d.ts +60 -0
  54. package/dist/atlas/src/query/NPlusOneDetector.d.ts +10 -0
  55. package/dist/atlas/src/query/QueryBuilder.d.ts +573 -0
  56. package/dist/atlas/src/query/clauses/GroupByClause.d.ts +51 -0
  57. package/dist/atlas/src/query/clauses/HavingClause.d.ts +70 -0
  58. package/dist/atlas/src/query/clauses/JoinClause.d.ts +87 -0
  59. package/dist/atlas/src/query/clauses/LimitClause.d.ts +82 -0
  60. package/dist/atlas/src/query/clauses/OrderByClause.d.ts +69 -0
  61. package/dist/atlas/src/query/clauses/SelectClause.d.ts +71 -0
  62. package/dist/atlas/src/query/clauses/WhereClause.d.ts +167 -0
  63. package/dist/atlas/src/query/clauses/index.d.ts +11 -0
  64. package/dist/atlas/src/schema/Blueprint.d.ts +276 -0
  65. package/dist/atlas/src/schema/ColumnDefinition.d.ts +154 -0
  66. package/dist/atlas/src/schema/ForeignKeyDefinition.d.ts +37 -0
  67. package/dist/atlas/src/schema/Schema.d.ts +131 -0
  68. package/dist/atlas/src/schema/grammars/MySQLSchemaGrammar.d.ts +23 -0
  69. package/dist/atlas/src/schema/grammars/PostgresSchemaGrammar.d.ts +26 -0
  70. package/dist/atlas/src/schema/grammars/SQLiteSchemaGrammar.d.ts +28 -0
  71. package/dist/atlas/src/schema/grammars/SchemaGrammar.d.ts +97 -0
  72. package/dist/atlas/src/schema/grammars/index.d.ts +7 -0
  73. package/dist/atlas/src/schema/index.d.ts +8 -0
  74. package/dist/atlas/src/seed/Factory.d.ts +90 -0
  75. package/dist/atlas/src/seed/Seeder.d.ts +28 -0
  76. package/dist/atlas/src/seed/SeederRunner.d.ts +74 -0
  77. package/dist/atlas/src/seed/index.d.ts +6 -0
  78. package/dist/atlas/src/types/index.d.ts +1100 -0
  79. package/dist/atlas/src/utils/levenshtein.d.ts +9 -0
  80. package/dist/core/src/Application.d.ts +43 -17
  81. package/dist/core/src/CommandKernel.d.ts +33 -0
  82. package/dist/core/src/Container.d.ts +78 -14
  83. package/dist/core/src/HookManager.d.ts +422 -8
  84. package/dist/core/src/PlanetCore.d.ts +52 -7
  85. package/dist/core/src/Router.d.ts +41 -7
  86. package/dist/core/src/ServiceProvider.d.ts +14 -8
  87. package/dist/core/src/adapters/GravitoEngineAdapter.d.ts +1 -0
  88. package/dist/core/src/adapters/PhotonAdapter.d.ts +1 -0
  89. package/dist/core/src/adapters/bun/BunNativeAdapter.d.ts +1 -0
  90. package/dist/core/src/adapters/types.d.ts +39 -0
  91. package/dist/core/src/engine/AOTRouter.d.ts +1 -11
  92. package/dist/core/src/engine/FastContext.d.ts +4 -2
  93. package/dist/core/src/engine/Gravito.d.ts +1 -1
  94. package/dist/core/src/engine/MinimalContext.d.ts +4 -2
  95. package/dist/core/src/engine/types.d.ts +6 -1
  96. package/dist/core/src/events/CircuitBreaker.d.ts +229 -0
  97. package/dist/core/src/events/DeadLetterQueue.d.ts +145 -0
  98. package/dist/core/src/events/EventBackend.d.ts +11 -0
  99. package/dist/core/src/events/EventOptions.d.ts +109 -0
  100. package/dist/core/src/events/EventPriorityQueue.d.ts +202 -0
  101. package/dist/core/src/events/IdempotencyCache.d.ts +60 -0
  102. package/dist/core/src/events/index.d.ts +14 -0
  103. package/dist/core/src/events/observability/EventMetrics.d.ts +132 -0
  104. package/dist/core/src/events/observability/EventTracer.d.ts +68 -0
  105. package/dist/core/src/events/observability/EventTracing.d.ts +161 -0
  106. package/dist/core/src/events/observability/OTelEventMetrics.d.ts +240 -0
  107. package/dist/core/src/events/observability/ObservableHookManager.d.ts +108 -0
  108. package/dist/core/src/events/observability/index.d.ts +20 -0
  109. package/dist/core/src/events/observability/metrics-types.d.ts +16 -0
  110. package/dist/core/src/events/types.d.ts +75 -0
  111. package/dist/core/src/exceptions/CircularDependencyException.d.ts +9 -0
  112. package/dist/core/src/exceptions/index.d.ts +1 -0
  113. package/dist/core/src/http/cookie.d.ts +29 -0
  114. package/dist/core/src/http/types.d.ts +21 -0
  115. package/dist/core/src/index.d.ts +13 -3
  116. package/dist/core/src/instrumentation/index.d.ts +35 -0
  117. package/dist/core/src/instrumentation/opentelemetry.d.ts +178 -0
  118. package/dist/core/src/instrumentation/types.d.ts +182 -0
  119. package/dist/core/src/reliability/DeadLetterQueueManager.d.ts +316 -0
  120. package/dist/core/src/reliability/RetryPolicy.d.ts +217 -0
  121. package/dist/core/src/reliability/index.d.ts +6 -0
  122. package/dist/core/src/router/ControllerDispatcher.d.ts +12 -0
  123. package/dist/core/src/router/RequestValidator.d.ts +20 -0
  124. package/dist/echo/src/OrbitEcho.d.ts +71 -16
  125. package/dist/echo/src/dlq/DeadLetterQueue.d.ts +94 -0
  126. package/dist/echo/src/dlq/MemoryDeadLetterQueue.d.ts +36 -0
  127. package/dist/echo/src/dlq/index.d.ts +2 -0
  128. package/dist/echo/src/index.d.ts +31 -15
  129. package/dist/echo/src/middleware/RequestBufferMiddleware.d.ts +62 -0
  130. package/dist/echo/src/middleware/index.d.ts +8 -0
  131. package/dist/echo/src/observability/index.d.ts +3 -0
  132. package/dist/echo/src/observability/logging/ConsoleEchoLogger.d.ts +37 -0
  133. package/dist/echo/src/observability/logging/EchoLogger.d.ts +38 -0
  134. package/dist/echo/src/observability/logging/index.d.ts +2 -0
  135. package/dist/echo/src/observability/metrics/MetricsProvider.d.ts +69 -0
  136. package/dist/echo/src/observability/metrics/NoopMetricsProvider.d.ts +17 -0
  137. package/dist/echo/src/observability/metrics/PrometheusMetricsProvider.d.ts +39 -0
  138. package/dist/echo/src/observability/metrics/index.d.ts +3 -0
  139. package/dist/echo/src/observability/tracing/NoopTracer.d.ts +33 -0
  140. package/dist/echo/src/observability/tracing/Tracer.d.ts +75 -0
  141. package/dist/echo/src/observability/tracing/index.d.ts +2 -0
  142. package/dist/echo/src/providers/GenericProvider.d.ts +37 -18
  143. package/dist/echo/src/providers/GitHubProvider.d.ts +21 -12
  144. package/dist/echo/src/providers/LinearProvider.d.ts +27 -0
  145. package/dist/echo/src/providers/PaddleProvider.d.ts +31 -0
  146. package/dist/echo/src/providers/ShopifyProvider.d.ts +27 -0
  147. package/dist/echo/src/providers/SlackProvider.d.ts +27 -0
  148. package/dist/echo/src/providers/StripeProvider.d.ts +20 -12
  149. package/dist/echo/src/providers/TwilioProvider.d.ts +31 -0
  150. package/dist/echo/src/providers/base/BaseProvider.d.ts +87 -0
  151. package/dist/echo/src/providers/base/HeaderUtils.d.ts +34 -0
  152. package/dist/echo/src/providers/index.d.ts +14 -3
  153. package/dist/echo/src/receive/SignatureValidator.d.ts +33 -0
  154. package/dist/echo/src/receive/WebhookReceiver.d.ts +139 -21
  155. package/dist/echo/src/replay/WebhookReplayService.d.ts +35 -0
  156. package/dist/echo/src/replay/index.d.ts +1 -0
  157. package/dist/echo/src/resilience/CircuitBreaker.d.ts +117 -0
  158. package/dist/echo/src/resilience/index.d.ts +10 -0
  159. package/dist/echo/src/rotation/KeyRotationManager.d.ts +127 -0
  160. package/dist/echo/src/rotation/index.d.ts +10 -0
  161. package/dist/echo/src/send/WebhookDispatcher.d.ts +159 -15
  162. package/dist/echo/src/storage/MemoryWebhookStore.d.ts +14 -0
  163. package/dist/echo/src/storage/WebhookStore.d.ts +236 -0
  164. package/dist/echo/src/storage/index.d.ts +2 -0
  165. package/dist/echo/src/types.d.ts +656 -64
  166. package/dist/index.js +1327 -189
  167. package/dist/index.js.map +28 -10
  168. package/dist/photon/src/index.d.ts +69 -5
  169. package/dist/photon/src/middleware/binary.d.ts +12 -15
  170. package/dist/photon/src/middleware/htmx.d.ts +39 -0
  171. package/dist/photon/src/middleware/ratelimit.d.ts +157 -0
  172. package/dist/photon/src/openapi.d.ts +19 -0
  173. package/package.json +7 -5
@@ -1,164 +1,756 @@
1
+ import type { DeadLetterQueue } from './dlq/DeadLetterQueue';
2
+ import type { EchoLogger } from './observability/logging';
3
+ import type { MetricsProvider } from './observability/metrics';
4
+ import type { Tracer } from './observability/tracing';
5
+ import type { WebhookStore } from './storage/WebhookStore';
1
6
  /**
2
- * @fileoverview Core types for @gravito/echo webhook module
3
- * @module @gravito/echo
7
+ * Core types for the Echo module.
8
+ *
9
+ * This module defines the fundamental structures for both receiving and sending webhooks,
10
+ * ensuring a consistent interface across different providers and delivery targets.
11
+ *
12
+ * @packageDocumentation
4
13
  */
5
14
  /**
6
- * Configuration for a specific webhook provider (e.g., Stripe, GitHub).
15
+ * Configuration for a specific webhook provider instance.
16
+ *
17
+ * This interface defines the essential security and routing parameters required to
18
+ * authenticate incoming requests from external services. It acts as a contract
19
+ * between the Echo receiver and the specific provider implementation.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const stripeConfig: WebhookProviderConfig = {
24
+ * name: 'stripe_prod',
25
+ * secret: process.env.STRIPE_WEBHOOK_SECRET,
26
+ * signatureHeader: 'stripe-signature',
27
+ * tolerance: 300 // Allow for 5 minutes of clock drift
28
+ * };
29
+ * ```
30
+ *
7
31
  * @public
8
32
  */
9
33
  export interface WebhookProviderConfig {
10
- /** The unique name of the provider */
34
+ /**
35
+ * A unique identifier for this provider configuration instance.
36
+ * This name is used to route incoming requests to the correct security context.
37
+ */
11
38
  name: string;
12
- /** The shared secret used to verify incoming webhook signatures */
39
+ /**
40
+ * The cryptographic shared secret used to verify request signatures.
41
+ * Depending on the provider, this might be a signing secret or a client secret.
42
+ */
13
43
  secret: string;
14
- /** The name of the HTTP header containing the signature (e.g., 'stripe-signature') */
44
+ /**
45
+ * The specific HTTP header name containing the signature.
46
+ * If omitted, the provider's default header (e.g., 'x-hub-signature-256' for GitHub) is used.
47
+ *
48
+ * @example 'x-paddle-signature'
49
+ */
15
50
  signatureHeader?: string;
16
- /** Maximum allowed time drift in seconds for timestamp validation (default: 300) */
51
+ /**
52
+ * The maximum permissible age of a webhook request in seconds.
53
+ * Used to mitigate replay attacks by ensuring the request was recently signed.
54
+ *
55
+ * @defaultValue 300
56
+ */
17
57
  tolerance?: number;
18
58
  }
19
59
  /**
20
- * The result of verifying an incoming webhook request.
60
+ * The normalized result of a webhook authenticity and integrity check.
61
+ *
62
+ * This structure encapsulates the outcome of the verification process, providing
63
+ * both the status and the extracted data needed for subsequent processing.
64
+ *
21
65
  * @public
22
66
  */
23
67
  export interface WebhookVerificationResult {
24
- /** True if the signature is valid and the timestamp is within tolerance */
68
+ /**
69
+ * Indicates whether the cryptographic signature is valid and the request
70
+ * falls within the specified time tolerance window.
71
+ */
25
72
  valid: boolean;
26
- /** Descriptive error message if the verification failed */
73
+ /**
74
+ * A human-readable or machine-parsable explanation of why verification failed.
75
+ * Only populated when `valid` is false.
76
+ */
27
77
  error?: string;
28
- /** The parsed JSON payload from the request body */
78
+ /**
79
+ * The parsed JSON payload extracted from the validated request body.
80
+ * Guaranteed to be available and authentic if `valid` is true.
81
+ */
29
82
  payload?: unknown;
30
- /** The specific event name extracted from the payload or headers */
83
+ /**
84
+ * The semantic category of the event (e.g., 'invoice.created').
85
+ * Inferred by the provider implementation during verification.
86
+ */
31
87
  eventType?: string;
32
- /** The unique identifier for this webhook message, if provided by the source */
88
+ /**
89
+ * The unique ID assigned to this event by the source service.
90
+ * Used for idempotency checks and audit logging.
91
+ */
33
92
  webhookId?: string;
34
93
  }
35
94
  /**
36
- * Interface that all webhook provider implementations must follow.
37
- * Providers handle the logic for specific services like Stripe or Shopify.
95
+ * Contract for implementing service-specific webhook verification and parsing.
96
+ *
97
+ * Implementations of this interface handle the low-level, service-specific details
98
+ * of signature algorithms (HMAC, RSA), timestamp header formats, and payload
99
+ * structure for specific providers like Stripe, GitHub, or Shopify.
100
+ *
38
101
  * @public
39
102
  */
40
103
  export interface WebhookProvider {
41
- /** Uniquely identifies the provider (e.g., 'stripe') */
104
+ /**
105
+ * The canonical type name of the provider.
106
+ * This name is used to match incoming requests to the correct implementation.
107
+ *
108
+ * @example 'stripe'
109
+ */
42
110
  readonly name: string;
43
111
  /**
44
- * Validates the integrity and authenticity of an incoming request.
112
+ * Validates the cryptographic integrity and temporal validity of a request.
45
113
  *
46
- * @param payload - The raw request body as a string or Buffer.
47
- * @param headers - The incoming HTTP headers.
48
- * @param secret - The secret key used for verification.
114
+ * This method must perform signature check and timestamp validation to prevent
115
+ * forgery and replay attacks.
116
+ *
117
+ * @param payload - The exact raw request body as received (crucial for HMAC).
118
+ * @param headers - Complete HTTP headers from the incoming request.
119
+ * @param secret - The configured secret key for the provider instance.
120
+ * @returns A promise resolving to the verification result and parsed payload.
121
+ * @throws {Error} Should only throw for unexpected internal errors, not for invalid signatures.
49
122
  */
50
123
  verify(payload: string | Buffer, headers: Record<string, string | string[] | undefined>, secret: string): Promise<WebhookVerificationResult>;
51
124
  /**
52
- * Determines the event type from the validated payload.
53
- * @param payload - The parsed JSON body.
125
+ * Identifies the semantic event type from a validated and parsed payload.
126
+ *
127
+ * @param payload - The authentic data object returned by `verify`.
128
+ * @returns The event type string (e.g., 'customer.subscription.deleted') or undefined if unrecognized.
54
129
  */
55
130
  parseEventType?(payload: unknown): string | undefined;
56
131
  }
57
132
  /**
58
- * A callback function triggered when a valid webhook event is received.
133
+ * A callback function triggered when a valid webhook event is matched and processed.
134
+ *
135
+ * @param event - The normalized and authenticated webhook event object.
59
136
  * @public
60
137
  */
61
138
  export type WebhookHandler<T = unknown> = (event: WebhookEvent<T>) => void | Promise<void>;
62
139
  /**
63
- * Represents a normalized webhook event processed by Echo.
64
- * Provides a consistent interface regardless of the source provider.
140
+ * Normalized representation of an authenticated incoming webhook event.
141
+ *
142
+ * Echo transforms diverse provider-specific requests into this standard format,
143
+ * allowing application logic to remain decoupled from the specifics of the source service.
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * const processOrder: WebhookHandler<OrderData> = async (event) => {
148
+ * const { provider, type, payload } = event;
149
+ * console.log(`Processing ${type} from ${provider}`);
150
+ * await updateDatabase(payload.orderId);
151
+ * };
152
+ * ```
153
+ *
65
154
  * @public
66
155
  */
67
156
  export interface WebhookEvent<T = unknown> {
68
- /** Name of the provider that sent the event */
157
+ /**
158
+ * The name of the provider instance that received and verified this event.
159
+ */
69
160
  provider: string;
70
- /** The type of event (e.g., 'payment_intent.succeeded') */
161
+ /**
162
+ * The semantic category of the event (e.g., 'payment.captured').
163
+ */
71
164
  type: string;
72
- /** The parsed and type-safe data payload */
165
+ /**
166
+ * The parsed and type-safe data payload.
167
+ */
73
168
  payload: T;
74
- /** The original HTTP headers received with the request */
169
+ /**
170
+ * The original HTTP headers received with the request.
171
+ */
75
172
  headers: Record<string, string | string[] | undefined>;
76
- /** The raw, unparsed request body string */
173
+ /**
174
+ * The exact raw request body, preserved for audit trails or re-verification.
175
+ */
77
176
  rawBody: string;
78
- /** The local system time when the webhook was received */
177
+ /**
178
+ * The high-precision timestamp when the event was successfully processed by Echo.
179
+ */
79
180
  receivedAt: Date;
80
- /** Unique ID for the event, if provided by the source */
181
+ /**
182
+ * The unique ID assigned by the upstream service for this event.
183
+ */
81
184
  id?: string;
82
185
  }
83
186
  /**
84
- * Data structure for sending a webhook to an external service.
187
+ * A snapshot of a raw HTTP request before body parsing occurs.
188
+ *
189
+ * This is used by middleware to prevent upstream body parsers from modifying the
190
+ * raw request body, which would otherwise invalidate cryptographic signatures.
191
+ *
192
+ * @public
193
+ */
194
+ export interface BufferedRequest {
195
+ /**
196
+ * The exact raw body as received from the socket.
197
+ */
198
+ rawBody: string | Buffer;
199
+ /**
200
+ * A lazily-evaluated parsed version of the body if requested by handlers.
201
+ */
202
+ parsedBody?: unknown;
203
+ /**
204
+ * The original request headers.
205
+ */
206
+ headers: Record<string, string | string[] | undefined>;
207
+ /**
208
+ * The timestamp when the request entered the buffer.
209
+ */
210
+ bufferedAt: Date;
211
+ }
212
+ /**
213
+ * Operational settings for the request buffering mechanism.
214
+ *
215
+ * @public
216
+ */
217
+ export interface RequestBufferConfig {
218
+ /**
219
+ * Whether to activate the buffering middleware.
220
+ * @defaultValue true
221
+ */
222
+ enabled?: boolean;
223
+ /**
224
+ * The maximum size of the request body allowed to be buffered (in bytes).
225
+ * Prevents memory exhaustion attacks.
226
+ * @defaultValue 10485760 (10MB)
227
+ */
228
+ maxBodySize?: number;
229
+ /**
230
+ * List of MIME types that should bypass the buffering logic.
231
+ * Useful for large file uploads or binary streams.
232
+ * @defaultValue ['multipart/form-data', 'application/octet-stream']
233
+ */
234
+ skipContentTypes?: string[];
235
+ }
236
+ /**
237
+ * The current operational state of a circuit breaker.
238
+ *
239
+ * - `CLOSED`: Healthy state, allowing all requests through.
240
+ * - `OPEN`: Failing state, blocking all requests to prevent cascading failure.
241
+ * - `HALF_OPEN`: Recovery state, allowing a limited number of test requests.
242
+ *
243
+ * @public
244
+ */
245
+ export type CircuitBreakerState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
246
+ /**
247
+ * Resilience configuration for outgoing webhook delivery.
248
+ *
249
+ * Protects downstream consumers from being overwhelmed during outages and prevents
250
+ * the dispatcher from wasting resources on doomed requests.
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * const cbConfig: CircuitBreakerConfig = {
255
+ * failureThreshold: 10,
256
+ * windowSize: 30000, // 30 seconds
257
+ * openTimeout: 60000 // Stay open for 1 minute
258
+ * };
259
+ * ```
260
+ *
261
+ * @public
262
+ */
263
+ export interface CircuitBreakerConfig {
264
+ /**
265
+ * Whether to enable circuit breaking for the dispatcher.
266
+ * @defaultValue true
267
+ */
268
+ enabled?: boolean;
269
+ /**
270
+ * Number of consecutive failures required to trip the circuit to `OPEN`.
271
+ * @defaultValue 5
272
+ */
273
+ failureThreshold?: number;
274
+ /**
275
+ * Number of consecutive successes required in `HALF_OPEN` to return to `CLOSED`.
276
+ * @defaultValue 2
277
+ */
278
+ successThreshold?: number;
279
+ /**
280
+ * The rolling time window (in ms) within which failures are counted.
281
+ * @defaultValue 60000 (1 minute)
282
+ */
283
+ windowSize?: number;
284
+ /**
285
+ * Duration (in ms) to wait in `OPEN` state before transitioning to `HALF_OPEN`.
286
+ * @defaultValue 30000 (30 seconds)
287
+ */
288
+ openTimeout?: number;
289
+ /**
290
+ * Callback executed when the circuit trips to `OPEN`.
291
+ */
292
+ onOpen?: (target: string) => void;
293
+ /**
294
+ * Callback executed when the circuit enters `HALF_OPEN` state.
295
+ */
296
+ onHalfOpen?: (target: string) => void;
297
+ /**
298
+ * Callback executed when the circuit returns to `CLOSED` state.
299
+ */
300
+ onClose?: (target: string) => void;
301
+ }
302
+ /**
303
+ * Real-time operational metrics for a specific circuit breaker instance.
304
+ *
305
+ * Provides visibility into the health and traffic patterns of a downstream
306
+ * webhook target.
307
+ *
308
+ * @public
309
+ */
310
+ export interface CircuitBreakerMetrics {
311
+ /**
312
+ * The current state of the circuit (CLOSED, OPEN, or HALF_OPEN).
313
+ */
314
+ state: CircuitBreakerState;
315
+ /**
316
+ * The total number of failed requests recorded within the current time window.
317
+ */
318
+ failures: number;
319
+ /**
320
+ * The total number of successful requests recorded within the current time window.
321
+ */
322
+ successes: number;
323
+ /**
324
+ * The exact time when the most recent failure occurred.
325
+ */
326
+ lastFailureAt?: Date;
327
+ /**
328
+ * The exact time when the most recent success occurred.
329
+ */
330
+ lastSuccessAt?: Date;
331
+ /**
332
+ * If the circuit is currently `OPEN`, this is the timestamp when it tripped.
333
+ */
334
+ openedAt?: Date;
335
+ }
336
+ /**
337
+ * Metadata and value for a single version of a provider's secret key.
338
+ *
339
+ * Echo supports multiple concurrent keys per provider to facilitate zero-downtime
340
+ * key rotation. The receiver will attempt verification with all active keys.
341
+ *
342
+ * @public
343
+ */
344
+ export interface ProviderKeyEntry {
345
+ /**
346
+ * The raw cryptographic secret key value.
347
+ */
348
+ key: string;
349
+ /**
350
+ * The timestamp when this key becomes eligible for use in verification.
351
+ */
352
+ activeFrom: Date;
353
+ /**
354
+ * The timestamp when this key should no longer be used.
355
+ * If omitted, the key remains valid indefinitely until manually removed.
356
+ */
357
+ expiresAt?: Date;
358
+ /**
359
+ * Whether this key is the primary (current) secret.
360
+ * New configurations or rotations should generally promote a new key to primary.
361
+ */
362
+ isPrimary: boolean;
363
+ /**
364
+ * A unique identifier for this key version (e.g., a timestamp or serial).
365
+ */
366
+ version: string;
367
+ }
368
+ /**
369
+ * Policy settings for managing the lifecycle of webhook secrets.
370
+ *
371
+ * Key rotation allows you to replace compromised or aging secrets without
372
+ * dropping incoming webhooks from services that may still be using the old key.
373
+ *
374
+ * @public
375
+ */
376
+ export interface KeyRotationConfig {
377
+ /**
378
+ * Whether to enable the multi-key verification logic and rotation manager.
379
+ * @defaultValue false
380
+ */
381
+ enabled?: boolean;
382
+ /**
383
+ * Automatically purge keys that have passed their `expiresAt` date.
384
+ * @defaultValue true
385
+ */
386
+ autoCleanup?: boolean;
387
+ /**
388
+ * The duration (in ms) to keep an old key active after a new primary key is promoted.
389
+ * Prevents race conditions during the propagation of the new secret.
390
+ * @defaultValue 86400000 (24 hours)
391
+ */
392
+ gracePeriod?: number;
393
+ /**
394
+ * An optional asynchronous function to fetch keys from an external vault (e.g., AWS Secrets Manager).
395
+ */
396
+ keyProvider?: (providerName: string) => Promise<ProviderKeyEntry[]>;
397
+ /**
398
+ * Callback executed whenever a new key is successfully rotated.
399
+ */
400
+ onRotate?: (providerName: string, newKey: ProviderKeyEntry) => void;
401
+ }
402
+ /**
403
+ * Configuration for a provider that includes advanced key rotation settings.
404
+ *
405
+ * Extends the basic provider configuration with a list of historical and future keys.
406
+ *
407
+ * @public
408
+ */
409
+ export interface WebhookProviderConfigWithRotation extends WebhookProviderConfig {
410
+ /**
411
+ * Collection of valid keys for this provider.
412
+ */
413
+ keys?: ProviderKeyEntry[];
414
+ /**
415
+ * Specific rotation overrides for this provider.
416
+ */
417
+ rotation?: KeyRotationConfig;
418
+ }
419
+ /**
420
+ * Structure representing an intent to dispatch a webhook to an external target.
421
+ *
422
+ * @example
423
+ * ```typescript
424
+ * const payload: WebhookPayload = {
425
+ * url: 'https://customer-api.com/hooks',
426
+ * event: 'order.shipped',
427
+ * data: { trackingNumber: 'XYZ123' },
428
+ * timestamp: new Date()
429
+ * };
430
+ * ```
431
+ *
85
432
  * @public
86
433
  */
87
434
  export interface WebhookPayload<T = unknown> {
88
- /** The destination URL where the webhook should be POSTed */
435
+ /**
436
+ * The fully-qualified destination URL for the HTTP POST request.
437
+ */
89
438
  url: string;
90
- /** The name of the event being dispatched */
439
+ /**
440
+ * The semantic name of the event being broadcast.
441
+ */
91
442
  event: string;
92
- /** The data to be JSON-encoded and sent in the body */
443
+ /**
444
+ * The data payload to be serialized as JSON in the request body.
445
+ */
93
446
  data: T;
94
- /** Optional unique identifier for this specific delivery attempt */
447
+ /**
448
+ * An optional unique ID for this specific delivery attempt (for idempotency).
449
+ */
95
450
  id?: string;
96
- /** Optional timestamp representing when the event occurred */
451
+ /**
452
+ * The timestamp when the underlying event actually occurred.
453
+ */
97
454
  timestamp?: Date;
98
455
  }
99
456
  /**
100
- * Summary of a webhook delivery attempt.
457
+ * Detailed outcome of a single webhook delivery attempt.
458
+ *
101
459
  * @public
102
460
  */
103
461
  export interface WebhookDeliveryResult {
104
- /** True if the destination returned a 2xx status code */
462
+ /**
463
+ * True if the destination server returned a success status code (2xx).
464
+ */
105
465
  success: boolean;
106
- /** The HTTP status code returned by the destination server */
466
+ /**
467
+ * The numeric HTTP status code returned by the target server.
468
+ */
107
469
  statusCode?: number;
108
- /** The raw response body from the destination server */
470
+ /**
471
+ * The raw response body returned by the target server.
472
+ */
109
473
  body?: string;
110
- /** Error message if the request failed (e.g., network timeout) */
474
+ /**
475
+ * A descriptive error message if the network request or server returned an error.
476
+ */
111
477
  error?: string;
112
- /** Which attempt number this was (starts at 1) */
478
+ /**
479
+ * The sequence number of this delivery attempt (starts at 1).
480
+ */
113
481
  attempt: number;
114
- /** Total time elapsed for the request in milliseconds */
482
+ /**
483
+ * Total wall-clock time taken for the HTTP request in milliseconds.
484
+ */
115
485
  duration: number;
116
- /** Timestamp when the delivery attempt was recorded */
486
+ /**
487
+ * The exact timestamp when this delivery result was recorded.
488
+ */
117
489
  deliveredAt: Date;
118
490
  }
119
491
  /**
120
- * Strategy for retrying failed webhook deliveries with exponential backoff.
492
+ * Strategy settings for handling failed delivery attempts with exponential backoff.
493
+ *
121
494
  * @public
122
495
  */
123
496
  export interface RetryConfig {
124
- /** Maximum number of delivery attempts (default: 3) */
497
+ /**
498
+ * Maximum number of times to try delivering the webhook before giving up.
499
+ * @defaultValue 3
500
+ */
125
501
  maxAttempts?: number;
126
- /** Initial delay before the first retry in milliseconds (default: 1000) */
502
+ /**
503
+ * Initial delay (in ms) before the first retry attempt.
504
+ * @defaultValue 1000
505
+ */
127
506
  initialDelay?: number;
128
- /** Multiplier for the delay between subsequent retries (default: 2) */
507
+ /**
508
+ * The factor by which the delay increases after each failed attempt.
509
+ * @defaultValue 2
510
+ */
129
511
  backoffMultiplier?: number;
130
- /** Upper bound for the retry delay in milliseconds (default: 300,000) */
512
+ /**
513
+ * The absolute maximum delay (in ms) between retry attempts.
514
+ * @defaultValue 300000 (5 minutes)
515
+ */
131
516
  maxDelay?: number;
132
- /** List of HTTP status codes that should trigger a retry (e.g., 502, 503) */
517
+ /**
518
+ * List of HTTP status codes that should trigger a retry attempt.
519
+ * Codes not in this list (like 400 Bad Request) are considered terminal failures.
520
+ *
521
+ * @example [500, 502, 503, 504, 429]
522
+ */
133
523
  retryableStatuses?: number[];
134
524
  }
135
525
  /**
136
- * Configuration for the outgoing webhook dispatcher.
526
+ * Security and policy configuration for the outgoing webhook dispatcher.
527
+ *
528
+ * Use this interface to define how your application signs and delivers events
529
+ * to external consumers, ensuring both reliability and authenticity.
530
+ *
137
531
  * @public
138
532
  */
139
533
  export interface WebhookDispatcherConfig {
140
- /** Secret key used to sign outgoing webhook payloads for security */
534
+ /**
535
+ * Global secret key used to sign all outgoing webhook payloads.
536
+ * Consumers use this to verify the request originated from your application.
537
+ */
141
538
  secret: string;
142
- /** Optional retry strategy for failed deliveries */
539
+ /**
540
+ * Custom retry policy for handling transient delivery failures.
541
+ */
143
542
  retry?: RetryConfig;
144
- /** Maximum time in milliseconds to wait for a response (default: 30,000) */
543
+ /**
544
+ * The maximum time (in ms) to wait for the target server to respond.
545
+ * @defaultValue 30000
546
+ */
145
547
  timeout?: number;
146
- /** Custom User-Agent header for the outgoing request */
548
+ /**
549
+ * Custom string sent in the `User-Agent` HTTP header.
550
+ */
147
551
  userAgent?: string;
552
+ /**
553
+ * Operational settings for the circuit breaker mechanism.
554
+ * @since v1.1
555
+ */
556
+ circuitBreaker?: CircuitBreakerConfig;
557
+ }
558
+ /**
559
+ * Execution parameters for parallel or high-volume webhook dispatch operations.
560
+ *
561
+ * @public
562
+ */
563
+ export interface BatchDispatchOptions {
564
+ /**
565
+ * The maximum number of requests to execute simultaneously.
566
+ * Balancing performance vs. source/target rate limits.
567
+ * @defaultValue 5
568
+ */
569
+ concurrency?: number;
570
+ /**
571
+ * If true, the batch process will abort immediately if any single delivery fails.
572
+ * @defaultValue false
573
+ */
574
+ stopOnFirstFailure?: boolean;
148
575
  }
149
576
  /**
150
- * Full configuration for the OrbitEcho module.
577
+ * Detailed report of a batch dispatch operation's success and failure rates.
578
+ *
579
+ * @public
580
+ */
581
+ export interface BatchDispatchResult {
582
+ /**
583
+ * The total number of webhook payloads processed in this batch.
584
+ */
585
+ total: number;
586
+ /**
587
+ * Number of payloads that were successfully delivered (HTTP 2xx).
588
+ */
589
+ succeeded: number;
590
+ /**
591
+ * Number of payloads that failed delivery after all retries.
592
+ */
593
+ failed: number;
594
+ /**
595
+ * Individual delivery results mapped to their corresponding payloads.
596
+ */
597
+ results: Array<{
598
+ payload: WebhookPayload;
599
+ result: WebhookDeliveryResult;
600
+ }>;
601
+ }
602
+ /**
603
+ * Filter and execution parameters for replaying historical webhook events.
604
+ *
605
+ * Replay is useful for testing, recovery from consumer outages, or
606
+ * synchronizing data after a code update.
607
+ *
608
+ * @public
609
+ */
610
+ export interface ReplayOptions {
611
+ /**
612
+ * Specific event IDs to re-send. If provided, other filters are ignored.
613
+ */
614
+ eventIds?: string[];
615
+ /**
616
+ * Temporal range for selecting events from storage.
617
+ */
618
+ timeRange?: {
619
+ from: Date;
620
+ to: Date;
621
+ };
622
+ /**
623
+ * Limit replay to a specific provider instance.
624
+ */
625
+ provider?: string;
626
+ /**
627
+ * Limit replay to a specific semantic event type.
628
+ */
629
+ eventType?: string;
630
+ /**
631
+ * If true, logs the actions without actually sending any network requests.
632
+ */
633
+ dryRun?: boolean;
634
+ /**
635
+ * Redirect the replayed events to a different URL instead of the original one.
636
+ */
637
+ targetUrl?: string;
638
+ }
639
+ /**
640
+ * Summary outcome of a mass event replay operation.
641
+ *
642
+ * @public
643
+ */
644
+ export interface ReplayResult {
645
+ /**
646
+ * Total number of events matching the replay filters.
647
+ */
648
+ total: number;
649
+ /**
650
+ * Number of events that were successfully re-dispatched.
651
+ */
652
+ replayed: number;
653
+ /**
654
+ * Number of events that were intentionally skipped (e.g., due to duplicate filters).
655
+ */
656
+ skipped: number;
657
+ /**
658
+ * Number of events that encountered errors during the replay attempt.
659
+ */
660
+ failed: number;
661
+ /**
662
+ * Detailed audit log for each event considered in the replay.
663
+ */
664
+ events: Array<{
665
+ eventId: string;
666
+ status: 'replayed' | 'skipped' | 'failed';
667
+ result?: WebhookDeliveryResult;
668
+ error?: string;
669
+ }>;
670
+ }
671
+ /**
672
+ * Integration points for external monitoring and diagnostic tools.
673
+ *
674
+ * Echo is designed to be fully observable, allowing you to plug in
675
+ * Prometheus, OpenTelemetry, or custom logging solutions.
676
+ *
677
+ * @public
678
+ */
679
+ export interface EchoObservabilityConfig {
680
+ /**
681
+ * Provider for collecting counters, histograms, and health metrics.
682
+ */
683
+ metrics?: MetricsProvider;
684
+ /**
685
+ * Distributed tracer for tracking the full lifecycle of a webhook request.
686
+ */
687
+ tracer?: Tracer;
688
+ /**
689
+ * Logger for recording security events and operational warnings.
690
+ */
691
+ logger?: EchoLogger;
692
+ }
693
+ /**
694
+ * The root configuration object for the OrbitEcho module.
695
+ *
696
+ * This structure defines the entire security, reliability, and persistence
697
+ * architecture for webhooks within a Gravito application.
698
+ *
699
+ * @example
700
+ * ```typescript
701
+ * const echoConfig: EchoConfig = {
702
+ * providers: {
703
+ * stripe: { name: 'stripe', secret: 'whsec_...' }
704
+ * },
705
+ * dispatcher: {
706
+ * secret: 'my-app-outbound-secret',
707
+ * retry: { maxAttempts: 5 }
708
+ * },
709
+ * store: new MyDatabaseStore(),
710
+ * basePath: '/v1/webhooks'
711
+ * };
712
+ * ```
713
+ *
151
714
  * @public
152
715
  */
153
716
  export interface EchoConfig {
154
- /** Map of named provider configurations for receiving webhooks */
155
- providers?: Record<string, WebhookProviderConfig>;
156
- /** Settings for sending webhooks to other services */
717
+ /**
718
+ * A registry of named provider configurations for authenticating incoming events.
719
+ */
720
+ providers?: Record<string, WebhookProviderConfig | WebhookProviderConfigWithRotation>;
721
+ /**
722
+ * Settings for signing and reliably delivering outgoing webhooks.
723
+ */
157
724
  dispatcher?: WebhookDispatcherConfig;
158
725
  /**
159
- * The URL prefix for the automatically generated webhook endpoints.
160
- * (e.g., '/webhooks' will create '/webhooks/:provider')
161
- * Default: '/webhooks'
726
+ * The root URL path where Echo will mount its internal webhook handlers.
727
+ * @defaultValue '/webhooks'
162
728
  */
163
729
  basePath?: string;
730
+ /**
731
+ * The persistence engine used for auditing, idempotency, and replay.
732
+ */
733
+ store?: WebhookStore;
734
+ /**
735
+ * The queue implementation for handling permanently failed events.
736
+ */
737
+ deadLetterQueue?: DeadLetterQueue;
738
+ /**
739
+ * Default performance and concurrency settings for bulk operations.
740
+ */
741
+ batch?: BatchDispatchOptions;
742
+ /**
743
+ * Settings for metrics, tracing, and logging.
744
+ */
745
+ observability?: EchoObservabilityConfig;
746
+ /**
747
+ * Advanced middleware settings for body preservation and integrity.
748
+ * @since 1.1.0
749
+ */
750
+ requestBuffer?: RequestBufferConfig;
751
+ /**
752
+ * Central policy settings for dynamic secret lifecycle management.
753
+ * @since 1.2.0
754
+ */
755
+ keyRotation?: KeyRotationConfig;
164
756
  }