@vorim/sdk 3.0.2 → 3.1.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 CHANGED
@@ -280,26 +280,41 @@ trust.revocation_status; // false
280
280
  - Denial ratio (high denials = lower trust)
281
281
  - Scope breadth (too many scopes = higher risk)
282
282
 
283
- ### Payload Signing
283
+ ### Per-event signing (auto-signing)
284
+
285
+ From v3.1.0, the SDK signs every audit event at source with the agent's Ed25519 private key. No code change required — `register()` caches the key in memory and `emit()` adds the signature transparently.
284
286
 
285
287
  ```typescript
286
- // Sign a payload with the agent's Ed25519 private key (client-side)
287
- const signature = await vorim.sign(
288
- JSON.stringify({ action: "transfer", amount: 500 }),
289
- privateKeyPem
290
- );
291
- // Returns: "ed25519:base64signature..."
288
+ const { agent } = await vorim.register({ name: "agent", capabilities: [], scopes: [] });
292
289
 
293
- // Include signature in audit events for non-repudiation
290
+ // Auto-signed. The signature is attached before the request leaves the process.
294
291
  await vorim.emit({
295
- agent_id: "agid_acme_a1b2c3d4",
292
+ agent_id: agent.agent_id,
296
293
  event_type: "tool_call",
297
294
  action: "transfer_funds",
298
295
  result: "success",
299
- signature,
300
296
  });
301
297
  ```
302
298
 
299
+ To verify signatures server-side, the API operator sets `VORIM_VERIFY_AUDIT_SIGNATURES=true`. The canonical bytes signed are `event_type|action|resource|input_hash|output_hash|result`.
300
+
301
+ **Restoring keys across process restarts.** The in-memory keyring is lost on restart. Load the private key from your secret store and call:
302
+
303
+ ```typescript
304
+ vorim.useAgentKey(agent.agent_id, privateKeyPem);
305
+ vorim.forgetAgentKey(agent.agent_id); // revoke from memory
306
+ ```
307
+
308
+ **Opting out.** Per event with `{ sign: false }`, or globally with `autoSign: false` in the config:
309
+
310
+ ```typescript
311
+ await vorim.emit(event, { sign: false });
312
+
313
+ const vorim = createVorim({ apiKey, autoSign: false });
314
+ ```
315
+
316
+ **Manual signing.** For payloads you sign yourself, `vorim.sign(payload, privateKeyPem)` returns an `ed25519:` prefixed signature. Any event with a pre-existing `signature` field is passed through unchanged.
317
+
303
318
  ### Embeddable Trust Badge
304
319
 
305
320
  Every registered agent gets a public SVG trust badge you can embed anywhere:
@@ -322,6 +337,7 @@ const vorim = createVorim({
322
337
  apiKey: "agid_sk_live_...", // Required — your Vorim API key
323
338
  baseUrl: "https://api.vorim.ai", // Optional (default)
324
339
  timeout: 10000, // Optional — request timeout in ms (default: 10000)
340
+ autoSign: true, // Optional — sign audit events at source (default: true)
325
341
  });
326
342
  ```
327
343
 
@@ -330,6 +346,7 @@ const vorim = createVorim({
330
346
  | `apiKey` | `string` | — | Your Vorim API key (`agid_sk_live_...` or `agid_sk_test_...`) |
331
347
  | `baseUrl` | `string` | `https://api.vorim.ai` | API base URL (override for self-hosted) |
332
348
  | `timeout` | `number` | `10000` | Request timeout in milliseconds |
349
+ | `autoSign` | `boolean` | `true` | Sign every audit event at source with the agent's Ed25519 key |
333
350
 
334
351
  ---
335
352
 
package/dist/index.cjs CHANGED
@@ -32,19 +32,56 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  VorimError: () => VorimError,
34
34
  VorimSDK: () => VorimSDK,
35
+ canonicalPayloadV0: () => canonicalPayloadV0,
35
36
  default: () => createVorim
36
37
  });
37
38
  module.exports = __toCommonJS(index_exports);
38
- var SDK_VERSION = "3.0.2";
39
+ var SDK_VERSION = true ? "3.1.0" : "0.0.0";
39
40
  var USER_AGENT = `vorim-sdk/${SDK_VERSION}`;
41
+ function canonicalPayloadV0(event) {
42
+ return [
43
+ event.event_type,
44
+ event.action,
45
+ event.resource ?? "",
46
+ event.input_hash ?? "",
47
+ event.output_hash ?? "",
48
+ event.result
49
+ ].join("|");
50
+ }
40
51
  var VorimSDK = class {
41
52
  apiKey;
42
53
  baseUrl;
43
54
  timeout;
55
+ autoSign;
56
+ /**
57
+ * In-memory keyring mapping agent_id -> PEM-encoded Ed25519 private key.
58
+ * Populated automatically by register() and registerEphemeral(), or
59
+ * explicitly via useAgentKey(). Lost on process restart by design; the
60
+ * caller is responsible for durable key storage.
61
+ */
62
+ agentKeys = /* @__PURE__ */ new Map();
44
63
  constructor(config) {
45
64
  this.apiKey = config.apiKey;
46
65
  this.baseUrl = (config.baseUrl || "https://api.vorim.ai").replace(/\/$/, "") + "/v1";
47
66
  this.timeout = config.timeout || 1e4;
67
+ this.autoSign = config.autoSign !== false;
68
+ }
69
+ /**
70
+ * Register a previously-issued agent keypair so this SDK instance can
71
+ * auto-sign events for it on emit. Use this when restoring an agent across
72
+ * process restarts: read the agent's private_key from durable storage,
73
+ * call useAgentKey(agentId, privateKey), and emit() will sign automatically.
74
+ */
75
+ useAgentKey(agentId, privateKeyPem) {
76
+ this.agentKeys.set(agentId, privateKeyPem);
77
+ }
78
+ /**
79
+ * Forget an agent's signing key (e.g. after revocation). Subsequent emit()
80
+ * calls for that agent will pass through unsigned unless a key is provided
81
+ * inline.
82
+ */
83
+ forgetAgentKey(agentId) {
84
+ this.agentKeys.delete(agentId);
48
85
  }
49
86
  // ─── Health Check ────────────────────────────────────────────────
50
87
  /**
@@ -63,9 +100,18 @@ var VorimSDK = class {
63
100
  /**
64
101
  * Register a new agent with Vorim AI.
65
102
  * Returns the agent identity and a private key (shown once).
103
+ *
104
+ * Side effect: the returned private_key is cached in this SDK instance's
105
+ * in-memory keyring so subsequent emit() calls for this agent auto-sign.
106
+ * The keyring is process-local; the caller is responsible for persisting
107
+ * the private_key to durable storage if the agent should survive restarts.
66
108
  */
67
109
  async register(input) {
68
- return this.post("/agents", input);
110
+ const result = await this.post("/agents", input);
111
+ if (result?.agent?.agent_id && result?.private_key) {
112
+ this.agentKeys.set(result.agent.agent_id, result.private_key);
113
+ }
114
+ return result;
69
115
  }
70
116
  /**
71
117
  * Verify an agent's identity via the public Trust API.
@@ -127,15 +173,47 @@ var VorimSDK = class {
127
173
  // ─── Audit ────────────────────────────────────────────────────────
128
174
  /**
129
175
  * Emit an audit event for an agent action.
176
+ *
177
+ * By default (autoSign=true on the SDK), the event is signed with the
178
+ * agent's private key before it leaves the process. Set options.sign=false
179
+ * to skip signing (e.g. for testing). If the SDK has no private key for the
180
+ * event's agent_id, the event is sent unsigned and a warning is not
181
+ * raised — callers that require signing should check event.signature on
182
+ * the returned event after a round-trip, or use a server-side enforcement
183
+ * flag (VORIM_VERIFY_AUDIT_SIGNATURES).
184
+ */
185
+ async emit(event, options) {
186
+ const prepared = await this.prepareEvent(event, options?.sign);
187
+ return this.post("/audit/events", { events: [prepared] });
188
+ }
189
+ /**
190
+ * Emit a batch of audit events (up to 1,000). Each event is signed
191
+ * independently using its agent_id to look up the signing key. See
192
+ * {@link VorimSDK.emit} for signing behaviour and opt-out.
130
193
  */
131
- async emit(event) {
132
- return this.post("/audit/events", { events: [event] });
194
+ async emitBatch(events, options) {
195
+ const prepared = await Promise.all(events.map((e) => this.prepareEvent(e, options?.sign)));
196
+ return this.post("/audit/events", { events: prepared });
133
197
  }
134
198
  /**
135
- * Emit a batch of audit events (up to 1,000).
199
+ * Internal: prepare an event for transmission. Auto-signs if the SDK has a
200
+ * key for this agent and signing isn't explicitly opted out. Pre-existing
201
+ * signatures on the event are respected (caller-signed events are not
202
+ * re-signed). Per-agent failure is non-fatal: if signing throws, the event
203
+ * still sends unsigned so a single bad key doesn't break a batch.
136
204
  */
137
- async emitBatch(events) {
138
- return this.post("/audit/events", { events });
205
+ async prepareEvent(event, signOverride) {
206
+ const shouldSign = signOverride ?? this.autoSign;
207
+ if (!shouldSign) return event;
208
+ if (event.signature) return event;
209
+ const key = this.agentKeys.get(event.agent_id);
210
+ if (!key) return event;
211
+ try {
212
+ const signature = await this.sign(canonicalPayloadV0(event), key);
213
+ return { ...event, signature };
214
+ } catch {
215
+ return event;
216
+ }
139
217
  }
140
218
  /**
141
219
  * Export a signed audit bundle for a date range.
@@ -166,9 +244,17 @@ var VorimSDK = class {
166
244
  /**
167
245
  * Register an ephemeral agent with W3C did:key identity.
168
246
  * The agent auto-expires after the specified TTL.
247
+ *
248
+ * Side effect: the returned private_key is cached in this SDK instance's
249
+ * in-memory keyring (matching register()).
169
250
  */
170
251
  async registerEphemeral(input) {
171
- return this.post("/agents/ephemeral", input);
252
+ const result = await this.post("/agents/ephemeral", input);
253
+ const agentId = result?.agent?.agent_id ?? result?.did_key;
254
+ if (agentId && result?.private_key) {
255
+ this.agentKeys.set(agentId, result.private_key);
256
+ }
257
+ return result;
172
258
  }
173
259
  // ─── Credential Delegation ──────────────────────────────────────────
174
260
  /**
@@ -319,6 +405,9 @@ var VorimError = class extends Error {
319
405
  this.details = details;
320
406
  this.name = "VorimError";
321
407
  }
408
+ status;
409
+ code;
410
+ details;
322
411
  };
323
412
  function createVorim(config) {
324
413
  return new VorimSDK(config);
@@ -326,6 +415,7 @@ function createVorim(config) {
326
415
  // Annotate the CommonJS export names for ESM import in node:
327
416
  0 && (module.exports = {
328
417
  VorimError,
329
- VorimSDK
418
+ VorimSDK,
419
+ canonicalPayloadV0
330
420
  });
331
421
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// ============================================================================\n// VORIM SDK — TypeScript\n// Thin client wrapping the Vorim AI REST API\n// ============================================================================\n\nimport type {\n Agent, AgentRegistrationInput, AgentRegistrationResult,\n TrustRecord, AuditEventInput, PermissionScope, PermissionCheckResult,\n} from './types.js';\n\n// Keep in sync with package.json version. Used in the User-Agent header.\nconst SDK_VERSION = '3.0.2';\nconst USER_AGENT = `vorim-sdk/${SDK_VERSION}`;\n\nexport interface VorimConfig {\n apiKey: string;\n baseUrl?: string;\n timeout?: number;\n}\n\nexport class VorimSDK {\n private apiKey: string;\n private baseUrl: string;\n private timeout: number;\n\n constructor(config: VorimConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = (config.baseUrl || 'https://api.vorim.ai').replace(/\\/$/, '') + '/v1';\n this.timeout = config.timeout || 10000;\n }\n\n // ─── Health Check ────────────────────────────────────────────────\n\n /**\n * Ping the Vorim API to verify connectivity and API key validity.\n * Returns { status, timestamp } on success, throws VorimError on failure.\n */\n async ping(): Promise<{ status: string; timestamp: string }> {\n const response = await fetch(`${this.baseUrl.replace('/v1', '')}/health`, {\n headers: { 'User-Agent': USER_AGENT },\n signal: AbortSignal.timeout(this.timeout),\n });\n if (!response.ok) throw new VorimError(response.status, 'UNREACHABLE', 'Vorim API is not reachable');\n return response.json() as Promise<{ status: string; timestamp: string }>;\n }\n\n // ─── Agent Identity ────────────────────────────────────────────────\n\n /**\n * Register a new agent with Vorim AI.\n * Returns the agent identity and a private key (shown once).\n */\n async register(input: AgentRegistrationInput): Promise<AgentRegistrationResult> {\n return this.post('/agents', input);\n }\n\n /**\n * Verify an agent's identity via the public Trust API.\n */\n async verify(agentId: string): Promise<TrustRecord> {\n return this.get(`/trust/verify/${agentId}`);\n }\n\n /**\n * Get agent details.\n */\n async getAgent(agentId: string): Promise<Agent> {\n return this.get(`/agents/${agentId}`);\n }\n\n /**\n * List all agents in the organisation.\n */\n async listAgents(params?: { page?: number; per_page?: number; status?: string }): Promise<{ agents: Agent[]; meta: any }> {\n const qs = new URLSearchParams(params as any).toString();\n return this.get(`/agents${qs ? '?' + qs : ''}`);\n }\n\n /**\n * Update an agent's metadata.\n */\n async updateAgent(agentId: string, updates: Partial<Pick<Agent, 'name' | 'description' | 'status' | 'capabilities'>>): Promise<Agent> {\n return this.patch(`/agents/${agentId}`, updates);\n }\n\n /**\n * Revoke an agent (permanent deactivation).\n */\n async revoke(agentId: string): Promise<void> {\n await this.delete(`/agents/${agentId}`);\n }\n\n // ─── Permissions ──────────────────────────────────────────────────\n\n /**\n * Check if an agent has a specific permission scope.\n * Target: < 5ms response via Redis cache.\n */\n async check(agentId: string, scope: PermissionScope): Promise<PermissionCheckResult> {\n return this.post(`/agents/${agentId}/permissions/verify`, { scope });\n }\n\n /**\n * Grant a permission scope to an agent.\n */\n async grant(agentId: string, scope: PermissionScope, options?: {\n valid_until?: string;\n rate_limit?: { max: number; window: string };\n }): Promise<any> {\n return this.post(`/agents/${agentId}/permissions`, { scope, ...options });\n }\n\n /**\n * List all active permissions for an agent.\n */\n async listPermissions(agentId: string): Promise<any[]> {\n return this.get(`/agents/${agentId}/permissions`);\n }\n\n /**\n * Revoke a specific permission scope from an agent.\n */\n async revokePermission(agentId: string, scope: PermissionScope): Promise<any> {\n return this.delete(`/agents/${agentId}/permissions/${scope}`);\n }\n\n // ─── Audit ────────────────────────────────────────────────────────\n\n /**\n * Emit an audit event for an agent action.\n */\n async emit(event: AuditEventInput): Promise<{ ingested: number }> {\n return this.post('/audit/events', { events: [event] });\n }\n\n /**\n * Emit a batch of audit events (up to 1,000).\n */\n async emitBatch(events: AuditEventInput[]): Promise<{ ingested: number }> {\n return this.post('/audit/events', { events });\n }\n\n /**\n * Export a signed audit bundle for a date range.\n */\n async exportAudit(from: string, to: string, format: string = 'json'): Promise<any> {\n return this.post('/audit/export', { from, to, format });\n }\n\n // ─── API Keys ──────────────────────────────────────────────────────\n\n /**\n * List all API keys for the organisation.\n */\n async listApiKeys(): Promise<any[]> {\n return this.get('/api-keys');\n }\n\n /**\n * Create a new API key.\n */\n async createApiKey(name: string, options?: { scopes?: string[]; expires_at?: string }): Promise<any> {\n return this.post('/api-keys', { name, ...options });\n }\n\n /**\n * Revoke an API key.\n */\n async deleteApiKey(keyId: string): Promise<{ revoked: boolean }> {\n return this.delete(`/api-keys/${keyId}`);\n }\n\n // ─── Ephemeral Agents ──────────────────────────────────────────────\n\n /**\n * Register an ephemeral agent with W3C did:key identity.\n * The agent auto-expires after the specified TTL.\n */\n async registerEphemeral(input: {\n capabilities: string[];\n scopes: string[];\n ttl_seconds?: number;\n }): Promise<any> {\n return this.post('/agents/ephemeral', input);\n }\n\n // ─── Credential Delegation ──────────────────────────────────────────\n\n /**\n * Register an OAuth provider for credential delegation.\n */\n async registerProvider(input: {\n provider_key: string;\n display_name?: string;\n client_id: string;\n client_secret: string;\n auth_url: string;\n token_url: string;\n revoke_url?: string;\n scopes_available?: string[];\n }): Promise<any> {\n return this.post('/credentials/providers', input);\n }\n\n /**\n * List registered OAuth providers.\n */\n async listProviders(): Promise<any[]> {\n return this.get('/credentials/providers');\n }\n\n /**\n * Store an OAuth connection (user's authorized tokens).\n */\n async storeConnection(input: {\n provider_id: string;\n refresh_token: string;\n scopes_granted: string[];\n external_account_id?: string;\n }): Promise<any> {\n return this.post('/credentials/connections', input);\n }\n\n /**\n * List OAuth connections.\n */\n async listConnections(): Promise<any[]> {\n return this.get('/credentials/connections');\n }\n\n /**\n * Delegate a credential to an agent.\n * The agent will be able to request short-lived access tokens\n * for the delegated scopes without ever seeing the refresh token.\n */\n async delegateCredential(input: {\n connection_id: string;\n agent_id: string;\n scopes_delegated: string[];\n max_requests_per_hr?: number;\n valid_until?: string;\n }): Promise<any> {\n return this.post('/credentials/delegations', input);\n }\n\n /**\n * List credential delegations for the organisation or a specific agent.\n */\n async listDelegations(agentId?: string): Promise<any[]> {\n const params = agentId ? `?agent_id=${agentId}` : '';\n return this.get(`/credentials/delegations${params}`);\n }\n\n /**\n * Revoke a credential delegation (cascades to delegation chains).\n */\n async revokeDelegation(delegationId: string): Promise<{ revoked: boolean }> {\n return this.delete(`/credentials/delegations/${delegationId}`);\n }\n\n /**\n * Request a short-lived access token for an agent.\n * The agent must have an active credential delegation.\n * The refresh token is never exposed — the platform proxies the request.\n */\n async requestToken(input: {\n agent_id: string;\n scope: string;\n provider_id?: string;\n }): Promise<{\n access_token: string;\n token_type: string;\n expires_in: number;\n scope: string;\n delegation_id: string;\n }> {\n return this.post('/credentials/token', input);\n }\n\n // ─── Signing ──────────────────────────────────────────────────────\n\n /**\n * Sign a payload with an Ed25519 private key (client-side).\n * Uses the Web Crypto API or Node.js crypto.\n */\n async sign(payload: string, privateKeyPem: string): Promise<string> {\n if (typeof globalThis.crypto?.subtle !== 'undefined') {\n // Web Crypto API\n const keyData = this.pemToArrayBuffer(privateKeyPem);\n const key = await globalThis.crypto.subtle.importKey(\n 'pkcs8', keyData, { name: 'Ed25519' }, false, ['sign']\n );\n const signature = await globalThis.crypto.subtle.sign(\n 'Ed25519', key, new TextEncoder().encode(payload)\n );\n return `ed25519:${this.arrayBufferToBase64(signature)}`;\n } else {\n // Node.js crypto fallback\n const crypto = await import('node:crypto');\n const sign = crypto.sign(null, Buffer.from(payload), privateKeyPem);\n return `ed25519:${sign.toString('base64')}`;\n }\n }\n\n // ─── HTTP Client ──────────────────────────────────────────────────\n\n private async get(path: string): Promise<any> {\n return this.request('GET', path);\n }\n\n private async post(path: string, body: any): Promise<any> {\n return this.request('POST', path, body);\n }\n\n private async patch(path: string, body: any): Promise<any> {\n return this.request('PATCH', path, body);\n }\n\n private async delete(path: string): Promise<any> {\n return this.request('DELETE', path);\n }\n\n private async request(method: string, path: string, body?: any): Promise<any> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': USER_AGENT,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errBody = await response.json().catch(() => ({})) as Record<string, any>;\n throw new VorimError(\n response.status,\n errBody.error?.code || 'UNKNOWN_ERROR',\n errBody.error?.message || `HTTP ${response.status}`,\n errBody.error?.details\n );\n }\n\n const json = await response.json() as Record<string, any>;\n return json.data;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private pemToArrayBuffer(pem: string): ArrayBuffer {\n const b64 = pem.replace(/-----[^-]+-----/g, '').replace(/\\s/g, '');\n const binary = atob(b64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n }\n\n private arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n }\n}\n\nexport class VorimError extends Error {\n constructor(\n public status: number,\n public code: string,\n message: string,\n public details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'VorimError';\n }\n}\n\n// ─── Convenience export ──────────────────────────────────────────────\n\nexport default function createVorim(config: VorimConfig): VorimSDK {\n return new VorimSDK(config);\n}\n\n// Re-export types for consumers\nexport type {\n Agent, AgentRegistrationInput, AgentRegistrationResult,\n TrustRecord, AuditEventInput, AuditEventType, AuditResult,\n PermissionScope, PermissionCheckResult, AgentStatus,\n} from './types.js';\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// ============================================================================\n// VORIM SDK — TypeScript\n// Thin client wrapping the Vorim AI REST API\n// ============================================================================\n\nimport type {\n Agent, AgentRegistrationInput, AgentRegistrationResult,\n TrustRecord, AuditEventInput, PermissionScope, PermissionCheckResult,\n} from './types.js';\n\n// __SDK_VERSION__ is replaced at build time (tsup define) with the package.json\n// version, so the User-Agent always matches the published version. Falls back to\n// '0.0.0' when run un-bundled (e.g. ts-node / tests) where the define isn't applied.\ndeclare const __SDK_VERSION__: string | undefined;\nconst SDK_VERSION = typeof __SDK_VERSION__ !== 'undefined' ? __SDK_VERSION__ : '0.0.0';\nconst USER_AGENT = `vorim-sdk/${SDK_VERSION}`;\n\nexport interface VorimConfig {\n apiKey: string;\n baseUrl?: string;\n timeout?: number;\n /**\n * Auto-sign audit events with the agent's private key at emit time.\n * Default true in v3.1+. Set to false to opt out globally.\n * When enabled, the SDK signs the event using whichever private key was\n * stored via {@link VorimSDK.useAgentKey} or returned by\n * {@link VorimSDK.register}. Events for unknown agents pass through unsigned.\n */\n autoSign?: boolean;\n}\n\n/**\n * VAIP v0 canonical bytes used by Vorim's per-event signing.\n *\n * Pipe-joined content fields with empty-string substitution for missing values.\n * This is intentionally duplicated from `@vorim/shared-types` so the published\n * SDK ships with zero runtime dependencies. A parity test in this package\n * imports both definitions and asserts byte-exact equality across a fixture\n * matrix, so they cannot drift silently.\n *\n * To upgrade the format, version the function (`canonicalPayloadV1`) — never\n * edit this one. Old signatures must remain verifiable.\n */\nexport function canonicalPayloadV0(event: AuditEventInput): string {\n return [\n event.event_type,\n event.action,\n event.resource ?? '',\n event.input_hash ?? '',\n event.output_hash ?? '',\n event.result,\n ].join('|');\n}\n\nexport class VorimSDK {\n private apiKey: string;\n private baseUrl: string;\n private timeout: number;\n private autoSign: boolean;\n /**\n * In-memory keyring mapping agent_id -> PEM-encoded Ed25519 private key.\n * Populated automatically by register() and registerEphemeral(), or\n * explicitly via useAgentKey(). Lost on process restart by design; the\n * caller is responsible for durable key storage.\n */\n private agentKeys: Map<string, string> = new Map();\n\n constructor(config: VorimConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = (config.baseUrl || 'https://api.vorim.ai').replace(/\\/$/, '') + '/v1';\n this.timeout = config.timeout || 10000;\n this.autoSign = config.autoSign !== false;\n }\n\n /**\n * Register a previously-issued agent keypair so this SDK instance can\n * auto-sign events for it on emit. Use this when restoring an agent across\n * process restarts: read the agent's private_key from durable storage,\n * call useAgentKey(agentId, privateKey), and emit() will sign automatically.\n */\n useAgentKey(agentId: string, privateKeyPem: string): void {\n this.agentKeys.set(agentId, privateKeyPem);\n }\n\n /**\n * Forget an agent's signing key (e.g. after revocation). Subsequent emit()\n * calls for that agent will pass through unsigned unless a key is provided\n * inline.\n */\n forgetAgentKey(agentId: string): void {\n this.agentKeys.delete(agentId);\n }\n\n // ─── Health Check ────────────────────────────────────────────────\n\n /**\n * Ping the Vorim API to verify connectivity and API key validity.\n * Returns { status, timestamp } on success, throws VorimError on failure.\n */\n async ping(): Promise<{ status: string; timestamp: string }> {\n const response = await fetch(`${this.baseUrl.replace('/v1', '')}/health`, {\n headers: { 'User-Agent': USER_AGENT },\n signal: AbortSignal.timeout(this.timeout),\n });\n if (!response.ok) throw new VorimError(response.status, 'UNREACHABLE', 'Vorim API is not reachable');\n return response.json() as Promise<{ status: string; timestamp: string }>;\n }\n\n // ─── Agent Identity ────────────────────────────────────────────────\n\n /**\n * Register a new agent with Vorim AI.\n * Returns the agent identity and a private key (shown once).\n *\n * Side effect: the returned private_key is cached in this SDK instance's\n * in-memory keyring so subsequent emit() calls for this agent auto-sign.\n * The keyring is process-local; the caller is responsible for persisting\n * the private_key to durable storage if the agent should survive restarts.\n */\n async register(input: AgentRegistrationInput): Promise<AgentRegistrationResult> {\n const result = await this.post('/agents', input) as AgentRegistrationResult;\n if (result?.agent?.agent_id && result?.private_key) {\n this.agentKeys.set(result.agent.agent_id, result.private_key);\n }\n return result;\n }\n\n /**\n * Verify an agent's identity via the public Trust API.\n */\n async verify(agentId: string): Promise<TrustRecord> {\n return this.get(`/trust/verify/${agentId}`);\n }\n\n /**\n * Get agent details.\n */\n async getAgent(agentId: string): Promise<Agent> {\n return this.get(`/agents/${agentId}`);\n }\n\n /**\n * List all agents in the organisation.\n */\n async listAgents(params?: { page?: number; per_page?: number; status?: string }): Promise<{ agents: Agent[]; meta: any }> {\n const qs = new URLSearchParams(params as any).toString();\n return this.get(`/agents${qs ? '?' + qs : ''}`);\n }\n\n /**\n * Update an agent's metadata.\n */\n async updateAgent(agentId: string, updates: Partial<Pick<Agent, 'name' | 'description' | 'status' | 'capabilities'>>): Promise<Agent> {\n return this.patch(`/agents/${agentId}`, updates);\n }\n\n /**\n * Revoke an agent (permanent deactivation).\n */\n async revoke(agentId: string): Promise<void> {\n await this.delete(`/agents/${agentId}`);\n }\n\n // ─── Permissions ──────────────────────────────────────────────────\n\n /**\n * Check if an agent has a specific permission scope.\n * Target: < 5ms response via Redis cache.\n */\n async check(agentId: string, scope: PermissionScope): Promise<PermissionCheckResult> {\n return this.post(`/agents/${agentId}/permissions/verify`, { scope });\n }\n\n /**\n * Grant a permission scope to an agent.\n */\n async grant(agentId: string, scope: PermissionScope, options?: {\n valid_until?: string;\n rate_limit?: { max: number; window: string };\n }): Promise<any> {\n return this.post(`/agents/${agentId}/permissions`, { scope, ...options });\n }\n\n /**\n * List all active permissions for an agent.\n */\n async listPermissions(agentId: string): Promise<any[]> {\n return this.get(`/agents/${agentId}/permissions`);\n }\n\n /**\n * Revoke a specific permission scope from an agent.\n */\n async revokePermission(agentId: string, scope: PermissionScope): Promise<any> {\n return this.delete(`/agents/${agentId}/permissions/${scope}`);\n }\n\n // ─── Audit ────────────────────────────────────────────────────────\n\n /**\n * Emit an audit event for an agent action.\n *\n * By default (autoSign=true on the SDK), the event is signed with the\n * agent's private key before it leaves the process. Set options.sign=false\n * to skip signing (e.g. for testing). If the SDK has no private key for the\n * event's agent_id, the event is sent unsigned and a warning is not\n * raised — callers that require signing should check event.signature on\n * the returned event after a round-trip, or use a server-side enforcement\n * flag (VORIM_VERIFY_AUDIT_SIGNATURES).\n */\n async emit(event: AuditEventInput, options?: { sign?: boolean }): Promise<{ ingested: number }> {\n const prepared = await this.prepareEvent(event, options?.sign);\n return this.post('/audit/events', { events: [prepared] });\n }\n\n /**\n * Emit a batch of audit events (up to 1,000). Each event is signed\n * independently using its agent_id to look up the signing key. See\n * {@link VorimSDK.emit} for signing behaviour and opt-out.\n */\n async emitBatch(events: AuditEventInput[], options?: { sign?: boolean }): Promise<{ ingested: number }> {\n const prepared = await Promise.all(events.map(e => this.prepareEvent(e, options?.sign)));\n return this.post('/audit/events', { events: prepared });\n }\n\n /**\n * Internal: prepare an event for transmission. Auto-signs if the SDK has a\n * key for this agent and signing isn't explicitly opted out. Pre-existing\n * signatures on the event are respected (caller-signed events are not\n * re-signed). Per-agent failure is non-fatal: if signing throws, the event\n * still sends unsigned so a single bad key doesn't break a batch.\n */\n private async prepareEvent(\n event: AuditEventInput,\n signOverride?: boolean\n ): Promise<AuditEventInput> {\n const shouldSign = signOverride ?? this.autoSign;\n if (!shouldSign) return event;\n if (event.signature) return event;\n const key = this.agentKeys.get(event.agent_id);\n if (!key) return event;\n try {\n const signature = await this.sign(canonicalPayloadV0(event), key);\n return { ...event, signature };\n } catch {\n return event;\n }\n }\n\n /**\n * Export a signed audit bundle for a date range.\n */\n async exportAudit(from: string, to: string, format: string = 'json'): Promise<any> {\n return this.post('/audit/export', { from, to, format });\n }\n\n // ─── API Keys ──────────────────────────────────────────────────────\n\n /**\n * List all API keys for the organisation.\n */\n async listApiKeys(): Promise<any[]> {\n return this.get('/api-keys');\n }\n\n /**\n * Create a new API key.\n */\n async createApiKey(name: string, options?: { scopes?: string[]; expires_at?: string }): Promise<any> {\n return this.post('/api-keys', { name, ...options });\n }\n\n /**\n * Revoke an API key.\n */\n async deleteApiKey(keyId: string): Promise<{ revoked: boolean }> {\n return this.delete(`/api-keys/${keyId}`);\n }\n\n // ─── Ephemeral Agents ──────────────────────────────────────────────\n\n /**\n * Register an ephemeral agent with W3C did:key identity.\n * The agent auto-expires after the specified TTL.\n *\n * Side effect: the returned private_key is cached in this SDK instance's\n * in-memory keyring (matching register()).\n */\n async registerEphemeral(input: {\n capabilities: string[];\n scopes: string[];\n ttl_seconds?: number;\n }): Promise<any> {\n const result = await this.post('/agents/ephemeral', input);\n const agentId: string | undefined = result?.agent?.agent_id ?? result?.did_key;\n if (agentId && result?.private_key) {\n this.agentKeys.set(agentId, result.private_key);\n }\n return result;\n }\n\n // ─── Credential Delegation ──────────────────────────────────────────\n\n /**\n * Register an OAuth provider for credential delegation.\n */\n async registerProvider(input: {\n provider_key: string;\n display_name?: string;\n client_id: string;\n client_secret: string;\n auth_url: string;\n token_url: string;\n revoke_url?: string;\n scopes_available?: string[];\n }): Promise<any> {\n return this.post('/credentials/providers', input);\n }\n\n /**\n * List registered OAuth providers.\n */\n async listProviders(): Promise<any[]> {\n return this.get('/credentials/providers');\n }\n\n /**\n * Store an OAuth connection (user's authorized tokens).\n */\n async storeConnection(input: {\n provider_id: string;\n refresh_token: string;\n scopes_granted: string[];\n external_account_id?: string;\n }): Promise<any> {\n return this.post('/credentials/connections', input);\n }\n\n /**\n * List OAuth connections.\n */\n async listConnections(): Promise<any[]> {\n return this.get('/credentials/connections');\n }\n\n /**\n * Delegate a credential to an agent.\n * The agent will be able to request short-lived access tokens\n * for the delegated scopes without ever seeing the refresh token.\n */\n async delegateCredential(input: {\n connection_id: string;\n agent_id: string;\n scopes_delegated: string[];\n max_requests_per_hr?: number;\n valid_until?: string;\n }): Promise<any> {\n return this.post('/credentials/delegations', input);\n }\n\n /**\n * List credential delegations for the organisation or a specific agent.\n */\n async listDelegations(agentId?: string): Promise<any[]> {\n const params = agentId ? `?agent_id=${agentId}` : '';\n return this.get(`/credentials/delegations${params}`);\n }\n\n /**\n * Revoke a credential delegation (cascades to delegation chains).\n */\n async revokeDelegation(delegationId: string): Promise<{ revoked: boolean }> {\n return this.delete(`/credentials/delegations/${delegationId}`);\n }\n\n /**\n * Request a short-lived access token for an agent.\n * The agent must have an active credential delegation.\n * The refresh token is never exposed — the platform proxies the request.\n */\n async requestToken(input: {\n agent_id: string;\n scope: string;\n provider_id?: string;\n }): Promise<{\n access_token: string;\n token_type: string;\n expires_in: number;\n scope: string;\n delegation_id: string;\n }> {\n return this.post('/credentials/token', input);\n }\n\n // ─── Signing ──────────────────────────────────────────────────────\n\n /**\n * Sign a payload with an Ed25519 private key (client-side).\n * Uses the Web Crypto API or Node.js crypto.\n */\n async sign(payload: string, privateKeyPem: string): Promise<string> {\n if (typeof globalThis.crypto?.subtle !== 'undefined') {\n // Web Crypto API\n const keyData = this.pemToArrayBuffer(privateKeyPem);\n const key = await globalThis.crypto.subtle.importKey(\n 'pkcs8', keyData, { name: 'Ed25519' }, false, ['sign']\n );\n const signature = await globalThis.crypto.subtle.sign(\n 'Ed25519', key, new TextEncoder().encode(payload)\n );\n return `ed25519:${this.arrayBufferToBase64(signature)}`;\n } else {\n // Node.js crypto fallback\n const crypto = await import('node:crypto');\n const sign = crypto.sign(null, Buffer.from(payload), privateKeyPem);\n return `ed25519:${sign.toString('base64')}`;\n }\n }\n\n // ─── HTTP Client ──────────────────────────────────────────────────\n\n private async get(path: string): Promise<any> {\n return this.request('GET', path);\n }\n\n private async post(path: string, body: any): Promise<any> {\n return this.request('POST', path, body);\n }\n\n private async patch(path: string, body: any): Promise<any> {\n return this.request('PATCH', path, body);\n }\n\n private async delete(path: string): Promise<any> {\n return this.request('DELETE', path);\n }\n\n private async request(method: string, path: string, body?: any): Promise<any> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': USER_AGENT,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errBody = await response.json().catch(() => ({})) as Record<string, any>;\n throw new VorimError(\n response.status,\n errBody.error?.code || 'UNKNOWN_ERROR',\n errBody.error?.message || `HTTP ${response.status}`,\n errBody.error?.details\n );\n }\n\n const json = await response.json() as Record<string, any>;\n return json.data;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private pemToArrayBuffer(pem: string): ArrayBuffer {\n const b64 = pem.replace(/-----[^-]+-----/g, '').replace(/\\s/g, '');\n const binary = atob(b64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n }\n\n private arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n }\n}\n\nexport class VorimError extends Error {\n constructor(\n public status: number,\n public code: string,\n message: string,\n public details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'VorimError';\n }\n}\n\n// ─── Convenience export ──────────────────────────────────────────────\n\nexport default function createVorim(config: VorimConfig): VorimSDK {\n return new VorimSDK(config);\n}\n\n// Re-export types for consumers\nexport type {\n Agent, AgentRegistrationInput, AgentRegistrationResult,\n TrustRecord, AuditEventInput, AuditEventType, AuditResult,\n PermissionScope, PermissionCheckResult, AgentStatus,\n} from './types.js';\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -72,12 +72,54 @@ interface VorimConfig {
72
72
  apiKey: string;
73
73
  baseUrl?: string;
74
74
  timeout?: number;
75
+ /**
76
+ * Auto-sign audit events with the agent's private key at emit time.
77
+ * Default true in v3.1+. Set to false to opt out globally.
78
+ * When enabled, the SDK signs the event using whichever private key was
79
+ * stored via {@link VorimSDK.useAgentKey} or returned by
80
+ * {@link VorimSDK.register}. Events for unknown agents pass through unsigned.
81
+ */
82
+ autoSign?: boolean;
75
83
  }
84
+ /**
85
+ * VAIP v0 canonical bytes used by Vorim's per-event signing.
86
+ *
87
+ * Pipe-joined content fields with empty-string substitution for missing values.
88
+ * This is intentionally duplicated from `@vorim/shared-types` so the published
89
+ * SDK ships with zero runtime dependencies. A parity test in this package
90
+ * imports both definitions and asserts byte-exact equality across a fixture
91
+ * matrix, so they cannot drift silently.
92
+ *
93
+ * To upgrade the format, version the function (`canonicalPayloadV1`) — never
94
+ * edit this one. Old signatures must remain verifiable.
95
+ */
96
+ declare function canonicalPayloadV0(event: AuditEventInput): string;
76
97
  declare class VorimSDK {
77
98
  private apiKey;
78
99
  private baseUrl;
79
100
  private timeout;
101
+ private autoSign;
102
+ /**
103
+ * In-memory keyring mapping agent_id -> PEM-encoded Ed25519 private key.
104
+ * Populated automatically by register() and registerEphemeral(), or
105
+ * explicitly via useAgentKey(). Lost on process restart by design; the
106
+ * caller is responsible for durable key storage.
107
+ */
108
+ private agentKeys;
80
109
  constructor(config: VorimConfig);
110
+ /**
111
+ * Register a previously-issued agent keypair so this SDK instance can
112
+ * auto-sign events for it on emit. Use this when restoring an agent across
113
+ * process restarts: read the agent's private_key from durable storage,
114
+ * call useAgentKey(agentId, privateKey), and emit() will sign automatically.
115
+ */
116
+ useAgentKey(agentId: string, privateKeyPem: string): void;
117
+ /**
118
+ * Forget an agent's signing key (e.g. after revocation). Subsequent emit()
119
+ * calls for that agent will pass through unsigned unless a key is provided
120
+ * inline.
121
+ */
122
+ forgetAgentKey(agentId: string): void;
81
123
  /**
82
124
  * Ping the Vorim API to verify connectivity and API key validity.
83
125
  * Returns { status, timestamp } on success, throws VorimError on failure.
@@ -89,6 +131,11 @@ declare class VorimSDK {
89
131
  /**
90
132
  * Register a new agent with Vorim AI.
91
133
  * Returns the agent identity and a private key (shown once).
134
+ *
135
+ * Side effect: the returned private_key is cached in this SDK instance's
136
+ * in-memory keyring so subsequent emit() calls for this agent auto-sign.
137
+ * The keyring is process-local; the caller is responsible for persisting
138
+ * the private_key to durable storage if the agent should survive restarts.
92
139
  */
93
140
  register(input: AgentRegistrationInput): Promise<AgentRegistrationResult>;
94
141
  /**
@@ -143,16 +190,38 @@ declare class VorimSDK {
143
190
  revokePermission(agentId: string, scope: PermissionScope): Promise<any>;
144
191
  /**
145
192
  * Emit an audit event for an agent action.
193
+ *
194
+ * By default (autoSign=true on the SDK), the event is signed with the
195
+ * agent's private key before it leaves the process. Set options.sign=false
196
+ * to skip signing (e.g. for testing). If the SDK has no private key for the
197
+ * event's agent_id, the event is sent unsigned and a warning is not
198
+ * raised — callers that require signing should check event.signature on
199
+ * the returned event after a round-trip, or use a server-side enforcement
200
+ * flag (VORIM_VERIFY_AUDIT_SIGNATURES).
146
201
  */
147
- emit(event: AuditEventInput): Promise<{
202
+ emit(event: AuditEventInput, options?: {
203
+ sign?: boolean;
204
+ }): Promise<{
148
205
  ingested: number;
149
206
  }>;
150
207
  /**
151
- * Emit a batch of audit events (up to 1,000).
208
+ * Emit a batch of audit events (up to 1,000). Each event is signed
209
+ * independently using its agent_id to look up the signing key. See
210
+ * {@link VorimSDK.emit} for signing behaviour and opt-out.
152
211
  */
153
- emitBatch(events: AuditEventInput[]): Promise<{
212
+ emitBatch(events: AuditEventInput[], options?: {
213
+ sign?: boolean;
214
+ }): Promise<{
154
215
  ingested: number;
155
216
  }>;
217
+ /**
218
+ * Internal: prepare an event for transmission. Auto-signs if the SDK has a
219
+ * key for this agent and signing isn't explicitly opted out. Pre-existing
220
+ * signatures on the event are respected (caller-signed events are not
221
+ * re-signed). Per-agent failure is non-fatal: if signing throws, the event
222
+ * still sends unsigned so a single bad key doesn't break a batch.
223
+ */
224
+ private prepareEvent;
156
225
  /**
157
226
  * Export a signed audit bundle for a date range.
158
227
  */
@@ -177,6 +246,9 @@ declare class VorimSDK {
177
246
  /**
178
247
  * Register an ephemeral agent with W3C did:key identity.
179
248
  * The agent auto-expires after the specified TTL.
249
+ *
250
+ * Side effect: the returned private_key is cached in this SDK instance's
251
+ * in-memory keyring (matching register()).
180
252
  */
181
253
  registerEphemeral(input: {
182
254
  capabilities: string[];
@@ -272,4 +344,4 @@ declare class VorimError extends Error {
272
344
  }
273
345
  declare function createVorim(config: VorimConfig): VorimSDK;
274
346
 
275
- export { type Agent, type AgentRegistrationInput, type AgentRegistrationResult, type AgentStatus, type AuditEventInput, type AuditEventType, type AuditResult, type PermissionCheckResult, type PermissionScope, type TrustRecord, type VorimConfig, VorimError, VorimSDK, createVorim as default };
347
+ export { type Agent, type AgentRegistrationInput, type AgentRegistrationResult, type AgentStatus, type AuditEventInput, type AuditEventType, type AuditResult, type PermissionCheckResult, type PermissionScope, type TrustRecord, type VorimConfig, VorimError, VorimSDK, canonicalPayloadV0, createVorim as default };
package/dist/index.d.ts CHANGED
@@ -72,12 +72,54 @@ interface VorimConfig {
72
72
  apiKey: string;
73
73
  baseUrl?: string;
74
74
  timeout?: number;
75
+ /**
76
+ * Auto-sign audit events with the agent's private key at emit time.
77
+ * Default true in v3.1+. Set to false to opt out globally.
78
+ * When enabled, the SDK signs the event using whichever private key was
79
+ * stored via {@link VorimSDK.useAgentKey} or returned by
80
+ * {@link VorimSDK.register}. Events for unknown agents pass through unsigned.
81
+ */
82
+ autoSign?: boolean;
75
83
  }
84
+ /**
85
+ * VAIP v0 canonical bytes used by Vorim's per-event signing.
86
+ *
87
+ * Pipe-joined content fields with empty-string substitution for missing values.
88
+ * This is intentionally duplicated from `@vorim/shared-types` so the published
89
+ * SDK ships with zero runtime dependencies. A parity test in this package
90
+ * imports both definitions and asserts byte-exact equality across a fixture
91
+ * matrix, so they cannot drift silently.
92
+ *
93
+ * To upgrade the format, version the function (`canonicalPayloadV1`) — never
94
+ * edit this one. Old signatures must remain verifiable.
95
+ */
96
+ declare function canonicalPayloadV0(event: AuditEventInput): string;
76
97
  declare class VorimSDK {
77
98
  private apiKey;
78
99
  private baseUrl;
79
100
  private timeout;
101
+ private autoSign;
102
+ /**
103
+ * In-memory keyring mapping agent_id -> PEM-encoded Ed25519 private key.
104
+ * Populated automatically by register() and registerEphemeral(), or
105
+ * explicitly via useAgentKey(). Lost on process restart by design; the
106
+ * caller is responsible for durable key storage.
107
+ */
108
+ private agentKeys;
80
109
  constructor(config: VorimConfig);
110
+ /**
111
+ * Register a previously-issued agent keypair so this SDK instance can
112
+ * auto-sign events for it on emit. Use this when restoring an agent across
113
+ * process restarts: read the agent's private_key from durable storage,
114
+ * call useAgentKey(agentId, privateKey), and emit() will sign automatically.
115
+ */
116
+ useAgentKey(agentId: string, privateKeyPem: string): void;
117
+ /**
118
+ * Forget an agent's signing key (e.g. after revocation). Subsequent emit()
119
+ * calls for that agent will pass through unsigned unless a key is provided
120
+ * inline.
121
+ */
122
+ forgetAgentKey(agentId: string): void;
81
123
  /**
82
124
  * Ping the Vorim API to verify connectivity and API key validity.
83
125
  * Returns { status, timestamp } on success, throws VorimError on failure.
@@ -89,6 +131,11 @@ declare class VorimSDK {
89
131
  /**
90
132
  * Register a new agent with Vorim AI.
91
133
  * Returns the agent identity and a private key (shown once).
134
+ *
135
+ * Side effect: the returned private_key is cached in this SDK instance's
136
+ * in-memory keyring so subsequent emit() calls for this agent auto-sign.
137
+ * The keyring is process-local; the caller is responsible for persisting
138
+ * the private_key to durable storage if the agent should survive restarts.
92
139
  */
93
140
  register(input: AgentRegistrationInput): Promise<AgentRegistrationResult>;
94
141
  /**
@@ -143,16 +190,38 @@ declare class VorimSDK {
143
190
  revokePermission(agentId: string, scope: PermissionScope): Promise<any>;
144
191
  /**
145
192
  * Emit an audit event for an agent action.
193
+ *
194
+ * By default (autoSign=true on the SDK), the event is signed with the
195
+ * agent's private key before it leaves the process. Set options.sign=false
196
+ * to skip signing (e.g. for testing). If the SDK has no private key for the
197
+ * event's agent_id, the event is sent unsigned and a warning is not
198
+ * raised — callers that require signing should check event.signature on
199
+ * the returned event after a round-trip, or use a server-side enforcement
200
+ * flag (VORIM_VERIFY_AUDIT_SIGNATURES).
146
201
  */
147
- emit(event: AuditEventInput): Promise<{
202
+ emit(event: AuditEventInput, options?: {
203
+ sign?: boolean;
204
+ }): Promise<{
148
205
  ingested: number;
149
206
  }>;
150
207
  /**
151
- * Emit a batch of audit events (up to 1,000).
208
+ * Emit a batch of audit events (up to 1,000). Each event is signed
209
+ * independently using its agent_id to look up the signing key. See
210
+ * {@link VorimSDK.emit} for signing behaviour and opt-out.
152
211
  */
153
- emitBatch(events: AuditEventInput[]): Promise<{
212
+ emitBatch(events: AuditEventInput[], options?: {
213
+ sign?: boolean;
214
+ }): Promise<{
154
215
  ingested: number;
155
216
  }>;
217
+ /**
218
+ * Internal: prepare an event for transmission. Auto-signs if the SDK has a
219
+ * key for this agent and signing isn't explicitly opted out. Pre-existing
220
+ * signatures on the event are respected (caller-signed events are not
221
+ * re-signed). Per-agent failure is non-fatal: if signing throws, the event
222
+ * still sends unsigned so a single bad key doesn't break a batch.
223
+ */
224
+ private prepareEvent;
156
225
  /**
157
226
  * Export a signed audit bundle for a date range.
158
227
  */
@@ -177,6 +246,9 @@ declare class VorimSDK {
177
246
  /**
178
247
  * Register an ephemeral agent with W3C did:key identity.
179
248
  * The agent auto-expires after the specified TTL.
249
+ *
250
+ * Side effect: the returned private_key is cached in this SDK instance's
251
+ * in-memory keyring (matching register()).
180
252
  */
181
253
  registerEphemeral(input: {
182
254
  capabilities: string[];
@@ -272,4 +344,4 @@ declare class VorimError extends Error {
272
344
  }
273
345
  declare function createVorim(config: VorimConfig): VorimSDK;
274
346
 
275
- export { type Agent, type AgentRegistrationInput, type AgentRegistrationResult, type AgentStatus, type AuditEventInput, type AuditEventType, type AuditResult, type PermissionCheckResult, type PermissionScope, type TrustRecord, type VorimConfig, VorimError, VorimSDK, createVorim as default };
347
+ export { type Agent, type AgentRegistrationInput, type AgentRegistrationResult, type AgentStatus, type AuditEventInput, type AuditEventType, type AuditResult, type PermissionCheckResult, type PermissionScope, type TrustRecord, type VorimConfig, VorimError, VorimSDK, canonicalPayloadV0, createVorim as default };
package/dist/index.js CHANGED
@@ -1,14 +1,50 @@
1
1
  // src/index.ts
2
- var SDK_VERSION = "3.0.2";
2
+ var SDK_VERSION = true ? "3.1.0" : "0.0.0";
3
3
  var USER_AGENT = `vorim-sdk/${SDK_VERSION}`;
4
+ function canonicalPayloadV0(event) {
5
+ return [
6
+ event.event_type,
7
+ event.action,
8
+ event.resource ?? "",
9
+ event.input_hash ?? "",
10
+ event.output_hash ?? "",
11
+ event.result
12
+ ].join("|");
13
+ }
4
14
  var VorimSDK = class {
5
15
  apiKey;
6
16
  baseUrl;
7
17
  timeout;
18
+ autoSign;
19
+ /**
20
+ * In-memory keyring mapping agent_id -> PEM-encoded Ed25519 private key.
21
+ * Populated automatically by register() and registerEphemeral(), or
22
+ * explicitly via useAgentKey(). Lost on process restart by design; the
23
+ * caller is responsible for durable key storage.
24
+ */
25
+ agentKeys = /* @__PURE__ */ new Map();
8
26
  constructor(config) {
9
27
  this.apiKey = config.apiKey;
10
28
  this.baseUrl = (config.baseUrl || "https://api.vorim.ai").replace(/\/$/, "") + "/v1";
11
29
  this.timeout = config.timeout || 1e4;
30
+ this.autoSign = config.autoSign !== false;
31
+ }
32
+ /**
33
+ * Register a previously-issued agent keypair so this SDK instance can
34
+ * auto-sign events for it on emit. Use this when restoring an agent across
35
+ * process restarts: read the agent's private_key from durable storage,
36
+ * call useAgentKey(agentId, privateKey), and emit() will sign automatically.
37
+ */
38
+ useAgentKey(agentId, privateKeyPem) {
39
+ this.agentKeys.set(agentId, privateKeyPem);
40
+ }
41
+ /**
42
+ * Forget an agent's signing key (e.g. after revocation). Subsequent emit()
43
+ * calls for that agent will pass through unsigned unless a key is provided
44
+ * inline.
45
+ */
46
+ forgetAgentKey(agentId) {
47
+ this.agentKeys.delete(agentId);
12
48
  }
13
49
  // ─── Health Check ────────────────────────────────────────────────
14
50
  /**
@@ -27,9 +63,18 @@ var VorimSDK = class {
27
63
  /**
28
64
  * Register a new agent with Vorim AI.
29
65
  * Returns the agent identity and a private key (shown once).
66
+ *
67
+ * Side effect: the returned private_key is cached in this SDK instance's
68
+ * in-memory keyring so subsequent emit() calls for this agent auto-sign.
69
+ * The keyring is process-local; the caller is responsible for persisting
70
+ * the private_key to durable storage if the agent should survive restarts.
30
71
  */
31
72
  async register(input) {
32
- return this.post("/agents", input);
73
+ const result = await this.post("/agents", input);
74
+ if (result?.agent?.agent_id && result?.private_key) {
75
+ this.agentKeys.set(result.agent.agent_id, result.private_key);
76
+ }
77
+ return result;
33
78
  }
34
79
  /**
35
80
  * Verify an agent's identity via the public Trust API.
@@ -91,15 +136,47 @@ var VorimSDK = class {
91
136
  // ─── Audit ────────────────────────────────────────────────────────
92
137
  /**
93
138
  * Emit an audit event for an agent action.
139
+ *
140
+ * By default (autoSign=true on the SDK), the event is signed with the
141
+ * agent's private key before it leaves the process. Set options.sign=false
142
+ * to skip signing (e.g. for testing). If the SDK has no private key for the
143
+ * event's agent_id, the event is sent unsigned and a warning is not
144
+ * raised — callers that require signing should check event.signature on
145
+ * the returned event after a round-trip, or use a server-side enforcement
146
+ * flag (VORIM_VERIFY_AUDIT_SIGNATURES).
147
+ */
148
+ async emit(event, options) {
149
+ const prepared = await this.prepareEvent(event, options?.sign);
150
+ return this.post("/audit/events", { events: [prepared] });
151
+ }
152
+ /**
153
+ * Emit a batch of audit events (up to 1,000). Each event is signed
154
+ * independently using its agent_id to look up the signing key. See
155
+ * {@link VorimSDK.emit} for signing behaviour and opt-out.
94
156
  */
95
- async emit(event) {
96
- return this.post("/audit/events", { events: [event] });
157
+ async emitBatch(events, options) {
158
+ const prepared = await Promise.all(events.map((e) => this.prepareEvent(e, options?.sign)));
159
+ return this.post("/audit/events", { events: prepared });
97
160
  }
98
161
  /**
99
- * Emit a batch of audit events (up to 1,000).
162
+ * Internal: prepare an event for transmission. Auto-signs if the SDK has a
163
+ * key for this agent and signing isn't explicitly opted out. Pre-existing
164
+ * signatures on the event are respected (caller-signed events are not
165
+ * re-signed). Per-agent failure is non-fatal: if signing throws, the event
166
+ * still sends unsigned so a single bad key doesn't break a batch.
100
167
  */
101
- async emitBatch(events) {
102
- return this.post("/audit/events", { events });
168
+ async prepareEvent(event, signOverride) {
169
+ const shouldSign = signOverride ?? this.autoSign;
170
+ if (!shouldSign) return event;
171
+ if (event.signature) return event;
172
+ const key = this.agentKeys.get(event.agent_id);
173
+ if (!key) return event;
174
+ try {
175
+ const signature = await this.sign(canonicalPayloadV0(event), key);
176
+ return { ...event, signature };
177
+ } catch {
178
+ return event;
179
+ }
103
180
  }
104
181
  /**
105
182
  * Export a signed audit bundle for a date range.
@@ -130,9 +207,17 @@ var VorimSDK = class {
130
207
  /**
131
208
  * Register an ephemeral agent with W3C did:key identity.
132
209
  * The agent auto-expires after the specified TTL.
210
+ *
211
+ * Side effect: the returned private_key is cached in this SDK instance's
212
+ * in-memory keyring (matching register()).
133
213
  */
134
214
  async registerEphemeral(input) {
135
- return this.post("/agents/ephemeral", input);
215
+ const result = await this.post("/agents/ephemeral", input);
216
+ const agentId = result?.agent?.agent_id ?? result?.did_key;
217
+ if (agentId && result?.private_key) {
218
+ this.agentKeys.set(agentId, result.private_key);
219
+ }
220
+ return result;
136
221
  }
137
222
  // ─── Credential Delegation ──────────────────────────────────────────
138
223
  /**
@@ -283,6 +368,9 @@ var VorimError = class extends Error {
283
368
  this.details = details;
284
369
  this.name = "VorimError";
285
370
  }
371
+ status;
372
+ code;
373
+ details;
286
374
  };
287
375
  function createVorim(config) {
288
376
  return new VorimSDK(config);
@@ -290,6 +378,7 @@ function createVorim(config) {
290
378
  export {
291
379
  VorimError,
292
380
  VorimSDK,
381
+ canonicalPayloadV0,
293
382
  createVorim as default
294
383
  };
295
384
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// ============================================================================\n// VORIM SDK — TypeScript\n// Thin client wrapping the Vorim AI REST API\n// ============================================================================\n\nimport type {\n Agent, AgentRegistrationInput, AgentRegistrationResult,\n TrustRecord, AuditEventInput, PermissionScope, PermissionCheckResult,\n} from './types.js';\n\n// Keep in sync with package.json version. Used in the User-Agent header.\nconst SDK_VERSION = '3.0.2';\nconst USER_AGENT = `vorim-sdk/${SDK_VERSION}`;\n\nexport interface VorimConfig {\n apiKey: string;\n baseUrl?: string;\n timeout?: number;\n}\n\nexport class VorimSDK {\n private apiKey: string;\n private baseUrl: string;\n private timeout: number;\n\n constructor(config: VorimConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = (config.baseUrl || 'https://api.vorim.ai').replace(/\\/$/, '') + '/v1';\n this.timeout = config.timeout || 10000;\n }\n\n // ─── Health Check ────────────────────────────────────────────────\n\n /**\n * Ping the Vorim API to verify connectivity and API key validity.\n * Returns { status, timestamp } on success, throws VorimError on failure.\n */\n async ping(): Promise<{ status: string; timestamp: string }> {\n const response = await fetch(`${this.baseUrl.replace('/v1', '')}/health`, {\n headers: { 'User-Agent': USER_AGENT },\n signal: AbortSignal.timeout(this.timeout),\n });\n if (!response.ok) throw new VorimError(response.status, 'UNREACHABLE', 'Vorim API is not reachable');\n return response.json() as Promise<{ status: string; timestamp: string }>;\n }\n\n // ─── Agent Identity ────────────────────────────────────────────────\n\n /**\n * Register a new agent with Vorim AI.\n * Returns the agent identity and a private key (shown once).\n */\n async register(input: AgentRegistrationInput): Promise<AgentRegistrationResult> {\n return this.post('/agents', input);\n }\n\n /**\n * Verify an agent's identity via the public Trust API.\n */\n async verify(agentId: string): Promise<TrustRecord> {\n return this.get(`/trust/verify/${agentId}`);\n }\n\n /**\n * Get agent details.\n */\n async getAgent(agentId: string): Promise<Agent> {\n return this.get(`/agents/${agentId}`);\n }\n\n /**\n * List all agents in the organisation.\n */\n async listAgents(params?: { page?: number; per_page?: number; status?: string }): Promise<{ agents: Agent[]; meta: any }> {\n const qs = new URLSearchParams(params as any).toString();\n return this.get(`/agents${qs ? '?' + qs : ''}`);\n }\n\n /**\n * Update an agent's metadata.\n */\n async updateAgent(agentId: string, updates: Partial<Pick<Agent, 'name' | 'description' | 'status' | 'capabilities'>>): Promise<Agent> {\n return this.patch(`/agents/${agentId}`, updates);\n }\n\n /**\n * Revoke an agent (permanent deactivation).\n */\n async revoke(agentId: string): Promise<void> {\n await this.delete(`/agents/${agentId}`);\n }\n\n // ─── Permissions ──────────────────────────────────────────────────\n\n /**\n * Check if an agent has a specific permission scope.\n * Target: < 5ms response via Redis cache.\n */\n async check(agentId: string, scope: PermissionScope): Promise<PermissionCheckResult> {\n return this.post(`/agents/${agentId}/permissions/verify`, { scope });\n }\n\n /**\n * Grant a permission scope to an agent.\n */\n async grant(agentId: string, scope: PermissionScope, options?: {\n valid_until?: string;\n rate_limit?: { max: number; window: string };\n }): Promise<any> {\n return this.post(`/agents/${agentId}/permissions`, { scope, ...options });\n }\n\n /**\n * List all active permissions for an agent.\n */\n async listPermissions(agentId: string): Promise<any[]> {\n return this.get(`/agents/${agentId}/permissions`);\n }\n\n /**\n * Revoke a specific permission scope from an agent.\n */\n async revokePermission(agentId: string, scope: PermissionScope): Promise<any> {\n return this.delete(`/agents/${agentId}/permissions/${scope}`);\n }\n\n // ─── Audit ────────────────────────────────────────────────────────\n\n /**\n * Emit an audit event for an agent action.\n */\n async emit(event: AuditEventInput): Promise<{ ingested: number }> {\n return this.post('/audit/events', { events: [event] });\n }\n\n /**\n * Emit a batch of audit events (up to 1,000).\n */\n async emitBatch(events: AuditEventInput[]): Promise<{ ingested: number }> {\n return this.post('/audit/events', { events });\n }\n\n /**\n * Export a signed audit bundle for a date range.\n */\n async exportAudit(from: string, to: string, format: string = 'json'): Promise<any> {\n return this.post('/audit/export', { from, to, format });\n }\n\n // ─── API Keys ──────────────────────────────────────────────────────\n\n /**\n * List all API keys for the organisation.\n */\n async listApiKeys(): Promise<any[]> {\n return this.get('/api-keys');\n }\n\n /**\n * Create a new API key.\n */\n async createApiKey(name: string, options?: { scopes?: string[]; expires_at?: string }): Promise<any> {\n return this.post('/api-keys', { name, ...options });\n }\n\n /**\n * Revoke an API key.\n */\n async deleteApiKey(keyId: string): Promise<{ revoked: boolean }> {\n return this.delete(`/api-keys/${keyId}`);\n }\n\n // ─── Ephemeral Agents ──────────────────────────────────────────────\n\n /**\n * Register an ephemeral agent with W3C did:key identity.\n * The agent auto-expires after the specified TTL.\n */\n async registerEphemeral(input: {\n capabilities: string[];\n scopes: string[];\n ttl_seconds?: number;\n }): Promise<any> {\n return this.post('/agents/ephemeral', input);\n }\n\n // ─── Credential Delegation ──────────────────────────────────────────\n\n /**\n * Register an OAuth provider for credential delegation.\n */\n async registerProvider(input: {\n provider_key: string;\n display_name?: string;\n client_id: string;\n client_secret: string;\n auth_url: string;\n token_url: string;\n revoke_url?: string;\n scopes_available?: string[];\n }): Promise<any> {\n return this.post('/credentials/providers', input);\n }\n\n /**\n * List registered OAuth providers.\n */\n async listProviders(): Promise<any[]> {\n return this.get('/credentials/providers');\n }\n\n /**\n * Store an OAuth connection (user's authorized tokens).\n */\n async storeConnection(input: {\n provider_id: string;\n refresh_token: string;\n scopes_granted: string[];\n external_account_id?: string;\n }): Promise<any> {\n return this.post('/credentials/connections', input);\n }\n\n /**\n * List OAuth connections.\n */\n async listConnections(): Promise<any[]> {\n return this.get('/credentials/connections');\n }\n\n /**\n * Delegate a credential to an agent.\n * The agent will be able to request short-lived access tokens\n * for the delegated scopes without ever seeing the refresh token.\n */\n async delegateCredential(input: {\n connection_id: string;\n agent_id: string;\n scopes_delegated: string[];\n max_requests_per_hr?: number;\n valid_until?: string;\n }): Promise<any> {\n return this.post('/credentials/delegations', input);\n }\n\n /**\n * List credential delegations for the organisation or a specific agent.\n */\n async listDelegations(agentId?: string): Promise<any[]> {\n const params = agentId ? `?agent_id=${agentId}` : '';\n return this.get(`/credentials/delegations${params}`);\n }\n\n /**\n * Revoke a credential delegation (cascades to delegation chains).\n */\n async revokeDelegation(delegationId: string): Promise<{ revoked: boolean }> {\n return this.delete(`/credentials/delegations/${delegationId}`);\n }\n\n /**\n * Request a short-lived access token for an agent.\n * The agent must have an active credential delegation.\n * The refresh token is never exposed — the platform proxies the request.\n */\n async requestToken(input: {\n agent_id: string;\n scope: string;\n provider_id?: string;\n }): Promise<{\n access_token: string;\n token_type: string;\n expires_in: number;\n scope: string;\n delegation_id: string;\n }> {\n return this.post('/credentials/token', input);\n }\n\n // ─── Signing ──────────────────────────────────────────────────────\n\n /**\n * Sign a payload with an Ed25519 private key (client-side).\n * Uses the Web Crypto API or Node.js crypto.\n */\n async sign(payload: string, privateKeyPem: string): Promise<string> {\n if (typeof globalThis.crypto?.subtle !== 'undefined') {\n // Web Crypto API\n const keyData = this.pemToArrayBuffer(privateKeyPem);\n const key = await globalThis.crypto.subtle.importKey(\n 'pkcs8', keyData, { name: 'Ed25519' }, false, ['sign']\n );\n const signature = await globalThis.crypto.subtle.sign(\n 'Ed25519', key, new TextEncoder().encode(payload)\n );\n return `ed25519:${this.arrayBufferToBase64(signature)}`;\n } else {\n // Node.js crypto fallback\n const crypto = await import('node:crypto');\n const sign = crypto.sign(null, Buffer.from(payload), privateKeyPem);\n return `ed25519:${sign.toString('base64')}`;\n }\n }\n\n // ─── HTTP Client ──────────────────────────────────────────────────\n\n private async get(path: string): Promise<any> {\n return this.request('GET', path);\n }\n\n private async post(path: string, body: any): Promise<any> {\n return this.request('POST', path, body);\n }\n\n private async patch(path: string, body: any): Promise<any> {\n return this.request('PATCH', path, body);\n }\n\n private async delete(path: string): Promise<any> {\n return this.request('DELETE', path);\n }\n\n private async request(method: string, path: string, body?: any): Promise<any> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': USER_AGENT,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errBody = await response.json().catch(() => ({})) as Record<string, any>;\n throw new VorimError(\n response.status,\n errBody.error?.code || 'UNKNOWN_ERROR',\n errBody.error?.message || `HTTP ${response.status}`,\n errBody.error?.details\n );\n }\n\n const json = await response.json() as Record<string, any>;\n return json.data;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private pemToArrayBuffer(pem: string): ArrayBuffer {\n const b64 = pem.replace(/-----[^-]+-----/g, '').replace(/\\s/g, '');\n const binary = atob(b64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n }\n\n private arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n }\n}\n\nexport class VorimError extends Error {\n constructor(\n public status: number,\n public code: string,\n message: string,\n public details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'VorimError';\n }\n}\n\n// ─── Convenience export ──────────────────────────────────────────────\n\nexport default function createVorim(config: VorimConfig): VorimSDK {\n return new VorimSDK(config);\n}\n\n// Re-export types for consumers\nexport type {\n Agent, AgentRegistrationInput, AgentRegistrationResult,\n TrustRecord, AuditEventInput, AuditEventType, AuditResult,\n PermissionScope, PermissionCheckResult, AgentStatus,\n} from './types.js';\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// ============================================================================\n// VORIM SDK — TypeScript\n// Thin client wrapping the Vorim AI REST API\n// ============================================================================\n\nimport type {\n Agent, AgentRegistrationInput, AgentRegistrationResult,\n TrustRecord, AuditEventInput, PermissionScope, PermissionCheckResult,\n} from './types.js';\n\n// __SDK_VERSION__ is replaced at build time (tsup define) with the package.json\n// version, so the User-Agent always matches the published version. Falls back to\n// '0.0.0' when run un-bundled (e.g. ts-node / tests) where the define isn't applied.\ndeclare const __SDK_VERSION__: string | undefined;\nconst SDK_VERSION = typeof __SDK_VERSION__ !== 'undefined' ? __SDK_VERSION__ : '0.0.0';\nconst USER_AGENT = `vorim-sdk/${SDK_VERSION}`;\n\nexport interface VorimConfig {\n apiKey: string;\n baseUrl?: string;\n timeout?: number;\n /**\n * Auto-sign audit events with the agent's private key at emit time.\n * Default true in v3.1+. Set to false to opt out globally.\n * When enabled, the SDK signs the event using whichever private key was\n * stored via {@link VorimSDK.useAgentKey} or returned by\n * {@link VorimSDK.register}. Events for unknown agents pass through unsigned.\n */\n autoSign?: boolean;\n}\n\n/**\n * VAIP v0 canonical bytes used by Vorim's per-event signing.\n *\n * Pipe-joined content fields with empty-string substitution for missing values.\n * This is intentionally duplicated from `@vorim/shared-types` so the published\n * SDK ships with zero runtime dependencies. A parity test in this package\n * imports both definitions and asserts byte-exact equality across a fixture\n * matrix, so they cannot drift silently.\n *\n * To upgrade the format, version the function (`canonicalPayloadV1`) — never\n * edit this one. Old signatures must remain verifiable.\n */\nexport function canonicalPayloadV0(event: AuditEventInput): string {\n return [\n event.event_type,\n event.action,\n event.resource ?? '',\n event.input_hash ?? '',\n event.output_hash ?? '',\n event.result,\n ].join('|');\n}\n\nexport class VorimSDK {\n private apiKey: string;\n private baseUrl: string;\n private timeout: number;\n private autoSign: boolean;\n /**\n * In-memory keyring mapping agent_id -> PEM-encoded Ed25519 private key.\n * Populated automatically by register() and registerEphemeral(), or\n * explicitly via useAgentKey(). Lost on process restart by design; the\n * caller is responsible for durable key storage.\n */\n private agentKeys: Map<string, string> = new Map();\n\n constructor(config: VorimConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = (config.baseUrl || 'https://api.vorim.ai').replace(/\\/$/, '') + '/v1';\n this.timeout = config.timeout || 10000;\n this.autoSign = config.autoSign !== false;\n }\n\n /**\n * Register a previously-issued agent keypair so this SDK instance can\n * auto-sign events for it on emit. Use this when restoring an agent across\n * process restarts: read the agent's private_key from durable storage,\n * call useAgentKey(agentId, privateKey), and emit() will sign automatically.\n */\n useAgentKey(agentId: string, privateKeyPem: string): void {\n this.agentKeys.set(agentId, privateKeyPem);\n }\n\n /**\n * Forget an agent's signing key (e.g. after revocation). Subsequent emit()\n * calls for that agent will pass through unsigned unless a key is provided\n * inline.\n */\n forgetAgentKey(agentId: string): void {\n this.agentKeys.delete(agentId);\n }\n\n // ─── Health Check ────────────────────────────────────────────────\n\n /**\n * Ping the Vorim API to verify connectivity and API key validity.\n * Returns { status, timestamp } on success, throws VorimError on failure.\n */\n async ping(): Promise<{ status: string; timestamp: string }> {\n const response = await fetch(`${this.baseUrl.replace('/v1', '')}/health`, {\n headers: { 'User-Agent': USER_AGENT },\n signal: AbortSignal.timeout(this.timeout),\n });\n if (!response.ok) throw new VorimError(response.status, 'UNREACHABLE', 'Vorim API is not reachable');\n return response.json() as Promise<{ status: string; timestamp: string }>;\n }\n\n // ─── Agent Identity ────────────────────────────────────────────────\n\n /**\n * Register a new agent with Vorim AI.\n * Returns the agent identity and a private key (shown once).\n *\n * Side effect: the returned private_key is cached in this SDK instance's\n * in-memory keyring so subsequent emit() calls for this agent auto-sign.\n * The keyring is process-local; the caller is responsible for persisting\n * the private_key to durable storage if the agent should survive restarts.\n */\n async register(input: AgentRegistrationInput): Promise<AgentRegistrationResult> {\n const result = await this.post('/agents', input) as AgentRegistrationResult;\n if (result?.agent?.agent_id && result?.private_key) {\n this.agentKeys.set(result.agent.agent_id, result.private_key);\n }\n return result;\n }\n\n /**\n * Verify an agent's identity via the public Trust API.\n */\n async verify(agentId: string): Promise<TrustRecord> {\n return this.get(`/trust/verify/${agentId}`);\n }\n\n /**\n * Get agent details.\n */\n async getAgent(agentId: string): Promise<Agent> {\n return this.get(`/agents/${agentId}`);\n }\n\n /**\n * List all agents in the organisation.\n */\n async listAgents(params?: { page?: number; per_page?: number; status?: string }): Promise<{ agents: Agent[]; meta: any }> {\n const qs = new URLSearchParams(params as any).toString();\n return this.get(`/agents${qs ? '?' + qs : ''}`);\n }\n\n /**\n * Update an agent's metadata.\n */\n async updateAgent(agentId: string, updates: Partial<Pick<Agent, 'name' | 'description' | 'status' | 'capabilities'>>): Promise<Agent> {\n return this.patch(`/agents/${agentId}`, updates);\n }\n\n /**\n * Revoke an agent (permanent deactivation).\n */\n async revoke(agentId: string): Promise<void> {\n await this.delete(`/agents/${agentId}`);\n }\n\n // ─── Permissions ──────────────────────────────────────────────────\n\n /**\n * Check if an agent has a specific permission scope.\n * Target: < 5ms response via Redis cache.\n */\n async check(agentId: string, scope: PermissionScope): Promise<PermissionCheckResult> {\n return this.post(`/agents/${agentId}/permissions/verify`, { scope });\n }\n\n /**\n * Grant a permission scope to an agent.\n */\n async grant(agentId: string, scope: PermissionScope, options?: {\n valid_until?: string;\n rate_limit?: { max: number; window: string };\n }): Promise<any> {\n return this.post(`/agents/${agentId}/permissions`, { scope, ...options });\n }\n\n /**\n * List all active permissions for an agent.\n */\n async listPermissions(agentId: string): Promise<any[]> {\n return this.get(`/agents/${agentId}/permissions`);\n }\n\n /**\n * Revoke a specific permission scope from an agent.\n */\n async revokePermission(agentId: string, scope: PermissionScope): Promise<any> {\n return this.delete(`/agents/${agentId}/permissions/${scope}`);\n }\n\n // ─── Audit ────────────────────────────────────────────────────────\n\n /**\n * Emit an audit event for an agent action.\n *\n * By default (autoSign=true on the SDK), the event is signed with the\n * agent's private key before it leaves the process. Set options.sign=false\n * to skip signing (e.g. for testing). If the SDK has no private key for the\n * event's agent_id, the event is sent unsigned and a warning is not\n * raised — callers that require signing should check event.signature on\n * the returned event after a round-trip, or use a server-side enforcement\n * flag (VORIM_VERIFY_AUDIT_SIGNATURES).\n */\n async emit(event: AuditEventInput, options?: { sign?: boolean }): Promise<{ ingested: number }> {\n const prepared = await this.prepareEvent(event, options?.sign);\n return this.post('/audit/events', { events: [prepared] });\n }\n\n /**\n * Emit a batch of audit events (up to 1,000). Each event is signed\n * independently using its agent_id to look up the signing key. See\n * {@link VorimSDK.emit} for signing behaviour and opt-out.\n */\n async emitBatch(events: AuditEventInput[], options?: { sign?: boolean }): Promise<{ ingested: number }> {\n const prepared = await Promise.all(events.map(e => this.prepareEvent(e, options?.sign)));\n return this.post('/audit/events', { events: prepared });\n }\n\n /**\n * Internal: prepare an event for transmission. Auto-signs if the SDK has a\n * key for this agent and signing isn't explicitly opted out. Pre-existing\n * signatures on the event are respected (caller-signed events are not\n * re-signed). Per-agent failure is non-fatal: if signing throws, the event\n * still sends unsigned so a single bad key doesn't break a batch.\n */\n private async prepareEvent(\n event: AuditEventInput,\n signOverride?: boolean\n ): Promise<AuditEventInput> {\n const shouldSign = signOverride ?? this.autoSign;\n if (!shouldSign) return event;\n if (event.signature) return event;\n const key = this.agentKeys.get(event.agent_id);\n if (!key) return event;\n try {\n const signature = await this.sign(canonicalPayloadV0(event), key);\n return { ...event, signature };\n } catch {\n return event;\n }\n }\n\n /**\n * Export a signed audit bundle for a date range.\n */\n async exportAudit(from: string, to: string, format: string = 'json'): Promise<any> {\n return this.post('/audit/export', { from, to, format });\n }\n\n // ─── API Keys ──────────────────────────────────────────────────────\n\n /**\n * List all API keys for the organisation.\n */\n async listApiKeys(): Promise<any[]> {\n return this.get('/api-keys');\n }\n\n /**\n * Create a new API key.\n */\n async createApiKey(name: string, options?: { scopes?: string[]; expires_at?: string }): Promise<any> {\n return this.post('/api-keys', { name, ...options });\n }\n\n /**\n * Revoke an API key.\n */\n async deleteApiKey(keyId: string): Promise<{ revoked: boolean }> {\n return this.delete(`/api-keys/${keyId}`);\n }\n\n // ─── Ephemeral Agents ──────────────────────────────────────────────\n\n /**\n * Register an ephemeral agent with W3C did:key identity.\n * The agent auto-expires after the specified TTL.\n *\n * Side effect: the returned private_key is cached in this SDK instance's\n * in-memory keyring (matching register()).\n */\n async registerEphemeral(input: {\n capabilities: string[];\n scopes: string[];\n ttl_seconds?: number;\n }): Promise<any> {\n const result = await this.post('/agents/ephemeral', input);\n const agentId: string | undefined = result?.agent?.agent_id ?? result?.did_key;\n if (agentId && result?.private_key) {\n this.agentKeys.set(agentId, result.private_key);\n }\n return result;\n }\n\n // ─── Credential Delegation ──────────────────────────────────────────\n\n /**\n * Register an OAuth provider for credential delegation.\n */\n async registerProvider(input: {\n provider_key: string;\n display_name?: string;\n client_id: string;\n client_secret: string;\n auth_url: string;\n token_url: string;\n revoke_url?: string;\n scopes_available?: string[];\n }): Promise<any> {\n return this.post('/credentials/providers', input);\n }\n\n /**\n * List registered OAuth providers.\n */\n async listProviders(): Promise<any[]> {\n return this.get('/credentials/providers');\n }\n\n /**\n * Store an OAuth connection (user's authorized tokens).\n */\n async storeConnection(input: {\n provider_id: string;\n refresh_token: string;\n scopes_granted: string[];\n external_account_id?: string;\n }): Promise<any> {\n return this.post('/credentials/connections', input);\n }\n\n /**\n * List OAuth connections.\n */\n async listConnections(): Promise<any[]> {\n return this.get('/credentials/connections');\n }\n\n /**\n * Delegate a credential to an agent.\n * The agent will be able to request short-lived access tokens\n * for the delegated scopes without ever seeing the refresh token.\n */\n async delegateCredential(input: {\n connection_id: string;\n agent_id: string;\n scopes_delegated: string[];\n max_requests_per_hr?: number;\n valid_until?: string;\n }): Promise<any> {\n return this.post('/credentials/delegations', input);\n }\n\n /**\n * List credential delegations for the organisation or a specific agent.\n */\n async listDelegations(agentId?: string): Promise<any[]> {\n const params = agentId ? `?agent_id=${agentId}` : '';\n return this.get(`/credentials/delegations${params}`);\n }\n\n /**\n * Revoke a credential delegation (cascades to delegation chains).\n */\n async revokeDelegation(delegationId: string): Promise<{ revoked: boolean }> {\n return this.delete(`/credentials/delegations/${delegationId}`);\n }\n\n /**\n * Request a short-lived access token for an agent.\n * The agent must have an active credential delegation.\n * The refresh token is never exposed — the platform proxies the request.\n */\n async requestToken(input: {\n agent_id: string;\n scope: string;\n provider_id?: string;\n }): Promise<{\n access_token: string;\n token_type: string;\n expires_in: number;\n scope: string;\n delegation_id: string;\n }> {\n return this.post('/credentials/token', input);\n }\n\n // ─── Signing ──────────────────────────────────────────────────────\n\n /**\n * Sign a payload with an Ed25519 private key (client-side).\n * Uses the Web Crypto API or Node.js crypto.\n */\n async sign(payload: string, privateKeyPem: string): Promise<string> {\n if (typeof globalThis.crypto?.subtle !== 'undefined') {\n // Web Crypto API\n const keyData = this.pemToArrayBuffer(privateKeyPem);\n const key = await globalThis.crypto.subtle.importKey(\n 'pkcs8', keyData, { name: 'Ed25519' }, false, ['sign']\n );\n const signature = await globalThis.crypto.subtle.sign(\n 'Ed25519', key, new TextEncoder().encode(payload)\n );\n return `ed25519:${this.arrayBufferToBase64(signature)}`;\n } else {\n // Node.js crypto fallback\n const crypto = await import('node:crypto');\n const sign = crypto.sign(null, Buffer.from(payload), privateKeyPem);\n return `ed25519:${sign.toString('base64')}`;\n }\n }\n\n // ─── HTTP Client ──────────────────────────────────────────────────\n\n private async get(path: string): Promise<any> {\n return this.request('GET', path);\n }\n\n private async post(path: string, body: any): Promise<any> {\n return this.request('POST', path, body);\n }\n\n private async patch(path: string, body: any): Promise<any> {\n return this.request('PATCH', path, body);\n }\n\n private async delete(path: string): Promise<any> {\n return this.request('DELETE', path);\n }\n\n private async request(method: string, path: string, body?: any): Promise<any> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': USER_AGENT,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errBody = await response.json().catch(() => ({})) as Record<string, any>;\n throw new VorimError(\n response.status,\n errBody.error?.code || 'UNKNOWN_ERROR',\n errBody.error?.message || `HTTP ${response.status}`,\n errBody.error?.details\n );\n }\n\n const json = await response.json() as Record<string, any>;\n return json.data;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private pemToArrayBuffer(pem: string): ArrayBuffer {\n const b64 = pem.replace(/-----[^-]+-----/g, '').replace(/\\s/g, '');\n const binary = atob(b64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n }\n\n private arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n }\n}\n\nexport class VorimError extends Error {\n constructor(\n public status: number,\n public code: string,\n message: string,\n public details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'VorimError';\n }\n}\n\n// ─── Convenience export ──────────────────────────────────────────────\n\nexport default function createVorim(config: VorimConfig): VorimSDK {\n return new VorimSDK(config);\n}\n\n// Re-export types for consumers\nexport type {\n Agent, AgentRegistrationInput, AgentRegistrationResult,\n TrustRecord, AuditEventInput, AuditEventType, AuditResult,\n PermissionScope, PermissionCheckResult, AgentStatus,\n} from './types.js';\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vorim/sdk",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "Official TypeScript SDK for Vorim AI — AI Agent Identity, Permissions & Audit",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -75,7 +75,7 @@
75
75
  ],
76
76
  "scripts": {
77
77
  "build": "tsup",
78
- "prepublishOnly": "npm run build",
78
+ "prepublishOnly": "npm run typecheck && npm run test && npm run build",
79
79
  "typecheck": "tsc --noEmit",
80
80
  "test": "vitest run"
81
81
  },