@mondaydotcomorg/atp-providers 0.17.14

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.
Files changed (58) hide show
  1. package/README.md +430 -0
  2. package/__tests__/oauth-integration.test.ts +457 -0
  3. package/__tests__/scope-checkers.test.ts +560 -0
  4. package/__tests__/token-expiration.test.ts +308 -0
  5. package/dist/audit/jsonl.d.ts +29 -0
  6. package/dist/audit/jsonl.d.ts.map +1 -0
  7. package/dist/audit/jsonl.js +163 -0
  8. package/dist/audit/jsonl.js.map +1 -0
  9. package/dist/audit/opentelemetry.d.ts +23 -0
  10. package/dist/audit/opentelemetry.d.ts.map +1 -0
  11. package/dist/audit/opentelemetry.js +240 -0
  12. package/dist/audit/opentelemetry.js.map +1 -0
  13. package/dist/audit/otel-metrics.d.ts +111 -0
  14. package/dist/audit/otel-metrics.d.ts.map +1 -0
  15. package/dist/audit/otel-metrics.js +115 -0
  16. package/dist/audit/otel-metrics.js.map +1 -0
  17. package/dist/auth/env.d.ts +21 -0
  18. package/dist/auth/env.d.ts.map +1 -0
  19. package/dist/auth/env.js +48 -0
  20. package/dist/auth/env.js.map +1 -0
  21. package/dist/cache/file.d.ts +47 -0
  22. package/dist/cache/file.d.ts.map +1 -0
  23. package/dist/cache/file.js +262 -0
  24. package/dist/cache/file.js.map +1 -0
  25. package/dist/cache/memory.d.ts +30 -0
  26. package/dist/cache/memory.d.ts.map +1 -0
  27. package/dist/cache/memory.js +81 -0
  28. package/dist/cache/memory.js.map +1 -0
  29. package/dist/cache/redis.d.ts +28 -0
  30. package/dist/cache/redis.d.ts.map +1 -0
  31. package/dist/cache/redis.js +124 -0
  32. package/dist/cache/redis.js.map +1 -0
  33. package/dist/index.d.ts +10 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +9 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/oauth/index.d.ts +2 -0
  38. package/dist/oauth/index.d.ts.map +1 -0
  39. package/dist/oauth/index.js +2 -0
  40. package/dist/oauth/index.js.map +1 -0
  41. package/dist/oauth/scope-checkers.d.ts +61 -0
  42. package/dist/oauth/scope-checkers.d.ts.map +1 -0
  43. package/dist/oauth/scope-checkers.js +166 -0
  44. package/dist/oauth/scope-checkers.js.map +1 -0
  45. package/package.json +26 -0
  46. package/project.json +31 -0
  47. package/src/audit/jsonl.ts +189 -0
  48. package/src/audit/opentelemetry.ts +286 -0
  49. package/src/audit/otel-metrics.ts +122 -0
  50. package/src/auth/env.ts +65 -0
  51. package/src/cache/file.ts +330 -0
  52. package/src/cache/memory.ts +105 -0
  53. package/src/cache/redis.ts +160 -0
  54. package/src/index.ts +32 -0
  55. package/src/oauth/index.ts +1 -0
  56. package/src/oauth/scope-checkers.ts +196 -0
  57. package/tsconfig.json +14 -0
  58. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,308 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import type { AuthProvider, UserCredentialData } from '@mondaydotcomorg/atp-protocol';
3
+
4
+ // Test implementation that mimics production behavior
5
+ class TestAuthProvider implements AuthProvider {
6
+ name = 'test';
7
+ private userCredentials = new Map<string, Map<string, UserCredentialData>>();
8
+
9
+ async getCredential(key: string): Promise<string | null> {
10
+ return null;
11
+ }
12
+
13
+ async setCredential(key: string, value: string): Promise<void> {}
14
+
15
+ async deleteCredential(key: string): Promise<void> {}
16
+
17
+ async getUserCredential(userId: string, provider: string): Promise<UserCredentialData | null> {
18
+ const userMap = this.userCredentials.get(userId);
19
+ const creds = userMap?.get(provider);
20
+
21
+ if (!creds) {
22
+ return null;
23
+ }
24
+
25
+ // Check if token has expired
26
+ if (creds.expiresAt && creds.expiresAt < Date.now()) {
27
+ // In production, would attempt to refresh here
28
+ return null;
29
+ }
30
+
31
+ return creds;
32
+ }
33
+
34
+ async setUserCredential(
35
+ userId: string,
36
+ provider: string,
37
+ data: UserCredentialData
38
+ ): Promise<void> {
39
+ if (!this.userCredentials.has(userId)) {
40
+ this.userCredentials.set(userId, new Map());
41
+ }
42
+ this.userCredentials.get(userId)!.set(provider, data);
43
+ }
44
+
45
+ async deleteUserCredential(userId: string, provider: string): Promise<void> {
46
+ this.userCredentials.get(userId)?.delete(provider);
47
+ }
48
+
49
+ async listUserProviders(userId: string): Promise<string[]> {
50
+ const userMap = this.userCredentials.get(userId);
51
+ return userMap ? Array.from(userMap.keys()) : [];
52
+ }
53
+ }
54
+
55
+ describe('Token Expiration Handling', () => {
56
+ let authProvider: TestAuthProvider;
57
+
58
+ beforeEach(() => {
59
+ authProvider = new TestAuthProvider();
60
+ });
61
+
62
+ describe('getUserCredential with expired token', () => {
63
+ it('should return null for expired token', async () => {
64
+ const userId = 'user123';
65
+ const provider = 'github';
66
+
67
+ // Store credential with expired token
68
+ const expiredTime = Date.now() - 3600000; // 1 hour ago
69
+ await authProvider.setUserCredential(userId, provider, {
70
+ token: 'gho_expired_token',
71
+ scopes: ['repo'],
72
+ expiresAt: expiredTime,
73
+ });
74
+
75
+ // Should return null due to expiration
76
+ const result = await authProvider.getUserCredential(userId, provider);
77
+
78
+ expect(result).toBeNull();
79
+ });
80
+
81
+ it('should return credential for non-expired token', async () => {
82
+ const userId = 'user123';
83
+ const provider = 'github';
84
+
85
+ // Store credential with valid token
86
+ const futureTime = Date.now() + 3600000; // 1 hour from now
87
+ const credentials: UserCredentialData = {
88
+ token: 'gho_valid_token',
89
+ scopes: ['repo'],
90
+ expiresAt: futureTime,
91
+ };
92
+
93
+ await authProvider.setUserCredential(userId, provider, credentials);
94
+
95
+ // Should return the credential
96
+ const result = await authProvider.getUserCredential(userId, provider);
97
+
98
+ expect(result).toEqual(credentials);
99
+ });
100
+
101
+ it('should return credential when no expiration time set', async () => {
102
+ const userId = 'user123';
103
+ const provider = 'github';
104
+
105
+ // Store credential without expiration
106
+ const credentials: UserCredentialData = {
107
+ token: 'gho_no_expiry_token',
108
+ scopes: ['repo'],
109
+ };
110
+
111
+ await authProvider.setUserCredential(userId, provider, credentials);
112
+
113
+ // Should return the credential
114
+ const result = await authProvider.getUserCredential(userId, provider);
115
+
116
+ expect(result).toEqual(credentials);
117
+ });
118
+
119
+ it('should handle token that expires right at current time', async () => {
120
+ const userId = 'user123';
121
+ const provider = 'github';
122
+
123
+ // Store credential that expires exactly now
124
+ const nowTime = Date.now();
125
+ await authProvider.setUserCredential(userId, provider, {
126
+ token: 'gho_expires_now_token',
127
+ scopes: ['repo'],
128
+ expiresAt: nowTime - 1, // Expires 1ms in the past to ensure it's expired
129
+ });
130
+
131
+ // Should return null (expired)
132
+ const result = await authProvider.getUserCredential(userId, provider);
133
+
134
+ expect(result).toBeNull();
135
+ });
136
+ });
137
+
138
+ describe('Token refresh scenarios', () => {
139
+ it('should store refresh token when provided', async () => {
140
+ const userId = 'user123';
141
+ const provider = 'google';
142
+
143
+ const credentials: UserCredentialData = {
144
+ token: 'ya29.access_token',
145
+ refreshToken: 'refresh_token_here',
146
+ scopes: ['calendar'],
147
+ expiresAt: Date.now() + 3600000,
148
+ };
149
+
150
+ await authProvider.setUserCredential(userId, provider, credentials);
151
+
152
+ const result = await authProvider.getUserCredential(userId, provider);
153
+
154
+ expect(result?.refreshToken).toBe('refresh_token_here');
155
+ });
156
+
157
+ it('should handle credentials without refresh token', async () => {
158
+ const userId = 'user123';
159
+ const provider = 'github';
160
+
161
+ const credentials: UserCredentialData = {
162
+ token: 'gho_token',
163
+ scopes: ['repo'],
164
+ expiresAt: Date.now() + 3600000,
165
+ };
166
+
167
+ await authProvider.setUserCredential(userId, provider, credentials);
168
+
169
+ const result = await authProvider.getUserCredential(userId, provider);
170
+
171
+ expect(result?.refreshToken).toBeUndefined();
172
+ });
173
+ });
174
+
175
+ describe('Multiple users with different expiration times', () => {
176
+ it('should handle different expiration times for different users', async () => {
177
+ const provider = 'github';
178
+
179
+ // User 1: expired token
180
+ await authProvider.setUserCredential('user1', provider, {
181
+ token: 'token1',
182
+ scopes: ['repo'],
183
+ expiresAt: Date.now() - 1000, // Expired
184
+ });
185
+
186
+ // User 2: valid token
187
+ await authProvider.setUserCredential('user2', provider, {
188
+ token: 'token2',
189
+ scopes: ['repo'],
190
+ expiresAt: Date.now() + 3600000, // Valid
191
+ });
192
+
193
+ const user1Creds = await authProvider.getUserCredential('user1', provider);
194
+ const user2Creds = await authProvider.getUserCredential('user2', provider);
195
+
196
+ expect(user1Creds).toBeNull(); // Expired
197
+ expect(user2Creds).not.toBeNull(); // Valid
198
+ expect(user2Creds?.token).toBe('token2');
199
+ });
200
+
201
+ it('should handle same user with multiple providers at different expiration states', async () => {
202
+ const userId = 'user123';
203
+
204
+ // GitHub: expired
205
+ await authProvider.setUserCredential(userId, 'github', {
206
+ token: 'github_token',
207
+ scopes: ['repo'],
208
+ expiresAt: Date.now() - 1000,
209
+ });
210
+
211
+ // Google: valid
212
+ await authProvider.setUserCredential(userId, 'google', {
213
+ token: 'google_token',
214
+ scopes: ['calendar'],
215
+ expiresAt: Date.now() + 3600000,
216
+ });
217
+
218
+ const githubCreds = await authProvider.getUserCredential(userId, 'github');
219
+ const googleCreds = await authProvider.getUserCredential(userId, 'google');
220
+
221
+ expect(githubCreds).toBeNull();
222
+ expect(googleCreds).not.toBeNull();
223
+ expect(googleCreds?.token).toBe('google_token');
224
+ });
225
+ });
226
+
227
+ describe('Token metadata handling', () => {
228
+ it('should preserve metadata with expired tokens', async () => {
229
+ const userId = 'user123';
230
+ const provider = 'github';
231
+
232
+ await authProvider.setUserCredential(userId, provider, {
233
+ token: 'token',
234
+ scopes: ['repo'],
235
+ expiresAt: Date.now() + 3600000,
236
+ metadata: {
237
+ username: 'octocat',
238
+ userId: 'github_123',
239
+ },
240
+ });
241
+
242
+ const result = await authProvider.getUserCredential(userId, provider);
243
+
244
+ expect(result?.metadata).toEqual({
245
+ username: 'octocat',
246
+ userId: 'github_123',
247
+ });
248
+ });
249
+
250
+ it('should handle credentials with complex metadata', async () => {
251
+ const userId = 'user123';
252
+ const provider = 'microsoft';
253
+
254
+ const complexMetadata = {
255
+ tenantId: 'tenant-id',
256
+ objectId: 'object-id',
257
+ permissions: ['User.Read', 'Mail.Send'],
258
+ nested: {
259
+ data: {
260
+ value: 123,
261
+ },
262
+ },
263
+ };
264
+
265
+ await authProvider.setUserCredential(userId, provider, {
266
+ token: 'token',
267
+ scopes: ['User.Read'],
268
+ expiresAt: Date.now() + 3600000,
269
+ metadata: complexMetadata,
270
+ });
271
+
272
+ const result = await authProvider.getUserCredential(userId, provider);
273
+
274
+ expect(result?.metadata).toEqual(complexMetadata);
275
+ });
276
+ });
277
+
278
+ describe('Scope management', () => {
279
+ it('should handle empty scopes array', async () => {
280
+ const userId = 'user123';
281
+ const provider = 'github';
282
+
283
+ await authProvider.setUserCredential(userId, provider, {
284
+ token: 'token',
285
+ scopes: [],
286
+ expiresAt: Date.now() + 3600000,
287
+ });
288
+
289
+ const result = await authProvider.getUserCredential(userId, provider);
290
+
291
+ expect(result?.scopes).toEqual([]);
292
+ });
293
+
294
+ it('should handle undefined scopes', async () => {
295
+ const userId = 'user123';
296
+ const provider = 'github';
297
+
298
+ await authProvider.setUserCredential(userId, provider, {
299
+ token: 'token',
300
+ expiresAt: Date.now() + 3600000,
301
+ });
302
+
303
+ const result = await authProvider.getUserCredential(userId, provider);
304
+
305
+ expect(result?.scopes).toBeUndefined();
306
+ });
307
+ });
308
+ });
@@ -0,0 +1,29 @@
1
+ import type { AuditEvent, AuditFilter, AuditSink } from '@mondaydotcomorg/atp-protocol';
2
+ /**
3
+ * JSONL (JSON Lines) audit sink
4
+ * Writes audit events to a file, one JSON object per line
5
+ * Simple, append-only, easy to parse with standard tools
6
+ */
7
+ export declare class JSONLAuditSink implements AuditSink {
8
+ name: string;
9
+ private filePath;
10
+ private sanitizeSecrets;
11
+ private buffer;
12
+ private flushInterval;
13
+ private batchSize;
14
+ constructor(options: {
15
+ filePath: string;
16
+ sanitizeSecrets?: boolean;
17
+ batchSize?: number;
18
+ flushIntervalMs?: number;
19
+ });
20
+ write(event: AuditEvent): Promise<void>;
21
+ writeBatch(events: AuditEvent[]): Promise<void>;
22
+ query(filter: AuditFilter): Promise<AuditEvent[]>;
23
+ disconnect(): Promise<void>;
24
+ private flush;
25
+ private sanitizeEvent;
26
+ private sanitizeString;
27
+ private sanitizeObject;
28
+ }
29
+ //# sourceMappingURL=jsonl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../../src/audit/jsonl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAKxF;;;;GAIG;AACH,qBAAa,cAAe,YAAW,SAAS;IAC/C,IAAI,SAAW;IACf,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAU;IACjC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,EAAE;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,eAAe,CAAC,EAAE,MAAM,CAAC;KACzB;IAuBK,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvC,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAa/C,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAqCjD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAUnB,KAAK;IAOnB,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,cAAc;CA0BtB"}
@@ -0,0 +1,163 @@
1
+ import { appendFile, readFile, mkdir } from 'node:fs/promises';
2
+ import { existsSync } from 'node:fs';
3
+ import { dirname } from 'node:path';
4
+ /**
5
+ * JSONL (JSON Lines) audit sink
6
+ * Writes audit events to a file, one JSON object per line
7
+ * Simple, append-only, easy to parse with standard tools
8
+ */
9
+ export class JSONLAuditSink {
10
+ name = 'jsonl';
11
+ filePath;
12
+ sanitizeSecrets;
13
+ buffer = [];
14
+ flushInterval = null;
15
+ batchSize;
16
+ constructor(options) {
17
+ this.filePath = options.filePath;
18
+ this.sanitizeSecrets = options.sanitizeSecrets ?? true;
19
+ this.batchSize = options.batchSize || 10;
20
+ const dir = dirname(this.filePath);
21
+ if (!existsSync(dir)) {
22
+ mkdir(dir, { recursive: true }).catch((err) => {
23
+ console.error(`Failed to create audit directory: ${err.message}`);
24
+ });
25
+ }
26
+ if (options.flushIntervalMs) {
27
+ this.flushInterval = setInterval(() => {
28
+ if (this.buffer.length > 0) {
29
+ this.flush().catch((err) => {
30
+ console.error(`Failed to flush audit buffer: ${err.message}`);
31
+ });
32
+ }
33
+ }, options.flushIntervalMs);
34
+ }
35
+ }
36
+ async write(event) {
37
+ const sanitized = this.sanitizeSecrets ? this.sanitizeEvent(event) : event;
38
+ const line = JSON.stringify(sanitized) + '\n';
39
+ try {
40
+ await appendFile(this.filePath, line, 'utf8');
41
+ }
42
+ catch (error) {
43
+ console.error(`Failed to write audit event: ${error.message}`);
44
+ throw error;
45
+ }
46
+ }
47
+ async writeBatch(events) {
48
+ const sanitized = this.sanitizeSecrets ? events.map((e) => this.sanitizeEvent(e)) : events;
49
+ const lines = sanitized.map((e) => JSON.stringify(e)).join('\n') + '\n';
50
+ try {
51
+ await appendFile(this.filePath, lines, 'utf8');
52
+ }
53
+ catch (error) {
54
+ console.error(`Failed to write audit batch: ${error.message}`);
55
+ throw error;
56
+ }
57
+ }
58
+ async query(filter) {
59
+ try {
60
+ const content = await readFile(this.filePath, 'utf8');
61
+ const lines = content.split('\n').filter((line) => line.trim());
62
+ const events = lines.map((line) => JSON.parse(line));
63
+ return events
64
+ .filter((event) => {
65
+ if (filter.clientId && event.clientId !== filter.clientId)
66
+ return false;
67
+ if (filter.userId && event.userId !== filter.userId)
68
+ return false;
69
+ if (filter.from && event.timestamp < filter.from)
70
+ return false;
71
+ if (filter.to && event.timestamp > filter.to)
72
+ return false;
73
+ if (filter.resource && event.resource !== filter.resource)
74
+ return false;
75
+ if (filter.eventType) {
76
+ const types = Array.isArray(filter.eventType) ? filter.eventType : [filter.eventType];
77
+ if (!types.includes(event.eventType))
78
+ return false;
79
+ }
80
+ if (filter.status) {
81
+ const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];
82
+ if (!statuses.includes(event.status))
83
+ return false;
84
+ }
85
+ if (filter.minRiskScore && (event.riskScore || 0) < filter.minRiskScore)
86
+ return false;
87
+ return true;
88
+ })
89
+ .slice(filter.offset || 0, (filter.offset || 0) + (filter.limit || 100));
90
+ }
91
+ catch (error) {
92
+ if (error.code === 'ENOENT') {
93
+ return [];
94
+ }
95
+ throw error;
96
+ }
97
+ }
98
+ async disconnect() {
99
+ if (this.flushInterval) {
100
+ clearInterval(this.flushInterval);
101
+ }
102
+ if (this.buffer.length > 0) {
103
+ await this.flush();
104
+ }
105
+ }
106
+ async flush() {
107
+ if (this.buffer.length === 0)
108
+ return;
109
+ await this.writeBatch([...this.buffer]);
110
+ this.buffer = [];
111
+ }
112
+ sanitizeEvent(event) {
113
+ const sanitized = { ...event };
114
+ if (sanitized.code) {
115
+ sanitized.code = this.sanitizeString(sanitized.code);
116
+ }
117
+ if (sanitized.input) {
118
+ sanitized.input = this.sanitizeObject(sanitized.input);
119
+ }
120
+ if (sanitized.output) {
121
+ sanitized.output = this.sanitizeObject(sanitized.output);
122
+ }
123
+ return sanitized;
124
+ }
125
+ sanitizeString(str) {
126
+ const patterns = [
127
+ /api[_-]?key/gi,
128
+ /secret/gi,
129
+ /token/gi,
130
+ /password/gi,
131
+ /bearer/gi,
132
+ /authorization/gi,
133
+ ];
134
+ for (const pattern of patterns) {
135
+ str = str.replace(new RegExp(`(${pattern.source})\\s*[:=]\\s*['\"]?([^'\"\\s]+)`, 'gi'), '$1: [REDACTED]');
136
+ }
137
+ return str;
138
+ }
139
+ sanitizeObject(obj) {
140
+ if (typeof obj !== 'object' || obj === null) {
141
+ return obj;
142
+ }
143
+ if (Array.isArray(obj)) {
144
+ return obj.map((item) => this.sanitizeObject(item));
145
+ }
146
+ const sanitized = {};
147
+ const secretPatterns = ['key', 'secret', 'token', 'password', 'bearer', 'auth'];
148
+ for (const [key, value] of Object.entries(obj)) {
149
+ const lowerKey = key.toLowerCase();
150
+ if (secretPatterns.some((pattern) => lowerKey.includes(pattern))) {
151
+ sanitized[key] = '[REDACTED]';
152
+ }
153
+ else if (typeof value === 'object') {
154
+ sanitized[key] = this.sanitizeObject(value);
155
+ }
156
+ else {
157
+ sanitized[key] = value;
158
+ }
159
+ }
160
+ return sanitized;
161
+ }
162
+ }
163
+ //# sourceMappingURL=jsonl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl.js","sourceRoot":"","sources":["../../src/audit/jsonl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { AuditSink, AuditEvent } from '@mondaydotcomorg/atp-protocol';
2
+ /**
3
+ * OpenTelemetry-based audit sink
4
+ * Provides industry-standard observability with distributed tracing and metrics
5
+ */
6
+ export declare class OpenTelemetryAuditSink implements AuditSink {
7
+ name: string;
8
+ private tracer;
9
+ private meter;
10
+ private executionCounter;
11
+ private toolCallCounter;
12
+ private llmCallCounter;
13
+ private approvalCounter;
14
+ private executionDuration;
15
+ private toolDuration;
16
+ write(event: AuditEvent): Promise<void>;
17
+ writeBatch(events: AuditEvent[]): Promise<void>;
18
+ private buildAttributes;
19
+ private handleEvent;
20
+ private recordMetrics;
21
+ private flattenObject;
22
+ }
23
+ //# sourceMappingURL=opentelemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opentelemetry.d.ts","sourceRoot":"","sources":["../../src/audit/opentelemetry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAY3E;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,SAAS;IACvD,IAAI,SAAmB;IACvB,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,KAAK,CAAqC;IAElD,OAAO,CAAC,gBAAgB,CAGtB;IAEF,OAAO,CAAC,eAAe,CAGrB;IAEF,OAAO,CAAC,cAAc,CAGpB;IAEF,OAAO,CAAC,eAAe,CAGrB;IAEF,OAAO,CAAC,iBAAiB,CAGvB;IAEF,OAAO,CAAC,YAAY,CAGlB;IAEI,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBvC,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,OAAO,CAAC,eAAe;IAiDvB,OAAO,CAAC,WAAW;IA8EnB,OAAO,CAAC,aAAa;IA6DrB,OAAO,CAAC,aAAa;CAmBrB"}