@cleocode/core 2026.9.26 → 2026.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-provenance.json +2 -2
- package/dist/cloud/nexus-attach.d.ts +94 -0
- package/dist/cloud/nexus-attach.d.ts.map +1 -0
- package/dist/cloud/nexus-attach.js +192 -0
- package/dist/cloud/nexus-attach.js.map +1 -0
- package/dist/cloud/nexus-auth.d.ts +15 -3
- package/dist/cloud/nexus-auth.d.ts.map +1 -1
- package/dist/cloud/nexus-auth.js +90 -6
- package/dist/cloud/nexus-auth.js.map +1 -1
- package/dist/cloud/nexus-cloud-status.d.ts +132 -0
- package/dist/cloud/nexus-cloud-status.d.ts.map +1 -0
- package/dist/cloud/nexus-cloud-status.js +440 -0
- package/dist/cloud/nexus-cloud-status.js.map +1 -0
- package/dist/cloud/nexus-cloud.d.ts +179 -0
- package/dist/cloud/nexus-cloud.d.ts.map +1 -0
- package/dist/cloud/nexus-cloud.js +296 -0
- package/dist/cloud/nexus-cloud.js.map +1 -0
- package/dist/cloud/nexus-device.d.ts +31 -6
- package/dist/cloud/nexus-device.d.ts.map +1 -1
- package/dist/cloud/nexus-device.js +54 -7
- package/dist/cloud/nexus-device.js.map +1 -1
- package/dist/cloud/nexus-enrol.d.ts +35 -4
- package/dist/cloud/nexus-enrol.d.ts.map +1 -1
- package/dist/cloud/nexus-enrol.js +187 -47
- package/dist/cloud/nexus-enrol.js.map +1 -1
- package/dist/cloud/nexus-link.d.ts +8 -1
- package/dist/cloud/nexus-link.d.ts.map +1 -1
- package/dist/cloud/nexus-link.js +138 -11
- package/dist/cloud/nexus-link.js.map +1 -1
- package/dist/cloud/nexus-logout.d.ts +114 -0
- package/dist/cloud/nexus-logout.d.ts.map +1 -0
- package/dist/cloud/nexus-logout.js +429 -0
- package/dist/cloud/nexus-logout.js.map +1 -0
- package/dist/docs/export-document.js +242 -37
- package/dist/docs/export-document.js.map +3 -3
- package/dist/llm/plugin-facade.js +343 -138
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/selfimprove/fix-gen.js +347 -142
- package/dist/selfimprove/fix-gen.js.map +3 -3
- package/dist/setup/sections/nexus-account.d.ts +8 -6
- package/dist/setup/sections/nexus-account.d.ts.map +1 -1
- package/dist/setup/sections/nexus-account.js +53 -9
- package/dist/setup/sections/nexus-account.js.map +1 -1
- package/dist/store/sync/replica.d.ts +34 -3
- package/dist/store/sync/replica.d.ts.map +1 -1
- package/dist/store/sync/replica.js +39 -2
- package/dist/store/sync/replica.js.map +1 -1
- package/dist/store/sync/schema.d.ts +6 -3
- package/dist/store/sync/schema.d.ts.map +1 -1
- package/dist/store/sync/schema.js +6 -3
- package/dist/store/sync/schema.js.map +1 -1
- package/package.json +13 -13
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cleo Nexus device logout: `cleo logout nexus [--revoke]` with device
|
|
3
|
+
* credentials (cleo-nexus device contract §3.5, review M3, T12844).
|
|
4
|
+
*
|
|
5
|
+
* A logout never reports success while a credential may still be live:
|
|
6
|
+
*
|
|
7
|
+
* 1. Under the lock, the live credentials move into `pendingSignOut`
|
|
8
|
+
* (`--revoke`: `pendingRevoke`), newest first: `pending`, then `current`
|
|
9
|
+
* ({@link applyBeginSignOut}, {@link applyBeginRevoke}). From then on they
|
|
10
|
+
* are used for nothing but that request. The lock is released.
|
|
11
|
+
* 2. E9 (`POST /v1/devices/self/sign-out`) or E10 (`DELETE /v1/devices/self`)
|
|
12
|
+
* is sent with each credential in turn, newest first, with one attempt and
|
|
13
|
+
* a {@link NEXUS_REVOKE_TIMEOUT_MS} timeout.
|
|
14
|
+
* 3. Done means proved: 200, or a 401 whose reason proves the device state
|
|
15
|
+
* (`device-signed-out`, `device-revoked`, or `credential-revoked` with
|
|
16
|
+
* `revokedReason` `signed-out` / `revoked`). A revoke needs proof of a
|
|
17
|
+
* revoke; a signed-out device is not a revoked one. Any other 401 means
|
|
18
|
+
* that credential is dead, so the next one is tried. A network error,
|
|
19
|
+
* timeout, 429, 5xx or a route the server does not have yet stops the run:
|
|
20
|
+
* the slot is kept and every remaining request is left for the next run
|
|
21
|
+
* without another call.
|
|
22
|
+
* 4. The lock is re-taken and the slot is changed only if it still holds the
|
|
23
|
+
* credential that was answered (compare-and-swap):
|
|
24
|
+
* - a sign-out (confirmed, or every credential dead) clears
|
|
25
|
+
* `pendingSignOut` and keeps the device keys for the next login;
|
|
26
|
+
* - a revoke that ended (confirmed, found the device signed out, or every
|
|
27
|
+
* credential dead) forgets the device locally ({@link applyForgetDevice}),
|
|
28
|
+
* so no later login re-activates the id the user asked to burn. The
|
|
29
|
+
* entry is deleted, or kept stripped while `retired` requests of other
|
|
30
|
+
* devices remain; the store keeps the file while other entries remain.
|
|
31
|
+
* Only a confirmed request is reported `confirmed`; the others name the
|
|
32
|
+
* web remedy.
|
|
33
|
+
*
|
|
34
|
+
* Unsettled slots, and the `retired` requests of replaced devices, are
|
|
35
|
+
* retried by every later logout and, best effort with a shorter timeout, by
|
|
36
|
+
* `cleo login nexus` and `cleo project link` ({@link retryNexusDeviceEnds}).
|
|
37
|
+
* Retired requests are sent before the entry's own request.
|
|
38
|
+
*
|
|
39
|
+
* No function here logs, and no result or error carries a token.
|
|
40
|
+
*
|
|
41
|
+
* @task T12870
|
|
42
|
+
* @epic T12323
|
|
43
|
+
*/
|
|
44
|
+
import { z } from 'zod';
|
|
45
|
+
import { Http, NexusError } from './http.js';
|
|
46
|
+
import { logoutFromNexus, NEXUS_REVOKE_TIMEOUT_MS, resolveNexusApiUrl } from './nexus-auth.js';
|
|
47
|
+
import { FileNexusTokenStore, nexusOriginKey } from './nexus-credentials.js';
|
|
48
|
+
import { applyBeginRevoke, applyBeginSignOut, applyForgetDevice, applyRetiredSettled, applySignOutConfirmed, isForgottenDevice, NexusDeviceStore, UnreadableNexusDevice, } from './nexus-device.js';
|
|
49
|
+
/**
|
|
50
|
+
* Timeout of each E9/E10 call when a login or a link only retries on the way
|
|
51
|
+
* ({@link retryNexusDeviceEnds}); an explicit logout uses {@link NEXUS_REVOKE_TIMEOUT_MS}.
|
|
52
|
+
*/
|
|
53
|
+
export const NEXUS_END_RETRY_TIMEOUT_MS = 2_000;
|
|
54
|
+
function context(opts) {
|
|
55
|
+
const apiUrl = resolveNexusApiUrl(opts.apiUrl);
|
|
56
|
+
return {
|
|
57
|
+
apiUrl,
|
|
58
|
+
origin: nexusOriginKey(apiUrl),
|
|
59
|
+
fetch: opts.fetch ?? ((input, init) => globalThis.fetch(input, init)),
|
|
60
|
+
devices: opts.deviceStore ?? new NexusDeviceStore(),
|
|
61
|
+
now: opts.now ?? (() => new Date()),
|
|
62
|
+
timeoutMs: opts.timeoutMs ?? NEXUS_REVOKE_TIMEOUT_MS,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** E9 answers `{ deviceId, state }`; E10 answers `{ revoked }`. Only the status matters. */
|
|
66
|
+
const endAnswerSchema = z.looseObject({});
|
|
67
|
+
/**
|
|
68
|
+
* What a 401 proves about the device (§4.0.4): `revoked`, `signed-out`, or
|
|
69
|
+
* nothing (`null`: only this credential is dead).
|
|
70
|
+
*/
|
|
71
|
+
function provenState(details) {
|
|
72
|
+
const reason = details?.['reason'];
|
|
73
|
+
const revokedReason = details?.['revokedReason'];
|
|
74
|
+
if (reason === 'device-revoked')
|
|
75
|
+
return 'revoked';
|
|
76
|
+
if (reason === 'device-signed-out')
|
|
77
|
+
return 'signed-out';
|
|
78
|
+
if (reason === 'credential-revoked' && revokedReason === 'revoked')
|
|
79
|
+
return 'revoked';
|
|
80
|
+
if (reason === 'credential-revoked' && revokedReason === 'signed-out')
|
|
81
|
+
return 'signed-out';
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Send E9 or E10 with one credential: one attempt, a plain timeout, no lock held.
|
|
86
|
+
*
|
|
87
|
+
* @returns `done` for 200 or a 401 that proves the requested state,
|
|
88
|
+
* `signed-out` for a revoke that proves only a sign-out, `stale` for any
|
|
89
|
+
* other 401, `unanswered` for everything else, with the reason in `detail`.
|
|
90
|
+
*/
|
|
91
|
+
async function callEnd(ctx, action, token) {
|
|
92
|
+
const timed = (input, init) => ctx.fetch(input, { ...init, signal: AbortSignal.timeout(ctx.timeoutMs) });
|
|
93
|
+
const http = new Http({ baseUrl: ctx.apiUrl, token, fetch: timed, maxAttempts: 1 });
|
|
94
|
+
try {
|
|
95
|
+
if (action === 'sign-out') {
|
|
96
|
+
await http.request('POST', '/v1/devices/self/sign-out', endAnswerSchema, {});
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
await http.request('DELETE', '/v1/devices/self', endAnswerSchema);
|
|
100
|
+
}
|
|
101
|
+
return { answer: 'done', detail: 'HTTP 200' };
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
if (!(err instanceof NexusError)) {
|
|
105
|
+
return {
|
|
106
|
+
answer: 'unanswered',
|
|
107
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
108
|
+
transport: true,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (err.status === 401) {
|
|
112
|
+
const reason = err.details?.['reason'];
|
|
113
|
+
const detail = `HTTP 401 ${typeof reason === 'string' ? reason : err.code}`;
|
|
114
|
+
const state = provenState(err.details);
|
|
115
|
+
if (state === 'revoked' || (state === 'signed-out' && action === 'sign-out')) {
|
|
116
|
+
return { answer: 'done', detail };
|
|
117
|
+
}
|
|
118
|
+
if (state === 'signed-out')
|
|
119
|
+
return { answer: 'signed-out', detail };
|
|
120
|
+
// Only the Nexus API's own verdict on this credential counts as dead. A
|
|
121
|
+
// 401 without its envelope (a proxy or SSO gateway) or with reason
|
|
122
|
+
// `missing` (an Authorization header stripped on the way) proves
|
|
123
|
+
// nothing about the credential, so it is treated as no answer.
|
|
124
|
+
const dead = err.code === 'E_UNAUTHENTICATED' &&
|
|
125
|
+
(reason === 'invalid' ||
|
|
126
|
+
reason === 'credential-expired' ||
|
|
127
|
+
reason === 'credential-revoked');
|
|
128
|
+
return { answer: dead ? 'stale' : 'unanswered', detail };
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
answer: 'unanswered',
|
|
132
|
+
detail: err.code === 'E_NETWORK' ? 'no answer' : `HTTP ${err.status} ${err.code}`,
|
|
133
|
+
transport: err.code === 'E_NETWORK',
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** Every unsettled request of one entry: its `retired` items first, then its own slot. */
|
|
138
|
+
function requestsOf(userId, entry) {
|
|
139
|
+
const out = [];
|
|
140
|
+
for (const r of entry.retired ?? []) {
|
|
141
|
+
out.push({
|
|
142
|
+
userId,
|
|
143
|
+
deviceId: r.deviceId,
|
|
144
|
+
action: r.kind,
|
|
145
|
+
retired: true,
|
|
146
|
+
credentials: r.credentials,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const own = entry.pendingRevoke ?? entry.pendingSignOut;
|
|
150
|
+
if (own) {
|
|
151
|
+
out.push({
|
|
152
|
+
userId,
|
|
153
|
+
deviceId: entry.deviceId,
|
|
154
|
+
action: entry.pendingRevoke ? 'revoke' : 'sign-out',
|
|
155
|
+
retired: false,
|
|
156
|
+
credentials: own.credentials,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return out;
|
|
160
|
+
}
|
|
161
|
+
/** The credentials a request's slot holds now, or `null` when the slot is gone. */
|
|
162
|
+
function slotNow(entry, req) {
|
|
163
|
+
if (entry === null)
|
|
164
|
+
return null;
|
|
165
|
+
if (req.retired) {
|
|
166
|
+
const item = (entry.retired ?? []).find((r) => r.deviceId === req.deviceId && r.kind === req.action);
|
|
167
|
+
return item ? item.credentials : null;
|
|
168
|
+
}
|
|
169
|
+
if (entry.deviceId !== req.deviceId)
|
|
170
|
+
return null;
|
|
171
|
+
const slot = req.action === 'revoke' ? entry.pendingRevoke : entry.pendingSignOut;
|
|
172
|
+
return slot ? slot.credentials : null;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* End a request under the lock, only if its slot still holds `token` (CAS):
|
|
176
|
+
* clear a sign-out slot, settle a retired item, or forget the device after a
|
|
177
|
+
* revoke. An entry left with nothing to keep is deleted.
|
|
178
|
+
*/
|
|
179
|
+
async function settleEnded(ctx, req, token) {
|
|
180
|
+
return ctx.devices.update((tx) => {
|
|
181
|
+
const entry = tx.get(ctx.apiUrl, req.userId);
|
|
182
|
+
const creds = slotNow(entry, req);
|
|
183
|
+
if (entry === null || creds === null || !creds.some((c) => c.token === token)) {
|
|
184
|
+
return { applied: false, removed: false };
|
|
185
|
+
}
|
|
186
|
+
const next = req.retired
|
|
187
|
+
? applyRetiredSettled(entry, req.deviceId, req.action)
|
|
188
|
+
: req.action === 'sign-out'
|
|
189
|
+
? applySignOutConfirmed(entry)
|
|
190
|
+
: applyForgetDevice(entry);
|
|
191
|
+
if (isForgottenDevice(next)) {
|
|
192
|
+
const removed = tx.delete(ctx.apiUrl, req.userId, {
|
|
193
|
+
deviceId: entry.deviceId,
|
|
194
|
+
credentialId: entry.current?.credentialId ?? null,
|
|
195
|
+
});
|
|
196
|
+
return { applied: true, removed };
|
|
197
|
+
}
|
|
198
|
+
tx.set(ctx.apiUrl, req.userId, next);
|
|
199
|
+
return { applied: true, removed: false };
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
/** Try each credential of one request, newest first, and end it when it can be ended. */
|
|
203
|
+
async function settleRequest(ctx, req, warnings) {
|
|
204
|
+
const row = (outcome, removedLocally = false) => ({
|
|
205
|
+
userId: req.userId,
|
|
206
|
+
deviceId: req.deviceId,
|
|
207
|
+
action: req.action,
|
|
208
|
+
retired: req.retired,
|
|
209
|
+
outcome,
|
|
210
|
+
removedLocally,
|
|
211
|
+
});
|
|
212
|
+
const what = `${req.action === 'revoke' ? 'revoke' : 'sign-out'} of device ${req.deviceId}`;
|
|
213
|
+
const web = req.action === 'revoke'
|
|
214
|
+
? `revoke device ${req.deviceId} on cleocode.dev (Devices)`
|
|
215
|
+
: `sign out or revoke device ${req.deviceId} on cleocode.dev (Devices)`;
|
|
216
|
+
const end = async (token, outcome, note) => {
|
|
217
|
+
const settled = await settleEnded(ctx, req, token);
|
|
218
|
+
if (!settled.applied) {
|
|
219
|
+
warnings.push(`${what}: the local entry changed while the request was in flight (a login or another logout?); this machine may hold a newer credential. Run \`cleo logout nexus${req.action === 'revoke' ? ' --revoke' : ''}\` again`);
|
|
220
|
+
}
|
|
221
|
+
else if (note !== null) {
|
|
222
|
+
warnings.push(note);
|
|
223
|
+
}
|
|
224
|
+
return row(outcome, settled.removed);
|
|
225
|
+
};
|
|
226
|
+
for (const c of req.credentials) {
|
|
227
|
+
const { answer, detail, transport } = await callEnd(ctx, req.action, c.token);
|
|
228
|
+
if (answer === 'done')
|
|
229
|
+
return { row: await end(c.token, 'confirmed', null), unreachable: false };
|
|
230
|
+
if (answer === 'signed-out') {
|
|
231
|
+
const signedOut = await end(c.token, 'signed-out', `device ${req.deviceId} is signed out but not revoked, and a signed-out device's credentials cannot revoke it; this machine forgot the device, so the next login enrols a new one. To burn the old id, ${web}`);
|
|
232
|
+
return { row: signedOut, unreachable: false };
|
|
233
|
+
}
|
|
234
|
+
if (answer === 'unanswered') {
|
|
235
|
+
warnings.push(`${what} not confirmed (${detail}); it was kept and is retried by the next \`cleo logout nexus\`, \`cleo login nexus\` or \`cleo project link\``);
|
|
236
|
+
return { row: row('pending'), unreachable: transport === true };
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// Every credential is dead: retrying can never succeed, so the request ends here.
|
|
240
|
+
const first = req.credentials[0];
|
|
241
|
+
if (first === undefined)
|
|
242
|
+
return { row: row('unconfirmed'), unreachable: false };
|
|
243
|
+
const ended = await end(first.token, 'unconfirmed', `${what} not confirmed: the server refused every credential this machine held for it as no longer valid, so none is live and none was kept${req.action === 'revoke' && !req.retired ? '; this machine forgot the device' : ''}. To make sure, ${web}`);
|
|
244
|
+
return { row: ended, unreachable: false };
|
|
245
|
+
}
|
|
246
|
+
/** Every unsettled request on the origin, plus a warning per entry this machine cannot open. */
|
|
247
|
+
async function unsettled(ctx, warnings, warnUnreadable) {
|
|
248
|
+
const out = [];
|
|
249
|
+
for (const d of await ctx.devices.list()) {
|
|
250
|
+
if (d.origin !== ctx.origin)
|
|
251
|
+
continue;
|
|
252
|
+
if (d instanceof UnreadableNexusDevice) {
|
|
253
|
+
if (!warnUnreadable)
|
|
254
|
+
continue;
|
|
255
|
+
warnings.push(`the device entry for user ${d.userId}${d.deviceId ? ` (device ${d.deviceId})` : ''} cannot be opened on this machine (${d.reason}); sign it out or revoke it on cleocode.dev`);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
out.push(...requestsOf(d.userId, d.unseal()));
|
|
259
|
+
}
|
|
260
|
+
return out;
|
|
261
|
+
}
|
|
262
|
+
/** Sort rows by user, then device, for a stable envelope. */
|
|
263
|
+
function byUserThenDevice(a, b) {
|
|
264
|
+
return a.userId.localeCompare(b.userId) || a.deviceId.localeCompare(b.deviceId);
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Retry every unsettled sign-out and revoke on the origin (contract §3.5,
|
|
268
|
+
* L2): each entry's `pendingSignOut` or `pendingRevoke`, and the `retired`
|
|
269
|
+
* requests of devices it replaced. Never throws for a server that cannot be
|
|
270
|
+
* reached; the rows and warnings say what is still open.
|
|
271
|
+
*
|
|
272
|
+
* @param opts - API URL, stores and test overrides.
|
|
273
|
+
* @returns One row per request tried, and the warnings.
|
|
274
|
+
*/
|
|
275
|
+
export async function settleNexusDeviceEnds(opts = {}) {
|
|
276
|
+
const ctx = context(opts);
|
|
277
|
+
const warnings = [];
|
|
278
|
+
const devices = [];
|
|
279
|
+
let unreachable = false;
|
|
280
|
+
let skipped = 0;
|
|
281
|
+
for (const req of await unsettled(ctx, warnings, opts.warnUnreadable ?? true)) {
|
|
282
|
+
if (unreachable) {
|
|
283
|
+
skipped += 1;
|
|
284
|
+
// The server already failed to answer in this run: leave the rest for
|
|
285
|
+
// the next run rather than wait out one timeout per request.
|
|
286
|
+
devices.push({
|
|
287
|
+
userId: req.userId,
|
|
288
|
+
deviceId: req.deviceId,
|
|
289
|
+
action: req.action,
|
|
290
|
+
retired: req.retired,
|
|
291
|
+
outcome: 'pending',
|
|
292
|
+
removedLocally: false,
|
|
293
|
+
});
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
try {
|
|
297
|
+
const r = await settleRequest(ctx, req, warnings);
|
|
298
|
+
// Only a transport failure (no answer at all) stops the run: an HTTP
|
|
299
|
+
// error on one request (a 404, 5xx or 429 for an old device) never
|
|
300
|
+
// keeps the entry's own sign-out or revoke from being sent.
|
|
301
|
+
if (r.unreachable)
|
|
302
|
+
unreachable = true;
|
|
303
|
+
devices.push(r.row);
|
|
304
|
+
}
|
|
305
|
+
catch (err) {
|
|
306
|
+
// A store failure on one request keeps every row collected so far.
|
|
307
|
+
warnings.push(`${req.action} of device ${req.deviceId} could not be settled locally (${err instanceof Error ? err.message : String(err)}); it is retried next time`);
|
|
308
|
+
devices.push({
|
|
309
|
+
userId: req.userId,
|
|
310
|
+
deviceId: req.deviceId,
|
|
311
|
+
action: req.action,
|
|
312
|
+
retired: req.retired,
|
|
313
|
+
outcome: 'pending',
|
|
314
|
+
removedLocally: false,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (skipped > 0) {
|
|
319
|
+
warnings.push(`${skipped} more unsettled sign-out or revoke request(s) were not sent because Cleo Nexus did not answer; they are retried next time`);
|
|
320
|
+
}
|
|
321
|
+
return { devices: devices.sort(byUserThenDevice), warnings };
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Best-effort {@link settleNexusDeviceEnds} for flows that only retry on the
|
|
325
|
+
* way (login, commands that need a credential): a store or network failure
|
|
326
|
+
* becomes a warning and never fails the caller.
|
|
327
|
+
*
|
|
328
|
+
* @param opts - API URL, stores and test overrides.
|
|
329
|
+
* @param warnings - Receives the warnings.
|
|
330
|
+
*/
|
|
331
|
+
export async function retryNexusDeviceEnds(opts, warnings) {
|
|
332
|
+
try {
|
|
333
|
+
const settled = await settleNexusDeviceEnds({
|
|
334
|
+
timeoutMs: NEXUS_END_RETRY_TIMEOUT_MS,
|
|
335
|
+
...opts,
|
|
336
|
+
warnUnreadable: false,
|
|
337
|
+
});
|
|
338
|
+
warnings.push(...settled.warnings);
|
|
339
|
+
}
|
|
340
|
+
catch (err) {
|
|
341
|
+
warnings.push(`could not retry an unsettled Cleo Nexus sign-out (${err instanceof Error ? err.message : String(err)}); \`cleo logout nexus\` retries it`);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Under the lock, move every readable entry on the origin into its
|
|
346
|
+
* sign-out or revoke slot. A revoke of an entry with no credential left
|
|
347
|
+
* (already signed out) cannot be sent, so the device is forgotten locally
|
|
348
|
+
* and the web remedy is returned.
|
|
349
|
+
*
|
|
350
|
+
* @returns Warnings for the result envelope.
|
|
351
|
+
*/
|
|
352
|
+
async function beginEnds(ctx, action) {
|
|
353
|
+
const begin = action === 'revoke' ? applyBeginRevoke : applyBeginSignOut;
|
|
354
|
+
return ctx.devices.update((tx) => {
|
|
355
|
+
const notes = [];
|
|
356
|
+
for (const k of tx.keys()) {
|
|
357
|
+
if (k.origin !== ctx.origin || !k.readable)
|
|
358
|
+
continue;
|
|
359
|
+
const entry = tx.get(ctx.apiUrl, k.userId);
|
|
360
|
+
if (entry === null)
|
|
361
|
+
continue;
|
|
362
|
+
const next = begin(entry, ctx.now());
|
|
363
|
+
if (action === 'revoke' && next.pendingRevoke === null && next.keys !== null) {
|
|
364
|
+
const forgotten = applyForgetDevice(next);
|
|
365
|
+
if (isForgottenDevice(forgotten)) {
|
|
366
|
+
tx.delete(ctx.apiUrl, k.userId, { deviceId: entry.deviceId, credentialId: null });
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
tx.set(ctx.apiUrl, k.userId, forgotten);
|
|
370
|
+
}
|
|
371
|
+
notes.push(`device ${next.deviceId} holds no credential (it is signed out), so it cannot be revoked from here; this machine forgot it, so the next login enrols a new device. To burn the old id, revoke device ${next.deviceId} on cleocode.dev (Devices)`);
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
tx.set(ctx.apiUrl, k.userId, next);
|
|
375
|
+
}
|
|
376
|
+
return [...tx.warnings, ...notes];
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* `cleo logout nexus [--revoke]` with device credentials (contract §3.5, M3).
|
|
381
|
+
*
|
|
382
|
+
* Every readable entry on the origin is moved to `pendingSignOut` (or
|
|
383
|
+
* `pendingRevoke`), then every unsettled request on the origin is sent,
|
|
384
|
+
* including ones left by earlier runs. A leftover 9.24 session for the origin
|
|
385
|
+
* is signed out too. The device keys stay after a sign-out, so a later login
|
|
386
|
+
* reuses the device id; a confirmed revoke removes the entry.
|
|
387
|
+
*
|
|
388
|
+
* @param opts - API URL, `revoke`, stores and test overrides.
|
|
389
|
+
* @returns The per-device outcomes. A row that is not `confirmed` is also
|
|
390
|
+
* named in `warnings`; the result never claims a sign-out the server did
|
|
391
|
+
* not confirm.
|
|
392
|
+
* A device file that cannot be read or locked is reported as a warning, and
|
|
393
|
+
* the 9.24 session is still signed out.
|
|
394
|
+
*/
|
|
395
|
+
export async function logoutNexusDevice(opts = {}) {
|
|
396
|
+
const ctx = context(opts);
|
|
397
|
+
const action = opts.revoke === true ? 'revoke' : 'sign-out';
|
|
398
|
+
const warnings = [];
|
|
399
|
+
let devices = [];
|
|
400
|
+
try {
|
|
401
|
+
warnings.push(...(await beginEnds(ctx, action)));
|
|
402
|
+
const settled = await settleNexusDeviceEnds({
|
|
403
|
+
...opts,
|
|
404
|
+
apiUrl: ctx.apiUrl,
|
|
405
|
+
deviceStore: ctx.devices,
|
|
406
|
+
});
|
|
407
|
+
devices = settled.devices;
|
|
408
|
+
warnings.push(...settled.warnings);
|
|
409
|
+
}
|
|
410
|
+
catch (err) {
|
|
411
|
+
// A broken device file must not stop the 9.24 session sign-out below.
|
|
412
|
+
warnings.push(`the device credentials could not be signed out (${err instanceof Error ? err.message : String(err)}); fix the device file and run \`cleo logout nexus\` again`);
|
|
413
|
+
}
|
|
414
|
+
let session = null;
|
|
415
|
+
const sessions = opts.store ?? new FileNexusTokenStore();
|
|
416
|
+
if ((await sessions.get(ctx.apiUrl)) !== null) {
|
|
417
|
+
session = await logoutFromNexus({
|
|
418
|
+
apiUrl: ctx.apiUrl,
|
|
419
|
+
store: sessions,
|
|
420
|
+
...(opts.fetch ? { fetch: opts.fetch } : {}),
|
|
421
|
+
});
|
|
422
|
+
warnings.push(...session.warnings);
|
|
423
|
+
}
|
|
424
|
+
if (action === 'revoke' && devices.length === 0 && session !== null) {
|
|
425
|
+
warnings.push(`no device credential is stored for ${ctx.apiUrl}, so nothing was revoked; the 9.24 session was signed out`);
|
|
426
|
+
}
|
|
427
|
+
return { apiUrl: ctx.apiUrl, action, devices, session, warnings };
|
|
428
|
+
}
|
|
429
|
+
//# sourceMappingURL=nexus-logout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nexus-logout.js","sourceRoot":"","sources":["../../src/cloud/nexus-logout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAQH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAkB,IAAI,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAwB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACnG,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EAGjB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,CAAC;AAkDhD,SAAS,OAAO,CAAC,IAA8B;IAC7C,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C,OAAO;QACL,MAAM;QACN,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC;QAC9B,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,KAAa,EAAE,IAAkB,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC3F,OAAO,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI,gBAAgB,EAAE;QACnD,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QACnC,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,uBAAuB;KACrD,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,MAAM,eAAe,GAAG,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AAE1C;;;GAGG;AACH,SAAS,WAAW,CAClB,OAA4C;IAE5C,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,aAAa,GAAG,OAAO,EAAE,CAAC,eAAe,CAAC,CAAC;IACjD,IAAI,MAAM,KAAK,gBAAgB;QAAE,OAAO,SAAS,CAAC;IAClD,IAAI,MAAM,KAAK,mBAAmB;QAAE,OAAO,YAAY,CAAC;IACxD,IAAI,MAAM,KAAK,oBAAoB,IAAI,aAAa,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACrF,IAAI,MAAM,KAAK,oBAAoB,IAAI,aAAa,KAAK,YAAY;QAAE,OAAO,YAAY,CAAC;IAC3F,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,OAAO,CACpB,GAAQ,EACR,MAA4B,EAC5B,KAAa;IAEb,MAAM,KAAK,GAAc,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CACvC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;IACpF,IAAI,CAAC;QACH,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;YAC1B,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,2BAA2B,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;QAC/E,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,kBAAkB,EAAE,eAAe,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,CAAC,GAAG,YAAY,UAAU,CAAC,EAAE,CAAC;YACjC,OAAO;gBACL,MAAM,EAAE,YAAY;gBACpB,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;gBACxD,SAAS,EAAE,IAAI;aAChB,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,MAAM,GAAG,YAAY,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAC5E,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,KAAK,YAAY,IAAI,MAAM,KAAK,UAAU,CAAC,EAAE,CAAC;gBAC7E,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;YACpC,CAAC;YACD,IAAI,KAAK,KAAK,YAAY;gBAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;YACpE,wEAAwE;YACxE,mEAAmE;YACnE,iEAAiE;YACjE,+DAA+D;YAC/D,MAAM,IAAI,GACR,GAAG,CAAC,IAAI,KAAK,mBAAmB;gBAChC,CAAC,MAAM,KAAK,SAAS;oBACnB,MAAM,KAAK,oBAAoB;oBAC/B,MAAM,KAAK,oBAAoB,CAAC,CAAC;YACrC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC;QAC3D,CAAC;QACD,OAAO;YACL,MAAM,EAAE,YAAY;YACpB,MAAM,EAAE,GAAG,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE;YACjF,SAAS,EAAE,GAAG,CAAC,IAAI,KAAK,WAAW;SACpC,CAAC;IACJ,CAAC;AACH,CAAC;AAED,0FAA0F;AAC1F,SAAS,UAAU,CAAC,MAAc,EAAE,KAAuB;IACzD,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QACpC,GAAG,CAAC,IAAI,CAAC;YACP,MAAM;YACN,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,MAAM,EAAE,CAAC,CAAC,IAAI;YACd,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,CAAC,CAAC,WAAW;SAC3B,CAAC,CAAC;IACL,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,cAAc,CAAC;IACxD,IAAI,GAAG,EAAE,CAAC;QACR,GAAG,CAAC,IAAI,CAAC;YACP,MAAM;YACN,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU;YACnD,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,GAAG,CAAC,WAAW;SAC7B,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,mFAAmF;AACnF,SAAS,OAAO,CACd,KAA8B,EAC9B,GAAe;IAEf,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CACrC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,CAC5D,CAAC;QACF,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;IACxC,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC;IAClF,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AACxC,CAAC;AAUD;;;;GAIG;AACH,KAAK,UAAU,WAAW,CAAC,GAAQ,EAAE,GAAe,EAAE,KAAa;IACjE,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QAC/B,MAAM,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAClC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,EAAE,CAAC;YAC9E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC5C,CAAC;QACD,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO;YACtB,CAAC,CAAC,mBAAmB,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC;YACtD,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,UAAU;gBACzB,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC;gBAC9B,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE;gBAChD,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,YAAY,EAAE,KAAK,CAAC,OAAO,EAAE,YAAY,IAAI,IAAI;aAClD,CAAC,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QACpC,CAAC;QACD,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC;AAED,yFAAyF;AACzF,KAAK,UAAU,aAAa,CAC1B,GAAQ,EACR,GAAe,EACf,QAAkB;IAElB,MAAM,GAAG,GAAG,CAAC,OAA8B,EAAE,cAAc,GAAG,KAAK,EAAwB,EAAE,CAAC,CAAC;QAC7F,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,OAAO;QACP,cAAc;KACf,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,cAAc,GAAG,CAAC,QAAQ,EAAE,CAAC;IAC5F,MAAM,GAAG,GACP,GAAG,CAAC,MAAM,KAAK,QAAQ;QACrB,CAAC,CAAC,iBAAiB,GAAG,CAAC,QAAQ,4BAA4B;QAC3D,CAAC,CAAC,6BAA6B,GAAG,CAAC,QAAQ,4BAA4B,CAAC;IAC5E,MAAM,GAAG,GAAG,KAAK,EAAE,KAAa,EAAE,OAA8B,EAAE,IAAmB,EAAE,EAAE;QACvF,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACrB,QAAQ,CAAC,IAAI,CACX,GAAG,IAAI,4JAA4J,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,UAAU,CACxN,CAAC;QACJ,CAAC;aAAM,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACzB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QACD,OAAO,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QAChC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9E,IAAI,MAAM,KAAK,MAAM;YACnB,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QAC5E,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;YAC5B,MAAM,SAAS,GAAG,MAAM,GAAG,CACzB,CAAC,CAAC,KAAK,EACP,YAAY,EACZ,UAAU,GAAG,CAAC,QAAQ,mLAAmL,GAAG,EAAE,CAC/M,CAAC;YACF,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QAChD,CAAC;QACD,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;YAC5B,QAAQ,CAAC,IAAI,CACX,GAAG,IAAI,mBAAmB,MAAM,gHAAgH,CACjJ,CAAC;YACF,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,SAAS,KAAK,IAAI,EAAE,CAAC;QAClE,CAAC;IACH,CAAC;IACD,kFAAkF;IAClF,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IAChF,MAAM,KAAK,GAAG,MAAM,GAAG,CACrB,KAAK,CAAC,KAAK,EACX,aAAa,EACb,GAAG,IAAI,qIAAqI,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,EAAE,mBAAmB,GAAG,EAAE,CACtP,CAAC;IACF,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AAC5C,CAAC;AAED,gGAAgG;AAChG,KAAK,UAAU,SAAS,CACtB,GAAQ,EACR,QAAkB,EAClB,cAAuB;IAEvB,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QACzC,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM;YAAE,SAAS;QACtC,IAAI,CAAC,YAAY,qBAAqB,EAAE,CAAC;YACvC,IAAI,CAAC,cAAc;gBAAE,SAAS;YAC9B,QAAQ,CAAC,IAAI,CACX,6BAA6B,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,sCAAsC,CAAC,CAAC,MAAM,6CAA6C,CAC/K,CAAC;YACF,SAAS;QACX,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,6DAA6D;AAC7D,SAAS,gBAAgB,CAAC,CAAuB,EAAE,CAAuB;IACxE,OAAO,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAClF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAgE,EAAE;IAElE,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,GAAG,IAAI,MAAM,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,EAAE,CAAC;QAC9E,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC,CAAC;YACb,sEAAsE;YACtE,6DAA6D;YAC7D,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,OAAO,EAAE,SAAS;gBAClB,cAAc,EAAE,KAAK;aACtB,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;YAClD,qEAAqE;YACrE,mEAAmE;YACnE,4DAA4D;YAC5D,IAAI,CAAC,CAAC,WAAW;gBAAE,WAAW,GAAG,IAAI,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mEAAmE;YACnE,QAAQ,CAAC,IAAI,CACX,GAAG,GAAG,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,kCAAkC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,4BAA4B,CACtJ,CAAC;YACF,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,OAAO,EAAE,SAAS;gBAClB,cAAc,EAAE,KAAK;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,QAAQ,CAAC,IAAI,CACX,GAAG,OAAO,2HAA2H,CACtI,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,QAAQ,EAAE,CAAC;AAC/D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAA8B,EAC9B,QAAkB;IAElB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC;YAC1C,SAAS,EAAE,0BAA0B;YACrC,GAAG,IAAI;YACP,cAAc,EAAE,KAAK;SACtB,CAAC,CAAC;QACH,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,QAAQ,CAAC,IAAI,CACX,qDAAqD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,qCAAqC,CAC3I,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,SAAS,CAAC,GAAQ,EAAE,MAA6B;IAC9D,MAAM,KAAK,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACzE,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QAC/B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1B,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,QAAQ;gBAAE,SAAS;YACrD,MAAM,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,KAAK,KAAK,IAAI;gBAAE,SAAS;YAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;YACrC,IAAI,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;gBAC7E,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAC1C,IAAI,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;oBACjC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;gBACpF,CAAC;qBAAM,CAAC;oBACN,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;gBAC1C,CAAC;gBACD,KAAK,CAAC,IAAI,CACR,UAAU,IAAI,CAAC,QAAQ,gLAAgL,IAAI,CAAC,QAAQ,4BAA4B,CACjP,CAAC;gBACF,SAAS;YACX,CAAC;YACD,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAoC,EAAE;IAEtC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IAC5D,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,OAAO,GAA2B,EAAE,CAAC;IACzC,IAAI,CAAC;QACH,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC;YAC1C,GAAG,IAAI;YACP,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,WAAW,EAAE,GAAG,CAAC,OAAO;SACzB,CAAC,CAAC;QACH,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,sEAAsE;QACtE,QAAQ,CAAC,IAAI,CACX,mDAAmD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,4DAA4D,CAChK,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,GAA6B,IAAI,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,mBAAmB,EAAE,CAAC;IACzD,IAAI,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9C,OAAO,GAAG,MAAM,eAAe,CAAC;YAC9B,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,KAAK,EAAE,QAAQ;YACf,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7C,CAAC,CAAC;QACH,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACpE,QAAQ,CAAC,IAAI,CACX,sCAAsC,GAAG,CAAC,MAAM,2DAA2D,CAC5G,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpE,CAAC"}
|