@substrat-run/engine-protocol 0.3.5 → 0.4.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.
- package/README.md +12 -7
- package/dist/index.d.ts +323 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +863 -100
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
# @substrat-run/engine-protocol
|
|
2
2
|
|
|
3
3
|
Protocol engine for [Substrat](https://github.com/substrat-run/substrat) —
|
|
4
|
-
checklists/protocols (self-inspection, condition reports, inspection records)
|
|
5
|
-
**
|
|
6
|
-
verifiable content hash, and counter-signatures on frozen content.
|
|
4
|
+
checklists/protocols (self-inspection, condition reports, inspection records) **and signed
|
|
5
|
+
documents** (avtal, reports) with the **freeze → immutable** invariant: versioned templates,
|
|
6
|
+
append-only responses, a verifiable content hash, and counter-signatures on frozen content.
|
|
7
7
|
|
|
8
8
|
The engine owns only the invariants. Template *content* — which protocols exist and
|
|
9
9
|
what they contain — is 100% vertical-owned, and an instance binds to any `EntityRef`
|
|
10
|
-
(a work order today, anything tomorrow).
|
|
10
|
+
(a work order today, anything tomorrow). Content comes in two kinds: a `checklist` of
|
|
11
|
+
sections and items, or an opaque `document` whose bytes live in the vertical and whose hash
|
|
12
|
+
is all the engine holds.
|
|
11
13
|
|
|
12
14
|
## What it owns
|
|
13
15
|
|
|
14
|
-
1. **
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
1. **Freeze freezes** — any write to a frozen instance's content fails. Freezing happens at
|
|
17
|
+
an in-app signature, or at dispatch when a document goes out for external signature.
|
|
18
|
+
2. **Content hash** — SHA-256 over template content plus the frozen content, verifiable
|
|
19
|
+
against replayed state. One recipe per content kind.
|
|
17
20
|
3. **Counter-sign** — a second signature on the *same* frozen content; the hash is
|
|
18
21
|
recomputed and must match.
|
|
19
22
|
4. **Append-only responses** — an edit is a new row; history is audit material.
|
|
20
23
|
5. **Version-pinned templates** — an instance pins `(key, version)` at instantiation forever.
|
|
21
24
|
6. **Void, not delete** — a protocol is superseded, never mutated or removed.
|
|
25
|
+
7. **Signatures name a signatory** — a principal, or an **external person with no account**
|
|
26
|
+
(BankID via Scrive), recorded at the provider's timestamp with an evidence reference.
|
|
22
27
|
|
|
23
28
|
## Install
|
|
24
29
|
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ import { type GuardPredicate, type ModuleRegistration, type OperationContext } f
|
|
|
4
4
|
export declare const PROTOCOL_PERM: {
|
|
5
5
|
create: string & z.core.$brand<"PermissionKey">;
|
|
6
6
|
fill: string & z.core.$brand<"PermissionKey">;
|
|
7
|
+
bind: string & z.core.$brand<"PermissionKey">;
|
|
8
|
+
requestSignature: string & z.core.$brand<"PermissionKey">;
|
|
9
|
+
recordSignature: string & z.core.$brand<"PermissionKey">;
|
|
7
10
|
sign: string & z.core.$brand<"PermissionKey">;
|
|
8
11
|
countersign: string & z.core.$brand<"PermissionKey">;
|
|
9
12
|
read: string & z.core.$brand<"PermissionKey">;
|
|
@@ -94,7 +97,9 @@ export declare const protocolItem: z.ZodObject<{
|
|
|
94
97
|
unit: z.ZodOptional<z.ZodString>;
|
|
95
98
|
}, z.core.$strip>;
|
|
96
99
|
export type ProtocolItem = z.infer<typeof protocolItem>;
|
|
97
|
-
|
|
100
|
+
/** The original shape: sections of items, filled response-by-response. */
|
|
101
|
+
export declare const checklistContent: z.ZodObject<{
|
|
102
|
+
kind: z.ZodLiteral<"checklist">;
|
|
98
103
|
sections: z.ZodArray<z.ZodObject<{
|
|
99
104
|
title: z.ZodString;
|
|
100
105
|
items: z.ZodArray<z.ZodObject<{
|
|
@@ -109,7 +114,106 @@ export declare const protocolTemplateContent: z.ZodObject<{
|
|
|
109
114
|
}, z.core.$strip>>;
|
|
110
115
|
}, z.core.$strip>>;
|
|
111
116
|
}, z.core.$strip>;
|
|
112
|
-
export type
|
|
117
|
+
export type ChecklistContent = z.infer<typeof checklistContent>;
|
|
118
|
+
/**
|
|
119
|
+
* Content the engine never sees. The template says what KIND of document this
|
|
120
|
+
* is and how to render it; the instance carries the vertical's `EntityRef` and
|
|
121
|
+
* the hash the vertical computed over its own rows.
|
|
122
|
+
*
|
|
123
|
+
* `hashRecipe` is free text, and it is the load-bearing honesty of this kind:
|
|
124
|
+
* a document signature attests to a hash the engine did not compute, so the
|
|
125
|
+
* recipe for reproducing it must be written down where an auditor reading the
|
|
126
|
+
* template finds it. The engine cannot enforce that the text is true — but a
|
|
127
|
+
* signature over an unreproducible hash is worth nothing, and a required field
|
|
128
|
+
* is what makes the vertical say out loud how to reproduce it.
|
|
129
|
+
*/
|
|
130
|
+
export declare const documentContent: z.ZodObject<{
|
|
131
|
+
kind: z.ZodLiteral<"document">;
|
|
132
|
+
documentType: z.ZodString;
|
|
133
|
+
hashRecipe: z.ZodString;
|
|
134
|
+
description: z.ZodOptional<z.ZodString>;
|
|
135
|
+
}, z.core.$strip>;
|
|
136
|
+
export type DocumentContent = z.infer<typeof documentContent>;
|
|
137
|
+
declare const contentUnion: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
138
|
+
kind: z.ZodLiteral<"checklist">;
|
|
139
|
+
sections: z.ZodArray<z.ZodObject<{
|
|
140
|
+
title: z.ZodString;
|
|
141
|
+
items: z.ZodArray<z.ZodObject<{
|
|
142
|
+
key: z.ZodString;
|
|
143
|
+
label: z.ZodString;
|
|
144
|
+
type: z.ZodEnum<{
|
|
145
|
+
check: "check";
|
|
146
|
+
value: "value";
|
|
147
|
+
text: "text";
|
|
148
|
+
}>;
|
|
149
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
150
|
+
}, z.core.$strip>>;
|
|
151
|
+
}, z.core.$strip>>;
|
|
152
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
153
|
+
kind: z.ZodLiteral<"document">;
|
|
154
|
+
documentType: z.ZodString;
|
|
155
|
+
hashRecipe: z.ZodString;
|
|
156
|
+
description: z.ZodOptional<z.ZodString>;
|
|
157
|
+
}, z.core.$strip>], "kind">;
|
|
158
|
+
/**
|
|
159
|
+
* Parses either kind, defaulting a missing discriminant to 'checklist' so
|
|
160
|
+
* every template defined before milestone D still parses. Note this is a
|
|
161
|
+
* READ-time normalisation: `defineTemplate` stores what it is given after
|
|
162
|
+
* parsing, so new templates carry an explicit `kind`, and old rows keep their
|
|
163
|
+
* bytes (and therefore their hashes) exactly as signed.
|
|
164
|
+
*/
|
|
165
|
+
export declare const protocolTemplateContent: z.ZodPreprocess<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
166
|
+
kind: z.ZodLiteral<"checklist">;
|
|
167
|
+
sections: z.ZodArray<z.ZodObject<{
|
|
168
|
+
title: z.ZodString;
|
|
169
|
+
items: z.ZodArray<z.ZodObject<{
|
|
170
|
+
key: z.ZodString;
|
|
171
|
+
label: z.ZodString;
|
|
172
|
+
type: z.ZodEnum<{
|
|
173
|
+
check: "check";
|
|
174
|
+
value: "value";
|
|
175
|
+
text: "text";
|
|
176
|
+
}>;
|
|
177
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
178
|
+
}, z.core.$strip>>;
|
|
179
|
+
}, z.core.$strip>>;
|
|
180
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
181
|
+
kind: z.ZodLiteral<"document">;
|
|
182
|
+
documentType: z.ZodString;
|
|
183
|
+
hashRecipe: z.ZodString;
|
|
184
|
+
description: z.ZodOptional<z.ZodString>;
|
|
185
|
+
}, z.core.$strip>], "kind">>;
|
|
186
|
+
export type ProtocolTemplateContent = z.infer<typeof contentUnion>;
|
|
187
|
+
/**
|
|
188
|
+
* Who signed. Two kinds, and the difference is the whole point of milestone D:
|
|
189
|
+
*
|
|
190
|
+
* - `principal` — an authenticated principal in this scope. `ref` is their
|
|
191
|
+
* `PrincipalId`. Every in-app signature.
|
|
192
|
+
* - `external` — a human with no account, identified by an external provider
|
|
193
|
+
* (BankID via Scrive). `ref` is an OPAQUE `DataSubjectId` the vertical minted
|
|
194
|
+
* for that person.
|
|
195
|
+
*
|
|
196
|
+
* A personnummer, an email or a name must NEVER land in `ref`. It is `direct`
|
|
197
|
+
* PII, and `subjectId` on the emitted event is what crypto-shredding keys the
|
|
198
|
+
* erasure on (§5.3) — a `DataSubjectId` is shreddable, a personnummer written
|
|
199
|
+
* into a signature row is a GDPR liability that immutability makes permanent.
|
|
200
|
+
* The provider's own party identifier belongs in `evidenceRef`, which is where
|
|
201
|
+
* the sealed PDF and the provider audit log are reachable from.
|
|
202
|
+
*
|
|
203
|
+
* This follows `engines/booking`'s `partyRef`: a participant is a person with
|
|
204
|
+
* no principal, and it names them with a `DataSubjectId` for exactly this
|
|
205
|
+
* reason.
|
|
206
|
+
*/
|
|
207
|
+
export declare const signatory: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
208
|
+
kind: z.ZodLiteral<"principal">;
|
|
209
|
+
ref: z.core.$ZodBranded<z.ZodString, "PrincipalId", "out">;
|
|
210
|
+
label: z.ZodOptional<z.ZodString>;
|
|
211
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
212
|
+
kind: z.ZodLiteral<"external">;
|
|
213
|
+
ref: z.core.$ZodBranded<z.ZodString, "DataSubjectId", "out">;
|
|
214
|
+
label: z.ZodOptional<z.ZodString>;
|
|
215
|
+
}, z.core.$strip>], "kind">;
|
|
216
|
+
export type Signatory = z.infer<typeof signatory>;
|
|
113
217
|
export interface ProtocolTemplateRow {
|
|
114
218
|
id: string;
|
|
115
219
|
key: string;
|
|
@@ -124,12 +228,20 @@ export interface ProtocolInstanceRow {
|
|
|
124
228
|
template_version: number;
|
|
125
229
|
entity_type: string;
|
|
126
230
|
entity_id: string;
|
|
127
|
-
status: 'open' | 'signed' | 'voided';
|
|
231
|
+
status: 'open' | 'pending_signature' | 'signed' | 'voided';
|
|
128
232
|
created_by: string;
|
|
129
233
|
created_at: string;
|
|
130
234
|
voided_by: string | null;
|
|
131
235
|
voided_reason: string | null;
|
|
132
236
|
voided_at: string | null;
|
|
237
|
+
/** Document kind: the vertical entity holding the real content. */
|
|
238
|
+
content_ref_type: string | null;
|
|
239
|
+
content_ref_id: string | null;
|
|
240
|
+
/** Document kind: the hash the VERTICAL computed over its own rows. */
|
|
241
|
+
bound_hash: string | null;
|
|
242
|
+
/** Set when content freezes — the hash every signature must match. */
|
|
243
|
+
frozen_hash: string | null;
|
|
244
|
+
frozen_at: string | null;
|
|
133
245
|
}
|
|
134
246
|
export interface ProtocolResponseRow {
|
|
135
247
|
id: string;
|
|
@@ -143,22 +255,50 @@ export interface ProtocolResponseRow {
|
|
|
143
255
|
export interface ProtocolSignatureRow {
|
|
144
256
|
id: string;
|
|
145
257
|
instance_id: string;
|
|
258
|
+
/** The signatory reference: a `PrincipalId`, or an opaque `DataSubjectId`. */
|
|
146
259
|
signed_by: string;
|
|
147
260
|
kind: 'primary' | 'counter';
|
|
148
261
|
method: string;
|
|
149
262
|
content_hash: string;
|
|
150
263
|
evidence_ref: string | null;
|
|
151
264
|
signed_at: string;
|
|
265
|
+
request_id: string | null;
|
|
266
|
+
signatory_kind: 'principal' | 'external';
|
|
267
|
+
signatory_label: string | null;
|
|
152
268
|
}
|
|
153
|
-
export
|
|
269
|
+
export interface ProtocolSignatureRequestRow {
|
|
270
|
+
id: string;
|
|
271
|
+
instance_id: string;
|
|
272
|
+
party_label: string;
|
|
273
|
+
party_kind: 'principal' | 'external';
|
|
274
|
+
party_ref: string | null;
|
|
275
|
+
signature_kind: 'primary' | 'counter';
|
|
276
|
+
method: string;
|
|
277
|
+
status: 'pending' | 'signed' | 'declined' | 'expired' | 'cancelled';
|
|
278
|
+
content_hash: string;
|
|
279
|
+
external_ref: string | null;
|
|
280
|
+
resolved_note: string | null;
|
|
281
|
+
requested_by: string;
|
|
282
|
+
requested_at: string;
|
|
283
|
+
resolved_at: string | null;
|
|
284
|
+
}
|
|
285
|
+
export declare function protocolContentHash(template: Pick<ProtocolTemplateRow, 'key' | 'version' | 'content_json'>, latest: Record<string, ProtocolResponseRow>, boundHash?: string | null): Promise<string>;
|
|
154
286
|
export declare function requireSigned(ctx: OperationContext, entity: EntityRef, templateKey: string): void;
|
|
155
287
|
/**
|
|
156
288
|
* The stronger form: signed AND counter-signed — the frozen content was
|
|
157
|
-
* ACCEPTED by a second
|
|
289
|
+
* ACCEPTED by a second signatory (the customer at pickup). Invariant 3 already
|
|
158
290
|
* guarantees a counter-signature can only exist on verified frozen content, so
|
|
159
291
|
* the existence of the row is the whole check.
|
|
160
292
|
*/
|
|
161
293
|
export declare function requireCountersigned(ctx: OperationContext, entity: EntityRef, templateKey: string): void;
|
|
294
|
+
/**
|
|
295
|
+
* NOTE on multi-party: there is deliberately no `requireAllSigned`. In the
|
|
296
|
+
* request-driven path an instance reaches `signed` only once EVERY requested
|
|
297
|
+
* party has signed (see `recordSignature`), so "all parties signed" IS
|
|
298
|
+
* `requireSigned` — a separate guard would read as though it checked something
|
|
299
|
+
* stronger while checking the same thing. The multi-party question is answered
|
|
300
|
+
* by the state machine, not by a second predicate.
|
|
301
|
+
*/
|
|
162
302
|
/**
|
|
163
303
|
* Config for the `protocol/all-signed` predicate — parsed by the PREDICATE, not
|
|
164
304
|
* by the kernel (the kernel keeps `config` opaque). `entityIdFrom` names the
|
|
@@ -178,7 +318,8 @@ export declare const allSignedPredicate: GuardPredicate;
|
|
|
178
318
|
export declare const defineTemplateInput: z.ZodObject<{
|
|
179
319
|
key: z.ZodString;
|
|
180
320
|
title: z.ZodString;
|
|
181
|
-
content: z.ZodObject<{
|
|
321
|
+
content: z.ZodPreprocess<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
322
|
+
kind: z.ZodLiteral<"checklist">;
|
|
182
323
|
sections: z.ZodArray<z.ZodObject<{
|
|
183
324
|
title: z.ZodString;
|
|
184
325
|
items: z.ZodArray<z.ZodObject<{
|
|
@@ -192,9 +333,28 @@ export declare const defineTemplateInput: z.ZodObject<{
|
|
|
192
333
|
unit: z.ZodOptional<z.ZodString>;
|
|
193
334
|
}, z.core.$strip>>;
|
|
194
335
|
}, z.core.$strip>>;
|
|
195
|
-
}, z.core.$strip
|
|
336
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
337
|
+
kind: z.ZodLiteral<"document">;
|
|
338
|
+
documentType: z.ZodString;
|
|
339
|
+
hashRecipe: z.ZodString;
|
|
340
|
+
description: z.ZodOptional<z.ZodString>;
|
|
341
|
+
}, z.core.$strip>], "kind">>;
|
|
196
342
|
}, z.core.$strip>;
|
|
197
|
-
|
|
343
|
+
/**
|
|
344
|
+
* What a template author writes. Spelled out rather than inferred because the
|
|
345
|
+
* `kind` normalisation is a `z.preprocess`, whose inferred INPUT type is
|
|
346
|
+
* `unknown` — which would silently drop type-checking on exactly the object a
|
|
347
|
+
* vertical hand-writes most often. `kind` is optional only for checklists, so
|
|
348
|
+
* every template that predates the discriminant still compiles unchanged.
|
|
349
|
+
*/
|
|
350
|
+
export type ProtocolTemplateContentInput = (Omit<ChecklistContent, 'kind'> & {
|
|
351
|
+
kind?: 'checklist';
|
|
352
|
+
}) | DocumentContent;
|
|
353
|
+
export interface DefineTemplateInput {
|
|
354
|
+
key: string;
|
|
355
|
+
title: string;
|
|
356
|
+
content: ProtocolTemplateContentInput;
|
|
357
|
+
}
|
|
198
358
|
/**
|
|
199
359
|
* Templates version immutably: same key + new content = next version, the
|
|
200
360
|
* old row is never touched. Editing a template never rewrites what a signed
|
|
@@ -225,16 +385,158 @@ export declare const fillProtocolInput: z.ZodObject<{
|
|
|
225
385
|
}, z.core.$strip>;
|
|
226
386
|
export type FillProtocolInput = z.infer<typeof fillProtocolInput>;
|
|
227
387
|
export declare function fillProtocol(ctx: OperationContext, rawInput: FillProtocolInput): ProtocolResponseRow;
|
|
388
|
+
export declare const bindDocumentInput: z.ZodObject<{
|
|
389
|
+
instanceId: z.ZodString;
|
|
390
|
+
contentRef: z.ZodObject<{
|
|
391
|
+
entityType: z.ZodString;
|
|
392
|
+
entityId: z.ZodString;
|
|
393
|
+
}, z.core.$strip>;
|
|
394
|
+
contentHash: z.ZodString;
|
|
395
|
+
}, z.core.$strip>;
|
|
396
|
+
export type BindDocumentInput = z.infer<typeof bindDocumentInput>;
|
|
397
|
+
/**
|
|
398
|
+
* Bind (or re-bind) a document protocol's content while it is still open —
|
|
399
|
+
* the document-kind counterpart of `fillProtocol`. Re-binding is the whole
|
|
400
|
+
* point during negotiation: an avtal's price changes until it is sent out, and
|
|
401
|
+
* each rebind moves the hash the signature will be taken over.
|
|
402
|
+
*
|
|
403
|
+
* Once frozen, this fails like any other write to frozen content.
|
|
404
|
+
*/
|
|
405
|
+
export declare function bindDocument(ctx: OperationContext, rawInput: BindDocumentInput): ProtocolInstanceRow;
|
|
406
|
+
export declare const signatureRequestParty: z.ZodObject<{
|
|
407
|
+
label: z.ZodString;
|
|
408
|
+
kind: z.ZodEnum<{
|
|
409
|
+
principal: "principal";
|
|
410
|
+
external: "external";
|
|
411
|
+
}>;
|
|
412
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
413
|
+
signatureKind: z.ZodOptional<z.ZodEnum<{
|
|
414
|
+
primary: "primary";
|
|
415
|
+
counter: "counter";
|
|
416
|
+
}>>;
|
|
417
|
+
}, z.core.$strip>;
|
|
418
|
+
export type SignatureRequestParty = z.input<typeof signatureRequestParty>;
|
|
419
|
+
export declare const requestSignaturesInput: z.ZodObject<{
|
|
420
|
+
instanceId: z.ZodString;
|
|
421
|
+
method: z.ZodString;
|
|
422
|
+
parties: z.ZodArray<z.ZodObject<{
|
|
423
|
+
label: z.ZodString;
|
|
424
|
+
kind: z.ZodEnum<{
|
|
425
|
+
principal: "principal";
|
|
426
|
+
external: "external";
|
|
427
|
+
}>;
|
|
428
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
429
|
+
signatureKind: z.ZodOptional<z.ZodEnum<{
|
|
430
|
+
primary: "primary";
|
|
431
|
+
counter: "counter";
|
|
432
|
+
}>>;
|
|
433
|
+
}, z.core.$strip>>;
|
|
434
|
+
}, z.core.$strip>;
|
|
435
|
+
export type RequestSignaturesInput = z.input<typeof requestSignaturesInput>;
|
|
436
|
+
export interface RequestSignaturesResult {
|
|
437
|
+
instance: ProtocolInstanceRow;
|
|
438
|
+
contentHash: string;
|
|
439
|
+
requests: ProtocolSignatureRequestRow[];
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Freeze the content and ask named parties to sign it — the asynchronous
|
|
443
|
+
* counterpart of `signProtocol`.
|
|
444
|
+
*
|
|
445
|
+
* This is the transition that closes the drift window: the instance leaves
|
|
446
|
+
* `open` immediately, so nothing can fill or rebind it while it sits at the
|
|
447
|
+
* provider. The hash is computed ONCE, here, and every signature that comes
|
|
448
|
+
* back must match it.
|
|
449
|
+
*
|
|
450
|
+
* The engine dispatches nothing. It emits `protocol.signatures-requested` with
|
|
451
|
+
* everything a connector needs (the hash, the parties, the method) and an
|
|
452
|
+
* executor outside the scope makes the call — module code never touches the
|
|
453
|
+
* network (boundary-lint R3).
|
|
454
|
+
*/
|
|
455
|
+
export declare function requestSignatures(ctx: OperationContext, rawInput: RequestSignaturesInput): Promise<RequestSignaturesResult>;
|
|
456
|
+
export declare const recordSignatureInput: z.ZodObject<{
|
|
457
|
+
requestId: z.ZodString;
|
|
458
|
+
signatory: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
459
|
+
kind: z.ZodLiteral<"principal">;
|
|
460
|
+
ref: z.core.$ZodBranded<z.ZodString, "PrincipalId", "out">;
|
|
461
|
+
label: z.ZodOptional<z.ZodString>;
|
|
462
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
463
|
+
kind: z.ZodLiteral<"external">;
|
|
464
|
+
ref: z.core.$ZodBranded<z.ZodString, "DataSubjectId", "out">;
|
|
465
|
+
label: z.ZodOptional<z.ZodString>;
|
|
466
|
+
}, z.core.$strip>], "kind">;
|
|
467
|
+
signedAt: z.core.$ZodBranded<z.ZodString, "Instant", "out">;
|
|
468
|
+
contentHash: z.ZodString;
|
|
469
|
+
evidenceRef: z.ZodOptional<z.ZodString>;
|
|
470
|
+
}, z.core.$strip>;
|
|
471
|
+
export type RecordSignatureInput = z.input<typeof recordSignatureInput>;
|
|
228
472
|
export interface SignResult {
|
|
229
473
|
instance: ProtocolInstanceRow;
|
|
230
474
|
signature: ProtocolSignatureRow;
|
|
231
475
|
}
|
|
232
476
|
/**
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
* the
|
|
477
|
+
* Record a signature that happened OUTSIDE this system — the webhook's half.
|
|
478
|
+
*
|
|
479
|
+
* Everything `signProtocol` takes from ambient context, this takes as data:
|
|
480
|
+
* the signatory is supplied (and may be an external person with no account),
|
|
481
|
+
* the timestamp is the provider's, the method is the request's, and the
|
|
482
|
+
* evidence reference points at the provider's sealed artifact.
|
|
483
|
+
*
|
|
484
|
+
* The last pending request resolving is what transitions the instance to
|
|
485
|
+
* `signed` — which is the multi-party rule stated in code: an avtal is signed
|
|
486
|
+
* when every requested party has signed it, not when the first one has.
|
|
487
|
+
*
|
|
488
|
+
* NOTE ON THE CALLER: there is no webhook ingress in the kernel yet, and no
|
|
489
|
+
* inbound authority seam that would let a provider callback invoke a scope
|
|
490
|
+
* operation (`ScopeHost.getScope` demands a `PrincipalId`; `ExecutorHandler`
|
|
491
|
+
* has no return path into a scope). Until those land this is reachable only by
|
|
492
|
+
* a principal holding `protocol:record-signature` — a key deliberately held by
|
|
493
|
+
* no human role in any demo.
|
|
494
|
+
*/
|
|
495
|
+
export declare function recordSignature(ctx: OperationContext, rawInput: RecordSignatureInput): Promise<SignResult>;
|
|
496
|
+
export declare const declineSignatureInput: z.ZodObject<{
|
|
497
|
+
requestId: z.ZodString;
|
|
498
|
+
reason: z.ZodString;
|
|
499
|
+
outcome: z.ZodDefault<z.ZodEnum<{
|
|
500
|
+
declined: "declined";
|
|
501
|
+
expired: "expired";
|
|
502
|
+
}>>;
|
|
503
|
+
}, z.core.$strip>;
|
|
504
|
+
export type DeclineSignatureInput = z.input<typeof declineSignatureInput>;
|
|
505
|
+
/**
|
|
506
|
+
* A party refused, or the provider's window expired. The instance stays
|
|
507
|
+
* `pending_signature` and therefore frozen — a refusal is not permission to
|
|
508
|
+
* edit. Renegotiating means cancelling the request set explicitly, which is a
|
|
509
|
+
* separate, permissioned, audited act.
|
|
510
|
+
*/
|
|
511
|
+
export declare function declineSignature(ctx: OperationContext, rawInput: DeclineSignatureInput): ProtocolSignatureRequestRow;
|
|
512
|
+
export declare const cancelSignatureRequestsInput: z.ZodObject<{
|
|
513
|
+
instanceId: z.ZodString;
|
|
514
|
+
reason: z.ZodString;
|
|
515
|
+
}, z.core.$strip>;
|
|
516
|
+
export type CancelSignatureRequestsInput = z.infer<typeof cancelSignatureRequestsInput>;
|
|
517
|
+
/**
|
|
518
|
+
* Withdraw an outstanding request set and thaw the instance — the
|
|
519
|
+
* renegotiation path an avtal needs when a party declines or the price moves.
|
|
520
|
+
*
|
|
521
|
+
* Cancelling THAWS: status returns to `open` and the frozen hash is cleared,
|
|
522
|
+
* so the next `requestSignatures` freezes fresh content at a fresh hash.
|
|
523
|
+
* Signatures already collected are NOT removed — they are append-only history
|
|
524
|
+
* attesting to content that really was frozen at the time — but they were
|
|
525
|
+
* taken over the OLD hash, so they can never satisfy the new one. That is the
|
|
526
|
+
* intended reading: a party who signed v1 has not signed v2.
|
|
527
|
+
*/
|
|
528
|
+
export declare function cancelSignatureRequests(ctx: OperationContext, rawInput: CancelSignatureRequestsInput): ProtocolInstanceRow;
|
|
529
|
+
/**
|
|
530
|
+
* In-app sign (engine-protocol.md §5): the authenticated principal signs, now;
|
|
531
|
+
* integrity comes from the hash + immutability + the spine event. Freezing and
|
|
532
|
+
* signing coincide here, which is sound precisely BECAUSE it is synchronous —
|
|
533
|
+
* there is no window between what the signer saw and what was hashed.
|
|
534
|
+
*
|
|
535
|
+
* For an external provider flow (BankID via Scrive) use `requestSignatures` +
|
|
536
|
+
* `recordSignature` instead: the signatory is not `ctx.principal`, the moment
|
|
537
|
+
* is not now, and freezing must happen at dispatch rather than at signature.
|
|
538
|
+
* Exactly ONE primary signature per instance — enforced by the open → signed
|
|
539
|
+
* transition.
|
|
238
540
|
*/
|
|
239
541
|
export declare function signProtocol(ctx: OperationContext, input: {
|
|
240
542
|
instanceId: string;
|
|
@@ -242,9 +544,9 @@ export declare function signProtocol(ctx: OperationContext, input: {
|
|
|
242
544
|
/**
|
|
243
545
|
* Counter-sign (invariant 3): a SECOND signature on the SAME frozen content —
|
|
244
546
|
* the customer at pickup. Requires a signed instance; the content hash is
|
|
245
|
-
* recomputed and must equal the
|
|
246
|
-
*
|
|
247
|
-
*
|
|
547
|
+
* recomputed and must equal the frozen hash (frozen content, verified, never
|
|
548
|
+
* assumed). One counter-signature per signatory; a signatory never
|
|
549
|
+
* counter-signs what they primary-signed.
|
|
248
550
|
*/
|
|
249
551
|
export declare function countersignProtocol(ctx: OperationContext, input: {
|
|
250
552
|
instanceId: string;
|
|
@@ -266,18 +568,23 @@ export interface ProtocolDetail {
|
|
|
266
568
|
latest: Record<string, ProtocolResponseRow>;
|
|
267
569
|
signature: ProtocolSignatureRow | null;
|
|
268
570
|
signatures: ProtocolSignatureRow[];
|
|
571
|
+
requests: ProtocolSignatureRequestRow[];
|
|
269
572
|
}
|
|
270
573
|
export declare function getProtocol(ctx: OperationContext, instanceId: string): ProtocolDetail;
|
|
271
574
|
export interface ProtocolSummary {
|
|
272
575
|
instance: ProtocolInstanceRow;
|
|
273
576
|
title: string;
|
|
577
|
+
contentKind: ProtocolTemplateContent['kind'];
|
|
274
578
|
answered: number;
|
|
275
579
|
total: number;
|
|
276
580
|
signedBy: string | null;
|
|
277
581
|
signedAt: string | null;
|
|
278
582
|
countersignedBy: string | null;
|
|
279
583
|
countersignedAt: string | null;
|
|
584
|
+
/** How many requested signatures are still outstanding. */
|
|
585
|
+
pendingSignatures: number;
|
|
280
586
|
}
|
|
281
587
|
export declare function listProtocolsForEntity(ctx: OperationContext, entity: EntityRef): ProtocolSummary[];
|
|
282
588
|
export declare const protocolModule: ModuleRegistration;
|
|
589
|
+
export {};
|
|
283
590
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EAEtB,MAAM,sBAAsB,CAAC;AAuF9B,eAAO,MAAM,aAAa;;;;;;;;;;CAUzB,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmC3B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;GA8K9B,CAAC;AAaF,eAAO,MAAM,YAAY;;;;;;;;;iBAKvB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAExD,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;iBAK3B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe;;;;;iBAO1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;2BAAoE,CAAC;AAEvF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;4BAMnC,CAAC;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAKnE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,SAAS;;;;;;;;2BAWpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mEAAmE;IACnE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,uEAAuE;IACvE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,sEAAsE;IACtE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,WAAW,GAAG,UAAU,CAAC;IACzC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,WAAW,GAAG,UAAU,CAAC;IACrC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,EAAE,SAAS,GAAG,SAAS,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,CAAC;IACpE,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA0GD,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,IAAI,CAAC,mBAAmB,EAAE,KAAK,GAAG,SAAS,GAAG,cAAc,CAAC,EACvE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC3C,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB,OAAO,CAAC,MAAM,CAAC,CAQjB;AA8DD,wBAAgB,aAAa,CAAC,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAajG;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,gBAAgB,EACrB,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,GAClB,IAAI,CAgBN;AAED;;;;;;;GAOG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;;;iBAK/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,sFAAsF;AACtF,eAAO,MAAM,kBAAkB,EAAE,cAShC,CAAC;AAQF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;iBAI9B,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,4BAA4B,GACpC,CAAC,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC,GACzD,eAAe,CAAC;AAEpB,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,4BAA4B,CAAC;CACvC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,mBAAmB,GAC5B,mBAAmB,CAgBrB;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CAM1E;AAED,eAAO,MAAM,wBAAwB;;;;;;iBAGnC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEhF;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,wBAAwB,GACjC,mBAAmB,CAuDrB;AAiBD,eAAO,MAAM,iBAAiB;;;;;iBAK5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,wBAAgB,YAAY,CAC1B,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,iBAAiB,GAC1B,mBAAmB,CA4DrB;AAED,eAAO,MAAM,iBAAiB;;;;;;;iBAM5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,iBAAiB,GAC1B,mBAAmB,CAmCrB;AAMD,eAAO,MAAM,qBAAqB;;;;;;;;;;;iBAwBhC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;iBAKjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,2BAA2B,EAAE,CAAC;CACzC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,sBAAsB,GAC/B,OAAO,CAAC,uBAAuB,CAAC,CAqFlC;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;iBAc/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,SAAS,EAAE,oBAAoB,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAAC,UAAU,CAAC,CA6FrB;AAED,eAAO,MAAM,qBAAqB;;;;;;;iBAKhC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,qBAAqB,GAC9B,2BAA2B,CAmC7B;AAED,eAAO,MAAM,4BAA4B;;;iBAGvC,CAAC;AACH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAExF;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,4BAA4B,GACrC,mBAAmB,CAkCrB;AAwED;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GAC5B,OAAO,CAAC,UAAU,CAAC,CA6BrB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GAC5B,OAAO,CAAC,UAAU,CAAC,CAoCrB;AAED,2EAA2E;AAC3E,wBAAgB,YAAY,CAC1B,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5C,mBAAmB,CAiCrB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,uBAAuB,CAAA;KAAE,CAAC;IAC5F,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC5C,SAAS,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACvC,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,QAAQ,EAAE,2BAA2B,EAAE,CAAC;CACzC;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,GAAG,cAAc,CAmBrF;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,2DAA2D;IAC3D,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAS,GAAG,eAAe,EAAE,CA0ClG;AA+GD,eAAO,MAAM,cAAc,EAAE,kBAyB5B,CAAC"}
|