@substrat-run/contract-tests 0.114.0 → 0.117.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.
@@ -0,0 +1,498 @@
1
+ /**
2
+ * Contract suite for capabilities (#1672) — authority carried by a secret rather than held
3
+ * by a principal: a link share, a claim link.
4
+ *
5
+ * What it pins, in one sentence: **whoever exchanges a capability's secret acts as the
6
+ * capability, and the capability reaches exactly its entity subtree and keys, never more
7
+ * than its minter holds right now, for as long as it is live — and the kernel stores only the
8
+ * secret's hash.**
9
+ *
10
+ * Every refusal here is paired with the allow beside it, so a checker that refused
11
+ * everything cannot pass: the sibling folder is refused NEXT TO the shared folder being
12
+ * read, the other key NEXT TO the carried one, the revoked capability NEXT TO its live
13
+ * twin. The properties, and why each is behavioural rather than a note:
14
+ *
15
+ * 1. **The subtree and the keys.** A capability over folder F reads F, a document in F and
16
+ * a document two levels down; it is refused the sibling folder G, G's document, a
17
+ * node-level read, and a key it does not carry — each refusal landing in the denial log
18
+ * against `{ capability }`.
19
+ * 2. **Never more than the minter holds, on every use.** A reader cannot mint a write key;
20
+ * and when the minter's own role is taken away AFTER the mint, the capability stops
21
+ * granting on the very next call.
22
+ * 3. **Revocation, expiry and the use limit.** A revoke refuses the next invoke on a stub
23
+ * minted before it; a use limit refuses the exchange past it while the sessions already
24
+ * handed out keep working — a use is an exchange, not an invocation; two exchanges racing
25
+ * for a single-use capability admit one. (The expiry TRANSITION needs a clock a test can
26
+ * move, so it is asserted on the pure host — see `capabilityExpiryContractSuite`.)
27
+ * 4. **The spine.** An event the capability causes carries `{ capability }` as its actor
28
+ * and K-34 authorization naming the root; the mint and the exchange are events too.
29
+ * 5. **Only the hash is stored.** Every table of the scope is scanned after a mint, an
30
+ * exchange and a use; the hash is there and the secret is not. The TRIPWIRE for a module
31
+ * persisting its own secret by accident — as a payload value, an object key, an entity id,
32
+ * an intent's kind, a text or a byte SQL parameter — refuses the write and rolls the mint
33
+ * back, and each channel's clean twin goes through. An idempotent replay of a mint returns
34
+ * a placeholder. (A tripwire, not a boundary: a module that means to leak its secret can
35
+ * encode it first, and no scan of storage can recognise every encoding.)
36
+ */
37
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
38
+ import { CAPABILITY_SECRET_PREFIX, CAPABILITY_SESSION_PREFIX, capabilityRecord, errorCodeOf, permissionKey, platformActorId, principalId, scopeId, tenantId, } from '@substrat-run/contracts';
39
+ import { capabilityTokenHash, ulid, WITHHELD_SECRET } from '@substrat-run/kernel';
40
+ import { CAP_LEAK_CHANNELS, capMod } from './modules.js';
41
+ const CAP_READ = permissionKey.parse('cap:read');
42
+ const CAP_WRITE = permissionKey.parse('cap:write');
43
+ const CAP_ADMIN = permissionKey.parse('cap:admin');
44
+ const folder = (id) => ({ entityType: 'folder', entityId: id });
45
+ const doc = (id) => ({ entityType: 'doc', entityId: id });
46
+ /** The refusal a promise settles with, or `undefined` when it resolved. */
47
+ const refusal = (p) => p.then(() => undefined, (e) => e);
48
+ export function capabilityContractSuite(adapterName, makeFixture) {
49
+ describe(`capability contract (#1672): ${adapterName}`, () => {
50
+ let fixture;
51
+ let host;
52
+ const t1 = tenantId.parse(ulid());
53
+ const s1 = scopeId.parse(ulid());
54
+ const s2 = scopeId.parse(ulid()); // same tenant, a second scope
55
+ const alice = principalId.parse(ulid()); // owner: read + write + admin, tenant-wide
56
+ const bob = principalId.parse(ulid()); // reader at s1 only
57
+ const carol = principalId.parse(ulid()); // holds nothing
58
+ const seat = principalId.parse(ulid()); // the principal a `become` yields
59
+ const staff = platformActorId.parse(ulid());
60
+ const inFuture = (ms) => new Date(Date.now() + ms).toISOString();
61
+ const as = (who, scope = s1) => host.getScope(who, t1, scope);
62
+ const share = async (who, spec) => (await as(who)).invoke('cap/share', spec);
63
+ const exchange = (secret, scope = s1) => host.exchangeCapability(t1, scope, secret);
64
+ const sessionOf = async (secret) => {
65
+ const ex = await exchange(secret);
66
+ if (ex?.kind !== 'session')
67
+ throw new Error(`expected a session, got ${JSON.stringify(ex)}`);
68
+ return ex.sessionToken;
69
+ };
70
+ const holder = async (secret) => host.getCapabilityScope(await sessionOf(secret), t1, s1);
71
+ const outbox = async () => (await as(alice)).invoke('cap/outbox');
72
+ const denials = async () => (await as(alice)).invoke('cap/denials');
73
+ const dump = async () => (await as(alice)).invoke('cap/dump');
74
+ beforeAll(async () => {
75
+ fixture = await makeFixture();
76
+ host = fixture.host;
77
+ host.registerModule(capMod);
78
+ await host.admin.createTenant(staff, { id: t1, slug: 'cap-tenant', name: 'Cap Tenant' });
79
+ await host.admin.grantEntitlement(staff, t1, 'cap');
80
+ await host.provisionScope(staff, { tenantId: t1, scopeId: s1, vertical: 'cap-vertical' });
81
+ await host.admin.activateScope(staff, t1, s1);
82
+ await host.provisionScope(staff, { tenantId: t1, scopeId: s2, vertical: 'cap-vertical' });
83
+ await host.admin.activateScope(staff, t1, s2);
84
+ await host.admin.defineRole(staff, t1, {
85
+ key: 'owner',
86
+ permissions: [CAP_READ, CAP_WRITE, CAP_ADMIN],
87
+ source: 'vertical',
88
+ });
89
+ await host.admin.defineRole(staff, t1, { key: 'reader', permissions: [CAP_READ], source: 'vertical' });
90
+ await host.admin.assignRole(staff, {
91
+ principalId: alice,
92
+ roleKey: 'owner',
93
+ node: { tenantId: t1, scopeId: null },
94
+ });
95
+ await host.admin.assignRole(staff, {
96
+ principalId: bob,
97
+ roleKey: 'reader',
98
+ node: { tenantId: t1, scopeId: s1 },
99
+ });
100
+ // The tree in s1: F ─┬─ d1 G ── d3
101
+ // ├─ d2
102
+ // └─ F2 ── d4
103
+ const stub = await as(alice);
104
+ const link = (child, parent) => stub.invoke('cap/link', { child, parent });
105
+ await link(doc('d1'), folder('F'));
106
+ await link(doc('d2'), folder('F'));
107
+ await link(folder('F2'), folder('F'));
108
+ await link(doc('d4'), folder('F2'));
109
+ await link(doc('d3'), folder('G'));
110
+ });
111
+ afterAll(async () => {
112
+ await fixture.cleanup();
113
+ });
114
+ describe('mint → exchange → act: exactly the subtree and the keys', () => {
115
+ let minted;
116
+ let stub;
117
+ beforeAll(async () => {
118
+ minted = await share(alice, { entity: folder('F'), permissions: [CAP_READ] });
119
+ stub = await holder(minted.secret);
120
+ });
121
+ it('hands back a prefixed secret and an id, once', () => {
122
+ expect(minted.secret.startsWith(CAPABILITY_SECRET_PREFIX)).toBe(true);
123
+ expect(minted.secret.length).toBeGreaterThanOrEqual(CAPABILITY_SECRET_PREFIX.length + 43);
124
+ });
125
+ it('an exchange yields a session, never the secret back', async () => {
126
+ const ex = await exchange(minted.secret);
127
+ expect(ex?.kind).toBe('session');
128
+ if (ex?.kind !== 'session')
129
+ return;
130
+ expect(ex.sessionToken.startsWith(CAPABILITY_SESSION_PREFIX)).toBe(true);
131
+ expect(ex.sessionToken).not.toContain(minted.secret);
132
+ expect(ex.capabilityId).toBe(minted.id);
133
+ expect(ex.entity).toEqual(folder('F'));
134
+ });
135
+ it('reads the shared folder, a document in it, and one two levels down', async () => {
136
+ for (const entity of [folder('F'), doc('d1'), doc('d4')]) {
137
+ await expect(stub.invoke('cap/read', { entity })).resolves.toMatchObject({ read: entity });
138
+ }
139
+ });
140
+ it('the proof ends at the capability’s grant on its root, after the minter’s own chain', async () => {
141
+ const out = await stub.invoke('cap/read', { entity: doc('d4') });
142
+ const last = out.proof[out.proof.length - 1];
143
+ expect(last).toEqual({
144
+ subject: `capability:${minted.id}`,
145
+ relation: 'granted:cap:read',
146
+ object: 'folder:F',
147
+ });
148
+ expect(out.proof).toContainEqual({
149
+ subject: `capability:${minted.id}`,
150
+ relation: 'minted-by',
151
+ object: `principal:${alice}`,
152
+ });
153
+ // The walk it took: d4 → F2 → F.
154
+ expect(out.proof).toContainEqual({ subject: 'doc:d4', relation: 'parent', object: 'folder:F2' });
155
+ expect(out.proof).toContainEqual({ subject: 'folder:F2', relation: 'parent', object: 'folder:F' });
156
+ });
157
+ it('is refused the sibling folder and the sibling’s document — and the refusal is recorded', async () => {
158
+ for (const entity of [folder('G'), doc('d3')]) {
159
+ const err = await refusal(stub.invoke('cap/read', { entity }));
160
+ expect(errorCodeOf(err)).toBe('permission_denied');
161
+ }
162
+ const rows = (await denials()).filter((d) => d.actor === JSON.stringify({ capability: minted.id }));
163
+ expect(rows.filter((d) => d.permission === 'cap:read' && d.operation === 'cap/read')).toHaveLength(2);
164
+ });
165
+ it('is refused a key it does not carry, even on its own root', async () => {
166
+ const err = await refusal(stub.invoke('cap/comment', { doc: doc('d1'), body: 'hi' }));
167
+ expect(errorCodeOf(err)).toBe('permission_denied');
168
+ const rows = await denials();
169
+ expect(rows).toContainEqual(expect.objectContaining({
170
+ actor: JSON.stringify({ capability: minted.id }),
171
+ permission: 'cap:write',
172
+ operation: 'cap/comment',
173
+ }));
174
+ });
175
+ it('holds no node-level authority: a check without an entity refuses it', async () => {
176
+ const err = await refusal(stub.invoke('cap/read-all'));
177
+ expect(errorCodeOf(err)).toBe('permission_denied');
178
+ // The positive twin: the owner, holding the key at the node, passes the same check.
179
+ await expect((await as(alice)).invoke('cap/read-all')).resolves.toEqual({ all: true });
180
+ });
181
+ it('ctx.principal carries the capability id — it is not a person', async () => {
182
+ expect(await stub.invoke('cap/whoami')).toBe(minted.id);
183
+ });
184
+ it('a session is scope-bound: presented to another scope of the tenant, it acts as nobody', async () => {
185
+ const token = await sessionOf(minted.secret);
186
+ const elsewhere = await host.getCapabilityScope(token, t1, s2);
187
+ expect(errorCodeOf(await refusal(elsewhere.invoke('cap/read', { entity: folder('F') })))).toBe('unauthenticated');
188
+ });
189
+ it('a secret is scope-bound: exchanged at another scope of the tenant, it finds nothing', async () => {
190
+ expect(await exchange(minted.secret, s2)).toBeNull();
191
+ });
192
+ });
193
+ describe('never more than the minter holds — at the mint, and on every use', () => {
194
+ it('a reader cannot mint a write key; the same reader can mint the read key', async () => {
195
+ const err = await refusal(share(bob, { entity: folder('F'), permissions: [CAP_WRITE] }));
196
+ expect(errorCodeOf(err)).toBe('permission_denied');
197
+ const ok = await share(bob, { entity: folder('F'), permissions: [CAP_READ] });
198
+ expect(ok.id).toMatch(/^[0-9A-HJKMNP-TV-Z]{26}$/);
199
+ });
200
+ it('one key too many refuses the whole mint, and leaves no row behind', async () => {
201
+ const before = (await (await as(alice)).invoke('cap/list', { includeRevoked: true })).length;
202
+ await refusal(share(bob, { entity: folder('F'), permissions: [CAP_READ, CAP_WRITE] }));
203
+ const after = (await (await as(alice)).invoke('cap/list', { includeRevoked: true })).length;
204
+ expect(after).toBe(before);
205
+ });
206
+ it('someone holding nothing mints nothing', async () => {
207
+ const err = await refusal(share(carol, { entity: folder('F'), permissions: [CAP_READ] }));
208
+ expect(errorCodeOf(err)).toBe('permission_denied');
209
+ });
210
+ it('taking the minter’s role away AFTER the mint ends what the capability can do, at the next call', async () => {
211
+ const dan = principalId.parse(ulid());
212
+ const role = { principalId: dan, roleKey: 'reader', node: { tenantId: t1, scopeId: s1 } };
213
+ await host.admin.assignRole(staff, role);
214
+ const minted = await share(dan, { entity: folder('F'), permissions: [CAP_READ] });
215
+ const stub = await holder(minted.secret);
216
+ await expect(stub.invoke('cap/read', { entity: doc('d1') })).resolves.toBeTruthy();
217
+ await host.admin.unassignRole(staff, role);
218
+ expect(errorCodeOf(await refusal(stub.invoke('cap/read', { entity: doc('d1') })))).toBe('permission_denied');
219
+ // Given back, it grants again — the re-check is live, not a latch.
220
+ await host.admin.assignRole(staff, role);
221
+ await expect(stub.invoke('cap/read', { entity: doc('d1') })).resolves.toBeTruthy();
222
+ });
223
+ it('a consumer cannot mint: its checks allow unconditionally, so it is refused outright', async () => {
224
+ await (await as(alice)).invoke('cap/request-mint', { entity: folder('F') });
225
+ const notes = await (await as(alice)).invoke('cap/notes');
226
+ expect(notes.map((n) => n.body)).toContain('refused forbidden');
227
+ expect(notes.some((n) => n.body.startsWith('minted'))).toBe(false);
228
+ });
229
+ it('a capability cannot mint a capability — no re-delegation', async () => {
230
+ const minted = await share(alice, {
231
+ entity: folder('F'),
232
+ permissions: [CAP_READ],
233
+ });
234
+ const stub = await holder(minted.secret);
235
+ const err = await refusal(stub.invoke('cap/share', { entity: folder('F'), permissions: [CAP_READ] }));
236
+ expect(errorCodeOf(err)).toBe('forbidden');
237
+ });
238
+ });
239
+ describe('revocation, the use limit, and the operation list', () => {
240
+ it('a revoke refuses the NEXT invoke on a stub minted before it; its live twin keeps working', async () => {
241
+ const doomed = await share(alice, { entity: folder('F'), permissions: [CAP_READ] });
242
+ const twin = await share(alice, { entity: folder('F'), permissions: [CAP_READ] });
243
+ const doomedStub = await holder(doomed.secret);
244
+ const twinStub = await holder(twin.secret);
245
+ await expect(doomedStub.invoke('cap/read', { entity: folder('F') })).resolves.toBeTruthy();
246
+ await (await as(alice)).invoke('cap/unshare', { id: doomed.id });
247
+ expect(errorCodeOf(await refusal(doomedStub.invoke('cap/read', { entity: folder('F') })))).toBe('unauthenticated');
248
+ expect(await exchange(doomed.secret)).toBeNull();
249
+ await expect(twinStub.invoke('cap/read', { entity: folder('F') })).resolves.toBeTruthy();
250
+ });
251
+ it('revoking twice is a no-op, not an error', async () => {
252
+ const minted = await share(alice, { entity: folder('F'), permissions: [CAP_READ] });
253
+ await (await as(alice)).invoke('cap/unshare', { id: minted.id });
254
+ await expect((await as(alice)).invoke('cap/unshare', { id: minted.id })).resolves.toEqual({
255
+ revoked: true,
256
+ });
257
+ });
258
+ it('only someone who could have minted it may revoke it', async () => {
259
+ const minted = await share(alice, { entity: folder('F'), permissions: [CAP_WRITE] });
260
+ // bob reads F but does not hold cap:write there.
261
+ expect(errorCodeOf(await refusal((await as(bob)).invoke('cap/unshare', { id: minted.id })))).toBe('permission_denied');
262
+ expect(errorCodeOf(await refusal((await as(carol)).invoke('cap/unshare', { id: minted.id })))).toBe('permission_denied');
263
+ });
264
+ it('a use limit refuses the exchange past it — and the sessions already out keep acting', async () => {
265
+ const minted = await share(alice, { entity: folder('F'), permissions: [CAP_READ], maxUses: 2 });
266
+ const first = await host.getCapabilityScope(await sessionOf(minted.secret), t1, s1);
267
+ await sessionOf(minted.secret);
268
+ expect(await exchange(minted.secret)).toBeNull();
269
+ // A use is an EXCHANGE: the first session reads as often as it likes.
270
+ for (let i = 0; i < 3; i++) {
271
+ await expect(first.invoke('cap/read', { entity: doc('d1') })).resolves.toBeTruthy();
272
+ }
273
+ const [record] = (await (await as(alice)).invoke('cap/list', { entity: folder('F') }))
274
+ .map((r) => capabilityRecord.parse(r))
275
+ .filter((r) => r.id === minted.id);
276
+ expect(record?.uses).toBe(2);
277
+ expect(record?.maxUses).toBe(2);
278
+ });
279
+ it('two exchanges racing for a single-use capability admit exactly one', async () => {
280
+ const minted = await share(alice, { entity: folder('F'), permissions: [CAP_READ], maxUses: 1 });
281
+ const results = await Promise.all(Array.from({ length: 5 }, () => exchange(minted.secret)));
282
+ expect(results.filter((r) => r !== null)).toHaveLength(1);
283
+ });
284
+ it('an operation off the capability’s list is refused before its handler, whatever the keys allow', async () => {
285
+ const minted = await share(alice, {
286
+ entity: folder('F'),
287
+ permissions: [CAP_READ, CAP_WRITE],
288
+ operations: ['cap/read'],
289
+ });
290
+ const stub = await holder(minted.secret);
291
+ await expect(stub.invoke('cap/read', { entity: doc('d1') })).resolves.toBeTruthy();
292
+ expect(errorCodeOf(await refusal(stub.invoke('cap/comment', { doc: doc('d1'), body: 'x' })))).toBe('forbidden');
293
+ // Refused at the door: no key was checked, so nothing lands in the denial log.
294
+ const rows = (await denials()).filter((d) => d.actor === JSON.stringify({ capability: minted.id }));
295
+ expect(rows).toHaveLength(0);
296
+ });
297
+ it('an allowlist naming an operation that does not exist is refused at the mint', async () => {
298
+ const err = await refusal(share(alice, { entity: folder('F'), permissions: [CAP_READ], operations: ['cap/no-such-op'] }));
299
+ expect(errorCodeOf(err)).toBe('validation_failed');
300
+ });
301
+ it('an expiry that is not in the future is refused at the mint', async () => {
302
+ const err = await refusal(share(alice, { entity: folder('F'), permissions: [CAP_READ], expiresAt: '2000-01-01T00:00:00.000Z' }));
303
+ expect(errorCodeOf(err)).toBe('validation_failed');
304
+ });
305
+ it('a secret that is not one of ours, or one never minted, exchanges for nothing', async () => {
306
+ expect(await exchange('not-a-secret')).toBeNull();
307
+ expect(await exchange(`${CAPABILITY_SECRET_PREFIX}${'A'.repeat(43)}`)).toBeNull();
308
+ });
309
+ });
310
+ describe('the spine: the actor, K-34, and the capability’s own events', () => {
311
+ it('an event the capability causes is stamped `{ capability }`, with the key and root that authorized it', async () => {
312
+ const minted = await share(alice, { entity: folder('F'), permissions: [CAP_READ, CAP_WRITE] });
313
+ const stub = await holder(minted.secret);
314
+ await stub.invoke('cap/comment', { doc: doc('d2'), body: 'looks good' });
315
+ const row = (await outbox())
316
+ .filter((r) => r.type === 'cap.commented' && r.entity_id === 'd2')
317
+ .pop();
318
+ expect(JSON.parse(row.actor)).toEqual({ capability: minted.id });
319
+ expect(JSON.parse(row.authorization)).toEqual([{ permission: 'cap:write', grant: 'folder:F' }]);
320
+ expect(row.operation).toBe('cap/comment');
321
+ });
322
+ it('the mint is on the spine as the minter; the exchange as the capability — neither carries the secret', async () => {
323
+ const minted = await share(alice, { entity: folder('F'), permissions: [CAP_READ] });
324
+ await sessionOf(minted.secret);
325
+ const rows = await outbox();
326
+ const mint = rows.find((r) => r.type === 'capability.minted' && JSON.parse(r.payload).capabilityId === minted.id);
327
+ expect(JSON.parse(mint.actor)).toBe(alice);
328
+ expect(mint.entity_type).toBe('folder');
329
+ expect(mint.entity_id).toBe('F');
330
+ const exercised = rows.find((r) => r.type === 'capability.exercised' && JSON.parse(r.payload).capabilityId === minted.id);
331
+ expect(JSON.parse(exercised.actor)).toEqual({ capability: minted.id });
332
+ expect(exercised.operation).toBe('capabilities.exchange');
333
+ // ONE instant per exchange: the event says the use happened exactly when the row does.
334
+ const [record] = (await (await as(alice)).invoke('cap/list', { entity: folder('F'), limit: 200 }))
335
+ .map((r) => capabilityRecord.parse(r))
336
+ .filter((r) => r.id === minted.id);
337
+ expect(record?.lastUsedAt).toBe(exercised.occurred_at);
338
+ expect(JSON.parse(exercised.payload)).toMatchObject({ mode: 'act', uses: 1 });
339
+ for (const r of [mint, exercised])
340
+ expect(r.payload).not.toContain(minted.secret);
341
+ });
342
+ it('a revoke is on the spine as the revoker', async () => {
343
+ const minted = await share(alice, { entity: folder('F'), permissions: [CAP_READ] });
344
+ await (await as(alice)).invoke('cap/unshare', { id: minted.id });
345
+ const row = (await outbox()).find((r) => r.type === 'capability.revoked' && JSON.parse(r.payload).capabilityId === minted.id);
346
+ expect(JSON.parse(row.actor)).toBe(alice);
347
+ });
348
+ });
349
+ describe('only the hash is stored; an accidental write of the secret is refused', () => {
350
+ it('after a mint, an exchange and a use, every table holds the hash and none holds the secret', async () => {
351
+ const minted = await share(alice, { entity: folder('F'), permissions: [CAP_READ, CAP_WRITE] });
352
+ const token = await sessionOf(minted.secret);
353
+ const stub = await host.getCapabilityScope(token, t1, s1);
354
+ await stub.invoke('cap/comment', { doc: doc('d1'), body: 'stored' });
355
+ const tables = await dump();
356
+ const everything = Object.values(tables).join('\n');
357
+ expect(everything).not.toContain(minted.secret);
358
+ expect(everything).not.toContain(token);
359
+ // The positive twin: what IS stored is the hash — of both.
360
+ expect(tables._substrat_capabilities).toContain(await capabilityTokenHash(minted.secret));
361
+ expect(tables._substrat_capability_sessions).toContain(await capabilityTokenHash(token));
362
+ });
363
+ // The tripwire, channel by channel: each accidental write of the secret is refused
364
+ // and takes its mint down with it; the SAME channel carrying a harmless value goes
365
+ // through and the capability persists — so a guard that refused a channel wholesale,
366
+ // or scanned only the payload, would fail one side or the other.
367
+ const labelled = async (label) => (await (await as(alice)).invoke('cap/list', { includeRevoked: true, limit: 200 }))
368
+ .map((r) => capabilityRecord.parse(r))
369
+ .some((r) => r.label === label);
370
+ for (const via of CAP_LEAK_CHANNELS) {
371
+ it(`the secret written via ${via} is refused, and its mint rolled back with it`, async () => {
372
+ const label = `leak-${via}-${ulid()}`;
373
+ const err = await refusal((await as(alice)).invoke('cap/share-and-leak', {
374
+ entity: folder('F'),
375
+ permissions: [CAP_READ],
376
+ label,
377
+ via,
378
+ }));
379
+ expect(errorCodeOf(err)).toBe('forbidden');
380
+ expect(await labelled(label)).toBe(false);
381
+ });
382
+ it(`a harmless value written via ${via} goes through (the clean twin)`, async () => {
383
+ const label = `clean-${via}-${ulid()}`;
384
+ await (await as(alice)).invoke('cap/share-and-leak', {
385
+ entity: folder('F'),
386
+ permissions: [CAP_READ],
387
+ label,
388
+ via,
389
+ leak: false,
390
+ });
391
+ expect(await labelled(label)).toBe(true);
392
+ });
393
+ }
394
+ it('an idempotent replay of a mint withholds the secret; the first response carried it', async () => {
395
+ const key = `mint-${ulid()}`;
396
+ const input = { entity: folder('F'), permissions: [CAP_READ], label: key };
397
+ const stub = await as(alice);
398
+ const first = await stub.invoke('cap/share-link', input, {
399
+ idempotencyKey: key,
400
+ });
401
+ expect(first.link).toMatch(new RegExp(`#share=${CAPABILITY_SECRET_PREFIX}`));
402
+ const replay = await stub.invoke('cap/share-link', input, {
403
+ idempotencyKey: key,
404
+ });
405
+ expect(replay.id).toBe(first.id);
406
+ expect(replay.link).toBe(`https://docs.example/#share=${WITHHELD_SECRET}`);
407
+ const secret = first.link.split('#share=')[1];
408
+ expect(Object.values(await dump()).join('\n')).not.toContain(secret);
409
+ // The first response's secret is the real one: it exchanges.
410
+ expect((await exchange(secret))?.kind).toBe('session');
411
+ });
412
+ });
413
+ describe('listing', () => {
414
+ it('lists records with neither the secret nor its hash; revoked ones only when asked', async () => {
415
+ const live = await share(alice, { entity: folder('F2'), permissions: [CAP_READ], label: 'live' });
416
+ const gone = await share(alice, { entity: folder('F2'), permissions: [CAP_READ], label: 'gone' });
417
+ await (await as(alice)).invoke('cap/unshare', { id: gone.id });
418
+ const listed = await (await as(alice)).invoke('cap/list', { entity: folder('F2') });
419
+ const ids = listed.map((r) => capabilityRecord.parse(r).id);
420
+ expect(ids).toContain(live.id);
421
+ expect(ids).not.toContain(gone.id);
422
+ const all = (await (await as(alice)).invoke('cap/list', {
423
+ entity: folder('F2'),
424
+ includeRevoked: true,
425
+ })).map((r) => capabilityRecord.parse(r));
426
+ expect(all.find((r) => r.id === gone.id)?.revokedBy).toBe(alice);
427
+ const text = JSON.stringify(all);
428
+ expect(text).not.toContain(live.secret);
429
+ expect(text).not.toContain(await capabilityTokenHash(live.secret));
430
+ });
431
+ });
432
+ describe('become — platform-minted, exchanged for a principal', () => {
433
+ it('yields the principal once, is spent, and is audited without its secret', async () => {
434
+ const minted = await host.admin.mintCapability(staff, t1, s1, {
435
+ principal: seat,
436
+ expiresAt: inFuture(60_000),
437
+ maxUses: 1,
438
+ label: 'claim',
439
+ });
440
+ const ex = await exchange(minted.secret);
441
+ expect(ex).toEqual({ kind: 'principal', capabilityId: minted.id, principal: seat });
442
+ expect(await exchange(minted.secret)).toBeNull();
443
+ const log = await host.admin.auditLog(staff);
444
+ const entry = log.find((e) => e.action === 'mintCapability' && JSON.stringify(e.after).includes(minted.id));
445
+ expect(entry).toBeDefined();
446
+ expect(JSON.stringify(log)).not.toContain(minted.secret);
447
+ expect(JSON.stringify(log)).not.toContain(await capabilityTokenHash(minted.secret));
448
+ const exercised = (await outbox()).find((r) => r.type === 'capability.exercised' && JSON.parse(r.payload).capabilityId === minted.id);
449
+ expect(JSON.parse(exercised.actor)).toEqual({ capability: minted.id });
450
+ expect(JSON.parse(exercised.payload)).toMatchObject({ mode: 'become', principal: seat });
451
+ });
452
+ it('a route that can only take a session refuses a `become` secret WITHOUT spending it', async () => {
453
+ const minted = await host.admin.mintCapability(staff, t1, s1, {
454
+ principal: seat,
455
+ expiresAt: inFuture(60_000),
456
+ maxUses: 1,
457
+ });
458
+ expect(await host.exchangeCapability(t1, s1, minted.secret, { mode: 'act' })).toBeNull();
459
+ // Still unspent: the route that CAN take a principal gets it.
460
+ expect(await host.exchangeCapability(t1, s1, minted.secret, { mode: 'become' })).toEqual({
461
+ kind: 'principal',
462
+ capabilityId: minted.id,
463
+ principal: seat,
464
+ });
465
+ });
466
+ it('and a claim route refuses a share link without spending it', async () => {
467
+ const link = await share(alice, { entity: folder('F'), permissions: [CAP_READ], maxUses: 1 });
468
+ expect(await host.exchangeCapability(t1, s1, link.secret, { mode: 'become' })).toBeNull();
469
+ expect((await host.exchangeCapability(t1, s1, link.secret, { mode: 'act' }))?.kind).toBe('session');
470
+ });
471
+ it('is revoked by the platform, not by a module', async () => {
472
+ const minted = await host.admin.mintCapability(staff, t1, s1, {
473
+ principal: seat,
474
+ expiresAt: inFuture(60_000),
475
+ maxUses: 3,
476
+ });
477
+ expect(errorCodeOf(await refusal((await as(alice)).invoke('cap/unshare', { id: minted.id })))).toBe('forbidden');
478
+ await host.admin.revokeCapability(staff, t1, s1, minted.id);
479
+ expect(await exchange(minted.secret)).toBeNull();
480
+ });
481
+ it('the platform can revoke a module-minted link too — the lever for a leaked one', async () => {
482
+ const minted = await share(alice, { entity: folder('F'), permissions: [CAP_READ] });
483
+ const stub = await holder(minted.secret);
484
+ await host.admin.revokeCapability(staff, t1, s1, minted.id);
485
+ expect(errorCodeOf(await refusal(stub.invoke('cap/read', { entity: folder('F') })))).toBe('unauthenticated');
486
+ });
487
+ it('requires a future expiry, and refuses an unknown capability on revoke', async () => {
488
+ expect(errorCodeOf(await refusal(host.admin.mintCapability(staff, t1, s1, {
489
+ principal: seat,
490
+ expiresAt: '2000-01-01T00:00:00.000Z',
491
+ maxUses: 1,
492
+ })))).toBe('validation_failed');
493
+ expect(errorCodeOf(await refusal(host.admin.revokeCapability(staff, t1, s1, ulid())))).toBe('not_found');
494
+ });
495
+ });
496
+ });
497
+ }
498
+ //# sourceMappingURL=capability-suite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-suite.js","sourceRoot":"","sources":["../src/capability-suite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACnE,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,eAAe,EACf,WAAW,EACX,OAAO,EACP,QAAQ,GAOT,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,IAAI,EAAE,eAAe,EAAkB,MAAM,sBAAsB,CAAC;AAElG,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AACjD,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AACnD,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AAEnD,MAAM,MAAM,GAAG,CAAC,EAAU,EAAa,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;AACnF,MAAM,GAAG,GAAG,CAAC,EAAU,EAAa,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;AAmB7E,2EAA2E;AAC3E,MAAM,OAAO,GAAG,CAAC,CAAmB,EAAoB,EAAE,CACxD,CAAC,CAAC,IAAI,CACJ,GAAG,EAAE,CAAC,SAAS,EACf,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAClB,CAAC;AAEJ,MAAM,UAAU,uBAAuB,CACrC,WAAmB,EACnB,WAA4C;IAE5C,QAAQ,CAAC,gCAAgC,WAAW,EAAE,EAAE,GAAG,EAAE;QAC3D,IAAI,OAAyB,CAAC;QAC9B,IAAI,IAAe,CAAC;QACpB,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAClC,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACjC,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,8BAA8B;QAChE,MAAM,KAAK,GAAgB,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,2CAA2C;QACjG,MAAM,GAAG,GAAgB,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,oBAAoB;QACxE,MAAM,KAAK,GAAgB,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,gBAAgB;QACtE,MAAM,IAAI,GAAgB,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,kCAAkC;QACvF,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAE5C,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAW,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,WAAW,EAAa,CAAC;QAE7F,MAAM,EAAE,GAAG,CAAC,GAAgB,EAAE,KAAK,GAAY,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QACpF,MAAM,KAAK,GAAG,KAAK,EACjB,GAAgB,EAChB,IAA6B,EACF,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAmB,WAAW,EAAE,IAAI,CAAC,CAAC;QAC5F,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,KAAK,GAAY,EAAE,EAAsC,EAAE,CAC3F,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,KAAK,EAAE,MAAc,EAAmB,EAAE;YAC1D,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,EAAE,EAAE,IAAI,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7F,OAAO,EAAE,CAAC,YAAY,CAAC;QACzB,CAAC,CAAC;QACF,MAAM,MAAM,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAClG,MAAM,MAAM,GAAG,KAAK,IAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAc,YAAY,CAAC,CAAC;QACrG,MAAM,OAAO,GAAG,KAAK,IAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAc,aAAa,CAAC,CAAC;QACvG,MAAM,IAAI,GAAG,KAAK,IAAqC,EAAE,CACvD,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAyB,UAAU,CAAC,CAAC;QAE/D,SAAS,CAAC,KAAK,IAAI,EAAE;YACnB,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;YAC9B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YACpB,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YAC5B,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;YACzF,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YACpD,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;YAC1F,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;YAC1F,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE;gBACrC,GAAG,EAAE,OAAO;gBACZ,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC;gBAC7C,MAAM,EAAE,UAAU;aACnB,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YACvG,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE;gBACjC,WAAW,EAAE,KAAK;gBAClB,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;aACtC,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE;gBACjC,WAAW,EAAE,GAAG;gBAChB,OAAO,EAAE,QAAQ;gBACjB,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;aACpC,CAAC,CAAC;YAEH,8CAA8C;YAC9C,6BAA6B;YAC7B,mCAAmC;YACnC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;YAC7B,MAAM,IAAI,GAAG,CAAC,KAAgB,EAAE,MAAiB,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YACjG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACnC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACnC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACtC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YACpC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,KAAK,IAAI,EAAE;YAClB,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,yDAAyD,EAAE,GAAG,EAAE;YACvE,IAAI,MAAwB,CAAC;YAC7B,IAAI,IAA0D,CAAC;YAE/D,SAAS,CAAC,KAAK,IAAI,EAAE;gBACnB,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC9E,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;gBACtD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACtE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,wBAAwB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;YAC5F,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;gBACnE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACzC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACjC,IAAI,EAAE,EAAE,IAAI,KAAK,SAAS;oBAAE,OAAO;gBACnC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,yBAAyB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzE,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACrD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACxC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACzC,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;gBAClF,KAAK,MAAM,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;oBACzD,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC7F,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;gBAClG,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAC3B,UAAU,EACV,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CACtB,CAAC;gBACF,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;gBAC9C,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;oBACnB,OAAO,EAAE,cAAc,MAAM,CAAC,EAAE,EAAE;oBAClC,QAAQ,EAAE,kBAAkB;oBAC5B,MAAM,EAAE,UAAU;iBACnB,CAAC,CAAC;gBACH,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC;oBAC/B,OAAO,EAAE,cAAc,MAAM,CAAC,EAAE,EAAE;oBAClC,QAAQ,EAAE,WAAW;oBACrB,MAAM,EAAE,aAAa,KAAK,EAAE;iBAC7B,CAAC,CAAC;gBACH,iCAAiC;gBACjC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;gBACjG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YACrG,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,wFAAwF,EAAE,KAAK,IAAI,EAAE;gBACtG,KAAK,MAAM,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;oBAC9C,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;oBAC/D,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;gBACrD,CAAC;gBACD,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC,MAAM,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAC7D,CAAC;gBACF,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,IAAI,CAAC,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACxG,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;gBACxE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBACtF,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;gBACnD,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAC;gBAC7B,MAAM,CAAC,IAAI,CAAC,CAAC,cAAc,CACzB,MAAM,CAAC,gBAAgB,CAAC;oBACtB,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;oBAChD,UAAU,EAAE,WAAW;oBACvB,SAAS,EAAE,aAAa;iBACzB,CAAC,CACH,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;gBACnF,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;gBACvD,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;gBACnD,oFAAoF;gBACpF,MAAM,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;YACzF,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;gBAC5E,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1D,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,uFAAuF,EAAE,KAAK,IAAI,EAAE;gBACrG,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC7C,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC/D,MAAM,CAAC,WAAW,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC5F,iBAAiB,CAClB,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,qFAAqF,EAAE,KAAK,IAAI,EAAE;gBACnG,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;YACvD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,kEAAkE,EAAE,GAAG,EAAE;YAChF,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;gBACvF,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;gBACzF,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;gBACnD,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC9E,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;YACpD,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;gBACjF,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAY,UAAU,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;gBACxG,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;gBACvF,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAY,UAAU,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;gBACvG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7B,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;gBACrD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC1F,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,gGAAgG,EAAE,KAAK,IAAI,EAAE;gBAC9G,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;gBACtC,MAAM,IAAI,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC;gBAC1F,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBACzC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAClF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACzC,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACnF,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBAC3C,MAAM,CAAC,WAAW,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACrF,mBAAmB,CACpB,CAAC;gBACF,mEAAmE;gBACnE,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBACzC,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;YACrF,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,qFAAqF,EAAE,KAAK,IAAI,EAAE;gBACnG,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC5E,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAqB,WAAW,CAAC,CAAC;gBAC9E,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;gBAChE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrE,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;gBACxE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE;oBAChC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC;oBACnB,WAAW,EAAE,CAAC,QAAQ,CAAC;iBACxB,CAAC,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACzC,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;gBACtG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC7C,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,mDAAmD,EAAE,GAAG,EAAE;YACjE,EAAE,CAAC,0FAA0F,EAAE,KAAK,IAAI,EAAE;gBACxG,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBACpF,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAClF,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC/C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC3C,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAE3F,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;gBAEjE,MAAM,CAAC,WAAW,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC7F,iBAAiB,CAClB,CAAC;gBACF,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;gBACjD,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;YAC3F,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;gBACvD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBACpF,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;gBACjE,MAAM,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;oBACxF,OAAO,EAAE,IAAI;iBACd,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;gBACnE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;gBACrF,iDAAiD;gBACjD,MAAM,CAAC,WAAW,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC/F,mBAAmB,CACpB,CAAC;gBACF,MAAM,CAAC,WAAW,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACjG,mBAAmB,CACpB,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,qFAAqF,EAAE,KAAK,IAAI,EAAE;gBACnG,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;gBAChG,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;gBACpF,MAAM,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC/B,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;gBACjD,sEAAsE;gBACtE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC3B,MAAM,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACtF,CAAC;gBACD,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAY,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;qBAC9F,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;qBACrC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;gBACrC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;gBAClF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;gBAChG,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBAC5F,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC5D,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,+FAA+F,EAAE,KAAK,IAAI,EAAE;gBAC7G,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE;oBAChC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC;oBACnB,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;oBAClC,UAAU,EAAE,CAAC,UAAU,CAAC;iBACzB,CAAC,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACzC,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACnF,MAAM,CAAC,WAAW,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAChG,WAAW,CACZ,CAAC;gBACF,+EAA+E;gBAC/E,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;gBACpG,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC/B,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;gBAC3F,MAAM,GAAG,GAAG,MAAM,OAAO,CACvB,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAC/F,CAAC;gBACF,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;gBAC1E,MAAM,GAAG,GAAG,MAAM,OAAO,CACvB,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,0BAA0B,EAAE,CAAC,CACtG,CAAC;gBACF,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;gBAC5F,MAAM,CAAC,MAAM,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAClD,MAAM,CAAC,MAAM,QAAQ,CAAC,GAAG,wBAAwB,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;YACpF,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,6DAA6D,EAAE,GAAG,EAAE;YAC3E,EAAE,CAAC,sGAAsG,EAAE,KAAK,IAAI,EAAE;gBACpH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;gBAC/F,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACzC,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;gBACzE,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,EAAE,CAAC;qBACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC;qBACjE,GAAG,EAAG,CAAC;gBACV,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;gBACjE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAc,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;gBACjG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC5C,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,qGAAqG,EAAE,KAAK,IAAI,EAAE;gBACnH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBACpF,MAAM,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC/B,MAAM,IAAI,GAAG,MAAM,MAAM,EAAE,CAAC;gBAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CACpB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,mBAAmB,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAQ,CAAC,CAAC,YAAY,KAAK,MAAM,CAAC,EAAE,CAC1F,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC3C,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACxC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACjC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CACzB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,sBAAsB,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAQ,CAAC,CAAC,YAAY,KAAK,MAAM,CAAC,EAAE,CAC7F,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;gBACvE,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;gBAC1D,uFAAuF;gBACvF,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAY,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;qBAC1G,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;qBACrC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;gBACrC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;gBACvD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC/E,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;oBAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACpF,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;gBACvD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBACpF,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;gBACjE,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,oBAAoB,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAQ,CAAC,CAAC,YAAY,KAAK,MAAM,CAAC,EAAE,CAC3F,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC5C,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,uEAAuE,EAAE,GAAG,EAAE;YACrF,EAAE,CAAC,2FAA2F,EAAE,KAAK,IAAI,EAAE;gBACzG,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;gBAC/F,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC7C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC1D,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACrE,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;gBAC5B,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACpD,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAChD,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBACxC,2DAA2D;gBAC3D,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,SAAS,CAAC,MAAM,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC1F,MAAM,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC,SAAS,CAAC,MAAM,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3F,CAAC,CAAC,CAAC;YAEH,mFAAmF;YACnF,mFAAmF;YACnF,qFAAqF;YACrF,iEAAiE;YACjE,MAAM,QAAQ,GAAG,KAAK,EAAE,KAAa,EAAE,EAAE,CACvC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAY,UAAU,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;iBAC1F,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;iBACrC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;YACpC,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;gBACpC,EAAE,CAAC,0BAA0B,GAAG,+CAA+C,EAAE,KAAK,IAAI,EAAE;oBAC1F,MAAM,KAAK,GAAG,QAAQ,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;oBACtC,MAAM,GAAG,GAAG,MAAM,OAAO,CACvB,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,oBAAoB,EAAE;wBAC7C,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC;wBACnB,WAAW,EAAE,CAAC,QAAQ,CAAC;wBACvB,KAAK;wBACL,GAAG;qBACJ,CAAC,CACH,CAAC;oBACF,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;oBAC3C,MAAM,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC5C,CAAC,CAAC,CAAC;gBAEH,EAAE,CAAC,gCAAgC,GAAG,gCAAgC,EAAE,KAAK,IAAI,EAAE;oBACjF,MAAM,KAAK,GAAG,SAAS,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;oBACvC,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,oBAAoB,EAAE;wBACnD,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC;wBACnB,WAAW,EAAE,CAAC,QAAQ,CAAC;wBACvB,KAAK;wBACL,GAAG;wBACH,IAAI,EAAE,KAAK;qBACZ,CAAC,CAAC;oBACH,MAAM,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC3C,CAAC,CAAC,CAAC;YACL,CAAC;YAED,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;gBAClG,MAAM,GAAG,GAAG,QAAQ,IAAI,EAAE,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;gBAC3E,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;gBAC7B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAA+B,gBAAgB,EAAE,KAAK,EAAE;oBACrF,cAAc,EAAE,GAAG;iBACpB,CAAC,CAAC;gBACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,UAAU,wBAAwB,EAAE,CAAC,CAAC,CAAC;gBAC7E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAA+B,gBAAgB,EAAE,KAAK,EAAE;oBACtF,cAAc,EAAE,GAAG;iBACpB,CAAC,CAAC;gBACH,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBACjC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,+BAA+B,eAAe,EAAE,CAAC,CAAC;gBAC3E,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAE,CAAC;gBAC/C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBACrE,6DAA6D;gBAC7D,MAAM,CAAC,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;YACvB,EAAE,CAAC,kFAAkF,EAAE,KAAK,IAAI,EAAE;gBAChG,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;gBAClG,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;gBAClG,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAY,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC/F,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC5D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC/B,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACnC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAY,UAAU,EAAE;oBACjE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC;oBACpB,cAAc,EAAE,IAAI;iBACrB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC1C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACjE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACxC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YACrE,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;YACnE,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;gBACtF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;oBAC5D,SAAS,EAAE,IAAI;oBACf,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC;oBAC3B,OAAO,EAAE,CAAC;oBACV,KAAK,EAAE,OAAO;iBACf,CAAC,CAAC;gBACH,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACzC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACpF,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;gBACjD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CACpB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,gBAAgB,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CACpF,CAAC;gBACF,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACzD,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBACpF,MAAM,SAAS,GAAG,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,IAAI,CACrC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,sBAAsB,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAQ,CAAC,CAAC,YAAY,KAAK,MAAM,CAAC,EAAE,CAC7F,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;gBACvE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5F,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;gBAClG,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;oBAC5D,SAAS,EAAE,IAAI;oBACf,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC;oBAC3B,OAAO,EAAE,CAAC;iBACX,CAAC,CAAC;gBACH,MAAM,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;gBACzF,8DAA8D;gBAC9D,MAAM,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;oBACvF,IAAI,EAAE,WAAW;oBACjB,YAAY,EAAE,MAAM,CAAC,EAAE;oBACvB,SAAS,EAAE,IAAI;iBAChB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;gBAC1E,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC9F,MAAM,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAC1F,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtG,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;gBAC3D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;oBAC5D,SAAS,EAAE,IAAI;oBACf,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC;oBAC3B,OAAO,EAAE,CAAC;iBACX,CAAC,CAAC;gBACH,MAAM,CAAC,WAAW,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACjG,WAAW,CACZ,CAAC;gBACF,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;gBAC5D,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;YACnD,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;gBAC7F,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBACpF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACzC,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;gBAC5D,MAAM,CAAC,WAAW,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACvF,iBAAiB,CAClB,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;gBACrF,MAAM,CACJ,WAAW,CACT,MAAM,OAAO,CACX,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;oBACvC,SAAS,EAAE,IAAI;oBACf,SAAS,EAAE,0BAAqC;oBAChD,OAAO,EAAE,CAAC;iBACX,CAAC,CACH,CACF,CACF,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;gBAC5B,MAAM,CACJ,WAAW,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAW,CAAC,CAAC,CAAC,CACxF,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
package/dist/index.d.ts CHANGED
@@ -3,6 +3,9 @@ export type { ScopeHostFixture, ScopeHostSuiteOptions } from './scope-host-suite
3
3
  export { permissionContractSuite } from './permission-suite.js';
4
4
  export { atomicContractSuite } from './atomic-suite.js';
5
5
  export { impersonationContractSuite } from './impersonation-suite.js';
6
+ export { capabilityContractSuite } from './capability-suite.js';
7
+ export { capabilityExpiryContractSuite } from './capability-expiry-suite.js';
8
+ export type { CapabilityExpiryFixture } from './capability-expiry-suite.js';
6
9
  export { searchContractSuite } from './search-suite.js';
7
10
  export { entityVersionContractSuite } from './entity-version-suite.js';
8
11
  export { timelineContractSuite } from './timeline-suite.js';
@@ -10,6 +13,8 @@ export { concurrencyContractSuite } from './concurrency-suite.js';
10
13
  export { idempotencyContractSuite } from './idempotency-suite.js';
11
14
  export { listContractSuite } from './list-suite.js';
12
15
  export { scheduleContractSuite } from './schedule-suite.js';
16
+ export { jobRunContractSuite } from './job-run-suite.js';
17
+ export { systemSwitchContractSuite } from './system-switch-suite.js';
13
18
  export { inputParseContractSuite } from './input-parse-suite.js';
14
19
  export { spineGuardContractSuite } from './spine-guard-suite.js';
15
20
  export { grantExpiryContractSuite } from './grant-expiry-suite.js';
@@ -21,6 +26,6 @@ export { nodeOnlySuite, declaredNodeOnlySuite } from './node-only-suite.js';
21
26
  export type { NodeOnlyOptions } from './node-only-suite.js';
22
27
  export { declareEntityChecks, declareNodeOnly, assertNodeOnly } from './conformance.js';
23
28
  export type { ConformanceDeclaration, DrivenConformance, DeclaredNodeOnlyConformance, AssertedNodeOnlyConformance, } from './conformance.js';
24
- export { atomicMod, billedMod, brokenMod, connectorMod, contractTestBareOps, contractTestInitialModules, contractTestModules, permMod, scheduleMod, testMod, freshnessMod, searchMod, searchModManifest, listMod, listModManifest, parseMod, parseModManifest, } from './modules.js';
29
+ export { atomicMod, billedMod, brokenMod, connectorMod, contractTestBareOps, contractTestInitialModules, contractTestModules, liveMod, liveModManifest, permMod, capMod, capModManifest, scheduleMod, jobsMod, testMod, freshnessMod, searchMod, searchModManifest, listMod, listModManifest, parseMod, parseModManifest, } from './modules.js';
25
30
  export { connectorCalls, connectorTestFetch, resetConnectorCalls, type ConnectorCall, } from './connector-fixture.js';
26
31
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,KAAK,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/F,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC/F,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACzG,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACxF,YAAY,EACV,sBAAsB,EACtB,iBAAiB,EACjB,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,EACnB,OAAO,EACP,WAAW,EACX,OAAO,EACP,YAAY,EACZ,SAAS,EACT,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAC7E,YAAY,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,KAAK,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/F,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC/F,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACzG,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACxF,YAAY,EACV,sBAAsB,EACtB,iBAAiB,EACjB,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,EACnB,OAAO,EACP,eAAe,EACf,OAAO,EACP,MAAM,EACN,cAAc,EACd,WAAW,EACX,OAAO,EACP,OAAO,EACP,YAAY,EACZ,SAAS,EACT,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC"}