@floegence/flowersec-core 2.3.6 → 2.3.8
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 +37 -43
- package/THIRD_PARTY_NOTICES.md +4 -79
- package/dist/cli.js +31 -31
- package/dist/connector/adapters/rawQuicCandidate.d.ts +5 -0
- package/dist/connector/adapters/rawQuicCandidate.js +71 -0
- package/dist/connector/sessionAcceptor.d.ts +22 -2
- package/dist/connector/sessionAcceptor.js +51 -21
- package/dist/connector/sessionConnector.d.ts +2 -0
- package/dist/connector/sessionConnector.js +4 -1
- package/dist/interop/proxyServerPeer.d.ts +1 -0
- package/dist/interop/proxyServerPeer.js +83 -0
- package/dist/interop/serverParityPeer.d.ts +1 -0
- package/dist/interop/serverParityPeer.js +608 -0
- package/dist/node/acceptor.d.ts +31 -19
- package/dist/node/acceptor.js +353 -72
- package/dist/node/connectSession.d.ts +2 -1
- package/dist/node/connectSession.js +22 -12
- package/dist/node/controlplane.d.ts +137 -0
- package/dist/node/controlplane.js +439 -0
- package/dist/node/index.d.ts +8 -2
- package/dist/node/index.js +4 -1
- package/dist/node/nativeTransportAddon.d.ts +94 -0
- package/dist/node/nativeTransportAddon.js +166 -0
- package/dist/node/proxyServer.d.ts +31 -0
- package/dist/node/proxyServer.js +572 -0
- package/dist/node/rawQuicAdapter.d.ts +9 -0
- package/dist/node/rawQuicAdapter.js +107 -0
- package/dist/node/rawQuicServer.d.ts +24 -0
- package/dist/node/rawQuicServer.js +37 -0
- package/dist/node/runtimeCapability.d.ts +8 -1
- package/dist/node/runtimeCapability.js +20 -6
- package/dist/node/tunnelRuntime.d.ts +42 -0
- package/dist/node/tunnelRuntime.js +552 -0
- package/dist/node/webSocketServer.d.ts +24 -0
- package/dist/node/webSocketServer.js +135 -0
- package/dist/public/contract.d.ts +4 -3
- package/dist/transport/webSocketAdapter.d.ts +7 -0
- package/dist/transport/webSocketAdapter.js +136 -0
- package/dist/v2/artifact.js +1 -1
- package/dist/v2/capability.js +1 -1
- package/dist/v2/carrier.d.ts +4 -1
- package/dist/v2/carrier.js +2 -2
- package/dist/v2/handshake.js +7 -7
- package/dist/v2/protocol.js +5 -5
- package/dist/v2/publicSession.js +25 -7
- package/dist/v2/session.d.ts +2 -2
- package/dist/v2/session.js +3 -3
- package/dist/v2/unreliableMessage.js +4 -4
- package/dist/vendor/tr46.js +11 -6
- package/dist/ws-client/binaryTransport.d.ts +3 -0
- package/dist/ws-client/binaryTransport.js +14 -0
- package/package.json +19 -16
- package/sbom/cyclonedx.json +52 -2585
- package/sbom/spdx.json +56 -1826
- package/dist/node/webTransportClient.d.ts +0 -9
- package/dist/node/webTransportClient.js +0 -56
- package/dist/node/webTransportServer.d.ts +0 -22
- package/dist/node/webTransportServer.js +0 -100
package/README.md
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
# Flowersec for TypeScript
|
|
2
2
|
|
|
3
|
-
`@floegence/flowersec-core` is the ESM-only Flowersec
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
`@floegence/flowersec-core` is the ESM-only Flowersec SDK for browsers and
|
|
4
|
+
Node.js. It gives both runtimes the same encrypted session, RPC, notification,
|
|
5
|
+
and byte-stream API through the root, `/browser`, `/node`, and `/proxy`
|
|
6
|
+
entrypoints.
|
|
6
7
|
|
|
7
8
|
## Install
|
|
8
9
|
|
|
9
10
|
```bash
|
|
10
|
-
npm install @floegence/flowersec-core
|
|
11
|
+
npm install @floegence/flowersec-core
|
|
11
12
|
```
|
|
12
13
|
|
|
13
14
|
## Public API
|
|
14
15
|
|
|
15
16
|
- `@floegence/flowersec-core` exports the portable artifact, lease, session, stream, RPC, stream-metadata, and connection-controller API, plus profile-owned unreliable messages when negotiated.
|
|
16
17
|
- `@floegence/flowersec-core/browser` adds `connect(...)`, `createConnectionController(...)`, and their options.
|
|
17
|
-
- `@floegence/flowersec-core/node` adds `connect(...)`, `createConnectionController(...)`, `createAcceptor(...)`, `SessionHandlers`, and `
|
|
18
|
+
- `@floegence/flowersec-core/node` adds `connect(...)`, `createConnectionController(...)`, direct-only `createAcceptor(...)`, opaque `createTunnelRuntime(...)`, `SessionHandlers`, `AcceptedSession`, `Issuer`, authorization record/request/response types, `authorizeRuntime(...)`, `authorizeTunnelRuntime(...)`, and `ProxyServer`.
|
|
18
19
|
- `@floegence/flowersec-core/proxy` adds the `Session`-based HTTP/WebSocket runtime, Service Worker and controller/app-window bridges, strict `proxy.runtime@2` validation, and `connectProxyBrowser(...)` composition.
|
|
19
20
|
|
|
20
21
|
The root type exports are:
|
|
@@ -38,7 +39,7 @@ The Browser and Node `connect(...)` operations are one-shot and never reconnect.
|
|
|
38
39
|
|
|
39
40
|
The controller has one scheduler and one in-flight attempt. Its states are `idle`, `connecting`, `connected`, `waiting`, `failed`, and `closed`; immutable snapshots expose `ConnectionSnapshot.retryDisposition` while the corresponding retry decision applies and clear it before a new attempt, after connection, and on close. Call `start()` once, observe snapshots with `subscribe(...)`, await an established session with `waitForSession(...)`, and use `retryNow()` only to wake a `waiting` controller. `close()` cancels acquisition, connection, and waiting before closing the current session.
|
|
40
41
|
|
|
41
|
-
Node `SessionHandlers` accept application stream kinds whose UTF-8 encoding is 1 through 255 bytes and reserve `flowersec.rpc.v2` for Flowersec RPC. `AcceptedSession.serve(...)` closes successfully handled streams. A rejected handler Promise resets
|
|
42
|
+
Node `SessionHandlers` accept application stream kinds whose UTF-8 encoding is 1 through 255 bytes and reserve `flowersec.rpc.v2` for Flowersec RPC. `AcceptedSession.serve(...)` half-closes successfully handled streams. A rejected handler Promise resets only that stream; the accept loop and unrelated streams continue.
|
|
42
43
|
|
|
43
44
|
Source failures return a structured `terminal`, `retryable`, or `retry_after` disposition. Thrown or malformed source failures are terminal. Retry delay is deterministic exponential backoff from 250 ms, doubling to a 30-second maximum with no jitter; `retry_after` is never attempted before its specified Unix-millisecond boundary. Attempts are unlimited unless `maximumAttempts` is explicitly set.
|
|
44
45
|
|
|
@@ -46,25 +47,22 @@ A newly established session replaces `currentSession` atomically. The controller
|
|
|
46
47
|
|
|
47
48
|
A negotiated `Session.unreliableMessages` channel sends defensively copied `Uint8Array` values and returns `accepted`, `dropped_expired`, `dropped_budget`, or `dropped_carrier`. `receive(...)` also returns a fresh `Uint8Array`. Invalid payloads, unavailable channels, cancellation, closure, and internal failures remain redacted public operation errors.
|
|
48
49
|
|
|
49
|
-
##
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
the
|
|
65
|
-
includes static generic RPC result typing, notification subscriptions, and
|
|
66
|
-
proxy composition. These conveniences do not expand the
|
|
67
|
-
portable core required from Go, Swift, or Rust.
|
|
50
|
+
## Supported Connections
|
|
51
|
+
|
|
52
|
+
Browsers support WebSocket. Browser WebTransport is capability-dependent on
|
|
53
|
+
the browser's WebTransport API and is an optional browser adapter, not a
|
|
54
|
+
required native-server carrier. Through
|
|
55
|
+
`/node`, Node.js supports WebSocket and raw QUIC client connections, direct
|
|
56
|
+
server sessions, and opaque `TunnelRuntime` relay legs. Raw QUIC uses the
|
|
57
|
+
Flowersec-owned optional native addon wrapper and one of its supported
|
|
58
|
+
prebuilt platform packages; it never loads from the browser entrypoint. The
|
|
59
|
+
wrapper selects the matching optional package for macOS arm64/x64 or Linux
|
|
60
|
+
arm64/x64 glibc. Windows and musl packages are not published. The same Node entrypoint provides the
|
|
61
|
+
control plane and `ProxyServer`, and the relay never terminates an E2EE
|
|
62
|
+
Session. WebTransport is an optional adapter profile and the Node.js runtime
|
|
63
|
+
does not currently expose a production adapter.
|
|
64
|
+
The `/proxy` entrypoint adds browser bridges for applications that need to keep
|
|
65
|
+
the session behind a Service Worker or another window.
|
|
68
66
|
|
|
69
67
|
## Opaque Boundaries
|
|
70
68
|
|
|
@@ -72,35 +70,31 @@ portable core required from Go, Swift, or Rust.
|
|
|
72
70
|
|
|
73
71
|
`ConnectError` and `SessionError` expose only a closed `code`. They do not retain raw causes, credentials, URLs, candidate diagnostics, transport objects, peer details, or internal routing and handshake state.
|
|
74
72
|
|
|
75
|
-
|
|
73
|
+
Connection negotiation and cryptographic state are not package exports.
|
|
76
74
|
|
|
77
75
|
Admission rejection reasons are server-authorized bounded protocol tokens. Clients validate their wire form without carrying a deployment-specific reason registry; the public error boundary remains closed and redacted.
|
|
78
76
|
|
|
79
|
-
The proxy entrypoint accepts an opaque `ArtifactLease` or an already connected `Session`.
|
|
80
|
-
|
|
81
|
-
## Transport v2 Support
|
|
77
|
+
The proxy entrypoint accepts an opaque `ArtifactLease` or an already connected `Session`. Cross-window bridges require an exact allowed origin and may require a bounded capability nonce; runtime failures are mapped to closed status/code values before reaching Service Worker or Window messages.
|
|
82
78
|
|
|
83
|
-
|
|
79
|
+
## Connection Notes
|
|
84
80
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
Browser applications receive a ready `Session` from `connect(...)`. The browser connector supports WSS, restricted plaintext loopback WebSocket direct connections, and WebTransport. WebTransport uses native HTTP/3 bidirectional streams and does not use Yamux.
|
|
81
|
+
Browser applications receive a ready `Session` from `connect(...)`. The browser
|
|
82
|
+
connector supports WSS, restricted plaintext loopback WebSocket direct
|
|
83
|
+
connections, and WebTransport when the browser exposes that API. WebTransport
|
|
84
|
+
uses browser-owned HTTP/3 streams and is not available in the Node entrypoint.
|
|
90
85
|
|
|
91
86
|
Chromium does not support a WebTransport pooling option; each carrier creates an independent native WebTransport connection.
|
|
92
87
|
|
|
93
88
|
Cold-connection diagnostics require every independent carrier to meet the declared deadline. A `dial_failed` result remains a test failure and is not hidden by pooling, retry, or timeout relaxation.
|
|
94
89
|
|
|
95
|
-
Node.js applications receive the same `Session` contract from `connect(...)`.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
Transport v2 production carrier support: browsers support WebSocket and WebTransport; Node.js supports WebSocket and WebTransport dialing for direct clients and both tunnel roles. Node WebTransport uses the pinned native quiche adapter and is covered by a real admission/session integration test without Playwright.
|
|
90
|
+
Node.js applications receive the same `Session` contract from `connect(...)`.
|
|
91
|
+
The Node connector supports WSS, restricted plaintext loopback WebSocket
|
|
92
|
+
direct connections, and raw QUIC through the optional native package. It
|
|
93
|
+
requires an absolute HTTP(S) `origin`; custom certificate authorities can be
|
|
94
|
+
supplied through `tls.ca`, and raw QUIC requires explicit trust roots.
|
|
102
95
|
|
|
103
|
-
|
|
96
|
+
The connectors choose an eligible connection path from the invitation. They do
|
|
97
|
+
not expose transport selectors, candidate lists, or native carrier objects to application code.
|
|
104
98
|
|
|
105
99
|
## Verify
|
|
106
100
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -3,87 +3,12 @@
|
|
|
3
3
|
This file is generated from the canonical Flowersec source dependency inventory for flowersec-ts.
|
|
4
4
|
Do not edit it manually. License decisions are reviewed by the repository source license policy.
|
|
5
5
|
|
|
6
|
-
- @
|
|
7
|
-
- @
|
|
8
|
-
- @
|
|
9
|
-
- @noble/ciphers 0.6.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.6.0.tgz)
|
|
10
|
-
- @noble/curves 1.9.7 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz)
|
|
11
|
-
- @noble/hashes 1.8.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz)
|
|
12
|
-
- @types/debug 4.1.13 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz)
|
|
13
|
-
- @types/ms 2.1.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz)
|
|
14
|
-
- ansi-regex 5.0.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz)
|
|
15
|
-
- ansi-styles 4.3.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz)
|
|
16
|
-
- base64-js 1.5.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz)
|
|
17
|
-
- bindings 1.5.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz)
|
|
18
|
-
- bl 4.1.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/bl/-/bl-4.1.0.tgz)
|
|
19
|
-
- buffer 5.7.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz)
|
|
20
|
-
- chownr 1.1.4 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz)
|
|
21
|
-
- chownr 3.0.0 (Declared: BlueOak-1.0.0; selected: BlueOak-1.0.0; source: https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz)
|
|
22
|
-
- cliui 8.0.1 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz)
|
|
23
|
-
- cmake-js 8.0.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/cmake-js/-/cmake-js-8.0.0.tgz)
|
|
24
|
-
- color-convert 2.0.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz)
|
|
25
|
-
- color-name 1.1.4 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz)
|
|
26
|
-
- debug 4.4.3 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/debug/-/debug-4.4.3.tgz)
|
|
27
|
-
- decompress-response 6.0.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz)
|
|
28
|
-
- deep-extend 0.6.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz)
|
|
29
|
-
- detect-libc 2.1.2 (Declared: Apache-2.0; selected: Apache-2.0; source: https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz)
|
|
30
|
-
- emoji-regex 8.0.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz)
|
|
31
|
-
- end-of-stream 1.4.5 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz)
|
|
32
|
-
- escalade 3.2.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz)
|
|
33
|
-
- expand-template 2.0.3 (Declared: MIT OR WTFPL; selected: MIT; source: https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz)
|
|
34
|
-
- file-uri-to-path 1.0.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz)
|
|
35
|
-
- fs-constants 1.0.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz)
|
|
36
|
-
- fs-extra 11.4.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/fs-extra/-/fs-extra-11.4.0.tgz)
|
|
37
|
-
- get-caller-file 2.0.5 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz)
|
|
38
|
-
- github-from-package 0.0.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz)
|
|
39
|
-
- graceful-fs 4.2.11 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz)
|
|
40
|
-
- ieee754 1.2.1 (Declared: BSD-3-Clause; selected: BSD-3-Clause; source: https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz)
|
|
41
|
-
- inherits 2.0.4 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz)
|
|
42
|
-
- ini 1.3.8 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/ini/-/ini-1.3.8.tgz)
|
|
43
|
-
- is-fullwidth-code-point 3.0.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz)
|
|
44
|
-
- isexe 4.0.0 (Declared: BlueOak-1.0.0; selected: BlueOak-1.0.0; source: https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz)
|
|
45
|
-
- jsonfile 6.2.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz)
|
|
46
|
-
- mimic-response 3.1.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz)
|
|
47
|
-
- minimist 1.2.8 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz)
|
|
48
|
-
- minipass 7.1.3 (Declared: BlueOak-1.0.0; selected: BlueOak-1.0.0; source: https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz)
|
|
49
|
-
- minizlib 3.1.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz)
|
|
50
|
-
- mkdirp-classic 0.5.3 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz)
|
|
51
|
-
- ms 2.1.3 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/ms/-/ms-2.1.3.tgz)
|
|
52
|
-
- napi-build-utils 2.0.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz)
|
|
53
|
-
- node-abi 3.94.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz)
|
|
54
|
-
- node-addon-api 7.1.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz)
|
|
55
|
-
- node-api-headers 1.9.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.9.0.tgz)
|
|
56
|
-
- once 1.4.0 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/once/-/once-1.4.0.tgz)
|
|
57
|
-
- prebuild-install 7.1.3 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz)
|
|
58
|
-
- pump 3.0.4 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/pump/-/pump-3.0.4.tgz)
|
|
6
|
+
- @noble/ciphers 2.3.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.3.0.tgz)
|
|
7
|
+
- @noble/curves 2.3.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/@noble/curves/-/curves-2.3.0.tgz)
|
|
8
|
+
- @noble/hashes 2.3.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/@noble/hashes/-/hashes-2.3.0.tgz)
|
|
59
9
|
- punycode 2.3.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz)
|
|
60
|
-
- rc 1.2.8 (Declared: BSD-2-Clause OR MIT OR Apache-2.0; selected: MIT; source: https://registry.npmjs.org/rc/-/rc-1.2.8.tgz)
|
|
61
|
-
- readable-stream 3.6.2 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz)
|
|
62
|
-
- require-directory 2.1.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz)
|
|
63
|
-
- safe-buffer 5.2.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz)
|
|
64
|
-
- semver 7.7.3 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/semver/-/semver-7.7.3.tgz)
|
|
65
|
-
- simple-concat 1.0.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz)
|
|
66
|
-
- simple-get 4.0.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz)
|
|
67
|
-
- string_decoder 1.3.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz)
|
|
68
|
-
- string-width 4.2.3 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz)
|
|
69
|
-
- strip-ansi 6.0.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz)
|
|
70
|
-
- strip-json-comments 2.0.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz)
|
|
71
|
-
- tar 7.5.22 (Declared: BlueOak-1.0.0; selected: BlueOak-1.0.0; source: https://registry.npmjs.org/tar/-/tar-7.5.22.tgz)
|
|
72
|
-
- tar-fs 2.1.5 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz)
|
|
73
|
-
- tar-stream 2.2.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz)
|
|
74
10
|
- tr46 5.0.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz)
|
|
75
|
-
-
|
|
76
|
-
- universalify 2.0.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz)
|
|
77
|
-
- url-join 4.0.1 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz)
|
|
78
|
-
- util-deprecate 1.0.2 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz)
|
|
79
|
-
- which 6.0.1 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/which/-/which-6.0.1.tgz)
|
|
80
|
-
- wrap-ansi 7.0.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz)
|
|
81
|
-
- wrappy 1.0.2 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz)
|
|
82
|
-
- ws 8.21.0 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/ws/-/ws-8.21.0.tgz)
|
|
83
|
-
- y18n 5.0.8 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz)
|
|
84
|
-
- yallist 5.0.0 (Declared: BlueOak-1.0.0; selected: BlueOak-1.0.0; source: https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz)
|
|
85
|
-
- yargs 17.7.3 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz)
|
|
86
|
-
- yargs-parser 21.1.1 (Declared: ISC; selected: ISC; source: https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz)
|
|
11
|
+
- ws 8.21.3 (Declared: MIT; selected: MIT; source: https://registry.npmjs.org/ws/-/ws-8.21.3.tgz)
|
|
87
12
|
## Distributed Dependency License Materials
|
|
88
13
|
|
|
89
14
|
The following dependencies are incorporated into distributed Flowersec files or binaries.
|
package/dist/cli.js
CHANGED
|
@@ -1,32 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
|
+
import { acceptNativeSessionV2 } from "./connector/sessionAcceptor.js";
|
|
4
|
+
import { claimSpendMarker } from "./cliSpendMarker.js";
|
|
5
|
+
import { connect } from "./node/connectSession.js";
|
|
6
|
+
import { nodeSessionRuntimeV2 } from "./node/sessionRuntime.js";
|
|
7
|
+
import { startNodeWebSocketServer } from "./node/webSocketServer.js";
|
|
3
8
|
import { createArtifactLeaseV2 } from "./v2/artifactLease.js";
|
|
4
9
|
import { buildFSB2RequestV2, encodeFSB2RequestV2 } from "./v2/artifact.js";
|
|
5
10
|
import { parseArtifact, unwrapArtifact } from "./v2/opaqueArtifact.js";
|
|
6
|
-
import { connect } from "./node/connectSession.js";
|
|
7
|
-
import { startNodeWebTransportServerV2 } from "./node/webTransportServer.js";
|
|
8
|
-
import { acceptNativeSessionV2 } from "./connector/sessionAcceptor.js";
|
|
9
|
-
import { nodeSessionRuntimeV2 } from "./node/sessionRuntime.js";
|
|
10
|
-
import { claimSpendMarker } from "./cliSpendMarker.js";
|
|
11
11
|
const args = parseArguments(process.argv.slice(2));
|
|
12
12
|
if (args.mode === "client")
|
|
13
13
|
await runClient(args.values);
|
|
14
14
|
else
|
|
15
15
|
await runServer(args.values);
|
|
16
16
|
async function runClient(values) {
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
requireWebTransport(values);
|
|
21
|
-
const artifact = parseArtifact(readFileSync(artifactPath));
|
|
17
|
+
requireWebSocket(values);
|
|
18
|
+
const artifact = parseArtifact(readFileSync(required(values, "artifact")));
|
|
19
|
+
const lease = createArtifactLeaseV2(artifact, async () => claimSpendMarker(required(values, "spend-marker")));
|
|
22
20
|
let session;
|
|
23
|
-
const lease = createArtifactLeaseV2(artifact, async () => claimSpendMarker(spendMarker));
|
|
24
21
|
try {
|
|
25
22
|
session = await connect(lease, {
|
|
26
|
-
origin,
|
|
27
|
-
...(values
|
|
28
|
-
tls: { serverCertificateHash: decodeHash(values["certificate-hash"]) },
|
|
29
|
-
}),
|
|
23
|
+
origin: required(values, "origin"),
|
|
24
|
+
...(values.ca === undefined ? {} : { tls: { ca: readFileSync(values.ca, "utf8") } }),
|
|
30
25
|
});
|
|
31
26
|
const stream = await session.openStream("cli");
|
|
32
27
|
await stream.write(new TextEncoder().encode("flowersec-ts-cli"));
|
|
@@ -42,16 +37,27 @@ async function runClient(values) {
|
|
|
42
37
|
}
|
|
43
38
|
}
|
|
44
39
|
async function runServer(values) {
|
|
40
|
+
requireWebSocket(values);
|
|
45
41
|
const artifact = unwrapArtifact(parseArtifact(readFileSync(required(values, "artifact"))));
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
if (artifact.path.kind !== "direct")
|
|
43
|
+
throw new Error("CLI server requires a direct artifact");
|
|
44
|
+
const certificatePath = values.certificate;
|
|
45
|
+
const privateKeyPath = values["private-key"];
|
|
46
|
+
if ((certificatePath === undefined) !== (privateKeyPath === undefined)) {
|
|
47
|
+
throw new Error("--certificate and --private-key must be provided together");
|
|
48
|
+
}
|
|
49
|
+
const server = await startNodeWebSocketServer({
|
|
48
50
|
host: values.host ?? "127.0.0.1",
|
|
49
51
|
port: Number.parseInt(required(values, "port"), 10),
|
|
50
|
-
path:
|
|
51
|
-
|
|
52
|
-
privateKey: readFileSync(required(values, "private-key"), "utf8"),
|
|
53
|
-
carrierPath: artifact.path.kind,
|
|
52
|
+
path: "direct",
|
|
53
|
+
allowedOrigins: [required(values, "origin")],
|
|
54
54
|
inboundBidirectionalStreamCapacity: artifact.session.max_inbound_streams + 2,
|
|
55
|
+
...(certificatePath === undefined || privateKeyPath === undefined ? {} : {
|
|
56
|
+
tls: {
|
|
57
|
+
certificate: readFileSync(certificatePath, "utf8"),
|
|
58
|
+
privateKey: readFileSync(privateKeyPath, "utf8"),
|
|
59
|
+
},
|
|
60
|
+
}),
|
|
55
61
|
});
|
|
56
62
|
process.stdout.write(JSON.stringify(server.address()) + "\n");
|
|
57
63
|
const abort = new AbortController();
|
|
@@ -61,7 +67,7 @@ async function runServer(values) {
|
|
|
61
67
|
try {
|
|
62
68
|
const session = await acceptNativeSessionV2(await server.accept({ signal: abort.signal }), async (request) => {
|
|
63
69
|
const chosen = artifact.path.candidates.find(({ id }) => id === request.request.chosen_candidate_id);
|
|
64
|
-
if (request.request.pathKind !==
|
|
70
|
+
if (request.request.pathKind !== "direct" || chosen?.carrier !== "websocket") {
|
|
65
71
|
throw new Error("CLI server rejected an unexpected artifact candidate");
|
|
66
72
|
}
|
|
67
73
|
const expected = encodeFSB2RequestV2(buildFSB2RequestV2(artifact, request.request.chosen_candidate_id));
|
|
@@ -106,15 +112,9 @@ function required(values, name) {
|
|
|
106
112
|
throw new Error(`missing --${name}`);
|
|
107
113
|
return value;
|
|
108
114
|
}
|
|
109
|
-
function
|
|
110
|
-
if (
|
|
111
|
-
throw new Error("--
|
|
112
|
-
return Uint8Array.from(Buffer.from(value, "hex"));
|
|
113
|
-
}
|
|
114
|
-
function requireWebTransport(values) {
|
|
115
|
-
if (values.transport !== "webtransport") {
|
|
116
|
-
throw new Error("--transport webtransport is required");
|
|
117
|
-
}
|
|
115
|
+
function requireWebSocket(values) {
|
|
116
|
+
if (values.transport !== "websocket")
|
|
117
|
+
throw new Error("--transport websocket is required");
|
|
118
118
|
}
|
|
119
119
|
function bytesEqual(left, right) {
|
|
120
120
|
if (left.length !== right.length)
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ArtifactV2, CanonicalArtifactCandidateV2 } from "../../v2/artifact.js";
|
|
2
|
+
import { type NativeCarrierSessionV2 } from "../../v2/carrier.js";
|
|
3
|
+
import type { CandidateAttemptFactoryV2 } from "../sessionConnector.js";
|
|
4
|
+
export type RawQuicClientFactoryV2 = (candidate: CanonicalArtifactCandidateV2, artifact: ArtifactV2, signal: AbortSignal) => Promise<NativeCarrierSessionV2>;
|
|
5
|
+
export declare function createRawQuicCandidateFactoryV2(factory: RawQuicClientFactoryV2): CandidateAttemptFactoryV2;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { adaptNativeCarrierSessionV2, } from "../../v2/carrier.js";
|
|
2
|
+
export function createRawQuicCandidateFactoryV2(factory) {
|
|
3
|
+
return {
|
|
4
|
+
create(candidate, artifact) {
|
|
5
|
+
if (candidate.carrier !== "raw_quic") {
|
|
6
|
+
throw new Error(`unsupported raw QUIC carrier ${candidate.carrier}`);
|
|
7
|
+
}
|
|
8
|
+
return new RawQuicCandidateAttempt(candidate, artifact, factory);
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
class RawQuicCandidateAttempt {
|
|
13
|
+
candidate;
|
|
14
|
+
artifact;
|
|
15
|
+
factory;
|
|
16
|
+
controller = new AbortController();
|
|
17
|
+
carrier;
|
|
18
|
+
finalized = false;
|
|
19
|
+
constructor(candidate, artifact, factory) {
|
|
20
|
+
this.candidate = candidate;
|
|
21
|
+
this.artifact = artifact;
|
|
22
|
+
this.factory = factory;
|
|
23
|
+
}
|
|
24
|
+
async ready(signal) {
|
|
25
|
+
const unlink = linkAbort(signal, this.controller);
|
|
26
|
+
try {
|
|
27
|
+
const carrier = await this.factory(this.candidate, this.artifact, this.controller.signal);
|
|
28
|
+
this.carrier = carrier;
|
|
29
|
+
return {
|
|
30
|
+
candidate: this.candidate,
|
|
31
|
+
kind: carrier.kind,
|
|
32
|
+
path: carrier.path,
|
|
33
|
+
inboundBidirectionalStreamCapacity: carrier.inboundBidirectionalStreamCapacity,
|
|
34
|
+
openAdmissionChannel: async (channelSignal) => {
|
|
35
|
+
const options = channelSignal === undefined ? {} : { signal: channelSignal };
|
|
36
|
+
const stream = await carrier.openStream(options);
|
|
37
|
+
return {
|
|
38
|
+
framing: "stream",
|
|
39
|
+
stream,
|
|
40
|
+
abort: (error) => stream.abort(error),
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
finalize: () => {
|
|
44
|
+
if (this.finalized)
|
|
45
|
+
throw new Error("raw QUIC candidate already finalized");
|
|
46
|
+
this.finalized = true;
|
|
47
|
+
return adaptNativeCarrierSessionV2(carrier);
|
|
48
|
+
},
|
|
49
|
+
close: async () => await carrier.close(),
|
|
50
|
+
abort: () => carrier.abort({ code: 6, reason: "candidate aborted" }),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
unlink();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
abort() {
|
|
58
|
+
this.controller.abort(new Error("raw QUIC candidate aborted"));
|
|
59
|
+
this.carrier?.abort({ code: 6, reason: "candidate aborted" });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function linkAbort(parent, child) {
|
|
63
|
+
if (parent === undefined)
|
|
64
|
+
return () => undefined;
|
|
65
|
+
const abort = () => child.abort(parent.reason);
|
|
66
|
+
if (parent.aborted)
|
|
67
|
+
abort();
|
|
68
|
+
else
|
|
69
|
+
parent.addEventListener("abort", abort, { once: true });
|
|
70
|
+
return () => parent.removeEventListener("abort", abort);
|
|
71
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AdmissionStatusV2, type ArtifactV2, type DecodedFSB2RequestV2 } from "../v2/artifact.js";
|
|
2
|
-
import {
|
|
2
|
+
import type { CarrierSessionV2, CarrierStreamV2 } from "../v2/carrier.js";
|
|
3
3
|
import type { SessionProtocolRuntimeV2, SessionV2 as InternalSessionV2 } from "../v2/session.js";
|
|
4
4
|
import type { RpcRouter } from "../rpc/server.js";
|
|
5
5
|
export type AdmissionDecisionV2 = Readonly<{
|
|
@@ -11,7 +11,27 @@ export type AdmissionDecisionV2 = Readonly<{
|
|
|
11
11
|
reason: string;
|
|
12
12
|
}>;
|
|
13
13
|
export type AdmissionAuthorizerV2 = (request: DecodedFSB2RequestV2, signal?: AbortSignal) => Promise<AdmissionDecisionV2>;
|
|
14
|
-
export
|
|
14
|
+
export type ReceivedSessionAdmissionV2 = Readonly<{
|
|
15
|
+
carrier: CarrierSessionV2;
|
|
16
|
+
stream: CarrierStreamV2;
|
|
17
|
+
rawFSB2: Uint8Array;
|
|
18
|
+
decoded: DecodedFSB2RequestV2;
|
|
19
|
+
}>;
|
|
20
|
+
export declare function receiveSessionAdmissionV2(carrier: CarrierSessionV2, signal?: AbortSignal): Promise<ReceivedSessionAdmissionV2>;
|
|
21
|
+
export declare function rejectSessionAdmissionV2(received: ReceivedSessionAdmissionV2, decision: Extract<AdmissionDecisionV2, Readonly<{
|
|
22
|
+
accepted: false;
|
|
23
|
+
}>>, signal?: AbortSignal): Promise<never>;
|
|
24
|
+
export declare function acceptReceivedSessionV2(received: ReceivedSessionAdmissionV2, artifact: ArtifactV2, options: Readonly<{
|
|
25
|
+
runtime: SessionProtocolRuntimeV2;
|
|
26
|
+
rpcRouter?: RpcRouter;
|
|
27
|
+
signal?: AbortSignal;
|
|
28
|
+
role?: "client" | "server";
|
|
29
|
+
localAdmissionBinding?: Uint8Array;
|
|
30
|
+
peerAdmissionBinding?: Uint8Array;
|
|
31
|
+
localEndpointInstanceID?: string;
|
|
32
|
+
expectedPeerEndpointInstanceID?: string;
|
|
33
|
+
}>): Promise<InternalSessionV2>;
|
|
34
|
+
export declare function acceptNativeSessionV2(carrier: CarrierSessionV2, authorize: AdmissionAuthorizerV2, options: Readonly<{
|
|
15
35
|
runtime: SessionProtocolRuntimeV2;
|
|
16
36
|
rpcRouter?: RpcRouter;
|
|
17
37
|
signal?: AbortSignal;
|
|
@@ -1,38 +1,68 @@
|
|
|
1
1
|
import { AdmissionStatusV2, buildFSB2RequestV2, decodeFSB2RequestV2, encodeFSB2RequestV2, encodeFSA2ResponseV2, } from "../v2/artifact.js";
|
|
2
|
-
import { adaptNativeCarrierSessionV2 } from "../v2/carrier.js";
|
|
3
2
|
import { establishSessionV2 } from "../v2/session.js";
|
|
4
3
|
import { AdmissionSessionV2Error } from "../v2/admissionError.js";
|
|
5
4
|
import { sessionConfigFromArtifactV2 } from "./sessionConfig.js";
|
|
5
|
+
export async function receiveSessionAdmissionV2(carrier, signal) {
|
|
6
|
+
const stream = carrier.kind === "webtransport"
|
|
7
|
+
? await carrier.openStream(signalOptions(signal))
|
|
8
|
+
: await carrier.acceptStream(signalOptions(signal));
|
|
9
|
+
try {
|
|
10
|
+
const rawFSB2 = await readFSB2(stream, signal);
|
|
11
|
+
return Object.freeze({ carrier, stream, rawFSB2, decoded: decodeFSB2RequestV2(rawFSB2) });
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
stream.abort(asError(error));
|
|
15
|
+
carrier.abort({ code: 6, reason: "admission failed" });
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function rejectSessionAdmissionV2(received, decision, signal) {
|
|
20
|
+
await respondAdmission(received.stream, { status: decision.status, reason: decision.reason }, signal);
|
|
21
|
+
received.carrier.abort({ code: 6, reason: "admission rejected" });
|
|
22
|
+
throw new AdmissionSessionV2Error(decision.reason, `Flowersec v2 admission rejected: ${decision.reason}`);
|
|
23
|
+
}
|
|
24
|
+
export async function acceptReceivedSessionV2(received, artifact, options) {
|
|
25
|
+
try {
|
|
26
|
+
const expected = encodeFSB2RequestV2(buildFSB2RequestV2(artifact, received.decoded.request.chosen_candidate_id));
|
|
27
|
+
if (!equalBytes(expected, received.rawFSB2))
|
|
28
|
+
throw new Error("authorized artifact does not match admission");
|
|
29
|
+
await respondAdmission(received.stream, { status: AdmissionStatusV2.Success, reason: "" }, options.signal);
|
|
30
|
+
const base = sessionConfigFromArtifactV2(artifact, received.rawFSB2, options.runtime, undefined, options.role);
|
|
31
|
+
const config = {
|
|
32
|
+
...base,
|
|
33
|
+
...(options.rpcRouter === undefined ? {} : { rpcRouter: options.rpcRouter }),
|
|
34
|
+
...(options.localAdmissionBinding === undefined ? {} : { localAdmissionBinding: options.localAdmissionBinding }),
|
|
35
|
+
...(options.peerAdmissionBinding === undefined ? {} : { peerAdmissionBinding: options.peerAdmissionBinding }),
|
|
36
|
+
...(options.localEndpointInstanceID === undefined ? {} : { localEndpointInstanceID: options.localEndpointInstanceID }),
|
|
37
|
+
...(options.expectedPeerEndpointInstanceID === undefined ? {} : { expectedPeerEndpointInstanceID: options.expectedPeerEndpointInstanceID }),
|
|
38
|
+
};
|
|
39
|
+
return await establishSessionV2(received.carrier, config, signalOptions(options.signal));
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
received.stream.abort(asError(error));
|
|
43
|
+
received.carrier.abort({ code: 6, reason: "admission failed" });
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
6
47
|
export async function acceptNativeSessionV2(carrier, authorize, options) {
|
|
7
|
-
const
|
|
8
|
-
? await carrier.openStream(signalOptions(options.signal))
|
|
9
|
-
: await carrier.acceptStream(signalOptions(options.signal));
|
|
48
|
+
const received = await receiveSessionAdmissionV2(carrier, options.signal);
|
|
10
49
|
try {
|
|
11
|
-
const
|
|
12
|
-
const decoded = decodeFSB2RequestV2(rawFSB2);
|
|
13
|
-
const decision = await authorize(decoded, options.signal);
|
|
14
|
-
if (decision.accepted) {
|
|
15
|
-
const expected = encodeFSB2RequestV2(buildFSB2RequestV2(decision.artifact, decoded.request.chosen_candidate_id));
|
|
16
|
-
if (!equalBytes(expected, rawFSB2))
|
|
17
|
-
throw new Error("authorized artifact does not match admission");
|
|
18
|
-
}
|
|
19
|
-
const response = decision.accepted
|
|
20
|
-
? { status: AdmissionStatusV2.Success, reason: "" }
|
|
21
|
-
: { status: decision.status, reason: decision.reason };
|
|
22
|
-
await writeAll(admission, encodeFSA2ResponseV2(response), options.signal);
|
|
23
|
-
await raceAbort(admission.closeWrite(), options.signal);
|
|
50
|
+
const decision = await authorize(received.decoded, options.signal);
|
|
24
51
|
if (!decision.accepted) {
|
|
25
|
-
|
|
52
|
+
return await rejectSessionAdmissionV2(received, decision, options.signal);
|
|
26
53
|
}
|
|
27
|
-
|
|
28
|
-
return await establishSessionV2(adaptNativeCarrierSessionV2(carrier), options.rpcRouter === undefined ? config : { ...config, rpcRouter: options.rpcRouter }, signalOptions(options.signal));
|
|
54
|
+
return await acceptReceivedSessionV2(received, decision.artifact, { ...options, role: "server" });
|
|
29
55
|
}
|
|
30
56
|
catch (error) {
|
|
31
|
-
|
|
57
|
+
received.stream.abort(asError(error));
|
|
32
58
|
carrier.abort({ code: 6, reason: "admission failed" });
|
|
33
59
|
throw error;
|
|
34
60
|
}
|
|
35
61
|
}
|
|
62
|
+
async function respondAdmission(stream, response, signal) {
|
|
63
|
+
await writeAll(stream, encodeFSA2ResponseV2(response), signal);
|
|
64
|
+
await raceAbort(stream.closeWrite(), signal);
|
|
65
|
+
}
|
|
36
66
|
function equalBytes(left, right) {
|
|
37
67
|
if (left.length !== right.length)
|
|
38
68
|
return false;
|
|
@@ -2,6 +2,7 @@ import { type ArtifactV2, type CanonicalArtifactCandidateV2 } from "../v2/artifa
|
|
|
2
2
|
import { type SessionDeadlineFactoryV2, type SessionProtocolRuntimeV2, type SessionV2 as InternalSessionV2 } from "../v2/session.js";
|
|
3
3
|
import type { ArtifactLeaseV2 } from "../v2/artifactLease.js";
|
|
4
4
|
import { type RuntimeCapabilityDescriptorV2 } from "../v2/capability.js";
|
|
5
|
+
import type { RpcRouter } from "../rpc/server.js";
|
|
5
6
|
import { type ReadyAdmissionTransportV2 } from "./admissionCommit.js";
|
|
6
7
|
export type SessionConnectorStateV2 = "attempt" | "ready" | "winner" | "admitted" | "established" | "terminated";
|
|
7
8
|
export type ConnectorArtifactLeaseV2 = ArtifactLeaseV2;
|
|
@@ -20,6 +21,7 @@ export type SessionConnectorOptionsV2 = Readonly<{
|
|
|
20
21
|
}>;
|
|
21
22
|
type SessionConnectorInternalOptionsV2 = Readonly<{
|
|
22
23
|
runtime: SessionProtocolRuntimeV2;
|
|
24
|
+
rpcRouter?: RpcRouter;
|
|
23
25
|
connectTimeoutMs?: number;
|
|
24
26
|
deadlineFactory?: SessionDeadlineFactoryV2;
|
|
25
27
|
loserCloseTimeoutMs?: number;
|
|
@@ -199,7 +199,10 @@ export class SessionConnectorV2 {
|
|
|
199
199
|
let config;
|
|
200
200
|
try {
|
|
201
201
|
rawFSB2 = encodeFSB2RequestV2(buildFSB2RequestV2(this.artifact, selected.attempt.candidate.id));
|
|
202
|
-
|
|
202
|
+
const baseConfig = sessionConfigFromArtifactV2(this.artifact, rawFSB2, this.options.runtime, this.options.deadlineFactory);
|
|
203
|
+
config = this.options.rpcRouter === undefined
|
|
204
|
+
? baseConfig
|
|
205
|
+
: { ...baseConfig, rpcRouter: this.options.rpcRouter };
|
|
203
206
|
}
|
|
204
207
|
catch (error) {
|
|
205
208
|
const closeFailure = await captureCandidateCleanupFailure(selected.attempt.candidate, "close selected candidate", () => selected.ready.close(), loserCloseTimeoutMs, operationSignal, abortSources, selected.ready.abort);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|