@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.
- package/README.md +430 -0
- package/__tests__/oauth-integration.test.ts +457 -0
- package/__tests__/scope-checkers.test.ts +560 -0
- package/__tests__/token-expiration.test.ts +308 -0
- package/dist/audit/jsonl.d.ts +29 -0
- package/dist/audit/jsonl.d.ts.map +1 -0
- package/dist/audit/jsonl.js +163 -0
- package/dist/audit/jsonl.js.map +1 -0
- package/dist/audit/opentelemetry.d.ts +23 -0
- package/dist/audit/opentelemetry.d.ts.map +1 -0
- package/dist/audit/opentelemetry.js +240 -0
- package/dist/audit/opentelemetry.js.map +1 -0
- package/dist/audit/otel-metrics.d.ts +111 -0
- package/dist/audit/otel-metrics.d.ts.map +1 -0
- package/dist/audit/otel-metrics.js +115 -0
- package/dist/audit/otel-metrics.js.map +1 -0
- package/dist/auth/env.d.ts +21 -0
- package/dist/auth/env.d.ts.map +1 -0
- package/dist/auth/env.js +48 -0
- package/dist/auth/env.js.map +1 -0
- package/dist/cache/file.d.ts +47 -0
- package/dist/cache/file.d.ts.map +1 -0
- package/dist/cache/file.js +262 -0
- package/dist/cache/file.js.map +1 -0
- package/dist/cache/memory.d.ts +30 -0
- package/dist/cache/memory.d.ts.map +1 -0
- package/dist/cache/memory.js +81 -0
- package/dist/cache/memory.js.map +1 -0
- package/dist/cache/redis.d.ts +28 -0
- package/dist/cache/redis.d.ts.map +1 -0
- package/dist/cache/redis.js +124 -0
- package/dist/cache/redis.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth/index.d.ts +2 -0
- package/dist/oauth/index.d.ts.map +1 -0
- package/dist/oauth/index.js +2 -0
- package/dist/oauth/index.js.map +1 -0
- package/dist/oauth/scope-checkers.d.ts +61 -0
- package/dist/oauth/scope-checkers.d.ts.map +1 -0
- package/dist/oauth/scope-checkers.js +166 -0
- package/dist/oauth/scope-checkers.js.map +1 -0
- package/package.json +26 -0
- package/project.json +31 -0
- package/src/audit/jsonl.ts +189 -0
- package/src/audit/opentelemetry.ts +286 -0
- package/src/audit/otel-metrics.ts +122 -0
- package/src/auth/env.ts +65 -0
- package/src/cache/file.ts +330 -0
- package/src/cache/memory.ts +105 -0
- package/src/cache/redis.ts +160 -0
- package/src/index.ts +32 -0
- package/src/oauth/index.ts +1 -0
- package/src/oauth/scope-checkers.ts +196 -0
- package/tsconfig.json +14 -0
- package/tsconfig.tsbuildinfo +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
# @mondaydotcomorg/atp-providers
|
|
2
|
+
|
|
3
|
+
Production-ready provider implementations for ATP (cache, auth, OAuth, audit).
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package provides concrete implementations of ATP provider interfaces including cache backends, authentication providers, OAuth integrations, and audit sinks.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @mondaydotcomorg/atp-providers
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Architecture
|
|
16
|
+
|
|
17
|
+
```mermaid
|
|
18
|
+
graph TB
|
|
19
|
+
Providers[Providers Package] --> Cache[Cache Providers]
|
|
20
|
+
Providers --> Auth[Auth Providers]
|
|
21
|
+
Providers --> OAuth[OAuth Providers]
|
|
22
|
+
Providers --> Audit[Audit Sinks]
|
|
23
|
+
|
|
24
|
+
Cache --> Memory[MemoryCache]
|
|
25
|
+
Cache --> Redis[RedisCache]
|
|
26
|
+
Cache --> File[FileCache]
|
|
27
|
+
|
|
28
|
+
Auth --> Env[EnvAuthProvider]
|
|
29
|
+
|
|
30
|
+
OAuth --> Google[GoogleOAuthProvider]
|
|
31
|
+
OAuth --> GitHub[GitHubOAuthProvider]
|
|
32
|
+
|
|
33
|
+
Audit --> JSONL[JSONLAuditSink]
|
|
34
|
+
Audit --> OTel[OpenTelemetryAuditSink]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Cache Providers
|
|
38
|
+
|
|
39
|
+
### MemoryCache
|
|
40
|
+
|
|
41
|
+
In-memory cache for development and testing.
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { MemoryCache } from '@mondaydotcomorg/atp-providers';
|
|
45
|
+
|
|
46
|
+
const cache = new MemoryCache({
|
|
47
|
+
defaultTTL: 3600, // 1 hour
|
|
48
|
+
maxSize: 1000, // Max entries
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
await cache.set('key', value, 3600);
|
|
52
|
+
const cached = await cache.get('key');
|
|
53
|
+
await cache.delete('key');
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### RedisCache
|
|
57
|
+
|
|
58
|
+
Redis-backed cache for production and distributed systems.
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { RedisCache } from '@mondaydotcomorg/atp-providers';
|
|
62
|
+
import Redis from 'ioredis';
|
|
63
|
+
|
|
64
|
+
const redis = new Redis({
|
|
65
|
+
host: 'localhost',
|
|
66
|
+
port: 6379,
|
|
67
|
+
password: process.env.REDIS_PASSWORD,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const cache = new RedisCache({
|
|
71
|
+
redis,
|
|
72
|
+
keyPrefix: 'atp:',
|
|
73
|
+
defaultTTL: 3600,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
await cache.set('key', value, 3600);
|
|
77
|
+
const cached = await cache.get('key');
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Benefits:**
|
|
81
|
+
|
|
82
|
+
- Cross-pod state sharing
|
|
83
|
+
- Persistent storage
|
|
84
|
+
- High performance
|
|
85
|
+
- Production-ready
|
|
86
|
+
|
|
87
|
+
### FileCache
|
|
88
|
+
|
|
89
|
+
File-based cache for simple persistence.
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { FileCache } from '@mondaydotcomorg/atp-providers';
|
|
93
|
+
|
|
94
|
+
const cache = new FileCache({
|
|
95
|
+
directory: './cache',
|
|
96
|
+
defaultTTL: 3600,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
await cache.set('key', value);
|
|
100
|
+
const cached = await cache.get('key');
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Auth Providers
|
|
104
|
+
|
|
105
|
+
### EnvAuthProvider
|
|
106
|
+
|
|
107
|
+
Environment-based authentication for simple use cases.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { EnvAuthProvider } from '@mondaydotcomorg/atp-providers';
|
|
111
|
+
|
|
112
|
+
const authProvider = new EnvAuthProvider({
|
|
113
|
+
envPrefix: 'AUTH_', // Reads AUTH_* env vars
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Set credentials
|
|
117
|
+
await authProvider.setCredentials('github', {
|
|
118
|
+
accessToken: 'ghp_...',
|
|
119
|
+
refreshToken: null,
|
|
120
|
+
expiresAt: null,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Get credentials
|
|
124
|
+
const credentials = await authProvider.getCredentials('github');
|
|
125
|
+
console.log(credentials.accessToken);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## OAuth Providers
|
|
129
|
+
|
|
130
|
+
### GoogleOAuthProvider
|
|
131
|
+
|
|
132
|
+
Google OAuth 2.0 integration.
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { GoogleOAuthProvider } from '@mondaydotcomorg/atp-providers';
|
|
136
|
+
|
|
137
|
+
const oauth = new GoogleOAuthProvider({
|
|
138
|
+
clientId: process.env.GOOGLE_CLIENT_ID,
|
|
139
|
+
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
140
|
+
redirectUri: 'http://localhost:3333/oauth/callback',
|
|
141
|
+
scopes: [
|
|
142
|
+
'https://www.googleapis.com/auth/userinfo.email',
|
|
143
|
+
'https://www.googleapis.com/auth/calendar',
|
|
144
|
+
],
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Generate auth URL
|
|
148
|
+
const authUrl = await oauth.generateAuthUrl({
|
|
149
|
+
state: 'random-state',
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Handle callback
|
|
153
|
+
const tokens = await oauth.handleCallback('authorization-code', {
|
|
154
|
+
state: 'random-state',
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Refresh token
|
|
158
|
+
const newTokens = await oauth.refreshToken('refresh-token');
|
|
159
|
+
|
|
160
|
+
// Check scopes
|
|
161
|
+
const hasScope = await oauth.checkScopes(tokens.accessToken, [
|
|
162
|
+
'https://www.googleapis.com/auth/calendar',
|
|
163
|
+
]);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### GitHubOAuthProvider
|
|
167
|
+
|
|
168
|
+
GitHub OAuth integration.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { GitHubOAuthProvider } from '@mondaydotcomorg/atp-providers';
|
|
172
|
+
|
|
173
|
+
const oauth = new GitHubOAuthProvider({
|
|
174
|
+
clientId: process.env.GITHUB_CLIENT_ID,
|
|
175
|
+
clientSecret: process.env.GITHUB_CLIENT_SECRET,
|
|
176
|
+
redirectUri: 'http://localhost:3333/oauth/callback',
|
|
177
|
+
scopes: ['repo', 'user'],
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const authUrl = await oauth.generateAuthUrl({ state: 'state' });
|
|
181
|
+
const tokens = await oauth.handleCallback('code', { state: 'state' });
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Custom OAuth Provider
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import type { OAuthProvider } from '@mondaydotcomorg/atp-protocol';
|
|
188
|
+
|
|
189
|
+
class SlackOAuthProvider implements OAuthProvider {
|
|
190
|
+
name = 'slack';
|
|
191
|
+
|
|
192
|
+
async generateAuthUrl(config) {
|
|
193
|
+
return `https://slack.com/oauth/v2/authorize?client_id=${config.clientId}&...`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async handleCallback(code, config) {
|
|
197
|
+
// Exchange code for tokens
|
|
198
|
+
const response = await fetch('https://slack.com/api/oauth.v2.access', {
|
|
199
|
+
method: 'POST',
|
|
200
|
+
body: JSON.stringify({ code, client_id: config.clientId, ... }),
|
|
201
|
+
});
|
|
202
|
+
const data = await response.json();
|
|
203
|
+
return {
|
|
204
|
+
accessToken: data.access_token,
|
|
205
|
+
refreshToken: data.refresh_token,
|
|
206
|
+
expiresAt: Date.now() + data.expires_in * 1000,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async refreshToken(refreshToken, config) {
|
|
211
|
+
// Implement refresh
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async checkScopes(accessToken, requiredScopes) {
|
|
215
|
+
// Verify scopes
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Audit Sinks
|
|
222
|
+
|
|
223
|
+
### JSONLAuditSink
|
|
224
|
+
|
|
225
|
+
Write audit logs as JSON Lines files.
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
import { JSONLAuditSink } from '@mondaydotcomorg/atp-providers';
|
|
229
|
+
|
|
230
|
+
const auditSink = new JSONLAuditSink({
|
|
231
|
+
path: './audit-logs',
|
|
232
|
+
rotateDaily: true, // Create new file each day
|
|
233
|
+
compress: true, // Compress old logs
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Automatically logs all events
|
|
237
|
+
// Files: audit-2024-01-15.jsonl
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Features:**
|
|
241
|
+
|
|
242
|
+
- Daily rotation
|
|
243
|
+
- Compression
|
|
244
|
+
- Structured JSON
|
|
245
|
+
- Easy parsing
|
|
246
|
+
|
|
247
|
+
### OpenTelemetryAuditSink
|
|
248
|
+
|
|
249
|
+
Export audit events to OpenTelemetry collector.
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
import { OpenTelemetryAuditSink } from '@mondaydotcomorg/atp-providers';
|
|
253
|
+
|
|
254
|
+
const auditSink = new OpenTelemetryAuditSink({
|
|
255
|
+
endpoint: 'http://localhost:4318/v1/traces',
|
|
256
|
+
serviceName: 'atp-server',
|
|
257
|
+
serviceVersion: '1.0.0',
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Events exported as spans and metrics
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Integration with observability platforms:**
|
|
264
|
+
|
|
265
|
+
- Jaeger
|
|
266
|
+
- Zipkin
|
|
267
|
+
- Prometheus
|
|
268
|
+
- Datadog
|
|
269
|
+
- New Relic
|
|
270
|
+
|
|
271
|
+
## OpenTelemetry Metrics
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
import { OTelCounter, OTelHistogram, METRIC_CONFIGS } from '@mondaydotcomorg/atp-providers';
|
|
275
|
+
|
|
276
|
+
// Predefined metrics
|
|
277
|
+
// - atp.execution.count (counter)
|
|
278
|
+
// - atp.execution.duration (histogram)
|
|
279
|
+
// - atp.execution.memory (histogram)
|
|
280
|
+
// - atp.tool.calls (counter)
|
|
281
|
+
// - atp.llm.calls (counter)
|
|
282
|
+
// - atp.cache.hits/misses (counters)
|
|
283
|
+
|
|
284
|
+
// Custom attributes
|
|
285
|
+
import { OTelAttribute } from '@mondaydotcomorg/atp-providers';
|
|
286
|
+
|
|
287
|
+
const attributes = {
|
|
288
|
+
[OTelAttribute.EXECUTION_ID]: 'exec-123',
|
|
289
|
+
[OTelAttribute.CLIENT_ID]: 'client-456',
|
|
290
|
+
[OTelAttribute.TOOL_NAME]: 'github.repos.get',
|
|
291
|
+
};
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Usage in Server
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import { createServer } from '@mondaydotcomorg/atp-server';
|
|
298
|
+
import {
|
|
299
|
+
RedisCache,
|
|
300
|
+
EnvAuthProvider,
|
|
301
|
+
GoogleOAuthProvider,
|
|
302
|
+
JSONLAuditSink,
|
|
303
|
+
OpenTelemetryAuditSink,
|
|
304
|
+
} from '@mondaydotcomorg/atp-providers';
|
|
305
|
+
import Redis from 'ioredis';
|
|
306
|
+
|
|
307
|
+
const redis = new Redis(process.env.REDIS_URL);
|
|
308
|
+
|
|
309
|
+
const server = createServer({
|
|
310
|
+
audit: {
|
|
311
|
+
enabled: true,
|
|
312
|
+
sinks: [
|
|
313
|
+
new JSONLAuditSink({ path: './audit-logs', rotateDaily: true }),
|
|
314
|
+
new OpenTelemetryAuditSink({
|
|
315
|
+
endpoint: 'http://localhost:4318/v1/traces',
|
|
316
|
+
serviceName: 'atp-server',
|
|
317
|
+
}),
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
otel: {
|
|
321
|
+
enabled: true,
|
|
322
|
+
serviceName: 'atp-server',
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
server.setCacheProvider(new RedisCache({ redis }));
|
|
327
|
+
server.setAuthProvider(new EnvAuthProvider());
|
|
328
|
+
|
|
329
|
+
// Add OAuth-protected API
|
|
330
|
+
const googleCalendar = {
|
|
331
|
+
name: 'calendar',
|
|
332
|
+
type: 'oauth',
|
|
333
|
+
oauthProvider: new GoogleOAuthProvider({
|
|
334
|
+
clientId: process.env.GOOGLE_CLIENT_ID,
|
|
335
|
+
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
336
|
+
redirectUri: 'http://localhost:3333/oauth/callback',
|
|
337
|
+
scopes: ['https://www.googleapis.com/auth/calendar'],
|
|
338
|
+
}),
|
|
339
|
+
functions: [
|
|
340
|
+
{
|
|
341
|
+
name: 'listEvents',
|
|
342
|
+
description: 'List calendar events',
|
|
343
|
+
inputSchema: { type: 'object', properties: {} },
|
|
344
|
+
handler: async (input, credentials) => {
|
|
345
|
+
const response = await fetch(
|
|
346
|
+
'https://www.googleapis.com/calendar/v3/calendars/primary/events',
|
|
347
|
+
{
|
|
348
|
+
headers: {
|
|
349
|
+
Authorization: `Bearer ${credentials.accessToken}`,
|
|
350
|
+
},
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
return await response.json();
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
],
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
server.addAPIGroup(googleCalendar);
|
|
360
|
+
|
|
361
|
+
await server.start(3333);
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## Cache Provider Interface
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
interface CacheProvider {
|
|
368
|
+
name: string;
|
|
369
|
+
get<T>(key: string): Promise<T | null>;
|
|
370
|
+
set(key: string, value: unknown, ttl?: number): Promise<void>;
|
|
371
|
+
delete(key: string): Promise<void>;
|
|
372
|
+
has(key: string): Promise<boolean>;
|
|
373
|
+
clear?(): Promise<void>;
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Auth Provider Interface
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
interface AuthProvider {
|
|
381
|
+
name: string;
|
|
382
|
+
getCredentials(key: string): Promise<UserCredentialData | null>;
|
|
383
|
+
setCredentials(key: string, credentials: UserCredentialData): Promise<void>;
|
|
384
|
+
deleteCredentials(key: string): Promise<void>;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
interface UserCredentialData {
|
|
388
|
+
accessToken: string;
|
|
389
|
+
refreshToken: string | null;
|
|
390
|
+
expiresAt: number | null;
|
|
391
|
+
scopes?: string[];
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## OAuth Provider Interface
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
interface OAuthProvider {
|
|
399
|
+
name: string;
|
|
400
|
+
generateAuthUrl(config: OAuthConfig): Promise<string>;
|
|
401
|
+
handleCallback(code: string, config: OAuthConfig): Promise<OAuthTokens>;
|
|
402
|
+
refreshToken(refreshToken: string, config: OAuthConfig): Promise<OAuthTokens>;
|
|
403
|
+
checkScopes(accessToken: string, requiredScopes: string[]): Promise<boolean>;
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## Audit Sink Interface
|
|
408
|
+
|
|
409
|
+
```typescript
|
|
410
|
+
interface AuditSink {
|
|
411
|
+
write(event: AuditEvent): Promise<void>;
|
|
412
|
+
flush?(): Promise<void>;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
interface AuditEvent {
|
|
416
|
+
timestamp: number;
|
|
417
|
+
type: 'execution' | 'tool_call' | 'llm_call' | 'approval' | 'error';
|
|
418
|
+
executionId?: string;
|
|
419
|
+
clientId?: string;
|
|
420
|
+
data: Record<string, unknown>;
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## TypeScript Support
|
|
425
|
+
|
|
426
|
+
Full TypeScript definitions included.
|
|
427
|
+
|
|
428
|
+
## License
|
|
429
|
+
|
|
430
|
+
MIT
|