ftown 0.20.9 → 0.24.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 (154) hide show
  1. package/dist/attention-events.d.ts +1 -1
  2. package/dist/attention-store.d.ts +3 -0
  3. package/dist/attention-store.js +25 -1
  4. package/dist/attention-store.js.map +1 -1
  5. package/dist/centrifugo-client.d.ts +28 -11
  6. package/dist/centrifugo-client.js +84 -70
  7. package/dist/centrifugo-client.js.map +1 -1
  8. package/dist/cli-client.d.ts +11 -1
  9. package/dist/cli-client.js +23 -3
  10. package/dist/cli-client.js.map +1 -1
  11. package/dist/command-rpc.d.ts +2 -0
  12. package/dist/command-rpc.js +59 -17
  13. package/dist/command-rpc.js.map +1 -1
  14. package/dist/identity-reset.d.ts +4 -1
  15. package/dist/identity-reset.js +54 -6
  16. package/dist/identity-reset.js.map +1 -1
  17. package/dist/index.js +194 -288
  18. package/dist/index.js.map +1 -1
  19. package/dist/ledger-pairing-client.d.ts +28 -0
  20. package/dist/ledger-pairing-client.js +154 -0
  21. package/dist/ledger-pairing-client.js.map +1 -0
  22. package/dist/ledger-relay.d.ts +159 -0
  23. package/dist/ledger-relay.js +595 -0
  24. package/dist/ledger-relay.js.map +1 -0
  25. package/dist/ledger-reoffer.d.ts +56 -0
  26. package/dist/ledger-reoffer.js +210 -0
  27. package/dist/ledger-reoffer.js.map +1 -0
  28. package/dist/ledger-startup.d.ts +176 -0
  29. package/dist/ledger-startup.js +233 -0
  30. package/dist/ledger-startup.js.map +1 -0
  31. package/dist/local-api-server.d.ts +3 -0
  32. package/dist/local-api-server.js +68 -6
  33. package/dist/local-api-server.js.map +1 -1
  34. package/dist/mail-delivery.d.ts +26 -3
  35. package/dist/mail-delivery.js +65 -7
  36. package/dist/mail-delivery.js.map +1 -1
  37. package/dist/preview-protocol.d.ts +19 -3
  38. package/dist/preview-protocol.js +14 -0
  39. package/dist/preview-protocol.js.map +1 -1
  40. package/dist/relay-token.d.ts +45 -0
  41. package/dist/relay-token.js +138 -0
  42. package/dist/relay-token.js.map +1 -0
  43. package/dist/revocation-gating.d.ts +0 -13
  44. package/dist/revocation-gating.js +0 -16
  45. package/dist/revocation-gating.js.map +1 -1
  46. package/dist/security/bridge/identity.d.ts +2 -47
  47. package/dist/security/bridge/identity.js +3 -3
  48. package/dist/security/bridge/identity.js.map +1 -1
  49. package/dist/security/bridge/ledger-identity.d.ts +48 -0
  50. package/dist/security/bridge/ledger-identity.js +342 -0
  51. package/dist/security/bridge/ledger-identity.js.map +1 -0
  52. package/dist/security/bridge/ledger-rpc.d.ts +34 -0
  53. package/dist/security/bridge/ledger-rpc.js +58 -0
  54. package/dist/security/bridge/ledger-rpc.js.map +1 -0
  55. package/dist/security/bridge/ledger-store.d.ts +153 -0
  56. package/dist/security/bridge/ledger-store.js +825 -0
  57. package/dist/security/bridge/ledger-store.js.map +1 -0
  58. package/dist/security/bridge/metadata.d.ts +2 -2
  59. package/dist/security/bridge/permissions.js +4 -3
  60. package/dist/security/bridge/permissions.js.map +1 -1
  61. package/dist/security/bridge/policy.d.ts +43 -23
  62. package/dist/security/bridge/policy.js +214 -146
  63. package/dist/security/bridge/policy.js.map +1 -1
  64. package/dist/security/bridge/security.d.ts +212 -33
  65. package/dist/security/bridge/security.js +437 -165
  66. package/dist/security/bridge/security.js.map +1 -1
  67. package/dist/security/crypto.js +1 -1
  68. package/dist/security/crypto.js.map +1 -1
  69. package/dist/security/ledger/announce.d.ts +32 -0
  70. package/dist/security/ledger/announce.js +101 -0
  71. package/dist/security/ledger/announce.js.map +1 -0
  72. package/dist/security/ledger/channels.d.ts +5 -0
  73. package/dist/security/ledger/channels.js +21 -0
  74. package/dist/security/ledger/channels.js.map +1 -0
  75. package/dist/security/ledger/ledger.d.ts +154 -0
  76. package/dist/security/ledger/ledger.js +878 -0
  77. package/dist/security/ledger/ledger.js.map +1 -0
  78. package/dist/security/ledger/pairing.d.ts +81 -0
  79. package/dist/security/ledger/pairing.js +414 -0
  80. package/dist/security/ledger/pairing.js.map +1 -0
  81. package/dist/security/ledger/proof.d.ts +36 -0
  82. package/dist/security/ledger/proof.js +193 -0
  83. package/dist/security/ledger/proof.js.map +1 -0
  84. package/dist/security/ledger/protocol.d.ts +113 -0
  85. package/dist/security/ledger/protocol.js +16 -0
  86. package/dist/security/ledger/protocol.js.map +1 -0
  87. package/dist/security/ledger/testing.d.ts +27 -0
  88. package/dist/security/ledger/testing.js +70 -0
  89. package/dist/security/ledger/testing.js.map +1 -0
  90. package/dist/security/ledger/webauthn.d.ts +12 -0
  91. package/dist/security/ledger/webauthn.js +147 -0
  92. package/dist/security/ledger/webauthn.js.map +1 -0
  93. package/dist/security/protocol.d.ts +5 -10
  94. package/dist/security-cli.d.ts +5 -0
  95. package/dist/security-cli.js +28 -16
  96. package/dist/security-cli.js.map +1 -1
  97. package/dist/session-controller.d.ts +9 -3
  98. package/dist/session-controller.js +120 -20
  99. package/dist/session-controller.js.map +1 -1
  100. package/dist/session-inbox-protocol.d.ts +2 -0
  101. package/dist/session-preview.d.ts +20 -5
  102. package/dist/session-preview.js +185 -37
  103. package/dist/session-preview.js.map +1 -1
  104. package/dist/session-store.js +19 -1
  105. package/dist/session-store.js.map +1 -1
  106. package/dist/sessions-commands.js +41 -7
  107. package/dist/sessions-commands.js.map +1 -1
  108. package/dist/token-provider.d.ts +39 -0
  109. package/dist/token-provider.js +101 -0
  110. package/dist/token-provider.js.map +1 -0
  111. package/dist/types.d.ts +1 -1
  112. package/opencode-plugin/ftown.js +15 -2
  113. package/package.json +2 -2
  114. package/skills/ftown/SKILL.md +18 -7
  115. package/skills/ftown/references/sessions.md +38 -12
  116. package/dist/bridge-auth.d.ts +0 -31
  117. package/dist/bridge-auth.js +0 -70
  118. package/dist/bridge-auth.js.map +0 -1
  119. package/dist/pairing-client.d.ts +0 -62
  120. package/dist/pairing-client.js +0 -469
  121. package/dist/pairing-client.js.map +0 -1
  122. package/dist/rotating-token-refresher.d.ts +0 -42
  123. package/dist/rotating-token-refresher.js +0 -91
  124. package/dist/rotating-token-refresher.js.map +0 -1
  125. package/dist/security/account-crypto.d.ts +0 -33
  126. package/dist/security/account-crypto.js +0 -649
  127. package/dist/security/account-crypto.js.map +0 -1
  128. package/dist/security/account-protocol.d.ts +0 -228
  129. package/dist/security/account-protocol.js +0 -2
  130. package/dist/security/account-protocol.js.map +0 -1
  131. package/dist/security/bridge/account-client.d.ts +0 -7
  132. package/dist/security/bridge/account-client.js +0 -101
  133. package/dist/security/bridge/account-client.js.map +0 -1
  134. package/dist/security/bridge/account-state.d.ts +0 -105
  135. package/dist/security/bridge/account-state.js +0 -79
  136. package/dist/security/bridge/account-state.js.map +0 -1
  137. package/dist/security/bridge/pending-approval.d.ts +0 -21
  138. package/dist/security/bridge/pending-approval.js +0 -80
  139. package/dist/security/bridge/pending-approval.js.map +0 -1
  140. package/dist/security/bridge/pending-enrollment.d.ts +0 -33
  141. package/dist/security/bridge/pending-enrollment.js +0 -177
  142. package/dist/security/bridge/pending-enrollment.js.map +0 -1
  143. package/dist/security/bridge/revocation.d.ts +0 -14
  144. package/dist/security/bridge/revocation.js +0 -40
  145. package/dist/security/bridge/revocation.js.map +0 -1
  146. package/dist/security/pending-approval-crypto.d.ts +0 -29
  147. package/dist/security/pending-approval-crypto.js +0 -716
  148. package/dist/security/pending-approval-crypto.js.map +0 -1
  149. package/dist/security/pending-approval-protocol.d.ts +0 -329
  150. package/dist/security/pending-approval-protocol.js +0 -2
  151. package/dist/security/pending-approval-protocol.js.map +0 -1
  152. package/dist/security/security-nudge.d.ts +0 -31
  153. package/dist/security/security-nudge.js +0 -98
  154. package/dist/security/security-nudge.js.map +0 -1
@@ -0,0 +1,595 @@
1
+ /*
2
+ * Account-mode wiring between the bridge's ledger replica (via BridgeSecurityService), the ftown server and the relay:
3
+ * - the server's public ledger endpoints, bounded (createLedgerServer);
4
+ * - the relay token by proof (createRelayTokenFetcher) behind the cooldown/caching provider, with the ledger hooks (createAccountRelay);
5
+ * - the relay's ledger messages and (re)subscriptions, spaced so a relay publisher cannot force back-to-back reads and verifies;
6
+ * - the re-offer of this bridge's chain when a server read shows the server behind it (ledger-reoffer.ts): relay input only ever leads to
7
+ * a paced read, never to a POST, and a refused relay token (plain 401) only to a read that may then re-offer;
8
+ * - signed head announcements (security/ledger/announce.ts, CONTRACT §10/§13): this bridge announces its head after the ledger channel
9
+ * subscribes and after every adopt (at most one per HEAD_ANNOUNCE_SPACING_MS, latest head, best effort); a received one is verified against
10
+ * the trusted checkpoint and, when its head is unknown here, only queues the same paced server read as a ledger notice;
11
+ * - the last relay URL the server named (security/relay-url.json), for an offline start.
12
+ * Nothing here decides trust: every ledger goes to security.offerLedgerResult / refreshLedger / readServerLedger, which verify it.
13
+ */
14
+ import { randomUUID } from 'node:crypto';
15
+ import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
16
+ import { join } from 'node:path';
17
+ import { UnauthorizedError } from 'centrifuge';
18
+ import { signHeadAnnouncement } from './security/ledger/announce.js';
19
+ import { createLedgerReoffer } from './ledger-reoffer.js';
20
+ import { createRelayTokenFetcher } from './relay-token.js';
21
+ import { createTokenProvider } from './token-provider.js';
22
+ export const LEDGER_REQUEST_TIMEOUT_MS = 15_000;
23
+ /** A ledger is at most 2 MiB (LEDGER_LIMITS.maxBytes); its JSON envelope stays well under this. */
24
+ const MAX_LEDGER_RESPONSE_BYTES = 3 * 1024 * 1024;
25
+ const MAX_RELAY_URL_LENGTH = 2048;
26
+ /** Relay-triggered ledger work (offers and refreshes) runs at least this far apart... */
27
+ export const RELAY_LEDGER_MIN_SPACING_MS = 1_000;
28
+ /** ...doubling up to this while it keeps changing nothing; an adopted ledger resets it. */
29
+ export const RELAY_LEDGER_MAX_SPACING_MS = 60_000;
30
+ /** Refreshes pulled by requests from endpoints the replica does not list run at most this often (single-flight, trailing). */
31
+ export const UNKNOWN_ENDPOINT_REFRESH_SPACING_MS = 2_000;
32
+ /** This bridge announces its head at most this often; a pending announcement is replaced by the latest head, never queued. */
33
+ export const HEAD_ANNOUNCE_SPACING_MS = 5_000;
34
+ /** A failed announcement (best effort) is logged at most this often. */
35
+ export const HEAD_ANNOUNCE_WARN_SPACING_MS = 60_000;
36
+ /** Retry-After as ms from `now`: delta-seconds or an HTTP date; null when absent or unreadable. */
37
+ export function parseRetryAfter(value, now = Date.now()) {
38
+ if (value === null)
39
+ return null;
40
+ const text = value.trim();
41
+ if (/^\d{1,9}$/.test(text))
42
+ return Number(text) * 1000;
43
+ // An HTTP date starts with the day name ("Sun, 06 Nov 1994 08:49:37 GMT"); anything else is not a date here.
44
+ if (!/^[A-Za-z]{3}/.test(text))
45
+ return null;
46
+ const at = Date.parse(text);
47
+ return Number.isNaN(at) ? null : Math.max(0, at - now);
48
+ }
49
+ /** An HTTP answer that is not a success, with its status. */
50
+ export class HttpStatusError extends Error {
51
+ status;
52
+ constructor(message, status) {
53
+ super(message);
54
+ this.status = status;
55
+ this.name = 'HttpStatusError';
56
+ }
57
+ }
58
+ const messageOf = (error) => error instanceof Error ? error.message : String(error);
59
+ const apiBase = (apiUrl) => apiUrl.replace(/\/+$/, '');
60
+ /** The HTTP status an error reports: its `status`, else a `(NNN)` in its message (relay-token errors), else null. */
61
+ export function httpStatusOf(error) {
62
+ if (typeof error === 'object' && error !== null && 'status' in error && typeof error.status === 'number')
63
+ return error.status;
64
+ const match = /\((\d{3})\)/.exec(messageOf(error));
65
+ return match ? Number(match[1]) : null;
66
+ }
67
+ /** A refusal (401/403, or an UnauthorizedError) rather than a temporary failure. */
68
+ export function isRefusal(error) {
69
+ if (error instanceof UnauthorizedError)
70
+ return true;
71
+ const status = httpStatusOf(error);
72
+ return status === 401 || status === 403;
73
+ }
74
+ function timeoutError(error, timeoutMs) {
75
+ return error instanceof Error && (error.name === 'TimeoutError' || error.name === 'AbortError')
76
+ ? new Error(`Ledger request timed out after ${timeoutMs}ms`) : error;
77
+ }
78
+ export function createLedgerServer(input) {
79
+ const fetchImpl = input.fetchImpl ?? fetch;
80
+ const timeoutMs = input.timeoutMs ?? LEDGER_REQUEST_TIMEOUT_MS;
81
+ const maxBytes = input.maxBytes ?? MAX_LEDGER_RESPONSE_BYTES;
82
+ const base = apiBase(input.apiUrl);
83
+ return {
84
+ async fetchLedger(accountId) {
85
+ let text;
86
+ let status;
87
+ try {
88
+ const response = await fetchImpl(`${base}/api/account/ledger?accountId=${encodeURIComponent(accountId)}`, {
89
+ method: 'GET', headers: { accept: 'application/json' }, cache: 'no-store', signal: AbortSignal.timeout(timeoutMs),
90
+ });
91
+ status = response.status;
92
+ if (Number(response.headers.get('content-length')) > maxBytes) {
93
+ await response.body?.cancel().catch(() => undefined);
94
+ throw new Error('ledger_response_too_large');
95
+ }
96
+ text = await response.text();
97
+ }
98
+ catch (error) {
99
+ throw timeoutError(error, timeoutMs);
100
+ }
101
+ if (Buffer.byteLength(text, 'utf8') > maxBytes)
102
+ throw new Error('ledger_response_too_large');
103
+ if (status !== 200)
104
+ throw new HttpStatusError(`Ledger read failed (${status})`, status);
105
+ let body;
106
+ try {
107
+ body = JSON.parse(text);
108
+ }
109
+ catch {
110
+ throw new Error('Ledger response malformed');
111
+ }
112
+ const ledger = typeof body === 'object' && body !== null && !Array.isArray(body) ? body.ledger : undefined;
113
+ if (typeof ledger !== 'object' || ledger === null)
114
+ throw new Error('Ledger response malformed');
115
+ return ledger;
116
+ },
117
+ async postLedger(ledger, expectHead) {
118
+ let status;
119
+ let retryAfterMs;
120
+ let text = null;
121
+ try {
122
+ const response = await fetchImpl(`${base}/api/account/ledger`, {
123
+ method: 'POST', headers: { 'Content-Type': 'application/json', accept: 'application/json' }, cache: 'no-store',
124
+ body: JSON.stringify({ ledger, expectHead }), signal: AbortSignal.timeout(timeoutMs),
125
+ });
126
+ status = response.status;
127
+ retryAfterMs = parseRetryAfter(response.headers.get('retry-after'));
128
+ if (Number(response.headers.get('content-length')) > maxBytes)
129
+ await response.body?.cancel().catch(() => undefined);
130
+ else
131
+ text = await response.text();
132
+ }
133
+ catch (error) {
134
+ throw timeoutError(error, timeoutMs);
135
+ }
136
+ let body = null;
137
+ if (text !== null && Buffer.byteLength(text, 'utf8') <= maxBytes) {
138
+ try {
139
+ body = JSON.parse(text);
140
+ }
141
+ catch {
142
+ body = null;
143
+ }
144
+ }
145
+ return { status, body, retryAfterMs };
146
+ },
147
+ };
148
+ }
149
+ /**
150
+ * Publishes ONLY this bridge's own ledger endpoint in the account's endpoint directory (PUT /api/security/endpoints), authenticated
151
+ * with its relay token. Throws HttpStatusError when the server does not accept it.
152
+ */
153
+ export async function registerBridgeEndpoint(input) {
154
+ const fetchImpl = input.fetchImpl ?? fetch;
155
+ const timeoutMs = input.timeoutMs ?? LEDGER_REQUEST_TIMEOUT_MS;
156
+ let status;
157
+ try {
158
+ const response = await fetchImpl(`${apiBase(input.apiUrl)}/api/security/endpoints`, {
159
+ method: 'PUT', headers: { Authorization: `Bearer ${input.token}`, 'Content-Type': 'application/json' },
160
+ body: JSON.stringify({ endpoint: input.endpoint, bridgeId: input.bridgeId, label: input.label, protocolVersion: 1 }),
161
+ signal: AbortSignal.timeout(timeoutMs),
162
+ });
163
+ await response.body?.cancel().catch(() => undefined);
164
+ status = response.status;
165
+ }
166
+ catch (error) {
167
+ throw timeoutError(error, timeoutMs);
168
+ }
169
+ if (status < 200 || status >= 300)
170
+ throw new HttpStatusError(`Endpoint directory registration failed (${status})`, status);
171
+ }
172
+ /** The line printed when the startup relay token is refused (exit 1). */
173
+ export function relayTokenFailureMessage(error, apiUrl) {
174
+ if (error instanceof UnauthorizedError) {
175
+ return "[Bridge] The ftown server did not accept this computer's key. If it was removed from your account, run `ftown start --new-identity` to pair it again.";
176
+ }
177
+ if (isRefusal(error))
178
+ return `[Bridge] The ftown server at ${apiBase(apiUrl)} refused this computer (${messageOf(error)}).`;
179
+ return `[Bridge] Could not get a relay token from ${apiBase(apiUrl)} (${messageOf(error)}). Check the connection and run \`ftown start\` again.`;
180
+ }
181
+ export const MISSING_RELAY_URL_MESSAGE = '[Bridge] The ftown server did not name its relay (centrifugoUrl) in the relay-token response. '
182
+ + 'Update the server, or set FTOWN_CENTRIFUGO_URL to its wss:// URL.';
183
+ function isLoopbackHost(hostname) {
184
+ return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]' || hostname.endsWith('.localhost');
185
+ }
186
+ /**
187
+ * A Centrifugo URL the bridge may connect to, or null: wss://, or ws:// only to a loopback host or when the API itself is plain
188
+ * http (the operator already chose an insecure transport). The token rides this connection.
189
+ */
190
+ export function parseRelayUrl(value, apiUrl) {
191
+ if (typeof value !== 'string' || value.length === 0 || value.length > MAX_RELAY_URL_LENGTH)
192
+ return null;
193
+ let url;
194
+ try {
195
+ url = new URL(value);
196
+ }
197
+ catch {
198
+ return null;
199
+ }
200
+ if (url.username || url.password)
201
+ return null;
202
+ if (url.protocol === 'wss:')
203
+ return url.href;
204
+ if (url.protocol !== 'ws:')
205
+ return null;
206
+ let insecureApi = false;
207
+ try {
208
+ insecureApi = new URL(apiUrl).protocol === 'http:';
209
+ }
210
+ catch { /* treated as secure */ }
211
+ return insecureApi || isLoopbackHost(url.hostname) ? url.href : null;
212
+ }
213
+ const relayUrlFile = (dataDir) => join(dataDir, 'security', 'relay-url.json');
214
+ /** The last relay URL the server named (`security/relay-url.json`), if it is still acceptable for this API; else null. */
215
+ export function readSavedRelayUrl(dataDir, apiUrl) {
216
+ try {
217
+ const value = JSON.parse(readFileSync(relayUrlFile(dataDir), 'utf8'));
218
+ if (typeof value !== 'object' || value === null || value.version !== 1)
219
+ return null;
220
+ return parseRelayUrl(value.url, apiUrl);
221
+ }
222
+ catch {
223
+ return null;
224
+ }
225
+ }
226
+ /** Atomically saves the relay URL (mode 0600). The identity reset deletes it. */
227
+ export function saveRelayUrl(dataDir, url) {
228
+ const file = relayUrlFile(dataDir);
229
+ const temporary = `${file}.${randomUUID()}.tmp`;
230
+ mkdirSync(join(dataDir, 'security'), { recursive: true, mode: 0o700 });
231
+ try {
232
+ writeFileSync(temporary, JSON.stringify({ version: 1, url }), { mode: 0o600, flag: 'wx' });
233
+ renameSync(temporary, file);
234
+ }
235
+ catch (error) {
236
+ rmSync(temporary, { force: true });
237
+ throw error;
238
+ }
239
+ }
240
+ /** Subscribes `listener` when the security service offers onApprovalRequired; false when it does not (nothing subscribed). */
241
+ export function subscribeApprovalRequired(security, listener) {
242
+ const signal = security.onApprovalRequired;
243
+ if (typeof signal !== 'function')
244
+ return false;
245
+ signal.call(security, listener);
246
+ return true;
247
+ }
248
+ const defaultSchedule = (run, ms) => {
249
+ const timer = setTimeout(run, ms);
250
+ timer.unref();
251
+ return () => clearTimeout(timer);
252
+ };
253
+ export function createAccountRelay(deps) {
254
+ const log = deps.log ?? ((line) => console.warn(line));
255
+ const monotonic = deps.now ?? (() => performance.now());
256
+ const schedule = deps.schedule ?? defaultSchedule;
257
+ const baseFetch = deps.fetchImpl ?? fetch;
258
+ const relayTokenUrl = `${apiBase(deps.apiUrl)}/api/auth/relay-token`;
259
+ const override = deps.relayUrlOverride === undefined || deps.relayUrlOverride === '' ? null : parseRelayUrl(deps.relayUrlOverride, deps.apiUrl);
260
+ if (deps.relayUrlOverride && override === null)
261
+ log('[Bridge] Ignoring FTOWN_CENTRIFUGO_URL: it must be a wss:// URL (ws:// only for a local relay).');
262
+ let learnedRelayUrl = null;
263
+ const savedRelayUrl = deps.savedRelayUrl ?? null;
264
+ const head = () => deps.security.ledgerStatus().head;
265
+ /** The relay connection was refused (terminal for centrifuge-js) and has not been reconnected since. */
266
+ let relayRefused = false;
267
+ let stopped = false;
268
+ // Our chain goes back to the server only after a fresh read shows the server holding a strict prefix of it, with that head as expectHead.
269
+ const reoffer = createLedgerReoffer({
270
+ read: () => deps.security.readServerLedger(),
271
+ local: async () => {
272
+ // Like a browser, a bridge that is not an active member of its own chain sends nothing.
273
+ if (deps.security.ledgerStatus().own !== 'active')
274
+ return null;
275
+ const state = await deps.store.read();
276
+ return state === null ? null : { ledger: state.ledger, head: state.checkpoint.head };
277
+ },
278
+ post: (ledger, expectHead) => deps.server.postLedger(ledger, expectHead),
279
+ offer: ledger => deps.security.offerLedgerResult(ledger, 'server'),
280
+ now: monotonic, random: deps.random ?? Math.random, schedule, log,
281
+ });
282
+ /** After any server read: the server is behind us, so re-offer (paced; it reads again first). */
283
+ const afterServerRead = () => {
284
+ if (!stopped && deps.security.ledgerStatus().serverBehind)
285
+ reoffer.noteServerBehind();
286
+ };
287
+ const reconnectIfRefused = () => {
288
+ if (!relayRefused || stopped)
289
+ return;
290
+ relayRefused = false;
291
+ try {
292
+ deps.reconnect?.();
293
+ }
294
+ catch (error) {
295
+ log(`[Bridge] Relay reconnect failed: ${messageOf(error)}`);
296
+ }
297
+ };
298
+ // Reads `centrifugoUrl` from a successful relay-token response without consuming the body the fetcher reads.
299
+ const fetchImpl = async (input, init) => {
300
+ const response = await baseFetch(input, init);
301
+ if (response.ok && String(input) === relayTokenUrl) {
302
+ try {
303
+ const body = JSON.parse(await response.clone().text());
304
+ const named = typeof body === 'object' && body !== null ? parseRelayUrl(body.centrifugoUrl, deps.apiUrl) : null;
305
+ if (named !== null) {
306
+ const previous = learnedRelayUrl ?? savedRelayUrl;
307
+ learnedRelayUrl = named;
308
+ if (named !== previous) {
309
+ try {
310
+ deps.onRelayUrl?.(named);
311
+ }
312
+ catch (error) {
313
+ log(`[Bridge] Could not save the relay URL: ${messageOf(error)}`);
314
+ }
315
+ }
316
+ }
317
+ }
318
+ catch { /* the fetcher reports a malformed response */ }
319
+ }
320
+ return response;
321
+ };
322
+ const fetcher = createRelayTokenFetcher({
323
+ apiUrl: deps.apiUrl,
324
+ accountId: () => deps.accountId,
325
+ bridgeId: deps.bridgeId,
326
+ authPrivateKey: deps.authPrivateKey,
327
+ head,
328
+ // A newer server ledger rides the token response. An invalid one is only logged: the token is still returned. One the server holds
329
+ // as a strict prefix of ours (a rolled-back server) starts the re-offer.
330
+ onLedger: async (ledger) => {
331
+ try {
332
+ const outcome = await deps.security.offerLedgerResult(ledger, 'server');
333
+ if (outcome.decision === 'reject')
334
+ log('[Bridge] Ignored an account ledger from the relay-token response.');
335
+ if (outcome.relation === 'behind')
336
+ reoffer.noteServerBehind();
337
+ }
338
+ catch (error) {
339
+ log(`[Bridge] Account ledger from the relay-token response failed: ${messageOf(error)}`);
340
+ }
341
+ },
342
+ // No chain in the answer: the server's head is the one we sent (or the one it names). Behind -> re-offer; unknown -> read it.
343
+ onServerHead: server => {
344
+ const relation = deps.security.noteServerHead(server);
345
+ if (relation === 'behind')
346
+ reoffer.noteServerBehind();
347
+ else if (relation === 'unknown')
348
+ submit({ kind: 'refresh', head: null });
349
+ },
350
+ // Evidence of a revoked key: the replica's append-only rule decides. Only a chain that is AHEAD of ours (or an owner-chosen history)
351
+ // and revokes this bridge triggers the reset (security's onBridgeRevoked); a diverged one is refused and recorded, never evidence.
352
+ onRevoked: async (ledger) => {
353
+ try {
354
+ await deps.security.offerLedgerResult(ledger, 'server');
355
+ }
356
+ catch (error) {
357
+ log(`[Bridge] Revocation evidence failed: ${messageOf(error)}`);
358
+ }
359
+ },
360
+ // A plain 401: the server may lack our records (a rolled-back server missing our add_bridge). Nothing is posted blindly: the
361
+ // re-offer reads the server first and posts our chain (expectHead, never creating an account) only if the server is behind it.
362
+ // The token is retried once only when the server took our chain.
363
+ onUnauthorized: async () => (await reoffer.check()) === 'posted',
364
+ hostname: deps.hostname,
365
+ localPort: deps.localPort,
366
+ fetchImpl,
367
+ timeoutMs: LEDGER_REQUEST_TIMEOUT_MS,
368
+ });
369
+ const tokens = createTokenProvider({
370
+ fetchToken: async () => {
371
+ const token = await fetcher();
372
+ // Every relay-token answer is a server contact: it renews the offline grace of the account devices.
373
+ deps.security.noteServerContact();
374
+ // The key is accepted again (e.g. the server learned our add_bridge): a refused relay connection may come back.
375
+ reconnectIfRefused();
376
+ return token;
377
+ },
378
+ now: monotonic,
379
+ random: deps.random,
380
+ head,
381
+ });
382
+ // Relay-triggered ledger work: at most one at a time, at least RELAY_LEDGER_MIN_SPACING_MS apart, only the latest kept.
383
+ let pending = null;
384
+ let running = false;
385
+ let cancelTimer = null;
386
+ let readyAt = 0;
387
+ let idleRuns = 0;
388
+ let lastRunEndedAt = Number.NEGATIVE_INFINITY;
389
+ const run = async (work) => {
390
+ const before = head();
391
+ try {
392
+ if (work.kind === 'offer') {
393
+ const outcome = await deps.security.offerLedgerResult(work.ledger, 'relay');
394
+ // A relayed chain that is a prefix of ours hints that the server may be behind: read the server (paced). A relay message is never
395
+ // proof of the server's state, so it never leads to a POST by itself.
396
+ if (outcome.relation === 'behind' && pending === null)
397
+ pending = { kind: 'refresh', head: null };
398
+ if (outcome.decision !== 'adopt')
399
+ return 'idle';
400
+ }
401
+ else {
402
+ if (work.head !== null && work.head === before)
403
+ return 'skipped';
404
+ await deps.security.refreshLedger();
405
+ afterServerRead();
406
+ if (head() === before)
407
+ return 'idle';
408
+ }
409
+ }
410
+ catch (error) {
411
+ log(`[Bridge] Relay ledger update failed: ${messageOf(error)}`);
412
+ return 'idle';
413
+ }
414
+ reconnectIfRefused();
415
+ return 'adopt';
416
+ };
417
+ const pump = () => {
418
+ if (stopped || running || cancelTimer !== null || pending === null)
419
+ return;
420
+ const wait = readyAt - monotonic();
421
+ if (wait > 0) {
422
+ cancelTimer = schedule(() => { cancelTimer = null; pump(); }, wait);
423
+ return;
424
+ }
425
+ const work = pending;
426
+ pending = null;
427
+ running = true;
428
+ void run(work).then(outcome => {
429
+ if (outcome === 'skipped')
430
+ return;
431
+ lastRunEndedAt = monotonic();
432
+ if (outcome === 'adopt')
433
+ idleRuns = 0;
434
+ const spacing = outcome === 'adopt' ? RELAY_LEDGER_MIN_SPACING_MS
435
+ : Math.min(RELAY_LEDGER_MIN_SPACING_MS * 2 ** idleRuns++, RELAY_LEDGER_MAX_SPACING_MS);
436
+ readyAt = monotonic() + spacing;
437
+ }).finally(() => { running = false; pump(); });
438
+ };
439
+ const submit = (work) => {
440
+ if (stopped)
441
+ return;
442
+ // Leading edge: the first work after a quiet second runs at once with a fresh backoff; only a burst is spaced and backed off.
443
+ if (!running && pending === null && cancelTimer === null && monotonic() - lastRunEndedAt >= RELAY_LEDGER_MIN_SPACING_MS) {
444
+ idleRuns = 0;
445
+ readyAt = 0;
446
+ }
447
+ pending = work;
448
+ pump();
449
+ };
450
+ // Refreshes pulled by unknown endpoints: their own limit, independent of the relay spacing.
451
+ let unknownInFlight = false;
452
+ let unknownQueued = false;
453
+ let unknownCancel = null;
454
+ let unknownReadyAt = Number.NEGATIVE_INFINITY;
455
+ const refreshForUnknown = () => {
456
+ if (stopped)
457
+ return;
458
+ if (unknownInFlight) {
459
+ unknownQueued = true;
460
+ return;
461
+ }
462
+ if (unknownCancel !== null)
463
+ return;
464
+ const wait = unknownReadyAt - monotonic();
465
+ if (wait > 0) {
466
+ unknownCancel = schedule(() => { unknownCancel = null; refreshForUnknown(); }, wait);
467
+ return;
468
+ }
469
+ unknownInFlight = true;
470
+ unknownReadyAt = monotonic() + UNKNOWN_ENDPOINT_REFRESH_SPACING_MS;
471
+ const before = head();
472
+ deps.security.refreshLedger()
473
+ .then(() => { afterServerRead(); if (head() !== before)
474
+ reconnectIfRefused(); })
475
+ .catch((error) => log(`[Bridge] Account ledger refresh failed: ${messageOf(error)}`))
476
+ .finally(() => {
477
+ unknownInFlight = false;
478
+ if (unknownQueued) {
479
+ unknownQueued = false;
480
+ refreshForUnknown();
481
+ }
482
+ });
483
+ };
484
+ // This bridge's head announcements: best effort, never awaited by a caller, at most one per HEAD_ANNOUNCE_SPACING_MS. A request while one
485
+ // is pending only marks it wanted; the head is read when it is signed, so the latest head is the one announced.
486
+ const wallClock = deps.wallClock ?? Date.now;
487
+ let publisher = null;
488
+ let announceWanted = false;
489
+ let announcing = false;
490
+ let announceCancel = null;
491
+ let lastAnnounceAt = Number.NEGATIVE_INFINITY;
492
+ let lastAnnounceWarnAt = Number.NEGATIVE_INFINITY;
493
+ const sendAnnouncement = async () => {
494
+ const publish = publisher;
495
+ const status = deps.security.ledgerStatus();
496
+ // Only an active member of its own chain speaks for it (not unpaired, absent or revoked).
497
+ if (publish === null || status.own !== 'active' || status.head === null || status.revision === null)
498
+ return;
499
+ try {
500
+ const announcement = await signHeadAnnouncement(deps.authPrivateKey, {
501
+ accountId: deps.accountId, kind: 'bridge', keyId: deps.bridgeId, head: status.head, revision: status.revision, at: Math.floor(wallClock()),
502
+ });
503
+ if (!stopped)
504
+ await publish(announcement);
505
+ }
506
+ catch (error) {
507
+ const at = monotonic();
508
+ if (at - lastAnnounceWarnAt >= HEAD_ANNOUNCE_WARN_SPACING_MS) {
509
+ lastAnnounceWarnAt = at;
510
+ log(`[Bridge] Could not announce the ledger head: ${messageOf(error)}`);
511
+ }
512
+ }
513
+ };
514
+ const pumpAnnounce = () => {
515
+ if (stopped || !announceWanted || announcing || announceCancel !== null)
516
+ return;
517
+ const wait = lastAnnounceAt + HEAD_ANNOUNCE_SPACING_MS - monotonic();
518
+ if (wait > 0) {
519
+ announceCancel = schedule(() => { announceCancel = null; pumpAnnounce(); }, wait);
520
+ return;
521
+ }
522
+ announceWanted = false;
523
+ announcing = true;
524
+ lastAnnounceAt = monotonic();
525
+ void sendAnnouncement().finally(() => { announcing = false; pumpAnnounce(); });
526
+ };
527
+ const announce = () => {
528
+ // Not wired to a relay client (yet): nothing to announce on, nothing scheduled.
529
+ if (stopped || publisher === null)
530
+ return;
531
+ announceWanted = true;
532
+ pumpAnnounce();
533
+ };
534
+ // Every adopt (and an own-status change, e.g. paired again) is announced.
535
+ const stopHeadListener = deps.security.onLedgerHead(announce);
536
+ // A received announcement: the owner filter and the strict shape ran in the client. Verified against the trusted checkpoint (one signature
537
+ // check); an unknown head only queues the paced server read. An announcement is never proof: no POST, nothing fetched from its sender.
538
+ const judge = async (announcement) => {
539
+ if (stopped || (announcement.kind === 'bridge' && announcement.keyId === deps.bridgeId))
540
+ return;
541
+ let relation;
542
+ try {
543
+ relation = await deps.security.judgeHeadAnnouncement(announcement);
544
+ }
545
+ catch {
546
+ return;
547
+ }
548
+ if (relation === 'unknown')
549
+ submit({ kind: 'refresh', head: announcement.head });
550
+ };
551
+ // The startup read (security.startLedger) may already have shown the server behind.
552
+ afterServerRead();
553
+ return {
554
+ tokens,
555
+ async connectionToken() {
556
+ try {
557
+ return await tokens.getToken();
558
+ }
559
+ catch (error) {
560
+ if (error instanceof UnauthorizedError)
561
+ relayRefused = true;
562
+ throw error;
563
+ }
564
+ },
565
+ relayUrl: () => override ?? learnedRelayUrl ?? savedRelayUrl,
566
+ onLedgerMessage(message) {
567
+ if (message.type === 'ledger')
568
+ submit({ kind: 'offer', ledger: message.ledger });
569
+ else if (message.type === 'head_announcement')
570
+ void judge(message.announcement);
571
+ else if (message.head !== head())
572
+ submit({ kind: 'refresh', head: message.head });
573
+ },
574
+ onLedgerSubscribed: () => {
575
+ submit({ kind: 'refresh', head: null });
576
+ announce();
577
+ },
578
+ setLedgerPublisher(publish) { publisher = publish; },
579
+ onUnknownEndpoint: refreshForUnknown,
580
+ stop() {
581
+ stopped = true;
582
+ reoffer.stop();
583
+ pending = null;
584
+ cancelTimer?.();
585
+ cancelTimer = null;
586
+ unknownCancel?.();
587
+ unknownCancel = null;
588
+ announceWanted = false;
589
+ announceCancel?.();
590
+ announceCancel = null;
591
+ stopHeadListener();
592
+ },
593
+ };
594
+ }
595
+ //# sourceMappingURL=ledger-relay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger-relay.js","sourceRoot":"","sources":["../src/ledger-relay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAG/C,OAAO,EAAE,oBAAoB,EAAyB,MAAM,+BAA+B,CAAC;AAG5F,OAAO,EAAE,mBAAmB,EAAyB,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAsB,MAAM,qBAAqB,CAAC;AAE9E,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAChD,mGAAmG;AACnG,MAAM,yBAAyB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAClD,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAClC,yFAAyF;AACzF,MAAM,CAAC,MAAM,2BAA2B,GAAG,KAAK,CAAC;AACjD,2FAA2F;AAC3F,MAAM,CAAC,MAAM,2BAA2B,GAAG,MAAM,CAAC;AAClD,8HAA8H;AAC9H,MAAM,CAAC,MAAM,mCAAmC,GAAG,KAAK,CAAC;AACzD,8HAA8H;AAC9H,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAC9C,wEAAwE;AACxE,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAC;AAWpD,mGAAmG;AACnG,MAAM,UAAU,eAAe,CAAC,KAAoB,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;IAC5E,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC1B,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACvD,6GAA6G;IAC7G,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,GAAG,CAAC,CAAC;AACzD,CAAC;AAED,6DAA6D;AAC7D,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACF;IAAtC,YAAY,OAAe,EAAW,MAAc;QAClD,KAAK,CAAC,OAAO,CAAC,CAAC;QADqB,WAAM,GAAN,MAAM,CAAQ;QAElD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,SAAS,GAAG,CAAC,KAAc,EAAU,EAAE,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACrG,MAAM,OAAO,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAEvE,qHAAqH;AACrH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC;IAC9H,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,IAAI,KAAK,YAAY,iBAAiB;QAAE,OAAO,IAAI,CAAC;IACpD,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,CAAC;AAC1C,CAAC;AAED,SAAS,YAAY,CAAC,KAAc,EAAE,SAAiB;IACrD,OAAO,KAAK,YAAY,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC;QAC7F,CAAC,CAAC,IAAI,KAAK,CAAC,kCAAkC,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAA0F;IAC3H,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC;IAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,yBAAyB,CAAC;IAC/D,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,yBAAyB,CAAC;IAC7D,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACnC,OAAO;QACL,KAAK,CAAC,WAAW,CAAC,SAAS;YACzB,IAAI,IAAY,CAAC;YACjB,IAAI,MAAc,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,iCAAiC,kBAAkB,CAAC,SAAS,CAAC,EAAE,EAAE;oBACxG,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC;iBAClH,CAAC,CAAC;gBACH,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;gBACzB,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,GAAG,QAAQ,EAAE,CAAC;oBAC9D,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;oBACrD,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;gBAC/C,CAAC;gBACD,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC/B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAAC,MAAM,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YAAC,CAAC;YACzD,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC7F,IAAI,MAAM,KAAK,GAAG;gBAAE,MAAM,IAAI,eAAe,CAAC,uBAAuB,MAAM,GAAG,EAAE,MAAM,CAAC,CAAC;YACxF,IAAI,IAAa,CAAC;YAClB,IAAI,CAAC;gBAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC;gBAAC,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAAC,CAAC;YACxF,MAAM,MAAM,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,IAA6B,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;YACrI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAChG,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU;YACjC,IAAI,MAAc,CAAC;YACnB,IAAI,YAA2B,CAAC;YAChC,IAAI,IAAI,GAAkB,IAAI,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,IAAI,qBAAqB,EAAE;oBAC7D,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,KAAK,EAAE,UAAU;oBAC9G,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC;iBACrF,CAAC,CAAC;gBACH,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;gBACzB,YAAY,GAAG,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;gBACpE,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,GAAG,QAAQ;oBAAE,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;;oBAC/G,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAAC,MAAM,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YAAC,CAAC;YACzD,IAAI,IAAI,GAAY,IAAI,CAAC;YACzB,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACjE,IAAI,CAAC;oBAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC;oBAAC,IAAI,GAAG,IAAI,CAAC;gBAAC,CAAC;YACzD,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;QACxC,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,KAE5C;IACC,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC;IAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,yBAAyB,CAAC;IAC/D,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,yBAAyB,EAAE;YAClF,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YACtG,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;YACpH,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC;SACvC,CAAC,CAAC;QACH,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAAC,MAAM,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAAC,CAAC;IACzD,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,IAAI,GAAG;QAAE,MAAM,IAAI,eAAe,CAAC,2CAA2C,MAAM,GAAG,EAAE,MAAM,CAAC,CAAC;AAC7H,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,wBAAwB,CAAC,KAAc,EAAE,MAAc;IACrE,IAAI,KAAK,YAAY,iBAAiB,EAAE,CAAC;QACvC,OAAO,uJAAuJ,CAAC;IACjK,CAAC;IACD,IAAI,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO,gCAAgC,OAAO,CAAC,MAAM,CAAC,2BAA2B,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;IAC5H,OAAO,6CAA6C,OAAO,CAAC,MAAM,CAAC,KAAK,SAAS,CAAC,KAAK,CAAC,wDAAwD,CAAC;AACnJ,CAAC;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG,gGAAgG;MACrI,mEAAmE,CAAC;AAExE,SAAS,cAAc,CAAC,QAAgB;IACtC,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;AACzH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,MAAc;IAC1D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,oBAAoB;QAAE,OAAO,IAAI,CAAC;IACxG,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QAAC,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IACpD,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC;IAC7C,IAAI,GAAG,CAAC,QAAQ,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,CAAC;QAAC,WAAW,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,uBAAuB,CAAC,CAAC;IAC7F,OAAO,WAAW,IAAI,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACvE,CAAC;AAED,MAAM,YAAY,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;AAE9F,0HAA0H;AAC1H,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,MAAc;IAC/D,IAAI,CAAC;QACH,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QAC/E,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAK,KAA+B,CAAC,OAAO,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/G,OAAO,aAAa,CAAE,KAA2B,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AAC1B,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,GAAW;IACvD,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,UAAU,EAAE,MAAM,CAAC;IAChD,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE,IAAI,CAAC;QACH,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3F,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AA+ED,8HAA8H;AAC9H,MAAM,UAAU,yBAAyB,CAAC,QAAgB,EAAE,QAAsC;IAChG,MAAM,MAAM,GAAI,QAAmC,CAAC,kBAAkB,CAAC;IACvE,IAAI,OAAO,MAAM,KAAK,UAAU;QAAE,OAAO,KAAK,CAAC;IAC/C,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC;AACd,CAAC;AAID,MAAM,eAAe,GAAG,CAAC,GAAe,EAAE,EAAU,EAAgB,EAAE;IACpE,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAClC,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,IAAsB;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,eAAe,CAAC;IAClD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC;IAC1C,MAAM,aAAa,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC;IACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,KAAK,SAAS,IAAI,IAAI,CAAC,gBAAgB,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAChJ,IAAI,IAAI,CAAC,gBAAgB,IAAI,QAAQ,KAAK,IAAI;QAAE,GAAG,CAAC,iGAAiG,CAAC,CAAC;IACvJ,IAAI,eAAe,GAAkB,IAAI,CAAC;IAC1C,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC;IACjD,MAAM,IAAI,GAAG,GAAkB,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC;IACpE,wGAAwG;IACxG,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,0IAA0I;IAC1I,MAAM,OAAO,GAAG,mBAAmB,CAAC;QAClC,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE;QAC5C,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,wFAAwF;YACxF,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,GAAG,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YAC/D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACtC,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACvF,CAAC;QACD,IAAI,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC;QACxE,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC;QAClE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG;KAClE,CAAC,CAAC;IACH,iGAAiG;IACjG,MAAM,eAAe,GAAG,GAAS,EAAE;QACjC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,YAAY;YAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC;IACxF,CAAC,CAAC;IAEF,MAAM,kBAAkB,GAAG,GAAS,EAAE;QACpC,IAAI,CAAC,YAAY,IAAI,OAAO;YAAE,OAAO;QACrC,YAAY,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC;YAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;QAAC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,GAAG,CAAC,oCAAoC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAAC,CAAC;IAC5G,CAAC,CAAC;IAEF,6GAA6G;IAC7G,MAAM,SAAS,GAAiB,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACpD,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,QAAQ,CAAC,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,aAAa,EAAE,CAAC;YACnD,IAAI,CAAC;gBACH,MAAM,IAAI,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;gBAChE,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,aAAa,CAAE,IAAoC,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBACjJ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;oBACnB,MAAM,QAAQ,GAAG,eAAe,IAAI,aAAa,CAAC;oBAClD,eAAe,GAAG,KAAK,CAAC;oBACxB,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;wBACvB,IAAI,CAAC;4BAAC,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC;wBAAC,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BAAC,GAAG,CAAC,0CAA0C,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;wBAAC,CAAC;oBACxH,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC,CAAC,8CAA8C,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,uBAAuB,CAAC;QACtC,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS;QAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,IAAI;QACJ,mIAAmI;QACnI,yEAAyE;QACzE,QAAQ,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;YACvB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBACxE,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;oBAAE,GAAG,CAAC,mEAAmE,CAAC,CAAC;gBAC5G,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;oBAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAChE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAAC,GAAG,CAAC,iEAAiE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAAC,CAAC;QAC/G,CAAC;QACD,8HAA8H;QAC9H,YAAY,EAAE,MAAM,CAAC,EAAE;YACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,QAAQ,KAAK,QAAQ;gBAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC;iBACjD,IAAI,QAAQ,KAAK,SAAS;gBAAE,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3E,CAAC;QACD,qIAAqI;QACrI,mIAAmI;QACnI,SAAS,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;YACxB,IAAI,CAAC;gBAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAAC,CAAC;YAChE,OAAO,KAAK,EAAE,CAAC;gBAAC,GAAG,CAAC,wCAAwC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAAC,CAAC;QACpF,CAAC;QACD,6HAA6H;QAC7H,+HAA+H;QAC/H,iEAAiE;QACjE,cAAc,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,QAAQ;QAChE,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,SAAS;QACT,SAAS,EAAE,yBAAyB;KACrC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,mBAAmB,CAAC;QACjC,UAAU,EAAE,KAAK,IAAI,EAAE;YACrB,MAAM,KAAK,GAAG,MAAM,OAAO,EAAE,CAAC;YAC9B,oGAAoG;YACpG,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,CAAC;YAClC,gHAAgH;YAChH,kBAAkB,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,GAAG,EAAE,SAAS;QACd,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI;KACL,CAAC,CAAC;IAEH,wHAAwH;IACxH,IAAI,OAAO,GAAqB,IAAI,CAAC;IACrC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,WAAW,GAAwB,IAAI,CAAC;IAC5C,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,cAAc,GAAG,MAAM,CAAC,iBAAiB,CAAC;IAE9C,MAAM,GAAG,GAAG,KAAK,EAAE,IAAe,EAAyC,EAAE;QAC3E,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC1B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC5E,kIAAkI;gBAClI,sEAAsE;gBACtE,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;oBAAE,OAAO,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;gBACjG,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;oBAAE,OAAO,MAAM,CAAC;YAClD,CAAC;iBAAM,CAAC;gBACN,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;oBAAE,OAAO,SAAS,CAAC;gBACjE,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;gBACpC,eAAe,EAAE,CAAC;gBAClB,IAAI,IAAI,EAAE,KAAK,MAAM;oBAAE,OAAO,MAAM,CAAC;YACvC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,wCAAwC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAChE,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,kBAAkB,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,IAAI,OAAO,IAAI,OAAO,IAAI,WAAW,KAAK,IAAI,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO;QAC3E,MAAM,IAAI,GAAG,OAAO,GAAG,SAAS,EAAE,CAAC;QACnC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACb,WAAW,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YACpE,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,CAAC;QACrB,OAAO,GAAG,IAAI,CAAC;QACf,OAAO,GAAG,IAAI,CAAC;QACf,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;YAC5B,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO;YAClC,cAAc,GAAG,SAAS,EAAE,CAAC;YAC7B,IAAI,OAAO,KAAK,OAAO;gBAAE,QAAQ,GAAG,CAAC,CAAC;YACtC,MAAM,OAAO,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,2BAA2B;gBAC/D,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,2BAA2B,GAAG,CAAC,IAAI,QAAQ,EAAE,EAAE,2BAA2B,CAAC,CAAC;YACzF,OAAO,GAAG,SAAS,EAAE,GAAG,OAAO,CAAC;QAClC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,CAAC,IAAe,EAAQ,EAAE;QACvC,IAAI,OAAO;YAAE,OAAO;QACpB,8HAA8H;QAC9H,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,IAAI,IAAI,WAAW,KAAK,IAAI,IAAI,SAAS,EAAE,GAAG,cAAc,IAAI,2BAA2B,EAAE,CAAC;YACxH,QAAQ,GAAG,CAAC,CAAC;YACb,OAAO,GAAG,CAAC,CAAC;QACd,CAAC;QACD,OAAO,GAAG,IAAI,CAAC;QACf,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;IAEF,4FAA4F;IAC5F,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,aAAa,GAAwB,IAAI,CAAC;IAC9C,IAAI,cAAc,GAAG,MAAM,CAAC,iBAAiB,CAAC;IAC9C,MAAM,iBAAiB,GAAG,GAAS,EAAE;QACnC,IAAI,OAAO;YAAE,OAAO;QACpB,IAAI,eAAe,EAAE,CAAC;YAAC,aAAa,GAAG,IAAI,CAAC;YAAC,OAAO;QAAC,CAAC;QACtD,IAAI,aAAa,KAAK,IAAI;YAAE,OAAO;QACnC,MAAM,IAAI,GAAG,cAAc,GAAG,SAAS,EAAE,CAAC;QAC1C,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACb,aAAa,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,aAAa,GAAG,IAAI,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YACrF,OAAO;QACT,CAAC;QACD,eAAe,GAAG,IAAI,CAAC;QACvB,cAAc,GAAG,SAAS,EAAE,GAAG,mCAAmC,CAAC;QACnE,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE;aAC1B,IAAI,CAAC,GAAG,EAAE,GAAG,eAAe,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,KAAK,MAAM;YAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,CAAC;aAC/E,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,GAAG,CAAC,2CAA2C,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;aAC7F,OAAO,CAAC,GAAG,EAAE;YACZ,eAAe,GAAG,KAAK,CAAC;YACxB,IAAI,aAAa,EAAE,CAAC;gBAAC,aAAa,GAAG,KAAK,CAAC;gBAAC,iBAAiB,EAAE,CAAC;YAAC,CAAC;QACpE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,0IAA0I;IAC1I,gHAAgH;IAChH,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC;IAC7C,IAAI,SAAS,GAA+D,IAAI,CAAC;IACjF,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,cAAc,GAAwB,IAAI,CAAC;IAC/C,IAAI,cAAc,GAAG,MAAM,CAAC,iBAAiB,CAAC;IAC9C,IAAI,kBAAkB,GAAG,MAAM,CAAC,iBAAiB,CAAC;IAElD,MAAM,gBAAgB,GAAG,KAAK,IAAmB,EAAE;QACjD,MAAM,OAAO,GAAG,SAAS,CAAC;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;QAC5C,0FAA0F;QAC1F,IAAI,OAAO,KAAK,IAAI,IAAI,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI;YAAE,OAAO;QAC5G,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,cAAc,EAAE;gBACnE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;aAC3I,CAAC,CAAC;YACH,IAAI,CAAC,OAAO;gBAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;YACvB,IAAI,EAAE,GAAG,kBAAkB,IAAI,6BAA6B,EAAE,CAAC;gBAC7D,kBAAkB,GAAG,EAAE,CAAC;gBACxB,GAAG,CAAC,gDAAgD,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,GAAS,EAAE;QAC9B,IAAI,OAAO,IAAI,CAAC,cAAc,IAAI,UAAU,IAAI,cAAc,KAAK,IAAI;YAAE,OAAO;QAChF,MAAM,IAAI,GAAG,cAAc,GAAG,wBAAwB,GAAG,SAAS,EAAE,CAAC;QACrE,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACb,cAAc,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,cAAc,GAAG,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YAClF,OAAO;QACT,CAAC;QACD,cAAc,GAAG,KAAK,CAAC;QACvB,UAAU,GAAG,IAAI,CAAC;QAClB,cAAc,GAAG,SAAS,EAAE,CAAC;QAC7B,KAAK,gBAAgB,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,KAAK,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACjF,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,GAAS,EAAE;QAC1B,gFAAgF;QAChF,IAAI,OAAO,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO;QAC1C,cAAc,GAAG,IAAI,CAAC;QACtB,YAAY,EAAE,CAAC;IACjB,CAAC,CAAC;IACF,0EAA0E;IAC1E,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAE9D,2IAA2I;IAC3I,uIAAuI;IACvI,MAAM,KAAK,GAAG,KAAK,EAAE,YAA8B,EAAiB,EAAE;QACpE,IAAI,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,KAAK,QAAQ,IAAI,YAAY,CAAC,KAAK,KAAK,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO;QAChG,IAAI,QAAmC,CAAC;QACxC,IAAI,CAAC;YAAC,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO;QAAC,CAAC;QAC7F,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;IACnF,CAAC,CAAC;IAEF,oFAAoF;IACpF,eAAe,EAAE,CAAC;IAElB,OAAO;QACL,MAAM;QACN,KAAK,CAAC,eAAe;YACnB,IAAI,CAAC;gBAAC,OAAO,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;YAAC,CAAC;YACvC,OAAO,KAAK,EAAE,CAAC;gBACb,IAAI,KAAK,YAAY,iBAAiB;oBAAE,YAAY,GAAG,IAAI,CAAC;gBAC5D,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QACD,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,IAAI,eAAe,IAAI,aAAa;QAC5D,eAAe,CAAC,OAAO;YACrB,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;iBAC5E,IAAI,OAAO,CAAC,IAAI,KAAK,mBAAmB;gBAAE,KAAK,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;iBAC3E,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,EAAE;gBAAE,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QACpF,CAAC;QACD,kBAAkB,EAAE,GAAG,EAAE;YACvB,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACxC,QAAQ,EAAE,CAAC;QACb,CAAC;QACD,kBAAkB,CAAC,OAAO,IAAI,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC;QACpD,iBAAiB,EAAE,iBAAiB;QACpC,IAAI;YACF,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,GAAG,IAAI,CAAC;YACf,WAAW,EAAE,EAAE,CAAC;YAChB,WAAW,GAAG,IAAI,CAAC;YACnB,aAAa,EAAE,EAAE,CAAC;YAClB,aAAa,GAAG,IAAI,CAAC;YACrB,cAAc,GAAG,KAAK,CAAC;YACvB,cAAc,EAAE,EAAE,CAAC;YACnB,cAAc,GAAG,IAAI,CAAC;YACtB,gBAAgB,EAAE,CAAC;QACrB,CAAC;KACF,CAAC;AACJ,CAAC"}