@floegence/flowersec-core 0.26.0 → 2.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.
Files changed (270) hide show
  1. package/README.md +91 -22
  2. package/THIRD_PARTY_NOTICES.md +141 -0
  3. package/dist/browser/connectSession.d.ts +13 -0
  4. package/dist/browser/connectSession.js +40 -0
  5. package/dist/browser/index.d.ts +3 -10
  6. package/dist/browser/index.js +2 -5
  7. package/dist/browser/runtimeCapability.d.ts +13 -0
  8. package/dist/browser/runtimeCapability.js +27 -0
  9. package/dist/browser/sessionRuntime.d.ts +2 -0
  10. package/dist/browser/sessionRuntime.js +21 -0
  11. package/dist/browser/webTransportClient.d.ts +8 -0
  12. package/dist/browser/webTransportClient.js +55 -0
  13. package/dist/cli.d.ts +2 -0
  14. package/dist/cli.js +126 -0
  15. package/dist/cliSpendMarker.d.ts +1 -0
  16. package/dist/cliSpendMarker.js +22 -0
  17. package/dist/connectionController.d.ts +54 -0
  18. package/dist/connectionController.js +438 -0
  19. package/dist/connector/adapters/webSocketCandidate.d.ts +7 -0
  20. package/dist/connector/adapters/webSocketCandidate.js +116 -0
  21. package/dist/connector/adapters/webTransportCandidate.d.ts +5 -0
  22. package/dist/connector/adapters/webTransportCandidate.js +73 -0
  23. package/dist/connector/admissionCommit.d.ts +31 -0
  24. package/dist/connector/admissionCommit.js +239 -0
  25. package/dist/connector/sessionAcceptor.d.ts +16 -0
  26. package/dist/connector/sessionAcceptor.js +114 -0
  27. package/dist/connector/sessionConfig.d.ts +3 -0
  28. package/dist/connector/sessionConfig.js +30 -0
  29. package/dist/connector/sessionConnector.d.ts +45 -0
  30. package/dist/connector/sessionConnector.js +603 -0
  31. package/dist/defaults.d.ts +7 -7
  32. package/dist/defaults.js +7 -7
  33. package/dist/facade.d.ts +12 -30
  34. package/dist/facade.js +6 -30
  35. package/dist/node/connectSession.d.ts +21 -0
  36. package/dist/node/connectSession.js +62 -0
  37. package/dist/node/index.d.ts +3 -11
  38. package/dist/node/index.js +2 -8
  39. package/dist/node/runtimeCapability.d.ts +7 -0
  40. package/dist/node/runtimeCapability.js +10 -0
  41. package/dist/node/sessionRuntime.d.ts +2 -0
  42. package/dist/node/sessionRuntime.js +13 -0
  43. package/dist/node/webTransportClient.d.ts +9 -0
  44. package/dist/node/webTransportClient.js +56 -0
  45. package/dist/node/webTransportServer.d.ts +22 -0
  46. package/dist/node/webTransportServer.js +100 -0
  47. package/dist/node/wsFactory.d.ts +3 -1
  48. package/dist/node/wsFactory.js +4 -3
  49. package/dist/proxy/controllerGuard.d.ts +4 -4
  50. package/dist/proxy/controllerGuard.js +83 -177
  51. package/dist/proxy/disableUpstreamServiceWorkerRegister.d.ts +3 -1
  52. package/dist/proxy/disableUpstreamServiceWorkerRegister.js +19 -17
  53. package/dist/proxy/index.d.ts +16 -15
  54. package/dist/proxy/index.js +8 -14
  55. package/dist/proxy/integration.d.ts +23 -71
  56. package/dist/proxy/integration.js +37 -340
  57. package/dist/proxy/registerServiceWorker.d.ts +1 -10
  58. package/dist/proxy/registerServiceWorker.js +43 -105
  59. package/dist/proxy/runtime.d.ts +3 -63
  60. package/dist/proxy/runtime.js +349 -462
  61. package/dist/proxy/scope.d.ts +6 -0
  62. package/dist/proxy/scope.js +131 -0
  63. package/dist/proxy/serviceWorker.d.ts +5 -16
  64. package/dist/proxy/serviceWorker.js +230 -617
  65. package/dist/proxy/stream.d.ts +9 -0
  66. package/dist/proxy/stream.js +40 -0
  67. package/dist/proxy/types.d.ts +78 -30
  68. package/dist/proxy/windowBridge.d.ts +61 -0
  69. package/dist/proxy/windowBridge.js +344 -0
  70. package/dist/proxy/wsPatch.d.ts +4 -14
  71. package/dist/proxy/wsPatch.js +173 -268
  72. package/dist/public/artifact.d.ts +11 -0
  73. package/dist/public/artifact.js +44 -0
  74. package/dist/public/artifactLease.d.ts +10 -0
  75. package/dist/public/artifactLease.js +48 -0
  76. package/dist/public/connectError.d.ts +6 -0
  77. package/dist/public/connectError.js +9 -0
  78. package/dist/public/contract.d.ts +83 -0
  79. package/dist/public/contract.js +17 -0
  80. package/dist/public/streamMetadata.d.ts +10 -0
  81. package/dist/public/streamMetadata.js +40 -0
  82. package/dist/rpc/caller.d.ts +1 -1
  83. package/dist/rpc/client.d.ts +1 -4
  84. package/dist/rpc/client.js +0 -21
  85. package/dist/rpc/rpcProxy.d.ts +1 -1
  86. package/dist/rpc/server.d.ts +1 -1
  87. package/dist/rpc/validate.d.ts +1 -1
  88. package/dist/rpc/wire.d.ts +15 -0
  89. package/dist/runtime/errors.d.ts +6 -0
  90. package/dist/runtime/errors.js +10 -0
  91. package/dist/transport/webSocketAdapter.d.ts +24 -0
  92. package/dist/transport/webSocketAdapter.js +234 -0
  93. package/dist/transport/webTransportAdapter.d.ts +27 -0
  94. package/dist/transport/webTransportAdapter.js +519 -0
  95. package/dist/utils/errors.d.ts +2 -20
  96. package/dist/utils/errors.js +73 -20
  97. package/dist/v2/admissionError.d.ts +4 -0
  98. package/dist/v2/admissionError.js +8 -0
  99. package/dist/v2/artifact.d.ts +128 -0
  100. package/dist/v2/artifact.js +1126 -0
  101. package/dist/v2/artifactLease.d.ts +1 -0
  102. package/dist/v2/artifactLease.js +7 -0
  103. package/dist/v2/capability.d.ts +29 -0
  104. package/dist/v2/capability.js +190 -0
  105. package/dist/v2/carrier.d.ts +79 -0
  106. package/dist/v2/carrier.js +405 -0
  107. package/dist/v2/contract.d.ts +37 -0
  108. package/dist/v2/contract.js +1 -0
  109. package/dist/v2/handshake.d.ts +80 -0
  110. package/dist/v2/handshake.js +470 -0
  111. package/dist/v2/opaqueArtifact.d.ts +1 -0
  112. package/dist/v2/opaqueArtifact.js +2 -0
  113. package/dist/v2/protocol.d.ts +99 -0
  114. package/dist/v2/protocol.js +739 -0
  115. package/dist/v2/publicSession.d.ts +1 -0
  116. package/dist/v2/publicSession.js +179 -0
  117. package/dist/v2/retryDisposition.d.ts +16 -0
  118. package/dist/v2/retryDisposition.js +30 -0
  119. package/dist/v2/session.d.ts +277 -0
  120. package/dist/v2/session.js +1879 -0
  121. package/dist/v2/streamLifetimeLedger.d.ts +31 -0
  122. package/dist/v2/streamLifetimeLedger.js +131 -0
  123. package/dist/v2/streamMetadata.d.ts +1 -0
  124. package/dist/v2/streamMetadata.js +7 -0
  125. package/dist/v2/unreliableMessage.d.ts +43 -0
  126. package/dist/v2/unreliableMessage.js +252 -0
  127. package/dist/vendor/tr46.d.ts +10 -0
  128. package/dist/vendor/tr46.js +501 -0
  129. package/dist/ws-client/binaryTransport.d.ts +0 -3
  130. package/dist/ws-client/binaryTransport.js +15 -39
  131. package/dist/yamux/errors.d.ts +0 -4
  132. package/dist/yamux/errors.js +0 -9
  133. package/dist/yamux/session.d.ts +0 -5
  134. package/dist/yamux/session.js +4 -70
  135. package/dist/yamux/stream.d.ts +1 -0
  136. package/dist/yamux/stream.js +4 -0
  137. package/package.json +29 -83
  138. package/sbom/cyclonedx.json +2764 -0
  139. package/sbom/spdx.json +1947 -0
  140. package/YAMUX_ALIGNMENT.md +0 -127
  141. package/dist/_examples/flowersec/demo/v1.facade.gen.d.ts +0 -12
  142. package/dist/_examples/flowersec/demo/v1.facade.gen.js +0 -15
  143. package/dist/_examples/flowersec/demo/v1.gen.d.ts +0 -16
  144. package/dist/_examples/flowersec/demo/v1.gen.js +0 -86
  145. package/dist/_examples/flowersec/demo/v1.rpc.gen.d.ts +0 -11
  146. package/dist/_examples/flowersec/demo/v1.rpc.gen.js +0 -22
  147. package/dist/browser/connect.d.ts +0 -12
  148. package/dist/browser/connect.js +0 -31
  149. package/dist/browser/controlplane.d.ts +0 -15
  150. package/dist/browser/controlplane.js +0 -64
  151. package/dist/browser/reconnectConfig.d.ts +0 -15
  152. package/dist/browser/reconnectConfig.js +0 -20
  153. package/dist/client-connect/common.d.ts +0 -26
  154. package/dist/client-connect/common.js +0 -167
  155. package/dist/client-connect/connectCore.d.ts +0 -61
  156. package/dist/client-connect/connectCore.js +0 -572
  157. package/dist/client-connect/contract.d.ts +0 -8
  158. package/dist/client-connect/contract.js +0 -51
  159. package/dist/client-connect/termination.d.ts +0 -6
  160. package/dist/client-connect/termination.js +0 -7
  161. package/dist/client-connect/transportSecurity.d.ts +0 -27
  162. package/dist/client-connect/transportSecurity.js +0 -199
  163. package/dist/client-connect/tunnelAttachCloseReason.d.ts +0 -3
  164. package/dist/client-connect/tunnelAttachCloseReason.js +0 -23
  165. package/dist/client.d.ts +0 -23
  166. package/dist/connect/artifact.d.ts +0 -37
  167. package/dist/connect/artifact.js +0 -217
  168. package/dist/connect/internalNormalize.d.ts +0 -22
  169. package/dist/connect/internalNormalize.js +0 -173
  170. package/dist/controlplane/channelInit.d.ts +0 -27
  171. package/dist/controlplane/channelInit.js +0 -116
  172. package/dist/controlplane/http.d.ts +0 -16
  173. package/dist/controlplane/http.js +0 -59
  174. package/dist/controlplane/index.d.ts +0 -6
  175. package/dist/controlplane/index.js +0 -5
  176. package/dist/controlplane/issuer.d.ts +0 -18
  177. package/dist/controlplane/issuer.js +0 -113
  178. package/dist/controlplane/request.d.ts +0 -51
  179. package/dist/controlplane/request.js +0 -273
  180. package/dist/controlplane/token.d.ts +0 -33
  181. package/dist/controlplane/token.js +0 -119
  182. package/dist/direct-client/connect.d.ts +0 -9
  183. package/dist/direct-client/connect.js +0 -90
  184. package/dist/direct-client/index.d.ts +0 -1
  185. package/dist/direct-client/index.js +0 -1
  186. package/dist/e2ee/constants.d.ts +0 -9
  187. package/dist/e2ee/constants.js +0 -18
  188. package/dist/e2ee/errors.d.ts +0 -5
  189. package/dist/e2ee/errors.js +0 -8
  190. package/dist/e2ee/framing.d.ts +0 -12
  191. package/dist/e2ee/framing.js +0 -57
  192. package/dist/e2ee/handshake.d.ts +0 -88
  193. package/dist/e2ee/handshake.js +0 -353
  194. package/dist/e2ee/index.d.ts +0 -7
  195. package/dist/e2ee/index.js +0 -7
  196. package/dist/e2ee/kdf.d.ts +0 -15
  197. package/dist/e2ee/kdf.js +0 -39
  198. package/dist/e2ee/record.d.ts +0 -11
  199. package/dist/e2ee/record.js +0 -76
  200. package/dist/e2ee/secureChannel.d.ts +0 -92
  201. package/dist/e2ee/secureChannel.js +0 -328
  202. package/dist/e2ee/transcript.d.ts +0 -23
  203. package/dist/e2ee/transcript.js +0 -31
  204. package/dist/endpoint/index.d.ts +0 -84
  205. package/dist/endpoint/index.js +0 -557
  206. package/dist/endpoint/node.d.ts +0 -9
  207. package/dist/endpoint/node.js +0 -51
  208. package/dist/gen/flowersec/controlplane/v1.gen.d.ts +0 -36
  209. package/dist/gen/flowersec/controlplane/v1.gen.js +0 -135
  210. package/dist/gen/flowersec/direct/v1.gen.d.ts +0 -21
  211. package/dist/gen/flowersec/direct/v1.gen.js +0 -101
  212. package/dist/gen/flowersec/e2ee/v1.gen.d.ts +0 -68
  213. package/dist/gen/flowersec/e2ee/v1.gen.js +0 -194
  214. package/dist/gen/flowersec/rpc/v1.gen.d.ts +0 -30
  215. package/dist/gen/flowersec/rpc/v1.gen.js +0 -107
  216. package/dist/gen/flowersec/tunnel/v1.gen.d.ts +0 -23
  217. package/dist/gen/flowersec/tunnel/v1.gen.js +0 -104
  218. package/dist/index.d.ts +0 -22
  219. package/dist/index.js +0 -22
  220. package/dist/node/connect.d.ts +0 -12
  221. package/dist/node/connect.js +0 -29
  222. package/dist/node/reconnectConfig.d.ts +0 -16
  223. package/dist/node/reconnectConfig.js +0 -20
  224. package/dist/observability/index.d.ts +0 -1
  225. package/dist/observability/index.js +0 -1
  226. package/dist/observability/observer.d.ts +0 -52
  227. package/dist/observability/observer.js +0 -314
  228. package/dist/proxy/appWindow.d.ts +0 -37
  229. package/dist/proxy/appWindow.js +0 -273
  230. package/dist/proxy/bootstrap.d.ts +0 -35
  231. package/dist/proxy/bootstrap.js +0 -119
  232. package/dist/proxy/constants.d.ts +0 -7
  233. package/dist/proxy/constants.js +0 -8
  234. package/dist/proxy/controllerWindow.d.ts +0 -12
  235. package/dist/proxy/controllerWindow.js +0 -384
  236. package/dist/proxy/cookieJar.d.ts +0 -7
  237. package/dist/proxy/cookieJar.js +0 -136
  238. package/dist/proxy/headerPolicy.d.ts +0 -14
  239. package/dist/proxy/headerPolicy.js +0 -134
  240. package/dist/proxy/portStream.d.ts +0 -5
  241. package/dist/proxy/portStream.js +0 -256
  242. package/dist/proxy/preset.d.ts +0 -29
  243. package/dist/proxy/preset.js +0 -111
  244. package/dist/proxy/runtimeScope.d.ts +0 -57
  245. package/dist/proxy/runtimeScope.js +0 -218
  246. package/dist/proxy/server.d.ts +0 -28
  247. package/dist/proxy/server.js +0 -833
  248. package/dist/proxy/windowBridgeProtocol.d.ts +0 -65
  249. package/dist/proxy/windowBridgeProtocol.js +0 -11
  250. package/dist/reconnect/artifactControlplane.d.ts +0 -16
  251. package/dist/reconnect/artifactControlplane.js +0 -35
  252. package/dist/reconnect/index.d.ts +0 -36
  253. package/dist/reconnect/index.js +0 -388
  254. package/dist/rpc-proxy/index.d.ts +0 -1
  255. package/dist/rpc-proxy/index.js +0 -1
  256. package/dist/rpc-proxy/rpcProxy.d.ts +0 -1
  257. package/dist/rpc-proxy/rpcProxy.js +0 -1
  258. package/dist/streamhello/index.d.ts +0 -1
  259. package/dist/streamhello/index.js +0 -1
  260. package/dist/streamhello/streamHello.d.ts +0 -3
  261. package/dist/streamhello/streamHello.js +0 -13
  262. package/dist/streamio/index.d.ts +0 -32
  263. package/dist/streamio/index.js +0 -87
  264. package/dist/tunnel-client/connect.d.ts +0 -9
  265. package/dist/tunnel-client/connect.js +0 -157
  266. package/dist/tunnel-client/index.d.ts +0 -1
  267. package/dist/tunnel-client/index.js +0 -1
  268. package/dist/ws/index.d.ts +0 -1
  269. package/dist/ws/index.js +0 -1
  270. /package/dist/{client.js → rpc/wire.js} +0 -0
@@ -0,0 +1,83 @@
1
+ import type { StreamMetadata } from "./streamMetadata.js";
2
+ export type CarrierKind = "websocket" | "raw_quic" | "webtransport";
3
+ export type PathKind = "direct" | "tunnel";
4
+ export type JsonPrimitive = null | boolean | number | string;
5
+ export type JsonValue = JsonPrimitive | JsonObject | readonly JsonValue[];
6
+ export type JsonObject = Readonly<{
7
+ [key: string]: JsonValue;
8
+ }>;
9
+ export type OperationOptions = Readonly<{
10
+ signal?: AbortSignal;
11
+ }>;
12
+ export type UnreliableMessageSendOptions = OperationOptions & Readonly<{
13
+ expiresAtUnixMs: number;
14
+ }>;
15
+ export type UnreliableMessageSendResult = "accepted" | "dropped_budget" | "dropped_expired" | "dropped_carrier";
16
+ export interface UnreliableMessageChannel {
17
+ readonly maxMessageSize: 976;
18
+ send(message: Uint8Array, options: UnreliableMessageSendOptions): Promise<UnreliableMessageSendResult>;
19
+ receive(options?: OperationOptions): Promise<Uint8Array>;
20
+ }
21
+ export declare class UnreliableMessageError extends Error {
22
+ readonly code: "invalid_message" | "closed" | "operation_failed";
23
+ constructor(code: "invalid_message" | "closed" | "operation_failed");
24
+ }
25
+ export type StreamOpenOptions = OperationOptions & Readonly<{
26
+ metadata?: StreamMetadata;
27
+ }>;
28
+ export type SessionErrorCode = "canceled" | "timeout" | "closed" | "going_away" | "resource_exhausted" | "stream_rejected" | "stream_reset" | "rekey_failed" | "liveness_failed" | "unreliable_unavailable" | "unreliable_too_large" | "unreliable_dropped" | "operation_failed";
29
+ /** A closed, carrier-neutral session failure with no internal cause or peer detail. */
30
+ export declare class SessionError extends Error {
31
+ readonly code: SessionErrorCode;
32
+ constructor(code: SessionErrorCode);
33
+ }
34
+ export type RpcResult<Response = unknown> = Readonly<{
35
+ ok: true;
36
+ payload: Response;
37
+ }> | Readonly<{
38
+ ok: false;
39
+ error: Readonly<{
40
+ code: number;
41
+ message?: string;
42
+ }>;
43
+ }>;
44
+ export interface RpcPeer {
45
+ call<Request = unknown, Response = unknown>(typeId: number, payload: Request, decodeResponse: (payload: JsonValue) => Response, signal?: AbortSignal): Promise<RpcResult<Response>>;
46
+ notify<Payload = unknown>(typeId: number, payload: Payload): Promise<void>;
47
+ onNotify<Payload = unknown>(typeId: number, handler: (payload: Payload) => void): () => void;
48
+ }
49
+ export interface ByteStream {
50
+ readonly kind: string;
51
+ readonly terminalError: SessionError | undefined;
52
+ read(options?: OperationOptions): Promise<Uint8Array | null>;
53
+ write(data: Uint8Array, options?: OperationOptions): Promise<number>;
54
+ closeWrite(): Promise<void>;
55
+ reset(): Promise<void>;
56
+ close(): Promise<void>;
57
+ }
58
+ export interface IncomingStream {
59
+ readonly kind: string;
60
+ readonly metadata: StreamMetadata;
61
+ readonly stream: ByteStream;
62
+ }
63
+ export type SessionTermination = Readonly<{
64
+ error: SessionError;
65
+ }>;
66
+ export interface Session {
67
+ readonly rpc: RpcPeer;
68
+ readonly unreliableMessages?: UnreliableMessageChannel;
69
+ openStream(kind: string, options?: StreamOpenOptions): Promise<ByteStream>;
70
+ acceptStream(options?: OperationOptions): Promise<IncomingStream>;
71
+ rekey(options?: OperationOptions): Promise<void>;
72
+ probeLiveness(options?: OperationOptions): Promise<number>;
73
+ waitTermination(): Promise<SessionTermination>;
74
+ close(): Promise<void>;
75
+ }
76
+ export type RetryDisposition = Readonly<{
77
+ kind: "terminal";
78
+ }> | Readonly<{
79
+ kind: "retryable";
80
+ }> | Readonly<{
81
+ kind: "retry_after";
82
+ notBeforeUnixMilliseconds: number;
83
+ }>;
@@ -0,0 +1,17 @@
1
+ export class UnreliableMessageError extends Error {
2
+ code;
3
+ constructor(code) {
4
+ super(`Flowersec unreliable message failed (code=${code})`);
5
+ this.code = code;
6
+ this.name = "UnreliableMessageError";
7
+ }
8
+ }
9
+ /** A closed, carrier-neutral session failure with no internal cause or peer detail. */
10
+ export class SessionError extends Error {
11
+ code;
12
+ constructor(code) {
13
+ super(`Flowersec session failed (code=${code})`);
14
+ this.code = code;
15
+ this.name = "SessionError";
16
+ }
17
+ }
@@ -0,0 +1,10 @@
1
+ import type { JsonObject } from "./contract.js";
2
+ export declare class StreamMetadataError extends Error {
3
+ constructor();
4
+ }
5
+ export declare class StreamMetadata {
6
+ readonly values: JsonObject;
7
+ private readonly streamMetadataBrand;
8
+ private constructor();
9
+ }
10
+ export declare function createStreamMetadata(values: JsonObject): StreamMetadata;
@@ -0,0 +1,40 @@
1
+ import { canonicalStreamMetadataJSONV2Internal } from "../v2/protocol.js";
2
+ export class StreamMetadataError extends Error {
3
+ constructor() {
4
+ super("invalid Flowersec stream metadata");
5
+ this.name = "StreamMetadataError";
6
+ }
7
+ }
8
+ export class StreamMetadata {
9
+ values;
10
+ constructor(values) {
11
+ this.values = values;
12
+ Object.freeze(this);
13
+ }
14
+ /** @internal */
15
+ static fromCanonicalValues(values) {
16
+ return new StreamMetadata(values);
17
+ }
18
+ }
19
+ export function createStreamMetadata(values) {
20
+ try {
21
+ const canonical = canonicalStreamMetadataJSONV2Internal(values);
22
+ return StreamMetadata.fromCanonicalValues(deepFreeze(JSON.parse(canonical)));
23
+ }
24
+ catch {
25
+ throw new StreamMetadataError();
26
+ }
27
+ }
28
+ /** @internal */
29
+ export function streamMetadataValues(metadata) {
30
+ if (!(metadata instanceof StreamMetadata))
31
+ throw new StreamMetadataError();
32
+ return metadata.values;
33
+ }
34
+ function deepFreeze(value) {
35
+ if (typeof value !== "object" || value === null || Object.isFrozen(value))
36
+ return value;
37
+ for (const child of Object.values(value))
38
+ deepFreeze(child);
39
+ return Object.freeze(value);
40
+ }
@@ -1,4 +1,4 @@
1
- import type { RpcError } from "../gen/flowersec/rpc/v1.gen.js";
1
+ import type { RpcError } from "./wire.js";
2
2
  export type RpcCaller = {
3
3
  call(typeId: number, payload: unknown, signal?: AbortSignal): Promise<{
4
4
  payload: unknown;
@@ -1,5 +1,4 @@
1
- import type { RpcError } from "../gen/flowersec/rpc/v1.gen.js";
2
- import { type ClientObserverLike } from "../observability/observer.js";
1
+ import type { RpcError } from "./wire.js";
3
2
  export declare class RpcClient {
4
3
  private readonly readExactly;
5
4
  private readonly write;
@@ -7,10 +6,8 @@ export declare class RpcClient {
7
6
  private readonly pending;
8
7
  private readonly notifyHandlers;
9
8
  private closed;
10
- private readonly observer;
11
9
  private readonly onTerminal;
12
10
  constructor(readExactly: (n: number) => Promise<Uint8Array>, write: (b: Uint8Array) => Promise<void>, opts?: Readonly<{
13
- observer?: ClientObserverLike;
14
11
  onTerminal?: (error: Error) => void;
15
12
  }>);
16
13
  call(typeId: number, payload: unknown, signal?: AbortSignal): Promise<{
@@ -1,4 +1,3 @@
1
- import { normalizeObserver, nowSeconds } from "../observability/observer.js";
2
1
  import { DEFAULT_MAX_JSON_FRAME_BYTES, readJsonFrame, writeJsonFrame } from "../framing/jsonframe.js";
3
2
  import { assertRpcEnvelope } from "./validate.js";
4
3
  // Guard against precision loss when encoding request IDs as numbers.
@@ -15,13 +14,10 @@ export class RpcClient {
15
14
  notifyHandlers = new Map();
16
15
  // Closed state to stop the read loop and reject calls.
17
16
  closed = false;
18
- // Observer for RPC events.
19
- observer;
20
17
  onTerminal;
21
18
  constructor(readExactly, write, opts = {}) {
22
19
  this.readExactly = readExactly;
23
20
  this.write = write;
24
- this.observer = normalizeObserver(opts.observer);
25
21
  this.onTerminal = opts.onTerminal;
26
22
  void this.readLoop();
27
23
  }
@@ -31,10 +27,6 @@ export class RpcClient {
31
27
  throw new Error("rpc client closed");
32
28
  if (this.nextId > MAX_SAFE_REQUEST_ID)
33
29
  throw new Error("request id overflow");
34
- const start = nowSeconds();
35
- const record = (result) => {
36
- this.observer.onRpcCall(result, nowSeconds() - start);
37
- };
38
30
  const requestId = this.nextId;
39
31
  this.nextId += 1n;
40
32
  const env = {
@@ -51,12 +43,10 @@ export class RpcClient {
51
43
  }
52
44
  catch (e) {
53
45
  this.pending.delete(requestId);
54
- record("transport_error");
55
46
  throw e;
56
47
  }
57
48
  if (signal?.aborted) {
58
49
  this.pending.delete(requestId);
59
- record("canceled");
60
50
  throw signal.reason ?? new Error("aborted");
61
51
  }
62
52
  let resp;
@@ -65,11 +55,8 @@ export class RpcClient {
65
55
  }
66
56
  catch (e) {
67
57
  this.pending.delete(requestId);
68
- record(signal?.aborted ? "canceled" : "transport_error");
69
58
  throw e;
70
59
  }
71
- const result = rpcResultFromError(resp.error);
72
- record(result);
73
60
  if (resp.error == null)
74
61
  return { payload: resp.payload };
75
62
  return { payload: resp.payload, error: resp.error };
@@ -114,7 +101,6 @@ export class RpcClient {
114
101
  if (v.response_to === 0) {
115
102
  // Notification: response_to=0 and request_id=0.
116
103
  if (v.request_id === 0) {
117
- this.observer.onRpcNotify();
118
104
  const set = this.notifyHandlers.get(v.type_id >>> 0);
119
105
  if (set != null) {
120
106
  for (const h of set) {
@@ -172,10 +158,3 @@ async function raceAbort(p, signal) {
172
158
  });
173
159
  });
174
160
  }
175
- function rpcResultFromError(err) {
176
- if (err == null)
177
- return "ok";
178
- if (err.code === 404)
179
- return "handler_not_found";
180
- return "rpc_error";
181
- }
@@ -10,7 +10,7 @@ export declare class RpcProxy {
10
10
  onNotify(typeId: number, handler: (payload: unknown) => void): () => void;
11
11
  call(typeId: number, payload: unknown, signal?: AbortSignal): Promise<{
12
12
  payload: unknown;
13
- error?: import("../gen/flowersec/rpc/v1.gen.js").RpcError;
13
+ error?: import("./wire.js").RpcError;
14
14
  }>;
15
15
  notify(typeId: number, payload: unknown): Promise<void>;
16
16
  }
@@ -1,4 +1,4 @@
1
- import type { RpcError } from "../gen/flowersec/rpc/v1.gen.js";
1
+ import type { RpcError } from "./wire.js";
2
2
  export type RpcHandler = (payload: unknown) => Promise<{
3
3
  payload: unknown;
4
4
  error?: RpcError;
@@ -1,2 +1,2 @@
1
- import type { RpcEnvelope } from "../gen/flowersec/rpc/v1.gen.js";
1
+ import type { RpcEnvelope } from "./wire.js";
2
2
  export declare function assertRpcEnvelope(v: unknown): RpcEnvelope;
@@ -0,0 +1,15 @@
1
+ export interface RpcEnvelope {
2
+ type_id: number;
3
+ request_id: number;
4
+ response_to: number;
5
+ payload: unknown;
6
+ error?: RpcError;
7
+ }
8
+ export interface RpcError {
9
+ code: number;
10
+ message?: string;
11
+ }
12
+ export interface StreamHello {
13
+ kind: string;
14
+ v: number;
15
+ }
@@ -0,0 +1,6 @@
1
+ export type RuntimeErrorCode = "runtime_unsupported" | "runtime_start_failed" | "runtime_crashed";
2
+ export declare class RuntimeError extends Error {
3
+ readonly code: RuntimeErrorCode;
4
+ readonly cause?: unknown | undefined;
5
+ constructor(code: RuntimeErrorCode, message: string, cause?: unknown | undefined);
6
+ }
@@ -0,0 +1,10 @@
1
+ export class RuntimeError extends Error {
2
+ code;
3
+ cause;
4
+ constructor(code, message, cause) {
5
+ super(message);
6
+ this.code = code;
7
+ this.cause = cause;
8
+ this.name = "RuntimeError";
9
+ }
10
+ }
@@ -0,0 +1,24 @@
1
+ import { type CarrierSessionV2 } from "../v2/carrier.js";
2
+ import type { OperationOptionsV2, PathKind } from "../v2/contract.js";
3
+ export type WebSocketBinaryTransportV2 = Readonly<{
4
+ readBinary(options?: Readonly<{
5
+ signal?: AbortSignal;
6
+ timeoutMs?: number;
7
+ }>): Promise<Uint8Array>;
8
+ writeBinary(data: Uint8Array, options?: OperationOptionsV2): Promise<void>;
9
+ close(): void;
10
+ }>;
11
+ export type WebSocketResourcePolicyV2 = Readonly<{
12
+ maxConcurrentStreams?: number;
13
+ maxFrameBytes?: number;
14
+ preferredWriteBytes?: number;
15
+ maxStreamWriteQueueBytes?: number;
16
+ maxStreamReceiveBytes?: number;
17
+ maxSessionReceiveBytes?: number;
18
+ }>;
19
+ export declare function createWebSocketCarrierSessionV2(transport: WebSocketBinaryTransportV2, options: Readonly<{
20
+ path: PathKind;
21
+ client: boolean;
22
+ inboundBidirectionalStreamCapacity: number;
23
+ resourcePolicy?: WebSocketResourcePolicyV2;
24
+ }>): CarrierSessionV2;
@@ -0,0 +1,234 @@
1
+ import { YamuxSession } from "../yamux/session.js";
2
+ import { CarrierError } from "../v2/carrier.js";
3
+ export function createWebSocketCarrierSessionV2(transport, options) {
4
+ return new WebSocketYamuxCarrierSession(transport, options);
5
+ }
6
+ class WebSocketYamuxCarrierSession {
7
+ kind = "websocket";
8
+ path;
9
+ inboundBidirectionalStreamCapacity;
10
+ unreliableDatagrams = undefined;
11
+ incoming = new IncomingStreamQueue();
12
+ yamux;
13
+ termination = deferred();
14
+ terminalError;
15
+ closed = false;
16
+ constructor(transport, options) {
17
+ requireCapacity(options.inboundBidirectionalStreamCapacity);
18
+ this.path = options.path;
19
+ this.inboundBidirectionalStreamCapacity = options.inboundBidirectionalStreamCapacity;
20
+ const duplex = {
21
+ read: async () => await transport.readBinary(),
22
+ write: async (chunk) => await transport.writeBinary(chunk),
23
+ close: () => transport.close(),
24
+ };
25
+ const policy = options.resourcePolicy ?? {};
26
+ this.yamux = new YamuxSession(duplex, {
27
+ client: options.client,
28
+ limits: {
29
+ maxActiveStreams: Math.max(policy.maxConcurrentStreams ?? this.inboundBidirectionalStreamCapacity, this.inboundBidirectionalStreamCapacity),
30
+ maxInboundStreams: this.inboundBidirectionalStreamCapacity,
31
+ ...(policy.maxFrameBytes === undefined ? {} : { maxFrameBytes: policy.maxFrameBytes }),
32
+ ...(policy.preferredWriteBytes === undefined ? {} : { preferredOutboundFrameBytes: policy.preferredWriteBytes }),
33
+ ...(policy.maxStreamWriteQueueBytes === undefined ? {} : { maxStreamWriteQueueBytes: policy.maxStreamWriteQueueBytes }),
34
+ ...(policy.maxStreamReceiveBytes === undefined ? {} : { maxStreamReceiveBytes: policy.maxStreamReceiveBytes }),
35
+ ...(policy.maxSessionReceiveBytes === undefined ? {} : { maxSessionReceiveBytes: policy.maxSessionReceiveBytes }),
36
+ },
37
+ onIncomingStream: (stream) => this.incoming.push(new YamuxCarrierStreamAdapter(stream)),
38
+ onTerminal: (error) => {
39
+ const failure = error instanceof CarrierError
40
+ ? error
41
+ : new CarrierError("closed", "WebSocket carrier terminated", error);
42
+ this.closed = true;
43
+ this.terminalError = failure;
44
+ this.incoming.fail(failure);
45
+ this.termination.resolve();
46
+ },
47
+ });
48
+ }
49
+ async openStream(options = {}) {
50
+ this.assertOpen();
51
+ try {
52
+ return new YamuxCarrierStreamAdapter(await this.yamux.openStream(options));
53
+ }
54
+ catch (error) {
55
+ throw error instanceof CarrierError ? error : new CarrierError("closed", "WebSocket stream open failed", error);
56
+ }
57
+ }
58
+ async acceptStream(options = {}) {
59
+ this.assertOpen();
60
+ return await this.incoming.shift(options.signal);
61
+ }
62
+ async close() {
63
+ this.closeLocally();
64
+ }
65
+ abort() {
66
+ this.closeLocally();
67
+ }
68
+ async waitTermination() {
69
+ await this.termination.promise;
70
+ if (this.terminalError !== undefined)
71
+ throw this.terminalError;
72
+ }
73
+ assertOpen() {
74
+ if (this.terminalError !== undefined)
75
+ throw this.terminalError;
76
+ if (this.closed)
77
+ throw new CarrierError("closed", "WebSocket carrier is closed");
78
+ }
79
+ closeLocally() {
80
+ if (this.closed)
81
+ return;
82
+ this.closed = true;
83
+ const failure = new CarrierError("closed", "WebSocket carrier is closed");
84
+ this.incoming.fail(failure);
85
+ this.yamux.close();
86
+ this.termination.resolve();
87
+ }
88
+ }
89
+ class YamuxCarrierStreamAdapter {
90
+ stream;
91
+ constructor(stream) {
92
+ this.stream = stream;
93
+ }
94
+ async read(options = {}) {
95
+ try {
96
+ return await abortable(this.stream.read(), options.signal, () => this.stream.abort());
97
+ }
98
+ catch (error) {
99
+ throw error instanceof CarrierError ? error : new CarrierError("reset", "WebSocket stream read failed", error);
100
+ }
101
+ }
102
+ async write(data, options = {}) {
103
+ throwIfAborted(options.signal);
104
+ try {
105
+ await abortable(this.stream.write(data), options.signal, () => this.stream.abort());
106
+ }
107
+ catch (error) {
108
+ throw error instanceof CarrierError ? error : new CarrierError("reset", "WebSocket stream write failed", error);
109
+ }
110
+ return data.length;
111
+ }
112
+ async closeWrite() {
113
+ await this.stream.close();
114
+ }
115
+ async reset() {
116
+ await this.stream.reset();
117
+ }
118
+ async stopSending() {
119
+ throw new CarrierError("stop_sending_unavailable", "WebSocket/Yamux cannot stop only the receive side of a bidirectional stream");
120
+ }
121
+ abort(error) {
122
+ this.stream.abort(error);
123
+ }
124
+ }
125
+ class IncomingStreamQueue {
126
+ values = [];
127
+ waiters = new Set();
128
+ terminalError;
129
+ push(value) {
130
+ if (this.terminalError !== undefined) {
131
+ value.abort(this.terminalError);
132
+ return;
133
+ }
134
+ const waiter = this.waiters.values().next().value;
135
+ if (waiter === undefined)
136
+ this.values.push(value);
137
+ else {
138
+ this.waiters.delete(waiter);
139
+ waiter.deliver(value);
140
+ }
141
+ }
142
+ shift(signal) {
143
+ throwIfAborted(signal);
144
+ if (this.terminalError !== undefined)
145
+ return Promise.reject(this.terminalError);
146
+ const value = this.values.shift();
147
+ if (value !== undefined)
148
+ return Promise.resolve(value);
149
+ return new Promise((resolve, reject) => {
150
+ let settled = false;
151
+ const cleanup = () => {
152
+ this.waiters.delete(waiter);
153
+ signal?.removeEventListener("abort", abort);
154
+ };
155
+ const waiter = {
156
+ deliver: (stream) => {
157
+ if (settled)
158
+ return;
159
+ settled = true;
160
+ cleanup();
161
+ resolve(stream);
162
+ },
163
+ fail: (error) => {
164
+ if (settled)
165
+ return;
166
+ settled = true;
167
+ cleanup();
168
+ reject(error);
169
+ },
170
+ };
171
+ const abort = () => waiter.fail(new CarrierError("aborted", "carrier operation aborted"));
172
+ this.waiters.add(waiter);
173
+ signal?.addEventListener("abort", abort, { once: true });
174
+ if (signal?.aborted === true)
175
+ abort();
176
+ });
177
+ }
178
+ fail(error) {
179
+ if (this.terminalError !== undefined)
180
+ return;
181
+ this.terminalError = error;
182
+ for (const stream of this.values)
183
+ stream.abort(error);
184
+ this.values.length = 0;
185
+ for (const waiter of this.waiters)
186
+ waiter.fail(error);
187
+ this.waiters.clear();
188
+ }
189
+ }
190
+ function deferred() {
191
+ let resolve;
192
+ const promise = new Promise((resolvePromise) => { resolve = resolvePromise; });
193
+ return { promise, resolve };
194
+ }
195
+ function requireCapacity(value) {
196
+ if (!Number.isInteger(value) || value < 3 || value > 130) {
197
+ throw new RangeError("inboundBidirectionalStreamCapacity must be an integer from 3 to 130");
198
+ }
199
+ }
200
+ function throwIfAborted(signal) {
201
+ if (signal?.aborted === true)
202
+ throw new CarrierError("aborted", "carrier operation aborted");
203
+ }
204
+ async function abortable(promise, signal, onAbort) {
205
+ if (signal === undefined)
206
+ return await promise;
207
+ throwIfAborted(signal);
208
+ return await new Promise((resolve, reject) => {
209
+ let settled = false;
210
+ const cleanup = () => signal.removeEventListener("abort", abort);
211
+ const abort = () => {
212
+ if (settled)
213
+ return;
214
+ settled = true;
215
+ cleanup();
216
+ onAbort();
217
+ reject(new CarrierError("aborted", "carrier operation aborted"));
218
+ };
219
+ signal.addEventListener("abort", abort, { once: true });
220
+ void promise.then((value) => {
221
+ if (settled)
222
+ return;
223
+ settled = true;
224
+ cleanup();
225
+ resolve(value);
226
+ }, (error) => {
227
+ if (settled)
228
+ return;
229
+ settled = true;
230
+ cleanup();
231
+ reject(error);
232
+ });
233
+ });
234
+ }
@@ -0,0 +1,27 @@
1
+ import { type NativeCarrierSessionV2 } from "../v2/carrier.js";
2
+ import type { PathKind } from "../v2/contract.js";
3
+ export type WebTransportBidirectionalLikeV2 = Readonly<{
4
+ readable: ReadableStream<Uint8Array>;
5
+ writable: WritableStream<Uint8Array>;
6
+ }>;
7
+ export type WebTransportDatagramsLikeV2 = Readonly<{
8
+ readable: ReadableStream<Uint8Array>;
9
+ writable: WritableStream<Uint8Array>;
10
+ maxDatagramSize?: number;
11
+ }>;
12
+ export type WebTransportSessionLikeV2 = Readonly<{
13
+ closed: Promise<unknown>;
14
+ incomingBidirectionalStreams: ReadableStream<WebTransportBidirectionalLikeV2>;
15
+ datagrams: WebTransportDatagramsLikeV2;
16
+ createBidirectionalStream(): Promise<WebTransportBidirectionalLikeV2>;
17
+ close(info?: Readonly<{
18
+ closeCode: number;
19
+ reason: string;
20
+ }>): void;
21
+ }>;
22
+ export declare function adaptWebTransportCarrierSessionV2(native: WebTransportSessionLikeV2, options: Readonly<{
23
+ path: PathKind;
24
+ inboundBidirectionalStreamCapacity: number;
25
+ datagramMaxSize?: number;
26
+ }>): NativeCarrierSessionV2;
27
+ export declare function hasWebTransportConstructorSurfaceV2(value: unknown): boolean;