@floegence/flowersec-core 0.24.0 → 0.26.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/README.md +6 -0
- package/dist/browser/controlplane.d.ts +1 -1
- package/dist/browser/controlplane.js +0 -1
- package/dist/browser/index.d.ts +3 -3
- package/dist/browser/index.js +2 -2
- package/dist/client-connect/transportSecurity.d.ts +1 -3
- package/dist/client-connect/transportSecurity.js +1 -5
- package/dist/controlplane/request.d.ts +1 -0
- package/dist/controlplane/request.js +77 -2
- package/dist/defaults.d.ts +1 -0
- package/dist/defaults.js +1 -0
- package/dist/endpoint/index.js +185 -33
- package/dist/facade.d.ts +1 -1
- package/dist/facade.js +1 -1
- package/dist/node/index.d.ts +1 -1
- package/dist/node/index.js +1 -1
- package/dist/proxy/appWindow.js +93 -7
- package/dist/proxy/bootstrap.d.ts +5 -24
- package/dist/proxy/bootstrap.js +1 -11
- package/dist/proxy/constants.d.ts +1 -0
- package/dist/proxy/constants.js +1 -0
- package/dist/proxy/controllerWindow.js +219 -78
- package/dist/proxy/integration.js +0 -6
- package/dist/proxy/portStream.d.ts +2 -1
- package/dist/proxy/portStream.js +173 -74
- package/dist/proxy/preset.d.ts +0 -1
- package/dist/proxy/preset.js +0 -9
- package/dist/proxy/runtimeScope.js +2 -7
- package/dist/proxy/server.d.ts +1 -0
- package/dist/proxy/server.js +466 -113
- package/dist/proxy/windowBridgeProtocol.d.ts +4 -3
- package/dist/proxy/windowBridgeProtocol.js +1 -1
- package/package.json +1 -1
- package/dist/proxy/profiles.d.ts +0 -18
- package/dist/proxy/profiles.js +0 -71
package/dist/proxy/portStream.js
CHANGED
|
@@ -4,79 +4,151 @@ function cloneChunk(chunk) {
|
|
|
4
4
|
out.set(chunk);
|
|
5
5
|
return out.buffer;
|
|
6
6
|
}
|
|
7
|
+
function validWriteId(value) {
|
|
8
|
+
return Number.isSafeInteger(value) && Number(value) > 0;
|
|
9
|
+
}
|
|
7
10
|
export function createMessagePortBackedStream(port, opts = {}) {
|
|
8
11
|
let closed = false;
|
|
12
|
+
let acceptingWrites = true;
|
|
9
13
|
let error = null;
|
|
10
14
|
const queue = [];
|
|
11
15
|
const waiters = [];
|
|
12
|
-
|
|
16
|
+
let pendingInboundWriteId = null;
|
|
17
|
+
let pendingOutboundAcknowledgement = null;
|
|
13
18
|
let nextWriteId = 1;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
let writeTail = Promise.resolve();
|
|
20
|
+
let queuedWriteBytes = 0;
|
|
21
|
+
const maxBufferedBytes = opts.maxBufferedBytes ?? 4 * (1 << 20);
|
|
22
|
+
let terminalNotified = false;
|
|
23
|
+
const notifyTerminal = () => {
|
|
24
|
+
if (terminalNotified)
|
|
25
|
+
return;
|
|
26
|
+
terminalNotified = true;
|
|
27
|
+
opts.onTerminal?.();
|
|
28
|
+
};
|
|
29
|
+
const closePort = () => {
|
|
30
|
+
try {
|
|
31
|
+
port.close();
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Best-effort.
|
|
19
35
|
}
|
|
20
|
-
return false;
|
|
21
36
|
};
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
queue.push(value);
|
|
37
|
+
const drainWaiters = (value) => {
|
|
38
|
+
for (const waiter of waiters.splice(0))
|
|
39
|
+
waiter(value);
|
|
26
40
|
};
|
|
27
|
-
const
|
|
41
|
+
const terminateWithError = (err, notifyPeer) => {
|
|
28
42
|
if (error != null)
|
|
29
43
|
return;
|
|
30
44
|
error = err;
|
|
31
|
-
|
|
32
|
-
|
|
45
|
+
closed = true;
|
|
46
|
+
acceptingWrites = false;
|
|
47
|
+
queue.length = 0;
|
|
48
|
+
pendingInboundWriteId = null;
|
|
49
|
+
drainWaiters(err);
|
|
50
|
+
pendingOutboundAcknowledgement?.reject(err);
|
|
51
|
+
pendingOutboundAcknowledgement = null;
|
|
52
|
+
if (notifyPeer) {
|
|
53
|
+
try {
|
|
54
|
+
port.postMessage({
|
|
55
|
+
type: PROXY_WINDOW_STREAM_RESET_MSG_TYPE,
|
|
56
|
+
message: err.message,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// The local error remains authoritative.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
closePort();
|
|
64
|
+
notifyTerminal();
|
|
65
|
+
};
|
|
66
|
+
const failProtocol = (message) => {
|
|
67
|
+
terminateWithError(new Error(`proxy Window stream protocol error: ${message}`), true);
|
|
68
|
+
};
|
|
69
|
+
const finishClosed = () => {
|
|
70
|
+
if (closed)
|
|
71
|
+
return;
|
|
72
|
+
if (pendingInboundWriteId != null) {
|
|
73
|
+
failProtocol("stream ended before the pending chunk was acknowledged");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
closed = true;
|
|
77
|
+
acceptingWrites = false;
|
|
78
|
+
const closeError = new Error("stream is closed");
|
|
79
|
+
pendingOutboundAcknowledgement?.reject(closeError);
|
|
80
|
+
pendingOutboundAcknowledgement = null;
|
|
81
|
+
drainWaiters(null);
|
|
82
|
+
closePort();
|
|
83
|
+
notifyTerminal();
|
|
84
|
+
};
|
|
85
|
+
const acknowledgeRead = (item) => {
|
|
86
|
+
if (closed)
|
|
87
|
+
return;
|
|
88
|
+
if (pendingInboundWriteId !== item.writeId) {
|
|
89
|
+
failProtocol("read acknowledgement does not match the pending chunk");
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
pendingInboundWriteId = null;
|
|
93
|
+
try {
|
|
94
|
+
port.postMessage({
|
|
95
|
+
type: PROXY_WINDOW_STREAM_WRITE_ACK_MSG_TYPE,
|
|
96
|
+
writeId: item.writeId,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
catch (cause) {
|
|
100
|
+
const err = cause instanceof Error ? cause : new Error(String(cause));
|
|
101
|
+
terminateWithError(err, false);
|
|
102
|
+
throw err;
|
|
33
103
|
}
|
|
34
|
-
for (const pending of pendingWrites.values())
|
|
35
|
-
pending.reject(err);
|
|
36
|
-
pendingWrites.clear();
|
|
37
104
|
};
|
|
38
105
|
port.onmessage = (ev) => {
|
|
106
|
+
if (closed)
|
|
107
|
+
return;
|
|
39
108
|
const data = ev.data;
|
|
40
109
|
if (data == null || typeof data !== "object")
|
|
41
110
|
return;
|
|
42
111
|
const type = typeof data.type === "string" ? data.type : "";
|
|
43
112
|
switch (type) {
|
|
44
113
|
case PROXY_WINDOW_STREAM_CHUNK_MSG_TYPE: {
|
|
45
|
-
const
|
|
46
|
-
if (!(
|
|
114
|
+
const msg = data;
|
|
115
|
+
if (!(msg.data instanceof ArrayBuffer) || !validWriteId(msg.writeId)) {
|
|
116
|
+
failProtocol("invalid stream chunk");
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (pendingInboundWriteId != null || queue.length > 0) {
|
|
120
|
+
failProtocol("received more than one unacknowledged chunk");
|
|
47
121
|
return;
|
|
48
|
-
|
|
122
|
+
}
|
|
123
|
+
pendingInboundWriteId = msg.writeId;
|
|
124
|
+
const item = { chunk: new Uint8Array(msg.data), writeId: msg.writeId };
|
|
125
|
+
const waiter = waiters.shift();
|
|
126
|
+
if (waiter == null) {
|
|
127
|
+
queue.push(item);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
waiter(item);
|
|
131
|
+
}
|
|
49
132
|
return;
|
|
50
133
|
}
|
|
51
134
|
case PROXY_WINDOW_STREAM_END_MSG_TYPE:
|
|
52
135
|
case PROXY_WINDOW_STREAM_CLOSE_MSG_TYPE:
|
|
53
|
-
|
|
54
|
-
for (const pending of pendingWrites.values())
|
|
55
|
-
pending.reject(new Error("stream is closed"));
|
|
56
|
-
pendingWrites.clear();
|
|
57
|
-
pushValue(null);
|
|
136
|
+
finishClosed();
|
|
58
137
|
return;
|
|
59
138
|
case PROXY_WINDOW_STREAM_WRITE_ACK_MSG_TYPE: {
|
|
60
139
|
const writeId = data.writeId;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (pending == null)
|
|
140
|
+
const pending = pendingOutboundAcknowledgement;
|
|
141
|
+
if (!validWriteId(writeId) || pending == null || pending.writeId !== writeId) {
|
|
142
|
+
failProtocol("unexpected stream write acknowledgement");
|
|
65
143
|
return;
|
|
66
|
-
|
|
144
|
+
}
|
|
145
|
+
pendingOutboundAcknowledgement = null;
|
|
67
146
|
pending.resolve();
|
|
68
147
|
return;
|
|
69
148
|
}
|
|
70
149
|
case PROXY_WINDOW_STREAM_RESET_MSG_TYPE: {
|
|
71
|
-
closed = true;
|
|
72
150
|
const message = String(data.message ?? "stream reset");
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
port.close();
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
// Best-effort.
|
|
79
|
-
}
|
|
151
|
+
terminateWithError(new Error(message), false);
|
|
80
152
|
return;
|
|
81
153
|
}
|
|
82
154
|
default:
|
|
@@ -88,9 +160,11 @@ export function createMessagePortBackedStream(port, opts = {}) {
|
|
|
88
160
|
async read() {
|
|
89
161
|
if (error != null)
|
|
90
162
|
throw error;
|
|
91
|
-
const
|
|
92
|
-
if (
|
|
93
|
-
|
|
163
|
+
const queued = queue.shift();
|
|
164
|
+
if (queued != null) {
|
|
165
|
+
acknowledgeRead(queued);
|
|
166
|
+
return queued.chunk;
|
|
167
|
+
}
|
|
94
168
|
if (closed)
|
|
95
169
|
return null;
|
|
96
170
|
const value = await new Promise((resolve) => {
|
|
@@ -98,60 +172,85 @@ export function createMessagePortBackedStream(port, opts = {}) {
|
|
|
98
172
|
});
|
|
99
173
|
if (value instanceof Error)
|
|
100
174
|
throw value;
|
|
101
|
-
|
|
175
|
+
if (value == null)
|
|
176
|
+
return null;
|
|
177
|
+
acknowledgeRead(value);
|
|
178
|
+
return value.chunk;
|
|
102
179
|
},
|
|
103
180
|
async write(chunk) {
|
|
104
181
|
if (error != null)
|
|
105
182
|
throw error;
|
|
106
|
-
if (closed)
|
|
183
|
+
if (!acceptingWrites || closed)
|
|
107
184
|
throw new Error("stream is closed");
|
|
108
|
-
const
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
return;
|
|
185
|
+
const nextQueuedWriteBytes = queuedWriteBytes + chunk.byteLength;
|
|
186
|
+
if (!Number.isSafeInteger(nextQueuedWriteBytes) || nextQueuedWriteBytes > maxBufferedBytes) {
|
|
187
|
+
throw new Error("proxy WebSocket outbound buffer exceeded");
|
|
112
188
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
189
|
+
queuedWriteBytes = nextQueuedWriteBytes;
|
|
190
|
+
const ab = cloneChunk(chunk);
|
|
191
|
+
const operation = writeTail.then(async () => {
|
|
192
|
+
if (error != null)
|
|
193
|
+
throw error;
|
|
194
|
+
if (closed)
|
|
195
|
+
throw new Error("stream is closed");
|
|
196
|
+
if (!Number.isSafeInteger(nextWriteId)) {
|
|
197
|
+
failProtocol("stream write identifier space exhausted");
|
|
198
|
+
throw error;
|
|
118
199
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
200
|
+
if (pendingOutboundAcknowledgement != null) {
|
|
201
|
+
failProtocol("multiple outbound chunks are awaiting acknowledgement");
|
|
202
|
+
throw error;
|
|
122
203
|
}
|
|
204
|
+
const writeId = nextWriteId++;
|
|
205
|
+
await new Promise((resolve, reject) => {
|
|
206
|
+
pendingOutboundAcknowledgement = { writeId, resolve, reject };
|
|
207
|
+
try {
|
|
208
|
+
port.postMessage({
|
|
209
|
+
type: PROXY_WINDOW_STREAM_CHUNK_MSG_TYPE,
|
|
210
|
+
data: ab,
|
|
211
|
+
writeId,
|
|
212
|
+
}, [ab]);
|
|
213
|
+
}
|
|
214
|
+
catch (cause) {
|
|
215
|
+
pendingOutboundAcknowledgement = null;
|
|
216
|
+
const postError = cause instanceof Error ? cause : new Error(String(cause));
|
|
217
|
+
terminateWithError(postError, false);
|
|
218
|
+
reject(postError);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
123
221
|
});
|
|
222
|
+
writeTail = operation.catch(() => { });
|
|
223
|
+
try {
|
|
224
|
+
await operation;
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
queuedWriteBytes = Math.max(0, queuedWriteBytes - chunk.byteLength);
|
|
228
|
+
}
|
|
124
229
|
},
|
|
125
230
|
async close() {
|
|
231
|
+
if (closed)
|
|
232
|
+
return;
|
|
233
|
+
acceptingWrites = false;
|
|
234
|
+
await writeTail;
|
|
235
|
+
if (error != null)
|
|
236
|
+
throw error;
|
|
126
237
|
if (closed)
|
|
127
238
|
return;
|
|
128
239
|
closed = true;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
pendingWrites.clear();
|
|
240
|
+
queue.length = 0;
|
|
241
|
+
pendingInboundWriteId = null;
|
|
242
|
+
drainWaiters(null);
|
|
133
243
|
try {
|
|
134
244
|
port.postMessage({ type: PROXY_WINDOW_STREAM_CLOSE_MSG_TYPE });
|
|
135
245
|
}
|
|
136
246
|
finally {
|
|
137
|
-
|
|
247
|
+
closePort();
|
|
248
|
+
notifyTerminal();
|
|
138
249
|
}
|
|
139
250
|
},
|
|
140
251
|
reset(err) {
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
fail(err instanceof Error ? err : new Error(message));
|
|
144
|
-
try {
|
|
145
|
-
port.postMessage({ type: PROXY_WINDOW_STREAM_RESET_MSG_TYPE, message });
|
|
146
|
-
}
|
|
147
|
-
finally {
|
|
148
|
-
try {
|
|
149
|
-
port.close();
|
|
150
|
-
}
|
|
151
|
-
catch {
|
|
152
|
-
// Best-effort.
|
|
153
|
-
}
|
|
154
|
-
}
|
|
252
|
+
const resetError = err instanceof Error ? err : new Error(String(err));
|
|
253
|
+
terminateWithError(resetError, true);
|
|
155
254
|
},
|
|
156
255
|
};
|
|
157
256
|
}
|
package/dist/proxy/preset.d.ts
CHANGED
|
@@ -26,5 +26,4 @@ export type ResolvedProxyPreset = Readonly<{
|
|
|
26
26
|
export declare const DEFAULT_PROXY_PRESET_MANIFEST: ProxyPresetManifest;
|
|
27
27
|
export type ProxyPresetInput = ProxyPresetManifest | Partial<ProxyPresetLimits>;
|
|
28
28
|
export declare function assertProxyPresetManifest(value: unknown): ProxyPresetManifest;
|
|
29
|
-
export declare function resolveNamedProxyPreset(name: string): ProxyPresetManifest;
|
|
30
29
|
export declare function resolveProxyPreset(input?: ProxyPresetInput): ResolvedProxyPreset;
|
package/dist/proxy/preset.js
CHANGED
|
@@ -75,15 +75,6 @@ export function assertProxyPresetManifest(value) {
|
|
|
75
75
|
limits: assertLimits(value.limits),
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
|
-
export function resolveNamedProxyPreset(name) {
|
|
79
|
-
switch (String(name ?? "").trim()) {
|
|
80
|
-
case "":
|
|
81
|
-
case "default":
|
|
82
|
-
return DEFAULT_PROXY_PRESET_MANIFEST;
|
|
83
|
-
default:
|
|
84
|
-
throw new Error(`unknown proxy preset: ${name}`);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
78
|
function toResolved(manifest) {
|
|
88
79
|
return Object.freeze({
|
|
89
80
|
v: 1,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assertProxyPresetManifest,
|
|
1
|
+
import { assertProxyPresetManifest, } from "./preset.js";
|
|
2
2
|
const RUNTIME_SCOPE_NAME = "proxy.runtime";
|
|
3
3
|
const PRESET_ID_RE = /^[a-z][a-z0-9._-]{0,63}$/;
|
|
4
4
|
const MAX_RUNTIME_PAYLOAD_BYTES = 8 * 1024;
|
|
@@ -203,12 +203,7 @@ export function resolvePresetInputFromScope(scope, presetOverride) {
|
|
|
203
203
|
return presetOverride;
|
|
204
204
|
if (scope.preset.snapshot)
|
|
205
205
|
return scope.preset.snapshot;
|
|
206
|
-
|
|
207
|
-
return resolveNamedProxyPreset(scope.preset.presetId);
|
|
208
|
-
}
|
|
209
|
-
catch {
|
|
210
|
-
return undefined;
|
|
211
|
-
}
|
|
206
|
+
throw new Error("proxy.runtime preset snapshot is required");
|
|
212
207
|
}
|
|
213
208
|
export function resolveRuntimePresetLimits(scope) {
|
|
214
209
|
if (scope.limits === undefined)
|
package/dist/proxy/server.d.ts
CHANGED