@agirails/sdk 4.4.8 → 4.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builders/DeliveryProofBuilder.d.ts +224 -13
- package/dist/builders/DeliveryProofBuilder.d.ts.map +1 -1
- package/dist/builders/DeliveryProofBuilder.js +247 -13
- package/dist/builders/DeliveryProofBuilder.js.map +1 -1
- package/dist/cli/agirails.d.ts +85 -1
- package/dist/cli/agirails.d.ts.map +1 -1
- package/dist/cli/agirails.js +429 -154
- package/dist/cli/agirails.js.map +1 -1
- package/dist/cli/commands/init.d.ts +54 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +193 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/receipt.d.ts +70 -2
- package/dist/cli/commands/receipt.d.ts.map +1 -1
- package/dist/cli/commands/receipt.js +218 -3
- package/dist/cli/commands/receipt.js.map +1 -1
- package/dist/cli/commands/test.d.ts +77 -1
- package/dist/cli/commands/test.d.ts.map +1 -1
- package/dist/cli/commands/test.js +264 -2
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/lib/runRequest.d.ts +90 -0
- package/dist/cli/lib/runRequest.d.ts.map +1 -1
- package/dist/cli/lib/runRequest.js +300 -9
- package/dist/cli/lib/runRequest.js.map +1 -1
- package/dist/cli/lib/sentinelReflections.d.ts +111 -0
- package/dist/cli/lib/sentinelReflections.d.ts.map +1 -0
- package/dist/cli/lib/sentinelReflections.js +193 -0
- package/dist/cli/lib/sentinelReflections.js.map +1 -0
- package/dist/delivery/MockDeliveryChannel.d.ts +208 -0
- package/dist/delivery/MockDeliveryChannel.d.ts.map +1 -0
- package/dist/delivery/MockDeliveryChannel.js +445 -0
- package/dist/delivery/MockDeliveryChannel.js.map +1 -0
- package/dist/delivery/RelayDeliveryChannel.d.ts +176 -0
- package/dist/delivery/RelayDeliveryChannel.d.ts.map +1 -0
- package/dist/delivery/RelayDeliveryChannel.js +377 -0
- package/dist/delivery/RelayDeliveryChannel.js.map +1 -0
- package/dist/delivery/channel.d.ts +282 -0
- package/dist/delivery/channel.d.ts.map +1 -0
- package/dist/delivery/channel.js +76 -0
- package/dist/delivery/channel.js.map +1 -0
- package/dist/delivery/channelLog.d.ts +115 -0
- package/dist/delivery/channelLog.d.ts.map +1 -0
- package/dist/delivery/channelLog.js +94 -0
- package/dist/delivery/channelLog.js.map +1 -0
- package/dist/delivery/crypto.d.ts +312 -0
- package/dist/delivery/crypto.d.ts.map +1 -0
- package/dist/delivery/crypto.js +495 -0
- package/dist/delivery/crypto.js.map +1 -0
- package/dist/delivery/eip712.d.ts +248 -0
- package/dist/delivery/eip712.d.ts.map +1 -0
- package/dist/delivery/eip712.js +397 -0
- package/dist/delivery/eip712.js.map +1 -0
- package/dist/delivery/envelopeBuilder.d.ts +531 -0
- package/dist/delivery/envelopeBuilder.d.ts.map +1 -0
- package/dist/delivery/envelopeBuilder.js +832 -0
- package/dist/delivery/envelopeBuilder.js.map +1 -0
- package/dist/delivery/index.d.ts +53 -0
- package/dist/delivery/index.d.ts.map +1 -0
- package/dist/delivery/index.js +143 -0
- package/dist/delivery/index.js.map +1 -0
- package/dist/delivery/keys.d.ts +344 -0
- package/dist/delivery/keys.d.ts.map +1 -0
- package/dist/delivery/keys.js +513 -0
- package/dist/delivery/keys.js.map +1 -0
- package/dist/delivery/nonce-keys.d.ts +93 -0
- package/dist/delivery/nonce-keys.d.ts.map +1 -0
- package/dist/delivery/nonce-keys.js +88 -0
- package/dist/delivery/nonce-keys.js.map +1 -0
- package/dist/delivery/setupBuilder.d.ts +403 -0
- package/dist/delivery/setupBuilder.d.ts.map +1 -0
- package/dist/delivery/setupBuilder.js +554 -0
- package/dist/delivery/setupBuilder.js.map +1 -0
- package/dist/delivery/types.d.ts +722 -0
- package/dist/delivery/types.d.ts.map +1 -0
- package/dist/delivery/types.js +150 -0
- package/dist/delivery/types.js.map +1 -0
- package/dist/delivery/validate.d.ts +288 -0
- package/dist/delivery/validate.d.ts.map +1 -0
- package/dist/delivery/validate.js +648 -0
- package/dist/delivery/validate.js.map +1 -0
- package/dist/level1/Agent.d.ts +130 -0
- package/dist/level1/Agent.d.ts.map +1 -1
- package/dist/level1/Agent.js +248 -0
- package/dist/level1/Agent.js.map +1 -1
- package/dist/level1/types/Options.d.ts +62 -0
- package/dist/level1/types/Options.d.ts.map +1 -1
- package/dist/level1/types/Options.js +22 -0
- package/dist/level1/types/Options.js.map +1 -1
- package/dist/runtime/MockRuntime.d.ts +32 -0
- package/dist/runtime/MockRuntime.d.ts.map +1 -1
- package/dist/runtime/MockRuntime.js +44 -0
- package/dist/runtime/MockRuntime.js.map +1 -1
- package/dist/wallet/aa/BundlerClient.d.ts.map +1 -1
- package/dist/wallet/aa/BundlerClient.js +18 -3
- package/dist/wallet/aa/BundlerClient.js.map +1 -1
- package/dist/wallet/aa/PaymasterClient.d.ts.map +1 -1
- package/dist/wallet/aa/PaymasterClient.js +4 -1
- package/dist/wallet/aa/PaymasterClient.js.map +1 -1
- package/package.json +6 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AIP-16 Delivery Surface — Channel Abstraction (Phase 2b)
|
|
4
|
+
* =========================================================
|
|
5
|
+
*
|
|
6
|
+
* Transport-agnostic interface for posting and observing delivery
|
|
7
|
+
* setup + envelope wire objects between requester and provider.
|
|
8
|
+
*
|
|
9
|
+
* The delivery channel is the wire-level boundary between the two
|
|
10
|
+
* participants of an AIP-16 delivery exchange. It does NOT participate
|
|
11
|
+
* in any cryptographic verification — its only job is to transport
|
|
12
|
+
* already-signed {@link DeliverySetupWireV1} and {@link DeliveryEnvelopeWireV1}
|
|
13
|
+
* objects between participants.
|
|
14
|
+
*
|
|
15
|
+
* ## Concrete implementations
|
|
16
|
+
*
|
|
17
|
+
* - **MockDeliveryChannel** — in-process loopback used by tests and
|
|
18
|
+
* MockRuntime flows. Implements dedup-after-verify on the read side
|
|
19
|
+
* (see {@link MockChannel} in `src/negotiation/` for the reference
|
|
20
|
+
* pattern). Useful for end-to-end tests without network setup.
|
|
21
|
+
* - **RelayDeliveryChannel** — HTTP client against the AGIRAILS relay
|
|
22
|
+
* (or any compatible relay implementing the same REST surface). Uses
|
|
23
|
+
* cursor pagination, polling at `POLL_INTERVAL_MS = 1000`, and an
|
|
24
|
+
* SSRF guard on the relay URL (see {@link RelayChannel} in
|
|
25
|
+
* `src/negotiation/` for the reference pattern).
|
|
26
|
+
*
|
|
27
|
+
* ## Security invariants (binding on ALL implementations)
|
|
28
|
+
*
|
|
29
|
+
* 1. **Dedup AFTER verify.** Implementations that deduplicate
|
|
30
|
+
* incoming setups/envelopes MUST verify signatures BEFORE adding any
|
|
31
|
+
* identifier (txId, sig hash, etc.) to a dedup set. Otherwise an
|
|
32
|
+
* attacker can post malformed signatures to permanently suppress
|
|
33
|
+
* the legitimate signed object that arrives later.
|
|
34
|
+
*
|
|
35
|
+
* 2. **Subscriber error isolation.** Subscriber callbacks may throw
|
|
36
|
+
* arbitrary errors (consumer code is not the channel's problem).
|
|
37
|
+
* Implementations MUST catch and silently swallow callback errors —
|
|
38
|
+
* NEVER propagate them into the channel's read loop, since one bad
|
|
39
|
+
* subscriber would otherwise halt delivery for all other subscribers
|
|
40
|
+
* sharing the same channel.
|
|
41
|
+
*
|
|
42
|
+
* 3. **No verification at the channel layer.** Channels do NOT call
|
|
43
|
+
* `recoverSetupSigner` / `recoverEnvelopeSigner` or any other
|
|
44
|
+
* cryptographic check. Verification is the consumer's responsibility
|
|
45
|
+
* (typically via {@link DeliverySetupBuilder.verify} /
|
|
46
|
+
* {@link DeliveryEnvelopeBuilder.verify}). The channel is a dumb pipe.
|
|
47
|
+
*
|
|
48
|
+
* 4. **Address comparison case-insensitivity.** Where addresses appear
|
|
49
|
+
* in dedup keys (e.g. `signerAddress`), implementations MUST normalize
|
|
50
|
+
* to lowercase on both sides of any comparison.
|
|
51
|
+
*
|
|
52
|
+
* ## Subscription semantics
|
|
53
|
+
*
|
|
54
|
+
* - `subscribeSetups` / `subscribeEnvelopes` are scoped to a single
|
|
55
|
+
* `txId`. A subscription begins emitting from "now" — that is, from
|
|
56
|
+
* objects that are NOT already known to the channel at subscribe time
|
|
57
|
+
* are guaranteed to be delivered; objects that ARE already known MAY
|
|
58
|
+
* or MAY NOT be re-delivered depending on the implementation. Code
|
|
59
|
+
* that needs the full historical set should call the optional
|
|
60
|
+
* `getSetups` / `getEnvelopes` methods.
|
|
61
|
+
*
|
|
62
|
+
* - Returning a {@link DeliverySubscription} whose `close()` is invoked
|
|
63
|
+
* MUST stop further callbacks from firing on that subscription. It
|
|
64
|
+
* SHOULD also free any underlying transport (polling timer, HTTP
|
|
65
|
+
* connection, etc.).
|
|
66
|
+
*
|
|
67
|
+
* - Multiple subscribers on the same `txId` MUST each receive all
|
|
68
|
+
* matching objects (fan-out, not steal). One subscriber's `close()`
|
|
69
|
+
* MUST NOT affect other subscribers.
|
|
70
|
+
*
|
|
71
|
+
* @module delivery/channel
|
|
72
|
+
* @see {@link DeliverySetupWireV1}
|
|
73
|
+
* @see {@link DeliveryEnvelopeWireV1}
|
|
74
|
+
*/
|
|
75
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
76
|
+
//# sourceMappingURL=channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/delivery/channel.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AIP-16 Delivery Surface — Pluggable Channel Logger (Phase 2b)
|
|
3
|
+
* ==============================================================
|
|
4
|
+
*
|
|
5
|
+
* Minimal logger contract used by delivery channel implementations
|
|
6
|
+
* (`MockDeliveryChannel`, `RelayDeliveryChannel`) to surface
|
|
7
|
+
* operational events — transport errors, dedup hits, subscriber-callback
|
|
8
|
+
* errors that were swallowed per security invariant #2 — without
|
|
9
|
+
* coupling those implementations to any specific logging framework.
|
|
10
|
+
*
|
|
11
|
+
* ## Design intent
|
|
12
|
+
*
|
|
13
|
+
* Channels are dumb pipes: they verify nothing, decrypt nothing, and
|
|
14
|
+
* make no business decisions. They DO, however, encounter transport
|
|
15
|
+
* failures, malformed payloads, and (per the subscriber-error-isolation
|
|
16
|
+
* invariant) consumer callbacks that throw. Operators need visibility
|
|
17
|
+
* into these events; tests need to be able to assert on or silence
|
|
18
|
+
* them. A pluggable {@link LogFn} satisfies both needs without
|
|
19
|
+
* pulling pino/winston/console into the SDK runtime.
|
|
20
|
+
*
|
|
21
|
+
* The shape is intentionally minimal — three levels, a message string,
|
|
22
|
+
* and an optional structured `details` bag. Implementers can adapt
|
|
23
|
+
* this to any backend (console, pino, OpenTelemetry, in-memory buffer
|
|
24
|
+
* for tests, etc.).
|
|
25
|
+
*
|
|
26
|
+
* ## Levels
|
|
27
|
+
*
|
|
28
|
+
* - `"info"` — Normal lifecycle events (subscription opened/closed,
|
|
29
|
+
* publish accepted). Quiet by default in production.
|
|
30
|
+
* - `"warn"` — Recoverable anomalies (dedup hit on poisoned signature,
|
|
31
|
+
* subscriber callback threw and was swallowed, optional `getSetups`
|
|
32
|
+
* not supported by the underlying transport). Worth surfacing in
|
|
33
|
+
* dashboards but not pageable.
|
|
34
|
+
* - `"error"` — Transport failures (relay returned 5xx, network
|
|
35
|
+
* unreachable, malformed wire object rejected before publish).
|
|
36
|
+
* May trigger retries upstream.
|
|
37
|
+
*
|
|
38
|
+
* ## Default
|
|
39
|
+
*
|
|
40
|
+
* The exported {@link noopLog} is a silent default suitable for
|
|
41
|
+
* library consumers who do not want any logging output. Tests can
|
|
42
|
+
* provide a capturing logger; production deployments can adapt the
|
|
43
|
+
* SDK's events to their preferred observability stack.
|
|
44
|
+
*
|
|
45
|
+
* @example Console logger
|
|
46
|
+
* ```typescript
|
|
47
|
+
* import type { LogFn } from '@agirails/sdk/delivery';
|
|
48
|
+
*
|
|
49
|
+
* const consoleLog: LogFn = (level, msg, details) => {
|
|
50
|
+
* // eslint-disable-next-line no-console
|
|
51
|
+
* console[level](`[delivery] ${msg}`, details ?? {});
|
|
52
|
+
* };
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example Capturing logger for tests
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const events: Array<{ level: string; msg: string; details?: unknown }> = [];
|
|
58
|
+
* const captureLog: LogFn = (level, msg, details) => {
|
|
59
|
+
* events.push({ level, msg, details });
|
|
60
|
+
* };
|
|
61
|
+
* // …run channel under test, then assert on `events`.
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @module delivery/channelLog
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* Pluggable logger function used by delivery channel implementations.
|
|
68
|
+
*
|
|
69
|
+
* Implementations of this signature receive a level, a human-readable
|
|
70
|
+
* message string, and an optional structured `details` bag. They MAY
|
|
71
|
+
* route the event to any backend (console, pino, OTel, in-memory
|
|
72
|
+
* capture, /dev/null) — the channel does not care.
|
|
73
|
+
*
|
|
74
|
+
* The function MUST be synchronous from the channel's point of view
|
|
75
|
+
* (the channel never `await`s it). Implementations that need to batch
|
|
76
|
+
* or ship logs asynchronously SHOULD do so via internal queues, NOT
|
|
77
|
+
* by returning a Promise.
|
|
78
|
+
*
|
|
79
|
+
* Implementations MUST NOT throw. If an underlying logging backend
|
|
80
|
+
* fails (e.g. write to disk failed), implementations SHOULD catch
|
|
81
|
+
* and discard — a channel cannot let a logging failure interrupt
|
|
82
|
+
* delivery transport.
|
|
83
|
+
*
|
|
84
|
+
* @param level The severity of the event. See module JSDoc for level
|
|
85
|
+
* semantics.
|
|
86
|
+
* @param msg A human-readable description of the event. Stable enough
|
|
87
|
+
* to be greppable across log volumes, but not promised as a
|
|
88
|
+
* machine-actionable identifier — use `details.code` (when present)
|
|
89
|
+
* for that.
|
|
90
|
+
* @param details Optional structured context (txId, signer address,
|
|
91
|
+
* HTTP status, error code, etc.). Implementations SHOULD attach
|
|
92
|
+
* any details bag to the underlying log record verbatim; loggers
|
|
93
|
+
* that flatten structured data SHOULD preserve key/value pairs.
|
|
94
|
+
*/
|
|
95
|
+
export type LogFn = (level: 'info' | 'warn' | 'error', msg: string, details?: Record<string, unknown>) => void;
|
|
96
|
+
/**
|
|
97
|
+
* Silent default {@link LogFn}: discards every event.
|
|
98
|
+
*
|
|
99
|
+
* Suitable as the default `log` parameter on channel constructors so
|
|
100
|
+
* that consumers who do not opt into logging see no output. Tests and
|
|
101
|
+
* production deployments that want visibility SHOULD pass their own
|
|
102
|
+
* {@link LogFn} implementation.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* import { noopLog } from '@agirails/sdk/delivery';
|
|
107
|
+
*
|
|
108
|
+
* const channel = new RelayDeliveryChannel({
|
|
109
|
+
* baseUrl: 'https://relay.agirails.io',
|
|
110
|
+
* log: noopLog, // explicit silence; same as omitting the param
|
|
111
|
+
* });
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare const noopLog: LogFn;
|
|
115
|
+
//# sourceMappingURL=channelLog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channelLog.d.ts","sourceRoot":"","sources":["../../src/delivery/channelLog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AAMH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,MAAM,KAAK,GAAG,CAClB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAChC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,IAAI,CAAC;AAMV;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AIP-16 Delivery Surface — Pluggable Channel Logger (Phase 2b)
|
|
4
|
+
* ==============================================================
|
|
5
|
+
*
|
|
6
|
+
* Minimal logger contract used by delivery channel implementations
|
|
7
|
+
* (`MockDeliveryChannel`, `RelayDeliveryChannel`) to surface
|
|
8
|
+
* operational events — transport errors, dedup hits, subscriber-callback
|
|
9
|
+
* errors that were swallowed per security invariant #2 — without
|
|
10
|
+
* coupling those implementations to any specific logging framework.
|
|
11
|
+
*
|
|
12
|
+
* ## Design intent
|
|
13
|
+
*
|
|
14
|
+
* Channels are dumb pipes: they verify nothing, decrypt nothing, and
|
|
15
|
+
* make no business decisions. They DO, however, encounter transport
|
|
16
|
+
* failures, malformed payloads, and (per the subscriber-error-isolation
|
|
17
|
+
* invariant) consumer callbacks that throw. Operators need visibility
|
|
18
|
+
* into these events; tests need to be able to assert on or silence
|
|
19
|
+
* them. A pluggable {@link LogFn} satisfies both needs without
|
|
20
|
+
* pulling pino/winston/console into the SDK runtime.
|
|
21
|
+
*
|
|
22
|
+
* The shape is intentionally minimal — three levels, a message string,
|
|
23
|
+
* and an optional structured `details` bag. Implementers can adapt
|
|
24
|
+
* this to any backend (console, pino, OpenTelemetry, in-memory buffer
|
|
25
|
+
* for tests, etc.).
|
|
26
|
+
*
|
|
27
|
+
* ## Levels
|
|
28
|
+
*
|
|
29
|
+
* - `"info"` — Normal lifecycle events (subscription opened/closed,
|
|
30
|
+
* publish accepted). Quiet by default in production.
|
|
31
|
+
* - `"warn"` — Recoverable anomalies (dedup hit on poisoned signature,
|
|
32
|
+
* subscriber callback threw and was swallowed, optional `getSetups`
|
|
33
|
+
* not supported by the underlying transport). Worth surfacing in
|
|
34
|
+
* dashboards but not pageable.
|
|
35
|
+
* - `"error"` — Transport failures (relay returned 5xx, network
|
|
36
|
+
* unreachable, malformed wire object rejected before publish).
|
|
37
|
+
* May trigger retries upstream.
|
|
38
|
+
*
|
|
39
|
+
* ## Default
|
|
40
|
+
*
|
|
41
|
+
* The exported {@link noopLog} is a silent default suitable for
|
|
42
|
+
* library consumers who do not want any logging output. Tests can
|
|
43
|
+
* provide a capturing logger; production deployments can adapt the
|
|
44
|
+
* SDK's events to their preferred observability stack.
|
|
45
|
+
*
|
|
46
|
+
* @example Console logger
|
|
47
|
+
* ```typescript
|
|
48
|
+
* import type { LogFn } from '@agirails/sdk/delivery';
|
|
49
|
+
*
|
|
50
|
+
* const consoleLog: LogFn = (level, msg, details) => {
|
|
51
|
+
* // eslint-disable-next-line no-console
|
|
52
|
+
* console[level](`[delivery] ${msg}`, details ?? {});
|
|
53
|
+
* };
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @example Capturing logger for tests
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const events: Array<{ level: string; msg: string; details?: unknown }> = [];
|
|
59
|
+
* const captureLog: LogFn = (level, msg, details) => {
|
|
60
|
+
* events.push({ level, msg, details });
|
|
61
|
+
* };
|
|
62
|
+
* // …run channel under test, then assert on `events`.
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @module delivery/channelLog
|
|
66
|
+
*/
|
|
67
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
68
|
+
exports.noopLog = void 0;
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// Default silent logger
|
|
71
|
+
// ============================================================================
|
|
72
|
+
/**
|
|
73
|
+
* Silent default {@link LogFn}: discards every event.
|
|
74
|
+
*
|
|
75
|
+
* Suitable as the default `log` parameter on channel constructors so
|
|
76
|
+
* that consumers who do not opt into logging see no output. Tests and
|
|
77
|
+
* production deployments that want visibility SHOULD pass their own
|
|
78
|
+
* {@link LogFn} implementation.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* import { noopLog } from '@agirails/sdk/delivery';
|
|
83
|
+
*
|
|
84
|
+
* const channel = new RelayDeliveryChannel({
|
|
85
|
+
* baseUrl: 'https://relay.agirails.io',
|
|
86
|
+
* log: noopLog, // explicit silence; same as omitting the param
|
|
87
|
+
* });
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
const noopLog = () => {
|
|
91
|
+
// Intentional no-op. See JSDoc for rationale.
|
|
92
|
+
};
|
|
93
|
+
exports.noopLog = noopLog;
|
|
94
|
+
//# sourceMappingURL=channelLog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channelLog.js","sourceRoot":"","sources":["../../src/delivery/channelLog.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;;;AAyCH,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;GAiBG;AACI,MAAM,OAAO,GAAU,GAAG,EAAE;IACjC,8CAA8C;AAChD,CAAC,CAAC;AAFW,QAAA,OAAO,WAElB"}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AIP-16 Delivery Surface — AES-256-GCM AEAD + Body Hashing (Phase 2a Foundation)
|
|
3
|
+
* ==============================================================================
|
|
4
|
+
*
|
|
5
|
+
* Authenticated encryption primitives for the `x25519-aes256gcm-v1`
|
|
6
|
+
* delivery scheme of AIP-16 Rev 5.
|
|
7
|
+
*
|
|
8
|
+
* This module sits one layer above `./keys.ts` (which produces the
|
|
9
|
+
* 32-byte session key via X25519 ECDH + HKDF-SHA256) and one layer
|
|
10
|
+
* below the envelope builders (`./envelopeBuilder.ts`, later phase),
|
|
11
|
+
* which assemble the ciphertext + nonce + tag + signature into the
|
|
12
|
+
* wire envelope.
|
|
13
|
+
*
|
|
14
|
+
* ## Scope of this file
|
|
15
|
+
*
|
|
16
|
+
* - {@link encryptBody}: seal a UTF-8 string or raw byte body with
|
|
17
|
+
* AES-256-GCM, returning ciphertext + 12-byte nonce + 16-byte tag.
|
|
18
|
+
* - {@link decryptBody}: inverse — verify the GCM tag and return the
|
|
19
|
+
* plaintext.
|
|
20
|
+
* - {@link bodyHash}: keccak256 of the UTF-8 / raw bytes, in the exact
|
|
21
|
+
* form used for the `payloadHash` field of the signed EIP-712
|
|
22
|
+
* projection.
|
|
23
|
+
* - Hex format helpers ({@link bytesToHex}, {@link bytesFromHex}) for
|
|
24
|
+
* ciphertext / nonce / tag serialization at the wire boundary.
|
|
25
|
+
*
|
|
26
|
+
* ## Library choice: `node:crypto`
|
|
27
|
+
*
|
|
28
|
+
* We use Node's built-in AES-GCM (`createCipheriv('aes-256-gcm', …)`)
|
|
29
|
+
* rather than `@noble/ciphers`. Reasons:
|
|
30
|
+
*
|
|
31
|
+
* 1. AES-256-GCM is a *standard* AEAD; the implementation surface is
|
|
32
|
+
* small and audited as part of OpenSSL (the engine behind
|
|
33
|
+
* `node:crypto`).
|
|
34
|
+
* 2. Zero new dependencies — matches the design constraint in the
|
|
35
|
+
* Phase 2a task brief.
|
|
36
|
+
* 3. The `setAuthTag` / `getAuthTag` pattern is mechanical and easy
|
|
37
|
+
* to audit for "did we actually verify the tag before returning
|
|
38
|
+
* plaintext?" (`decipher.final()` throws on tag mismatch).
|
|
39
|
+
*
|
|
40
|
+
* ## AAD (Additional Authenticated Data) — H5 defense-in-depth
|
|
41
|
+
*
|
|
42
|
+
* Both {@link encryptBody} and {@link decryptBody} accept an OPTIONAL
|
|
43
|
+
* `aad` byte buffer. When supplied, the bytes are fed into GCM via
|
|
44
|
+
* `cipher.setAAD(aad)` / `decipher.setAAD(aad)` — they are *not*
|
|
45
|
+
* encrypted, but the GCM authentication tag commits to them, so a
|
|
46
|
+
* decryption with the wrong AAD fails closed with a tag mismatch.
|
|
47
|
+
*
|
|
48
|
+
* For the `x25519-aes256gcm-v1` scheme the envelope builder constructs
|
|
49
|
+
*
|
|
50
|
+
* aad = txId_bytes (32) || signerAddress_bytes (20) // 52 bytes
|
|
51
|
+
*
|
|
52
|
+
* and passes it to both encrypt and decrypt. This binds the GCM
|
|
53
|
+
* authentication to the on-chain transaction id and the EOA that
|
|
54
|
+
* signed the envelope, so a misrouted envelope (correct ciphertext +
|
|
55
|
+
* nonce + tag + sessionKey, but delivered to a different `txId` or
|
|
56
|
+
* `signerAddress`) cannot be opened — defense-in-depth on top of the
|
|
57
|
+
* EIP-712 signature over `txId` and `payloadHash`.
|
|
58
|
+
*
|
|
59
|
+
* Because the channel is gated behind the Phase 2f feature flag and
|
|
60
|
+
* no in-flight `x25519-aes256gcm-v1` envelopes exist in production, we
|
|
61
|
+
* change the AAD inline within the existing scheme tag rather than
|
|
62
|
+
* minting a `-v2` suffix; the scheme name stays `x25519-aes256gcm-v1`.
|
|
63
|
+
*
|
|
64
|
+
* AAD is OPTIONAL at the primitive level. Callers that omit it get
|
|
65
|
+
* the legacy "AAD = empty" behavior (still interoperable with prior
|
|
66
|
+
* versions of the function). The envelope builder always supplies AAD.
|
|
67
|
+
*
|
|
68
|
+
* ## Memory hygiene
|
|
69
|
+
*
|
|
70
|
+
* `sessionKey` and plaintext are held in plain `Uint8Array`s. Like
|
|
71
|
+
* `./keys.ts`, this module does not attempt to zero memory — V8 makes
|
|
72
|
+
* no such guarantees, and the SDK target environments (Node + Bun)
|
|
73
|
+
* inherit that limitation. Callers SHOULD let secrets go out of scope
|
|
74
|
+
* promptly after use.
|
|
75
|
+
*
|
|
76
|
+
* @module delivery/crypto
|
|
77
|
+
* @see ./keys — produces the 32-byte session key consumed here
|
|
78
|
+
* @see ./eip712 — signs the `payloadHash` produced by {@link bodyHash}
|
|
79
|
+
* @see {@link https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf NIST SP 800-38D — GCM mode}
|
|
80
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc5116 RFC 5116 — AEAD interface}
|
|
81
|
+
*/
|
|
82
|
+
/**
|
|
83
|
+
* Length (in bytes) of the AES-256-GCM nonce / IV.
|
|
84
|
+
*
|
|
85
|
+
* Twelve bytes is the GCM-standard length (NIST SP 800-38D §5.2.1.1).
|
|
86
|
+
* Any other length is technically permitted by the spec but triggers
|
|
87
|
+
* an additional GHASH step and is interoperable only by convention;
|
|
88
|
+
* AIP-16 v1 mandates 12 bytes to keep the wire format unambiguous.
|
|
89
|
+
*
|
|
90
|
+
* We sample the nonce from `randomBytes(12)` per-encryption. The
|
|
91
|
+
* 2^96 nonce space is more than adequate for the AIP-16 use case
|
|
92
|
+
* (one nonce per delivery envelope per session key, with session keys
|
|
93
|
+
* themselves bound to a single transaction via HKDF).
|
|
94
|
+
*/
|
|
95
|
+
export declare const AES_GCM_NONCE_LENGTH: 12;
|
|
96
|
+
/**
|
|
97
|
+
* Length (in bytes) of the AES-256-GCM authentication tag.
|
|
98
|
+
*
|
|
99
|
+
* Sixteen bytes is the maximum (full-strength) tag length permitted
|
|
100
|
+
* by GCM; NIST SP 800-38D recommends this size when the application
|
|
101
|
+
* cannot tolerate any forgery probability. The wire format reserves
|
|
102
|
+
* a fixed 16-byte slot for the tag.
|
|
103
|
+
*/
|
|
104
|
+
export declare const AES_GCM_TAG_LENGTH: 16;
|
|
105
|
+
/**
|
|
106
|
+
* Length (in bytes) of an AES-256 key. Equal to
|
|
107
|
+
* {@link DELIVERY_SESSION_KEY_LENGTH} (re-exported from `./keys`) so
|
|
108
|
+
* callers do not have to import both files just for the length check.
|
|
109
|
+
*/
|
|
110
|
+
export declare const AES_KEY_LENGTH: 32;
|
|
111
|
+
/**
|
|
112
|
+
* Result of {@link encryptBody}.
|
|
113
|
+
*
|
|
114
|
+
* All three fields are raw bytes (not hex). The envelope builder will
|
|
115
|
+
* apply {@link bytesToHex} just before serializing to the wire
|
|
116
|
+
* envelope's `bodyCiphertextHex`, `nonceHex`, and `tagHex` fields.
|
|
117
|
+
*
|
|
118
|
+
* The separation of `ciphertext` and `tag` matches the `node:crypto`
|
|
119
|
+
* GCM API surface (`getAuthTag` is a distinct call from the cipher's
|
|
120
|
+
* `update` / `final` output). It also makes the wire format
|
|
121
|
+
* unambiguous: there is no need to peel the last 16 bytes off the
|
|
122
|
+
* ciphertext, which is a common parsing bug.
|
|
123
|
+
*/
|
|
124
|
+
export interface EncryptResult {
|
|
125
|
+
/**
|
|
126
|
+
* The AES-256-GCM ciphertext. Length is exactly equal to the
|
|
127
|
+
* plaintext length (GCM is a stream-cipher mode, no padding).
|
|
128
|
+
*/
|
|
129
|
+
ciphertext: Uint8Array;
|
|
130
|
+
/**
|
|
131
|
+
* The 12-byte random nonce / IV used for this encryption. Embedded
|
|
132
|
+
* verbatim in the wire envelope so the recipient can pass it to
|
|
133
|
+
* {@link decryptBody}.
|
|
134
|
+
*/
|
|
135
|
+
nonce: Uint8Array;
|
|
136
|
+
/**
|
|
137
|
+
* The 16-byte GCM authentication tag. The recipient MUST present
|
|
138
|
+
* this tag to AES-GCM during decryption; `decipher.final()` will
|
|
139
|
+
* throw if it does not match, which {@link decryptBody} catches
|
|
140
|
+
* and re-raises as `DeliveryCryptoError('crypto_decrypt_failed')`.
|
|
141
|
+
*/
|
|
142
|
+
tag: Uint8Array;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Encrypt a delivery envelope body with AES-256-GCM using the supplied
|
|
146
|
+
* session key.
|
|
147
|
+
*
|
|
148
|
+
* The session key MUST have been produced by
|
|
149
|
+
* {@link import('./keys').deriveSessionKey} (32 bytes, HKDF-SHA256
|
|
150
|
+
* output bound to the on-chain `txId`).
|
|
151
|
+
*
|
|
152
|
+
* A fresh 12-byte nonce is sampled from `randomBytes` per call.
|
|
153
|
+
* Re-using a (key, nonce) pair is *catastrophic* for GCM — it leaks
|
|
154
|
+
* the GHASH key, allowing both decryption of past messages and
|
|
155
|
+
* forgery of future ones. With session keys scoped to one transaction
|
|
156
|
+
* and nonces randomized per envelope, the probability of collision
|
|
157
|
+
* over realistic envelope counts is negligible.
|
|
158
|
+
*
|
|
159
|
+
* AAD is OPTIONAL. When supplied, the bytes are committed by the GCM
|
|
160
|
+
* tag (defense-in-depth — see the H5 section of the module-level docs).
|
|
161
|
+
* Decryption with a different AAD (or with no AAD at all when the
|
|
162
|
+
* encrypt side used one) will fail with `crypto_decrypt_failed`.
|
|
163
|
+
*
|
|
164
|
+
* @param plaintext - Body bytes to encrypt. A `string` is interpreted
|
|
165
|
+
* as UTF-8; pre-encoded `Uint8Array` is passed through verbatim.
|
|
166
|
+
* @param sessionKey - 32-byte AES-256-GCM key from `deriveSessionKey`.
|
|
167
|
+
* @param aad - Optional Additional Authenticated Data. When omitted,
|
|
168
|
+
* no AAD is fed into GCM (legacy behavior). When supplied, MUST be a
|
|
169
|
+
* `Uint8Array`; mismatched AAD at decrypt time fails tag verification.
|
|
170
|
+
* @returns {@link EncryptResult} carrying ciphertext, nonce, and tag.
|
|
171
|
+
* @throws {DeliveryCryptoError} `crypto_encrypt_failed` if
|
|
172
|
+
* `sessionKey` is malformed (not a `Uint8Array` of length 32), if
|
|
173
|
+
* `plaintext` is the wrong type, if `aad` is supplied as a non-bytes
|
|
174
|
+
* value, or if `node:crypto` raises.
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```typescript
|
|
178
|
+
* const key = deriveSessionKey(shared, txId);
|
|
179
|
+
* // AAD = txId_bytes || signerAddress_bytes (H5 binding)
|
|
180
|
+
* const aad = new Uint8Array(52);
|
|
181
|
+
* aad.set(bytesFromHex(txId), 0);
|
|
182
|
+
* aad.set(bytesFromHex(signerAddress), 32);
|
|
183
|
+
* const { ciphertext, nonce, tag } = encryptBody('{"result":"ok"}', key, aad);
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
export declare function encryptBody(plaintext: Uint8Array | string, sessionKey: Uint8Array, aad?: Uint8Array): EncryptResult;
|
|
187
|
+
/**
|
|
188
|
+
* Decrypt and authenticate an AES-256-GCM ciphertext produced by
|
|
189
|
+
* {@link encryptBody} (or an interoperable peer).
|
|
190
|
+
*
|
|
191
|
+
* The GCM authentication tag is verified inside `decipher.final()` —
|
|
192
|
+
* if the tag does not match, `node:crypto` throws and we re-raise as
|
|
193
|
+
* `DeliveryCryptoError('crypto_decrypt_failed')`. This is the *only*
|
|
194
|
+
* integrity check on the envelope body bytes; pair it with EIP-712
|
|
195
|
+
* signature verification one layer up to also bind the body to a
|
|
196
|
+
* specific signer.
|
|
197
|
+
*
|
|
198
|
+
* AAD is OPTIONAL but MUST match what the encrypt side used. The GCM
|
|
199
|
+
* tag commits to the AAD bytes; supplying the wrong AAD (or omitting
|
|
200
|
+
* AAD when the encrypt side supplied one, or vice versa) produces a
|
|
201
|
+
* tag-mismatch error, surfaced here as `crypto_decrypt_failed`. This
|
|
202
|
+
* is the H5 misrouting defense — see the module-level AAD section.
|
|
203
|
+
*
|
|
204
|
+
* @param ciphertext - GCM ciphertext as raw bytes.
|
|
205
|
+
* @param sessionKey - 32-byte AES-256-GCM key (same as encrypt side).
|
|
206
|
+
* @param nonce - 12-byte nonce that was used at encrypt time.
|
|
207
|
+
* @param tag - 16-byte GCM authentication tag.
|
|
208
|
+
* @param aad - Optional Additional Authenticated Data. MUST exactly
|
|
209
|
+
* match the AAD passed to {@link encryptBody}; mismatch (including
|
|
210
|
+
* AAD/no-AAD asymmetry) fails the tag check and throws
|
|
211
|
+
* `crypto_decrypt_failed`.
|
|
212
|
+
* @returns The decrypted plaintext as raw bytes. If the original
|
|
213
|
+
* plaintext was a UTF-8 string, the caller can recover it via
|
|
214
|
+
* `Buffer.from(plaintext).toString('utf8')`.
|
|
215
|
+
* @throws {DeliveryCryptoError} `crypto_decrypt_failed` on any of:
|
|
216
|
+
* malformed lengths, wrong session key, tampered ciphertext / tag /
|
|
217
|
+
* nonce, AAD mismatch, malformed AAD type, or underlying
|
|
218
|
+
* `node:crypto` failure.
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* const aad = new Uint8Array(52);
|
|
223
|
+
* aad.set(bytesFromHex(txId), 0);
|
|
224
|
+
* aad.set(bytesFromHex(signerAddress), 32);
|
|
225
|
+
* const plaintextBytes = decryptBody(ciphertext, key, nonce, tag, aad);
|
|
226
|
+
* const json = Buffer.from(plaintextBytes).toString('utf8');
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
export declare function decryptBody(ciphertext: Uint8Array, sessionKey: Uint8Array, nonce: Uint8Array, tag: Uint8Array, aad?: Uint8Array): Uint8Array;
|
|
230
|
+
/**
|
|
231
|
+
* Compute the keccak256 hash of an envelope body, in the exact form
|
|
232
|
+
* embedded into the `payloadHash` field of the signed EIP-712
|
|
233
|
+
* projection.
|
|
234
|
+
*
|
|
235
|
+
* Per AIP-16 Rev 5 §6.2, `payloadHash = keccak256(bodyBytes)` where
|
|
236
|
+
* `bodyBytes` is:
|
|
237
|
+
* - For `scheme: "public-v1"`: the UTF-8 bytes of the plaintext body
|
|
238
|
+
* string (or the raw `Uint8Array` if the caller pre-encoded).
|
|
239
|
+
* - For `scheme: "x25519-aes256gcm-v1"`: the *ciphertext* bytes (the
|
|
240
|
+
* output of {@link encryptBody}.ciphertext), not the plaintext.
|
|
241
|
+
* This commits the signer to the exact bytes that travel on the
|
|
242
|
+
* wire, preventing a malicious relay from substituting alternative
|
|
243
|
+
* ciphertext with the same plaintext (which GCM nonces would
|
|
244
|
+
* actually preclude, but the EIP-712 commitment is independent of
|
|
245
|
+
* that).
|
|
246
|
+
*
|
|
247
|
+
* The output is a 0x-prefixed lowercase 66-char hex string (32-byte
|
|
248
|
+
* keccak256 digest), exactly matching the `bytes32` field shape in
|
|
249
|
+
* the EIP-712 types.
|
|
250
|
+
*
|
|
251
|
+
* @param body - The bytes to hash. A `string` is interpreted as UTF-8.
|
|
252
|
+
* @returns The keccak256 digest as `0x` + 64 lowercase hex chars.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```typescript
|
|
256
|
+
* // Public scheme:
|
|
257
|
+
* const h1 = bodyHash('{"result":"ok"}');
|
|
258
|
+
*
|
|
259
|
+
* // Encrypted scheme — hash the CIPHERTEXT, not the plaintext:
|
|
260
|
+
* const { ciphertext } = encryptBody(plaintext, key);
|
|
261
|
+
* const h2 = bodyHash(ciphertext);
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
export declare function bodyHash(body: string | Uint8Array): `0x${string}`;
|
|
265
|
+
/**
|
|
266
|
+
* Encode raw bytes to a lowercase 0x-prefixed hex string.
|
|
267
|
+
*
|
|
268
|
+
* Intentionally byte-for-byte equivalent to the equivalent helper in
|
|
269
|
+
* `./keys.ts` (which is `internal` there). Exposed here at the
|
|
270
|
+
* module surface so envelope-builder callers can serialize their
|
|
271
|
+
* ciphertext / nonce / tag without reaching into `./keys.ts` internals.
|
|
272
|
+
*
|
|
273
|
+
* Hand-rolled rather than `Buffer.from(b).toString('hex')` so the
|
|
274
|
+
* implementation is portable to non-Node runtimes (Bun, web) without
|
|
275
|
+
* polyfills, and to avoid Buffer-vs-Uint8Array subclass confusion.
|
|
276
|
+
*
|
|
277
|
+
* @param b - Raw bytes to encode.
|
|
278
|
+
* @returns A `0x`-prefixed lowercase hex string of length
|
|
279
|
+
* `2 + 2 * b.length`.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```typescript
|
|
283
|
+
* bytesToHex(new Uint8Array([0xab, 0xcd])); // "0xabcd"
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
export declare function bytesToHex(b: Uint8Array): `0x${string}`;
|
|
287
|
+
/**
|
|
288
|
+
* Decode a 0x-prefixed hex string to raw bytes.
|
|
289
|
+
*
|
|
290
|
+
* Strict on shape: the string MUST start with `0x` (case-insensitive
|
|
291
|
+
* prefix), MUST contain only hex digits after the prefix, and MUST
|
|
292
|
+
* have an even number of hex digits. Returns a fresh `Uint8Array`.
|
|
293
|
+
*
|
|
294
|
+
* Used at the wire boundary to decode `bodyCiphertextHex`, `nonceHex`,
|
|
295
|
+
* `tagHex`, and any other hex-serialized byte field into the byte
|
|
296
|
+
* forms expected by {@link decryptBody}.
|
|
297
|
+
*
|
|
298
|
+
* @param hex - 0x-prefixed hex string, even number of hex digits.
|
|
299
|
+
* @returns A fresh `Uint8Array` of length `(hex.length - 2) / 2`.
|
|
300
|
+
* @throws {DeliveryCryptoError} `crypto_decrypt_failed` if `hex` is
|
|
301
|
+
* missing the `0x` prefix, has odd length, or contains non-hex
|
|
302
|
+
* characters. (`crypto_decrypt_failed` is the most likely site of
|
|
303
|
+
* failure for this helper; encrypt-side callers will instead get
|
|
304
|
+
* the structural validation in {@link encryptBody}.)
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```typescript
|
|
308
|
+
* bytesFromHex('0xabcd'); // Uint8Array(2) [0xab, 0xcd]
|
|
309
|
+
* ```
|
|
310
|
+
*/
|
|
311
|
+
export declare function bytesFromHex(hex: string): Uint8Array;
|
|
312
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/delivery/crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AAYH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB,IAAc,CAAC;AAEhD;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,IAAc,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,cAAc,IAA8B,CAAC;AAM1D;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,UAAU,EAAE,UAAU,CAAC;IAEvB;;;;OAIG;IACH,KAAK,EAAE,UAAU,CAAC;IAElB;;;;;OAKG;IACH,GAAG,EAAE,UAAU,CAAC;CACjB;AAwCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,UAAU,GAAG,MAAM,EAC9B,UAAU,EAAE,UAAU,EACtB,GAAG,CAAC,EAAE,UAAU,GACf,aAAa,CA2Gf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,UAAU,EACf,GAAG,CAAC,EAAE,UAAU,GACf,UAAU,CAsFZ;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,KAAK,MAAM,EAAE,CAOjE;AAMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,GAAG,KAAK,MAAM,EAAE,CAevD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAyCpD"}
|