@alter-ai/alter-sdk 0.2.1 → 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
- - **Automatic Audit Logging**: All API calls logged as fire-and-forget background tasks
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,12 +127,87 @@ 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
+
152
+ ### Connection Management
153
+
154
+ #### List Connections
155
+
156
+ Retrieve OAuth connections for your app, optionally filtered by provider:
157
+
158
+ ```typescript
159
+ const result = await vault.listConnections();
160
+ for (const conn of result.connections) {
161
+ console.log(`${conn.providerId}: ${conn.accountDisplayName} (${conn.status})`);
162
+ }
163
+
164
+ // Filter by provider with pagination
165
+ const googleConns = await vault.listConnections({
166
+ providerId: "google",
167
+ limit: 10,
168
+ offset: 0,
169
+ });
170
+ console.log(`Total: ${googleConns.total}, Has more: ${googleConns.hasMore}`);
171
+ ```
172
+
173
+ | Parameter | Type | Default | Description |
174
+ |-----------|------|---------|-------------|
175
+ | `providerId` | `string` | - | Filter by provider (e.g., `"google"`) |
176
+ | `limit` | `number` | `100` | Max connections to return |
177
+ | `offset` | `number` | `0` | Pagination offset |
178
+
179
+ Returns `ConnectionListResult` with: `connections` (`ConnectionInfo[]`), `total`, `limit`, `offset`, `hasMore`.
180
+
181
+ #### Create Connect Session
182
+
183
+ Generate a session URL for end-users to authenticate with OAuth providers:
184
+
185
+ ```typescript
186
+ const session = await vault.createConnectSession({
187
+ endUser: { id: "alice" },
188
+ allowedProviders: ["google", "github"],
189
+ returnUrl: "https://myapp.com/callback",
190
+ });
191
+ console.log(`Connect URL: ${session.connectUrl}`);
192
+ console.log(`Expires in: ${session.expiresIn}s`);
193
+ ```
194
+
195
+ | Parameter | Type | Default | Description |
196
+ |-----------|------|---------|-------------|
197
+ | `endUser` | `{ id: string }` | *required* | End user identity |
198
+ | `allowedProviders` | `string[]` | - | Restrict to specific providers |
199
+ | `returnUrl` | `string` | - | Redirect URL after OAuth flow |
200
+
201
+ Returns `ConnectSession` with: `sessionToken`, `connectUrl`, `expiresIn`, `expiresAt`.
202
+
106
203
  ### AI Agent Actor Tracking
107
204
 
108
205
  ```typescript
206
+ import { AlterVault, ActorType, Provider, HttpMethod } from "@alter-ai/alter-sdk";
207
+
109
208
  const vault = new AlterVault({
110
209
  apiKey: "alter_key_...",
111
- actorType: "ai_agent",
210
+ actorType: ActorType.AI_AGENT,
112
211
  actorIdentifier: "email-assistant-v2",
113
212
  actorName: "Email Assistant",
114
213
  actorVersion: "2.0.0",
@@ -116,18 +215,19 @@ const vault = new AlterVault({
116
215
  });
117
216
 
118
217
  const response = await vault.request(
119
- Provider.GOOGLE,
218
+ connectionId,
120
219
  HttpMethod.GET,
121
220
  "https://www.googleapis.com/calendar/v3/calendars/primary/events",
122
221
  {
123
- user: { user_id: "alice" },
124
- runId: "550e8400-e29b-41d4-a716-446655440000",
222
+ runId: "550e8400-e29b-41d4-a716-446655440000", // auto-generated UUID if omitted
125
223
  threadId: "thread-xyz",
126
224
  toolCallId: "call_abc_123",
127
225
  },
128
226
  );
129
227
  ```
130
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
+
131
231
  ### Multi-Agent Deployments
132
232
 
133
233
  Each agent must create its own `AlterVault` instance with a unique actor identity. Do not share a single instance across agents.
@@ -136,29 +236,28 @@ Each agent must create its own `AlterVault` instance with a unique actor identit
136
236
  // Each agent gets its own vault instance
137
237
  const emailAgent = new AlterVault({
138
238
  apiKey: "alter_key_...",
139
- actorType: "ai_agent",
239
+ actorType: ActorType.AI_AGENT,
140
240
  actorIdentifier: "email-assistant-v2",
141
241
  actorName: "Email Assistant",
142
242
  });
143
243
 
144
244
  const calendarAgent = new AlterVault({
145
245
  apiKey: "alter_key_...",
146
- actorType: "ai_agent",
246
+ actorType: ActorType.AI_AGENT,
147
247
  actorIdentifier: "calendar-agent-v1",
148
248
  actorName: "Calendar Agent",
149
249
  });
150
250
 
151
251
  // Audit logs and policies are tracked per agent
152
- const user = { user_id: "alice" };
153
252
  await emailAgent.request(
154
- Provider.GOOGLE, HttpMethod.GET,
253
+ gmailConnectionId, // from Alter Connect
254
+ HttpMethod.GET,
155
255
  "https://gmail.googleapis.com/gmail/v1/users/me/messages",
156
- { user },
157
256
  );
158
257
  await calendarAgent.request(
159
- Provider.GOOGLE, HttpMethod.GET,
258
+ calendarConnectionId, // from Alter Connect
259
+ HttpMethod.GET,
160
260
  "https://www.googleapis.com/calendar/v3/calendars/primary/events",
161
- { user },
162
261
  );
163
262
 
164
263
  // Clean up each instance
@@ -169,30 +268,29 @@ await calendarAgent.close();
169
268
  ## Configuration
170
269
 
171
270
  ```typescript
271
+ import { AlterVault, ActorType } from "@alter-ai/alter-sdk";
272
+
172
273
  const vault = new AlterVault({
173
274
  apiKey: "alter_key_...", // Required: Alter Vault API key
174
- baseUrl: "https://api.alter.com", // Optional: Custom API URL
275
+ actorType: ActorType.AI_AGENT, // Required: ActorType enum
276
+ actorIdentifier: "my-agent", // Required: Unique identifier
175
277
  timeout: 30000, // Optional: HTTP timeout in ms (default: 30000)
176
- // Actor tracking (optional)
177
- actorType: "ai_agent", // "ai_agent" or "mcp_server"
178
- actorIdentifier: "my-agent", // Unique identifier
179
- actorName: "My Agent", // Human-readable name
180
- actorVersion: "1.0.0", // Version string
181
- framework: "langgraph", // AI framework
182
- 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
183
282
  });
184
283
  ```
185
284
 
186
285
  ## Error Handling
187
286
 
188
- > **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`.
189
288
 
190
289
  ```typescript
191
290
  import {
192
291
  AlterVault,
193
- Provider,
194
292
  HttpMethod,
195
- AlterSDKError, // Base error (including validation: apiKey, actorType, URL scheme, pathParams)
293
+ AlterSDKError, // Base error (including validation: apiKey, actorType, actorIdentifier, URL scheme, pathParams)
196
294
  PolicyViolationError,
197
295
  ConnectionNotFoundError,
198
296
  TokenExpiredError,
@@ -204,10 +302,9 @@ import {
204
302
 
205
303
  try {
206
304
  const response = await vault.request(
207
- Provider.GOOGLE,
305
+ connectionId,
208
306
  HttpMethod.GET,
209
307
  "https://www.googleapis.com/calendar/v3/calendars/primary/events",
210
- { user: { user_id: "alice" } },
211
308
  );
212
309
  } catch (error) {
213
310
  if (error instanceof PolicyViolationError) {
@@ -230,7 +327,11 @@ try {
230
327
 
231
328
  ```typescript
232
329
  // Manual cleanup (recommended)
233
- 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
+ });
234
335
  try {
235
336
  const response = await vault.request(...);
236
337
  } finally {
@@ -243,18 +344,11 @@ try {
243
344
 
244
345
  ## Supported Providers
245
346
 
246
- ```typescript
247
- import { Provider } from "@alter-ai/alter-sdk";
248
-
249
- Provider.GOOGLE // "google"
250
- Provider.GITHUB // "github"
251
- Provider.SLACK // "slack"
252
- Provider.MICROSOFT // "microsoft"
253
- Provider.SALESFORCE // "salesforce"
254
- 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.
255
348
 
256
- // Strings also work for any provider
257
- 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);
258
352
  ```
259
353
 
260
354
  ## Requirements