@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
@@ -1,92 +0,0 @@
1
- export type ReadBinaryOptions = Readonly<{
2
- /** Optional AbortSignal to cancel the pending operation. */
3
- signal?: AbortSignal;
4
- /** Optional timeout (milliseconds) for the pending operation. */
5
- timeoutMs?: number;
6
- }>;
7
- export type WriteBinaryOptions = Readonly<{
8
- /** Optional AbortSignal to cancel the pending operation. */
9
- signal?: AbortSignal;
10
- }>;
11
- export type BinaryTransport = {
12
- /** Reads the next binary frame from the underlying transport. */
13
- readBinary(opts?: ReadBinaryOptions): Promise<Uint8Array>;
14
- /** Writes a binary frame to the underlying transport. */
15
- writeBinary(frame: Uint8Array, opts?: WriteBinaryOptions): Promise<void>;
16
- /** Closes the transport and unblocks pending readers/writers. */
17
- close(): void;
18
- };
19
- export type SecureChannelOptions = Readonly<{
20
- /** Maximum encoded record size (header + ciphertext). */
21
- maxRecordBytes: number;
22
- /** Preferred plaintext bytes per outbound record. */
23
- outboundRecordChunkBytes?: number;
24
- /** Maximum queued inbound plaintext bytes before the channel is closed. */
25
- maxBufferedBytes?: number;
26
- /** Maximum queued outbound plaintext bytes (default 4 MiB; 0 uses default). */
27
- maxOutboundBufferedBytes?: number;
28
- }>;
29
- type Direction = 1 | 2;
30
- export declare class SecureChannel {
31
- private readonly transport;
32
- private readonly maxRecordBytes;
33
- private readonly outboundRecordChunkBytes;
34
- private readonly maxInboundBufferedBytes;
35
- private readonly maxOutboundBufferedBytes;
36
- private sendKey;
37
- private recvKey;
38
- private sendNoncePrefix;
39
- private recvNoncePrefix;
40
- private readonly rekeyBase;
41
- private readonly transcriptHash;
42
- private readonly sendDir;
43
- private readonly recvDir;
44
- private sendSeq;
45
- private recvSeq;
46
- private sendQueue;
47
- private sendQueueHead;
48
- private sendWaiters;
49
- private sendWaitersHead;
50
- private sendQueueBytes;
51
- private sendClosed;
52
- private sendErr;
53
- private recvQueue;
54
- private recvQueueHead;
55
- private recvQueueBytes;
56
- private recvWaiters;
57
- private readErr;
58
- private closed;
59
- constructor(args: {
60
- transport: BinaryTransport;
61
- maxRecordBytes: number;
62
- outboundRecordChunkBytes?: number;
63
- maxBufferedBytes?: number;
64
- maxOutboundBufferedBytes?: number;
65
- sendKey: Uint8Array;
66
- recvKey: Uint8Array;
67
- sendNoncePrefix: Uint8Array;
68
- recvNoncePrefix: Uint8Array;
69
- rekeyBase: Uint8Array;
70
- transcriptHash: Uint8Array;
71
- sendDir: Direction;
72
- recvDir: Direction;
73
- sendSeq?: bigint;
74
- recvSeq?: bigint;
75
- });
76
- write(plaintext: Uint8Array): Promise<void>;
77
- read(): Promise<Uint8Array>;
78
- close(): void;
79
- sendPing(): Promise<void>;
80
- rekeyNow(): Promise<void>;
81
- private enqueueSend;
82
- private nextSend;
83
- private dequeueSend;
84
- private shiftSendWaiter;
85
- private wakeSendWaiters;
86
- private rejectQueuedSenders;
87
- private failSend;
88
- private reserveSendSeq;
89
- private sendLoop;
90
- private readLoop;
91
- }
92
- export {};
@@ -1,328 +0,0 @@
1
- import { RECORD_FLAG_APP, RECORD_FLAG_PING, RECORD_FLAG_REKEY } from "./constants.js";
2
- import { decryptRecord, encryptRecord, maxPlaintextBytes } from "./record.js";
3
- import { deriveRekeyKey } from "./kdf.js";
4
- import { SDK_DEFAULTS } from "../defaults.js";
5
- const maxRecordSeq = (1n << 64n) - 1n;
6
- class RecordSeqExhaustedError extends Error {
7
- constructor() {
8
- super("record seq exhausted");
9
- this.name = "RecordSeqExhaustedError";
10
- }
11
- }
12
- // SecureChannel encrypts/decrypts records and buffers application payloads.
13
- export class SecureChannel {
14
- // Underlying transport for encrypted record frames.
15
- transport;
16
- // Maximum allowed bytes per record frame.
17
- maxRecordBytes;
18
- outboundRecordChunkBytes;
19
- maxInboundBufferedBytes;
20
- maxOutboundBufferedBytes;
21
- // Active encryption keys and nonce prefixes for the current epoch.
22
- sendKey;
23
- recvKey;
24
- sendNoncePrefix;
25
- recvNoncePrefix;
26
- // Rekey base secret derived from the handshake.
27
- rekeyBase;
28
- // Transcript hash binding rekeys to the handshake.
29
- transcriptHash;
30
- // Rekey direction identifiers for send/recv.
31
- sendDir;
32
- recvDir;
33
- // Monotonic record sequence numbers per direction.
34
- sendSeq;
35
- recvSeq;
36
- // Send queue and waiters for backpressure.
37
- sendQueue = [];
38
- sendQueueHead = 0;
39
- sendWaiters = [];
40
- sendWaitersHead = 0;
41
- sendQueueBytes = 0;
42
- sendClosed = false;
43
- sendErr = null;
44
- // Receive queue and waiters for plaintext delivery.
45
- recvQueue = [];
46
- recvQueueHead = 0;
47
- recvQueueBytes = 0;
48
- recvWaiters = [];
49
- readErr = null;
50
- closed = false;
51
- constructor(args) {
52
- this.transport = args.transport;
53
- this.maxRecordBytes = args.maxRecordBytes;
54
- const maxPlain = Math.max(1, maxPlaintextBytes(this.maxRecordBytes));
55
- this.outboundRecordChunkBytes = args.outboundRecordChunkBytes ?? Math.min(SDK_DEFAULTS.e2ee.outboundRecordChunkBytes, maxPlain);
56
- if (!Number.isSafeInteger(this.outboundRecordChunkBytes) || this.outboundRecordChunkBytes <= 0 || this.outboundRecordChunkBytes > maxPlain) {
57
- throw new RangeError("outboundRecordChunkBytes must be a positive integer within the record plaintext limit");
58
- }
59
- this.maxInboundBufferedBytes = Math.max(0, args.maxBufferedBytes ?? SDK_DEFAULTS.e2ee.maxInboundBufferedBytes);
60
- const maxOutboundBufferedBytes = args.maxOutboundBufferedBytes ?? SDK_DEFAULTS.e2ee.maxOutboundBufferedBytes;
61
- if (!Number.isSafeInteger(maxOutboundBufferedBytes) || maxOutboundBufferedBytes < 0) {
62
- throw new RangeError("maxOutboundBufferedBytes must be a non-negative safe integer");
63
- }
64
- this.maxOutboundBufferedBytes = maxOutboundBufferedBytes === 0 ? SDK_DEFAULTS.e2ee.maxOutboundBufferedBytes : maxOutboundBufferedBytes;
65
- this.sendKey = args.sendKey;
66
- this.recvKey = args.recvKey;
67
- this.sendNoncePrefix = args.sendNoncePrefix;
68
- this.recvNoncePrefix = args.recvNoncePrefix;
69
- this.rekeyBase = args.rekeyBase;
70
- this.transcriptHash = args.transcriptHash;
71
- this.sendDir = args.sendDir;
72
- this.recvDir = args.recvDir;
73
- this.sendSeq = args.sendSeq ?? 1n;
74
- this.recvSeq = args.recvSeq ?? 1n;
75
- void this.readLoop();
76
- void this.sendLoop();
77
- }
78
- // write splits payloads into record-sized chunks and queues them for send.
79
- async write(plaintext) {
80
- if (plaintext.length === 0)
81
- return;
82
- await this.enqueueSend("app", plaintext);
83
- }
84
- // read resolves with the next plaintext chunk or throws on errors/close.
85
- async read() {
86
- while (true) {
87
- if (this.recvQueueHead < this.recvQueue.length) {
88
- const b = this.recvQueue[this.recvQueueHead];
89
- this.recvQueueHead++;
90
- if (this.recvQueueHead === this.recvQueue.length) {
91
- this.recvQueue = [];
92
- this.recvQueueHead = 0;
93
- }
94
- else if (this.recvQueueHead > 1024 && this.recvQueueHead * 2 > this.recvQueue.length) {
95
- this.recvQueue.splice(0, this.recvQueueHead);
96
- this.recvQueueHead = 0;
97
- }
98
- this.recvQueueBytes -= b.length;
99
- return b;
100
- }
101
- if (this.readErr != null)
102
- throw this.readErr;
103
- if (this.closed)
104
- throw new Error("closed");
105
- await new Promise((resolve) => this.recvWaiters.push(resolve));
106
- }
107
- }
108
- // close shuts down the transport and rejects any pending senders.
109
- close() {
110
- if (this.closed)
111
- return;
112
- this.closed = true;
113
- this.sendClosed = true;
114
- this.rejectQueuedSenders(this.sendErr ?? new Error("closed"));
115
- this.wakeSendWaiters();
116
- this.transport.close();
117
- const ws = this.recvWaiters;
118
- this.recvWaiters = [];
119
- for (const w of ws)
120
- w();
121
- }
122
- // sendPing emits a keepalive record.
123
- async sendPing() {
124
- await this.enqueueSend("ping");
125
- }
126
- // rekeyNow emits a rekey record and advances the send key.
127
- async rekeyNow() {
128
- await this.enqueueSend("rekey");
129
- }
130
- enqueueSend(kind, payload) {
131
- if (this.sendErr != null)
132
- return Promise.reject(this.sendErr);
133
- if (this.closed || this.sendClosed)
134
- return Promise.reject(new Error("closed"));
135
- const bufferedBytes = payload?.byteLength ?? 0;
136
- if (this.sendQueueBytes + bufferedBytes > this.maxOutboundBufferedBytes) {
137
- return Promise.reject(new Error("secure channel outbound buffer exceeded"));
138
- }
139
- return new Promise((resolve, reject) => {
140
- if (this.sendErr != null) {
141
- reject(this.sendErr);
142
- return;
143
- }
144
- if (this.closed || this.sendClosed) {
145
- reject(new Error("closed"));
146
- return;
147
- }
148
- if (this.sendQueueBytes + bufferedBytes > this.maxOutboundBufferedBytes) {
149
- reject(new Error("secure channel outbound buffer exceeded"));
150
- return;
151
- }
152
- const retainedPayload = payload?.slice();
153
- const req = retainedPayload === undefined
154
- ? { kind, bufferedBytes, resolve, reject }
155
- : { kind, payload: retainedPayload, bufferedBytes, resolve, reject };
156
- this.sendQueueBytes += bufferedBytes;
157
- this.sendQueue.push(req);
158
- const w = this.shiftSendWaiter();
159
- if (w != null)
160
- w();
161
- });
162
- }
163
- async nextSend() {
164
- const immediate = this.dequeueSend();
165
- if (immediate != null)
166
- return immediate;
167
- if (this.closed || this.sendClosed)
168
- return null;
169
- return await new Promise((resolve) => {
170
- this.sendWaiters.push(() => resolve(this.dequeueSend()));
171
- });
172
- }
173
- dequeueSend() {
174
- if (this.sendQueueHead >= this.sendQueue.length)
175
- return null;
176
- const req = this.sendQueue[this.sendQueueHead];
177
- this.sendQueueHead++;
178
- if (this.sendQueueHead === this.sendQueue.length) {
179
- this.sendQueue = [];
180
- this.sendQueueHead = 0;
181
- }
182
- else if (this.sendQueueHead > 1024 && this.sendQueueHead * 2 > this.sendQueue.length) {
183
- this.sendQueue.splice(0, this.sendQueueHead);
184
- this.sendQueueHead = 0;
185
- }
186
- return req;
187
- }
188
- shiftSendWaiter() {
189
- if (this.sendWaitersHead >= this.sendWaiters.length)
190
- return undefined;
191
- const w = this.sendWaiters[this.sendWaitersHead];
192
- this.sendWaitersHead++;
193
- if (this.sendWaitersHead === this.sendWaiters.length) {
194
- this.sendWaiters = [];
195
- this.sendWaitersHead = 0;
196
- }
197
- else if (this.sendWaitersHead > 1024 && this.sendWaitersHead * 2 > this.sendWaiters.length) {
198
- this.sendWaiters.splice(0, this.sendWaitersHead);
199
- this.sendWaitersHead = 0;
200
- }
201
- return w;
202
- }
203
- wakeSendWaiters() {
204
- const ws = this.sendWaiters;
205
- const start = this.sendWaitersHead;
206
- this.sendWaiters = [];
207
- this.sendWaitersHead = 0;
208
- for (let i = start; i < ws.length; i++)
209
- ws[i]();
210
- }
211
- rejectQueuedSenders(err) {
212
- const queued = this.sendQueue;
213
- const start = this.sendQueueHead;
214
- this.sendQueue = [];
215
- this.sendQueueHead = 0;
216
- for (let i = start; i < queued.length; i++) {
217
- const req = queued[i];
218
- this.sendQueueBytes = Math.max(0, this.sendQueueBytes - req.bufferedBytes);
219
- req.reject(err);
220
- }
221
- }
222
- failSend(err) {
223
- if (this.sendErr != null)
224
- return;
225
- this.sendErr = err;
226
- this.rejectQueuedSenders(err);
227
- this.wakeSendWaiters();
228
- }
229
- reserveSendSeq() {
230
- if (this.sendSeq >= maxRecordSeq) {
231
- const err = new RecordSeqExhaustedError();
232
- this.failSend(err);
233
- throw err;
234
- }
235
- const seq = this.sendSeq;
236
- this.sendSeq++;
237
- return seq;
238
- }
239
- async sendLoop() {
240
- while (true) {
241
- const req = await this.nextSend();
242
- if (req == null)
243
- return;
244
- try {
245
- if (this.sendErr != null) {
246
- req.reject(this.sendErr);
247
- continue;
248
- }
249
- if (this.closed || this.sendClosed) {
250
- req.reject(new Error("closed"));
251
- continue;
252
- }
253
- let frame;
254
- if (req.kind === "app") {
255
- const payload = req.payload ?? new Uint8Array();
256
- for (let offset = 0; offset < payload.length; offset += this.outboundRecordChunkBytes) {
257
- const chunk = payload.subarray(offset, Math.min(payload.length, offset + this.outboundRecordChunkBytes));
258
- const seq = this.reserveSendSeq();
259
- frame = encryptRecord(this.sendKey, this.sendNoncePrefix, RECORD_FLAG_APP, seq, chunk, this.maxRecordBytes);
260
- await this.transport.writeBinary(frame);
261
- }
262
- req.resolve();
263
- continue;
264
- }
265
- else if (req.kind === "ping") {
266
- const seq = this.reserveSendSeq();
267
- frame = encryptRecord(this.sendKey, this.sendNoncePrefix, RECORD_FLAG_PING, seq, new Uint8Array(), this.maxRecordBytes);
268
- }
269
- else {
270
- const seq = this.reserveSendSeq();
271
- frame = encryptRecord(this.sendKey, this.sendNoncePrefix, RECORD_FLAG_REKEY, seq, new Uint8Array(), this.maxRecordBytes);
272
- // Update the send key after enqueuing the rekey frame.
273
- this.sendKey = deriveRekeyKey(this.rekeyBase, this.transcriptHash, seq, this.sendDir);
274
- }
275
- await this.transport.writeBinary(frame);
276
- req.resolve();
277
- }
278
- catch (e) {
279
- req.reject(e);
280
- this.failSend(e);
281
- this.close();
282
- return;
283
- }
284
- finally {
285
- this.sendQueueBytes = Math.max(0, this.sendQueueBytes - req.bufferedBytes);
286
- }
287
- }
288
- }
289
- async readLoop() {
290
- try {
291
- while (!this.closed) {
292
- const frame = await this.transport.readBinary();
293
- const { flags, seq, plaintext } = decryptRecord(this.recvKey, this.recvNoncePrefix, frame, this.recvSeq, this.maxRecordBytes);
294
- if (seq >= maxRecordSeq) {
295
- throw new RecordSeqExhaustedError();
296
- }
297
- this.recvSeq = seq + 1n;
298
- if (flags === RECORD_FLAG_APP) {
299
- if (this.maxInboundBufferedBytes > 0 && this.recvQueueBytes + plaintext.length > this.maxInboundBufferedBytes) {
300
- throw new Error("recv buffer exceeded");
301
- }
302
- this.recvQueue.push(plaintext);
303
- this.recvQueueBytes += plaintext.length;
304
- const ws = this.recvWaiters;
305
- this.recvWaiters = [];
306
- for (const w of ws)
307
- w();
308
- continue;
309
- }
310
- if (flags === RECORD_FLAG_PING)
311
- continue;
312
- if (flags === RECORD_FLAG_REKEY) {
313
- this.recvKey = deriveRekeyKey(this.rekeyBase, this.transcriptHash, seq, this.recvDir);
314
- continue;
315
- }
316
- throw new Error(`unknown record flag ${flags}`);
317
- }
318
- }
319
- catch (e) {
320
- this.readErr = e;
321
- const ws = this.recvWaiters;
322
- this.recvWaiters = [];
323
- for (const w of ws)
324
- w();
325
- this.close();
326
- }
327
- }
328
- }
@@ -1,23 +0,0 @@
1
- export type TranscriptInputs = Readonly<{
2
- /** Protocol version byte used in the transcript. */
3
- version: number;
4
- /** Numeric suite identifier (see e2ee suite). */
5
- suite: number;
6
- /** Role byte (client=1, server=2). */
7
- role: number;
8
- /** Client feature bitset. */
9
- clientFeatures: number;
10
- /** Server feature bitset. */
11
- serverFeatures: number;
12
- /** Channel identifier shared by both endpoints. */
13
- channelId: string;
14
- /** Client nonce (32 bytes). */
15
- nonceC: Uint8Array;
16
- /** Server nonce (32 bytes). */
17
- nonceS: Uint8Array;
18
- /** Client ephemeral public key bytes. */
19
- clientEphPub: Uint8Array;
20
- /** Server ephemeral public key bytes. */
21
- serverEphPub: Uint8Array;
22
- }>;
23
- export declare function transcriptHash(inputs: TranscriptInputs): Uint8Array;
@@ -1,31 +0,0 @@
1
- import { sha256 } from "@noble/hashes/sha256";
2
- import { concatBytes, u16be, u32be } from "../utils/bin.js";
3
- const te = new TextEncoder();
4
- // transcriptHash computes the SHA-256 hash of the handshake transcript.
5
- export function transcriptHash(inputs) {
6
- if (inputs.nonceC.length !== 32 || inputs.nonceS.length !== 32)
7
- throw new Error("nonce must be 32 bytes");
8
- const channelIdBytes = te.encode(inputs.channelId);
9
- if (channelIdBytes.length > 0xffff)
10
- throw new Error("channel_id too long");
11
- if (inputs.clientEphPub.length > 0xffff || inputs.serverEphPub.length > 0xffff)
12
- throw new Error("pub too long");
13
- const prefix = te.encode("flowersec-e2ee-v1");
14
- const body = concatBytes([
15
- prefix,
16
- new Uint8Array([inputs.version & 0xff]),
17
- u16be(inputs.suite),
18
- new Uint8Array([inputs.role & 0xff]),
19
- u32be(inputs.clientFeatures >>> 0),
20
- u32be(inputs.serverFeatures >>> 0),
21
- u16be(channelIdBytes.length),
22
- channelIdBytes,
23
- inputs.nonceC,
24
- inputs.nonceS,
25
- u16be(inputs.clientEphPub.length),
26
- inputs.clientEphPub,
27
- u16be(inputs.serverEphPub.length),
28
- inputs.serverEphPub
29
- ]);
30
- return sha256(body);
31
- }
@@ -1,84 +0,0 @@
1
- import { type TransportSecurityPolicy } from "../client-connect/transportSecurity.js";
2
- import { serverHandshake, ServerHandshakeCache, type Suite } from "../e2ee/handshake.js";
3
- import { type YamuxLimits } from "../yamux/session.js";
4
- import type { YamuxStream } from "../yamux/stream.js";
5
- import { type RpcRouter, type RpcServerOptions } from "../rpc/server.js";
6
- import { type WebSocketLike, type WebSocketLimits } from "../ws-client/binaryTransport.js";
7
- export type { Suite } from "../e2ee/handshake.js";
8
- export type EndpointPath = "direct" | "tunnel";
9
- export type DirectHandshakeInit = Readonly<{
10
- channelId: string;
11
- version: number;
12
- suite: Suite;
13
- clientFeatures: number;
14
- }>;
15
- export type DirectHandshakeCredential = Readonly<{
16
- psk: Uint8Array | string;
17
- initExpireAtUnixS: number;
18
- commitAuthenticated?: () => void | Promise<void>;
19
- }>;
20
- export type DirectCredentialResolver = (init: DirectHandshakeInit) => DirectHandshakeCredential | Promise<DirectHandshakeCredential>;
21
- export type EndpointOptions = Readonly<{
22
- signal?: AbortSignal;
23
- handshakeTimeoutMs?: number;
24
- handshakeClockSkewMs?: number;
25
- serverFeatures?: number;
26
- maxHandshakePayload?: number;
27
- maxRecordBytes?: number;
28
- maxBufferedBytes?: number;
29
- maxOutboundBufferedBytes?: number;
30
- outboundRecordChunkBytes?: number;
31
- webSocketLimits?: Partial<WebSocketLimits>;
32
- yamuxLimits?: Partial<YamuxLimits>;
33
- handshakeCache?: ServerHandshakeCache;
34
- }>;
35
- export type DirectAcceptOptions = EndpointOptions & Readonly<{
36
- secureTransport?: boolean;
37
- transportSecurityPolicy?: TransportSecurityPolicy;
38
- }>;
39
- export type TunnelEndpointOptions = EndpointOptions & Readonly<{
40
- origin: string;
41
- connectTimeoutMs?: number;
42
- endpointInstanceId?: string;
43
- wsFactory: (url: string, origin: string) => WebSocketLike;
44
- transportSecurityPolicy?: TransportSecurityPolicy;
45
- }>;
46
- export type EndpointStream = Readonly<{
47
- kind: string;
48
- stream: YamuxStream;
49
- }>;
50
- export declare class Session {
51
- private readonly secure;
52
- private readonly mux;
53
- readonly path: EndpointPath;
54
- readonly endpointInstanceId: string | undefined;
55
- private readonly streams;
56
- private readonly waiters;
57
- private terminalError;
58
- private constructor();
59
- static create(path: EndpointPath, secure: Awaited<ReturnType<typeof serverHandshake>>, options?: Readonly<{
60
- yamuxLimits?: Partial<YamuxLimits>;
61
- endpointInstanceId?: string;
62
- }>): Session;
63
- openStream(kind: string, options?: Readonly<{
64
- signal?: AbortSignal;
65
- }>): Promise<YamuxStream>;
66
- acceptStream(options?: Readonly<{
67
- signal?: AbortSignal;
68
- }>): Promise<EndpointStream>;
69
- serveRPC(router: RpcRouter, options?: RpcServerOptions & Readonly<{
70
- signal?: AbortSignal;
71
- }>): Promise<void>;
72
- probeLiveness(timeoutMs?: 10000): Promise<number>;
73
- rekey(): Promise<void>;
74
- close(): void;
75
- private pushStream;
76
- private acceptRawStream;
77
- private fail;
78
- }
79
- export declare function acceptDirect(websocket: WebSocketLike, handshake: Readonly<{
80
- channelId: string;
81
- suite: Suite;
82
- }> & DirectHandshakeCredential, options?: DirectAcceptOptions): Promise<Session>;
83
- export declare function acceptDirectResolved(websocket: WebSocketLike, resolver: DirectCredentialResolver, options?: DirectAcceptOptions): Promise<Session>;
84
- export declare function connectTunnel(grantInput: unknown, options: TunnelEndpointOptions): Promise<Session>;