@stackline/sse 1.0.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/CHANGELOG.md +22 -0
- package/CONTRIBUTING.md +45 -0
- package/LICENSE +21 -0
- package/NOTICE +6 -0
- package/README.md +340 -0
- package/SECURITY.md +35 -0
- package/dist/index.cjs +1560 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.cts +293 -0
- package/dist/index.d.mts +293 -0
- package/dist/index.d.ts +293 -0
- package/dist/index.js +1539 -0
- package/dist/index.js.map +7 -0
- package/dist/index.min.js +13 -0
- package/dist/index.min.js.map +7 -0
- package/package.json +102 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are documented in this file.
|
|
4
|
+
|
|
5
|
+
## [1.0.0] - 2026-08-16
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- WHATWG-compatible incremental SSE parser for strings and UTF-8 bytes.
|
|
10
|
+
- Pull-based decoding for Response, Web Stream, async iterable, and iterable sources.
|
|
11
|
+
- JSON event decoding with optional completion sentinel support.
|
|
12
|
+
- Injection-resistant text and JSON encoders.
|
|
13
|
+
- Fetch client with resume IDs, retry policy, jitter, Retry-After, and timeouts.
|
|
14
|
+
- Callback compatibility for `eventsource-parser` and `@microsoft/fetch-event-source` migrations.
|
|
15
|
+
- Backpressure-aware server channel and async-iterable Response helper.
|
|
16
|
+
- Default line, event, and callback queue limits.
|
|
17
|
+
- ESM, CommonJS, browser, and TypeScript declarations.
|
|
18
|
+
- Cross-runtime CI, security tests, deterministic fuzzing, and release artifacts.
|
|
19
|
+
- Abort-safe custom Fetch, body factories, and async iterators, including late-response cleanup.
|
|
20
|
+
- Request header preservation when adding SSE negotiation and resume headers.
|
|
21
|
+
|
|
22
|
+
[1.0.0]: https://github.com/alexandroit/stackline-sse/releases/tag/v1.0.0
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Contributions are welcome through focused issues and pull requests.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Node.js 20.20 or newer for development;
|
|
8
|
+
- npm with lockfile support;
|
|
9
|
+
- no new runtime dependency without a documented architectural reason.
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm ci
|
|
15
|
+
npm test
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Useful commands:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm run test:unit
|
|
22
|
+
npm run test:coverage
|
|
23
|
+
npm run test:types
|
|
24
|
+
npm run test:attw
|
|
25
|
+
npm run benchmark
|
|
26
|
+
npm run docs:serve
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Change expectations
|
|
30
|
+
|
|
31
|
+
- Preserve WHATWG parsing behavior unless a deviation is explicitly documented.
|
|
32
|
+
- Add a regression test for every bug fix.
|
|
33
|
+
- Exercise arbitrary chunk boundaries for parser changes.
|
|
34
|
+
- Preserve Node.js 14 parser and encoder compatibility.
|
|
35
|
+
- Keep callback failures from causing automatic event replay.
|
|
36
|
+
- Keep all externally controlled buffers bounded.
|
|
37
|
+
- Update README, changelog, types, and examples with public API changes.
|
|
38
|
+
|
|
39
|
+
Performance changes should include correctness assertions and benchmark output.
|
|
40
|
+
Benchmarks are evidence, not a substitute for tests.
|
|
41
|
+
|
|
42
|
+
## Commit and review scope
|
|
43
|
+
|
|
44
|
+
Keep commits narrow and do not reformat unrelated files. Pull requests should
|
|
45
|
+
describe behavior, compatibility impact, security impact, and verification.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alexandro Paixao Marques
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
@stackline/sse
|
|
2
|
+
Copyright 2026 Alexandro Paixao Marques
|
|
3
|
+
|
|
4
|
+
This is an independently designed implementation of the Server-Sent Events
|
|
5
|
+
wire format defined by the WHATWG HTML Living Standard. Runtime code does not
|
|
6
|
+
include source copied from the packages used for development comparisons.
|
package/README.md
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
# @stackline/sse
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@stackline/sse)
|
|
4
|
+
[](https://www.npmjs.com/package/@stackline/sse)
|
|
5
|
+
[](https://github.com/alexandroit/stackline-sse/actions/workflows/ci.yml)
|
|
6
|
+
[](https://github.com/alexandroit/stackline-sse/actions/workflows/codeql.yml)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
One zero-dependency toolkit for consuming, parsing, encoding, serving, and
|
|
10
|
+
reconnecting Server-Sent Events. It is designed for AI token streams, live
|
|
11
|
+
interfaces, serverless runtimes, browsers, and Node.js services.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @stackline/sse
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Why this package
|
|
18
|
+
|
|
19
|
+
SSE projects commonly combine one parser package, another encoder, a stale
|
|
20
|
+
fetch wrapper, and custom server code. `@stackline/sse` gives those layers one
|
|
21
|
+
consistent contract:
|
|
22
|
+
|
|
23
|
+
- WHATWG-compatible incremental parsing of strings and UTF-8 bytes;
|
|
24
|
+
- pull-based async iteration with real stream backpressure;
|
|
25
|
+
- `fetch` streaming with POST, auth headers, retries, timeouts, and resume IDs;
|
|
26
|
+
- safe event encoding that rejects CRLF and `Last-Event-ID` injection;
|
|
27
|
+
- Web Stream and `Response` helpers for edge and server runtimes;
|
|
28
|
+
- bounded line, event, and callback queues by default;
|
|
29
|
+
- ESM, CommonJS, browser global, TypeScript 3.9 through 7, Deno, and Bun;
|
|
30
|
+
- zero runtime dependencies.
|
|
31
|
+
|
|
32
|
+
## AI streaming
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
import { fetchSSE } from '@stackline/sse';
|
|
36
|
+
|
|
37
|
+
const controller = new AbortController();
|
|
38
|
+
|
|
39
|
+
for await (const event of fetchSSE('https://api.example.com/responses', {
|
|
40
|
+
method: 'POST',
|
|
41
|
+
headers: {
|
|
42
|
+
Authorization: `Bearer ${process.env.API_TOKEN}`,
|
|
43
|
+
'Content-Type': 'application/json'
|
|
44
|
+
},
|
|
45
|
+
body: JSON.stringify({ model: 'example-model', stream: true }),
|
|
46
|
+
signal: controller.signal,
|
|
47
|
+
connectTimeout: 10_000,
|
|
48
|
+
idleTimeout: 45_000,
|
|
49
|
+
totalTimeout: 5 * 60_000,
|
|
50
|
+
retry: {
|
|
51
|
+
retries: 3,
|
|
52
|
+
minDelay: 500,
|
|
53
|
+
maxDelay: 10_000
|
|
54
|
+
}
|
|
55
|
+
})) {
|
|
56
|
+
if (event.data === '[DONE]') break;
|
|
57
|
+
console.log(event.event, JSON.parse(event.data));
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`fetchSSE` accepts all ordinary `fetch` request options. Node.js 18 and newer
|
|
62
|
+
provide `fetch`; Node.js 14 and 16 can pass an implementation with `fetch`.
|
|
63
|
+
|
|
64
|
+
## Parse any stream
|
|
65
|
+
|
|
66
|
+
### Async iterator
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
import { decodeSSE } from '@stackline/sse';
|
|
70
|
+
|
|
71
|
+
const response = await fetch('/events');
|
|
72
|
+
|
|
73
|
+
for await (const event of decodeSSE(response)) {
|
|
74
|
+
console.log(event.event, event.data, event.lastEventId);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The source can be a `Response`, `ReadableStream`, `AsyncIterable`, or ordinary
|
|
79
|
+
`Iterable` of `string` and `Uint8Array` chunks.
|
|
80
|
+
|
|
81
|
+
### Incremental callback parser
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
import { createParser } from '@stackline/sse';
|
|
85
|
+
|
|
86
|
+
const parser = createParser({
|
|
87
|
+
onEvent(event) {
|
|
88
|
+
console.log(event.data);
|
|
89
|
+
},
|
|
90
|
+
onRetry(milliseconds) {
|
|
91
|
+
console.log('Server retry interval:', milliseconds);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
parser.feed('id: 7\ndata: first chunk\n');
|
|
96
|
+
parser.feed('data: second chunk\n\n');
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Each event contains:
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
interface SSEEvent<T = string> {
|
|
103
|
+
data: T;
|
|
104
|
+
event?: string;
|
|
105
|
+
id?: string; // ID field in this event block
|
|
106
|
+
lastEventId: string; // committed resume ID, including inherited IDs
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
An `id`-only block commits `lastEventId` even when no message is dispatched.
|
|
111
|
+
That detail matters when a connection closes immediately after a checkpoint.
|
|
112
|
+
|
|
113
|
+
## JSON streams
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
import { decodeJSON } from '@stackline/sse';
|
|
117
|
+
|
|
118
|
+
for await (const event of decodeJSON(response, {
|
|
119
|
+
doneSentinel: '[DONE]'
|
|
120
|
+
})) {
|
|
121
|
+
console.log(event.data); // parsed JSON value
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Invalid JSON throws `SSEParseError`. Set `ignoreInvalidJSON: true` only when a
|
|
126
|
+
mixed text and JSON protocol intentionally requires it.
|
|
127
|
+
|
|
128
|
+
## Encode events
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
import { encodeJSON, encodeSSE } from '@stackline/sse';
|
|
132
|
+
|
|
133
|
+
encodeSSE({
|
|
134
|
+
id: '42',
|
|
135
|
+
event: 'delta',
|
|
136
|
+
retry: 3000,
|
|
137
|
+
data: 'line one\nline two'
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
encodeJSON({ token: 'hello' }, { event: 'delta', id: '43' });
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`id` and `event` values cannot contain line breaks. IDs also reject NUL. This
|
|
144
|
+
prevents a value from injecting additional SSE fields or HTTP resume headers.
|
|
145
|
+
|
|
146
|
+
## Serve events
|
|
147
|
+
|
|
148
|
+
### Response from an async generator
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
import { eventStreamResponse } from '@stackline/sse';
|
|
152
|
+
|
|
153
|
+
async function* updates() {
|
|
154
|
+
yield { event: 'ready', data: 'connected', id: '1' };
|
|
155
|
+
yield { event: 'delta', data: 'hello', id: '2' };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function GET() {
|
|
159
|
+
return eventStreamResponse(updates());
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The response includes `text/event-stream`, `no-cache, no-transform`, and
|
|
164
|
+
`X-Accel-Buffering: no` headers unless the caller overrides them.
|
|
165
|
+
|
|
166
|
+
### Push channel
|
|
167
|
+
|
|
168
|
+
```js
|
|
169
|
+
import { createSSEChannel } from '@stackline/sse';
|
|
170
|
+
|
|
171
|
+
const channel = createSSEChannel({
|
|
172
|
+
heartbeatInterval: 15_000
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const response = channel.toResponse();
|
|
176
|
+
|
|
177
|
+
if (!channel.sendJSON({ progress: 25 }, { event: 'progress' })) {
|
|
178
|
+
await channel.ready;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
channel.close();
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`send` and `sendJSON` return `false` when the stream applies backpressure.
|
|
185
|
+
Wait for `channel.ready` before producing more data.
|
|
186
|
+
|
|
187
|
+
## Reconnection behavior
|
|
188
|
+
|
|
189
|
+
`fetchSSE` follows SSE resume semantics and adds explicit production controls:
|
|
190
|
+
|
|
191
|
+
- sends `Accept: text/event-stream` and `Cache-Control: no-store` behavior;
|
|
192
|
+
- commits and forwards `Last-Event-ID` on reconnect;
|
|
193
|
+
- honors valid `retry:` fields and `Retry-After` headers;
|
|
194
|
+
- retries network failures and HTTP 408, 425, 429, 500, 502, 503, and 504;
|
|
195
|
+
- rejects other HTTP statuses and incorrect content types;
|
|
196
|
+
- uses exponential backoff with full jitter by default;
|
|
197
|
+
- stops permanently on HTTP 204;
|
|
198
|
+
- never replays a streaming request body without `bodyFactory`.
|
|
199
|
+
|
|
200
|
+
Native EventSource reconnects indefinitely, so the default retry budget is
|
|
201
|
+
also unlimited. Production applications should pass an `AbortSignal`, a finite
|
|
202
|
+
`retry.retries`, or `totalTimeout`.
|
|
203
|
+
|
|
204
|
+
```js
|
|
205
|
+
const options = {
|
|
206
|
+
retry: {
|
|
207
|
+
retries: 5,
|
|
208
|
+
minDelay: 500,
|
|
209
|
+
maxDelay: 30_000,
|
|
210
|
+
factor: 2,
|
|
211
|
+
jitter: 'full'
|
|
212
|
+
},
|
|
213
|
+
onRetry({ delay, reconnects, error }) {
|
|
214
|
+
console.warn({ delay, reconnects, error });
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
For a body that must be recreated on every attempt, `bodyFactory` receives the
|
|
220
|
+
attempt number, committed resume ID, and that attempt's abort signal:
|
|
221
|
+
|
|
222
|
+
```js
|
|
223
|
+
const options = {
|
|
224
|
+
bodyFactory({ attempt, lastEventId, signal }) {
|
|
225
|
+
return createUploadStream({ attempt, lastEventId, signal });
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
When the input is a `Request`, its headers are preserved unless `options.headers`
|
|
231
|
+
explicitly replaces them. The SSE `Accept` and resume headers are then merged
|
|
232
|
+
case-insensitively.
|
|
233
|
+
|
|
234
|
+
## Memory safety
|
|
235
|
+
|
|
236
|
+
The parser is bounded by default:
|
|
237
|
+
|
|
238
|
+
| Limit | Default | Purpose |
|
|
239
|
+
| --- | ---: | --- |
|
|
240
|
+
| `maxLineLength` | 1 MiB | unterminated or oversized field line |
|
|
241
|
+
| `maxEventSize` | 1 MiB | accumulated multiline event |
|
|
242
|
+
| `maxQueuedEvents` | 4096 | callback burst inside one feed slice |
|
|
243
|
+
| `feedSize` | 16 KiB | limits work admitted before yielding |
|
|
244
|
+
|
|
245
|
+
Raise a limit explicitly for a trusted protocol that carries larger events.
|
|
246
|
+
Limit failures terminate the parser with a stable `ERR_SSE_*` code.
|
|
247
|
+
|
|
248
|
+
## Migration
|
|
249
|
+
|
|
250
|
+
### From eventsource-parser
|
|
251
|
+
|
|
252
|
+
Direct dependency:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
npm install @stackline/sse
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
The familiar API is available:
|
|
259
|
+
|
|
260
|
+
```js
|
|
261
|
+
import { createParser } from '@stackline/sse';
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
For a low-change trial, npm aliases preserve the old import name:
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
npm install eventsource-parser@npm:@stackline/sse
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
`createParser({ onEvent, onRetry, onComment, onError, maxBufferSize })` is
|
|
271
|
+
supported. The additional `lastEventId` property follows WHATWG resume
|
|
272
|
+
semantics. Security limits are enabled by default, unlike unbounded parsers.
|
|
273
|
+
|
|
274
|
+
### From @microsoft/fetch-event-source
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
npm install @stackline/sse
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
```js
|
|
281
|
+
import { fetchEventSource } from '@stackline/sse';
|
|
282
|
+
|
|
283
|
+
await fetchEventSource('/events', {
|
|
284
|
+
onopen(response) {},
|
|
285
|
+
onmessage(event) {},
|
|
286
|
+
onclose(context) {},
|
|
287
|
+
onerror(error) {}
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
An alias can support staged migration:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
npm install @microsoft/fetch-event-source@npm:@stackline/sse
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
The callback names are supported. `openWhenHidden` is accepted but this package
|
|
298
|
+
does not silently disconnect a healthy stream when a page becomes hidden.
|
|
299
|
+
|
|
300
|
+
## Runtime matrix
|
|
301
|
+
|
|
302
|
+
| Runtime | Parser / encoder | Fetch client | Server helpers |
|
|
303
|
+
| --- | --- | --- | --- |
|
|
304
|
+
| Modern browsers | Yes | Yes | Yes |
|
|
305
|
+
| Node.js 18+ | Yes | Yes | Yes |
|
|
306
|
+
| Node.js 14 / 16 | Yes | Inject `fetch` | Inject Web Streams if needed |
|
|
307
|
+
| Deno 2 | Yes | Yes | Yes |
|
|
308
|
+
| Bun | Yes | Yes | Yes |
|
|
309
|
+
| Cloudflare Workers | Yes | Yes | Yes |
|
|
310
|
+
|
|
311
|
+
The package ships ESM, CommonJS, a browser IIFE, and declarations tested with
|
|
312
|
+
TypeScript 3.9, 4.7, 4.9, 5.x, 6.x, and 7.x.
|
|
313
|
+
|
|
314
|
+
## Errors
|
|
315
|
+
|
|
316
|
+
| Class | Code | Meaning |
|
|
317
|
+
| --- | --- | --- |
|
|
318
|
+
| `SSEParseError` | `ERR_SSE_PARSE` and specific variants | malformed or limited stream |
|
|
319
|
+
| `SSEEncodeError` | `ERR_SSE_ENCODE` | unsafe or unsupported output field |
|
|
320
|
+
| `SSEHTTPError` | `ERR_SSE_HTTP` | rejected HTTP response |
|
|
321
|
+
| `SSETimeoutError` | `ERR_SSE_TIMEOUT` | connect, idle, or total deadline |
|
|
322
|
+
| `SSERetryError` | `ERR_SSE_RETRY` | finite reconnect budget exhausted |
|
|
323
|
+
| `SSEReplayError` | `ERR_SSE_BODY_REPLAY` | non-replayable request body |
|
|
324
|
+
|
|
325
|
+
## Package integrity
|
|
326
|
+
|
|
327
|
+
- zero runtime dependencies;
|
|
328
|
+
- no install scripts;
|
|
329
|
+
- deterministic ESM, CommonJS, and browser builds;
|
|
330
|
+
- CI tests Node.js 14 through 24, Windows, macOS, Linux, Deno, and Bun;
|
|
331
|
+
- CodeQL, npm audit, registry signature verification, `publint`, and
|
|
332
|
+
Are the Types Wrong checks;
|
|
333
|
+
- release tarballs include SHA-512 checksums and a CycloneDX SBOM.
|
|
334
|
+
|
|
335
|
+
See [SECURITY.md](SECURITY.md) for vulnerability reporting and
|
|
336
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) for development instructions.
|
|
337
|
+
|
|
338
|
+
## License
|
|
339
|
+
|
|
340
|
+
[MIT](LICENSE) Copyright 2026 Alexandro Paixao Marques.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| 1.x | Yes |
|
|
8
|
+
| Pre-release or unpublished builds | No |
|
|
9
|
+
|
|
10
|
+
Security fixes are released as new immutable npm versions. A vulnerable
|
|
11
|
+
published version is deprecated when appropriate; it is not silently replaced.
|
|
12
|
+
|
|
13
|
+
## Reporting a vulnerability
|
|
14
|
+
|
|
15
|
+
Do not open a public issue for an undisclosed vulnerability. Use GitHub's
|
|
16
|
+
private vulnerability reporting for
|
|
17
|
+
[alexandroit/stackline-sse](https://github.com/alexandroit/stackline-sse/security/advisories/new).
|
|
18
|
+
|
|
19
|
+
Include:
|
|
20
|
+
|
|
21
|
+
- affected version and runtime;
|
|
22
|
+
- minimal reproduction or malformed byte sequence;
|
|
23
|
+
- security impact and expected behavior;
|
|
24
|
+
- whether the issue affects parser, encoder, client, or server APIs.
|
|
25
|
+
|
|
26
|
+
Reports are acknowledged as soon as practical. Confirmed issues receive a
|
|
27
|
+
coordinated fix, regression tests, release notes, and credit when requested.
|
|
28
|
+
|
|
29
|
+
## Security boundaries
|
|
30
|
+
|
|
31
|
+
The package limits parser memory and validates encoded control fields. It does
|
|
32
|
+
not authenticate event producers, authorize endpoints, validate event JSON
|
|
33
|
+
schemas, encrypt transport, or make arbitrary event data safe for HTML output.
|
|
34
|
+
Applications must still use HTTPS, validate origin and payloads, and escape
|
|
35
|
+
data at the rendering boundary.
|