@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,210 +1,116 @@
1
- function dedupeStrings(values) {
2
- const out = [];
3
- const seen = new Set();
4
- for (const value of values) {
5
- const normalized = String(value ?? "").trim();
6
- if (normalized === "" || seen.has(normalized))
7
- continue;
8
- seen.add(normalized);
9
- out.push(normalized);
10
- }
11
- return out;
12
- }
13
- function resolveWindow(raw, label) {
14
- const candidate = (raw ?? globalThis.window);
15
- if (candidate == null) {
16
- throw new Error(`${label} is not available in this environment`);
17
- }
18
- return candidate;
19
- }
20
- function getServiceWorker(targetWindow) {
21
- return targetWindow.navigator?.serviceWorker ?? null;
22
- }
23
- function parseRepairAttemptFromHref(href, queryKey) {
1
+ function serviceWorkerContainer(target) {
24
2
  try {
25
- const url = new URL(href);
26
- const raw = String(url.searchParams.get(queryKey) ?? "").trim();
27
- const n = raw === "" ? 0 : Number(raw);
28
- if (!Number.isFinite(n) || n < 0)
29
- return 0;
30
- return Math.min(9, Math.floor(n));
3
+ return target.navigator?.serviceWorker;
31
4
  }
32
5
  catch {
33
- return 0;
6
+ return undefined;
34
7
  }
35
8
  }
36
- function buildHrefWithRepairAttempt(href, queryKey, attempt) {
37
- const url = new URL(href);
38
- url.searchParams.set(queryKey, String(Math.max(0, Math.floor(attempt))));
39
- return url.toString();
40
- }
41
- function isServiceWorkerScriptPathSuffix(raw, suffix) {
42
- const script = String(raw ?? "").trim();
43
- const wanted = String(suffix ?? "").trim();
44
- if (script === "" || wanted === "")
9
+ function scriptMatches(scriptURL, suffix) {
10
+ if (scriptURL === undefined || scriptURL === "")
45
11
  return false;
46
12
  try {
47
- return new URL(script).pathname.endsWith(wanted);
13
+ return new URL(scriptURL).pathname.endsWith(suffix);
48
14
  }
49
15
  catch {
50
- return script.endsWith(wanted);
16
+ return scriptURL.endsWith(suffix);
51
17
  }
52
18
  }
53
- async function waitForControllerSuffix(targetWindow, suffix, timeoutMs) {
54
- const sw = getServiceWorker(targetWindow);
55
- if (sw == null)
56
- return false;
57
- const isMatch = () => isServiceWorkerScriptPathSuffix(String(sw.controller?.scriptURL ?? ""), suffix);
58
- if (isMatch())
59
- return true;
60
- const ms = Math.max(0, Math.floor(timeoutMs));
61
- return await new Promise((resolve) => {
62
- let done = false;
63
- let timer = null;
64
- const finish = (ok) => {
65
- if (done)
66
- return;
67
- done = true;
68
- if (timer != null)
69
- targetWindow.clearTimeout(timer);
70
- sw.removeEventListener?.("controllerchange", onChange);
71
- resolve(ok);
72
- };
73
- const onChange = () => {
74
- if (isMatch())
75
- finish(true);
76
- };
77
- sw.addEventListener?.("controllerchange", onChange);
78
- if (isMatch()) {
79
- finish(true);
80
- return;
81
- }
82
- if (ms > 0) {
83
- timer = targetWindow.setTimeout(() => finish(isMatch()), ms);
84
- }
85
- else {
86
- finish(isMatch());
87
- }
88
- });
89
- }
90
- async function uninstallConflictingServiceWorkers(targetWindow, conflicts) {
91
- if (conflicts?.uninstallOnMismatch === false)
92
- return;
93
- const sw = getServiceWorker(targetWindow);
94
- if (sw == null || typeof sw.getRegistrations !== "function")
19
+ async function removeConflicts(container, expected, policy) {
20
+ if (policy?.uninstallOnMismatch === false || typeof container.getRegistrations !== "function")
95
21
  return;
96
- const keepSuffixes = dedupeStrings(conflicts?.keepScriptPathSuffixes ?? []);
97
- const regs = await sw.getRegistrations();
98
- for (const reg of regs) {
99
- const script = String(reg?.active?.scriptURL ?? reg?.waiting?.scriptURL ?? reg?.installing?.scriptURL ?? "").trim();
100
- if (script === "")
101
- continue;
102
- let shouldKeep = false;
103
- for (const suffix of keepSuffixes) {
104
- if (isServiceWorkerScriptPathSuffix(script, suffix)) {
105
- shouldKeep = true;
106
- break;
107
- }
108
- }
109
- if (shouldKeep)
110
- continue;
111
- try {
112
- await reg.unregister?.();
113
- }
114
- catch {
115
- // Best effort cleanup.
22
+ const keep = [expected, ...(policy?.keepScriptPathSuffixes ?? [])];
23
+ for (const registration of await container.getRegistrations()) {
24
+ const script = registration.active?.scriptURL ?? registration.waiting?.scriptURL ?? registration.installing?.scriptURL;
25
+ if (script !== undefined && !keep.some((suffix) => scriptMatches(script, suffix))) {
26
+ await registration.unregister().catch(() => false);
116
27
  }
117
28
  }
118
29
  }
119
- function triggerRepairNavigation(navigationWindow, repair, attempt) {
120
- const queryKey = String(repair?.queryKey ?? "_flowersec_sw_repair").trim() || "_flowersec_sw_repair";
121
- const maxAttempts = Math.max(0, Math.floor(repair?.maxAttempts ?? 2));
122
- const strategy = repair?.strategy ?? "replace";
123
- const hrefAttempt = parseRepairAttemptFromHref(navigationWindow.location.href, queryKey);
124
- const effectiveAttempt = Math.max(attempt, hrefAttempt);
125
- if (effectiveAttempt >= maxAttempts)
126
- return false;
127
- if (strategy === "reload") {
128
- navigationWindow.location.reload();
129
- return true;
30
+ function repair(target, options) {
31
+ const key = options?.queryKey?.trim() || "_flowersec_sw_repair";
32
+ const maxAttempts = options?.maxAttempts ?? 2;
33
+ let url;
34
+ try {
35
+ url = new URL(target.location.href);
130
36
  }
131
- const next = buildHrefWithRepairAttempt(navigationWindow.location.href, queryKey, effectiveAttempt + 1);
132
- navigationWindow.location.replace(next);
133
- return true;
134
- }
135
- export function createServiceWorkerControllerGuard(opts) {
136
- const targetWindow = resolveWindow(opts.targetWindow, "targetWindow");
137
- const navigationWindow = resolveWindow(opts.navigationWindow ?? opts.targetWindow, "navigationWindow");
138
- const expectedScriptPathSuffix = String(opts.expectedScriptPathSuffix ?? "").trim();
139
- if (expectedScriptPathSuffix === "") {
140
- throw new Error("expectedScriptPathSuffix must be non-empty");
37
+ catch {
38
+ throw new Error("service worker controller repair URL is unavailable");
39
+ }
40
+ const current = Number(url.searchParams.get(key) ?? "0");
41
+ const attempt = Number.isSafeInteger(current) && current >= 0 ? current : 0;
42
+ if (attempt >= maxAttempts)
43
+ throw new Error("service worker controller mismatch persists");
44
+ if (options?.strategy === "reload") {
45
+ target.location.reload();
141
46
  }
142
- const controllerTimeoutMs = Math.max(0, Math.floor(opts.repair?.controllerTimeoutMs ?? 8_000));
143
- const monitorEnabled = opts.monitor?.enabled ?? true;
144
- const monitorThrottleMs = Math.max(0, Math.floor(opts.monitor?.throttleMs ?? 10_000));
47
+ else {
48
+ url.searchParams.set(key, String(attempt + 1));
49
+ target.location.replace(url.toString());
50
+ }
51
+ throw new Error("service worker controller repair navigation started");
52
+ }
53
+ export function createServiceWorkerControllerGuard(options) {
54
+ const target = options.targetWindow ?? globalThis.window;
55
+ const navigation = options.navigationWindow ?? target;
56
+ const expected = options.expectedScriptPathSuffix.trim();
57
+ if (expected === "")
58
+ throw new TypeError("expected service worker script suffix is required");
59
+ const container = serviceWorkerContainer(target);
145
60
  let disposed = false;
146
- let monitorHandler = null;
147
- let lastMonitorRepairAt = 0;
148
- let repairAttempts = 0;
61
+ let lastRepairAt = 0;
149
62
  const handleMismatch = async (stage) => {
150
- const actualScriptURL = String(getServiceWorker(targetWindow)?.controller?.scriptURL ?? "").trim();
151
- const ctx = {
152
- expectedScriptPathSuffix,
153
- actualScriptURL,
154
- stage,
155
- };
156
- const action = opts.onControllerMismatch?.(ctx);
157
- if (action === "ignore")
158
- return "ignored";
159
- await uninstallConflictingServiceWorkers(targetWindow, opts.conflicts);
160
- const repaired = triggerRepairNavigation(navigationWindow, opts.repair, repairAttempts);
161
- if (repaired)
162
- repairAttempts += 1;
163
- return repaired ? "repaired" : "skipped";
63
+ if (disposed || container === undefined)
64
+ throw new Error("service worker controller is unavailable");
65
+ const actual = container.controller?.scriptURL ?? "";
66
+ const context = { expectedScriptPathSuffix: expected, actualScriptURL: actual, stage };
67
+ if (options.onControllerMismatch?.(context) === "ignore")
68
+ return;
69
+ await removeConflicts(container, expected, options.conflicts);
70
+ repair(navigation, options.repair);
164
71
  };
165
- const attachMonitor = () => {
166
- if (!monitorEnabled || monitorHandler != null)
72
+ const onControllerChange = () => {
73
+ if (disposed || options.monitor?.enabled === false || scriptMatches(container?.controller?.scriptURL, expected))
167
74
  return;
168
- const currentSW = getServiceWorker(targetWindow);
169
- if (currentSW == null)
75
+ const now = Date.now();
76
+ const throttle = options.monitor?.throttleMs ?? 10_000;
77
+ if (now - lastRepairAt < throttle)
170
78
  return;
171
- monitorHandler = () => {
172
- const actualScriptURL = String(currentSW.controller?.scriptURL ?? "").trim();
173
- if (isServiceWorkerScriptPathSuffix(actualScriptURL, expectedScriptPathSuffix))
174
- return;
175
- const now = Date.now();
176
- if (monitorThrottleMs > 0 && now - lastMonitorRepairAt <= monitorThrottleMs)
177
- return;
178
- lastMonitorRepairAt = now;
179
- void handleMismatch("monitor");
180
- };
181
- currentSW.addEventListener?.("controllerchange", monitorHandler);
79
+ lastRepairAt = now;
80
+ void handleMismatch("monitor").catch(() => undefined);
182
81
  };
183
- return {
82
+ container?.addEventListener("controllerchange", onControllerChange);
83
+ return Object.freeze({
184
84
  ensure: async () => {
185
85
  if (disposed)
186
- throw new Error("controller guard is already disposed");
187
- if (getServiceWorker(targetWindow) == null) {
188
- throw new Error("service worker is not available in the target window");
189
- }
190
- const ok = await waitForControllerSuffix(targetWindow, expectedScriptPathSuffix, controllerTimeoutMs);
191
- if (!ok) {
192
- const outcome = await handleMismatch("ensure");
193
- if (outcome !== "ignored") {
194
- throw new Error("Proxy Service Worker is installed but not controlling the target window");
195
- }
86
+ throw new Error("service worker controller guard is disposed");
87
+ if (container === undefined)
88
+ throw new Error("service worker controller is unavailable");
89
+ if (scriptMatches(container.controller?.scriptURL, expected))
196
90
  return;
197
- }
198
- attachMonitor();
91
+ const timeoutMs = options.repair?.controllerTimeoutMs ?? 8_000;
92
+ const matched = await new Promise((resolve) => {
93
+ const onChange = () => {
94
+ if (!scriptMatches(container.controller?.scriptURL, expected))
95
+ return;
96
+ cleanup();
97
+ resolve(true);
98
+ };
99
+ const cleanup = () => {
100
+ clearTimeout(timer);
101
+ container.removeEventListener("controllerchange", onChange);
102
+ };
103
+ container.addEventListener("controllerchange", onChange);
104
+ const timer = setTimeout(() => { cleanup(); resolve(scriptMatches(container.controller?.scriptURL, expected)); }, timeoutMs);
105
+ });
106
+ if (!matched)
107
+ await handleMismatch("ensure");
199
108
  },
200
109
  dispose: () => {
201
110
  if (disposed)
202
111
  return;
203
112
  disposed = true;
204
- if (monitorHandler != null) {
205
- getServiceWorker(targetWindow)?.removeEventListener?.("controllerchange", monitorHandler);
206
- }
207
- monitorHandler = null;
113
+ container?.removeEventListener("controllerchange", onControllerChange);
208
114
  },
209
- };
115
+ });
210
116
  }
@@ -1 +1,3 @@
1
- export declare function disableUpstreamServiceWorkerRegister(): void;
1
+ export declare function disableUpstreamServiceWorkerRegister(): Readonly<{
2
+ restore(): void;
3
+ }>;
@@ -1,23 +1,25 @@
1
- // disableUpstreamServiceWorkerRegister blocks upstream apps from registering their own Service Worker.
2
- //
3
- // This is required for runtime-mode proxying where a proxy SW must control the app scope.
4
1
  export function disableUpstreamServiceWorkerRegister() {
2
+ const serviceWorker = globalThis.navigator?.serviceWorker;
3
+ if (serviceWorker === undefined || typeof serviceWorker.register !== "function")
4
+ return Object.freeze({ restore: () => undefined });
5
+ const original = serviceWorker.register.bind(serviceWorker);
6
+ const replacement = async () => {
7
+ throw new Error("upstream service worker registration is disabled by the Flowersec proxy runtime");
8
+ };
5
9
  try {
6
- const sw = globalThis.navigator?.serviceWorker;
7
- if (!sw || typeof sw.register !== "function")
8
- return;
9
- const blocked = () => {
10
- throw new Error("service worker register is disabled by flowersec-proxy runtime");
11
- };
12
- // Best-effort. Some environments may not allow overriding the property.
13
- try {
14
- sw.register = blocked;
15
- }
16
- catch {
17
- // Ignore.
18
- }
10
+ Object.defineProperty(serviceWorker, "register", { configurable: true, value: replacement });
19
11
  }
20
12
  catch {
21
- // Ignore.
13
+ return Object.freeze({ restore: () => undefined });
22
14
  }
15
+ return Object.freeze({
16
+ restore: () => {
17
+ try {
18
+ Object.defineProperty(serviceWorker, "register", { configurable: true, value: original });
19
+ }
20
+ catch {
21
+ // Best effort restoration during page teardown.
22
+ }
23
+ },
24
+ });
23
25
  }
@@ -1,16 +1,17 @@
1
- export * from "./constants.js";
2
- export * from "./types.js";
3
- export * from "./cookieJar.js";
4
- export type { ProxyPresetInput, ProxyPresetLimits, ProxyPresetManifest, ResolvedProxyPreset } from "./preset.js";
5
- export { DEFAULT_PROXY_PRESET_MANIFEST, assertProxyPresetManifest, resolveProxyPreset } from "./preset.js";
6
- export * from "./runtime.js";
7
- export * from "./serviceWorker.js";
1
+ export { PROXY_RUNTIME_SCOPE, assertProxyRuntimeScope } from "./scope.js";
2
+ export { createProxyRuntime, ensureServiceWorkerRuntimeRegistered } from "./runtime.js";
3
+ export type { EnsureServiceWorkerRuntimeRegisteredOptions } from "./runtime.js";
4
+ export { createProxyServiceWorkerScript } from "./serviceWorker.js";
5
+ export type { ProxyServiceWorkerInjectHTMLOptions, ProxyServiceWorkerPassthroughOptions, ProxyServiceWorkerScriptOptions, } from "./serviceWorker.js";
8
6
  export { registerServiceWorkerAndEnsureControl } from "./registerServiceWorker.js";
9
- export * from "./integration.js";
10
- export * from "./controllerGuard.js";
11
- export * from "./bootstrap.js";
12
- export * from "./runtimeScope.js";
13
- export * from "./controllerWindow.js";
14
- export * from "./appWindow.js";
15
- export * from "./wsPatch.js";
16
- export * from "./disableUpstreamServiceWorkerRegister.js";
7
+ export type { RegisterServiceWorkerOptions } from "./registerServiceWorker.js";
8
+ export { createServiceWorkerControllerGuard } from "./controllerGuard.js";
9
+ export type { ServiceWorkerControllerGuardConflictPolicy, ServiceWorkerControllerGuardHandle, ServiceWorkerControllerGuardMismatchContext, ServiceWorkerControllerGuardMonitorOptions, ServiceWorkerControllerGuardOptions, ServiceWorkerControllerGuardRepairOptions, } from "./controllerGuard.js";
10
+ export { registerProxyAppWindow, registerProxyAppWindowWithServiceWorkerControl, registerProxyControllerWindow, } from "./windowBridge.js";
11
+ export type { ProxyAppServiceWorkerControlOptions, ProxyAppWindowHandle, ProxyControllerWindowHandle, RegisterProxyAppWindowOptions, RegisterProxyAppWindowWithServiceWorkerControlOptions, RegisterProxyControllerWindowOptions, } from "./windowBridge.js";
12
+ export { installWebSocketPatch } from "./wsPatch.js";
13
+ export type { WebSocketPatchOptions } from "./wsPatch.js";
14
+ export { disableUpstreamServiceWorkerRegister } from "./disableUpstreamServiceWorkerRegister.js";
15
+ export { connectProxyBrowser, connectProxyControllerBrowser, } from "./integration.js";
16
+ export type { ProxyBrowserConnectOptions, ProxyBrowserHandle, ProxyControllerBrowserConnectOptions, ProxyControllerBrowserHandle, } from "./integration.js";
17
+ export type { ProxyFetchRequest, ProxyHeader, ProxyRuntime, ProxyRuntimeControllerBridgeScope, ProxyRuntimeLimits, ProxyRuntimeOptions, ProxyRuntimePathPolicy, ProxyRuntimeScopeLimits, ProxyRuntimeScope, ProxyRuntimeServiceWorkerScope, } from "./types.js";
@@ -1,15 +1,9 @@
1
- export * from "./constants.js";
2
- export * from "./types.js";
3
- export * from "./cookieJar.js";
4
- export { DEFAULT_PROXY_PRESET_MANIFEST, assertProxyPresetManifest, resolveProxyPreset } from "./preset.js";
5
- export * from "./runtime.js";
6
- export * from "./serviceWorker.js";
1
+ export { PROXY_RUNTIME_SCOPE, assertProxyRuntimeScope } from "./scope.js";
2
+ export { createProxyRuntime, ensureServiceWorkerRuntimeRegistered } from "./runtime.js";
3
+ export { createProxyServiceWorkerScript } from "./serviceWorker.js";
7
4
  export { registerServiceWorkerAndEnsureControl } from "./registerServiceWorker.js";
8
- export * from "./integration.js";
9
- export * from "./controllerGuard.js";
10
- export * from "./bootstrap.js";
11
- export * from "./runtimeScope.js";
12
- export * from "./controllerWindow.js";
13
- export * from "./appWindow.js";
14
- export * from "./wsPatch.js";
15
- export * from "./disableUpstreamServiceWorkerRegister.js";
5
+ export { createServiceWorkerControllerGuard } from "./controllerGuard.js";
6
+ export { registerProxyAppWindow, registerProxyAppWindowWithServiceWorkerControl, registerProxyControllerWindow, } from "./windowBridge.js";
7
+ export { installWebSocketPatch } from "./wsPatch.js";
8
+ export { disableUpstreamServiceWorkerRegister } from "./disableUpstreamServiceWorkerRegister.js";
9
+ export { connectProxyBrowser, connectProxyControllerBrowser, } from "./integration.js";
@@ -1,77 +1,29 @@
1
- import type { Client } from "../client.js";
2
- import { type ProxyPresetInput, type ResolvedProxyPreset } from "./preset.js";
3
- import { type ProxyRuntime, type ProxyRuntimePathPolicy } from "./runtime.js";
4
- import { type ProxyServiceWorkerScriptOptions } from "./serviceWorker.js";
5
- export type ProxyIntegrationMonitorOptions = Readonly<{
6
- enabled?: boolean;
7
- throttleMs?: number;
8
- }>;
9
- export type ProxyIntegrationRepairOptions = Readonly<{
10
- queryKey?: string;
11
- maxAttempts?: number;
12
- controllerTimeoutMs?: number;
13
- strategy?: "replace" | "reload";
14
- }>;
15
- export type ProxyServiceWorkerConflictPolicy = Readonly<{
16
- keepScriptPathSuffixes?: readonly string[];
17
- uninstallOnMismatch?: boolean;
18
- }>;
19
- export type ProxyIntegrationServiceWorkerOptions = Readonly<{
20
- scriptUrl: string;
21
- scope?: string;
22
- expectedScriptPathSuffix?: string;
23
- repair?: ProxyIntegrationRepairOptions;
24
- monitor?: ProxyIntegrationMonitorOptions;
25
- conflicts?: ProxyServiceWorkerConflictPolicy;
26
- }>;
27
- export type RegisterProxyIntegrationOptions = Readonly<{
28
- client: Client;
29
- preset?: ProxyPresetInput;
30
- runtimeGlobalKey?: string;
31
- runtime?: Readonly<{
32
- maxJsonFrameBytes?: number;
33
- maxChunkBytes?: number;
34
- maxBodyBytes?: number;
35
- maxWsFrameBytes?: number;
36
- maxWsBufferedAmountBytes?: number;
37
- maxConcurrentHttpStreams?: number;
38
- maxQueuedHttpRequests?: number;
39
- maxQueuedHttpBodyBytes?: number;
40
- timeoutMs?: number;
41
- pathPolicy?: ProxyRuntimePathPolicy;
42
- externalOrigin?: string;
43
- runtimeRegistrationToken?: string;
1
+ import { type SessionOptions } from "../browser/connectSession.js";
2
+ import type { ArtifactLease } from "../public/artifactLease.js";
3
+ import type { Session } from "../public/contract.js";
4
+ import type { ProxyRuntime, ProxyRuntimeOptions } from "./types.js";
5
+ import { type ProxyControllerWindowHandle, type RegisterProxyControllerWindowOptions } from "./windowBridge.js";
6
+ export type ProxyBrowserConnectOptions = Readonly<{
7
+ connect?: SessionOptions;
8
+ runtime?: Omit<ProxyRuntimeOptions, "session">;
9
+ serviceWorker?: Readonly<{
10
+ scriptUrl: string;
11
+ scope?: string;
12
+ repairQueryKey?: string;
13
+ maxRepairAttempts?: number;
14
+ controllerTimeoutMs?: number;
44
15
  }>;
45
- serviceWorker: ProxyIntegrationServiceWorkerOptions;
46
- plugins?: readonly ProxyIntegrationPlugin[];
47
16
  }>;
48
- export type ProxyIntegrationContext = Readonly<{
17
+ export type ProxyBrowserHandle = Readonly<{
18
+ session: Session;
49
19
  runtime: ProxyRuntime;
50
- options: RegisterProxyIntegrationOptions;
51
- preset: ResolvedProxyPreset;
20
+ dispose(): Promise<void>;
52
21
  }>;
53
- export type ControllerMismatchContext = Readonly<{
54
- expectedScriptPathSuffix: string;
55
- actualScriptURL: string;
56
- stage: "register" | "monitor";
57
- }>;
58
- export type ProxyIntegrationPlugin = Readonly<{
59
- name: string;
60
- mutateOptions?: (opts: RegisterProxyIntegrationOptions) => RegisterProxyIntegrationOptions;
61
- extendServiceWorkerScriptOptions?: (opts: ProxyServiceWorkerScriptOptions) => ProxyServiceWorkerScriptOptions;
62
- serviceWorkerConflictPolicy?: ProxyServiceWorkerConflictPolicy;
63
- forwardFetchMessageTypes?: readonly string[];
64
- onRegistered?: (ctx: ProxyIntegrationContext) => void | Promise<void>;
65
- onControllerMismatch?: (ctx: ControllerMismatchContext) => "repair" | "ignore" | void;
66
- onDisposed?: () => void | Promise<void>;
67
- }>;
68
- export type ProxyIntegrationHandle = Readonly<{
69
- runtime: ProxyRuntime;
70
- dispose: () => Promise<void>;
22
+ export declare function connectProxyBrowser(lease: ArtifactLease, options?: ProxyBrowserConnectOptions): Promise<ProxyBrowserHandle>;
23
+ export type ProxyControllerBrowserConnectOptions = ProxyBrowserConnectOptions & Readonly<{
24
+ controller: Omit<RegisterProxyControllerWindowOptions, "runtime">;
71
25
  }>;
72
- export type CreateProxyIntegrationServiceWorkerScriptOptions = Readonly<{
73
- baseOptions?: ProxyServiceWorkerScriptOptions;
74
- plugins?: readonly ProxyIntegrationPlugin[];
26
+ export type ProxyControllerBrowserHandle = ProxyBrowserHandle & Readonly<{
27
+ controller: ProxyControllerWindowHandle;
75
28
  }>;
76
- export declare function createProxyIntegrationServiceWorkerScript(opts?: CreateProxyIntegrationServiceWorkerScriptOptions): string;
77
- export declare function registerProxyIntegration(input: RegisterProxyIntegrationOptions): Promise<ProxyIntegrationHandle>;
29
+ export declare function connectProxyControllerBrowser(lease: ArtifactLease, options: ProxyControllerBrowserConnectOptions): Promise<ProxyControllerBrowserHandle>;