@xproof/xproof 0.1.7 → 0.1.9

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
@@ -1,5 +1,7 @@
1
1
  # xproof
2
2
 
3
+ [![npm SDK CI](https://github.com/jasonxkensei/xproof/actions/workflows/npm-sdk.yml/badge.svg?branch=main)](https://github.com/jasonxkensei/xproof/actions/workflows/npm-sdk.yml) [![npm version](https://img.shields.io/npm/v/@xproof/xproof)](https://www.npmjs.com/package/@xproof/xproof) [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue)](https://www.typescriptlang.org/)
4
+
3
5
  On-chain decision provenance for autonomous agents. **WHY before acting. WHAT after.** Timestamps written by the chain, not your agent.
4
6
 
5
7
  ```bash
@@ -161,6 +163,312 @@ const proof = await client.verifyHash(fileHash);
161
163
  console.log(proof.blockchainStatus); // "confirmed" | "pending"
162
164
  ```
163
165
 
166
+ ## Policy Compliance
167
+
168
+ Check whether a decision meets governance requirements — without fetching the full confidence trail:
169
+
170
+ ```typescript
171
+ import { XProofClient } from "@xproof/xproof";
172
+ import type { PolicyCheckResult } from "@xproof/xproof";
173
+
174
+ const client = new XProofClient({ apiKey: "pm_your_key" });
175
+
176
+ const result: PolicyCheckResult = await client.getPolicyCheck("trade-xyz-2026");
177
+
178
+ if (result.policyCompliant) {
179
+ console.log("Decision is compliant.");
180
+ } else {
181
+ for (const v of result.policyViolations) {
182
+ console.log(`VIOLATION — ${v.rule}`);
183
+ console.log(` proof: ${v.proofId}`);
184
+ console.log(` confidence: ${v.confidenceLevel} (required: ${v.threshold})`);
185
+ console.log(` class: ${v.reversibilityClass}`);
186
+ }
187
+ }
188
+ ```
189
+
190
+ `getPolicyCheck()` is a lightweight yes/no compliance check. It returns `result.policyCompliant` (boolean) and `result.policyViolations` (array). For the full audit trail including timestamps and intermediate confidence checkpoints, use `getConfidenceTrail()` instead.
191
+
192
+ ---
193
+
194
+ ## Timing Breakdown
195
+
196
+ Anchor the full decision chronology on-chain alongside the confidence anchor. Three ISO8601 timestamps mark **when the instruction arrived**, **when reasoning began**, and **when the action fired**. A `jurisdictionType` field records who was accountable for the decision.
197
+
198
+ ```typescript
199
+ import { XProofClient, hashString, JURISDICTION_TYPES } from "@xproof/xproof";
200
+ import type { TimingBreakdown } from "@xproof/xproof";
201
+
202
+ const client = new XProofClient({ apiKey: "pm_your_key" });
203
+
204
+ const instructionReceivedAt = new Date().toISOString();
205
+ // ... agent reasons ...
206
+ const reasoningStartedAt = new Date().toISOString();
207
+ // ... reasoning completes, agent executes ...
208
+ const actionTakenAt = new Date().toISOString();
209
+
210
+ const timing: TimingBreakdown = {
211
+ instructionReceivedAt,
212
+ reasoningStartedAt,
213
+ actionTakenAt,
214
+ jurisdictionType: "autonomous_inference", // agent reached its own conclusion
215
+ };
216
+
217
+ const cert = await client.certifyWithConfidence(
218
+ hashString(JSON.stringify({ action: "approve_transfer", amount: 50_000 })),
219
+ "transfer-decision.json",
220
+ "treasury-agent",
221
+ {
222
+ confidenceLevel: 0.97,
223
+ thresholdStage: "final",
224
+ decisionId: "transfer-xyz-2026",
225
+ reversibilityClass: "irreversible",
226
+ timing,
227
+ }
228
+ );
229
+
230
+ // cert.timingBreakdown is populated in the API response:
231
+ console.log(cert.timingBreakdown?.reasoningDurationMs); // ms between reasoning_started_at and action_taken_at
232
+ console.log(cert.timingBreakdown?.totalDurationMs); // ms between instruction_received_at and action_taken_at
233
+ ```
234
+
235
+ ### `jurisdictionType` values
236
+
237
+ | Value | Meaning | Who bears accountability |
238
+ |---|---|---|
239
+ | `"instruction_following"` | Agent executed an explicit human instruction | Principal (human) |
240
+ | `"autonomous_inference"` | Agent reached its own conclusion | Agent and its operator |
241
+ | `"human_approved"` | Agent recommended, human approved before action | Shared |
242
+
243
+ All valid values are exported as the `JURISDICTION_TYPES` constant for runtime validation:
244
+
245
+ ```typescript
246
+ import { JURISDICTION_TYPES } from "@xproof/xproof";
247
+
248
+ // ["instruction_following", "autonomous_inference", "human_approved"]
249
+ console.log(JURISDICTION_TYPES);
250
+
251
+ // Runtime guard
252
+ function isValidJurisdiction(s: string): boolean {
253
+ return (JURISDICTION_TYPES as readonly string[]).includes(s);
254
+ }
255
+ ```
256
+
257
+ ### Reading timing data back
258
+
259
+ ```typescript
260
+ const cert = await client.verify("certification-uuid");
261
+
262
+ if (cert.timingBreakdown) {
263
+ const { instructionReceivedAt, reasoningDurationMs, totalDurationMs } = cert.timingBreakdown;
264
+ console.log(`Instruction at: ${instructionReceivedAt}`);
265
+ console.log(`Reasoning took: ${reasoningDurationMs}ms`);
266
+ console.log(`Total latency: ${totalDurationMs}ms`);
267
+ }
268
+ ```
269
+
270
+ > All four fields (`instructionReceivedAt`, `reasoningStartedAt`, `actionTakenAt`, `jurisdictionType`) are optional — you can anchor whichever timestamps are available. `reasoningDurationMs` and `totalDurationMs` are computed server-side and appear only in responses, never in requests.
271
+
272
+ ---
273
+
274
+ ## Governance & Policy Enforcement
275
+
276
+ xProof detects automatically when an agent acted with insufficient confidence on an irreversible action — and writes the evidence on-chain before you ever open an incident report.
277
+
278
+ ### Mark decisions as reversible, costly, or irreversible
279
+
280
+ Add `reversibilityClass` to any certified action. The server enforces a policy: **irreversible actions require `confidenceLevel >= 0.95`**. Anything below that threshold generates a policy violation anchored to the chain.
281
+
282
+ ```typescript
283
+ import { XProofClient, hashString } from "@xproof/xproof";
284
+
285
+ const client = new XProofClient({ apiKey: "pm_..." });
286
+
287
+ // An agent is about to execute a trade it cannot undo.
288
+ // It certifies its reasoning at 0.72 confidence — below the 0.95 threshold.
289
+ const cert = await client.certifyWithConfidence(
290
+ hashString(JSON.stringify({ action: "sell", ticker: "AAPL", qty: 500 })),
291
+ "trade-decision.json",
292
+ "trading-agent",
293
+ {
294
+ confidenceLevel: 0.72, // Agent's self-assessed confidence
295
+ thresholdStage: "pre-commitment",
296
+ decisionId: "trade-xyz-2026",
297
+ reversibilityClass: "irreversible", // This action cannot be undone
298
+ }
299
+ );
300
+
301
+ // cert.reversibilityClass === "irreversible"
302
+ // The server has recorded a policy violation: 0.72 < 0.95 required
303
+ ```
304
+
305
+ ### Check compliance — without fetching the full trail
306
+
307
+ ```typescript
308
+ import type { PolicyCheckResult } from "@xproof/xproof";
309
+
310
+ const check: PolicyCheckResult = await client.getPolicyCheck("trade-xyz-2026");
311
+
312
+ if (!check.policyCompliant) {
313
+ for (const v of check.policyViolations) {
314
+ console.log(`VIOLATION — ${v.rule}`);
315
+ console.log(` proof: ${v.proofId}`);
316
+ console.log(` confidence: ${v.confidenceLevel} (required: ${v.threshold})`);
317
+ console.log(` class: ${v.reversibilityClass}`);
318
+ // → VIOLATION — irreversible actions require confidence_level >= 0.95
319
+ // → proof: abc-uuid
320
+ // → confidence: 0.72 (required: 0.95)
321
+ // → class: irreversible
322
+ }
323
+ }
324
+ ```
325
+
326
+ ### Full confidence trail with policy result
327
+
328
+ ```typescript
329
+ const trail = await client.getConfidenceTrail("trade-xyz-2026");
330
+
331
+ console.log(trail.policyCompliant); // false
332
+ console.log(trail.policyViolations.length); // 1
333
+ console.log(trail.currentConfidence); // 0.72
334
+ console.log(trail.isFinalized); // false — decision still open
335
+ ```
336
+
337
+ ### Observability — surfacing violations in dashboards
338
+
339
+ Throwing an error is enough to halt execution, but it gives your observability
340
+ stack nothing structured to alert on. The pattern below emits a
341
+ machine-readable JSON log line for each violation and optionally fires a
342
+ webhook, so Datadog / Grafana / CloudWatch log-based alerts can pick up
343
+ violations without grepping free-form text.
344
+
345
+ ```typescript
346
+ import { XProofClient } from "@xproof/xproof";
347
+ import type { PolicyViolation } from "@xproof/xproof";
348
+
349
+ const client = new XProofClient({ apiKey: "pm_..." });
350
+ const decisionId = "trade-xyz-2026"; // the decision ID passed to certifyWithConfidence()
351
+
352
+ // Optional: set a webhook URL to receive violation payloads
353
+ const VIOLATION_WEBHOOK_URL: string | null = null; // e.g. "https://hooks.example.com/compliance"
354
+
355
+ async function emitViolation(decisionId: string, violation: PolicyViolation): Promise<void> {
356
+ const payload = {
357
+ event: "policy_violation",
358
+ decision_id: decisionId,
359
+ rule: violation.rule,
360
+ proof_id: violation.proofId,
361
+ confidence_level: violation.confidenceLevel,
362
+ threshold: violation.threshold,
363
+ reversibility_class: violation.reversibilityClass,
364
+ threshold_stage: violation.thresholdStage,
365
+ };
366
+
367
+ // ── Structured JSON log (ingested by Datadog / CloudWatch / Loki) ─────────
368
+ // console.error writes to stderr, which log shippers (Fluentd, the Datadog
369
+ // Agent, the CloudWatch agent) forward verbatim.
370
+ // Drop-in replacements: pino.error(payload) emits NDJSON with no extra
371
+ // config; for winston, configure a JSON transport first (e.g.
372
+ // `winston.createLogger({ format: winston.format.json(), ... })`), then
373
+ // call logger.error(payload) to get the same single-line JSON output.
374
+ console.error(JSON.stringify(payload));
375
+
376
+ // ── Optional webhook / alerting callback (best-effort) ───────────────────
377
+ if (VIOLATION_WEBHOOK_URL) {
378
+ try {
379
+ await fetch(VIOLATION_WEBHOOK_URL, {
380
+ method: "POST",
381
+ headers: { "Content-Type": "application/json" },
382
+ body: JSON.stringify(payload),
383
+ signal: AbortSignal.timeout(5000), // fire-and-forget; add retry logic as needed
384
+ });
385
+ } catch (exc) {
386
+ // Best-effort delivery — a webhook failure must NOT swallow the
387
+ // compliance violation itself. Log and continue to the throw below.
388
+ console.warn(JSON.stringify({ event: "webhook_error", detail: String(exc) }));
389
+ }
390
+ }
391
+ }
392
+
393
+ const check = await client.getPolicyCheck(decisionId);
394
+
395
+ if (!check.policyCompliant) {
396
+ for (const v of check.policyViolations) {
397
+ await emitViolation(decisionId, v);
398
+ }
399
+
400
+ // ── Full audit trail for post-mortem / SIEM export ────────────────────────
401
+ // getConfidenceTrail() returns a ConfidenceTrail object containing every
402
+ // certification event — confidence levels, timestamps, transaction hashes —
403
+ // so you can attach the complete chain-of-evidence to an incident ticket or
404
+ // ship it to your SIEM without a separate lookup.
405
+ // Note: redact sensitive fields from trail.stages before logging or
406
+ // exporting to centralised logs / SIEM in production environments.
407
+ const trail = await client.getConfidenceTrail(decisionId);
408
+ console.error(JSON.stringify({
409
+ event: "audit_trail",
410
+ decision_id: decisionId,
411
+ current_confidence: trail.currentConfidence,
412
+ is_finalized: trail.isFinalized,
413
+ total_anchors: trail.totalAnchors,
414
+ stages: trail.stages,
415
+ }));
416
+
417
+ throw new Error("Action aborted: policy compliance check failed.");
418
+ }
419
+ ```
420
+
421
+ Each `console.error(JSON.stringify(...))` call writes a single-line JSON object
422
+ that log shippers (Fluentd, the Datadog Agent, the CloudWatch agent) forward
423
+ verbatim. Create a log-based metric or alert on `event = "policy_violation"` to
424
+ get dashboard counts and threshold alerts with no extra instrumentation.
425
+
426
+ #### Drop-in: pino
427
+
428
+ Replace `console.error(JSON.stringify(payload))` with a single `pino` call — no extra config needed, pino emits NDJSON by default:
429
+
430
+ ```typescript
431
+ import pino from "pino";
432
+
433
+ const logger = pino();
434
+
435
+ // inside emitViolation():
436
+ logger.error(payload); // emits: {"level":50,"time":...,"rule":"...","event":"policy_violation",...}
437
+ ```
438
+
439
+ #### Drop-in: winston
440
+
441
+ Configure a JSON transport once, then call `logger.error(payload)` to get the same single-line JSON output:
442
+
443
+ ```typescript
444
+ import winston from "winston";
445
+
446
+ const logger = winston.createLogger({
447
+ level: "error",
448
+ format: winston.format.json(),
449
+ transports: [new winston.transports.Console({ stderrLevels: ["error"] })],
450
+ });
451
+
452
+ // inside emitViolation():
453
+ logger.error("policy_violation", payload);
454
+ ```
455
+
456
+ Both emit a single JSON line per violation — identical in structure to the `console.error` version above.
457
+
458
+ > **Runnable example** — `examples/observability.ts` in this repo demonstrates the full pattern (violation detection, structured logging, webhook delivery, audit trail) with a mock client. Run it with `npx tsx examples/observability.ts`.
459
+
460
+ ### Three classes, one parameter
461
+
462
+ | `reversibilityClass` | What it means | Policy threshold |
463
+ |---|---|---|
464
+ | `"reversible"` | Action can be undone (e.g. draft, preview) | None — any confidence accepted |
465
+ | `"costly"` | Undoable but expensive (e.g. API call, DB write) | None — any confidence accepted |
466
+ | `"irreversible"` | Cannot be undone (e.g. trade, deletion, send) | `confidenceLevel >= 0.95` required |
467
+
468
+ > The threshold is configured server-side (`IRREVERSIBLE_CONFIDENCE_THRESHOLD=0.95`). All violations are written on-chain and cannot be amended.
469
+
470
+ ---
471
+
164
472
  ## Pricing
165
473
 
166
474
  ```typescript
@@ -208,11 +516,18 @@ try {
208
516
  | `XProofClient.register(agentName)` | Register agent, get trial key |
209
517
  | `certify(path, author, fileName?, fourW?)` | Certify file (hashes locally) |
210
518
  | `certifyHash(hash, name, author, fourW?)` | Certify by pre-computed hash |
519
+ | `certifyWithConfidence(hash, name, author, opts)` | Certify with confidence + governance class |
211
520
  | `batchCertify(files)` | Batch certify (up to 50) |
212
521
  | `verify(proofId)` | Look up by proof ID |
213
522
  | `verifyHash(fileHash)` | Look up by file hash |
523
+ | `getConfidenceTrail(decisionId)` | Full trail with `policyCompliant` + violations |
524
+ | `getPolicyCheck(decisionId)` | Lightweight compliance check — no full trail |
214
525
  | `getPricing()` | Get current pricing |
215
526
 
527
+ ## Contributing
528
+
529
+ If you use VS Code, install the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) (`dbaeumer.vscode-eslint`). The repo includes `.vscode/settings.json` that configures ESLint as the default formatter and runs `eslint --fix`, organise-imports, and remove-unused-imports automatically on every save. VS Code will prompt you to install the recommended extension when you open the folder.
530
+
216
531
  ## Links
217
532
 
218
533
  - [xproof.app](https://xproof.app) — dashboard & docs
@@ -1,3 +1,37 @@
1
+ type JurisdictionType = "instruction_following" | "autonomous_inference" | "human_approved";
2
+ /**
3
+ * All valid `JurisdictionType` values — useful for runtime validation.
4
+ *
5
+ * - `instruction_following` — agent executed an explicit human instruction;
6
+ * accountability follows the principal.
7
+ * - `autonomous_inference` — agent reached its own conclusion; agent and its
8
+ * operator bear primary accountability.
9
+ * - `human_approved` — agent recommended, human approved; shared accountability.
10
+ */
11
+ declare const JURISDICTION_TYPES: readonly JurisdictionType[];
12
+ /**
13
+ * Decomposed decision timeline for forensic audit.
14
+ *
15
+ * Pass a `TimingBreakdown` to `certifyWithConfidence()` via `confidence.timing`
16
+ * to anchor the full decision chronology on-chain.
17
+ *
18
+ * All timestamp fields are optional ISO8601 strings with a timezone offset
19
+ * (e.g. `"2026-04-20T14:31:58Z"`).
20
+ *
21
+ * When read back from the API the server populates two computed fields:
22
+ * - `reasoningDurationMs` — ms between `reasoningStartedAt` and `actionTakenAt`
23
+ * - `totalDurationMs` — ms between `instructionReceivedAt` and `actionTakenAt`
24
+ */
25
+ interface TimingBreakdown {
26
+ instructionReceivedAt?: string;
27
+ reasoningStartedAt?: string;
28
+ actionTakenAt?: string;
29
+ jurisdictionType?: JurisdictionType;
30
+ /** Computed by server; present in API responses only. */
31
+ reasoningDurationMs?: number;
32
+ /** Computed by server; present in API responses only. */
33
+ totalDurationMs?: number;
34
+ }
1
35
  interface Certification {
2
36
  id: string;
3
37
  fileName: string;
@@ -10,6 +44,7 @@ interface Certification {
10
44
  isPublic: boolean;
11
45
  certificateUrl: string;
12
46
  verifyUrl: string;
47
+ timingBreakdown?: TimingBreakdown;
13
48
  }
14
49
  interface BatchResultSummary {
15
50
  total: number;
@@ -68,6 +103,8 @@ interface ConfidenceOptions {
68
103
  thresholdStage: ThresholdStage;
69
104
  decisionId: string;
70
105
  reversibilityClass?: ReversibilityClass;
106
+ /** Optional timing breakdown to anchor the full decision chronology on-chain. */
107
+ timing?: TimingBreakdown;
71
108
  }
72
109
  interface ConfidenceTrailStage {
73
110
  proofId: string;
@@ -125,6 +162,7 @@ interface BatchFileEntry {
125
162
  fileName?: string;
126
163
  author?: string;
127
164
  metadata?: Record<string, unknown>;
165
+ timing?: TimingBreakdown;
128
166
  }
129
167
  interface XProofClientOptions {
130
168
  apiKey?: string;
@@ -189,4 +227,4 @@ declare class XProofClient {
189
227
  private handleError;
190
228
  }
191
229
 
192
- export { type BatchFileEntry as B, type Certification as C, type ExecutionContext as E, type FourWOptions as F, type PolicyCheckResult as P, type RegistrationResult as R, type ThresholdStage as T, XProofClient as X, type BatchResult as a, type BatchResultSummary as b, type CertifyHashOptions as c, type ConfidenceOptions as d, type ConfidenceTrail as e, type ConfidenceTrailDrift as f, type ConfidenceTrailStage as g, type ContextDrift as h, type ContextDriftStage as i, type PolicyViolation as j, type PricingInfo as k, type PricingTier as l, type ReversibilityClass as m, type TrialInfo as n, type XProofClientOptions as o };
230
+ export { type BatchFileEntry as B, type Certification as C, type ExecutionContext as E, type FourWOptions as F, JURISDICTION_TYPES as J, type PolicyCheckResult as P, type RegistrationResult as R, type ThresholdStage as T, XProofClient as X, type BatchResult as a, type BatchResultSummary as b, type CertifyHashOptions as c, type ConfidenceOptions as d, type ConfidenceTrail as e, type ConfidenceTrailDrift as f, type ConfidenceTrailStage as g, type ContextDrift as h, type ContextDriftStage as i, type JurisdictionType as j, type PolicyViolation as k, type PricingInfo as l, type PricingTier as m, type ReversibilityClass as n, type TimingBreakdown as o, type TrialInfo as p, type XProofClientOptions as q };
@@ -1,3 +1,37 @@
1
+ type JurisdictionType = "instruction_following" | "autonomous_inference" | "human_approved";
2
+ /**
3
+ * All valid `JurisdictionType` values — useful for runtime validation.
4
+ *
5
+ * - `instruction_following` — agent executed an explicit human instruction;
6
+ * accountability follows the principal.
7
+ * - `autonomous_inference` — agent reached its own conclusion; agent and its
8
+ * operator bear primary accountability.
9
+ * - `human_approved` — agent recommended, human approved; shared accountability.
10
+ */
11
+ declare const JURISDICTION_TYPES: readonly JurisdictionType[];
12
+ /**
13
+ * Decomposed decision timeline for forensic audit.
14
+ *
15
+ * Pass a `TimingBreakdown` to `certifyWithConfidence()` via `confidence.timing`
16
+ * to anchor the full decision chronology on-chain.
17
+ *
18
+ * All timestamp fields are optional ISO8601 strings with a timezone offset
19
+ * (e.g. `"2026-04-20T14:31:58Z"`).
20
+ *
21
+ * When read back from the API the server populates two computed fields:
22
+ * - `reasoningDurationMs` — ms between `reasoningStartedAt` and `actionTakenAt`
23
+ * - `totalDurationMs` — ms between `instructionReceivedAt` and `actionTakenAt`
24
+ */
25
+ interface TimingBreakdown {
26
+ instructionReceivedAt?: string;
27
+ reasoningStartedAt?: string;
28
+ actionTakenAt?: string;
29
+ jurisdictionType?: JurisdictionType;
30
+ /** Computed by server; present in API responses only. */
31
+ reasoningDurationMs?: number;
32
+ /** Computed by server; present in API responses only. */
33
+ totalDurationMs?: number;
34
+ }
1
35
  interface Certification {
2
36
  id: string;
3
37
  fileName: string;
@@ -10,6 +44,7 @@ interface Certification {
10
44
  isPublic: boolean;
11
45
  certificateUrl: string;
12
46
  verifyUrl: string;
47
+ timingBreakdown?: TimingBreakdown;
13
48
  }
14
49
  interface BatchResultSummary {
15
50
  total: number;
@@ -68,6 +103,8 @@ interface ConfidenceOptions {
68
103
  thresholdStage: ThresholdStage;
69
104
  decisionId: string;
70
105
  reversibilityClass?: ReversibilityClass;
106
+ /** Optional timing breakdown to anchor the full decision chronology on-chain. */
107
+ timing?: TimingBreakdown;
71
108
  }
72
109
  interface ConfidenceTrailStage {
73
110
  proofId: string;
@@ -125,6 +162,7 @@ interface BatchFileEntry {
125
162
  fileName?: string;
126
163
  author?: string;
127
164
  metadata?: Record<string, unknown>;
165
+ timing?: TimingBreakdown;
128
166
  }
129
167
  interface XProofClientOptions {
130
168
  apiKey?: string;
@@ -189,4 +227,4 @@ declare class XProofClient {
189
227
  private handleError;
190
228
  }
191
229
 
192
- export { type BatchFileEntry as B, type Certification as C, type ExecutionContext as E, type FourWOptions as F, type PolicyCheckResult as P, type RegistrationResult as R, type ThresholdStage as T, XProofClient as X, type BatchResult as a, type BatchResultSummary as b, type CertifyHashOptions as c, type ConfidenceOptions as d, type ConfidenceTrail as e, type ConfidenceTrailDrift as f, type ConfidenceTrailStage as g, type ContextDrift as h, type ContextDriftStage as i, type PolicyViolation as j, type PricingInfo as k, type PricingTier as l, type ReversibilityClass as m, type TrialInfo as n, type XProofClientOptions as o };
230
+ export { type BatchFileEntry as B, type Certification as C, type ExecutionContext as E, type FourWOptions as F, JURISDICTION_TYPES as J, type PolicyCheckResult as P, type RegistrationResult as R, type ThresholdStage as T, XProofClient as X, type BatchResult as a, type BatchResultSummary as b, type CertifyHashOptions as c, type ConfidenceOptions as d, type ConfidenceTrail as e, type ConfidenceTrailDrift as f, type ConfidenceTrailStage as g, type ContextDrift as h, type ContextDriftStage as i, type JurisdictionType as j, type PolicyViolation as k, type PricingInfo as l, type PricingTier as m, type ReversibilityClass as n, type TimingBreakdown as o, type TrialInfo as p, type XProofClientOptions as q };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { B as BatchFileEntry, a as BatchResult, b as BatchResultSummary, C as Certification, c as CertifyHashOptions, d as ConfidenceOptions, e as ConfidenceTrail, f as ConfidenceTrailDrift, g as ConfidenceTrailStage, h as ContextDrift, i as ContextDriftStage, E as ExecutionContext, F as FourWOptions, P as PolicyCheckResult, j as PolicyViolation, k as PricingInfo, l as PricingTier, R as RegistrationResult, m as ReversibilityClass, T as ThresholdStage, n as TrialInfo, X as XProofClient, o as XProofClientOptions } from './client-CWrki-T_.mjs';
1
+ export { B as BatchFileEntry, a as BatchResult, b as BatchResultSummary, C as Certification, c as CertifyHashOptions, d as ConfidenceOptions, e as ConfidenceTrail, f as ConfidenceTrailDrift, g as ConfidenceTrailStage, h as ContextDrift, i as ContextDriftStage, E as ExecutionContext, F as FourWOptions, J as JURISDICTION_TYPES, j as JurisdictionType, P as PolicyCheckResult, k as PolicyViolation, l as PricingInfo, m as PricingTier, R as RegistrationResult, n as ReversibilityClass, T as ThresholdStage, o as TimingBreakdown, p as TrialInfo, X as XProofClient, q as XProofClientOptions } from './client-Dq5Be9On.mjs';
2
2
 
3
3
  declare class XProofError extends Error {
4
4
  statusCode: number;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { B as BatchFileEntry, a as BatchResult, b as BatchResultSummary, C as Certification, c as CertifyHashOptions, d as ConfidenceOptions, e as ConfidenceTrail, f as ConfidenceTrailDrift, g as ConfidenceTrailStage, h as ContextDrift, i as ContextDriftStage, E as ExecutionContext, F as FourWOptions, P as PolicyCheckResult, j as PolicyViolation, k as PricingInfo, l as PricingTier, R as RegistrationResult, m as ReversibilityClass, T as ThresholdStage, n as TrialInfo, X as XProofClient, o as XProofClientOptions } from './client-CWrki-T_.js';
1
+ export { B as BatchFileEntry, a as BatchResult, b as BatchResultSummary, C as Certification, c as CertifyHashOptions, d as ConfidenceOptions, e as ConfidenceTrail, f as ConfidenceTrailDrift, g as ConfidenceTrailStage, h as ContextDrift, i as ContextDriftStage, E as ExecutionContext, F as FourWOptions, J as JURISDICTION_TYPES, j as JurisdictionType, P as PolicyCheckResult, k as PolicyViolation, l as PricingInfo, m as PricingTier, R as RegistrationResult, n as ReversibilityClass, T as ThresholdStage, o as TimingBreakdown, p as TrialInfo, X as XProofClient, q as XProofClientOptions } from './client-Dq5Be9On.js';
2
2
 
3
3
  declare class XProofError extends Error {
4
4
  statusCode: number;
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AuthenticationError: () => AuthenticationError,
24
24
  ConflictError: () => ConflictError,
25
+ JURISDICTION_TYPES: () => JURISDICTION_TYPES,
25
26
  NotFoundError: () => NotFoundError,
26
27
  RateLimitError: () => RateLimitError,
27
28
  ServerError: () => ServerError,
@@ -99,8 +100,47 @@ function hashString(data) {
99
100
  }
100
101
 
101
102
  // src/parse.ts
103
+ function parseTimingBreakdown(raw) {
104
+ const tb = {};
105
+ let hasAnyField = false;
106
+ if (raw.instruction_received_at != null) {
107
+ tb.instructionReceivedAt = raw.instruction_received_at;
108
+ hasAnyField = true;
109
+ }
110
+ if (raw.reasoning_started_at != null) {
111
+ tb.reasoningStartedAt = raw.reasoning_started_at;
112
+ hasAnyField = true;
113
+ }
114
+ if (raw.action_taken_at != null) {
115
+ tb.actionTakenAt = raw.action_taken_at;
116
+ hasAnyField = true;
117
+ }
118
+ if (raw.jurisdiction_type != null) {
119
+ tb.jurisdictionType = raw.jurisdiction_type;
120
+ hasAnyField = true;
121
+ }
122
+ if (raw.reasoning_duration_ms != null) {
123
+ tb.reasoningDurationMs = raw.reasoning_duration_ms;
124
+ hasAnyField = true;
125
+ }
126
+ if (raw.total_duration_ms != null) {
127
+ tb.totalDurationMs = raw.total_duration_ms;
128
+ hasAnyField = true;
129
+ }
130
+ return hasAnyField ? tb : void 0;
131
+ }
102
132
  function parseCertification(data) {
103
133
  const blockchain = data.blockchain || {};
134
+ const _meta = data.metadata;
135
+ const _TIMING_KEYS = [
136
+ "instruction_received_at",
137
+ "reasoning_started_at",
138
+ "action_taken_at",
139
+ "jurisdiction_type",
140
+ "reasoning_duration_ms",
141
+ "total_duration_ms"
142
+ ];
143
+ const rawTiming = data.timing_breakdown ?? _meta?.timing_breakdown ?? (_meta && _TIMING_KEYS.some((k) => _meta[k] != null) ? _meta : void 0);
104
144
  return {
105
145
  id: data.id || data.proof_id || "",
106
146
  fileName: data.fileName || data.filename || data.file_name || "",
@@ -112,7 +152,8 @@ function parseCertification(data) {
112
152
  blockchainStatus: data.blockchainStatus || data.status || "",
113
153
  isPublic: data.isPublic !== void 0 ? !!data.isPublic : data.is_public !== void 0 ? !!data.is_public : true,
114
154
  certificateUrl: data.certificateUrl || data.certificate_url || "",
115
- verifyUrl: data.verifyUrl || data.verify_url || ""
155
+ verifyUrl: data.verifyUrl || data.verify_url || "",
156
+ timingBreakdown: rawTiming ? parseTimingBreakdown(rawTiming) : void 0
116
157
  };
117
158
  }
118
159
  function parseBatchResult(data) {
@@ -170,8 +211,15 @@ function parseRegistrationResult(data) {
170
211
  };
171
212
  }
172
213
 
214
+ // src/types.ts
215
+ var JURISDICTION_TYPES = [
216
+ "instruction_following",
217
+ "autonomous_inference",
218
+ "human_approved"
219
+ ];
220
+
173
221
  // src/client.ts
174
- var VERSION = "0.1.7";
222
+ var VERSION = "0.1.9";
175
223
  var DEFAULT_BASE_URL = "https://xproof.app";
176
224
  var DEFAULT_TIMEOUT = 3e4;
177
225
  var XProofClient = class _XProofClient {
@@ -231,7 +279,25 @@ var XProofClient = class _XProofClient {
231
279
  filename: f.fileName ?? "unknown",
232
280
  file_hash: f.fileHash
233
281
  };
234
- if (f.metadata) entry.metadata = f.metadata;
282
+ const entryMeta = f.metadata ? { ...f.metadata } : {};
283
+ if (f.timing !== void 0) {
284
+ const t = f.timing;
285
+ if (t.jurisdictionType !== void 0 && !JURISDICTION_TYPES.includes(t.jurisdictionType)) {
286
+ throw new ValidationError(
287
+ `timing.jurisdictionType must be one of: ${JURISDICTION_TYPES.join(", ")}`,
288
+ {}
289
+ );
290
+ }
291
+ if (t.instructionReceivedAt !== void 0)
292
+ entryMeta.instruction_received_at = t.instructionReceivedAt;
293
+ if (t.reasoningStartedAt !== void 0)
294
+ entryMeta.reasoning_started_at = t.reasoningStartedAt;
295
+ if (t.actionTakenAt !== void 0)
296
+ entryMeta.action_taken_at = t.actionTakenAt;
297
+ if (t.jurisdictionType !== void 0)
298
+ entryMeta.jurisdiction_type = t.jurisdictionType;
299
+ }
300
+ if (Object.keys(entryMeta).length > 0) entry.metadata = entryMeta;
235
301
  return entry;
236
302
  });
237
303
  const payload = { files: entries };
@@ -241,13 +307,13 @@ var XProofClient = class _XProofClient {
241
307
  return parseBatchResult(data);
242
308
  }
243
309
  async verify(proofId) {
244
- const data = await this.request("GET", `/api/proof/${proofId}`, {
310
+ const data = await this.request("GET", `/api/proof/${encodeURIComponent(proofId)}`, {
245
311
  authRequired: false
246
312
  });
247
313
  return parseCertification(data);
248
314
  }
249
315
  async verifyHash(fileHash) {
250
- const data = await this.request("GET", `/api/proof/hash/${fileHash}`, {
316
+ const data = await this.request("GET", `/api/proof/hash/${encodeURIComponent(fileHash)}`, {
251
317
  authRequired: false
252
318
  });
253
319
  return parseCertification(data);
@@ -275,6 +341,23 @@ var XProofClient = class _XProofClient {
275
341
  metadata.decision_id = confidence.decisionId;
276
342
  if (confidence.reversibilityClass !== void 0)
277
343
  metadata.reversibility_class = confidence.reversibilityClass;
344
+ if (confidence.timing !== void 0) {
345
+ const t = confidence.timing;
346
+ if (t.jurisdictionType !== void 0 && !JURISDICTION_TYPES.includes(t.jurisdictionType)) {
347
+ throw new ValidationError(
348
+ `timing.jurisdictionType must be one of: ${JURISDICTION_TYPES.join(", ")}`,
349
+ {}
350
+ );
351
+ }
352
+ if (t.instructionReceivedAt !== void 0)
353
+ metadata.instruction_received_at = t.instructionReceivedAt;
354
+ if (t.reasoningStartedAt !== void 0)
355
+ metadata.reasoning_started_at = t.reasoningStartedAt;
356
+ if (t.actionTakenAt !== void 0)
357
+ metadata.action_taken_at = t.actionTakenAt;
358
+ if (t.jurisdictionType !== void 0)
359
+ metadata.jurisdiction_type = t.jurisdictionType;
360
+ }
278
361
  const payload = {
279
362
  filename: fileName,
280
363
  file_hash: fileHash,
@@ -285,6 +368,9 @@ var XProofClient = class _XProofClient {
285
368
  return parseCertification(data);
286
369
  }
287
370
  async getConfidenceTrail(decisionId) {
371
+ if (!decisionId || !decisionId.trim()) {
372
+ throw new ValidationError("decisionId is required", {});
373
+ }
288
374
  const data = await this.request(
289
375
  "GET",
290
376
  `/api/confidence-trail/${encodeURIComponent(decisionId)}`,
@@ -338,6 +424,9 @@ var XProofClient = class _XProofClient {
338
424
  };
339
425
  }
340
426
  async getContextDrift(decisionId) {
427
+ if (!decisionId || !decisionId.trim()) {
428
+ throw new ValidationError("decisionId is required", {});
429
+ }
341
430
  const data = await this.request(
342
431
  "GET",
343
432
  `/api/context-drift/${encodeURIComponent(decisionId)}`,
@@ -491,6 +580,7 @@ var XProofClient = class _XProofClient {
491
580
  0 && (module.exports = {
492
581
  AuthenticationError,
493
582
  ConflictError,
583
+ JURISDICTION_TYPES,
494
584
  NotFoundError,
495
585
  RateLimitError,
496
586
  ServerError,