skillshield 1.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,88 @@
1
+ /**
2
+ * SkillShield — Unified Runtime Security Engine
3
+ *
4
+ * Combines: Pre-scan (guard) + Network Policy + Filesystem Jail +
5
+ * Runtime Monitor + Kill Switch + Audit Trail
6
+ *
7
+ * This is what makes SkillShield unique:
8
+ * - Snyk/Cisco only scan before install
9
+ * - NVIDIA OpenShell needs Linux + enterprise infra
10
+ * - Aegis only intercepts LLM API calls
11
+ * - SkillShield does scan + runtime in one CLI, cross-platform
12
+ */
13
+ export { NetworkPolicyEngine, parseNetworkPolicy } from './network-policy.js';
14
+ export { FilesystemJail, parseFilesystemPolicy } from './filesystem-jail.js';
15
+ export { RuntimeMonitor, getDefaultMonitorPolicy } from './runtime-monitor.js';
16
+ export { AuditTrail } from './audit-trail.js';
17
+ import { NetworkPolicyEngine, parseNetworkPolicy } from './network-policy.js';
18
+ import { FilesystemJail, parseFilesystemPolicy } from './filesystem-jail.js';
19
+ import { RuntimeMonitor, getDefaultMonitorPolicy } from './runtime-monitor.js';
20
+ import { AuditTrail } from './audit-trail.js';
21
+ /**
22
+ * The main Shield — orchestrates all security layers.
23
+ */
24
+ export class SkillShield {
25
+ constructor(config) {
26
+ this.config = config;
27
+ const frontmatter = config.frontmatter || {};
28
+ const workDir = config.workDir || process.cwd();
29
+ // Initialize network policy
30
+ const baseNetPolicy = parseNetworkPolicy(frontmatter);
31
+ const netPolicy = { ...baseNetPolicy, ...config.networkPolicy };
32
+ this.network = new NetworkPolicyEngine(netPolicy);
33
+ // Initialize filesystem jail
34
+ const baseFsPolicy = parseFilesystemPolicy(frontmatter, workDir);
35
+ const fsPolicy = { ...baseFsPolicy, ...config.filesystemPolicy };
36
+ this.filesystem = new FilesystemJail(fsPolicy);
37
+ // Initialize runtime monitor
38
+ const baseMonPolicy = getDefaultMonitorPolicy();
39
+ const monPolicy = { ...baseMonPolicy, ...config.monitorPolicy };
40
+ this.monitor = new RuntimeMonitor(monPolicy);
41
+ // Initialize audit trail
42
+ this.audit = new AuditTrail(config.skillId);
43
+ }
44
+ /**
45
+ * Generate the combined enforcement code that wraps skill execution.
46
+ * This code is prepended to the skill's execution context.
47
+ */
48
+ generateEnforcementWrapper() {
49
+ const networkCode = this.network.generateEnforcementCode();
50
+ const filesystemCode = this.filesystem.generateEnforcementCode();
51
+ return `
52
+ // ╔══════════════════════════════════════════════════════════════╗
53
+ // ║ SKILLSHIELD RUNTIME ENFORCEMENT ║
54
+ // ║ Network Policy + Filesystem Jail + Output Monitoring ║
55
+ // ╚══════════════════════════════════════════════════════════════╝
56
+ ${networkCode}
57
+ ${filesystemCode}
58
+ // ── SkillShield Ready ──
59
+ console.error('[SkillShield] Runtime enforcement active');
60
+ `;
61
+ }
62
+ /**
63
+ * Get the final shield report after execution.
64
+ */
65
+ getReport(scanScore, scanStatus, durationMs) {
66
+ const networkStats = this.network.getStats();
67
+ const fsStats = this.filesystem.getStats();
68
+ const monitorReport = this.monitor.getReport();
69
+ const auditVerification = this.audit.verify();
70
+ return {
71
+ skillId: this.config.skillId,
72
+ timestamp: new Date().toISOString(),
73
+ scanScore,
74
+ scanStatus,
75
+ killed: this.monitor.isKilled(),
76
+ killReason: monitorReport.killReason,
77
+ durationMs,
78
+ networkViolations: networkStats.violations,
79
+ filesystemViolations: fsStats.violations,
80
+ runtimeThreats: monitorReport.threatsDetected,
81
+ totalViolations: networkStats.violations + fsStats.violations + monitorReport.threatsDetected,
82
+ auditHash: this.audit.getLatestHash(),
83
+ auditLength: this.audit.getLength(),
84
+ auditVerified: auditVerification.valid,
85
+ };
86
+ }
87
+ }
88
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shield/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * SkillShield — Network Policy Engine
3
+ *
4
+ * Per-skill domain allowlisting. Skills declare which domains they need,
5
+ * and SkillShield blocks everything else at the DNS resolution level.
6
+ *
7
+ * This is what Snyk and Cisco DON'T do — they scan before install,
8
+ * but can't stop a skill from phoning home at runtime.
9
+ */
10
+ export interface NetworkPolicy {
11
+ /** Allowed domains (e.g., ["api.openai.com", "api.anthropic.com"]) */
12
+ allowedDomains: string[];
13
+ /** Allowed IP ranges in CIDR notation (e.g., ["10.0.0.0/8"]) */
14
+ allowedIPs?: string[];
15
+ /** Block all outbound by default? (true = default-deny) */
16
+ defaultDeny: boolean;
17
+ /** Max concurrent connections per skill */
18
+ maxConnections?: number;
19
+ /** Max data transfer in bytes (prevent exfiltration) */
20
+ maxTransferBytes?: number;
21
+ /** Block known malicious IPs/domains */
22
+ blockMalicious?: boolean;
23
+ }
24
+ export interface NetworkViolation {
25
+ timestamp: string;
26
+ type: 'DNS_BLOCKED' | 'CONNECTION_BLOCKED' | 'TRANSFER_EXCEEDED' | 'MALICIOUS_DOMAIN';
27
+ domain?: string;
28
+ ip?: string;
29
+ port?: number;
30
+ details: string;
31
+ }
32
+ export declare class NetworkPolicyEngine {
33
+ private policy;
34
+ private violations;
35
+ private connectionCount;
36
+ private transferredBytes;
37
+ private blockedDomains;
38
+ constructor(policy: NetworkPolicy);
39
+ /**
40
+ * Check if a domain is allowed by the policy.
41
+ * Returns true if allowed, false if blocked.
42
+ */
43
+ checkDomain(domain: string): boolean;
44
+ /**
45
+ * Check if a connection attempt is allowed.
46
+ */
47
+ checkConnection(domain: string, port: number): boolean;
48
+ /**
49
+ * Track data transfer and block if limit exceeded.
50
+ */
51
+ trackTransfer(bytes: number): boolean;
52
+ /**
53
+ * Generate the Node.js code that enforces this policy at runtime.
54
+ * This wraps the skill's execution with DNS/network interception.
55
+ */
56
+ generateEnforcementCode(): string;
57
+ private recordViolation;
58
+ getViolations(): NetworkViolation[];
59
+ getStats(): {
60
+ connections: number;
61
+ transferredBytes: number;
62
+ violations: number;
63
+ };
64
+ reset(): void;
65
+ }
66
+ /**
67
+ * Parse network policy from SKILL.md frontmatter.
68
+ * Expected format in frontmatter:
69
+ * network:
70
+ * allowed: ["api.openai.com", "api.anthropic.com"]
71
+ * maxTransferMB: 10
72
+ */
73
+ export declare function parseNetworkPolicy(frontmatter: Record<string, unknown>): NetworkPolicy;
74
+ //# sourceMappingURL=network-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-policy.d.ts","sourceRoot":"","sources":["../../src/shield/network-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,2DAA2D;IAC3D,WAAW,EAAE,OAAO,CAAC;IACrB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wCAAwC;IACxC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,aAAa,GAAG,oBAAoB,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AA0BD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,cAAc,CAAc;gBAExB,MAAM,EAAE,aAAa;IAQjC;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAgDpC;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAqBtD;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAcrC;;;OAGG;IACH,uBAAuB,IAAI,MAAM;IA6DjC,OAAO,CAAC,eAAe;IAOvB,aAAa,IAAI,gBAAgB,EAAE;IAInC,QAAQ,IAAI;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAQjF,KAAK,IAAI,IAAI;CAKd;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAYtF"}
@@ -0,0 +1,226 @@
1
+ /**
2
+ * SkillShield — Network Policy Engine
3
+ *
4
+ * Per-skill domain allowlisting. Skills declare which domains they need,
5
+ * and SkillShield blocks everything else at the DNS resolution level.
6
+ *
7
+ * This is what Snyk and Cisco DON'T do — they scan before install,
8
+ * but can't stop a skill from phoning home at runtime.
9
+ */
10
+ /** Known malicious domains commonly used in skill attacks */
11
+ const MALICIOUS_DOMAINS = [
12
+ 'evil.com',
13
+ 'attacker.com',
14
+ 'exfil.io',
15
+ 'c2server.net',
16
+ 'malware.download',
17
+ 'ngrok.io', // Tunneling — often used for exfiltration
18
+ 'requestbin.com', // Data capture
19
+ 'webhook.site', // Data capture
20
+ 'pipedream.net', // Data capture
21
+ 'burpcollaborator.net', // Pentesting tool
22
+ ];
23
+ /** Known mining pool domains */
24
+ const MINING_DOMAINS = [
25
+ 'pool.monero.cc',
26
+ 'xmr.pool.minergate.com',
27
+ 'cryptonight.usa.nicehash.com',
28
+ 'mine.xmrpool.net',
29
+ 'coinhive.com',
30
+ 'authedmine.com',
31
+ ];
32
+ export class NetworkPolicyEngine {
33
+ constructor(policy) {
34
+ this.violations = [];
35
+ this.connectionCount = 0;
36
+ this.transferredBytes = 0;
37
+ this.policy = policy;
38
+ this.blockedDomains = new Set([
39
+ ...MALICIOUS_DOMAINS,
40
+ ...(policy.blockMalicious !== false ? MINING_DOMAINS : []),
41
+ ]);
42
+ }
43
+ /**
44
+ * Check if a domain is allowed by the policy.
45
+ * Returns true if allowed, false if blocked.
46
+ */
47
+ checkDomain(domain) {
48
+ const normalizedDomain = domain.toLowerCase().trim();
49
+ // Check malicious domains first
50
+ if (this.blockedDomains.has(normalizedDomain)) {
51
+ this.recordViolation({
52
+ type: 'MALICIOUS_DOMAIN',
53
+ domain: normalizedDomain,
54
+ details: `Blocked known malicious domain: ${normalizedDomain}`,
55
+ });
56
+ return false;
57
+ }
58
+ // Check against subdomain patterns in malicious list
59
+ for (const malicious of this.blockedDomains) {
60
+ if (normalizedDomain.endsWith(`.${malicious}`)) {
61
+ this.recordViolation({
62
+ type: 'MALICIOUS_DOMAIN',
63
+ domain: normalizedDomain,
64
+ details: `Blocked subdomain of malicious domain: ${normalizedDomain} (parent: ${malicious})`,
65
+ });
66
+ return false;
67
+ }
68
+ }
69
+ // Default deny mode — only allowlisted domains pass
70
+ if (this.policy.defaultDeny) {
71
+ const isAllowed = this.policy.allowedDomains.some((allowed) => {
72
+ const normalizedAllowed = allowed.toLowerCase().trim();
73
+ return (normalizedDomain === normalizedAllowed ||
74
+ normalizedDomain.endsWith(`.${normalizedAllowed}`));
75
+ });
76
+ if (!isAllowed) {
77
+ this.recordViolation({
78
+ type: 'DNS_BLOCKED',
79
+ domain: normalizedDomain,
80
+ details: `Domain not in allowlist: ${normalizedDomain}. Allowed: [${this.policy.allowedDomains.join(', ')}]`,
81
+ });
82
+ return false;
83
+ }
84
+ }
85
+ return true;
86
+ }
87
+ /**
88
+ * Check if a connection attempt is allowed.
89
+ */
90
+ checkConnection(domain, port) {
91
+ // Check domain first
92
+ if (!this.checkDomain(domain)) {
93
+ return false;
94
+ }
95
+ // Check max connections
96
+ if (this.policy.maxConnections && this.connectionCount >= this.policy.maxConnections) {
97
+ this.recordViolation({
98
+ type: 'CONNECTION_BLOCKED',
99
+ domain,
100
+ port,
101
+ details: `Max connections exceeded: ${this.connectionCount}/${this.policy.maxConnections}`,
102
+ });
103
+ return false;
104
+ }
105
+ this.connectionCount++;
106
+ return true;
107
+ }
108
+ /**
109
+ * Track data transfer and block if limit exceeded.
110
+ */
111
+ trackTransfer(bytes) {
112
+ this.transferredBytes += bytes;
113
+ if (this.policy.maxTransferBytes && this.transferredBytes > this.policy.maxTransferBytes) {
114
+ this.recordViolation({
115
+ type: 'TRANSFER_EXCEEDED',
116
+ details: `Transfer limit exceeded: ${this.transferredBytes}/${this.policy.maxTransferBytes} bytes`,
117
+ });
118
+ return false;
119
+ }
120
+ return true;
121
+ }
122
+ /**
123
+ * Generate the Node.js code that enforces this policy at runtime.
124
+ * This wraps the skill's execution with DNS/network interception.
125
+ */
126
+ generateEnforcementCode() {
127
+ const allowedJSON = JSON.stringify(this.policy.allowedDomains);
128
+ const blockedJSON = JSON.stringify([...this.blockedDomains]);
129
+ return `
130
+ // ── SkillShield Network Policy Enforcement ──
131
+ const __ss_allowed = new Set(${allowedJSON}.map(d => d.toLowerCase()));
132
+ const __ss_blocked = new Set(${blockedJSON}.map(d => d.toLowerCase()));
133
+ const __ss_defaultDeny = ${this.policy.defaultDeny};
134
+ const __ss_maxTransfer = ${this.policy.maxTransferBytes || 0};
135
+ let __ss_transferred = 0;
136
+
137
+ const __ss_originalDnsLookup = require('dns').lookup;
138
+ require('dns').lookup = function(hostname, options, callback) {
139
+ const domain = hostname.toLowerCase();
140
+
141
+ // Block malicious
142
+ for (const blocked of __ss_blocked) {
143
+ if (domain === blocked || domain.endsWith('.' + blocked)) {
144
+ const err = new Error('[SkillShield] BLOCKED: ' + domain + ' is a known malicious domain');
145
+ err.code = 'ENOTFOUND';
146
+ if (typeof options === 'function') return options(err);
147
+ return callback(err);
148
+ }
149
+ }
150
+
151
+ // Default deny check
152
+ if (__ss_defaultDeny) {
153
+ let allowed = false;
154
+ for (const a of __ss_allowed) {
155
+ if (domain === a || domain.endsWith('.' + a)) { allowed = true; break; }
156
+ }
157
+ if (!allowed) {
158
+ const err = new Error('[SkillShield] BLOCKED: ' + domain + ' not in network policy allowlist');
159
+ err.code = 'ENOTFOUND';
160
+ if (typeof options === 'function') return options(err);
161
+ return callback(err);
162
+ }
163
+ }
164
+
165
+ return __ss_originalDnsLookup.call(this, hostname, options, callback);
166
+ };
167
+
168
+ // Intercept http/https to track transfer size
169
+ const __ss_origRequest = require('https').request;
170
+ require('https').request = function(...args) {
171
+ const req = __ss_origRequest.apply(this, args);
172
+ req.on('response', (res) => {
173
+ res.on('data', (chunk) => {
174
+ __ss_transferred += chunk.length;
175
+ if (__ss_maxTransfer > 0 && __ss_transferred > __ss_maxTransfer) {
176
+ res.destroy(new Error('[SkillShield] Transfer limit exceeded: ' + __ss_transferred + ' bytes'));
177
+ }
178
+ });
179
+ });
180
+ return req;
181
+ };
182
+ // ── End SkillShield Network Policy ──
183
+ `;
184
+ }
185
+ recordViolation(partial) {
186
+ this.violations.push({
187
+ ...partial,
188
+ timestamp: new Date().toISOString(),
189
+ });
190
+ }
191
+ getViolations() {
192
+ return [...this.violations];
193
+ }
194
+ getStats() {
195
+ return {
196
+ connections: this.connectionCount,
197
+ transferredBytes: this.transferredBytes,
198
+ violations: this.violations.length,
199
+ };
200
+ }
201
+ reset() {
202
+ this.violations = [];
203
+ this.connectionCount = 0;
204
+ this.transferredBytes = 0;
205
+ }
206
+ }
207
+ /**
208
+ * Parse network policy from SKILL.md frontmatter.
209
+ * Expected format in frontmatter:
210
+ * network:
211
+ * allowed: ["api.openai.com", "api.anthropic.com"]
212
+ * maxTransferMB: 10
213
+ */
214
+ export function parseNetworkPolicy(frontmatter) {
215
+ const network = (frontmatter.network || frontmatter.networking || {});
216
+ const allowed = (network.allowed || network.domains || []);
217
+ const maxTransferMB = (network.maxTransferMB || network.maxTransfer || 10);
218
+ return {
219
+ allowedDomains: allowed.length > 0 ? allowed : [],
220
+ defaultDeny: allowed.length > 0, // If skill declares domains, enforce them
221
+ maxConnections: network.maxConnections || 50,
222
+ maxTransferBytes: maxTransferMB * 1024 * 1024,
223
+ blockMalicious: true,
224
+ };
225
+ }
226
+ //# sourceMappingURL=network-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-policy.js","sourceRoot":"","sources":["../../src/shield/network-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * SkillShield — Runtime Monitor + Kill Switch
3
+ *
4
+ * Real-time monitoring of skill execution. Watches stdout/stderr
5
+ * for threat patterns, tracks resource consumption, and kills the
6
+ * process if anomalies are detected.
7
+ *
8
+ * This is the core differentiator: Snyk scans before install,
9
+ * SkillShield watches DURING execution.
10
+ */
11
+ import { ChildProcess } from 'child_process';
12
+ import { type ThreatCategory, type SeverityLevel } from '../guard/patterns.js';
13
+ export interface MonitorPolicy {
14
+ /** Max execution time in ms (kill switch) */
15
+ maxExecutionTime: number;
16
+ /** Max memory in MB (kill switch) */
17
+ maxMemoryMB: number;
18
+ /** Max output size in bytes (prevent output flooding) */
19
+ maxOutputBytes: number;
20
+ /** Severity threshold to trigger kill (CRITICAL = kill immediately) */
21
+ killOnSeverity: SeverityLevel;
22
+ /** Re-scan output for threats in real-time */
23
+ enableOutputScanning: boolean;
24
+ /** Max violations before kill */
25
+ maxViolations: number;
26
+ /** Categories that trigger immediate kill */
27
+ criticalCategories: ThreatCategory[];
28
+ }
29
+ export interface RuntimeEvent {
30
+ timestamp: string;
31
+ type: 'STDOUT' | 'STDERR' | 'THREAT_DETECTED' | 'RESOURCE_LIMIT' | 'KILL_SWITCH' | 'ANOMALY' | 'EXIT';
32
+ severity: SeverityLevel;
33
+ details: string;
34
+ data?: unknown;
35
+ }
36
+ export interface MonitorReport {
37
+ startTime: string;
38
+ endTime?: string;
39
+ durationMs: number;
40
+ events: RuntimeEvent[];
41
+ threatsDetected: number;
42
+ killed: boolean;
43
+ killReason?: string;
44
+ resourceUsage: {
45
+ peakMemoryMB: number;
46
+ totalOutputBytes: number;
47
+ cpuTimeMs: number;
48
+ };
49
+ }
50
+ export declare class RuntimeMonitor {
51
+ private policy;
52
+ private events;
53
+ private startTime;
54
+ private outputBytes;
55
+ private threatsDetected;
56
+ private killed;
57
+ private killReason?;
58
+ private process?;
59
+ private killTimer?;
60
+ private memoryCheckInterval?;
61
+ /** Subset of patterns optimized for real-time output scanning */
62
+ private runtimePatterns;
63
+ constructor(policy: MonitorPolicy);
64
+ /**
65
+ * Attach the monitor to a running child process.
66
+ */
67
+ attach(childProcess: ChildProcess): void;
68
+ /**
69
+ * Process output from the skill and check for threats.
70
+ */
71
+ private onOutput;
72
+ /**
73
+ * Scan skill output for threat patterns in real-time.
74
+ * This catches skills that generate malicious output (e.g., writing
75
+ * shell commands to stdout that another tool might execute).
76
+ */
77
+ private scanOutput;
78
+ /**
79
+ * Check process memory usage.
80
+ */
81
+ private checkMemory;
82
+ /**
83
+ * Kill the child process — the kill switch.
84
+ */
85
+ killProcess(reason: string, details: string): void;
86
+ /**
87
+ * Clean up timers and intervals.
88
+ */
89
+ private cleanup;
90
+ /**
91
+ * Compare severity levels. Returns positive if a >= b.
92
+ */
93
+ private compareSeverity;
94
+ private recordEvent;
95
+ /**
96
+ * Generate the final monitoring report.
97
+ */
98
+ getReport(): MonitorReport;
99
+ isKilled(): boolean;
100
+ getEventCount(): number;
101
+ }
102
+ /**
103
+ * Default monitor policy — strict but reasonable for developer use.
104
+ */
105
+ export declare function getDefaultMonitorPolicy(): MonitorPolicy;
106
+ //# sourceMappingURL=runtime-monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-monitor.d.ts","sourceRoot":"","sources":["../../src/shield/runtime-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAA6C,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1H,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,gBAAgB,EAAE,MAAM,CAAC;IACzB,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,cAAc,EAAE,aAAa,CAAC;IAC9B,8CAA8C;IAC9C,oBAAoB,EAAE,OAAO,CAAC;IAC9B,iCAAiC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,kBAAkB,EAAE,cAAc,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,aAAa,GAAG,SAAS,GAAG,MAAM,CAAC;IACtG,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAC,CAAe;IAC/B,OAAO,CAAC,SAAS,CAAC,CAAiB;IACnC,OAAO,CAAC,mBAAmB,CAAC,CAAiB;IAE7C,iEAAiE;IACjE,OAAO,CAAC,eAAe,CAAqB;gBAEhC,MAAM,EAAE,aAAa;IAQjC;;OAEG;IACH,MAAM,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI;IAyCxC;;OAEG;IACH,OAAO,CAAC,QAAQ;IAahB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IA+ClB;;OAEG;IACH,OAAO,CAAC,WAAW;IAmBnB;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IA0BlD;;OAEG;IACH,OAAO,CAAC,OAAO;IAWf;;OAEG;IACH,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,SAAS,IAAI,aAAa;IAkB1B,QAAQ,IAAI,OAAO;IAInB,aAAa,IAAI,MAAM;CAGxB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,aAAa,CAevD"}