@decidio/sdk 0.6.3 → 0.7.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/openapi.yaml CHANGED
@@ -5,7 +5,7 @@
5
5
  openapi: 3.1.0
6
6
  info:
7
7
  title: Decidio Agent Gate
8
- version: 0.6.3 # tracks the SDK release - checked by packages/conformance/manifests.mjs
8
+ version: 0.7.0 # tracks the SDK release - checked by packages/conformance/manifests.mjs
9
9
  description: >
10
10
  Authorize an AI-agent action (proceed | route | block), confirm the captured outcome, and
11
11
  receive the signed resume webhook when a routed action is decided. Every outcome seals a
@@ -65,7 +65,28 @@ components:
65
65
  resumeUrl:
66
66
  type: string
67
67
  format: uri
68
- description: where Decidio POSTs the signed verdict when a routed decision resolves
68
+ description: where Decidio POSTs the signed wake-up when a routed decision resolves
69
+ requestCommitment:
70
+ type: string
71
+ pattern: "^[0-9a-f]{64}$"
72
+ description: >
73
+ REQUEST BINDING (SDK 0.7.0). An OPAQUE commitment to the exact request the agent will run:
74
+ lowercase-hex HMAC-SHA256 under a key only the agent holds (its Ed25519 signing key, else its
75
+ API token) over the canonical request. Stored with the decision and returned by
76
+ GET /agent/status; the SDK recomputes it over the request it is about to run and refuses a
77
+ mismatch. Carries no authority - the verdict is computed exactly as without it. Anything that
78
+ is not 64 lowercase hex is a 400.
79
+ idempotencyKey:
80
+ type: string
81
+ pattern: "^[A-Za-z0-9._:-]{16,128}$"
82
+ description: >
83
+ SDK 0.7.0. The same key from the same requester returns the SAME decision (idempotentReplay:
84
+ true) instead of a new one - an engine that re-runs its authorizing code on resume (LangGraph)
85
+ must not mint a phantom second decision. Accepted ONLY beside a requestCommitment (a key alone is
86
+ 400). Stored only as a requester-scoped HMAC. A replay must be the same request twice over - the
87
+ same requestCommitment AND the same requester, action, amount and scope (the server binds that
88
+ tuple itself) - otherwise 409 IDEMPOTENCY_CONFLICT; an earlier decision is never handed back for a
89
+ changed request.
69
90
  AuthorizeResponse:
70
91
  type: object
71
92
  required: [decision, decisionId, receiptId]
@@ -79,6 +100,17 @@ components:
79
100
  decisionId: { type: string }
80
101
  receiptId: { type: string }
81
102
  reason: { type: string }
103
+ requestCommitment:
104
+ type: [string, "null"]
105
+ description: the commitment stored with the decision (SDK 0.7.0), null when none was sent
106
+ idempotentReplay:
107
+ type: boolean
108
+ description: >
109
+ present (true) when this answer is an idempotent replay of an existing decision: nothing was
110
+ evaluated, created, sealed or summoned again (one `agent.authorize.replayed` audit row is written),
111
+ and `receipt` carries only the fields fixed at create. A sealed auto-approval replays as `proceed`
112
+ only when THIS call could itself auto-approve (a verified, replay-protected identity or a trusted
113
+ transport); anything else answers `route` or `block` - ask GET /agent/status for the real state.
82
114
  StatusResponse:
83
115
  type: object
84
116
  required: [state]
@@ -87,6 +119,13 @@ components:
87
119
  type: string
88
120
  enum: [pending, approved, auto_approved, rejected, blocked]
89
121
  reason: { type: string }
122
+ requestCommitment:
123
+ type: [string, "null"]
124
+ description: >
125
+ SDK 0.7.0: the request commitment the decision was authorized with (null when none was
126
+ sent). The SDK treats an approval as covering the request it is about to run only when this
127
+ equals its own recompute; a gate that returns no commitment for a request the SDK bound is
128
+ refused (commitment_missing), never trusted.
90
129
  ConfirmRequest:
91
130
  type: object
92
131
  required: [decisionId, capturedResponse, source]
@@ -163,10 +202,13 @@ components:
163
202
  properties:
164
203
  status:
165
204
  type: string
166
- enum: [executed, indeterminate, rejected, blocked, no_handler, unknown]
205
+ enum: [executed, indeterminate, rejected, blocked, no_handler, unknown, not_approved, request_unverified]
167
206
  description: >
168
207
  the LOCAL run. `indeterminate` means the handler was invoked and its outcome is
169
- unknown — it will NOT be retried automatically and needs reconcile().
208
+ unknown — it will NOT be retried automatically and needs reconcile(). Since SDK 0.7.0 the
209
+ webhook is a wake-up: `not_approved` = Decidio does not (yet) record an approval, so nothing
210
+ ran and the entry stays parked; `request_unverified` = the approval could not be tied to the
211
+ parked request (a different request, or no commitment from the gate), so nothing ran.
170
212
  decisionId: { type: string }
171
213
  reportRecorded: { type: boolean, description: "Decidio accepted the execution report." }
172
214
  executionConfirmed: { type: boolean, description: "the recorded tier attests a COMMITTED execution — a different question from reportRecorded." }
@@ -214,7 +256,11 @@ components:
214
256
  description: >
215
257
  OUTBOUND — Decidio → your resumeUrl when a routed decision is decided. The raw body is
216
258
  HMAC-signed; verify `x-decidio-signature: sha256=<hex>` with your DECIDIO_WEBHOOK_SECRET
217
- BEFORE acting (the SDK resume controllers fail closed). A duplicate delivery cannot cause a
259
+ BEFORE acting (the SDK resume controllers fail closed; since SDK 0.7.0 there is no fallback to
260
+ the API token - no secret means 401). The server signs with DECIDIO_WEBHOOK_SECRET only and sends
261
+ no webhook without it; it is a dedicated secret - never the server's API_AUTH_TOKEN. It is a WAKE-UP, never the authority: since SDK 0.7.0 the
262
+ SDK reads only `decisionId`, then asks GET /agent/status and runs the parked action only when
263
+ Decidio records it approved for THIS request (the request commitment). A duplicate delivery cannot cause a
218
264
  second execution: the SDK writes a durable invoking marker before calling the handler,
219
265
  so once invocation may have begun it is never invoked again automatically.
220
266
  OPERATOR DEPLOYMENTS ONLY: signing uses a shared secret configured on both the Decidio
@@ -245,7 +291,20 @@ paths:
245
291
  content:
246
292
  application/json:
247
293
  schema: { $ref: "#/components/schemas/AuthorizeResponse" }
294
+ "400": { description: "a malformed field, including a requestCommitment or idempotencyKey outside its grammar, or an idempotencyKey without a requestCommitment" }
248
295
  "401": { description: missing/invalid agent token }
296
+ "409":
297
+ description: >
298
+ IDEMPOTENCY_CONFLICT (SDK 0.7.0) - this idempotencyKey already names a decision for a
299
+ DIFFERENT request (its requestCommitment, or its requester, action, amount or scope, differs).
300
+ Send a new key for the new request.
301
+ content:
302
+ application/json:
303
+ schema:
304
+ type: object
305
+ properties:
306
+ code: { type: string, enum: [IDEMPOTENCY_CONFLICT] }
307
+ message: { type: string }
249
308
  /agent/status/{decisionId}:
250
309
  get:
251
310
  summary: Poll a routed decision (blocking mode / durable worker)
@@ -328,7 +387,7 @@ paths:
328
387
  x-webhooks:
329
388
  resume:
330
389
  post:
331
- summary: Signed verdict delivery (Decidio → agent resumeUrl)
390
+ summary: Signed wake-up delivery (Decidio → agent resumeUrl); the SDK confirms the approval with GET /agent/status before acting
332
391
  requestBody:
333
392
  content:
334
393
  application/json:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decidio/sdk",
3
- "version": "0.6.3",
3
+ "version": "0.7.0",
4
4
  "description": "One-line approval gate for AI-agent actions. Wrap a risky tool call with guard.protect(); Decidio's policy engine decides proceed | route | block, a human approves routed actions, and every outcome is sealed as a verifiable Authority Receipt.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -84,7 +84,7 @@
84
84
  "prepublishOnly": "npm run typecheck && npm run build && node ../publish-boundary/check.mjs --only @decidio/sdk"
85
85
  },
86
86
  "dependencies": {
87
- "@decidio/verify": "0.6.3"
87
+ "@decidio/verify": "0.7.0"
88
88
  },
89
89
  "author": "OmniTwin Technologies Inc.",
90
90
  "bugs": {