@auctra/sdk 0.3.5 → 0.6.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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.0
4
+
5
+ **Breaking — Authority Protocol public API (clean break, no legacy aliases)**
6
+
7
+ - Removed public `createDelegation()` and `evaluateAction()`.
8
+ - Canonical surface:
9
+ - `auctra.authority.issue()` / `verify()` / `delegate()` / `revoke()`
10
+ - `auctra.action.evaluate()` (dry-run) / `auctra.action.execute()` (enforce + evidence)
11
+ - `auctra.evidence.verify()`
12
+ - REST: prefer `/v1/authorities` and `/v1/actions/{evaluate,execute}`.
13
+ - `listAuthorities()` / `getAuthority()` replace `listDelegations()` / `getDelegation()`.
14
+
15
+ ## 0.5.0
16
+
17
+ - Introduced Authority Protocol compatibility wrappers (`authority.*`) alongside legacy methods.
18
+
3
19
  ## 0.3.5
4
20
 
5
21
  - Align `AUCTRA_SDK_VERSION` and the `x-auctra-sdk-version` request header with the published package version.
@@ -32,17 +48,14 @@
32
48
 
33
49
  ## 0.3.0
34
50
 
35
- - Extend `evaluateAction` with trust infrastructure fields: `claimedIntentId`, `parentActionId`, `actor`, and `action` (target, description, riskLevel, metadata).
51
+ - Extend action execution with trust infrastructure fields: `claimedIntentId`, `parentActionId`, `actor`, and `action` (target, description, riskLevel, metadata).
36
52
  - Return intelligence metadata on evaluation: authority validity, root intent validity, intent status, trust summary.
37
53
  - Add `listIntents`, `createIntent`, `getIntent`, `getAuthorityGraph`, `getActionEvaluation`, and `getRootIntentChain`.
38
54
 
39
55
  ## 0.2.1
40
56
 
41
57
  - Add complete response types for agents, delegations, action requests, policies, audit events, and API keys.
42
- - Add `getDelegation`, `createPolicy`, and `listApiKeys`.
43
58
  - Honor `Retry-After`, preserve caller cancellation, and validate client options.
44
- - Correct the REST example to use the API's snake_case contract.
45
- - Add package-level integration tests and npm provenance metadata.
46
59
  - Ship tested ESM and CommonJS entry points.
47
60
 
48
61
  ## 0.2.0
package/README.md CHANGED
@@ -2,9 +2,7 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@auctra/sdk.svg)](https://www.npmjs.com/package/@auctra/sdk)
4
4
 
5
- Official TypeScript SDK for [Auctra](https://auctra.tech) — authority infrastructure for AI agents.
6
-
7
- Evaluate every agent action against delegated authority and org policies **before** execution.
5
+ Official TypeScript SDK for [Auctra](https://auctra.tech) — **Authority Protocol** for autonomous actors.
8
6
 
9
7
  | Resource | URL |
10
8
  | -------------------------- | ------------------------------------------------------------- |
@@ -20,11 +18,23 @@ Evaluate every agent action against delegated authority and org policies **befor
20
18
  npm install @auctra/sdk
21
19
  ```
22
20
 
23
- Both ESM (`import`) and CommonJS (`require`) entry points are included.
21
+ ## Canonical API (v0.6+)
22
+
23
+ ```text
24
+ auctra.authority.issue()
25
+ auctra.authority.verify()
26
+ auctra.authority.delegate()
27
+ auctra.authority.revoke()
24
28
 
25
- ## Quick start — evaluateAction
29
+ auctra.action.evaluate() # dry-run Decision
30
+ auctra.action.execute() # enforce + Evidence
31
+
32
+ auctra.evidence.verify()
33
+ ```
26
34
 
27
- Copy-paste this before any consequential agent side effect (payments, refunds, prod changes, CRM writes):
35
+ There is **no** public `createDelegation()` or `evaluateAction()`.
36
+
37
+ ## Quick start
28
38
 
29
39
  ```typescript
30
40
  import { Auctra } from "@auctra/sdk";
@@ -35,129 +45,56 @@ const auctra = new Auctra({
35
45
  maxRetries: 2,
36
46
  });
37
47
 
38
- const decision = await auctra.evaluateAction(
48
+ const agentId = "your-agent-uuid";
49
+ const expiresAt = new Date(Date.now() + 30 * 864e5).toISOString();
50
+
51
+ const { authority } = await auctra.authority.issue({
52
+ subject: agentId,
53
+ capabilities: ["send_payment"],
54
+ constraints: { maxAmount: 1200, currency: "USD" },
55
+ expiresAt,
56
+ });
57
+
58
+ // Dry-run
59
+ await auctra.action.evaluate({
60
+ agentId,
61
+ actionType: "send_payment",
62
+ payload: { amount: 500, currency: "USD" },
63
+ });
64
+
65
+ // Production enforcement path
66
+ const decision = await auctra.action.execute(
39
67
  {
40
- agentId: "your-agent-uuid",
68
+ agentId,
41
69
  actionType: "send_payment",
42
- payload: { amount: 1200, currency: "USD" },
70
+ payload: { amount: 500, currency: "USD" },
43
71
  },
44
72
  { idempotencyKey: crypto.randomUUID() },
45
73
  );
46
74
 
47
75
  if (decision.decision === "allowed") {
48
- // proceed with action
76
+ // proceed
49
77
  } else if (decision.decision === "require_approval") {
50
- // pause for human review in console.auctra.tech/console/reviews
51
78
  console.log(decision.reason, decision.action_request_id);
52
79
  } else {
53
80
  throw new Error(decision.reason);
54
81
  }
55
82
  ```
56
83
 
57
- ### Trust infrastructure (0.3.5+)
58
-
59
- Declare why an action is happening and trace it back to human-approved intent:
84
+ ### Delegate (Child ⊆ Parent)
60
85
 
61
86
  ```typescript
62
- const intent = await auctra.createIntent({
63
- title: "Renew SaaS contracts under $500/month for Q3",
64
- description: "Procurement agent may renew eligible vendor subscriptions.",
87
+ const child = await auctra.authority.delegate({
88
+ parent: authority.id,
89
+ subject: "logistics-agent-uuid",
90
+ capabilities: ["send_payment"],
91
+ constraints: { maxAmount: 300, currency: "USD" },
92
+ expiresAt,
65
93
  });
66
-
67
- const decision = await auctra.evaluateAction({
68
- agentId: "your-agent-uuid",
69
- actionType: "send_payment",
70
- claimedIntentId: intent.intent.id,
71
- intentAnchorToken: intent.intent.anchor_token,
72
- action: {
73
- target: "vendor:slack",
74
- description: "Renew Slack Team plan",
75
- riskLevel: "medium",
76
- },
77
- payload: { amount: 420, currency: "USD" },
78
- });
79
-
80
- console.log(decision.intelligence?.trust_summary);
81
- ```
82
-
83
- ### Production control behavior
84
-
85
- - Anchored intents require the matching `intentAnchorToken`; token possession never bypasses expiry, risk, action-type, target, or resource bounds.
86
- - Count and monetary velocity limits are reserved atomically before a decision. Reuse the same idempotency key for retries of the same business action.
87
- - Custom action types use lowercase namespaced IDs such as `healthcare.ehr.modify_prescription` and recursively validated JSON payload schemas. Breaking schemas should use a new namespaced action ID.
88
- - Proposed policies can be replayed against up to 10,000 recorded actions in the console before publication.
89
- - Restricting an agent quarantines its delegations; reactivation can restore only those quarantined grants. Emergency fleet control is available in the console.
90
-
91
- ## Get an API key
92
-
93
- 1. [Sign up](https://console.auctra.tech/auth/signup) and create an organization
94
- 2. Register an agent and delegate scoped authority
95
- 3. Open [API Keys](https://console.auctra.tech/console/api-keys) → **Create API key**
96
- 4. Use a key with `write` permission for `evaluateAction`
97
-
98
- ## API
99
-
100
- | Method | Description |
101
- | ------------------------------------------- | --------------------------------------------------------------- |
102
- | `evaluateAction(input, options)` | Idempotently check authority + trust trace before an agent acts |
103
- | `listIntents()` | List human-approved intents |
104
- | `createIntent(input)` | Declare a new intent |
105
- | `updateIntent(id, input)` | Update intent metadata or lifecycle status |
106
- | `updateIntentStatus(id, status)` | Change intent lifecycle status |
107
- | `getIntent(id)` | Get intent detail and linked actions |
108
- | `getAuthorityGraph()` | Fetch authority graph nodes and edges |
109
- | `createAuthorityEdge(input)` | Add a validated authority edge |
110
- | `getActionEvaluation(actionRequestId)` | Get decision record for an action |
111
- | `getRootIntentChain(actionRequestId)` | Get root human intent chain (trust trace) |
112
- | `listAgents()` | List registered agents |
113
- | `createAgent(input)` | Register a new agent |
114
- | `updateAgentStatus(id, input)` | Restrict, suspend, reactivate, or mark an agent compromised |
115
- | `deleteAgent(id)` | Remove an agent with no evaluated actions |
116
- | `getAgent(id)` | Get one registered agent |
117
- | `listDelegations()` | List authority delegations |
118
- | `getDelegation(id)` | Get one authority delegation |
119
- | `createDelegation(input)` | Grant bounded authority |
120
- | `revokeDelegation(id)` | Revoke a delegation |
121
- | `listActionRequests()` | List recent evaluations |
122
- | `approveActionRequest(id, approverUserId)` | Approve as an accountable reviewer |
123
- | `rejectActionRequest(id, approverUserId)` | Reject as an accountable reviewer |
124
- | `escalateActionRequest(id, approverUserId)` | Escalate as an accountable reviewer |
125
- | `listPolicies()` | List org policies |
126
- | `createPolicy(input)` | Create an org policy |
127
- | `listAuditEvents()` | List audit ledger events |
128
- | `listApiKeys()` | List API key metadata |
129
-
130
- ## REST API (curl)
131
-
132
- ```bash
133
- curl -X POST https://console.auctra.tech/v1/action-requests/evaluate \
134
- -H "Authorization: Bearer YOUR_API_KEY" \
135
- -H "Idempotency-Key: $(uuidgen)" \
136
- -H "Content-Type: application/json" \
137
- -d '{
138
- "agent_id": "your-agent-uuid",
139
- "action_type": "send_payment",
140
- "payload": { "amount": 100, "currency": "USD" }
141
- }'
142
94
  ```
143
95
 
144
- The SDK applies bounded retries only to reads and idempotent evaluations. API failures throw
145
- `AuctraApiError` with `status`, optional structured `details`, and the server `requestId`.
146
-
147
- The machine-readable OpenAPI 3.1 contract is available at
148
- `https://console.auctra.tech/v1/openapi.json`.
149
-
150
- ## Integration guides (blog)
151
-
152
- Stack-specific walkthroughs with console steps:
153
-
154
- | Stack | Guide |
155
- | ----------------- | ---------------------------------------------------------------- |
156
- | LangChain + MCP | https://auctra.tech/blog/langchain-mcp-authority-integration |
157
- | OpenAI Agents SDK | https://auctra.tech/blog/openai-agents-sdk-authority-integration |
158
- | Vercel AI SDK | https://auctra.tech/blog/vercel-ai-sdk-evaluate-action-hook |
159
- | Stripe payments | https://auctra.tech/blog/stripe-agent-payments-authority-layer |
96
+ Scope escalation is rejected by the protocol/runtime.
160
97
 
161
- ## License
98
+ ## Docs
162
99
 
163
- MIT
100
+ See https://auctra.tech/docs and `docs/AUTHORITY_PROTOCOL_ARCHITECTURE.md`.
package/dist/cjs/index.js CHANGED
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Auctra = exports.AuctraApiError = exports.AUCTRA_SDK_VERSION = void 0;
4
- exports.AUCTRA_SDK_VERSION = "0.3.5";
4
+ exports.verifyMandateArtifact = verifyMandateArtifact;
5
+ exports.verifyDecisionArtifact = verifyDecisionArtifact;
6
+ const node_crypto_1 = require("node:crypto");
7
+ exports.AUCTRA_SDK_VERSION = "0.6.0";
5
8
  class AuctraApiError extends Error {
6
9
  status;
7
10
  code;
@@ -40,6 +43,69 @@ function wait(ms, signal) {
40
43
  }, { once: true });
41
44
  });
42
45
  }
46
+ function canonicalizeJson(value) {
47
+ if (Array.isArray(value))
48
+ return value.map(canonicalizeJson);
49
+ if (value && typeof value === "object" && !(value instanceof Date)) {
50
+ return Object.fromEntries(Object.entries(value)
51
+ .filter(([, child]) => child !== undefined)
52
+ .sort(([left], [right]) => left.localeCompare(right))
53
+ .map(([key, child]) => [key, canonicalizeJson(child)]));
54
+ }
55
+ if (value instanceof Date)
56
+ return value.toISOString();
57
+ return value;
58
+ }
59
+ function hashJson(value) {
60
+ return (0, node_crypto_1.createHash)("sha256")
61
+ .update(JSON.stringify(canonicalizeJson(value)))
62
+ .digest("hex");
63
+ }
64
+ function verifyEd25519(input) {
65
+ if (!input.publicKeyPem)
66
+ return false;
67
+ if (input.signature.alg !== "Ed25519")
68
+ return false;
69
+ return (0, node_crypto_1.verify)(null, Buffer.from(JSON.stringify(canonicalizeJson(input.payload))), typeof input.publicKeyPem === "string"
70
+ ? (0, node_crypto_1.createPublicKey)(input.publicKeyPem)
71
+ : input.publicKeyPem, Buffer.from(input.signature.value, "base64url"));
72
+ }
73
+ function verifyMandateArtifact(input) {
74
+ const expectedHash = hashJson(input.payload);
75
+ if (input.evidence.format !== "auctra-mandate.v0.1") {
76
+ return { valid: false, hashValid: false, signatureValid: false };
77
+ }
78
+ if (!input.evidence.signed) {
79
+ const hashValid = input.evidence.payload_hash === expectedHash;
80
+ return { valid: hashValid, hashValid, signatureValid: false };
81
+ }
82
+ const hashValid = input.evidence.payload_hash === expectedHash;
83
+ const signatureValid = hashValid &&
84
+ verifyEd25519({
85
+ payload: input.payload,
86
+ signature: input.evidence.signature,
87
+ publicKeyPem: input.publicKeyPem,
88
+ });
89
+ return { valid: hashValid && signatureValid, hashValid, signatureValid };
90
+ }
91
+ function verifyDecisionArtifact(input) {
92
+ const expectedHash = hashJson(input.payload);
93
+ if (input.evidence.format !== "auctra-evidence.v0.1") {
94
+ return { valid: false, hashValid: false, signatureValid: false };
95
+ }
96
+ if (!input.evidence.signed) {
97
+ const hashValid = input.evidence.payload_hash === expectedHash;
98
+ return { valid: hashValid, hashValid, signatureValid: false };
99
+ }
100
+ const hashValid = input.evidence.payload_hash === expectedHash;
101
+ const signatureValid = hashValid &&
102
+ verifyEd25519({
103
+ payload: input.payload,
104
+ signature: input.evidence.signature,
105
+ publicKeyPem: input.publicKeyPem,
106
+ });
107
+ return { valid: hashValid && signatureValid, hashValid, signatureValid };
108
+ }
43
109
  class Auctra {
44
110
  apiKey;
45
111
  baseUrl;
@@ -115,15 +181,17 @@ class Auctra {
115
181
  }
116
182
  throw lastError;
117
183
  }
118
- async evaluateAction(input, options = {}) {
119
- const idempotencyKey = options.idempotencyKey ?? crypto.randomUUID();
120
- return this.request("POST", "/v1/action-requests/evaluate", {
184
+ async executeOrEvaluateAction(input, options, mode) {
185
+ const idempotencyKey = mode === "execute" ? (options.idempotencyKey ?? crypto.randomUUID()) : options.idempotencyKey;
186
+ const path = mode === "execute" ? "/v1/actions/execute" : "/v1/actions/evaluate";
187
+ return this.request("POST", path, {
121
188
  agent_id: input.agentId,
122
189
  action_type: input.actionType,
123
190
  payload: input.payload ?? {},
124
191
  claimed_intent_id: input.claimedIntentId,
125
192
  intent_anchor_token: input.intentAnchorToken,
126
193
  parent_action_id: input.parentActionId,
194
+ dry_run: mode === "evaluate",
127
195
  actor: input.actor
128
196
  ? {
129
197
  id: input.actor.id,
@@ -139,7 +207,82 @@ class Auctra {
139
207
  metadata: input.action.metadata,
140
208
  }
141
209
  : undefined,
142
- }, { ...options, idempotencyKey });
210
+ }, mode === "execute" ? { ...options, idempotencyKey } : options);
211
+ }
212
+ async issueAuthorityRequest(input) {
213
+ const response = await this.request("POST", "/v1/authorities", {
214
+ agent_id: input.subject,
215
+ action_types: input.capabilities,
216
+ valid_until: input.expiresAt,
217
+ max_amount: input.constraints?.maxAmount,
218
+ max_count: input.constraints?.maxCount,
219
+ environment: input.constraints?.environment,
220
+ currency: input.constraints?.currency,
221
+ delegator_user_id: input.delegatorUserId ?? input.issuer,
222
+ parent_authority_id: input.parentAuthorityId,
223
+ max_delegation_depth: input.delegation?.maxDepth,
224
+ max_actions_per_window: input.maxActionsPerWindow
225
+ ? {
226
+ count: input.maxActionsPerWindow.count,
227
+ window_seconds: input.maxActionsPerWindow.windowSeconds,
228
+ action_type: input.maxActionsPerWindow.actionType,
229
+ }
230
+ : undefined,
231
+ max_amount_per_window: input.maxAmountPerWindow
232
+ ? {
233
+ amount: input.maxAmountPerWindow.amount,
234
+ window_seconds: input.maxAmountPerWindow.windowSeconds,
235
+ }
236
+ : undefined,
237
+ });
238
+ const authorityId = response.authority_id ?? response.delegation.id;
239
+ const authority = response.authority ?? {
240
+ id: authorityId,
241
+ protocol_version: "0.1",
242
+ status: response.delegation.status,
243
+ payload_hash: "",
244
+ signed: false,
245
+ parent_authority_id: input.parentAuthorityId ?? null,
246
+ capabilities: input.capabilities,
247
+ };
248
+ return {
249
+ authority,
250
+ authority_id: authorityId,
251
+ delegation: response.delegation,
252
+ };
253
+ }
254
+ /**
255
+ * Authority Protocol — issue, verify, delegate (subset), revoke.
256
+ * There is no legacy createDelegation() surface.
257
+ */
258
+ get authority() {
259
+ return {
260
+ issue: (input) => this.issueAuthorityRequest(input),
261
+ verify: (payload, artifact) => this.request("POST", "/v1/authorities/verify", { payload, artifact }),
262
+ delegate: (input) => this.issueAuthorityRequest({
263
+ ...input,
264
+ parentAuthorityId: input.parent,
265
+ }),
266
+ revoke: (authorityId) => this.request("POST", `/v1/authorities/${encodeURIComponent(authorityId)}/revoke`, {}),
267
+ };
268
+ }
269
+ /**
270
+ * Action Protocol — evaluate (dry-run) vs execute (enforce + evidence).
271
+ * There is no legacy evaluateAction() surface.
272
+ */
273
+ get action() {
274
+ return {
275
+ evaluate: (input, options = {}) => this.executeOrEvaluateAction(input, options, "evaluate"),
276
+ execute: (input, options = {}) => this.executeOrEvaluateAction(input, options, "execute"),
277
+ };
278
+ }
279
+ get evidence() {
280
+ return {
281
+ verify: (payload, evidence) => this.request("POST", "/v1/evidence/verify", { payload, evidence }),
282
+ };
283
+ }
284
+ async verifyMandate(payload, evidence) {
285
+ return this.request("POST", "/v1/mandates/verify", { payload, evidence });
143
286
  }
144
287
  async listIntents() {
145
288
  return this.request("GET", "/v1/intents");
@@ -223,39 +366,11 @@ class Auctra {
223
366
  async deleteAgent(agentId) {
224
367
  return this.request("DELETE", `/v1/agents/${encodeURIComponent(agentId)}`);
225
368
  }
226
- async listDelegations() {
227
- return this.request("GET", "/v1/delegations");
369
+ async listAuthorities() {
370
+ return this.request("GET", "/v1/authorities");
228
371
  }
229
- async getDelegation(delegationId) {
230
- return this.request("GET", `/v1/delegations/${encodeURIComponent(delegationId)}`);
231
- }
232
- async createDelegation(input) {
233
- return this.request("POST", "/v1/delegations", {
234
- agent_id: input.agentId,
235
- action_types: input.actionTypes,
236
- valid_until: input.validUntil,
237
- max_amount: input.maxAmount,
238
- max_count: input.maxCount,
239
- environment: input.environment,
240
- currency: input.currency,
241
- delegator_user_id: input.delegatorUserId,
242
- max_actions_per_window: input.maxActionsPerWindow
243
- ? {
244
- count: input.maxActionsPerWindow.count,
245
- window_seconds: input.maxActionsPerWindow.windowSeconds,
246
- action_type: input.maxActionsPerWindow.actionType,
247
- }
248
- : undefined,
249
- max_amount_per_window: input.maxAmountPerWindow
250
- ? {
251
- amount: input.maxAmountPerWindow.amount,
252
- window_seconds: input.maxAmountPerWindow.windowSeconds,
253
- }
254
- : undefined,
255
- });
256
- }
257
- async revokeDelegation(delegationId) {
258
- return this.request("POST", `/v1/delegations/${encodeURIComponent(delegationId)}/revoke`, {});
372
+ async getAuthority(authorityId) {
373
+ return this.request("GET", `/v1/authorities/${encodeURIComponent(authorityId)}`);
259
374
  }
260
375
  async listActionRequests() {
261
376
  return this.request("GET", "/v1/action-requests");
@@ -329,6 +444,12 @@ class Auctra {
329
444
  async listAuditEvents() {
330
445
  return this.request("GET", "/v1/audit-events");
331
446
  }
447
+ async getAuditEvent(auditEventId) {
448
+ return this.request("GET", `/v1/audit-events/${encodeURIComponent(auditEventId)}`);
449
+ }
450
+ async verifyAuditChain() {
451
+ return this.request("GET", "/v1/audit-events/verify");
452
+ }
332
453
  async listApiKeys() {
333
454
  return this.request("GET", "/v1/api-keys");
334
455
  }