@intentproof/sdk 0.1.1 → 0.1.3
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 +121 -79
- package/dist/index.cjs +417 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +305 -24
- package/dist/index.d.ts +305 -24
- package/dist/index.js +402 -28
- package/dist/index.js.map +1 -1
- package/package.json +25 -14
package/README.md
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
## **Logs narrate; IntentProof gives you proof.**
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**IntentProof** is **auditable execution records** for actions that must be defensible—**intent** tied to what actually ran.
|
|
4
|
+
|
|
5
|
+
**Wrap** the calls that matter; each invocation emits one **verifiable** **`ExecutionEvent`**, structured so intent and outcome can be **reconciled** with reality—not only observed.
|
|
6
|
+
|
|
4
7
|
Observability captures what happened. **IntentProof** tells you whether it matched what was **meant to happen**.
|
|
5
8
|
|
|
6
|
-
Every
|
|
9
|
+
Every **`ExecutionEvent`** contains:
|
|
7
10
|
|
|
8
11
|
- **`intent`**: what this invocation was meant to prove
|
|
9
12
|
- **`action`**: the stable operation id for this step
|
|
@@ -26,14 +29,27 @@ They don't tell you:
|
|
|
26
29
|
|
|
27
30
|
It records intent alongside execution so systems can be verified, not just observed.
|
|
28
31
|
|
|
32
|
+
### Picture this:
|
|
33
|
+
|
|
34
|
+
It's 4:47 on a Friday. A customer insists the critical action never happened. Support sees scattered traces; engineering sees green checks; finance asks for **one** clean chain: what was **supposed** to occur, what **did** occur, and whether the outcome is **complete**.
|
|
35
|
+
|
|
36
|
+
Ordinary telemetry shows that *something ran*. It rarely ships an **auditable story** you can hand to someone who doesn't read your codebase. **IntentProof** exists for when the question stops being "what was logged?" and starts being **"prove it."**
|
|
37
|
+
|
|
29
38
|
## Requirements
|
|
30
39
|
|
|
31
40
|
- **Node.js** 22 or newer
|
|
32
41
|
|
|
33
42
|
## Install
|
|
34
43
|
|
|
44
|
+
**Package:** `@intentproof/sdk`.
|
|
45
|
+
|
|
46
|
+
- [npm — `@intentproof/sdk`](https://www.npmjs.com/package/@intentproof/sdk)
|
|
47
|
+
- [GitHub Releases — IntentProof Node SDK](https://github.com/IntentProof/intentproof-sdk-node/releases)
|
|
48
|
+
|
|
49
|
+
Pin the **version** you want from npm or from GitHub Releases. Replace **`x.y.z`** below with that version.
|
|
50
|
+
|
|
35
51
|
```bash
|
|
36
|
-
npm install @intentproof/sdk
|
|
52
|
+
npm install @intentproof/sdk@x.y.z
|
|
37
53
|
```
|
|
38
54
|
|
|
39
55
|
## Quick start
|
|
@@ -49,80 +65,81 @@ const refund = client.wrap(
|
|
|
49
65
|
|
|
50
66
|
Each refund call emits one **`ExecutionEvent`** with the **`intent`** and **`action`** you chose, the **`inputs`** and **`output`** (or **`error`** + **`status: "error"`**), and timing fields—an execution record you can inspect, export, or verify later.
|
|
51
67
|
|
|
52
|
-
##
|
|
68
|
+
## Reference
|
|
53
69
|
|
|
70
|
+
Detailed tables for the client API, emitted events, configuration, and related exports.
|
|
54
71
|
|
|
55
|
-
|
|
56
|
-
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
57
|
-
| **`constructor(config?)`** | Creates a client. Default exporters: a single **`MemoryExporter`** if you omit **`config.exporters`**. |
|
|
58
|
-
| **`configure(config)`** | Re-applies **`IntentProofConfig`** fields (exporters, error hook, defaults, stack policy). |
|
|
59
|
-
| **`wrap(options, fn)`** | Returns a function that records one **`ExecutionEvent`** per call (sync or async). **`options`** must satisfy **`assertWrapOptionsShape`** (`intent` / `action` non-empty strings, etc.). |
|
|
60
|
-
| **`flush()`** | Awaits **`flush()`** on every **`Exporter`** that implements it, in parallel. |
|
|
61
|
-
| **`shutdown()`** | For each **`Exporter`**, awaits **`shutdown()`** if implemented, otherwise **`flush()`** if implemented. |
|
|
62
|
-
| **`getCorrelationId()`** | Returns the correlation ID from **`AsyncLocalStorage`**, if any. |
|
|
63
|
-
| **`withCorrelation(fn)`** | Runs **`fn`** with a **fresh UUID** as correlation ID for nested wraps. |
|
|
64
|
-
| **`withCorrelation(id, fn)`** | Runs **`fn`** with **`id`** trimmed; blank / whitespace-only **`id`** falls back to a UUID. |
|
|
72
|
+
### `IntentProofClient` API
|
|
65
73
|
|
|
74
|
+
| Member | Description |
|
|
75
|
+
| ------ | ----------- |
|
|
76
|
+
| **`constructor(config?)`** | Creates a client. Default exporters: a single **`MemoryExporter`** if you omit **`config.exporters`**. |
|
|
77
|
+
| **`configure(config)`** | Re-applies **`IntentProofConfig`** fields (exporters, error hook, defaults, stack policy). |
|
|
78
|
+
| **`wrap(options, fn)`** | Returns a function that records one **`ExecutionEvent`** per call (sync or async). **`options`** must satisfy **`assertWrapOptionsShape`** (`intent` / `action` non-empty strings, etc.). |
|
|
79
|
+
| **`flush()`** | Awaits **`flush()`** on every **`Exporter`** that implements it, in parallel. |
|
|
80
|
+
| **`shutdown()`** | For each **`Exporter`**, awaits **`shutdown()`** if implemented, otherwise **`flush()`** if implemented. |
|
|
81
|
+
| **`getCorrelationId()`** | Returns the correlation ID from **`AsyncLocalStorage`**, if any. |
|
|
82
|
+
| **`withCorrelation(fn)`** | Runs **`fn`** with a **fresh UUID** as correlation ID for nested wraps. |
|
|
83
|
+
| **`withCorrelation(id, fn)`** | Runs **`fn`** with **`id`** trimmed; blank / whitespace-only **`id`** falls back to a UUID. |
|
|
66
84
|
|
|
67
|
-
|
|
85
|
+
#### Module-level helpers (same module as the client)
|
|
68
86
|
|
|
69
87
|
These use the same async correlation store as **`IntentProofClient`** instances:
|
|
70
88
|
|
|
89
|
+
| Export | Description |
|
|
90
|
+
| ------ | ----------- |
|
|
91
|
+
| **`createIntentProofClient(config?)`** | New isolated client (tests, workers, multi-tenant). |
|
|
92
|
+
| **`getIntentProofClient()`** | Lazy singleton used by **`client`**. |
|
|
93
|
+
| **`client`** | Default singleton instance. |
|
|
94
|
+
| **`getCorrelationId()`** | Same behavior as the instance method. |
|
|
95
|
+
| **`runWithCorrelationId(id, fn)`** | Requires a **non-empty** correlation ID after trim; throws if invalid. |
|
|
96
|
+
| **`assertCorrelationId(id)`** | Runtime assertion for correlation ID shape. |
|
|
97
|
+
| **`assertWrapOptionsShape(options)`** | Runtime validation for **`WrapOptions`**. |
|
|
98
|
+
|
|
99
|
+
### `ExecutionEvent` fields
|
|
100
|
+
|
|
101
|
+
| Field | Description |
|
|
102
|
+
| ----- | ----------- |
|
|
103
|
+
| **`id`** | Unique event id (UUID). |
|
|
104
|
+
| **`correlationId`** | Request or trace correlation ID when present—usually from context or **`WrapOptions`**. |
|
|
105
|
+
| **`intent`** | Human-readable label for what this invocation is meant to prove (outcome, policy goal, or domain). |
|
|
106
|
+
| **`action`** | Stable operation id for this step (often dotted or namespaced). |
|
|
107
|
+
| **`inputs`** | JSON-safe snapshot of call arguments (default) or **`captureInput`** result. |
|
|
108
|
+
| **`output`** | JSON-safe return value or **`captureOutput`** result on success. When **`status`** is **`"error"`**, set only if **`captureError`** returned a value. |
|
|
109
|
+
| **`error`** | On failure: **`name`**, **`message`**, and optional **`stack`** (see **`includeErrorStack`**). |
|
|
110
|
+
| **`status`** | **`"ok"`** if the wrapped call completed normally; **`"error"`** if it threw. |
|
|
111
|
+
| **`startedAt`** | Start time (ISO 8601). |
|
|
112
|
+
| **`completedAt`** | Completion time (ISO 8601). |
|
|
113
|
+
| **`durationMs`** | Wall time between start and completion, in milliseconds. |
|
|
114
|
+
| **`attributes`** | Optional plain record (string / number / boolean values only), merged from client defaults and wrap options. |
|
|
115
|
+
|
|
116
|
+
### `WrapOptions` and `IntentProofConfig`
|
|
117
|
+
|
|
118
|
+
#### `WrapOptions` (passed to **`wrap`**)
|
|
119
|
+
|
|
120
|
+
| Field | Description |
|
|
121
|
+
| ----- | ----------- |
|
|
122
|
+
| **`intent`**, **`action`** | Required, non-empty after trim. |
|
|
123
|
+
| **`correlationId`** | Optional; when set, non-empty after trim. Otherwise the active correlation ID from context is used, if any. |
|
|
124
|
+
| **`attributes`** | Per-invocation dimensions merged over **`defaultAttributes`**. |
|
|
125
|
+
| **`captureInput`**, **`captureOutput`**, **`captureError`** | Optional hooks to replace default **`snapshot`** behavior for inputs, success output, or error-side extra **`output`**. |
|
|
126
|
+
| **`includeErrorStack`** | When `false`, omit **`error.stack`** for this wrap (overrides client default). |
|
|
127
|
+
| **`maxDepth`**, **`maxKeys`**, **`redactKeys`**, **`maxStringLength`** | Forwarded to **`snapshot`** for inputs and outputs (see **`SerializeOptions`** in types). |
|
|
128
|
+
|
|
129
|
+
#### `IntentProofConfig` (constructor / **`configure`**)
|
|
130
|
+
|
|
131
|
+
| Field | Description |
|
|
132
|
+
| ----- | ----------- |
|
|
133
|
+
| **`exporters`** | Ordered list of **`Exporter`** instances; each receives every **`ExecutionEvent`**. |
|
|
134
|
+
| **`onExporterError`** | Called when any exporter’s **`export()`** throws or returns a rejected promise. Defaults to **`console.error`**. |
|
|
135
|
+
| **`defaultAttributes`** | Merged into every event’s **`attributes`** (wrap-specific attributes win on key collision). |
|
|
136
|
+
| **`includeErrorStack`** | Default `true`; set `false` in production if stacks must not leave the trust zone. |
|
|
137
|
+
|
|
138
|
+
### Related exports
|
|
71
139
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
| **`getIntentProofClient()`** | Lazy singleton used by **`client`**. |
|
|
76
|
-
| **`client`** | Default singleton instance. |
|
|
77
|
-
| **`getCorrelationId()`** | Same behavior as the instance method. |
|
|
78
|
-
| **`runWithCorrelationId(id, fn)`** | Requires a **non-empty** correlation ID after trim; throws if invalid. |
|
|
79
|
-
| **`assertCorrelationId(id)`** | Runtime assertion for correlation ID shape. |
|
|
80
|
-
| **`assertWrapOptionsShape(options)`** | Runtime validation for **`WrapOptions`**. |
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
## `ExecutionEvent` fields
|
|
84
|
-
|
|
85
|
-
| Field | Description |
|
|
86
|
-
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
87
|
-
| **`id`** | Unique event id (UUID). |
|
|
88
|
-
| **`correlationId`** | Request or trace correlation ID when present—usually from context or **`WrapOptions`**. |
|
|
89
|
-
| **`intent`** | Human-readable label for what this invocation is meant to prove (outcome, policy goal, or domain). |
|
|
90
|
-
| **`action`** | Stable operation id for this step (often dotted or namespaced). |
|
|
91
|
-
| **`inputs`** | JSON-safe snapshot of call arguments (default) or **`captureInput`** result. |
|
|
92
|
-
| **`output`** | JSON-safe return value or **`captureOutput`** result on success. When **`status`** is **`"error"`**, set only if **`captureError`** returned a value. |
|
|
93
|
-
| **`error`** | On failure: **`name`**, **`message`**, and optional **`stack`** (see **`includeErrorStack`**). |
|
|
94
|
-
| **`status`** | **`"ok"`** if the wrapped call completed normally; **`"error"`** if it threw. |
|
|
95
|
-
| **`startedAt`** | Start time (ISO 8601). |
|
|
96
|
-
| **`completedAt`** | Completion time (ISO 8601). |
|
|
97
|
-
| **`durationMs`** | Wall time between start and completion, in milliseconds. |
|
|
98
|
-
| **`attributes`** | Optional plain record (string / number / boolean values only), merged from client defaults and wrap options. |
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
## `WrapOptions` and `IntentProofConfig`
|
|
102
|
-
|
|
103
|
-
### `WrapOptions` (passed to **`wrap`**)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
| Field | Description |
|
|
107
|
-
| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
108
|
-
| **`intent`**, **`action`** | Required, non-empty after trim. |
|
|
109
|
-
| **`correlationId`** | Optional; when set, non-empty after trim. Otherwise the active correlation ID from context is used, if any. |
|
|
110
|
-
| **`attributes`** | Per-invocation dimensions merged over **`defaultAttributes`**. |
|
|
111
|
-
| **`captureInput`**, **`captureOutput`**, **`captureError`** | Optional hooks to replace default **`snapshot`** behavior for inputs, success output, or error-side extra **`output`**. |
|
|
112
|
-
| **`includeErrorStack`** | When `false`, omit **`error.stack`** for this wrap (overrides client default). |
|
|
113
|
-
| **`maxDepth`**, **`maxKeys`**, **`redactKeys`**, **`maxStringLength`** | Forwarded to **`snapshot`** for inputs and outputs (see **`SerializeOptions`** in types). |
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
### `IntentProofConfig` (constructor / **`configure`**)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
| Field | Description |
|
|
120
|
-
| ----------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
121
|
-
| **`exporters`** | Ordered list of **`Exporter`** instances; each receives every **`ExecutionEvent`**. |
|
|
122
|
-
| **`onExporterError`** | Called when any exporter’s **`export()`** throws or returns a rejected promise. Defaults to **`console.error`**. |
|
|
123
|
-
| **`defaultAttributes`** | Merged into every event’s **`attributes`** (wrap-specific attributes win on key collision). |
|
|
124
|
-
| **`includeErrorStack`** | Default `true`; set `false` in production if stacks must not leave the trust zone. |
|
|
125
|
-
|
|
140
|
+
- **`MemoryExporter`**, **`HttpExporter`**, **`BoundedQueueExporter`** — Delivery implementations; each implements **`Exporter`**.
|
|
141
|
+
- **`snapshot`** — Same JSON-safe serializer the client uses internally, if you build custom tooling.
|
|
142
|
+
- **`VERSION`** — Package version string injected at build time.
|
|
126
143
|
|
|
127
144
|
---
|
|
128
145
|
|
|
@@ -134,6 +151,8 @@ Support approves **order `ORD-1042`**. Your service creates the **Stripe refund*
|
|
|
134
151
|
|
|
135
152
|
**`captureInput`** / **`captureOutput`** trim each record to the fields you want in proof (refund id, amounts, message id)—not full vendor payloads.
|
|
136
153
|
|
|
154
|
+
JSON on the wire uses **camelCase**; TypeScript **`WrapOptions`** use the same camelCase names (e.g. **`captureInput`**).
|
|
155
|
+
|
|
137
156
|
```ts
|
|
138
157
|
const createRefund = client.wrap(
|
|
139
158
|
{
|
|
@@ -320,7 +339,7 @@ try {
|
|
|
320
339
|
|
|
321
340
|
### 3 — Proof delivery over HTTP (same **`ExecutionEvent`** shape)
|
|
322
341
|
|
|
323
|
-
**`HttpExporter`** POSTs the same **`ExecutionEvent`** your verifiers see in memory—here alongside **`MemoryExporter`** so tests can assert the wire without a real collector. The request
|
|
342
|
+
**`HttpExporter`** POSTs the same **`ExecutionEvent`** your verifiers see in memory—here alongside **`MemoryExporter`** so tests can assert the wire without a real collector. The request omits ambient credentials; the body is **`{ "intentproof": "1", "event": … }`** (see exporter implementation). For authenticated collectors, pass **`headers`** (e.g. **`Authorization`**, API keys) — see [Security](#security).
|
|
324
343
|
|
|
325
344
|
```ts
|
|
326
345
|
const runProbe = client.wrap({ intent: "HTTP test", action: "test.http" }, () => 42);
|
|
@@ -341,30 +360,53 @@ runProbe();
|
|
|
341
360
|
|
|
342
361
|
## Security
|
|
343
362
|
|
|
363
|
+
For **vulnerability reporting**, use this repository’s [**Security**](https://github.com/IntentProof/intentproof-sdk-node/security) tab (private advisories).
|
|
364
|
+
|
|
344
365
|
Every **`ExecutionEvent`** you emit is data you may ship off-process. Treat them like audit-grade execution records: they can include PII, secrets, stack traces, and business identifiers depending on your **`snapshot`** / **`capture*`** hooks.
|
|
345
366
|
|
|
346
367
|
- **Minimize payload:** Use **`redactKeys`**, **`maxDepth`** / **`maxKeys`** / **`maxStringLength`**, and narrow **`captureInput`** / **`captureOutput`** / **`captureError`** so proof records contain only what verifiers need.
|
|
347
368
|
- **Stacks:** Set **`includeErrorStack: false`** on the client (or per wrap) when traces must not leave your trust zone.
|
|
348
369
|
- **HTTP ingest:** Keep collector **`url`** and any redirect behavior under **trusted configuration** (avoid SSRF if URLs were ever influenced by untrusted input). Prefer **HTTPS** and **short-lived credentials** end-to-end.
|
|
349
370
|
- **`HttpExporter` auth:** Pass credentials in **`headers`** (for example **`Authorization: Bearer …`**, **`x-api-key`**, or whatever your collector expects). The SDK does **not** log header values; use short-lived tokens and scope them to ingest only.
|
|
350
|
-
- **
|
|
371
|
+
- **Runtime surface:** This package targets **Node**; if you wrap code in a browser, treat the ingest endpoint and headers as you would any cross-origin credential (CORS, CSP, token storage policies are your app’s responsibility).
|
|
351
372
|
- **Delivery semantics:** Exporter failures invoke **`onExporterError`** and do **not** roll back the wrapped function’s side effects—design compensating controls if you need strict “delivered exactly once” guarantees.
|
|
352
373
|
|
|
353
374
|
Custom **`body`** serializers: if **`body(event)`** throws, **`HttpExporter`** notifies **`onError`** and falls back to the same **JSON envelope** path as the default serializer (full event, then a partial envelope, then a minimal `eventSerializeFailed` payload) so **`export()`** still completes and **`fetch`** runs when possible.
|
|
354
375
|
|
|
355
376
|
---
|
|
356
377
|
|
|
357
|
-
##
|
|
378
|
+
## Canonical specification (`intentproof-spec`)
|
|
358
379
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
380
|
+
**Shared pins and terminology** (`INTENTPROOF_SPEC_ROOT`, **`intentproofSpecCommit`**, script names): **[`intentproof-spec` CONTRIBUTING — Terminology](https://github.com/IntentProof/intentproof-spec/blob/main/CONTRIBUTING.md#terminology-shared-with-sdk-repos)**.
|
|
381
|
+
|
|
382
|
+
Schemas, golden oracles, and the **Vitest conformance oracle** live in the **[IntentProof specification repository (`intentproof-spec`)](https://github.com/IntentProof/intentproof-spec)**.
|
|
383
|
+
|
|
384
|
+
- **Version pin:** **`intentproofSpecVersion`** and **`intentproofSpecCommit`** in the root **`package.json`** and **`packages/sdk/package.json`** match **`spec.json`** and the spec **`HEAD`** checkout; **`scripts/check-sdk-spec-pin.sh`** enforces this before conformance.
|
|
385
|
+
|
|
386
|
+
- **CI:** every push/PR checks out this SDK plus **`intentproof-spec`** and runs **`scripts/spec-conformance.sh`** (pin check + full oracle; see `.github/workflows/ci.yml`). The **`sdk`** job sets **`INTENTPROOF_SPEC_ROOT`** so **`packages/sdk`** Vitest also imports the spec **`sdk_test_harness`**—golden **`execution_event_cases.jsonl`** oracle plus a **`MemoryExporter`** **`validateExecutionEvent`** smoke (`spec_conformance.integration.test.ts`).
|
|
387
|
+
- **Local:** clone `intentproof-spec` **next to** this repository (`../intentproof-spec`), then:
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
npm run spec:conformance
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Or set `INTENTPROOF_SPEC_ROOT` to your spec checkout and run `bash scripts/spec-conformance.sh`.
|
|
394
|
+
|
|
395
|
+
- **Generated fingerprint metadata:** schema codegen writes **`packages/sdk/src/generated/spec_fingerprint.json`** (spec version, generator version, per-schema SHA-256, aggregate hash). Validate/update generated artifacts with:
|
|
396
|
+
|
|
397
|
+
```bash
|
|
398
|
+
bash scripts/verify-generated-types.sh
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
- **No handwritten model types:** **`scripts/check-no-handwritten-model-types.sh`** delegates to the shared **`intentproof-spec`** checker. It is wired into **`npm run ci`**, CI, and release, and fails if schema model/type declarations appear outside **`packages/sdk/src/generated`** or if the bridge aliases in **`packages/sdk/src/types.ts`** stop mapping to generated types.
|
|
402
|
+
|
|
403
|
+
---
|
|
362
404
|
|
|
363
|
-
##
|
|
405
|
+
## Project development
|
|
364
406
|
|
|
365
|
-
|
|
407
|
+
Contributing and shared **`intentproof-spec`** terminology: **[`CONTRIBUTING.md`](CONTRIBUTING.md)**.
|
|
366
408
|
|
|
367
|
-
Requires **Node.js** 22 or newer (see `.nvmrc` and workspace
|
|
409
|
+
Layout: **npm workspace** (`package.json` **`workspaces`**, publishable package [`packages/sdk`](packages/sdk)). Requires **Node.js** 22 or newer (see `.nvmrc` and workspace **`engines`**). Release history: [`CHANGELOG.md`](CHANGELOG.md).
|
|
368
410
|
|
|
369
411
|
```bash
|
|
370
412
|
npm ci
|
|
@@ -373,4 +415,4 @@ npm run ci
|
|
|
373
415
|
|
|
374
416
|
## License
|
|
375
417
|
|
|
376
|
-
Apache-2.0 (see `LICENSE` at the repository root and in the published npm package).
|
|
418
|
+
Apache-2.0 (see `LICENSE` at the repository root and in the published npm package when released).
|