usertrust 1.2.5 → 1.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 +9 -9
- package/dist/anomaly/detector.d.ts +17 -0
- package/dist/anomaly/detector.d.ts.map +1 -0
- package/dist/anomaly/detector.js +174 -0
- package/dist/anomaly/detector.js.map +1 -0
- package/dist/anomaly/index.d.ts +8 -0
- package/dist/anomaly/index.d.ts.map +1 -0
- package/dist/anomaly/index.js +8 -0
- package/dist/anomaly/index.js.map +1 -0
- package/dist/anomaly/signals/injection-cascade.d.ts +31 -0
- package/dist/anomaly/signals/injection-cascade.d.ts.map +1 -0
- package/dist/anomaly/signals/injection-cascade.js +46 -0
- package/dist/anomaly/signals/injection-cascade.js.map +1 -0
- package/dist/anomaly/signals/spend-velocity.d.ts +41 -0
- package/dist/anomaly/signals/spend-velocity.d.ts.map +1 -0
- package/dist/anomaly/signals/spend-velocity.js +90 -0
- package/dist/anomaly/signals/spend-velocity.js.map +1 -0
- package/dist/anomaly/signals/token-rate.d.ts +46 -0
- package/dist/anomaly/signals/token-rate.d.ts.map +1 -0
- package/dist/anomaly/signals/token-rate.js +90 -0
- package/dist/anomaly/signals/token-rate.js.map +1 -0
- package/dist/anomaly/types.d.ts +103 -0
- package/dist/anomaly/types.d.ts.map +1 -0
- package/dist/anomaly/types.js +4 -0
- package/dist/anomaly/types.js.map +1 -0
- package/dist/audit/chain.d.ts +9 -0
- package/dist/audit/chain.d.ts.map +1 -1
- package/dist/audit/chain.js +65 -9
- package/dist/audit/chain.js.map +1 -1
- package/dist/audit/verify.d.ts +19 -0
- package/dist/audit/verify.d.ts.map +1 -1
- package/dist/audit/verify.js +216 -14
- package/dist/audit/verify.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +9 -1
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/skill.d.ts.map +1 -1
- package/dist/cli/skill.js +35 -5
- package/dist/cli/skill.js.map +1 -1
- package/dist/cli/snapshot.d.ts.map +1 -1
- package/dist/cli/snapshot.js +20 -2
- package/dist/cli/snapshot.js.map +1 -1
- package/dist/cli/verify.d.ts.map +1 -1
- package/dist/cli/verify.js +20 -11
- package/dist/cli/verify.js.map +1 -1
- package/dist/govern.d.ts +14 -3
- package/dist/govern.d.ts.map +1 -1
- package/dist/govern.js +367 -129
- package/dist/govern.js.map +1 -1
- package/dist/headless.d.ts.map +1 -1
- package/dist/headless.js +155 -36
- package/dist/headless.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/ledger/client.d.ts +14 -0
- package/dist/ledger/client.d.ts.map +1 -1
- package/dist/ledger/client.js +56 -0
- package/dist/ledger/client.js.map +1 -1
- package/dist/ledger/pricing.d.ts.map +1 -1
- package/dist/ledger/pricing.js +8 -2
- package/dist/ledger/pricing.js.map +1 -1
- package/dist/policy/default-rules.d.ts +18 -3
- package/dist/policy/default-rules.d.ts.map +1 -1
- package/dist/policy/default-rules.js +33 -15
- package/dist/policy/default-rules.js.map +1 -1
- package/dist/policy/gate.d.ts.map +1 -1
- package/dist/policy/gate.js +114 -16
- package/dist/policy/gate.js.map +1 -1
- package/dist/policy/injection.d.ts.map +1 -1
- package/dist/policy/injection.js +25 -16
- package/dist/policy/injection.js.map +1 -1
- package/dist/policy/pii.d.ts +20 -0
- package/dist/policy/pii.d.ts.map +1 -1
- package/dist/policy/pii.js +45 -2
- package/dist/policy/pii.js.map +1 -1
- package/dist/proxy.d.ts +17 -9
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +8 -36
- package/dist/proxy.js.map +1 -1
- package/dist/shared/errors.d.ts +8 -0
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/errors.js +18 -0
- package/dist/shared/errors.js.map +1 -1
- package/dist/shared/types.d.ts +119 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js +37 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/snapshot/checkpoint.d.ts +18 -2
- package/dist/snapshot/checkpoint.d.ts.map +1 -1
- package/dist/snapshot/checkpoint.js +101 -17
- package/dist/snapshot/checkpoint.js.map +1 -1
- package/dist/streaming.d.ts +21 -3
- package/dist/streaming.d.ts.map +1 -1
- package/dist/streaming.js +35 -8
- package/dist/streaming.js.map +1 -1
- package/dist/supply-chain/permissions.d.ts +16 -3
- package/dist/supply-chain/permissions.d.ts.map +1 -1
- package/dist/supply-chain/permissions.js +59 -9
- package/dist/supply-chain/permissions.js.map +1 -1
- package/dist/supply-chain/sign.d.ts +5 -2
- package/dist/supply-chain/sign.d.ts.map +1 -1
- package/dist/supply-chain/sign.js +10 -2
- package/dist/supply-chain/sign.js.map +1 -1
- package/package.json +2 -4
package/dist/shared/types.js
CHANGED
|
@@ -32,6 +32,10 @@ export const TrustConfigSchema = z.object({
|
|
|
32
32
|
.object({
|
|
33
33
|
rotation: z.enum(["daily", "weekly", "none"]).default("daily"),
|
|
34
34
|
indexLimit: z.number().int().default(10_000),
|
|
35
|
+
// P3-AUDIT-FAILCLOSED: when true, a failed CRITICAL audit write aborts the
|
|
36
|
+
// call (deny) instead of settling an unaudited spend. Default false keeps the
|
|
37
|
+
// legacy fail-open behavior (degraded receipt, money still moves).
|
|
38
|
+
failClosed: z.boolean().default(false),
|
|
35
39
|
})
|
|
36
40
|
.default({}),
|
|
37
41
|
tigerbeetle: z
|
|
@@ -55,8 +59,15 @@ export const TrustConfigSchema = z.object({
|
|
|
55
59
|
.optional(),
|
|
56
60
|
supplyChain: z
|
|
57
61
|
.object({
|
|
58
|
-
|
|
62
|
+
// SC-3: fail-closed by default. A skill with no registered signing key
|
|
63
|
+
// or a bad signature is rejected out of the box; operators opt out
|
|
64
|
+
// explicitly by setting enabled:false.
|
|
65
|
+
enabled: z.boolean().default(true),
|
|
59
66
|
trustedPublishers: z.array(z.string()).default([]),
|
|
67
|
+
// SC-1 trust anchor: publisher -> hex-encoded 32-byte Ed25519 public keys
|
|
68
|
+
// the operator vouches for (array = rotation-friendly). Identity is anchored
|
|
69
|
+
// by these keys, NOT by the key embedded in an attacker-controlled manifest.
|
|
70
|
+
publisherKeys: z.record(z.string(), z.array(z.string().regex(/^[a-f0-9]{64}$/))).default({}),
|
|
60
71
|
allowedPermissions: z
|
|
61
72
|
.array(z.enum([
|
|
62
73
|
"llm_call",
|
|
@@ -87,6 +98,31 @@ export const TrustConfigSchema = z.object({
|
|
|
87
98
|
.default({}),
|
|
88
99
|
})
|
|
89
100
|
.default({}),
|
|
101
|
+
anomaly: z
|
|
102
|
+
.object({
|
|
103
|
+
enabled: z.boolean().default(false),
|
|
104
|
+
tokenRate: z
|
|
105
|
+
.object({
|
|
106
|
+
thresholdTokPerSec: z.number().positive().default(500),
|
|
107
|
+
windowMs: z.number().int().positive().default(2_000),
|
|
108
|
+
consecutiveWindows: z.number().int().positive().default(3),
|
|
109
|
+
})
|
|
110
|
+
.default({}),
|
|
111
|
+
spendVelocity: z
|
|
112
|
+
.object({
|
|
113
|
+
thresholdDollarsPerMin: z.number().positive().default(1.0),
|
|
114
|
+
windowMs: z.number().int().positive().default(10_000),
|
|
115
|
+
})
|
|
116
|
+
.default({}),
|
|
117
|
+
injectionCascade: z
|
|
118
|
+
.object({
|
|
119
|
+
eventCount: z.number().int().positive().default(3),
|
|
120
|
+
windowMs: z.number().int().positive().default(60_000),
|
|
121
|
+
})
|
|
122
|
+
.default({}),
|
|
123
|
+
cooldownMs: z.number().int().nonnegative().default(30_000),
|
|
124
|
+
})
|
|
125
|
+
.default({}),
|
|
90
126
|
});
|
|
91
127
|
export const SkillManifestSchema = z.object({
|
|
92
128
|
version: z.literal(1),
|
package/dist/shared/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA8BxB,sBAAsB;AACtB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACnC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACtE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAClC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC;IACtD,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC/D,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC3D,KAAK,EAAE,CAAC;SACN,MAAM,CAAC;QACP,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QACnC,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;KAC5E,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IACb,cAAc,EAAE,CAAC;SACf,MAAM,CAAC;QACP,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;KAC9C,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IACb,QAAQ,EAAE,CAAC;SACT,MAAM,CAAC;QACP,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QAClC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;KACrC,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IACb,KAAK,EAAE,CAAC;SACN,MAAM,CAAC;QACP,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;QAC9D,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,17 @@ export interface SnapshotMeta {
|
|
|
3
3
|
timestamp: string;
|
|
4
4
|
files: string[];
|
|
5
5
|
size: number;
|
|
6
|
+
/** Audit chain head at snapshot time (from events.jsonl.meta). */
|
|
7
|
+
auditHead?: {
|
|
8
|
+
lastHash: string;
|
|
9
|
+
sequence: number;
|
|
10
|
+
};
|
|
11
|
+
/** Money mirror value at snapshot time (from spend-ledger.json). */
|
|
12
|
+
budgetSpent?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface RestoreOptions {
|
|
15
|
+
/** Acknowledge that a live TigerBeetle ledger will NOT be rolled back. */
|
|
16
|
+
forceLedgerDesync?: boolean;
|
|
6
17
|
}
|
|
7
18
|
/**
|
|
8
19
|
* Create a snapshot of the vault state.
|
|
@@ -12,9 +23,14 @@ export interface SnapshotMeta {
|
|
|
12
23
|
export declare function createSnapshot(vaultPath: string, name: string): Promise<SnapshotMeta>;
|
|
13
24
|
/**
|
|
14
25
|
* Restore the vault state from a named snapshot.
|
|
15
|
-
*
|
|
26
|
+
*
|
|
27
|
+
* Atomic (stage-then-commit), audit-writer-lock-aware, and refuses any restore
|
|
28
|
+
* that would sever money<->audit correspondence:
|
|
29
|
+
* - a snapshot that rolls back the audit chain MUST carry spend-ledger.json;
|
|
30
|
+
* - a live TigerBeetle store (which cannot be file-rolled-back) blocks an audit
|
|
31
|
+
* rollback unless the operator passes `forceLedgerDesync`.
|
|
16
32
|
*/
|
|
17
|
-
export declare function restoreSnapshot(vaultPath: string, name: string): Promise<void>;
|
|
33
|
+
export declare function restoreSnapshot(vaultPath: string, name: string, opts?: RestoreOptions): Promise<void>;
|
|
18
34
|
/**
|
|
19
35
|
* List all snapshots in the vault, sorted by timestamp (oldest first).
|
|
20
36
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint.d.ts","sourceRoot":"","sources":["../../src/snapshot/checkpoint.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"checkpoint.d.ts","sourceRoot":"","sources":["../../src/snapshot/checkpoint.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC9B,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAwHD;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAoD3F;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACpC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,cAAc,GACnB,OAAO,CAAC,IAAI,CAAC,CAsEf;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA2B9E"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright 2026 Usertools, Inc.
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { mkdir, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
|
|
5
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
6
|
+
import { withAuditWriterLock } from "../audit/chain.js";
|
|
5
7
|
// ── Constants ──
|
|
6
8
|
const SNAPSHOTS_DIR = "snapshots";
|
|
7
9
|
/** Directories to exclude from snapshots */
|
|
@@ -13,7 +15,13 @@ const INCLUDED_PATHS = new Set([
|
|
|
13
15
|
"patterns",
|
|
14
16
|
"usertrust.config.json",
|
|
15
17
|
"leases.json",
|
|
18
|
+
// SNAP-1: the durable money mirror. Captured so a restore rolls the audit chain
|
|
19
|
+
// and the money ledger back together, never one without the other.
|
|
20
|
+
"spend-ledger.json",
|
|
16
21
|
]);
|
|
22
|
+
/** Never captured: advisory lock file living inside audit/. */
|
|
23
|
+
const NEVER_CAPTURE = new Set([".audit-writer.lock"]);
|
|
24
|
+
const LOCK_FILE_NAME = ".audit-writer.lock";
|
|
17
25
|
// ── Internals ──
|
|
18
26
|
/**
|
|
19
27
|
* Recursively collect all files under a directory, returning relative paths.
|
|
@@ -35,6 +43,10 @@ async function collectFiles(basePath, currentPath) {
|
|
|
35
43
|
results.push(...nested);
|
|
36
44
|
}
|
|
37
45
|
else if (entry.isFile()) {
|
|
46
|
+
// Never capture the audit-writer advisory lock — restoring a stale lock
|
|
47
|
+
// would falsely block a future writer.
|
|
48
|
+
if (NEVER_CAPTURE.has(entry.name))
|
|
49
|
+
continue;
|
|
38
50
|
results.push(relPath);
|
|
39
51
|
}
|
|
40
52
|
}
|
|
@@ -103,11 +115,34 @@ export async function createSnapshot(vaultPath, name) {
|
|
|
103
115
|
entries[relPath] = content.toString("base64");
|
|
104
116
|
totalSize += content.length;
|
|
105
117
|
}
|
|
118
|
+
// Forensic head anchors: the audit chain head and money-mirror value at capture
|
|
119
|
+
// time. Best-effort (a fresh vault has neither); the desync guard on restore keys
|
|
120
|
+
// off payload presence, not these fields, so their absence never weakens it.
|
|
121
|
+
let auditHead;
|
|
122
|
+
try {
|
|
123
|
+
const metaRaw = await readFile(join(vaultPath, "audit", "events.jsonl.meta"), "utf-8");
|
|
124
|
+
const m = JSON.parse(metaRaw);
|
|
125
|
+
auditHead = { lastHash: m.lastHash, sequence: m.sequence };
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
/* no audit head yet */
|
|
129
|
+
}
|
|
130
|
+
let budgetSpent;
|
|
131
|
+
try {
|
|
132
|
+
const led = JSON.parse(await readFile(join(vaultPath, "spend-ledger.json"), "utf-8"));
|
|
133
|
+
if (typeof led.budgetSpent === "number")
|
|
134
|
+
budgetSpent = led.budgetSpent;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
/* no ledger yet */
|
|
138
|
+
}
|
|
106
139
|
const meta = {
|
|
107
140
|
name,
|
|
108
141
|
timestamp: new Date().toISOString(),
|
|
109
142
|
files,
|
|
110
143
|
size: totalSize,
|
|
144
|
+
...(auditHead !== undefined ? { auditHead } : {}),
|
|
145
|
+
...(budgetSpent !== undefined ? { budgetSpent } : {}),
|
|
111
146
|
};
|
|
112
147
|
const payload = { meta, entries };
|
|
113
148
|
const dir = snapshotsDir(vaultPath);
|
|
@@ -118,28 +153,77 @@ export async function createSnapshot(vaultPath, name) {
|
|
|
118
153
|
}
|
|
119
154
|
/**
|
|
120
155
|
* Restore the vault state from a named snapshot.
|
|
121
|
-
*
|
|
156
|
+
*
|
|
157
|
+
* Atomic (stage-then-commit), audit-writer-lock-aware, and refuses any restore
|
|
158
|
+
* that would sever money<->audit correspondence:
|
|
159
|
+
* - a snapshot that rolls back the audit chain MUST carry spend-ledger.json;
|
|
160
|
+
* - a live TigerBeetle store (which cannot be file-rolled-back) blocks an audit
|
|
161
|
+
* rollback unless the operator passes `forceLedgerDesync`.
|
|
122
162
|
*/
|
|
123
|
-
export async function restoreSnapshot(vaultPath, name) {
|
|
163
|
+
export async function restoreSnapshot(vaultPath, name, opts) {
|
|
124
164
|
validateSnapshotName(name);
|
|
125
165
|
const filePath = snapshotFilePath(vaultPath, name);
|
|
126
166
|
const raw = await readFile(filePath, "utf-8");
|
|
127
167
|
const payload = JSON.parse(raw);
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
168
|
+
const entries = Object.entries(payload.entries);
|
|
169
|
+
const rollsBackAudit = entries.some(([p]) => p.startsWith("audit/"));
|
|
170
|
+
const hasLedger = Object.prototype.hasOwnProperty.call(payload.entries, "spend-ledger.json");
|
|
171
|
+
// Desync guard 1: a snapshot that rolls the audit chain back MUST carry the money
|
|
172
|
+
// mirror, or restoring audit alone deletes spend events whose money still exists.
|
|
173
|
+
if (rollsBackAudit && !hasLedger) {
|
|
174
|
+
throw new Error("Refusing restore: snapshot rolls back the audit chain but has no spend-ledger.json — money and audit would desync. Re-create the snapshot with a version that captures spend-ledger.json.");
|
|
175
|
+
}
|
|
176
|
+
// Desync guard 2: TigerBeetle is a live append-only ledger that cannot be file-
|
|
177
|
+
// rolled-back to the snapshot point. Rolling audit back while TB moves on forks
|
|
178
|
+
// money<->audit. Refuse unless the operator explicitly acknowledges.
|
|
179
|
+
if (rollsBackAudit && existsSync(join(vaultPath, "tigerbeetle")) && !opts?.forceLedgerDesync) {
|
|
180
|
+
throw new Error("Refusing restore: a live TigerBeetle ledger is present and cannot be rolled back to match the restored audit chain. Reconcile TB first, then re-run with --force.");
|
|
181
|
+
}
|
|
182
|
+
// The advisory lock lives in audit/; ensure the dir exists so we can take it.
|
|
183
|
+
const auditDir = join(vaultPath, "audit");
|
|
184
|
+
await mkdir(auditDir, { recursive: true });
|
|
185
|
+
const logPath = join(auditDir, "events.jsonl");
|
|
186
|
+
await withAuditWriterLock(logPath, async () => {
|
|
134
187
|
const resolvedVault = resolve(vaultPath);
|
|
135
|
-
|
|
136
|
-
|
|
188
|
+
const staged = [];
|
|
189
|
+
try {
|
|
190
|
+
// Phase 1: validate every path and materialize each target as a temp file.
|
|
191
|
+
for (const [relPath, b64Content] of entries) {
|
|
192
|
+
if (relPath === "" || relPath === ".") {
|
|
193
|
+
throw new Error("Invalid empty path in snapshot entry");
|
|
194
|
+
}
|
|
195
|
+
// Never restore an advisory lock captured by an older snapshot.
|
|
196
|
+
if (relPath.split("/").pop() === LOCK_FILE_NAME)
|
|
197
|
+
continue;
|
|
198
|
+
const fullPath = join(vaultPath, relPath);
|
|
199
|
+
const resolvedPath = resolve(fullPath);
|
|
200
|
+
if (!resolvedPath.startsWith(`${resolvedVault}/`)) {
|
|
201
|
+
throw new Error(`Path traversal detected in snapshot: ${relPath}`);
|
|
202
|
+
}
|
|
203
|
+
await mkdir(dirname(fullPath), { recursive: true });
|
|
204
|
+
const tmpPath = `${fullPath}.restore-tmp`;
|
|
205
|
+
await writeFile(tmpPath, Buffer.from(b64Content, "base64"));
|
|
206
|
+
staged.push({ finalPath: fullPath, tmpPath });
|
|
207
|
+
}
|
|
208
|
+
// Phase 2: commit — rename staged temps into place. Renames are fast and
|
|
209
|
+
// same-filesystem-atomic, bounding the crash window to the rename loop.
|
|
210
|
+
for (const s of staged) {
|
|
211
|
+
await rename(s.tmpPath, s.finalPath);
|
|
212
|
+
}
|
|
137
213
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
214
|
+
catch (err) {
|
|
215
|
+
// Any failure before/at commit: remove uncommitted temps, leaving originals intact.
|
|
216
|
+
for (const s of staged) {
|
|
217
|
+
try {
|
|
218
|
+
await rm(s.tmpPath, { force: true });
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
/* best effort */
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
throw err;
|
|
225
|
+
}
|
|
226
|
+
});
|
|
143
227
|
}
|
|
144
228
|
/**
|
|
145
229
|
* List all snapshots in the vault, sorted by timestamp (oldest first).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../../src/snapshot/checkpoint.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;
|
|
1
|
+
{"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../../src/snapshot/checkpoint.ts"],"names":[],"mappings":"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"}
|
package/dist/streaming.d.ts
CHANGED
|
@@ -31,12 +31,30 @@ export interface GovernedStream<T> extends AsyncIterable<T> {
|
|
|
31
31
|
/** Resolves with the trust receipt when the stream completes */
|
|
32
32
|
receipt: Promise<TrustReceipt>;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Per-chunk hook called after token extraction but before yielding the chunk
|
|
36
|
+
* to the consumer. Throwing from this hook aborts the stream — onError will
|
|
37
|
+
* fire with the thrown value (this is how the anomaly detector trips a
|
|
38
|
+
* circuit breaker mid-stream).
|
|
39
|
+
*
|
|
40
|
+
* `delta` reflects the change in tokens compared to the previous chunk
|
|
41
|
+
* (cumulative reporting is normalised to a delta here).
|
|
42
|
+
*/
|
|
43
|
+
export interface ChunkObservation {
|
|
44
|
+
chunk: unknown;
|
|
45
|
+
deltaTokens: number;
|
|
46
|
+
cumulativeInputTokens: number;
|
|
47
|
+
cumulativeOutputTokens: number;
|
|
48
|
+
}
|
|
49
|
+
export type ChunkHook = (obs: ChunkObservation) => void;
|
|
34
50
|
/**
|
|
35
51
|
* Wraps a provider stream with token counting.
|
|
36
52
|
* Yields all chunks unchanged. Calls onComplete with accumulated usage
|
|
37
|
-
* when the stream ends, or onError on failure.
|
|
53
|
+
* when the stream ends, or onError on failure. An optional `onChunk` hook
|
|
54
|
+
* fires per chunk and can throw to abort the stream (used by the anomaly
|
|
55
|
+
* detector to trip a circuit breaker mid-stream).
|
|
38
56
|
*/
|
|
39
|
-
export declare function wrapStream<T>(stream: AsyncIterable<T>, kind: LLMClientKind, onComplete: (completion: StreamCompletion) => void, onError: (error: unknown, partial: StreamCompletion) => void): AsyncIterable<T>;
|
|
57
|
+
export declare function wrapStream<T>(stream: AsyncIterable<T>, kind: LLMClientKind, onComplete: (completion: StreamCompletion) => void, onError: (error: unknown, partial: StreamCompletion) => void, onChunk?: ChunkHook): AsyncIterable<T>;
|
|
40
58
|
/**
|
|
41
59
|
* Creates a GovernedStream: an AsyncIterable that also exposes a `.receipt`
|
|
42
60
|
* promise resolving to the TrustReceipt after the stream completes.
|
|
@@ -45,5 +63,5 @@ export declare function wrapStream<T>(stream: AsyncIterable<T>, kind: LLMClientK
|
|
|
45
63
|
* It should POST the actual cost and return the receipt.
|
|
46
64
|
* - `rejectReceipt` is called on stream error. It should VOID the hold.
|
|
47
65
|
*/
|
|
48
|
-
export declare function createGovernedStream<T>(stream: AsyncIterable<T>, kind: LLMClientKind, resolveReceipt: (completion: StreamCompletion) => Promise<TrustReceipt>, rejectReceipt: (error: unknown, partial: StreamCompletion) => void): GovernedStream<T>;
|
|
66
|
+
export declare function createGovernedStream<T>(stream: AsyncIterable<T>, kind: LLMClientKind, resolveReceipt: (completion: StreamCompletion) => Promise<TrustReceipt>, rejectReceipt: (error: unknown, partial: StreamCompletion) => void, onChunk?: ChunkHook): GovernedStream<T>;
|
|
49
67
|
//# sourceMappingURL=streaming.d.ts.map
|
package/dist/streaming.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIrE,MAAM,WAAW,WAAW;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,WAAW,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;IAC1D,gEAAgE;IAChE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/B;AAqDD
|
|
1
|
+
{"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIrE,MAAM,WAAW,WAAW;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,WAAW,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;IAC1D,gEAAgE;IAChE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/B;AAqDD;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,sBAAsB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC3B,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,IAAI,EAAE,aAAa,EACnB,UAAU,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAClD,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,KAAK,IAAI,EAC5D,OAAO,CAAC,EAAE,SAAS,GACjB,aAAa,CAAC,CAAC,CAAC,CAElB;AAiED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACrC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,IAAI,EAAE,aAAa,EACnB,cAAc,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,OAAO,CAAC,YAAY,CAAC,EACvE,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,KAAK,IAAI,EAClE,OAAO,CAAC,EAAE,SAAS,GACjB,cAAc,CAAC,CAAC,CAAC,CA+BnB"}
|
package/dist/streaming.js
CHANGED
|
@@ -42,41 +42,68 @@ function extractTokensFromChunk(chunk, kind) {
|
|
|
42
42
|
}
|
|
43
43
|
return { inputTokens: 0, outputTokens: 0 };
|
|
44
44
|
}
|
|
45
|
-
// ── Stream wrapper ──
|
|
46
45
|
/**
|
|
47
46
|
* Wraps a provider stream with token counting.
|
|
48
47
|
* Yields all chunks unchanged. Calls onComplete with accumulated usage
|
|
49
|
-
* when the stream ends, or onError on failure.
|
|
48
|
+
* when the stream ends, or onError on failure. An optional `onChunk` hook
|
|
49
|
+
* fires per chunk and can throw to abort the stream (used by the anomaly
|
|
50
|
+
* detector to trip a circuit breaker mid-stream).
|
|
50
51
|
*/
|
|
51
|
-
export function wrapStream(stream, kind, onComplete, onError) {
|
|
52
|
-
return wrapStreamImpl(stream, kind, onComplete, onError);
|
|
52
|
+
export function wrapStream(stream, kind, onComplete, onError, onChunk) {
|
|
53
|
+
return wrapStreamImpl(stream, kind, onComplete, onError, onChunk);
|
|
53
54
|
}
|
|
54
|
-
async function* wrapStreamImpl(stream, kind, onComplete, onError) {
|
|
55
|
+
async function* wrapStreamImpl(stream, kind, onComplete, onError, onChunk) {
|
|
55
56
|
let inputTokens = 0;
|
|
56
57
|
let outputTokens = 0;
|
|
57
58
|
let chunksDelivered = 0;
|
|
58
59
|
let usageReported = false;
|
|
60
|
+
// P4-STREAM-LEAK: settlement runs in `finally` so that a consumer who breaks
|
|
61
|
+
// out of the `for await` early (which drives generator `.return()`) settles the
|
|
62
|
+
// consumed cost EXACTLY like a normal end-of-stream — the hold is released, the
|
|
63
|
+
// audit event is written, and `.receipt` resolves. Only a thrown error voids.
|
|
64
|
+
let errored = false;
|
|
59
65
|
try {
|
|
60
66
|
for await (const chunk of stream) {
|
|
61
67
|
const tokens = extractTokensFromChunk(chunk, kind);
|
|
68
|
+
let deltaInput = 0;
|
|
69
|
+
let deltaOutput = 0;
|
|
62
70
|
// Use latest non-zero value (providers report cumulative or final)
|
|
63
71
|
if (tokens.inputTokens > 0) {
|
|
72
|
+
deltaInput = Math.max(0, tokens.inputTokens - inputTokens);
|
|
64
73
|
inputTokens = tokens.inputTokens;
|
|
65
74
|
usageReported = true;
|
|
66
75
|
}
|
|
67
76
|
if (tokens.outputTokens > 0) {
|
|
77
|
+
deltaOutput = Math.max(0, tokens.outputTokens - outputTokens);
|
|
68
78
|
outputTokens = tokens.outputTokens;
|
|
69
79
|
usageReported = true;
|
|
70
80
|
}
|
|
81
|
+
// Run hook BEFORE yielding so a throw aborts before the consumer sees it.
|
|
82
|
+
if (onChunk != null) {
|
|
83
|
+
onChunk({
|
|
84
|
+
chunk,
|
|
85
|
+
deltaTokens: deltaInput + deltaOutput,
|
|
86
|
+
cumulativeInputTokens: inputTokens,
|
|
87
|
+
cumulativeOutputTokens: outputTokens,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
71
90
|
yield chunk;
|
|
72
91
|
chunksDelivered++;
|
|
73
92
|
}
|
|
74
|
-
onComplete({ usage: { inputTokens, outputTokens }, chunksDelivered, usageReported });
|
|
75
93
|
}
|
|
76
94
|
catch (err) {
|
|
95
|
+
errored = true;
|
|
77
96
|
onError(err, { usage: { inputTokens, outputTokens }, chunksDelivered, usageReported });
|
|
78
97
|
throw err;
|
|
79
98
|
}
|
|
99
|
+
finally {
|
|
100
|
+
// Normal completion AND early termination (consumer break → generator
|
|
101
|
+
// `.return()`) both settle here. A thrown error already ran `onError` and set
|
|
102
|
+
// `errored`, so it is the only path that skips settlement (it voids instead).
|
|
103
|
+
if (!errored) {
|
|
104
|
+
onComplete({ usage: { inputTokens, outputTokens }, chunksDelivered, usageReported });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
80
107
|
}
|
|
81
108
|
// ── GovernedStream factory ──
|
|
82
109
|
/**
|
|
@@ -87,7 +114,7 @@ async function* wrapStreamImpl(stream, kind, onComplete, onError) {
|
|
|
87
114
|
* It should POST the actual cost and return the receipt.
|
|
88
115
|
* - `rejectReceipt` is called on stream error. It should VOID the hold.
|
|
89
116
|
*/
|
|
90
|
-
export function createGovernedStream(stream, kind, resolveReceipt, rejectReceipt) {
|
|
117
|
+
export function createGovernedStream(stream, kind, resolveReceipt, rejectReceipt, onChunk) {
|
|
91
118
|
let receiptResolve;
|
|
92
119
|
let receiptReject;
|
|
93
120
|
const receiptPromise = new Promise((resolve, reject) => {
|
|
@@ -105,7 +132,7 @@ export function createGovernedStream(stream, kind, resolveReceipt, rejectReceipt
|
|
|
105
132
|
}, (error, partial) => {
|
|
106
133
|
rejectReceipt(error, partial);
|
|
107
134
|
receiptReject(error);
|
|
108
|
-
});
|
|
135
|
+
}, onChunk);
|
|
109
136
|
return Object.assign(wrapped, {
|
|
110
137
|
receipt: receiptPromise,
|
|
111
138
|
});
|
package/dist/streaming.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming.js","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AA0CjC,yBAAyB;AAEzB,SAAS,sBAAsB,CAAC,KAAc,EAAE,IAAmB;IAClE,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IAC5C,CAAC;IAED,MAAM,CAAC,GAAG,KAAgC,CAAC;IAE3C,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACtF,MAAM,GAAG,GAAG,CAAC,CAAC,OAAkC,CAAC;YACjD,IAAI,GAAG,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACxD,MAAM,KAAK,GAAG,GAAG,CAAC,KAA+B,CAAC;gBAClD,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;YAClE,CAAC;QACF,CAAC;QACD,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACpD,MAAM,KAAK,GAAG,CAAC,CAAC,KAA+B,CAAC;gBAChD,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,aAAa,IAAI,CAAC,EAAE,CAAC;YACnE,CAAC;QACF,CAAC;QACD,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IAC5C,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACpD,MAAM,KAAK,GAAG,CAAC,CAAC,KAA+B,CAAC;YAChD,OAAO;gBACN,WAAW,EAAE,KAAK,CAAC,aAAa,IAAI,CAAC;gBACrC,YAAY,EAAE,KAAK,CAAC,iBAAiB,IAAI,CAAC;aAC1C,CAAC;QACH,CAAC;QACD,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IAC5C,CAAC;IAED,SAAS;IACT,IAAI,CAAC,CAAC,aAAa,IAAI,IAAI,IAAI,OAAO,CAAC,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;QACpE,MAAM,IAAI,GAAG,CAAC,CAAC,aAAuC,CAAC;QACvD,OAAO;YACN,WAAW,EAAE,IAAI,CAAC,gBAAgB,IAAI,CAAC;YACvC,YAAY,EAAE,IAAI,CAAC,oBAAoB,IAAI,CAAC;SAC5C,CAAC;IACH,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;AAC5C,CAAC;
|
|
1
|
+
{"version":3,"file":"streaming.js","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,11 +2,24 @@ import type { SkillManifest, SkillVerification, TrustConfig } from "../shared/ty
|
|
|
2
2
|
/**
|
|
3
3
|
* Checks whether a manifest's permissions are allowed by the config policy.
|
|
4
4
|
* Trusted publishers bypass permission restrictions.
|
|
5
|
+
*
|
|
6
|
+
* NOTE: this does NOT verify identity — it is only reached from `enforceSkillLoad`
|
|
7
|
+
* after the signature has been checked against a REGISTERED key, so the trusted-
|
|
8
|
+
* publisher bypass here cannot be triggered by a forged-publisher manifest.
|
|
9
|
+
* `integrityVerified` is set to false here; `enforceSkillLoad` overrides it once
|
|
10
|
+
* source bytes have been re-hashed.
|
|
5
11
|
*/
|
|
6
12
|
export declare function checkPermissions(manifest: SkillManifest, config: TrustConfig): SkillVerification;
|
|
7
13
|
/**
|
|
8
|
-
* Full verification pipeline: validate schema, verify signature
|
|
9
|
-
*
|
|
14
|
+
* Full verification pipeline: validate schema, verify signature against the
|
|
15
|
+
* REGISTERED publisher key(s), re-hash the loaded source against the signed
|
|
16
|
+
* entryHash, then check permissions. Returns a SkillVerification result.
|
|
17
|
+
* Throws SkillVerificationError on hard (schema) failures.
|
|
18
|
+
*
|
|
19
|
+
* @param entrySource The exact bytes to be executed. When provided, they are
|
|
20
|
+
* re-hashed and compared to the signed `entryHash` (SC-2). A call WITHOUT
|
|
21
|
+
* `entrySource` yields `integrityVerified:false` and MUST be treated by any
|
|
22
|
+
* executor as "integrity unverified — do not execute".
|
|
10
23
|
*/
|
|
11
|
-
export declare function enforceSkillLoad(manifest: SkillManifest, config: TrustConfig): SkillVerification;
|
|
24
|
+
export declare function enforceSkillLoad(manifest: SkillManifest, config: TrustConfig, entrySource?: string | Buffer): SkillVerification;
|
|
12
25
|
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/supply-chain/permissions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACX,aAAa,EAEb,iBAAiB,EACjB,WAAW,EACX,MAAM,oBAAoB,CAAC;AAY5B
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/supply-chain/permissions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACX,aAAa,EAEb,iBAAiB,EACjB,WAAW,EACX,MAAM,oBAAoB,CAAC;AAY5B;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,GAAG,iBAAiB,CAyBhG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC/B,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,WAAW,EACnB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAC3B,iBAAiB,CA0FnB"}
|