@mpfrontend/presentation-server 0.1.0 → 1.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.
- package/dist/core.d.ts +60 -0
- package/dist/core.js +250 -0
- package/dist/core.js.map +1 -0
- package/dist/index.d.ts +1 -60
- package/dist/index.js +1 -249
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +3 -0
- package/dist/internal.js.map +1 -0
- package/package.json +5 -1
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse, Server } from 'node:http';
|
|
2
|
+
import { type ConnectionBudget } from './connection-budget.js';
|
|
3
|
+
export type { ConnectionBudget } from './connection-budget.js';
|
|
4
|
+
export type SocketContext = {
|
|
5
|
+
subject: string;
|
|
6
|
+
tenant: string | null;
|
|
7
|
+
roles: string[];
|
|
8
|
+
csrf: string;
|
|
9
|
+
};
|
|
10
|
+
export type AdmissionTicket = {
|
|
11
|
+
cookieHash: string;
|
|
12
|
+
revision: string;
|
|
13
|
+
expires: number;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* consume must be atomic across all presentation replicas. `security` describes the vault behind a store that
|
|
17
|
+
* keeps its tickets in one, as `createVaultTicketStore` of the Security BFF's session store sets it. The
|
|
18
|
+
* production profile refuses a shared store that does not declare it, all three flags, because a store that
|
|
19
|
+
* says nothing cannot be shown to be reached over TLS and with authentication.
|
|
20
|
+
*/
|
|
21
|
+
export type AdmissionTicketStore = {
|
|
22
|
+
readonly shared?: boolean;
|
|
23
|
+
readonly security?: Readonly<{
|
|
24
|
+
durable: boolean;
|
|
25
|
+
tls: boolean;
|
|
26
|
+
authenticated: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
issue: (id: string, ticket: AdmissionTicket) => Promise<void>;
|
|
29
|
+
consume: (id: string) => Promise<AdmissionTicket | undefined>;
|
|
30
|
+
};
|
|
31
|
+
type CommonSocketConfig = {
|
|
32
|
+
publicOrigin: string;
|
|
33
|
+
bffOrigin: string;
|
|
34
|
+
resolve: (resource: string, context: SocketContext) => string | undefined;
|
|
35
|
+
pollMs?: number;
|
|
36
|
+
};
|
|
37
|
+
/** Today's single-process development profile, refused when NODE_ENV is production. */
|
|
38
|
+
export type DevelopmentSocketConfig = CommonSocketConfig & {
|
|
39
|
+
development: true;
|
|
40
|
+
production?: never;
|
|
41
|
+
ticketStore?: AdmissionTicketStore;
|
|
42
|
+
connectionBudget?: ConnectionBudget;
|
|
43
|
+
};
|
|
44
|
+
/** Shared, durable admission across replicas; no process-memory default exists in this profile. */
|
|
45
|
+
export type PresentationProductionProfile = Readonly<{
|
|
46
|
+
ticketStore: AdmissionTicketStore;
|
|
47
|
+
connectionBudget: ConnectionBudget;
|
|
48
|
+
}>;
|
|
49
|
+
export type ProductionSocketConfig = CommonSocketConfig & {
|
|
50
|
+
production: PresentationProductionProfile;
|
|
51
|
+
development?: never;
|
|
52
|
+
};
|
|
53
|
+
export type SocketConfig = DevelopmentSocketConfig | ProductionSocketConfig;
|
|
54
|
+
/** The unmet conditions of a production configuration; empty when it may start. */
|
|
55
|
+
export declare function presentationProductionRefusals(config: ProductionSocketConfig): string[];
|
|
56
|
+
export declare function createPresentationRealtime(config: SocketConfig): {
|
|
57
|
+
handleHttp: (req: IncomingMessage, res: ServerResponse) => Promise<boolean>;
|
|
58
|
+
attach: (server: Server) => void;
|
|
59
|
+
close: () => void;
|
|
60
|
+
};
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { createHash, randomBytes, randomUUID } from 'node:crypto';
|
|
2
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
3
|
+
import { createMemoryConnectionBudget } from './connection-budget.js';
|
|
4
|
+
/** The unmet conditions of a production configuration; empty when it may start. */
|
|
5
|
+
export function presentationProductionRefusals(config) {
|
|
6
|
+
const refusals = [];
|
|
7
|
+
let https = false;
|
|
8
|
+
try {
|
|
9
|
+
https = new URL(config.publicOrigin).protocol === 'https:';
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
https = false;
|
|
13
|
+
}
|
|
14
|
+
if (!https)
|
|
15
|
+
refusals.push('HTTPS_PUBLIC_ORIGIN_REQUIRED');
|
|
16
|
+
if (config.production?.ticketStore?.shared !== true)
|
|
17
|
+
refusals.push('SHARED_TICKET_STORE_REQUIRED');
|
|
18
|
+
// A store that every replica shares is reached over a network, so it must say how: one that declares nothing is
|
|
19
|
+
// refused, as the Security BFF refuses a session vault that declares nothing, instead of passing for lack of a claim.
|
|
20
|
+
const declared = (security) => typeof security?.durable === 'boolean' && typeof security.tls === 'boolean' && typeof security.authenticated === 'boolean';
|
|
21
|
+
if (config.production?.ticketStore?.shared === true && !declared(config.production.ticketStore.security))
|
|
22
|
+
refusals.push('TICKET_STORE_SECURITY_REQUIRED');
|
|
23
|
+
// Tickets in a durable vault travel and rest under the vault's own protection, which must be TLS and authentication.
|
|
24
|
+
const vault = config.production?.ticketStore?.security;
|
|
25
|
+
if (vault?.durable && vault.tls !== true)
|
|
26
|
+
refusals.push('TICKET_STORE_TLS_REQUIRED');
|
|
27
|
+
if (vault?.durable && vault.authenticated !== true)
|
|
28
|
+
refusals.push('TICKET_STORE_AUTHENTICATION_REQUIRED');
|
|
29
|
+
if (config.production?.connectionBudget?.shared !== true)
|
|
30
|
+
refusals.push('SHARED_CONNECTION_BUDGET_REQUIRED');
|
|
31
|
+
return refusals;
|
|
32
|
+
}
|
|
33
|
+
const digest = (value) => createHash('sha256').update(value).digest('base64url');
|
|
34
|
+
const authority = (c) => digest(JSON.stringify([c.subject, c.tenant, [...c.roles].sort()]));
|
|
35
|
+
function checkedOrigin(value) { const url = new URL(value); if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.pathname !== '/' || url.search || url.hash)
|
|
36
|
+
throw new Error('INVALID_ORIGIN'); return url.origin; }
|
|
37
|
+
function json(res, status, value) { res.writeHead(status, { 'content-type': 'application/json', 'cache-control': 'no-store', 'x-content-type-options': 'nosniff' }); res.end(JSON.stringify(value)); }
|
|
38
|
+
export function createPresentationRealtime(config) {
|
|
39
|
+
const production = 'production' in config && config.production !== undefined ? config.production : undefined;
|
|
40
|
+
if (production) {
|
|
41
|
+
const refusals = presentationProductionRefusals(config);
|
|
42
|
+
if (refusals.length)
|
|
43
|
+
throw new Error('PRODUCTION_PROFILE_REFUSED:' + refusals.join(','));
|
|
44
|
+
}
|
|
45
|
+
else if (config.development !== true || process.env.NODE_ENV === 'production')
|
|
46
|
+
throw new Error('DURABLE_REALTIME_PROFILE_REQUIRED');
|
|
47
|
+
const development = production ? undefined : config;
|
|
48
|
+
const publicOrigin = checkedOrigin(config.publicOrigin), bff = checkedOrigin(config.bffOrigin);
|
|
49
|
+
const interval = Math.max(3000, config.pollMs ?? 3000), tickets = new Map();
|
|
50
|
+
const connectionBudget = production ? production.connectionBudget : development?.connectionBudget ?? createMemoryConnectionBudget();
|
|
51
|
+
const ticketStore = production ? production.ticketStore : development?.ticketStore ?? {
|
|
52
|
+
async issue(id, ticket) {
|
|
53
|
+
for (const [key, value] of tickets)
|
|
54
|
+
if (value.expires <= Date.now())
|
|
55
|
+
tickets.delete(key);
|
|
56
|
+
if (tickets.size >= 256)
|
|
57
|
+
throw Object.assign(new Error('TICKET_LIMIT'), { status: 429 });
|
|
58
|
+
tickets.set(id, ticket);
|
|
59
|
+
},
|
|
60
|
+
async consume(id) { const ticket = tickets.get(id); tickets.delete(id); return ticket; }
|
|
61
|
+
};
|
|
62
|
+
const sockets = new WebSocketServer({ noServer: true, maxPayload: 4096, perMessageDeflate: false });
|
|
63
|
+
async function context(cookie) {
|
|
64
|
+
const response = await fetch(bff + '/context', { headers: { cookie }, redirect: 'error', signal: AbortSignal.timeout(8000), cache: 'no-store' });
|
|
65
|
+
if (response.status === 401 || response.status === 403)
|
|
66
|
+
throw Object.assign(new Error('LOGIN_REQUIRED'), { status: 401 });
|
|
67
|
+
if (!response.ok)
|
|
68
|
+
throw new Error('AUTHORITY_UNAVAILABLE');
|
|
69
|
+
const c = await response.json();
|
|
70
|
+
if (typeof c.subject !== 'string' || typeof c.csrf !== 'string' || !Array.isArray(c.roles) || !c.roles.every(v => typeof v === 'string') || (c.tenant !== null && typeof c.tenant !== 'string'))
|
|
71
|
+
throw new Error('INVALID_CONTEXT');
|
|
72
|
+
return c;
|
|
73
|
+
}
|
|
74
|
+
async function handleHttp(req, res) {
|
|
75
|
+
if (new URL(req.url ?? '/', publicOrigin).pathname !== '/api/realtime/ticket')
|
|
76
|
+
return false;
|
|
77
|
+
try {
|
|
78
|
+
if (req.method !== 'POST') {
|
|
79
|
+
json(res, 405, { title: 'POST_REQUIRED' });
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
if (req.headers.origin !== publicOrigin) {
|
|
83
|
+
json(res, 403, { title: 'ORIGIN_REJECTED' });
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
const cookie = req.headers.cookie ?? '', c = await context(cookie);
|
|
87
|
+
if (typeof req.headers['x-csrf-token'] !== 'string' || req.headers['x-csrf-token'] !== c.csrf) {
|
|
88
|
+
json(res, 403, { title: 'CSRF_REJECTED' });
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
const ticket = randomBytes(32).toString('base64url');
|
|
92
|
+
await ticketStore.issue(ticket, { cookieHash: digest(cookie), revision: authority(c), expires: Date.now() + 20000 });
|
|
93
|
+
json(res, 200, { ticket, expiresIn: 20 });
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
const status = e.status ?? 503;
|
|
97
|
+
json(res, status, { title: status === 401 ? 'LOGIN_REQUIRED' : status === 429 ? 'TICKET_LIMIT' : 'AUTHORITY_UNAVAILABLE' });
|
|
98
|
+
}
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
function attach(server) {
|
|
102
|
+
server.on('upgrade', async (req, socket, head) => {
|
|
103
|
+
const url = new URL(req.url ?? '/', publicOrigin);
|
|
104
|
+
if (url.pathname !== '/api/realtime' || url.search || req.headers.origin !== publicOrigin) {
|
|
105
|
+
socket.end('HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n');
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const cookie = req.headers.cookie ?? '', cookieHash = digest(cookie);
|
|
109
|
+
const connectionId = randomUUID();
|
|
110
|
+
let reserved = false, upgraded = false;
|
|
111
|
+
const release = () => connectionBudget.release(cookieHash, connectionId).catch(() => undefined);
|
|
112
|
+
try {
|
|
113
|
+
const initial = await context(cookie), revision = authority(initial);
|
|
114
|
+
if (sockets.clients.size >= 32 || !await connectionBudget.reserve(cookieHash, connectionId)) {
|
|
115
|
+
socket.end('HTTP/1.1 429 Too Many Requests\r\nConnection: close\r\n\r\n');
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
reserved = true;
|
|
119
|
+
// Includes rejected WebSocket handshakes and clients which disconnect during admission.
|
|
120
|
+
socket.once('close', () => { if (!upgraded)
|
|
121
|
+
void release(); });
|
|
122
|
+
if (socket.destroyed) {
|
|
123
|
+
await release();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
sockets.handleUpgrade(req, socket, head, ws => {
|
|
127
|
+
upgraded = true;
|
|
128
|
+
const contextRef = randomUUID(), resources = new Map();
|
|
129
|
+
let admitted = false, admitting = false, busy = false, cursor = 0, alive = true;
|
|
130
|
+
async function lease() {
|
|
131
|
+
if (ws.readyState !== WebSocket.OPEN)
|
|
132
|
+
return false;
|
|
133
|
+
const started = performance.now();
|
|
134
|
+
try {
|
|
135
|
+
const duration = await connectionBudget.renew(cookieHash, connectionId);
|
|
136
|
+
if (!duration || performance.now() - started >= duration) {
|
|
137
|
+
ws.close(4004, 'LEASE_LOST');
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
return ws.readyState === WebSocket.OPEN;
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
ws.close(1013, 'RUNTIME_UNAVAILABLE');
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const send = async (frame) => { if (!await lease())
|
|
148
|
+
return; if (ws.bufferedAmount > 65536) {
|
|
149
|
+
ws.close(4008, 'BACKPRESSURE');
|
|
150
|
+
return;
|
|
151
|
+
} ws.send(JSON.stringify(frame)); };
|
|
152
|
+
const admission = setTimeout(() => ws.close(4001, 'ADMISSION_TIMEOUT'), 5000);
|
|
153
|
+
ws.on('pong', () => { alive = true; });
|
|
154
|
+
ws.on('error', () => ws.close(1011, 'TRANSPORT_ERROR'));
|
|
155
|
+
ws.on('message', async (raw, binary) => {
|
|
156
|
+
try {
|
|
157
|
+
if (binary || admitted || admitting)
|
|
158
|
+
throw new Error('INVALID_FRAME');
|
|
159
|
+
admitting = true;
|
|
160
|
+
const frame = JSON.parse(raw.toString());
|
|
161
|
+
if (frame.v !== 1 || frame.type !== 'subscribe' || typeof frame.ticket !== 'string' || !Array.isArray(frame.resources) || frame.resources.length < 1 || frame.resources.length > 6 || frame.resources.some(v => typeof v !== 'string' || v.length > 80))
|
|
162
|
+
throw new Error('INVALID_FRAME');
|
|
163
|
+
if (!/^[-_a-zA-Z0-9]{43}$/.test(frame.ticket))
|
|
164
|
+
throw new Error('INVALID_TICKET');
|
|
165
|
+
const saved = await ticketStore.consume(frame.ticket);
|
|
166
|
+
if (!saved || saved.expires <= Date.now() || saved.cookieHash !== cookieHash || saved.revision !== revision)
|
|
167
|
+
throw new Error('INVALID_TICKET');
|
|
168
|
+
if (authority(await context(cookie)) !== revision)
|
|
169
|
+
throw new Error('AUTHORITY_CHANGED');
|
|
170
|
+
if (ws.readyState !== WebSocket.OPEN)
|
|
171
|
+
return;
|
|
172
|
+
for (const name of new Set(frame.resources)) {
|
|
173
|
+
const path = config.resolve(name, initial);
|
|
174
|
+
if (!path || !path.startsWith('/v1/') || path.includes('..') || path.includes('#') || new URL(path, bff).origin !== bff)
|
|
175
|
+
throw new Error('FORBIDDEN_RESOURCE');
|
|
176
|
+
resources.set(name, { path });
|
|
177
|
+
}
|
|
178
|
+
admitted = true;
|
|
179
|
+
clearTimeout(admission);
|
|
180
|
+
await send({ v: 1, type: 'ready', contextRef, accessRevision: revision, recovery: 'snapshot' });
|
|
181
|
+
void tick();
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
ws.close(4003, 'ADMISSION_REJECTED');
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
async function tick() {
|
|
188
|
+
if (!admitted || busy || ws.readyState !== WebSocket.OPEN)
|
|
189
|
+
return;
|
|
190
|
+
busy = true;
|
|
191
|
+
try {
|
|
192
|
+
if (!await lease())
|
|
193
|
+
return;
|
|
194
|
+
const current = await context(cookie);
|
|
195
|
+
if (authority(current) !== revision) {
|
|
196
|
+
ws.close(4003, 'AUTHORITY_CHANGED');
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
for (const [name, value] of resources) {
|
|
200
|
+
if (config.resolve(name, current) !== value.path) {
|
|
201
|
+
ws.close(4003, 'RESOURCE_REVOKED');
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const result = await fetch(bff + value.path, { headers: { cookie }, redirect: 'error', cache: 'no-store', signal: AbortSignal.timeout(8000) });
|
|
205
|
+
if (result.status === 401 || result.status === 403) {
|
|
206
|
+
ws.close(4003, 'RESOURCE_REVOKED');
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (!result.ok && result.status !== 404)
|
|
210
|
+
throw new Error('SNAPSHOT_UNAVAILABLE');
|
|
211
|
+
const text = await result.text();
|
|
212
|
+
if (text.length > 1048576)
|
|
213
|
+
throw new Error('SNAPSHOT_LIMIT');
|
|
214
|
+
const hash = digest(result.status + ':' + text);
|
|
215
|
+
if (value.hash !== hash) {
|
|
216
|
+
cursor++;
|
|
217
|
+
await send({ v: 1, type: 'invalidate', eventId: randomUUID(), contextRef, accessRevision: revision, resource: name, cursor: String(cursor) });
|
|
218
|
+
value.hash = hash;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (e) {
|
|
223
|
+
if (e.status === 401)
|
|
224
|
+
ws.close(4003, 'LOGIN_REQUIRED');
|
|
225
|
+
else
|
|
226
|
+
await send({ v: 1, type: 'resync-required', contextRef, accessRevision: revision });
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
busy = false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const polling = setInterval(() => void tick(), interval), heartbeat = setInterval(() => { if (!alive) {
|
|
233
|
+
ws.terminate();
|
|
234
|
+
return;
|
|
235
|
+
} alive = false; ws.ping(); }, 30000);
|
|
236
|
+
ws.on('close', () => { clearTimeout(admission); clearInterval(polling); clearInterval(heartbeat); void release(); });
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
catch (e) {
|
|
240
|
+
if (reserved)
|
|
241
|
+
await release();
|
|
242
|
+
socket.end('HTTP/1.1 ' + (e.status === 401 ? '401 Unauthorized' : '503 Service Unavailable') + '\r\nConnection: close\r\n\r\n');
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function close() { for (const ws of sockets.clients)
|
|
247
|
+
ws.terminate(); sockets.close(); tickets.clear(); }
|
|
248
|
+
return { handleHttp, attach, close };
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=core.js.map
|
package/dist/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,60 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { type ConnectionBudget } from './connection-budget.js';
|
|
3
|
-
export type { ConnectionBudget } from './connection-budget.js';
|
|
4
|
-
export type SocketContext = {
|
|
5
|
-
subject: string;
|
|
6
|
-
tenant: string | null;
|
|
7
|
-
roles: string[];
|
|
8
|
-
csrf: string;
|
|
9
|
-
};
|
|
10
|
-
export type AdmissionTicket = {
|
|
11
|
-
cookieHash: string;
|
|
12
|
-
revision: string;
|
|
13
|
-
expires: number;
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* consume must be atomic across all presentation replicas. `security` describes the vault behind a store that
|
|
17
|
-
* keeps its tickets in one, as `createVaultTicketStore` of the Security BFF's session store sets it. The
|
|
18
|
-
* production profile refuses a shared store that does not declare it, all three flags, because a store that
|
|
19
|
-
* says nothing cannot be shown to be reached over TLS and with authentication.
|
|
20
|
-
*/
|
|
21
|
-
export type AdmissionTicketStore = {
|
|
22
|
-
readonly shared?: boolean;
|
|
23
|
-
readonly security?: Readonly<{
|
|
24
|
-
durable: boolean;
|
|
25
|
-
tls: boolean;
|
|
26
|
-
authenticated: boolean;
|
|
27
|
-
}>;
|
|
28
|
-
issue: (id: string, ticket: AdmissionTicket) => Promise<void>;
|
|
29
|
-
consume: (id: string) => Promise<AdmissionTicket | undefined>;
|
|
30
|
-
};
|
|
31
|
-
type CommonSocketConfig = {
|
|
32
|
-
publicOrigin: string;
|
|
33
|
-
bffOrigin: string;
|
|
34
|
-
resolve: (resource: string, context: SocketContext) => string | undefined;
|
|
35
|
-
pollMs?: number;
|
|
36
|
-
};
|
|
37
|
-
/** Today's single-process development profile, refused when NODE_ENV is production. */
|
|
38
|
-
export type DevelopmentSocketConfig = CommonSocketConfig & {
|
|
39
|
-
development: true;
|
|
40
|
-
production?: never;
|
|
41
|
-
ticketStore?: AdmissionTicketStore;
|
|
42
|
-
connectionBudget?: ConnectionBudget;
|
|
43
|
-
};
|
|
44
|
-
/** Shared, durable admission across replicas; no process-memory default exists in this profile. */
|
|
45
|
-
export type PresentationProductionProfile = Readonly<{
|
|
46
|
-
ticketStore: AdmissionTicketStore;
|
|
47
|
-
connectionBudget: ConnectionBudget;
|
|
48
|
-
}>;
|
|
49
|
-
export type ProductionSocketConfig = CommonSocketConfig & {
|
|
50
|
-
production: PresentationProductionProfile;
|
|
51
|
-
development?: never;
|
|
52
|
-
};
|
|
53
|
-
export type SocketConfig = DevelopmentSocketConfig | ProductionSocketConfig;
|
|
54
|
-
/** The unmet conditions of a production configuration; empty when it may start. */
|
|
55
|
-
export declare function presentationProductionRefusals(config: ProductionSocketConfig): string[];
|
|
56
|
-
export declare function createPresentationRealtime(config: SocketConfig): {
|
|
57
|
-
handleHttp: (req: IncomingMessage, res: ServerResponse) => Promise<boolean>;
|
|
58
|
-
attach: (server: Server) => void;
|
|
59
|
-
close: () => void;
|
|
60
|
-
};
|
|
1
|
+
export { type AdmissionTicket, type AdmissionTicketStore, type ConnectionBudget, createPresentationRealtime, type DevelopmentSocketConfig, type PresentationProductionProfile, type ProductionSocketConfig, type SocketConfig, } from './core.js';
|
package/dist/index.js
CHANGED
|
@@ -1,250 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { WebSocketServer, WebSocket } from 'ws';
|
|
3
|
-
import { createMemoryConnectionBudget } from './connection-budget.js';
|
|
4
|
-
/** The unmet conditions of a production configuration; empty when it may start. */
|
|
5
|
-
export function presentationProductionRefusals(config) {
|
|
6
|
-
const refusals = [];
|
|
7
|
-
let https = false;
|
|
8
|
-
try {
|
|
9
|
-
https = new URL(config.publicOrigin).protocol === 'https:';
|
|
10
|
-
}
|
|
11
|
-
catch {
|
|
12
|
-
https = false;
|
|
13
|
-
}
|
|
14
|
-
if (!https)
|
|
15
|
-
refusals.push('HTTPS_PUBLIC_ORIGIN_REQUIRED');
|
|
16
|
-
if (config.production?.ticketStore?.shared !== true)
|
|
17
|
-
refusals.push('SHARED_TICKET_STORE_REQUIRED');
|
|
18
|
-
// A store that every replica shares is reached over a network, so it must say how: one that declares nothing is
|
|
19
|
-
// refused, as the Security BFF refuses a session vault that declares nothing, instead of passing for lack of a claim.
|
|
20
|
-
const declared = (security) => typeof security?.durable === 'boolean' && typeof security.tls === 'boolean' && typeof security.authenticated === 'boolean';
|
|
21
|
-
if (config.production?.ticketStore?.shared === true && !declared(config.production.ticketStore.security))
|
|
22
|
-
refusals.push('TICKET_STORE_SECURITY_REQUIRED');
|
|
23
|
-
// Tickets in a durable vault travel and rest under the vault's own protection, which must be TLS and authentication.
|
|
24
|
-
const vault = config.production?.ticketStore?.security;
|
|
25
|
-
if (vault?.durable && vault.tls !== true)
|
|
26
|
-
refusals.push('TICKET_STORE_TLS_REQUIRED');
|
|
27
|
-
if (vault?.durable && vault.authenticated !== true)
|
|
28
|
-
refusals.push('TICKET_STORE_AUTHENTICATION_REQUIRED');
|
|
29
|
-
if (config.production?.connectionBudget?.shared !== true)
|
|
30
|
-
refusals.push('SHARED_CONNECTION_BUDGET_REQUIRED');
|
|
31
|
-
return refusals;
|
|
32
|
-
}
|
|
33
|
-
const digest = (value) => createHash('sha256').update(value).digest('base64url');
|
|
34
|
-
const authority = (c) => digest(JSON.stringify([c.subject, c.tenant, [...c.roles].sort()]));
|
|
35
|
-
function checkedOrigin(value) { const url = new URL(value); if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.pathname !== '/' || url.search || url.hash)
|
|
36
|
-
throw new Error('INVALID_ORIGIN'); return url.origin; }
|
|
37
|
-
function json(res, status, value) { res.writeHead(status, { 'content-type': 'application/json', 'cache-control': 'no-store', 'x-content-type-options': 'nosniff' }); res.end(JSON.stringify(value)); }
|
|
38
|
-
export function createPresentationRealtime(config) {
|
|
39
|
-
const production = 'production' in config && config.production !== undefined ? config.production : undefined;
|
|
40
|
-
if (production) {
|
|
41
|
-
const refusals = presentationProductionRefusals(config);
|
|
42
|
-
if (refusals.length)
|
|
43
|
-
throw new Error('PRODUCTION_PROFILE_REFUSED:' + refusals.join(','));
|
|
44
|
-
}
|
|
45
|
-
else if (config.development !== true || process.env.NODE_ENV === 'production')
|
|
46
|
-
throw new Error('DURABLE_REALTIME_PROFILE_REQUIRED');
|
|
47
|
-
const development = production ? undefined : config;
|
|
48
|
-
const publicOrigin = checkedOrigin(config.publicOrigin), bff = checkedOrigin(config.bffOrigin);
|
|
49
|
-
const interval = Math.max(3000, config.pollMs ?? 3000), tickets = new Map();
|
|
50
|
-
const connectionBudget = production ? production.connectionBudget : development?.connectionBudget ?? createMemoryConnectionBudget();
|
|
51
|
-
const ticketStore = production ? production.ticketStore : development?.ticketStore ?? {
|
|
52
|
-
async issue(id, ticket) {
|
|
53
|
-
for (const [key, value] of tickets)
|
|
54
|
-
if (value.expires <= Date.now())
|
|
55
|
-
tickets.delete(key);
|
|
56
|
-
if (tickets.size >= 256)
|
|
57
|
-
throw Object.assign(new Error('TICKET_LIMIT'), { status: 429 });
|
|
58
|
-
tickets.set(id, ticket);
|
|
59
|
-
},
|
|
60
|
-
async consume(id) { const ticket = tickets.get(id); tickets.delete(id); return ticket; }
|
|
61
|
-
};
|
|
62
|
-
const sockets = new WebSocketServer({ noServer: true, maxPayload: 4096, perMessageDeflate: false });
|
|
63
|
-
async function context(cookie) {
|
|
64
|
-
const response = await fetch(bff + '/context', { headers: { cookie }, redirect: 'error', signal: AbortSignal.timeout(8000), cache: 'no-store' });
|
|
65
|
-
if (response.status === 401 || response.status === 403)
|
|
66
|
-
throw Object.assign(new Error('LOGIN_REQUIRED'), { status: 401 });
|
|
67
|
-
if (!response.ok)
|
|
68
|
-
throw new Error('AUTHORITY_UNAVAILABLE');
|
|
69
|
-
const c = await response.json();
|
|
70
|
-
if (typeof c.subject !== 'string' || typeof c.csrf !== 'string' || !Array.isArray(c.roles) || !c.roles.every(v => typeof v === 'string') || (c.tenant !== null && typeof c.tenant !== 'string'))
|
|
71
|
-
throw new Error('INVALID_CONTEXT');
|
|
72
|
-
return c;
|
|
73
|
-
}
|
|
74
|
-
async function handleHttp(req, res) {
|
|
75
|
-
if (new URL(req.url ?? '/', publicOrigin).pathname !== '/api/realtime/ticket')
|
|
76
|
-
return false;
|
|
77
|
-
try {
|
|
78
|
-
if (req.method !== 'POST') {
|
|
79
|
-
json(res, 405, { title: 'POST_REQUIRED' });
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
if (req.headers.origin !== publicOrigin) {
|
|
83
|
-
json(res, 403, { title: 'ORIGIN_REJECTED' });
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
const cookie = req.headers.cookie ?? '', c = await context(cookie);
|
|
87
|
-
if (typeof req.headers['x-csrf-token'] !== 'string' || req.headers['x-csrf-token'] !== c.csrf) {
|
|
88
|
-
json(res, 403, { title: 'CSRF_REJECTED' });
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
const ticket = randomBytes(32).toString('base64url');
|
|
92
|
-
await ticketStore.issue(ticket, { cookieHash: digest(cookie), revision: authority(c), expires: Date.now() + 20000 });
|
|
93
|
-
json(res, 200, { ticket, expiresIn: 20 });
|
|
94
|
-
}
|
|
95
|
-
catch (e) {
|
|
96
|
-
const status = e.status ?? 503;
|
|
97
|
-
json(res, status, { title: status === 401 ? 'LOGIN_REQUIRED' : status === 429 ? 'TICKET_LIMIT' : 'AUTHORITY_UNAVAILABLE' });
|
|
98
|
-
}
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
function attach(server) {
|
|
102
|
-
server.on('upgrade', async (req, socket, head) => {
|
|
103
|
-
const url = new URL(req.url ?? '/', publicOrigin);
|
|
104
|
-
if (url.pathname !== '/api/realtime' || url.search || req.headers.origin !== publicOrigin) {
|
|
105
|
-
socket.end('HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n');
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
const cookie = req.headers.cookie ?? '', cookieHash = digest(cookie);
|
|
109
|
-
const connectionId = randomUUID();
|
|
110
|
-
let reserved = false, upgraded = false;
|
|
111
|
-
const release = () => connectionBudget.release(cookieHash, connectionId).catch(() => undefined);
|
|
112
|
-
try {
|
|
113
|
-
const initial = await context(cookie), revision = authority(initial);
|
|
114
|
-
if (sockets.clients.size >= 32 || !await connectionBudget.reserve(cookieHash, connectionId)) {
|
|
115
|
-
socket.end('HTTP/1.1 429 Too Many Requests\r\nConnection: close\r\n\r\n');
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
reserved = true;
|
|
119
|
-
// Includes rejected WebSocket handshakes and clients which disconnect during admission.
|
|
120
|
-
socket.once('close', () => { if (!upgraded)
|
|
121
|
-
void release(); });
|
|
122
|
-
if (socket.destroyed) {
|
|
123
|
-
await release();
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
sockets.handleUpgrade(req, socket, head, ws => {
|
|
127
|
-
upgraded = true;
|
|
128
|
-
const contextRef = randomUUID(), resources = new Map();
|
|
129
|
-
let admitted = false, admitting = false, busy = false, cursor = 0, alive = true;
|
|
130
|
-
async function lease() {
|
|
131
|
-
if (ws.readyState !== WebSocket.OPEN)
|
|
132
|
-
return false;
|
|
133
|
-
const started = performance.now();
|
|
134
|
-
try {
|
|
135
|
-
const duration = await connectionBudget.renew(cookieHash, connectionId);
|
|
136
|
-
if (!duration || performance.now() - started >= duration) {
|
|
137
|
-
ws.close(4004, 'LEASE_LOST');
|
|
138
|
-
return false;
|
|
139
|
-
}
|
|
140
|
-
return ws.readyState === WebSocket.OPEN;
|
|
141
|
-
}
|
|
142
|
-
catch {
|
|
143
|
-
ws.close(1013, 'RUNTIME_UNAVAILABLE');
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
const send = async (frame) => { if (!await lease())
|
|
148
|
-
return; if (ws.bufferedAmount > 65536) {
|
|
149
|
-
ws.close(4008, 'BACKPRESSURE');
|
|
150
|
-
return;
|
|
151
|
-
} ws.send(JSON.stringify(frame)); };
|
|
152
|
-
const admission = setTimeout(() => ws.close(4001, 'ADMISSION_TIMEOUT'), 5000);
|
|
153
|
-
ws.on('pong', () => { alive = true; });
|
|
154
|
-
ws.on('error', () => ws.close(1011, 'TRANSPORT_ERROR'));
|
|
155
|
-
ws.on('message', async (raw, binary) => {
|
|
156
|
-
try {
|
|
157
|
-
if (binary || admitted || admitting)
|
|
158
|
-
throw new Error('INVALID_FRAME');
|
|
159
|
-
admitting = true;
|
|
160
|
-
const frame = JSON.parse(raw.toString());
|
|
161
|
-
if (frame.v !== 1 || frame.type !== 'subscribe' || typeof frame.ticket !== 'string' || !Array.isArray(frame.resources) || frame.resources.length < 1 || frame.resources.length > 6 || frame.resources.some(v => typeof v !== 'string' || v.length > 80))
|
|
162
|
-
throw new Error('INVALID_FRAME');
|
|
163
|
-
if (!/^[-_a-zA-Z0-9]{43}$/.test(frame.ticket))
|
|
164
|
-
throw new Error('INVALID_TICKET');
|
|
165
|
-
const saved = await ticketStore.consume(frame.ticket);
|
|
166
|
-
if (!saved || saved.expires <= Date.now() || saved.cookieHash !== cookieHash || saved.revision !== revision)
|
|
167
|
-
throw new Error('INVALID_TICKET');
|
|
168
|
-
if (authority(await context(cookie)) !== revision)
|
|
169
|
-
throw new Error('AUTHORITY_CHANGED');
|
|
170
|
-
if (ws.readyState !== WebSocket.OPEN)
|
|
171
|
-
return;
|
|
172
|
-
for (const name of new Set(frame.resources)) {
|
|
173
|
-
const path = config.resolve(name, initial);
|
|
174
|
-
if (!path || !path.startsWith('/v1/') || path.includes('..') || path.includes('#') || new URL(path, bff).origin !== bff)
|
|
175
|
-
throw new Error('FORBIDDEN_RESOURCE');
|
|
176
|
-
resources.set(name, { path });
|
|
177
|
-
}
|
|
178
|
-
admitted = true;
|
|
179
|
-
clearTimeout(admission);
|
|
180
|
-
await send({ v: 1, type: 'ready', contextRef, accessRevision: revision, recovery: 'snapshot' });
|
|
181
|
-
void tick();
|
|
182
|
-
}
|
|
183
|
-
catch {
|
|
184
|
-
ws.close(4003, 'ADMISSION_REJECTED');
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
async function tick() {
|
|
188
|
-
if (!admitted || busy || ws.readyState !== WebSocket.OPEN)
|
|
189
|
-
return;
|
|
190
|
-
busy = true;
|
|
191
|
-
try {
|
|
192
|
-
if (!await lease())
|
|
193
|
-
return;
|
|
194
|
-
const current = await context(cookie);
|
|
195
|
-
if (authority(current) !== revision) {
|
|
196
|
-
ws.close(4003, 'AUTHORITY_CHANGED');
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
for (const [name, value] of resources) {
|
|
200
|
-
if (config.resolve(name, current) !== value.path) {
|
|
201
|
-
ws.close(4003, 'RESOURCE_REVOKED');
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
const result = await fetch(bff + value.path, { headers: { cookie }, redirect: 'error', cache: 'no-store', signal: AbortSignal.timeout(8000) });
|
|
205
|
-
if (result.status === 401 || result.status === 403) {
|
|
206
|
-
ws.close(4003, 'RESOURCE_REVOKED');
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
if (!result.ok && result.status !== 404)
|
|
210
|
-
throw new Error('SNAPSHOT_UNAVAILABLE');
|
|
211
|
-
const text = await result.text();
|
|
212
|
-
if (text.length > 1048576)
|
|
213
|
-
throw new Error('SNAPSHOT_LIMIT');
|
|
214
|
-
const hash = digest(result.status + ':' + text);
|
|
215
|
-
if (value.hash !== hash) {
|
|
216
|
-
cursor++;
|
|
217
|
-
await send({ v: 1, type: 'invalidate', eventId: randomUUID(), contextRef, accessRevision: revision, resource: name, cursor: String(cursor) });
|
|
218
|
-
value.hash = hash;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
catch (e) {
|
|
223
|
-
if (e.status === 401)
|
|
224
|
-
ws.close(4003, 'LOGIN_REQUIRED');
|
|
225
|
-
else
|
|
226
|
-
await send({ v: 1, type: 'resync-required', contextRef, accessRevision: revision });
|
|
227
|
-
}
|
|
228
|
-
finally {
|
|
229
|
-
busy = false;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
const polling = setInterval(() => void tick(), interval), heartbeat = setInterval(() => { if (!alive) {
|
|
233
|
-
ws.terminate();
|
|
234
|
-
return;
|
|
235
|
-
} alive = false; ws.ping(); }, 30000);
|
|
236
|
-
ws.on('close', () => { clearTimeout(admission); clearInterval(polling); clearInterval(heartbeat); void release(); });
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
catch (e) {
|
|
240
|
-
if (reserved)
|
|
241
|
-
await release();
|
|
242
|
-
socket.end('HTTP/1.1 ' + (e.status === 401 ? '401 Unauthorized' : '503 Service Unavailable') + '\r\nConnection: close\r\n\r\n');
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
function close() { for (const ws of sockets.clients)
|
|
247
|
-
ws.terminate(); sockets.close(); tickets.clear(); }
|
|
248
|
-
return { handleHttp, attach, close };
|
|
249
|
-
}
|
|
1
|
+
export { createPresentationRealtime, } from './core.js';
|
|
250
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,0BAA0B,GAK3B,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { presentationProductionRefusals, type SocketContext } from './core.js';
|
package/dist/internal.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,OAAO,EAAC,8BAA8B,EAAoB,MAAM,WAAW,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpfrontend/presentation-server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
"./relay": {
|
|
19
19
|
"types": "./dist/relay.d.ts",
|
|
20
20
|
"import": "./dist/relay.js"
|
|
21
|
+
},
|
|
22
|
+
"./internal": {
|
|
23
|
+
"types": "./dist/internal.d.ts",
|
|
24
|
+
"import": "./dist/internal.js"
|
|
21
25
|
}
|
|
22
26
|
},
|
|
23
27
|
"files": [
|