verdifax 0.3.0 → 1.0.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 +123 -6
- package/dist/index.d.mts +357 -10
- package/dist/index.d.ts +357 -10
- package/dist/index.js +430 -24
- package/dist/index.mjs +419 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,17 +49,131 @@ if (v.verified) {
|
|
|
49
49
|
| --- | --- | --- |
|
|
50
50
|
| `client.health()` | `GET /health` | none |
|
|
51
51
|
| `client.version()` | `GET /version` | none |
|
|
52
|
+
| `client.getOpenAPI()` | `GET /openapi.json` | none |
|
|
53
|
+
| `client.getStats()` | `GET /stats` | required |
|
|
52
54
|
| `client.execute(req)` | `POST /execute` | required |
|
|
55
|
+
| `client.attest(req)` | `POST /execute` | required |
|
|
56
|
+
| `client.attestClaudeResponse(args)` | `POST /execute` | required |
|
|
57
|
+
| `client.attestOpenAIResponse(args)` | `POST /execute` | required |
|
|
58
|
+
| `client.executeBatch(runs)` | `POST /execute/batch` | required |
|
|
59
|
+
| `client.verifyDeterminism(req)` | `POST /execute/verify-determinism` | required |
|
|
53
60
|
| `client.getRun(id)` | `GET /runs/{id}` | required |
|
|
54
61
|
| `client.verifyRun(id)` | `GET /runs/{id}/verify` | required |
|
|
62
|
+
| `client.listRuns(params)` | `GET /runs` | required |
|
|
63
|
+
| `client.searchRuns(params)` | `GET /runs/search` | required |
|
|
64
|
+
| `client.exportRuns(params)` | `GET /runs/export` | required |
|
|
65
|
+
| `client.exportRunsCSV(params)` | `GET /runs/export?format=csv` | required |
|
|
66
|
+
| `client.getRunArtifacts(id)` | `GET /runs/{id}/artifacts` | required |
|
|
67
|
+
| `client.getRunReport(id)` | `GET /runs/{id}/report` | required |
|
|
68
|
+
| `client.downloadAuditPDF(id, format)` | `GET /runs/{id}/report.pdf` | required |
|
|
69
|
+
| `client.getAllowToken(id)` | `GET /runs/{id}/allow-token` | required |
|
|
70
|
+
| `client.getDenyReceipt(id)` | `GET /runs/{id}/deny-receipt` | required |
|
|
71
|
+
| `client.getCCVHaltReceipt(id)` | `GET /runs/{id}/ccv-halt-receipt` | required |
|
|
72
|
+
| `client.getMACCHaltReceipt(id)` | `GET /runs/{id}/macc-halt-receipt` | required |
|
|
73
|
+
| `client.getAivpT4HaltReceipt(id)` | `GET /runs/{id}/aivp-t4-halt-receipt` | required |
|
|
74
|
+
| `client.getAttestationGapReceipt(id)` | `GET /runs/{id}/attestation-gap-receipt` | required |
|
|
75
|
+
| `client.getCESAuditRecord(id)` | `GET /runs/{id}/ces-audit-record` | required |
|
|
76
|
+
| `client.listDeletionReceipts(id)` | `GET /runs/{id}/deletion-receipts` | required |
|
|
77
|
+
| `client.listAttestations(params)` | `GET /attestations` | required |
|
|
78
|
+
| `client.getAttestation(id)` | `GET /attestations/{id}` | required |
|
|
79
|
+
| `client.getPublicBundle(id)` | `GET /runs/{id}/bundle.json` | none |
|
|
80
|
+
| `client.getPublicBundleByToken(token)` | `GET /public/runs/{token}/bundle.json` | none |
|
|
81
|
+
| `client.dcaeVerify(bundle)` | `POST /dcae/verify` | none |
|
|
55
82
|
| `client.registerRequestKey()` | `POST /keys/request-key` | required |
|
|
56
83
|
| `client.clearRequestKey()` | `DELETE /keys/request-key` | required |
|
|
84
|
+
| `client.adminCreateKey(name)` | `POST /admin/keys` | admin |
|
|
85
|
+
| `client.adminListKeys()` | `GET /admin/keys` | admin |
|
|
86
|
+
| `client.adminRevokeKey(id)` | `DELETE /admin/keys/{id}` | admin |
|
|
87
|
+
| `client.adminErase(req)` | `POST /admin/erase` | admin |
|
|
57
88
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
89
|
+
These functions make no request: `captureEnvironment`, `formatProviderPayload`, `signRequest`, `requestKeyRegistrationBody`, `requestSignaturePreimage`, `generateRequestKeyPair`, `validateHex64`, `validateRouteId`, `dseDispatchHash`, `dcaeClosureHash` and `cresReceiptHash`. `RUN_STATUSES` lists every run status the server uses.
|
|
90
|
+
|
|
91
|
+
`getRunArtifacts`, `getPublicBundle` and `getPublicBundleByToken` return the exact JSON text the server sent, so you can save it and check it with `verdifax-verify`.
|
|
92
|
+
|
|
93
|
+
## Versioning
|
|
94
|
+
|
|
95
|
+
From 1.0, a breaking change needs a new major version.
|
|
96
|
+
|
|
97
|
+
## Settings
|
|
98
|
+
|
|
99
|
+
`new VerdifaxClient(config)` takes these options. `fromEnv()` reads the same settings from the environment.
|
|
100
|
+
|
|
101
|
+
| Setting | Option | Environment variable | Default |
|
|
102
|
+
| --- | --- | --- | --- |
|
|
103
|
+
| Base URL | `baseURL` | `VERDIFAX_BASE_URL`, then `VERDIFAX_API_URL` | `https://api.verdifax.com` |
|
|
104
|
+
| API key | `apiKey` | `VERDIFAX_API_KEY` | none |
|
|
105
|
+
| Timeout | `timeoutMs` | `VERDIFAX_TIMEOUT_MS` | 90 seconds |
|
|
106
|
+
| User agent | `userAgent` | `VERDIFAX_USER_AGENT` | `verdifax-sdk-node/<version>` |
|
|
107
|
+
| Retries | `maxRetries` | `VERDIFAX_MAX_RETRIES` | 3 |
|
|
108
|
+
| First retry delay | `retryBaseDelayMs` | none | 200 ms |
|
|
109
|
+
|
|
110
|
+
GET, HEAD and OPTIONS requests are retried after a network failure or an HTTP 429, 502, 503 or 504, with exponential backoff and full jitter. POST is never retried.
|
|
111
|
+
|
|
112
|
+
## Batch runs
|
|
113
|
+
|
|
114
|
+
`executeBatch(runs)` sends up to 1,000 runs in one request and refuses more before sending anything. A row that fails comes back in `results` with `ok: false`, so the call does not throw for it.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
const batch = await client.executeBatch([
|
|
118
|
+
{ program_id, route_id, registry_record_hash, payload_text: "first" },
|
|
119
|
+
{ program_id, route_id, registry_record_hash, payload_text: "second" },
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
for (const row of batch.results) {
|
|
123
|
+
console.log(row.index, row.ok, row.ok ? row.run_id : row.error);
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The client's timeout covers the whole batch, so raise `timeoutMs` for a large one. A batch is one POST and it is never retried. After a timeout the server may have run some or all of the rows, so list your runs before you send them again.
|
|
128
|
+
|
|
129
|
+
## Evidence export
|
|
130
|
+
|
|
131
|
+
`exportRuns` lists the runs the server holds for your key in a period, failures included, with up to 10,000 rows per export. `exportRunsCSV` returns the same rows as raw CSV text.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
const period = { from: "2026-11-01T00:00:00Z", to: "2026-12-01T00:00:00Z" };
|
|
135
|
+
|
|
136
|
+
const evidence = await client.exportRuns(period);
|
|
137
|
+
console.log(evidence.total, evidence.truncated, evidence.by_status);
|
|
138
|
+
|
|
139
|
+
const { csv, total, truncated } = await client.exportRunsCSV(period);
|
|
140
|
+
if (truncated) {
|
|
141
|
+
console.log(`The CSV holds part of ${total} runs. Use a narrower period.`);
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The export states what the server stored, not a verdict. A call that never reached Verdifax cannot appear in it. Both forms say when a period holds more rows than the export returned: check `truncated`. `exportRunsCSV` reads `total` and `truncated` from the `X-Verdifax-Total` and `X-Verdifax-Truncated` response headers, and throws if the server does not send them. In the CSV, a `route_id` that a spreadsheet could read as a formula gets a leading `'`.
|
|
146
|
+
|
|
147
|
+
## Provider helpers
|
|
148
|
+
|
|
149
|
+
`attestClaudeResponse` and `attestOpenAIResponse` attest a prompt and response as one payload: canonical JSON, exactly `{"prompt":...,"provider":...,"response":...}` with sorted keys and no extra whitespace, UTF-8, with `provider` set to `anthropic` or `openai`. `formatProviderPayload` builds that text. All four Verdifax SDKs produce the same bytes. A helper call from an earlier version used a different payload, so it gave a different hash for the same text; records already stored are not touched.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
await client.attestClaudeResponse({
|
|
153
|
+
program_id,
|
|
154
|
+
route_id,
|
|
155
|
+
registry_record_hash,
|
|
156
|
+
prompt: "What is the boiling point of water?",
|
|
157
|
+
response: "100 C at sea level.",
|
|
158
|
+
govern: true,
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`govern` is false by default, which changes earlier behavior. Set `govern: true` to also send the response text as `ai_output_text` for the AIVP review, which runs on Anthropic in production. Without it, the AI output text is not sent for review.
|
|
163
|
+
|
|
164
|
+
## Optional execute fields
|
|
165
|
+
|
|
166
|
+
`execute`, `attest`, `executeBatch` and `verifyDeterminism` accept `attested_context`, `reproducibility_context`, `request_substance`, `authorization_chain`, `regulatory_scaffolding` and `causal_graph`. Each is recorded as supplied and Verdifax does not check it. The client derives `attested` and `declared` from the fields you provide. Leave out `request_substance.origin.source_ip_hash` and `user_agent_hash`: the server computes them. `execute`, `attest` and `verifyDeterminism` refuse them before sending, and a batch row that sets them fails in `results`.
|
|
167
|
+
|
|
168
|
+
`execute`, `attest` and `verifyDeterminism` check that `program_id` and `registry_record_hash` are 64 lowercase hex characters and that `route_id` is 1 to 256 printable ASCII characters.
|
|
169
|
+
|
|
170
|
+
## Environment capture
|
|
171
|
+
|
|
172
|
+
`captureEnvironment()` records the Node version, the platform, the packages under `node_modules`, the git commit and any seeds you declare. Pass the result as `reproducibility_context` on `execute`, `attest`, `executeBatch` or `verifyDeterminism`. Detection is best effort, and a value it cannot read is left out. The server records these values as given and does not check them.
|
|
173
|
+
|
|
174
|
+
## Determinism check
|
|
175
|
+
|
|
176
|
+
`verifyDeterminism(req)` runs one payload twice on the server and compares the manifest hashes. `deterministic` is true when both runs ended `ok` and the two hashes match. Both runs are recorded, with the status `probe`.
|
|
63
177
|
|
|
64
178
|
## Authentication
|
|
65
179
|
|
|
@@ -117,7 +231,8 @@ const client = new VerdifaxClient({
|
|
|
117
231
|
|
|
118
232
|
await client.registerRequestKey(); // sends the public key with its proof
|
|
119
233
|
|
|
120
|
-
// execute, attest, attestClaudeResponse
|
|
234
|
+
// execute, attest, attestClaudeResponse, attestOpenAIResponse, executeBatch
|
|
235
|
+
// and verifyDeterminism now sign.
|
|
121
236
|
await client.execute({
|
|
122
237
|
program_id: "1111111111111111111111111111111111111111111111111111111111111111",
|
|
123
238
|
route_id: "demo-attestation",
|
|
@@ -130,6 +245,8 @@ await client.clearRequestKey(); // stops requiring signatures on this API key
|
|
|
130
245
|
|
|
131
246
|
Registering a key changes that API key for every client that uses it: the server then refuses a run without a valid signature, so every caller on the key needs the private key. Each request carries the time and a fresh random nonce. The server refuses a repeated nonce and a time more than five minutes from its own clock.
|
|
132
247
|
|
|
248
|
+
In a batch each row carries its own signature and nonce, and the server checks them as it reaches that row. A row refused for its signature comes back in `results`, so a repeated batch returns HTTP 200 with failed rows, and a row reached more than five minutes after it was signed fails the same way. A determinism check uses one signature for the request, and repeating it returns HTTP 403.
|
|
249
|
+
|
|
133
250
|
The signature shows the holder of the key requested the run. It does not show the key holder accepted the outcome.
|
|
134
251
|
|
|
135
252
|
## Trust model
|
package/dist/index.d.mts
CHANGED
|
@@ -48,11 +48,46 @@ interface ExecuteRequest {
|
|
|
48
48
|
registry_record_hash: Hex64;
|
|
49
49
|
/** When non-empty, opts the request into the AIVP governance pipeline. */
|
|
50
50
|
ai_output_text?: string;
|
|
51
|
-
/** Caller-attested actor + decision metadata; open schema.
|
|
51
|
+
/** Caller-attested actor + decision metadata; open schema. The client
|
|
52
|
+
* derives `attested` from whether any other field is provided. */
|
|
52
53
|
attested_context?: Record<string, unknown>;
|
|
54
|
+
/** Caller-declared runtime fingerprint, recorded in the audit bundle.
|
|
55
|
+
* Build it with {@link captureEnvironment}. */
|
|
56
|
+
reproducibility_context?: ReproducibilityContext;
|
|
57
|
+
/** Caller-supplied substance of the request: prompt, output, cost,
|
|
58
|
+
* latency and origin metadata. Recorded as supplied. Leave out
|
|
59
|
+
* `origin.source_ip_hash` and `origin.user_agent_hash`: the server
|
|
60
|
+
* computes those and refuses them. */
|
|
61
|
+
request_substance?: Record<string, unknown>;
|
|
62
|
+
/** Caller-supplied approval chain. Recorded as supplied, not verified
|
|
63
|
+
* by Verdifax. */
|
|
64
|
+
authorization_chain?: Record<string, unknown>;
|
|
65
|
+
/** Caller-supplied regulatory metadata. Recorded as supplied, not an
|
|
66
|
+
* assessment by Verdifax. */
|
|
67
|
+
regulatory_scaffolding?: Record<string, unknown>;
|
|
68
|
+
/** Caller-supplied record of what led to this run. Recorded as
|
|
69
|
+
* supplied. */
|
|
70
|
+
causal_graph?: Record<string, unknown>;
|
|
53
71
|
/** Filled in by the client when the `signingKey` option is set. */
|
|
54
72
|
request_signature?: RequestSignature;
|
|
55
73
|
}
|
|
74
|
+
/** The runtime a caller declares for a run. Every field is optional.
|
|
75
|
+
* The server records these values as given and does not check them. */
|
|
76
|
+
interface ReproducibilityContext {
|
|
77
|
+
/** True when any other field has a value. The client derives this. */
|
|
78
|
+
declared?: boolean;
|
|
79
|
+
/** 64 hex characters, without the `sha256:` prefix. */
|
|
80
|
+
container_image_hash?: string;
|
|
81
|
+
runtime_name?: string;
|
|
82
|
+
runtime_version?: string;
|
|
83
|
+
/** `name==version` strings, sorted. */
|
|
84
|
+
pinned_dependencies?: string[];
|
|
85
|
+
git_commit_sha?: string;
|
|
86
|
+
/** `library=seed` strings, sorted. */
|
|
87
|
+
random_seeds?: string[];
|
|
88
|
+
/** GOOS/GOARCH style, for example `linux/amd64`. */
|
|
89
|
+
platform?: string;
|
|
90
|
+
}
|
|
56
91
|
/** The signature an API key with a registered request key must carry.
|
|
57
92
|
* The public key comes from the registration, never from the request. */
|
|
58
93
|
interface RequestSignature {
|
|
@@ -88,6 +123,60 @@ interface ExecuteResponse {
|
|
|
88
123
|
manifest: ExecutionManifest;
|
|
89
124
|
duration_ms: number;
|
|
90
125
|
}
|
|
126
|
+
/** One row of {@link ExecuteBatchResponse}. A successful row has
|
|
127
|
+
* `manifest`. A failed row has `error`, and `error_stage` and a typed
|
|
128
|
+
* receipt when the pipeline halted. A row refused before it ran has
|
|
129
|
+
* no `run_id`. */
|
|
130
|
+
interface ExecuteBatchResult {
|
|
131
|
+
index: number;
|
|
132
|
+
ok: boolean;
|
|
133
|
+
run_id?: number;
|
|
134
|
+
manifest_hash?: Hex64;
|
|
135
|
+
manifest?: ExecutionManifest;
|
|
136
|
+
error?: string;
|
|
137
|
+
error_stage?: string;
|
|
138
|
+
duration_ms: number;
|
|
139
|
+
partial_manifest?: ExecutionManifest;
|
|
140
|
+
deny_receipt?: Record<string, unknown>;
|
|
141
|
+
ccv_halt_receipt?: Record<string, unknown>;
|
|
142
|
+
macc_halt_receipt?: Record<string, unknown>;
|
|
143
|
+
aivp_t4_halt_receipt?: Record<string, unknown>;
|
|
144
|
+
attestation_gap_receipt?: Record<string, unknown>;
|
|
145
|
+
}
|
|
146
|
+
/** Body returned by POST /execute/batch. */
|
|
147
|
+
interface ExecuteBatchResponse {
|
|
148
|
+
ok: boolean;
|
|
149
|
+
total: number;
|
|
150
|
+
successful: number;
|
|
151
|
+
failed: number;
|
|
152
|
+
duration_ms: number;
|
|
153
|
+
results: ExecuteBatchResult[];
|
|
154
|
+
}
|
|
155
|
+
/** One of the two runs of a determinism check. */
|
|
156
|
+
interface DeterminismRun {
|
|
157
|
+
run_id: number;
|
|
158
|
+
manifest_hash: string;
|
|
159
|
+
bundle_hash: string;
|
|
160
|
+
duration_ms: number;
|
|
161
|
+
status: string;
|
|
162
|
+
error?: string;
|
|
163
|
+
}
|
|
164
|
+
/** How the two runs of a determinism check compared. */
|
|
165
|
+
interface DeterminismDiff {
|
|
166
|
+
differs: boolean;
|
|
167
|
+
manifest_hash_differs: boolean;
|
|
168
|
+
bundle_hash_differs: boolean;
|
|
169
|
+
differing_fields?: string[];
|
|
170
|
+
}
|
|
171
|
+
/** Body returned by POST /execute/verify-determinism. `deterministic`
|
|
172
|
+
* means both runs ended ok with equal manifest hashes. */
|
|
173
|
+
interface VerifyDeterminismResponse {
|
|
174
|
+
ok: boolean;
|
|
175
|
+
deterministic: boolean;
|
|
176
|
+
first: DeterminismRun;
|
|
177
|
+
second: DeterminismRun;
|
|
178
|
+
diff: DeterminismDiff;
|
|
179
|
+
}
|
|
91
180
|
/**
|
|
92
181
|
* Sealed manifest. Field names match the orchestrator's Go-default
|
|
93
182
|
* JSON encoding (CapitalCamelCase).
|
|
@@ -121,6 +210,12 @@ interface ExecutionManifest {
|
|
|
121
210
|
LedgerProofHash?: Hex64;
|
|
122
211
|
LogEntryID?: string;
|
|
123
212
|
}
|
|
213
|
+
/** Every status the server gives a run. */
|
|
214
|
+
declare const RUN_STATUSES: readonly ["ok", "probe", "pepg_deny", "ccv_halt", "macc_halt", "aivp_t4_halt", "attestation_gap", "stage_error"];
|
|
215
|
+
/** A run's status: one of {@link RUN_STATUSES}, or a value a newer server
|
|
216
|
+
* adds. Written with `string & {}` so editors still offer the known
|
|
217
|
+
* values and any string can be compared. */
|
|
218
|
+
type RunStatus = (typeof RUN_STATUSES)[number] | (string & {});
|
|
124
219
|
interface Run {
|
|
125
220
|
ok: boolean;
|
|
126
221
|
id: number;
|
|
@@ -130,7 +225,7 @@ interface Run {
|
|
|
130
225
|
route_id: string;
|
|
131
226
|
manifest_hash: Hex64;
|
|
132
227
|
duration_ms: number;
|
|
133
|
-
status:
|
|
228
|
+
status: RunStatus;
|
|
134
229
|
error_stage?: string;
|
|
135
230
|
error_message?: string;
|
|
136
231
|
manifest: ExecutionManifest;
|
|
@@ -184,6 +279,11 @@ interface AttestRequest {
|
|
|
184
279
|
registry_record_hash: Hex64;
|
|
185
280
|
ai_output_text?: string;
|
|
186
281
|
attested_context?: Record<string, unknown>;
|
|
282
|
+
reproducibility_context?: ReproducibilityContext;
|
|
283
|
+
request_substance?: Record<string, unknown>;
|
|
284
|
+
authorization_chain?: Record<string, unknown>;
|
|
285
|
+
regulatory_scaffolding?: Record<string, unknown>;
|
|
286
|
+
causal_graph?: Record<string, unknown>;
|
|
187
287
|
}
|
|
188
288
|
/** Optional filters for {@link VerdifaxClient.listRuns}. */
|
|
189
289
|
interface ListRunsParams {
|
|
@@ -199,8 +299,94 @@ interface RunSummary {
|
|
|
199
299
|
program_id: Hex64;
|
|
200
300
|
route_id: string;
|
|
201
301
|
manifest_hash: Hex64;
|
|
202
|
-
status:
|
|
302
|
+
status: RunStatus;
|
|
203
303
|
outcome_kind?: string;
|
|
304
|
+
duration_ms?: number;
|
|
305
|
+
error_stage?: string;
|
|
306
|
+
execution_region?: string;
|
|
307
|
+
}
|
|
308
|
+
/** Optional filters for {@link VerdifaxClient.searchRuns}. `from` and
|
|
309
|
+
* `to` are RFC 3339 times. */
|
|
310
|
+
interface SearchRunsParams {
|
|
311
|
+
/** Matches manifest hashes that start with this value. */
|
|
312
|
+
manifest_hash?: string;
|
|
313
|
+
program_id?: Hex64;
|
|
314
|
+
route_id?: string;
|
|
315
|
+
status?: string;
|
|
316
|
+
from?: string;
|
|
317
|
+
to?: string;
|
|
318
|
+
limit?: number;
|
|
319
|
+
offset?: number;
|
|
320
|
+
}
|
|
321
|
+
/** Period for {@link VerdifaxClient.exportRuns} and
|
|
322
|
+
* {@link VerdifaxClient.exportRunsCSV}, as RFC 3339 times. `from` is
|
|
323
|
+
* inclusive and `to` is exclusive. `to` defaults to the time of the
|
|
324
|
+
* request. */
|
|
325
|
+
interface ExportRunsParams {
|
|
326
|
+
from?: string;
|
|
327
|
+
to?: string;
|
|
328
|
+
}
|
|
329
|
+
/** One run in an evidence export: what the server stored, not a verdict. */
|
|
330
|
+
interface ExportRow {
|
|
331
|
+
run_id: number;
|
|
332
|
+
created_at: string;
|
|
333
|
+
status: RunStatus;
|
|
334
|
+
error_stage: string;
|
|
335
|
+
route_id: string;
|
|
336
|
+
manifest_hash: string;
|
|
337
|
+
log_entry_id: string;
|
|
338
|
+
leaf_hash: string;
|
|
339
|
+
complete_record_entry_id: string;
|
|
340
|
+
complete_record_leaf_hash: string;
|
|
341
|
+
}
|
|
342
|
+
/** Body returned by GET /runs/export in JSON form. */
|
|
343
|
+
interface RunsExport {
|
|
344
|
+
ok: boolean;
|
|
345
|
+
/** The upper bound the server used for this export. */
|
|
346
|
+
to: string;
|
|
347
|
+
/** Runs held for the period. */
|
|
348
|
+
total: number;
|
|
349
|
+
/** Rows in this response. */
|
|
350
|
+
returned: number;
|
|
351
|
+
/** True when the period holds more rows than this response. */
|
|
352
|
+
truncated: boolean;
|
|
353
|
+
/** Rows returned, counted by status. */
|
|
354
|
+
by_status: Record<string, number>;
|
|
355
|
+
runs: ExportRow[];
|
|
356
|
+
}
|
|
357
|
+
/** Returned by {@link VerdifaxClient.exportRunsCSV}. */
|
|
358
|
+
interface RunsExportCSV {
|
|
359
|
+
/** The CSV text, unparsed. */
|
|
360
|
+
csv: string;
|
|
361
|
+
/** Runs held for the period. */
|
|
362
|
+
total: number;
|
|
363
|
+
/** True when the period holds more rows than `csv`. */
|
|
364
|
+
truncated: boolean;
|
|
365
|
+
}
|
|
366
|
+
/** Optional paging for {@link VerdifaxClient.listAttestations}. */
|
|
367
|
+
interface ListAttestationsParams {
|
|
368
|
+
limit?: number;
|
|
369
|
+
offset?: number;
|
|
370
|
+
}
|
|
371
|
+
/** Body returned by GET /attestations. Each row is a receipt as the
|
|
372
|
+
* server sends it, without its inclusion proof. */
|
|
373
|
+
interface AttestationList {
|
|
374
|
+
ok: boolean;
|
|
375
|
+
count: number;
|
|
376
|
+
limit: number;
|
|
377
|
+
offset: number;
|
|
378
|
+
attestations: Record<string, unknown>[];
|
|
379
|
+
}
|
|
380
|
+
/** Body returned by GET /stats. */
|
|
381
|
+
interface RunStats {
|
|
382
|
+
ok: boolean;
|
|
383
|
+
total_runs: number;
|
|
384
|
+
runs_today: number;
|
|
385
|
+
runs_last_24h: number;
|
|
386
|
+
pass_rate: number;
|
|
387
|
+
avg_duration_ms: number;
|
|
388
|
+
last_run_at: string;
|
|
389
|
+
runs_by_program: Record<string, number>;
|
|
204
390
|
}
|
|
205
391
|
/** Audit-PDF format selector. */
|
|
206
392
|
type PDFFormat = "brief" | "auditor" | "legal" | "comprehensive";
|
|
@@ -267,6 +453,8 @@ interface AdminAPIKey {
|
|
|
267
453
|
revoked: boolean;
|
|
268
454
|
}
|
|
269
455
|
|
|
456
|
+
/** The most rows POST /execute/batch accepts in one request. */
|
|
457
|
+
declare const MAX_BATCH_ROWS = 1000;
|
|
270
458
|
/**
|
|
271
459
|
* The Verdifax SDK client.
|
|
272
460
|
*
|
|
@@ -276,17 +464,32 @@ interface AdminAPIKey {
|
|
|
276
464
|
* | --- | --- | --- |
|
|
277
465
|
* | `health()` | GET /health | none |
|
|
278
466
|
* | `version()` | GET /version | none |
|
|
467
|
+
* | `getOpenAPI()` | GET /openapi.json | none |
|
|
468
|
+
* | `getStats()` | GET /stats | required |
|
|
279
469
|
* | `execute(req)` | POST /execute | required |
|
|
280
470
|
* | `attest(req)` | POST /execute (helper) | required |
|
|
281
471
|
* | `getRun(id)` | GET /runs/{id} | required |
|
|
282
472
|
* | `verifyRun(id)` | GET /runs/{id}/verify | required |
|
|
283
473
|
* | `listRuns(params)` | GET /runs | required |
|
|
474
|
+
* | `searchRuns(params)` | GET /runs/search | required |
|
|
475
|
+
* | `exportRuns(params)` | GET /runs/export | required |
|
|
476
|
+
* | `exportRunsCSV(params)` | GET /runs/export?format=csv | required |
|
|
477
|
+
* | `listAttestations(params)` | GET /attestations | required |
|
|
478
|
+
* | `getAttestation(id)` | GET /attestations/{id} | required |
|
|
479
|
+
* | `getRunArtifacts(id)` | GET /runs/{id}/artifacts | required |
|
|
480
|
+
* | `getRunReport(id)` | GET /runs/{id}/report | required |
|
|
481
|
+
* | `getPublicBundle(id)` | GET /runs/{id}/bundle.json | none |
|
|
482
|
+
* | `getPublicBundleByToken(token)` | GET /public/runs/{token}/bundle.json | none |
|
|
483
|
+
* | `executeBatch(runs)` | POST /execute/batch | required |
|
|
484
|
+
* | `verifyDeterminism(req)` | POST /execute/verify-determinism | required |
|
|
284
485
|
* | `downloadAuditPDF(id, format)` | GET /runs/{id}/report.pdf | required |
|
|
285
486
|
* | `getAllowToken(id)` | GET /runs/{id}/allow-token | required |
|
|
286
487
|
* | `getDenyReceipt(id)` | GET /runs/{id}/deny-receipt | required |
|
|
287
488
|
* | `getCCVHaltReceipt(id)` | GET /runs/{id}/ccv-halt-receipt | required |
|
|
288
489
|
* | `getMACCHaltReceipt(id)` | GET /runs/{id}/macc-halt-receipt | required |
|
|
289
490
|
* | `getAivpT4HaltReceipt(id)` | GET /runs/{id}/aivp-t4-halt-receipt | required |
|
|
491
|
+
* | `getAttestationGapReceipt(id)` | GET /runs/{id}/attestation-gap-receipt | required |
|
|
492
|
+
* | `getCESAuditRecord(id)` | GET /runs/{id}/ces-audit-record | required |
|
|
290
493
|
* | `listDeletionReceipts(id)` | GET /runs/{id}/deletion-receipts | required |
|
|
291
494
|
* | `adminErase(req)` | POST /admin/erase | required |
|
|
292
495
|
* | `dcaeVerify(bundle)` | POST /dcae/verify | none |
|
|
@@ -299,7 +502,8 @@ interface AdminAPIKey {
|
|
|
299
502
|
* | `clearRequestKey()` | DELETE /keys/request-key | required |
|
|
300
503
|
*
|
|
301
504
|
* With the `signingKey` option set, every path to POST /execute carries
|
|
302
|
-
* a fresh request signature
|
|
505
|
+
* a fresh request signature, each row of a batch carries its own, and a
|
|
506
|
+
* determinism check carries one. Without it, requests are unsigned.
|
|
303
507
|
*
|
|
304
508
|
* Idempotent GETs that hit a transient failure (502/503/504/429)
|
|
305
509
|
* are retried with exponential backoff + full jitter. Non-
|
|
@@ -317,7 +521,24 @@ declare class VerdifaxClient {
|
|
|
317
521
|
constructor(config?: ClientConfig);
|
|
318
522
|
health(): Promise<Health>;
|
|
319
523
|
version(): Promise<VerdifaxVersion>;
|
|
524
|
+
/** The server's own API description. */
|
|
525
|
+
getOpenAPI(): Promise<Record<string, unknown>>;
|
|
526
|
+
/** Run counts for this API key. */
|
|
527
|
+
getStats(): Promise<RunStats>;
|
|
320
528
|
execute(req: ExecuteRequest): Promise<ExecuteResponse>;
|
|
529
|
+
/** Runs one payload twice on the server and compares the manifest
|
|
530
|
+
* hashes. One signature covers the request, and the server claims
|
|
531
|
+
* its nonce once. Both runs are recorded. */
|
|
532
|
+
verifyDeterminism(req: ExecuteRequest): Promise<VerifyDeterminismResponse>;
|
|
533
|
+
/** Sends up to {@link MAX_BATCH_ROWS} runs in one request. With a
|
|
534
|
+
* signing key each row carries its own signature and nonce. A row
|
|
535
|
+
* that fails comes back in `results` with `ok: false`, so the call
|
|
536
|
+
* does not throw for it. The rows are not checked here: the server
|
|
537
|
+
* reports a bad row in that row's result.
|
|
538
|
+
*
|
|
539
|
+
* This is one POST and it is never retried. After a timeout the
|
|
540
|
+
* server may have run some or all of the rows. */
|
|
541
|
+
executeBatch(runs: ExecuteRequest[]): Promise<ExecuteBatchResponse>;
|
|
321
542
|
/** High-level convenience wrapper around `execute()`. Accepts
|
|
322
543
|
* either a Buffer (for binary payloads, auto-base64) or a
|
|
323
544
|
* string (for plain text). Validates the hex fields and
|
|
@@ -336,11 +557,47 @@ declare class VerdifaxClient {
|
|
|
336
557
|
runs: RunSummary[];
|
|
337
558
|
total: number;
|
|
338
559
|
}>;
|
|
560
|
+
/** Searches this key's runs. `manifest_hash` matches a prefix. The
|
|
561
|
+
* server ignores a `from` or `to` it cannot parse here, unlike
|
|
562
|
+
* {@link exportRuns}, which refuses one. */
|
|
563
|
+
searchRuns(params?: SearchRunsParams): Promise<{
|
|
564
|
+
runs: RunSummary[];
|
|
565
|
+
total: number;
|
|
566
|
+
}>;
|
|
567
|
+
/** Lists what the server holds for this key in a period, failures
|
|
568
|
+
* included, up to 10,000 rows. `truncated` is true when the period
|
|
569
|
+
* holds more. The list states what was stored, not a verdict, and a
|
|
570
|
+
* call that never reached Verdifax cannot appear in it. */
|
|
571
|
+
exportRuns(params?: ExportRunsParams): Promise<RunsExport>;
|
|
572
|
+
/** The same rows as {@link exportRuns}: the raw CSV text with `total`
|
|
573
|
+
* and `truncated` from the response headers. Check `truncated`: when
|
|
574
|
+
* true, the CSV is missing rows for the period. Throws when the server
|
|
575
|
+
* does not send those headers, so that a cut-off export cannot pass
|
|
576
|
+
* for a complete one. */
|
|
577
|
+
exportRunsCSV(params?: ExportRunsParams): Promise<RunsExportCSV>;
|
|
578
|
+
private exportPath;
|
|
579
|
+
listAttestations(params?: ListAttestationsParams): Promise<AttestationList>;
|
|
580
|
+
getAttestation(attestationId: number): Promise<Record<string, unknown>>;
|
|
339
581
|
getAllowToken(runId: number): Promise<Record<string, unknown>>;
|
|
340
582
|
getDenyReceipt(runId: number): Promise<Record<string, unknown>>;
|
|
341
583
|
getCCVHaltReceipt(runId: number): Promise<Record<string, unknown>>;
|
|
342
584
|
getMACCHaltReceipt(runId: number): Promise<Record<string, unknown>>;
|
|
343
585
|
getAivpT4HaltReceipt(runId: number): Promise<Record<string, unknown>>;
|
|
586
|
+
getAttestationGapReceipt(runId: number): Promise<Record<string, unknown>>;
|
|
587
|
+
getCESAuditRecord(runId: number): Promise<Record<string, unknown>>;
|
|
588
|
+
/** The audit report for a run, as JSON. */
|
|
589
|
+
getRunReport(runId: number): Promise<Record<string, unknown>>;
|
|
590
|
+
/** The run's sealed audit bundle as the exact JSON text the server
|
|
591
|
+
* sent, to save and check with `verdifax-verify`. It is not parsed:
|
|
592
|
+
* JSON.parse would round a number above 2^53 and the recomputed hash
|
|
593
|
+
* would stop matching. */
|
|
594
|
+
getRunArtifacts(runId: number): Promise<string>;
|
|
595
|
+
/** The public audit bundle of a record published by run id, as the
|
|
596
|
+
* exact JSON text the server sent. Needs no API key. */
|
|
597
|
+
getPublicBundle(runId: number): Promise<string>;
|
|
598
|
+
/** The public audit bundle a share token points to, as the exact JSON
|
|
599
|
+
* text the server sent. Needs no API key. */
|
|
600
|
+
getPublicBundleByToken(token: string): Promise<string>;
|
|
344
601
|
private getRunArtifact;
|
|
345
602
|
/** Streams the audit PDF bytes as a Buffer. Format defaults to
|
|
346
603
|
* "comprehensive" when not specified. */
|
|
@@ -351,27 +608,37 @@ declare class VerdifaxClient {
|
|
|
351
608
|
adminCreateKey(name: string): Promise<AdminCreateKeyResponse>;
|
|
352
609
|
adminListKeys(): Promise<AdminAPIKey[]>;
|
|
353
610
|
adminRevokeKey(keyId: number): Promise<void>;
|
|
354
|
-
/** Convenience for attesting an Anthropic Claude API response.
|
|
355
|
-
*
|
|
356
|
-
* by
|
|
611
|
+
/** Convenience for attesting an Anthropic Claude API response. With
|
|
612
|
+
* `govern: true` the response text also goes to the AIVP review as
|
|
613
|
+
* `ai_output_text`; that is off by default, so the text leaves your
|
|
614
|
+
* machine for review only when you ask. */
|
|
357
615
|
attestClaudeResponse(args: {
|
|
358
616
|
program_id: Hex64;
|
|
359
617
|
route_id: string;
|
|
360
618
|
registry_record_hash: Hex64;
|
|
361
619
|
prompt: string;
|
|
362
620
|
response: string;
|
|
621
|
+
govern?: boolean;
|
|
363
622
|
}): Promise<ExecuteResponse>;
|
|
364
|
-
/** Convenience for attesting an OpenAI API response.
|
|
623
|
+
/** Convenience for attesting an OpenAI API response. `govern` works as
|
|
624
|
+
* in {@link attestClaudeResponse}. */
|
|
365
625
|
attestOpenAIResponse(args: {
|
|
366
626
|
program_id: Hex64;
|
|
367
627
|
route_id: string;
|
|
368
628
|
registry_record_hash: Hex64;
|
|
369
629
|
prompt: string;
|
|
370
630
|
response: string;
|
|
631
|
+
govern?: boolean;
|
|
371
632
|
}): Promise<ExecuteResponse>;
|
|
372
633
|
private attestProviderResponse;
|
|
373
634
|
private request;
|
|
635
|
+
/** A GET whose body is kept as sent, retried like any other GET. */
|
|
636
|
+
private requestRaw;
|
|
374
637
|
private requireAPIKey;
|
|
638
|
+
private requireExecuteFields;
|
|
639
|
+
/** The request with its derived flags and, with a signing key, a fresh
|
|
640
|
+
* signature and nonce, on a copy. */
|
|
641
|
+
private prepared;
|
|
375
642
|
}
|
|
376
643
|
|
|
377
644
|
/**
|
|
@@ -380,7 +647,9 @@ declare class VerdifaxClient {
|
|
|
380
647
|
*
|
|
381
648
|
* Variables consumed (identical names across SDKs):
|
|
382
649
|
*
|
|
383
|
-
* VERDIFAX_BASE_URL base URL
|
|
650
|
+
* VERDIFAX_BASE_URL base URL, read first
|
|
651
|
+
* VERDIFAX_API_URL base URL, read when VERDIFAX_BASE_URL is unset
|
|
652
|
+
* (defaults to https://api.verdifax.com)
|
|
384
653
|
* VERDIFAX_API_KEY X-Verdifax-Key value
|
|
385
654
|
* VERDIFAX_TIMEOUT_MS per-request timeout in ms (defaults to 90000)
|
|
386
655
|
* VERDIFAX_USER_AGENT override the default User-Agent
|
|
@@ -389,6 +658,84 @@ declare class VerdifaxClient {
|
|
|
389
658
|
|
|
390
659
|
declare function fromEnv(): VerdifaxClient;
|
|
391
660
|
|
|
661
|
+
/**
|
|
662
|
+
* Best-effort detection of the running Node environment, for the
|
|
663
|
+
* `reproducibility_context` of a run. A value that cannot be read is
|
|
664
|
+
* left out, and the server records it as not declared.
|
|
665
|
+
*/
|
|
666
|
+
|
|
667
|
+
interface CaptureEnvironmentOptions {
|
|
668
|
+
/** Library name to seed value. Recorded as declared; the caller still
|
|
669
|
+
* has to apply the seeds. */
|
|
670
|
+
declaredSeeds?: Record<string, string | number>;
|
|
671
|
+
/** List the packages under `node_modules` in the working directory.
|
|
672
|
+
* Defaults to true. */
|
|
673
|
+
includeDependencies?: boolean;
|
|
674
|
+
/** Read the commit with `git rev-parse HEAD`. Defaults to true. */
|
|
675
|
+
includeGit?: boolean;
|
|
676
|
+
/** Read the container id from `/proc/self/cgroup` on Linux. Defaults
|
|
677
|
+
* to true. */
|
|
678
|
+
includeContainer?: boolean;
|
|
679
|
+
}
|
|
680
|
+
/** Auto-detects the running Node environment. */
|
|
681
|
+
declare function captureEnvironment(options?: CaptureEnvironmentOptions): ReproducibilityContext;
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* Request-body rules shared by every path to POST /execute.
|
|
685
|
+
*/
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* The payload the provider helpers attest: canonical JSON with sorted keys,
|
|
689
|
+
* no extra whitespace and UTF-8 text, exactly
|
|
690
|
+
* `{"prompt":...,"provider":...,"response":...}`. All four SDKs produce the
|
|
691
|
+
* same bytes, and a shared test vector holds them to it.
|
|
692
|
+
*
|
|
693
|
+
* Text with an unpaired surrogate has no UTF-8 form and is refused.
|
|
694
|
+
*/
|
|
695
|
+
declare function formatProviderPayload(provider: string, prompt: string, response: string): string;
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* The three canonical hash formulas from the Verdifax orchestrator, so a
|
|
699
|
+
* caller can recompute a DSE dispatch hash, a DCAE closure hash or a CRES
|
|
700
|
+
* receipt hash without calling the server.
|
|
701
|
+
*
|
|
702
|
+
* These match the Python SDK's `verdifax.section0` and pass its test
|
|
703
|
+
* vectors. Every hash is SHA-256 as 64 lowercase hex characters, over
|
|
704
|
+
* UTF-8 text.
|
|
705
|
+
*/
|
|
706
|
+
|
|
707
|
+
declare const DSE_FORMULA_VERSION = "dse.tcu.dispatch.v1";
|
|
708
|
+
declare const DCAE_PREIMAGE_VERSION = "verdifax.dcae.v1";
|
|
709
|
+
declare const CRES_PREIMAGE_VERSION = "verdifax.cres.v1";
|
|
710
|
+
declare const CRES_ENGINE_VERSION = "verdifax-cres/1.0.0";
|
|
711
|
+
/** The DSE formula joins its fields with a period. */
|
|
712
|
+
declare function dseDispatchHash(fields: {
|
|
713
|
+
envelope_id: string;
|
|
714
|
+
sequence_id: string;
|
|
715
|
+
program_id: Hex64;
|
|
716
|
+
registry_record_hash: Hex64;
|
|
717
|
+
}): Hex64;
|
|
718
|
+
/** The DCAE formula joins its fields with a pipe. */
|
|
719
|
+
declare function dcaeClosureHash(fields: {
|
|
720
|
+
manifest_hash: Hex64;
|
|
721
|
+
aer_hash: Hex64;
|
|
722
|
+
envelope_id: string;
|
|
723
|
+
zksp_binding_hash: Hex64;
|
|
724
|
+
formal_verifier_status: string;
|
|
725
|
+
}): Hex64;
|
|
726
|
+
/** The CRES formula joins its fields with a pipe. `engine_version`
|
|
727
|
+
* defaults to {@link CRES_ENGINE_VERSION}; pass another value only to
|
|
728
|
+
* recompute a receipt from an earlier engine. */
|
|
729
|
+
declare function cresReceiptHash(fields: {
|
|
730
|
+
envelope_id: string;
|
|
731
|
+
field_path: string;
|
|
732
|
+
deletion_clock: string;
|
|
733
|
+
actor_id: string;
|
|
734
|
+
ciphertext_hash_at_shred: Hex64;
|
|
735
|
+
dsar_reference: string;
|
|
736
|
+
engine_version?: string;
|
|
737
|
+
}): Hex64;
|
|
738
|
+
|
|
392
739
|
/**
|
|
393
740
|
* Optional customer request signing.
|
|
394
741
|
*
|
|
@@ -498,4 +845,4 @@ declare class APIKeyRequiredError extends VerdifaxError {
|
|
|
498
845
|
constructor();
|
|
499
846
|
}
|
|
500
847
|
|
|
501
|
-
export { APIError, APIKeyRequiredError, type AdminAPIKey, type AdminCreateKeyResponse, type AdminEraseRequest, type AttestRequest, AuthError, type ClientConfig, type DCAEProofBundle, type DCAEVerdict, type DeletionReceipt, type ExecuteRequest, type ExecuteResponse, type ExecutionManifest, type FormulaEra, type Health, type Hex64, type ListRunsParams, NotFoundError, type PDFFormat, type RequestKeyPair, type RequestKeyRegistration, type RequestKeyRegistrationBody, type RequestSignature, type Run, type RunSummary, VerdifaxClient, VerdifaxError, type VerdifaxVersion, type VerifyResponse, fromEnv, generateRequestKeyPair, requestKeyRegistrationBody, requestSignaturePreimage, signRequest, validateHex64, validateRouteId };
|
|
848
|
+
export { APIError, APIKeyRequiredError, type AdminAPIKey, type AdminCreateKeyResponse, type AdminEraseRequest, type AttestRequest, type AttestationList, AuthError, CRES_ENGINE_VERSION, CRES_PREIMAGE_VERSION, type ClientConfig, type DCAEProofBundle, type DCAEVerdict, DCAE_PREIMAGE_VERSION, DSE_FORMULA_VERSION, type DeletionReceipt, type DeterminismDiff, type DeterminismRun, type ExecuteBatchResponse, type ExecuteBatchResult, type ExecuteRequest, type ExecuteResponse, type ExecutionManifest, type ExportRow, type ExportRunsParams, type FormulaEra, type Health, type Hex64, type ListAttestationsParams, type ListRunsParams, MAX_BATCH_ROWS, NotFoundError, type PDFFormat, RUN_STATUSES, type ReproducibilityContext, type RequestKeyPair, type RequestKeyRegistration, type RequestKeyRegistrationBody, type RequestSignature, type Run, type RunStats, type RunStatus, type RunSummary, type RunsExport, type RunsExportCSV, type SearchRunsParams, VerdifaxClient, VerdifaxError, type VerdifaxVersion, type VerifyDeterminismResponse, type VerifyResponse, captureEnvironment, cresReceiptHash, dcaeClosureHash, dseDispatchHash, formatProviderPayload, fromEnv, generateRequestKeyPair, requestKeyRegistrationBody, requestSignaturePreimage, signRequest, validateHex64, validateRouteId };
|