@alter-ai/alter-sdk 0.2.2 → 0.3.1

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 CHANGED
@@ -1,17 +1,19 @@
1
1
  # Alter SDK for TypeScript / Node.js
2
2
 
3
- Official TypeScript SDK for [Alter Vault](https://alterai.dev) — OAuth token management with policy enforcement.
3
+ Official TypeScript SDK for [Alter Vault](https://alterai.dev) — Credential management for agents with policy enforcement.
4
4
 
5
5
  ## Features
6
6
 
7
7
  - **Zero Token Exposure**: Tokens are never exposed to developers — injected automatically
8
8
  - **Single Entry Point**: One method (`vault.request()`) for all provider APIs
9
- - **Type-Safe Enums**: `Provider` and `HttpMethod` enums with autocomplete
9
+ - **Type-Safe Enums**: `HttpMethod` enums with autocomplete
10
10
  - **URL Templating**: Path parameter substitution with automatic URL encoding
11
11
  - **Automatic Audit Logging**: All API calls logged with request metadata (HTTP method and URL) for full audit trail
12
12
  - **Real-time Policy Enforcement**: Every token request checked against current policies
13
13
  - **Automatic Token Refresh**: Tokens refreshed transparently by the backend
14
+ - **API Key and Custom Credential Support**: Handles OAuth tokens, API keys, and custom credential formats automatically
14
15
  - **Actor Tracking**: First-class support for AI agent and MCP server observability
16
+ - **HMAC Request Signing**: All SDK-to-backend requests are signed with a derived HMAC-SHA256 key for integrity, authenticity, and replay protection
15
17
  - **Native Promises**: Built on native `fetch` — no heavy dependencies
16
18
 
17
19
  ## Installation
@@ -23,17 +25,20 @@ npm install @alter-ai/alter-sdk
23
25
  ## Quick Start
24
26
 
25
27
  ```typescript
26
- import { AlterVault, Provider, HttpMethod } from "@alter-ai/alter-sdk";
28
+ import { AlterVault, ActorType, Provider, HttpMethod } from "@alter-ai/alter-sdk";
27
29
 
28
- const vault = new AlterVault({ apiKey: "alter_key_..." });
30
+ const vault = new AlterVault({
31
+ apiKey: "alter_key_...",
32
+ actorType: ActorType.AI_AGENT,
33
+ actorIdentifier: "my-agent",
34
+ });
29
35
 
30
36
  // Make API request — token injected automatically, never exposed
31
37
  const response = await vault.request(
32
- Provider.GOOGLE,
38
+ "CONNECTION_ID", // from Alter Connect (see below)
33
39
  HttpMethod.GET,
34
40
  "https://www.googleapis.com/calendar/v3/calendars/primary/events",
35
41
  {
36
- user: { user_id: "alice" },
37
42
  queryParams: { maxResults: "10" },
38
43
  },
39
44
  );
@@ -44,16 +49,38 @@ console.log(events);
44
49
  await vault.close();
45
50
  ```
46
51
 
52
+ ### Where does `connectionId` come from?
53
+
54
+ **OAuth connections:**
55
+ 1. User completes OAuth via [Alter Connect](https://docs.alterai.dev/sdks/javascript/quickstart) (frontend widget)
56
+ 2. The `onSuccess` callback returns a `connectionId` (UUID)
57
+ 3. You save it in your database, mapped to your user
58
+ 4. You pass it to `vault.request()` when making API calls
59
+
60
+ **Managed secrets** (API keys, service tokens):
61
+ 1. Store credentials in the [Developer Portal](https://portal.alterai.dev) under **Managed Secrets**
62
+ 2. Copy the `connectionId` returned
63
+ 3. Use the same `vault.request()` — credentials are injected automatically
64
+
65
+ ```typescript
66
+ // You can also discover connectionIds programmatically:
67
+ const result = await vault.listConnections({ providerId: "google" });
68
+ for (const conn of result.connections) {
69
+ console.log(`${conn.id}: ${conn.accountDisplayName}`);
70
+ }
71
+ ```
72
+
47
73
  ## Usage
48
74
 
75
+ The `request()` method returns the raw `Response` object. The token is injected automatically and never exposed. The backend token response includes `connectionId` and `providerId` for audit correlation.
76
+
49
77
  ### Simple GET Request
50
78
 
51
79
  ```typescript
52
80
  const response = await vault.request(
53
- Provider.GOOGLE,
81
+ connectionId,
54
82
  HttpMethod.GET,
55
83
  "https://www.googleapis.com/calendar/v3/calendars/primary/events",
56
- { user: { user_id: "alice" } },
57
84
  );
58
85
  ```
59
86
 
@@ -61,11 +88,10 @@ const response = await vault.request(
61
88
 
62
89
  ```typescript
63
90
  const response = await vault.request(
64
- Provider.SALESFORCE,
91
+ connectionId,
65
92
  HttpMethod.POST,
66
93
  "https://api.example.com/v1/items",
67
94
  {
68
- user: { user_id: "alice" },
69
95
  json: { name: "New Item", price: 99.99 },
70
96
  reason: "Creating new item",
71
97
  },
@@ -76,11 +102,10 @@ const response = await vault.request(
76
102
 
77
103
  ```typescript
78
104
  const response = await vault.request(
79
- Provider.SALESFORCE,
105
+ connectionId,
80
106
  HttpMethod.PUT,
81
107
  "https://api.example.com/v1/items/{item_id}",
82
108
  {
83
- user: { user_id: "alice" },
84
109
  pathParams: { item_id: "123" },
85
110
  json: { price: 89.99 },
86
111
  },
@@ -91,11 +116,10 @@ const response = await vault.request(
91
116
 
92
117
  ```typescript
93
118
  const response = await vault.request(
94
- "notion",
119
+ connectionId,
95
120
  HttpMethod.POST,
96
121
  "https://api.notion.com/v1/databases/{db_id}/query",
97
122
  {
98
- user: { user_id: "alice" },
99
123
  pathParams: { db_id: "abc123" },
100
124
  extraHeaders: { "Notion-Version": "2022-06-28" },
101
125
  json: { page_size: 10 },
@@ -103,6 +127,28 @@ const response = await vault.request(
103
127
  );
104
128
  ```
105
129
 
130
+ ### Using Managed Secrets
131
+
132
+ For your own APIs with API keys or service tokens (no OAuth flow needed):
133
+
134
+ ```typescript
135
+ const vault = new AlterVault({
136
+ apiKey: "alter_key_...",
137
+ actorType: ActorType.BACKEND_SERVICE,
138
+ actorIdentifier: "my-service",
139
+ });
140
+
141
+ const response = await vault.request(
142
+ "MANAGED_SECRET_CONNECTION_ID", // from Developer Portal
143
+ HttpMethod.GET,
144
+ "https://api.internal.com/v1/data",
145
+ );
146
+
147
+ await vault.close();
148
+ ```
149
+
150
+ The credential is injected automatically as the configured header type (Bearer, API Key, Basic Auth).
151
+
106
152
  ### Connection Management
107
153
 
108
154
  #### List Connections
@@ -149,7 +195,6 @@ console.log(`Expires in: ${session.expiresIn}s`);
149
195
  | Parameter | Type | Default | Description |
150
196
  |-----------|------|---------|-------------|
151
197
  | `endUser` | `{ id: string }` | *required* | End user identity |
152
- | `attributes` | `Record<string, unknown>` | - | Connection attributes |
153
198
  | `allowedProviders` | `string[]` | - | Restrict to specific providers |
154
199
  | `returnUrl` | `string` | - | Redirect URL after OAuth flow |
155
200
 
@@ -158,9 +203,11 @@ Returns `ConnectSession` with: `sessionToken`, `connectUrl`, `expiresIn`, `expir
158
203
  ### AI Agent Actor Tracking
159
204
 
160
205
  ```typescript
206
+ import { AlterVault, ActorType, Provider, HttpMethod } from "@alter-ai/alter-sdk";
207
+
161
208
  const vault = new AlterVault({
162
209
  apiKey: "alter_key_...",
163
- actorType: "ai_agent",
210
+ actorType: ActorType.AI_AGENT,
164
211
  actorIdentifier: "email-assistant-v2",
165
212
  actorName: "Email Assistant",
166
213
  actorVersion: "2.0.0",
@@ -168,18 +215,19 @@ const vault = new AlterVault({
168
215
  });
169
216
 
170
217
  const response = await vault.request(
171
- Provider.GOOGLE,
218
+ connectionId,
172
219
  HttpMethod.GET,
173
220
  "https://www.googleapis.com/calendar/v3/calendars/primary/events",
174
221
  {
175
- user: { user_id: "alice" },
176
- runId: "550e8400-e29b-41d4-a716-446655440000",
222
+ runId: "550e8400-e29b-41d4-a716-446655440000", // auto-generated UUID if omitted
177
223
  threadId: "thread-xyz",
178
224
  toolCallId: "call_abc_123",
179
225
  },
180
226
  );
181
227
  ```
182
228
 
229
+ > **Note**: `runId` is auto-generated as a UUID v4 if not provided. All sub-actions within a single `request()` call share the same `runId` for audit log grouping.
230
+
183
231
  ### Multi-Agent Deployments
184
232
 
185
233
  Each agent must create its own `AlterVault` instance with a unique actor identity. Do not share a single instance across agents.
@@ -188,29 +236,28 @@ Each agent must create its own `AlterVault` instance with a unique actor identit
188
236
  // Each agent gets its own vault instance
189
237
  const emailAgent = new AlterVault({
190
238
  apiKey: "alter_key_...",
191
- actorType: "ai_agent",
239
+ actorType: ActorType.AI_AGENT,
192
240
  actorIdentifier: "email-assistant-v2",
193
241
  actorName: "Email Assistant",
194
242
  });
195
243
 
196
244
  const calendarAgent = new AlterVault({
197
245
  apiKey: "alter_key_...",
198
- actorType: "ai_agent",
246
+ actorType: ActorType.AI_AGENT,
199
247
  actorIdentifier: "calendar-agent-v1",
200
248
  actorName: "Calendar Agent",
201
249
  });
202
250
 
203
251
  // Audit logs and policies are tracked per agent
204
- const user = { user_id: "alice" };
205
252
  await emailAgent.request(
206
- Provider.GOOGLE, HttpMethod.GET,
253
+ gmailConnectionId, // from Alter Connect
254
+ HttpMethod.GET,
207
255
  "https://gmail.googleapis.com/gmail/v1/users/me/messages",
208
- { user },
209
256
  );
210
257
  await calendarAgent.request(
211
- Provider.GOOGLE, HttpMethod.GET,
258
+ calendarConnectionId, // from Alter Connect
259
+ HttpMethod.GET,
212
260
  "https://www.googleapis.com/calendar/v3/calendars/primary/events",
213
- { user },
214
261
  );
215
262
 
216
263
  // Clean up each instance
@@ -221,30 +268,29 @@ await calendarAgent.close();
221
268
  ## Configuration
222
269
 
223
270
  ```typescript
271
+ import { AlterVault, ActorType } from "@alter-ai/alter-sdk";
272
+
224
273
  const vault = new AlterVault({
225
274
  apiKey: "alter_key_...", // Required: Alter Vault API key
226
- baseUrl: "https://api.alter.com", // Optional: Custom API URL
275
+ actorType: ActorType.AI_AGENT, // Required: ActorType enum
276
+ actorIdentifier: "my-agent", // Required: Unique identifier
227
277
  timeout: 30000, // Optional: HTTP timeout in ms (default: 30000)
228
- // Actor tracking (optional)
229
- actorType: "ai_agent", // "ai_agent" or "mcp_server"
230
- actorIdentifier: "my-agent", // Unique identifier
231
- actorName: "My Agent", // Human-readable name
232
- actorVersion: "1.0.0", // Version string
233
- framework: "langgraph", // AI framework
234
- clientType: "cursor", // MCP client type
278
+ actorName: "My Agent", // Optional: Human-readable name
279
+ actorVersion: "1.0.0", // Optional: Version string
280
+ framework: "langgraph", // Optional: AI framework
281
+ clientType: "cursor", // Optional: MCP client type
235
282
  });
236
283
  ```
237
284
 
238
285
  ## Error Handling
239
286
 
240
- > **Note:** Input validation errors (invalid `apiKey`, invalid `actorType`, invalid URL scheme, missing `pathParams`) throw `AlterSDKError`.
287
+ > **Note:** Input validation errors (invalid `apiKey`, invalid/missing `actorType`, missing `actorIdentifier`, invalid URL scheme, missing `pathParams`) throw `AlterSDKError`.
241
288
 
242
289
  ```typescript
243
290
  import {
244
291
  AlterVault,
245
- Provider,
246
292
  HttpMethod,
247
- AlterSDKError, // Base error (including validation: apiKey, actorType, URL scheme, pathParams)
293
+ AlterSDKError, // Base error (including validation: apiKey, actorType, actorIdentifier, URL scheme, pathParams)
248
294
  PolicyViolationError,
249
295
  ConnectionNotFoundError,
250
296
  TokenExpiredError,
@@ -256,10 +302,9 @@ import {
256
302
 
257
303
  try {
258
304
  const response = await vault.request(
259
- Provider.GOOGLE,
305
+ connectionId,
260
306
  HttpMethod.GET,
261
307
  "https://www.googleapis.com/calendar/v3/calendars/primary/events",
262
- { user: { user_id: "alice" } },
263
308
  );
264
309
  } catch (error) {
265
310
  if (error instanceof PolicyViolationError) {
@@ -282,7 +327,11 @@ try {
282
327
 
283
328
  ```typescript
284
329
  // Manual cleanup (recommended)
285
- const vault = new AlterVault({ apiKey: "alter_key_..." });
330
+ const vault = new AlterVault({
331
+ apiKey: "alter_key_...",
332
+ actorType: ActorType.BACKEND_SERVICE,
333
+ actorIdentifier: "my-service",
334
+ });
286
335
  try {
287
336
  const response = await vault.request(...);
288
337
  } finally {
@@ -295,18 +344,11 @@ try {
295
344
 
296
345
  ## Supported Providers
297
346
 
298
- ```typescript
299
- import { Provider } from "@alter-ai/alter-sdk";
300
-
301
- Provider.GOOGLE // "google"
302
- Provider.GITHUB // "github"
303
- Provider.SLACK // "slack"
304
- Provider.MICROSOFT // "microsoft"
305
- Provider.SALESFORCE // "salesforce"
306
- Provider.SENTRY // "sentry"
347
+ The SDK works with any OAuth provider configured in your Alter Vault dashboard. The first parameter to `vault.request()` is the `connection_id` (UUID) returned when a user connects via Alter Connect.
307
348
 
308
- // Strings also work for any provider
309
- await vault.request("notion", HttpMethod.GET, url, { user });
349
+ ```typescript
350
+ // Use the connection_id from Alter Connect
351
+ await vault.request("550e8400-e29b-41d4-a716-446655440000", HttpMethod.GET, url);
310
352
  ```
311
353
 
312
354
  ## Requirements