@futurewindai/wotchi 0.1.0-beta.2 → 0.1.0-beta.6

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 (103) hide show
  1. package/README.md +178 -47
  2. package/SECURITY.md +2 -2
  3. package/dist/cjs/core/admission.js +22 -0
  4. package/dist/cjs/core/client.js +416 -21
  5. package/dist/cjs/core/config.js +193 -18
  6. package/dist/cjs/core/diagnostics.js +16 -1
  7. package/dist/cjs/core/group-store.js +22 -9
  8. package/dist/cjs/core/incident-builder.js +18 -0
  9. package/dist/cjs/core/incident-policy.js +2 -7
  10. package/dist/cjs/core/limits.js +17 -0
  11. package/dist/cjs/core/normalize.js +16 -6
  12. package/dist/cjs/core/notification-queue.js +92 -6
  13. package/dist/cjs/core/prometheus.js +129 -0
  14. package/dist/cjs/core/redact.js +57 -8
  15. package/dist/cjs/core/runtime-monitor.js +109 -0
  16. package/dist/cjs/index.js +8 -1
  17. package/dist/cjs/integrations/express/error-handler.js +21 -4
  18. package/dist/cjs/integrations/express/index.js +2 -1
  19. package/dist/cjs/integrations/express/status-observer.js +6 -0
  20. package/dist/cjs/integrations/nest/capture.js +21 -0
  21. package/dist/cjs/integrations/nest/exception-filter.js +64 -8
  22. package/dist/cjs/integrations/nest/filter-wrapper.js +17 -0
  23. package/dist/cjs/integrations/nest/index.js +7 -1
  24. package/dist/cjs/integrations/nest/module.js +44 -0
  25. package/dist/cjs/integrations/nest/register.js +15 -1
  26. package/dist/cjs/integrations/request-context.js +83 -1
  27. package/dist/cjs/notifiers/alert-payload.js +20 -0
  28. package/dist/cjs/notifiers/console.js +85 -15
  29. package/dist/cjs/notifiers/telegram-format.js +75 -5
  30. package/dist/cjs/notifiers/webhook-http.js +394 -0
  31. package/dist/cjs/notifiers/webhook.js +28 -0
  32. package/dist/esm/core/admission.js +19 -0
  33. package/dist/esm/core/client.js +416 -21
  34. package/dist/esm/core/config.js +193 -18
  35. package/dist/esm/core/diagnostics.js +16 -1
  36. package/dist/esm/core/group-store.js +22 -9
  37. package/dist/esm/core/incident-builder.js +18 -0
  38. package/dist/esm/core/incident-policy.js +2 -7
  39. package/dist/esm/core/limits.js +14 -0
  40. package/dist/esm/core/normalize.js +16 -6
  41. package/dist/esm/core/notification-queue.js +92 -6
  42. package/dist/esm/core/prometheus.js +125 -0
  43. package/dist/esm/core/redact.js +57 -8
  44. package/dist/esm/core/runtime-monitor.js +106 -0
  45. package/dist/esm/index.js +4 -1
  46. package/dist/esm/integrations/express/error-handler.js +21 -4
  47. package/dist/esm/integrations/express/index.js +1 -1
  48. package/dist/esm/integrations/express/status-observer.js +6 -0
  49. package/dist/esm/integrations/nest/capture.js +17 -0
  50. package/dist/esm/integrations/nest/exception-filter.js +65 -9
  51. package/dist/esm/integrations/nest/filter-wrapper.js +14 -0
  52. package/dist/esm/integrations/nest/index.js +3 -1
  53. package/dist/esm/integrations/nest/module.js +41 -0
  54. package/dist/esm/integrations/nest/register.js +15 -1
  55. package/dist/esm/integrations/request-context.js +83 -1
  56. package/dist/esm/notifiers/alert-payload.js +16 -0
  57. package/dist/esm/notifiers/console.js +85 -15
  58. package/dist/esm/notifiers/telegram-format.js +75 -5
  59. package/dist/esm/notifiers/webhook-http.js +387 -0
  60. package/dist/esm/notifiers/webhook.js +24 -0
  61. package/dist/types/core/admission.d.ts +10 -0
  62. package/dist/types/core/config.d.ts +17 -1
  63. package/dist/types/core/diagnostics.d.ts +7 -1
  64. package/dist/types/core/incident-policy.d.ts +1 -1
  65. package/dist/types/core/limits.d.ts +14 -0
  66. package/dist/types/core/notification-queue.d.ts +14 -1
  67. package/dist/types/core/prometheus.d.ts +7 -0
  68. package/dist/types/core/runtime-monitor.d.ts +15 -0
  69. package/dist/types/core/types.d.ts +111 -2
  70. package/dist/types/index.d.ts +8 -2
  71. package/dist/types/integrations/express/index.d.ts +2 -2
  72. package/dist/types/integrations/nest/capture.d.ts +4 -0
  73. package/dist/types/integrations/nest/exception-filter.d.ts +6 -2
  74. package/dist/types/integrations/nest/filter-wrapper.d.ts +7 -0
  75. package/dist/types/integrations/nest/index.d.ts +6 -2
  76. package/dist/types/integrations/nest/module.d.ts +9 -0
  77. package/dist/types/integrations/nest/register.d.ts +3 -0
  78. package/dist/types/integrations/request-context.d.ts +3 -0
  79. package/dist/types/notifiers/alert-payload.d.ts +5 -0
  80. package/dist/types/notifiers/webhook-http.d.ts +37 -0
  81. package/dist/types/notifiers/webhook.d.ts +4 -0
  82. package/dist/types-cjs/core/admission.d.cts +10 -0
  83. package/dist/types-cjs/core/config.d.cts +17 -1
  84. package/dist/types-cjs/core/diagnostics.d.cts +7 -1
  85. package/dist/types-cjs/core/incident-policy.d.cts +1 -1
  86. package/dist/types-cjs/core/limits.d.cts +14 -0
  87. package/dist/types-cjs/core/notification-queue.d.cts +14 -1
  88. package/dist/types-cjs/core/prometheus.d.cts +7 -0
  89. package/dist/types-cjs/core/runtime-monitor.d.cts +15 -0
  90. package/dist/types-cjs/core/types.d.cts +111 -2
  91. package/dist/types-cjs/index.d.cts +8 -2
  92. package/dist/types-cjs/integrations/express/index.d.cts +2 -2
  93. package/dist/types-cjs/integrations/nest/capture.d.cts +4 -0
  94. package/dist/types-cjs/integrations/nest/exception-filter.d.cts +6 -2
  95. package/dist/types-cjs/integrations/nest/filter-wrapper.d.cts +7 -0
  96. package/dist/types-cjs/integrations/nest/index.d.cts +6 -2
  97. package/dist/types-cjs/integrations/nest/module.d.cts +9 -0
  98. package/dist/types-cjs/integrations/nest/register.d.cts +3 -0
  99. package/dist/types-cjs/integrations/request-context.d.cts +3 -0
  100. package/dist/types-cjs/notifiers/alert-payload.d.cts +5 -0
  101. package/dist/types-cjs/notifiers/webhook-http.d.cts +37 -0
  102. package/dist/types-cjs/notifiers/webhook.d.cts +4 -0
  103. package/package.json +17 -4
package/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  # Wotchi
2
2
 
3
- > Bounded incident alerts for Node.js services.
3
+ > Low-noise error alerts for Node.js services.
4
4
 
5
- > **Status:** Public beta (`0.1.0-beta.2`). Install with the `beta` tag; the API may evolve before the first stable release.
5
+ > **Status:** Public beta (`0.1.0-beta.6`). The API may evolve before the first stable release.
6
6
 
7
7
  [![CI](https://github.com/FutureWindAI/Wotchi/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/FutureWindAI/Wotchi/actions/workflows/ci.yml)
8
8
  [![CodeQL](https://github.com/FutureWindAI/Wotchi/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/FutureWindAI/Wotchi/actions/workflows/codeql.yml)
9
9
  [![npm](https://img.shields.io/npm/v/%40futurewindai%2Fwotchi?label=npm%20beta)](https://www.npmjs.com/package/@futurewindai/wotchi)
10
- [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
11
- [![Node.js >=18.18](https://img.shields.io/badge/node-%3E%3D18.18.0-339933?logo=node.js&logoColor=white)](https://nodejs.org/en/about/previous-releases)
10
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://github.com/FutureWindAI/Wotchi/blob/v0.1.0-beta.6/LICENSE)
11
+ [![Node.js 18–26](https://img.shields.io/badge/node-18%E2%80%9326-339933?logo=node.js&logoColor=white)](https://nodejs.org/en/about/previous-releases)
12
12
 
13
- Wotchi captures application errors in-process, removes sensitive values, groups repeated failures, and delivers bounded console or Telegram alerts without changing framework response handling.
13
+ Wotchi captures application errors in-process, removes sensitive values, groups repeated failures, and delivers bounded console, Telegram, or HTTPS webhook alerts without changing framework response handling. It is a signal-conditioning layer, not a replacement for a full observability platform.
14
14
 
15
15
  ## Quick start
16
16
 
@@ -34,6 +34,8 @@ await wotchi.flush();
34
34
 
35
35
  The example uses a threshold of one so the alert is visible immediately. The default policy groups three matching errors in one minute and suppresses duplicate alerts during the cooldown. Capture is synchronous; call `flush()` when the host needs to wait for notifier work.
36
36
 
37
+ To validate a notifier without deliberately throwing an application error, call `const result = await wotchi.testAlert()` in a controlled setup. The structured result reports whether the alert was queued, flushed, delivered, or rejected by a notifier; configuration errors still throw during `createWotchi`.
38
+
37
39
  Example console output:
38
40
 
39
41
  ```text
@@ -54,26 +56,66 @@ notifier.
54
56
 
55
57
  ## What you get
56
58
 
57
- | Capability | Result |
58
- | ----------------------------------------- | ---------------------------------------------------------------------------------- |
59
- | Bounded capture and queueing | Repeated failures cannot create unbounded in-memory work. |
60
- | Redaction before processing | Sensitive values are removed before grouping, logging, or transmission. |
61
- | Grouping and cooldowns | Repeated failures produce a small number of useful alerts. |
62
- | Express 4/5 and NestJS 10/11 adapters | Errors are observed while the framework keeps response ownership. |
63
- | ESM, CommonJS, and TypeScript types | Use the package with common Node.js module setups. |
64
- | Console and optional Telegram notifiers | Start locally or self-host delivery without a Wotchi control plane. |
65
- | Optional status observation and JSON logs | Observe direct `401`/`403`/`429`/`5xx` responses and emit collector-friendly JSON. |
59
+ | Capability | Result |
60
+ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
61
+ | Bounded capture and queueing | Repeated failures cannot create unbounded in-memory work. |
62
+ | Redaction before processing | Sensitive values are removed before grouping, logging, or transmission. |
63
+ | Grouping and cooldowns | Repeated failures produce a small number of useful alerts. |
64
+ | Express 4/5 and NestJS 10/11 adapters | Errors are observed while the framework keeps response ownership. |
65
+ | ESM, CommonJS, and TypeScript types | Use the package with common Node.js module setups. |
66
+ | Console and optional Telegram notifiers | Start locally or self-host delivery without a Wotchi control plane. |
67
+ | Generic HTTPS webhook notifier | Route bounded JSON alerts to an existing internal alert destination. |
68
+ | Actionable context and trace passthrough | Include route, release, request/correlation IDs, operation/job, safe tags, links, and existing trace/span IDs. |
69
+ | Optional status observation and JSON logs | Observe direct `401`/`403`/`429`/`5xx` responses and emit collector-friendly JSON. |
70
+ | Optional diagnostics exporter | Expose aggregate Wotchi health counters to an existing Prometheus-compatible `/metrics` endpoint. |
71
+ | Optional overload admission | Drop capture work before normalization at a measured rate and emit one sanitized overload signal. |
72
+ | Notifier isolation and shutdown | Bound slow destinations, open circuits after repeated failures, and drain safely during termination. |
73
+ | Optional runtime pressure watcher | Threshold CPU, RSS, heap, event-loop delay, or pending alerts with numeric-only local samples. |
74
+
75
+ ## When to use Wotchi
76
+
77
+ Use Wotchi when an Express or NestJS service needs low-noise, privacy-conscious alerts without
78
+ adding a collector, database, or hosted account. Keep a full observability platform when you need
79
+ durable incident history, cross-replica deduplication, dashboards, traces, or paging workflows.
80
+
81
+ ## Performance evidence
82
+
83
+ The package has zero direct runtime dependencies and keeps capture, grouping, and notification work
84
+ bounded. On a Node.js 22/macOS arm64 benchmark run of beta.6, capture p95/p99 was
85
+ `0.036 ms`/`0.036 ms`, duplicate-storm retained heap was `0.194 MiB`, and the packed artifact was
86
+ `60,534 bytes`. Prometheus rendering p95 was `0.0048 ms`. The queue benchmark admitted `101` alerts while a notifier was blocked, capped
87
+ pending work at `100`, and kept Express and NestJS responses completing. These are reproducible local
88
+ measurements, not production guarantees; repeat `npm run benchmark` and `npm run benchmark:queue`
89
+ on your runtime and workload. See [performance evidence](docs/PERFORMANCE.md).
90
+
91
+ The exporter does not open a server or send data. Attach it to a protected endpoint owned
92
+ by the host application:
93
+
94
+ ```ts
95
+ import { createWotchiPrometheusExporter } from "@futurewindai/wotchi";
96
+
97
+ const metrics = createWotchiPrometheusExporter(wotchi);
98
+ app.get("/metrics", (_request, response) => {
99
+ response.setHeader("Content-Type", metrics.contentType);
100
+ response.send(metrics.render());
101
+ });
102
+ ```
103
+
104
+ Beta.6 also supports opt-in admission control, notifier timeouts/circuits, graceful shutdown, and a
105
+ numeric-only runtime watcher.
106
+
107
+ It emits only aggregate counters and queue/group gauges. Prometheus, Grafana, or another existing
108
+ collector remains responsible for scraping, authentication, retention, and dashboards.
66
109
 
67
110
  ## How it works
68
111
 
69
- ```mermaid
70
- flowchart LR
71
- A[Application error] --> B[Normalize and redact]
72
- B --> C[Stable fingerprint]
73
- C --> D[Threshold and cooldown]
74
- D --> E[Bounded queue]
75
- E --> F[Console]
76
- E --> G[Telegram]
112
+ ```text
113
+ Application error
114
+ -> normalize and redact
115
+ -> stable fingerprint and optional user rule
116
+ -> threshold and cooldown
117
+ -> bounded notification queue
118
+ -> console, Telegram, or HTTPS webhook
77
119
  ```
78
120
 
79
121
  The same bounded capture path can be called from HTTP handlers, background workers, and queue
@@ -99,15 +141,30 @@ const wotchi = createWotchi({
99
141
  app.use(wotchiErrorHandler(wotchi));
100
142
  ```
101
143
 
102
- NestJS applications register the delegating global filter once after creating the application:
144
+ NestJS applications can register Wotchi from the root module, keeping `main.ts` focused on
145
+ application bootstrap:
103
146
 
104
147
  ```ts
105
- import { registerWotchiNest } from "@futurewindai/wotchi/nest";
106
-
107
- registerWotchiNest(app, wotchi);
148
+ import { Module } from "@nestjs/common";
149
+ import { consoleNotifier } from "@futurewindai/wotchi";
150
+ import { WotchiModule } from "@futurewindai/wotchi/nest";
151
+
152
+ @Module({
153
+ imports: [
154
+ WotchiModule.forRoot({
155
+ service: "orders-api",
156
+ environment: "production",
157
+ notifiers: [consoleNotifier()],
158
+ }),
159
+ ],
160
+ })
161
+ export class AppModule {}
108
162
  ```
109
163
 
110
- The package supports Node.js `>=18.18.0`. Express and NestJS adapters are optional subpath integrations, so applications only load the framework adapter they use.
164
+ For a custom dependency-injected `APP_FILTER`, keep its response and logging behavior, disable the
165
+ automatic Wotchi filter, and wrap it with `withWotchiNestFilter`. See the [NestJS API](docs/API.md#nestjs-entry-point).
166
+
167
+ The package keeps compatibility with Node.js `>=18.18.0` and is tested across Node.js 18–26. Node.js 22 or 24 LTS is recommended for production. Express and NestJS adapters are optional subpath integrations, so applications only load the framework adapter they use.
111
168
 
112
169
  ## Telegram alerts
113
170
 
@@ -122,14 +179,88 @@ const wotchi = createWotchi({
122
179
  notifiers: [
123
180
  consoleNotifier(),
124
181
  telegramNotifier({
125
- botToken: process.env.WOTCHI_TELEGRAM_BOT_TOKEN ?? "",
126
- chatId: process.env.WOTCHI_TELEGRAM_CHAT_ID ?? "",
182
+ botToken: requiredEnv("WOTCHI_TELEGRAM_BOT_TOKEN"),
183
+ chatId: requiredEnv("WOTCHI_TELEGRAM_CHAT_ID"),
184
+ }),
185
+ ],
186
+ });
187
+
188
+ function requiredEnv(name: string): string {
189
+ const value = process.env[name];
190
+ if (value === undefined || value.trim() === "") {
191
+ throw new Error(`${name} must be configured before enabling Telegram`);
192
+ }
193
+ return value;
194
+ }
195
+ ```
196
+
197
+ Wotchi does not ship a shared bot token. Delivery is queued outside the request path and sends only the sanitized incident alert. See [configuration](https://github.com/FutureWindAI/Wotchi/blob/main/docs/CONFIGURATION.md) for notifier and security options.
198
+
199
+ ## HTTPS webhook alerts
200
+
201
+ Use the generic webhook when an existing internal alerting or automation endpoint accepts JSON. Wotchi requires HTTPS by default, bounds headers and payloads, emits a versioned `{ version: 1, type: "incident.alert", sentAt, alert }` envelope, times out delivery, and retries one `429`/`5xx` response. Explicit loopback HTTP can be enabled for a local collector with `allowHttpLoopback: true`:
202
+
203
+ ```ts
204
+ import { createWotchi, webhookNotifier } from "@futurewindai/wotchi";
205
+
206
+ const wotchi = createWotchi({
207
+ service: "orders-api",
208
+ environment: "production",
209
+ notifiers: [
210
+ webhookNotifier({
211
+ url: requiredEnv("WOTCHI_WEBHOOK_URL"),
212
+ headers: { Authorization: requiredEnv("WOTCHI_WEBHOOK_AUTH") },
213
+ payloadBuilder: (alert) => ({
214
+ incident: alert.fingerprint,
215
+ summary: alert.summary,
216
+ }),
127
217
  }),
128
218
  ],
129
219
  });
220
+
221
+ function requiredEnv(name: string): string {
222
+ const value = process.env[name];
223
+ if (value === undefined || value.trim() === "") {
224
+ throw new Error(`${name} must be configured before enabling the webhook`);
225
+ }
226
+ return value;
227
+ }
130
228
  ```
131
229
 
132
- Wotchi does not ship a shared bot token. Delivery is queued outside the request path and sends only the sanitized incident alert. See [configuration](docs/CONFIGURATION.md) for notifier and security options.
230
+ Keep the URL and authentication header outside source control. `payloadBuilder` receives a frozen, sanitized alert and its output is redacted and bounded before transport; it is not a hosted Wotchi collector.
231
+
232
+ ## Context, filtering, and existing traces
233
+
234
+ Pass safe operational context and an existing OpenTelemetry trace/span ID explicitly; Wotchi does not install an OpenTelemetry SDK:
235
+
236
+ ```ts
237
+ wotchi.captureEvent({
238
+ level: "error",
239
+ message: "payment provider failed",
240
+ error,
241
+ request: {
242
+ method: "POST",
243
+ route: "/orders/:id",
244
+ requestId: "req-123",
245
+ correlationId: "corr-456",
246
+ trace: { traceId, spanId },
247
+ },
248
+ operation: "orders.pay",
249
+ job: "payment-retry",
250
+ tags: { component: "checkout" },
251
+ context: { provider: "stripe" },
252
+ });
253
+ ```
254
+
255
+ Use `filter`, `fingerprint`, `beforeSend`, and bounded exact-match `rules` for service-specific noise and grouping controls. `filter` and fingerprint callbacks receive frozen, normalized, redacted events. `beforeSend` receives a frozen, sanitized `IncidentAlert`; return `null` to suppress it or a bounded alert to transform it. Hook failures are isolated and counted in diagnostics. Optional `links.log` and `links.trace` templates can use placeholders such as `{{service}}`, `{{requestId}}`, and `{{traceId}}`.
256
+
257
+ ## Deployment boundaries
258
+
259
+ Wotchi keeps grouping and cooldown state in one process. Replicas have independent state, restarts
260
+ reset groups, and a serverless instance can terminate before asynchronous delivery completes. An
261
+ in-process SDK cannot reliably detect an OOM kill, frozen event loop, host failure, or unavailable
262
+ network. Pair it with an external uptime monitor and keep graceful shutdown explicit; see the
263
+ [production recipe](https://github.com/FutureWindAI/Wotchi/blob/main/examples/production-recipe/README.md).
133
264
 
134
265
  ## Process monitoring
135
266
 
@@ -147,31 +278,31 @@ const monitor = registerWotchiProcessMonitor(wotchi);
147
278
  - A full observability, APM, or log-management platform.
148
279
  - A hosted dashboard, collector, or persistent incident database.
149
280
  - An AI-generated incident-summary service in this release.
150
- - A Slack, Discord, email, or generic webhook notifier in this release.
281
+ - A Slack, Discord, email, or full incident-workflow platform.
151
282
  - A Docker, Kubernetes, or Helm collector bundled into the npm SDK.
152
283
  - An automatic-remediation system.
153
284
 
154
285
  ## Documentation
155
286
 
156
- - [Getting started](docs/GETTING_STARTED.md)
157
- - [Examples](docs/EXAMPLES.md)
158
- - [API reference](docs/API.md)
159
- - [Configuration](docs/CONFIGURATION.md)
160
- - [Compatibility](docs/COMPATIBILITY.md)
161
- - [Performance](docs/PERFORMANCE.md)
162
- - [Architecture](docs/ARCHITECTURE.md)
163
- - [Roadmap](docs/ROADMAP.md)
164
- - [Troubleshooting](docs/TROUBLESHOOTING.md)
165
- - [FAQ](docs/FAQ.md)
166
- - [Security and privacy](docs/SECURITY.md)
167
- - [Threat model](docs/THREAT_MODEL.md)
168
- - [Contributing](CONTRIBUTING.md)
169
- - [Changelog](CHANGELOG.md)
287
+ - [Getting started](https://github.com/FutureWindAI/Wotchi/blob/main/docs/GETTING_STARTED.md)
288
+ - [Examples](https://github.com/FutureWindAI/Wotchi/blob/main/docs/EXAMPLES.md)
289
+ - [API reference](https://github.com/FutureWindAI/Wotchi/blob/main/docs/API.md)
290
+ - [Configuration](https://github.com/FutureWindAI/Wotchi/blob/main/docs/CONFIGURATION.md)
291
+ - [Compatibility](https://github.com/FutureWindAI/Wotchi/blob/main/docs/COMPATIBILITY.md)
292
+ - [Performance](https://github.com/FutureWindAI/Wotchi/blob/main/docs/PERFORMANCE.md)
293
+ - [Architecture](https://github.com/FutureWindAI/Wotchi/blob/main/docs/ARCHITECTURE.md)
294
+ - [Roadmap](https://github.com/FutureWindAI/Wotchi/blob/main/docs/ROADMAP.md)
295
+ - [Troubleshooting](https://github.com/FutureWindAI/Wotchi/blob/main/docs/TROUBLESHOOTING.md)
296
+ - [FAQ](https://github.com/FutureWindAI/Wotchi/blob/main/docs/FAQ.md)
297
+ - [Security and privacy](https://github.com/FutureWindAI/Wotchi/blob/main/docs/SECURITY.md)
298
+ - [Threat model](https://github.com/FutureWindAI/Wotchi/blob/main/docs/THREAT_MODEL.md)
299
+ - [Contributing](https://github.com/FutureWindAI/Wotchi/blob/main/CONTRIBUTING.md)
300
+ - [Changelog](https://github.com/FutureWindAI/Wotchi/blob/main/CHANGELOG.md)
170
301
  - [GitHub releases](https://github.com/FutureWindAI/Wotchi/releases)
171
- - [Apache License 2.0](LICENSE)
302
+ - [Apache License 2.0](https://github.com/FutureWindAI/Wotchi/blob/main/LICENSE)
172
303
 
173
304
  ## Security
174
305
 
175
- Do not include real secrets or customer error data in issues, examples, or test fixtures. Report security vulnerabilities privately using [SECURITY.md](SECURITY.md).
306
+ Do not include real secrets or customer error data in issues, examples, or test fixtures. Report security vulnerabilities privately using the [security policy](https://github.com/FutureWindAI/Wotchi/blob/main/SECURITY.md).
176
307
 
177
308
  Wotchi is open source and maintained by FutureWind AI.
package/SECURITY.md CHANGED
@@ -4,13 +4,13 @@
4
4
 
5
5
  Wotchi targets applications running Node.js `>=18.18.0` and is built and tested across the Node.js 18–26 matrix. Node.js versions below 18.18 are not supported.
6
6
 
7
- The current package contains the framework-independent capture core, console and Telegram notifiers, Express 4/5 middleware, NestJS 10/11 exception-filter integration, and opt-in process monitoring. Supported runtime and framework combinations are documented after packed-tarball compatibility and release-security checks.
7
+ The current package contains the framework-independent capture core, console, Telegram, and generic HTTPS webhook notifiers, Express 4/5 middleware, NestJS 10/11 exception-filter integration, optional HTTP status observation, and opt-in process monitoring. Supported runtime and framework combinations are documented after packed-tarball compatibility and release-security checks.
8
8
 
9
9
  ## Reporting a Vulnerability
10
10
 
11
11
  Do not disclose a suspected vulnerability, exploit detail, credential, token, or real customer error in a public issue, discussion, pull request, or example.
12
12
 
13
- Use [GitHub private vulnerability reporting](https://github.com/FutureWindAI/wotchi/security/advisories/new) when it is available for this repository. If that private form is unavailable, open a public issue containing no sensitive detail and ask the maintainers to establish a private reporting channel.
13
+ Use [GitHub private vulnerability reporting](https://github.com/FutureWindAI/Wotchi/security/advisories/new). Do not open a public issue for a suspected vulnerability.
14
14
 
15
15
  Include only the minimum sanitized information needed to reproduce the problem. Remove application secrets, personal data, proprietary source, production URLs, and raw customer payloads.
16
16
 
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCaptureAdmission = createCaptureAdmission;
4
+ /** A small token bucket used before normalization to bound overload work. */
5
+ function createCaptureAdmission(options) {
6
+ const now = options.now ?? Date.now;
7
+ let tokens = options.burst;
8
+ let lastRefill = now();
9
+ return {
10
+ tryAcquire: () => {
11
+ const timestamp = now();
12
+ const elapsedMs = Math.max(0, timestamp - lastRefill);
13
+ tokens = Math.min(options.burst, tokens + (elapsedMs * options.maxEventsPerSecond) / 1_000);
14
+ lastRefill = timestamp;
15
+ if (tokens < 1) {
16
+ return false;
17
+ }
18
+ tokens -= 1;
19
+ return true;
20
+ },
21
+ };
22
+ }