@alter-ai/alter-sdk 0.2.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.
- package/README.md +234 -0
- package/dist/index.cjs +962 -0
- package/dist/index.d.cts +392 -0
- package/dist/index.d.ts +392 -0
- package/dist/index.js +923 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Alter SDK for TypeScript / Node.js
|
|
2
|
+
|
|
3
|
+
> **Version**: 0.4.0
|
|
4
|
+
|
|
5
|
+
Official TypeScript SDK for [Alter Vault](https://alterai.dev) — OAuth token management with policy enforcement.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Zero Token Exposure**: Tokens are never exposed to developers — injected automatically
|
|
10
|
+
- **Single Entry Point**: One method (`vault.request()`) for all provider APIs
|
|
11
|
+
- **Type-Safe Enums**: `Provider` and `HttpMethod` enums with autocomplete
|
|
12
|
+
- **URL Templating**: Path parameter substitution with automatic URL encoding
|
|
13
|
+
- **Automatic Audit Logging**: All API calls logged as fire-and-forget background tasks
|
|
14
|
+
- **Real-time Policy Enforcement**: Every token request checked against current policies
|
|
15
|
+
- **Automatic Token Refresh**: Tokens refreshed transparently by the backend
|
|
16
|
+
- **Dual HTTP Client Security**: Separate clients prevent credential leakage to providers
|
|
17
|
+
- **Security Hardened (v0.4.0)**: Frozen `HttpClient` prototype, `WeakMap` token storage, unexported module-private token accessors, and hardened `fetch` capture prevent rogue agent token extraction
|
|
18
|
+
- **Actor Tracking**: First-class support for AI agent and MCP server observability
|
|
19
|
+
- **Native Promises**: Built on native `fetch` — no heavy dependencies
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @alter-ai/alter-sdk
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { AlterVault, Provider, HttpMethod } from "@alter-ai/alter-sdk";
|
|
31
|
+
|
|
32
|
+
const vault = new AlterVault({ apiKey: "alter_key_..." });
|
|
33
|
+
|
|
34
|
+
// Make API request — token injected automatically, never exposed
|
|
35
|
+
const response = await vault.request(
|
|
36
|
+
Provider.GOOGLE,
|
|
37
|
+
HttpMethod.GET,
|
|
38
|
+
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
39
|
+
{
|
|
40
|
+
user: { user_id: "alice" },
|
|
41
|
+
queryParams: { maxResults: "10" },
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const events = await response.json();
|
|
46
|
+
console.log(events);
|
|
47
|
+
|
|
48
|
+
await vault.close();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
### Simple GET Request
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
const response = await vault.request(
|
|
57
|
+
Provider.GOOGLE,
|
|
58
|
+
HttpMethod.GET,
|
|
59
|
+
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
60
|
+
{ user: { user_id: "alice" } },
|
|
61
|
+
);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### POST with JSON Body
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const response = await vault.request(
|
|
68
|
+
Provider.SALESFORCE,
|
|
69
|
+
HttpMethod.POST,
|
|
70
|
+
"https://api.example.com/v1/items",
|
|
71
|
+
{
|
|
72
|
+
user: { user_id: "alice" },
|
|
73
|
+
json: { name: "New Item", price: 99.99 },
|
|
74
|
+
reason: "Creating new item",
|
|
75
|
+
},
|
|
76
|
+
);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### URL Path Templating
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
const response = await vault.request(
|
|
83
|
+
Provider.SALESFORCE,
|
|
84
|
+
HttpMethod.PUT,
|
|
85
|
+
"https://api.example.com/v1/items/{item_id}",
|
|
86
|
+
{
|
|
87
|
+
user: { user_id: "alice" },
|
|
88
|
+
pathParams: { item_id: "123" },
|
|
89
|
+
json: { price: 89.99 },
|
|
90
|
+
},
|
|
91
|
+
);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Query Parameters and Extra Headers
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const response = await vault.request(
|
|
98
|
+
Provider.GOOGLE,
|
|
99
|
+
HttpMethod.GET,
|
|
100
|
+
"https://api.example.com/v1/items",
|
|
101
|
+
{
|
|
102
|
+
user: { user_id: "alice" },
|
|
103
|
+
queryParams: { fields: "name,price", limit: "10" },
|
|
104
|
+
extraHeaders: { "Notion-Version": "2022-06-28" },
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### AI Agent Actor Tracking
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const vault = new AlterVault({
|
|
113
|
+
apiKey: "alter_key_...",
|
|
114
|
+
actorType: "ai_agent",
|
|
115
|
+
actorIdentifier: "email-assistant-v2",
|
|
116
|
+
actorName: "Email Assistant",
|
|
117
|
+
actorVersion: "2.0.0",
|
|
118
|
+
framework: "langgraph",
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const response = await vault.request(
|
|
122
|
+
Provider.GOOGLE,
|
|
123
|
+
HttpMethod.GET,
|
|
124
|
+
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
125
|
+
{
|
|
126
|
+
user: { user_id: "alice" },
|
|
127
|
+
runId: "550e8400-e29b-41d4-a716-446655440000",
|
|
128
|
+
threadId: "thread-xyz",
|
|
129
|
+
},
|
|
130
|
+
);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Configuration
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const vault = new AlterVault({
|
|
137
|
+
apiKey: "alter_key_...", // Required: Alter Vault API key
|
|
138
|
+
baseUrl: "https://api.alter.com", // Optional: Custom API URL
|
|
139
|
+
enableAuditLogging: true, // Optional: Enable audit logs (default: true)
|
|
140
|
+
timeout: 30000, // Optional: HTTP timeout in ms (default: 30000)
|
|
141
|
+
// Actor tracking (optional)
|
|
142
|
+
actorType: "ai_agent", // "ai_agent" or "mcp_server"
|
|
143
|
+
actorIdentifier: "my-agent", // Unique identifier
|
|
144
|
+
actorName: "My Agent", // Human-readable name
|
|
145
|
+
actorVersion: "1.0.0", // Version string
|
|
146
|
+
framework: "langgraph", // AI framework
|
|
147
|
+
clientType: "cursor", // MCP client type
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Error Handling
|
|
152
|
+
|
|
153
|
+
> **Note:** Input validation errors (invalid `apiKey`, invalid `actorType`, SSRF URL scheme violations, missing `pathParams`) throw `AlterSDKError`.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import {
|
|
157
|
+
AlterVault,
|
|
158
|
+
Provider,
|
|
159
|
+
HttpMethod,
|
|
160
|
+
AlterSDKError, // Base error (including validation: apiKey, actorType, SSRF, pathParams)
|
|
161
|
+
PolicyViolationError,
|
|
162
|
+
ConnectionNotFoundError,
|
|
163
|
+
TokenExpiredError,
|
|
164
|
+
TokenRetrievalError,
|
|
165
|
+
NetworkError,
|
|
166
|
+
TimeoutError,
|
|
167
|
+
ProviderAPIError,
|
|
168
|
+
} from "@alter-ai/alter-sdk";
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
const response = await vault.request(
|
|
172
|
+
Provider.GOOGLE,
|
|
173
|
+
HttpMethod.GET,
|
|
174
|
+
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
175
|
+
{ user: { user_id: "alice" } },
|
|
176
|
+
);
|
|
177
|
+
} catch (error) {
|
|
178
|
+
if (error instanceof PolicyViolationError) {
|
|
179
|
+
console.error(`Policy denied: ${error.message}`);
|
|
180
|
+
} else if (error instanceof ConnectionNotFoundError) {
|
|
181
|
+
console.error("No OAuth connection — user needs to authenticate");
|
|
182
|
+
} else if (error instanceof TokenExpiredError) {
|
|
183
|
+
console.error(`Token expired for connection: ${error.connectionId}`);
|
|
184
|
+
} else if (error instanceof TimeoutError) {
|
|
185
|
+
console.error(`Request timed out — safe to retry: ${error.message}`);
|
|
186
|
+
} else if (error instanceof NetworkError) {
|
|
187
|
+
console.error(`Network issue: ${error.message}`);
|
|
188
|
+
} else if (error instanceof ProviderAPIError) {
|
|
189
|
+
console.error(`Provider error ${error.statusCode}: ${error.responseBody}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Resource Management
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
// Manual cleanup (recommended)
|
|
198
|
+
const vault = new AlterVault({ apiKey: "alter_key_..." });
|
|
199
|
+
try {
|
|
200
|
+
const response = await vault.request(...);
|
|
201
|
+
} finally {
|
|
202
|
+
await vault.close(); // Waits for pending audit logs, cleans up timers
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// close() is idempotent — safe to call multiple times
|
|
206
|
+
// Calling request() after close() throws AlterSDKError
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Architecture
|
|
210
|
+
|
|
211
|
+
See [ALTER_TYPESCRIPT_SDK_ARCHITECTURE.md](./ALTER_TYPESCRIPT_SDK_ARCHITECTURE.md) for details on:
|
|
212
|
+
- Dual HTTP client security model
|
|
213
|
+
- Zero token exposure design
|
|
214
|
+
- No SDK-side caching (real-time policy enforcement)
|
|
215
|
+
- SSRF prevention with case-insensitive URL scheme validation
|
|
216
|
+
- Actor tracking and audit logging
|
|
217
|
+
|
|
218
|
+
## Development
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
npm install
|
|
222
|
+
npm run test # Run tests (70 tests)
|
|
223
|
+
npm run typecheck # Type check
|
|
224
|
+
npm run build # Build for distribution
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Requirements
|
|
228
|
+
|
|
229
|
+
- Node.js 18+ (uses native `fetch`)
|
|
230
|
+
- TypeScript 5.0+
|
|
231
|
+
|
|
232
|
+
## License
|
|
233
|
+
|
|
234
|
+
MIT License
|