burnledger 0.3.1 → 0.5.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 +15 -3
- package/dist/cjs/client.d.ts +14 -0
- package/dist/cjs/client.d.ts.map +1 -1
- package/dist/cjs/client.js +4 -0
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/errors.d.ts +28 -1
- package/dist/cjs/errors.d.ts.map +1 -1
- package/dist/cjs/errors.js +30 -2
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/http.d.ts +21 -1
- package/dist/cjs/http.d.ts.map +1 -1
- package/dist/cjs/http.js +76 -12
- package/dist/cjs/http.js.map +1 -1
- package/dist/cjs/index.browser.d.ts +2 -4
- package/dist/cjs/index.browser.d.ts.map +1 -1
- package/dist/cjs/index.browser.js.map +1 -1
- package/dist/cjs/index.d.ts +14 -7
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +13 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/keys.d.ts +6 -0
- package/dist/cjs/keys.d.ts.map +1 -1
- package/dist/cjs/keys.js.map +1 -1
- package/dist/cjs/models.d.ts +24 -4
- package/dist/cjs/models.d.ts.map +1 -1
- package/dist/cjs/models.js +10 -4
- package/dist/cjs/models.js.map +1 -1
- package/dist/cjs/pagination.d.ts.map +1 -1
- package/dist/cjs/pagination.js.map +1 -1
- package/dist/cjs/verify.d.ts +83 -5
- package/dist/cjs/verify.d.ts.map +1 -1
- package/dist/cjs/verify.js +359 -28
- package/dist/cjs/verify.js.map +1 -1
- package/dist/cjs/web-verifier.d.ts +10 -5
- package/dist/cjs/web-verifier.d.ts.map +1 -1
- package/dist/cjs/web-verifier.js +7 -3
- package/dist/cjs/web-verifier.js.map +1 -1
- package/dist/cjs/webhooks.js.map +1 -1
- package/dist/esm/cli.d.ts +6 -0
- package/dist/esm/cli.d.ts.map +1 -1
- package/dist/esm/cli.js +116 -15
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/client.d.ts +14 -0
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +4 -0
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/errors.d.ts +28 -1
- package/dist/esm/errors.d.ts.map +1 -1
- package/dist/esm/errors.js +29 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/http.d.ts +21 -1
- package/dist/esm/http.d.ts.map +1 -1
- package/dist/esm/http.js +75 -12
- package/dist/esm/http.js.map +1 -1
- package/dist/esm/index.browser.d.ts +2 -4
- package/dist/esm/index.browser.d.ts.map +1 -1
- package/dist/esm/index.browser.js.map +1 -1
- package/dist/esm/index.d.ts +14 -7
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +11 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/keys.d.ts +6 -0
- package/dist/esm/keys.d.ts.map +1 -1
- package/dist/esm/keys.js.map +1 -1
- package/dist/esm/models.d.ts +24 -4
- package/dist/esm/models.d.ts.map +1 -1
- package/dist/esm/models.js +10 -4
- package/dist/esm/models.js.map +1 -1
- package/dist/esm/pagination.d.ts.map +1 -1
- package/dist/esm/verify.d.ts +83 -5
- package/dist/esm/verify.d.ts.map +1 -1
- package/dist/esm/verify.js +357 -28
- package/dist/esm/verify.js.map +1 -1
- package/dist/esm/web-verifier.d.ts +10 -5
- package/dist/esm/web-verifier.d.ts.map +1 -1
- package/dist/esm/web-verifier.js +11 -3
- package/dist/esm/web-verifier.js.map +1 -1
- package/dist/esm/webhooks.js.map +1 -1
- package/package.json +5 -3
- package/src/cli.ts +123 -13
- package/src/client.ts +16 -0
- package/src/errors.ts +32 -2
- package/src/http.ts +79 -12
- package/src/index.browser.ts +2 -2
- package/src/index.ts +16 -4
- package/src/keys.ts +11 -1
- package/src/models.ts +34 -8
- package/src/verify.ts +428 -28
- package/src/web-verifier.ts +14 -5
package/src/http.ts
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
/** HTTP transport layer wrapping native fetch.
|
|
2
2
|
*
|
|
3
3
|
* Handles: Bearer auth, response envelope unwrapping, retry on 5xx/transport
|
|
4
|
-
* errors
|
|
4
|
+
* errors and on 429, and raw byte streaming for PDFs.
|
|
5
|
+
*
|
|
6
|
+
* Retry delay: a `Retry-After` header (delta-seconds or HTTP-date) is honoured
|
|
7
|
+
* when the server sends one and it is at most `MAX_RETRY_AFTER`; otherwise
|
|
8
|
+
* exponential backoff with jitter. A 429 with no usable `Retry-After`, one
|
|
9
|
+
* beyond the cap, or one on the last attempt throws `RateLimitError` with
|
|
10
|
+
* `retryAfter` populated so the caller can decide.
|
|
5
11
|
*/
|
|
6
12
|
|
|
7
13
|
import { raiseForError } from "./errors.js";
|
|
8
14
|
|
|
15
|
+
/** Longest Retry-After, in seconds, the transport will wait on before
|
|
16
|
+
* throwing instead: a server asking for minutes gets the error and the
|
|
17
|
+
* number rather than a promise nobody can cancel. */
|
|
18
|
+
export const MAX_RETRY_AFTER = 30;
|
|
19
|
+
|
|
9
20
|
export interface TransportOptions {
|
|
10
21
|
baseUrl: string;
|
|
11
22
|
apiKey: string;
|
|
12
23
|
timeout: number;
|
|
13
24
|
maxRetries: number;
|
|
25
|
+
/** Team to act as. Omit to let the API use the caller's default team. */
|
|
26
|
+
teamId?: string;
|
|
14
27
|
}
|
|
15
28
|
|
|
16
29
|
export class Transport {
|
|
@@ -18,12 +31,18 @@ export class Transport {
|
|
|
18
31
|
private readonly apiKey: string;
|
|
19
32
|
private readonly timeout: number;
|
|
20
33
|
private readonly maxRetries: number;
|
|
34
|
+
// Which team the caller is acting as. The API resolves scope from this
|
|
35
|
+
// header and otherwise falls back to the caller's default team, so a member
|
|
36
|
+
// of more than one team who does not send it silently acts as whichever they
|
|
37
|
+
// joined first.
|
|
38
|
+
private readonly teamId?: string;
|
|
21
39
|
|
|
22
40
|
constructor(opts: TransportOptions) {
|
|
23
41
|
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
24
42
|
this.apiKey = opts.apiKey;
|
|
25
43
|
this.timeout = opts.timeout;
|
|
26
44
|
this.maxRetries = opts.maxRetries;
|
|
45
|
+
this.teamId = opts.teamId;
|
|
27
46
|
}
|
|
28
47
|
|
|
29
48
|
/** Make a request and return the unwrapped `data` field. */
|
|
@@ -56,6 +75,12 @@ export class Transport {
|
|
|
56
75
|
};
|
|
57
76
|
if (authenticated) {
|
|
58
77
|
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
78
|
+
// Alongside the key, never without it: the header names the scope the
|
|
79
|
+
// caller is acting in, which is meaningless for an unauthenticated
|
|
80
|
+
// request and is not a second credential.
|
|
81
|
+
if (this.teamId) {
|
|
82
|
+
headers["X-Team-ID"] = this.teamId;
|
|
83
|
+
}
|
|
59
84
|
}
|
|
60
85
|
|
|
61
86
|
let url = `${this.baseUrl}${path}`;
|
|
@@ -80,14 +105,14 @@ export class Transport {
|
|
|
80
105
|
}
|
|
81
106
|
|
|
82
107
|
let lastError: Error | undefined;
|
|
108
|
+
// Delay before the next attempt when the server named one; undefined
|
|
109
|
+
// means fall back to backoff.
|
|
110
|
+
let retryAfter: number | undefined;
|
|
83
111
|
|
|
84
112
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
85
113
|
if (attempt > 0) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const base = 500 * 2 ** (attempt - 1);
|
|
89
|
-
const jitter = base * 0.25 * (Math.random() * 2 - 1);
|
|
90
|
-
await sleep(base + jitter);
|
|
114
|
+
await sleep(retryDelayMs(attempt, retryAfter));
|
|
115
|
+
retryAfter = undefined;
|
|
91
116
|
}
|
|
92
117
|
|
|
93
118
|
const controller = new AbortController();
|
|
@@ -116,8 +141,19 @@ export class Transport {
|
|
|
116
141
|
return {};
|
|
117
142
|
}
|
|
118
143
|
|
|
144
|
+
retryAfter = parseRetryAfter(resp);
|
|
119
145
|
if (resp.status === 429) {
|
|
120
|
-
|
|
146
|
+
// Only on the server's say-so: without Retry-After there is no delay
|
|
147
|
+
// known to be enough, and beyond the cap the caller gets the number
|
|
148
|
+
// (RateLimitError.retryAfter) rather than a hung promise.
|
|
149
|
+
if (
|
|
150
|
+
retryAfter !== undefined &&
|
|
151
|
+
retryAfter <= MAX_RETRY_AFTER &&
|
|
152
|
+
attempt < this.maxRetries
|
|
153
|
+
) {
|
|
154
|
+
lastError = new Error(`Server error ${resp.status}`);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
121
157
|
const errorBody = await safeJson(resp);
|
|
122
158
|
raiseForError(resp.status, errorBody, retryAfter);
|
|
123
159
|
}
|
|
@@ -150,6 +186,11 @@ export class Transport {
|
|
|
150
186
|
const headers: Record<string, string> = {};
|
|
151
187
|
if (authenticated) {
|
|
152
188
|
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
189
|
+
// A downloaded certificate is as team-scoped as the JSON one; omitting
|
|
190
|
+
// the header here would hand a member their default team's PDF.
|
|
191
|
+
if (this.teamId) {
|
|
192
|
+
headers["X-Team-ID"] = this.teamId;
|
|
193
|
+
}
|
|
153
194
|
}
|
|
154
195
|
|
|
155
196
|
const url = `${this.baseUrl}${path}`;
|
|
@@ -172,11 +213,37 @@ export class Transport {
|
|
|
172
213
|
}
|
|
173
214
|
}
|
|
174
215
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
216
|
+
/** Seconds to wait per the Retry-After header (RFC 9110 §10.2.3).
|
|
217
|
+
*
|
|
218
|
+
* Accepts both forms the header allows: non-negative delta-seconds and an
|
|
219
|
+
* HTTP-date, converted to seconds from now (a date already past reads as 0).
|
|
220
|
+
* Anything else is treated as absent.
|
|
221
|
+
*/
|
|
222
|
+
export function parseRetryAfter(resp: Response): number | undefined {
|
|
223
|
+
const raw = resp.headers.get("Retry-After")?.trim();
|
|
224
|
+
if (!raw) return undefined;
|
|
225
|
+
if (/^\d+(\.\d+)?$/.test(raw)) {
|
|
226
|
+
return Number(raw);
|
|
227
|
+
}
|
|
228
|
+
// Every HTTP-date form (IMF-fixdate, RFC 850, asctime) opens with a weekday
|
|
229
|
+
// name; Date.parse alone would also read "-3" or "2099" as a year.
|
|
230
|
+
if (!/^[A-Za-z]{3}/.test(raw)) return undefined;
|
|
231
|
+
const when = Date.parse(raw);
|
|
232
|
+
if (Number.isNaN(when)) return undefined;
|
|
233
|
+
return Math.max(0, (when - Date.now()) / 1000);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Milliseconds to sleep before retry `attempt` (1-based). A server-supplied
|
|
237
|
+
* delay within the cap wins; otherwise exponential backoff with ±25% jitter so
|
|
238
|
+
* coordinated 5xx events don't produce a synchronized retry storm from every
|
|
239
|
+
* client at the same instant. */
|
|
240
|
+
function retryDelayMs(attempt: number, retryAfter: number | undefined): number {
|
|
241
|
+
if (retryAfter !== undefined && retryAfter <= MAX_RETRY_AFTER) {
|
|
242
|
+
return retryAfter * 1000;
|
|
243
|
+
}
|
|
244
|
+
const base = Math.min(500 * 2 ** (attempt - 1), MAX_RETRY_AFTER * 1000);
|
|
245
|
+
const jitter = base * 0.25 * (Math.random() * 2 - 1);
|
|
246
|
+
return base + jitter;
|
|
180
247
|
}
|
|
181
248
|
|
|
182
249
|
async function safeJson(resp: Response): Promise<Record<string, unknown>> {
|
package/src/index.browser.ts
CHANGED
|
@@ -69,7 +69,7 @@ import {
|
|
|
69
69
|
verifyConsistency as _verifyConsistency,
|
|
70
70
|
publicKeyFromHex as _publicKeyFromHex,
|
|
71
71
|
} from "./verify.js";
|
|
72
|
-
import type { PublicKeyInfo } from "./verify.js";
|
|
72
|
+
import type { PublicKeyInfo, PublicKeyOptions } from "./verify.js";
|
|
73
73
|
import type { VerificationResult, TransparencyResult } from "./models.js";
|
|
74
74
|
|
|
75
75
|
type Cert = Record<string, unknown>;
|
|
@@ -93,7 +93,7 @@ export function verifyTransparency(
|
|
|
93
93
|
/** Construct a PublicKeyInfo from a hex-encoded Ed25519 public key. */
|
|
94
94
|
export function publicKeyFromHex(
|
|
95
95
|
hexKey: string,
|
|
96
|
-
opts?:
|
|
96
|
+
opts?: PublicKeyOptions,
|
|
97
97
|
): Promise<PublicKeyInfo> {
|
|
98
98
|
return _publicKeyFromHex(browserCrypto, hexKey, opts);
|
|
99
99
|
}
|
package/src/index.ts
CHANGED
|
@@ -14,11 +14,15 @@ export {
|
|
|
14
14
|
ServerError,
|
|
15
15
|
TimeoutError,
|
|
16
16
|
VerificationError,
|
|
17
|
+
CERTIFICATE_REVOKED,
|
|
18
|
+
UNSUPPORTED_FORMAT_VERSION,
|
|
17
19
|
} from "./errors.js";
|
|
18
20
|
|
|
19
21
|
export { Transport } from "./http.js";
|
|
20
22
|
export type { TransportOptions } from "./http.js";
|
|
21
23
|
|
|
24
|
+
export type { PublicKeyOptions } from "./verify.js";
|
|
25
|
+
|
|
22
26
|
export type {
|
|
23
27
|
ProofMode,
|
|
24
28
|
AttestationStatus,
|
|
@@ -76,7 +80,7 @@ import {
|
|
|
76
80
|
verifyConsistency as _verifyConsistency,
|
|
77
81
|
publicKeyFromHex as _publicKeyFromHex,
|
|
78
82
|
} from "./verify.js";
|
|
79
|
-
import type { PublicKeyInfo } from "./verify.js";
|
|
83
|
+
import type { PublicKeyInfo, PublicKeyOptions } from "./verify.js";
|
|
80
84
|
import type { VerificationResult, TransparencyResult } from "./models.js";
|
|
81
85
|
|
|
82
86
|
type Cert = Record<string, unknown>;
|
|
@@ -112,10 +116,18 @@ export function verifyTransparency(
|
|
|
112
116
|
return _verifyTransparency(nodeCrypto, certificate, publicKeys);
|
|
113
117
|
}
|
|
114
118
|
|
|
115
|
-
/** Construct a PublicKeyInfo from a hex-encoded Ed25519 public key.
|
|
119
|
+
/** Construct a PublicKeyInfo from a hex-encoded Ed25519 public key.
|
|
120
|
+
*
|
|
121
|
+
* The options mirror a published key entry from `/.well-known/burnledger-keys`.
|
|
122
|
+
* They were previously narrowed here to `{ revoked?: boolean }` while the
|
|
123
|
+
* implementation already accepted the ADR-017 fields — so a consumer could not
|
|
124
|
+
* express a compromised key or a validity interval through the public API at
|
|
125
|
+
* all, and every key they built looked unconditionally active. Widening only;
|
|
126
|
+
* `revoked` still works and still means "unusable".
|
|
127
|
+
*/
|
|
116
128
|
export function publicKeyFromHex(
|
|
117
129
|
hexKey: string,
|
|
118
|
-
opts?:
|
|
130
|
+
opts?: PublicKeyOptions,
|
|
119
131
|
): Promise<PublicKeyInfo> {
|
|
120
132
|
return _publicKeyFromHex(nodeCrypto, hexKey, opts);
|
|
121
133
|
}
|
|
@@ -131,4 +143,4 @@ export function verifyConsistency(
|
|
|
131
143
|
return _verifyConsistency(nodeCrypto, oldSize, newSize, oldRoot, newRoot, proof);
|
|
132
144
|
}
|
|
133
145
|
|
|
134
|
-
export { verifyWebhookSignature } from "./webhooks.js";
|
|
146
|
+
export { verifyWebhookSignature, isTimestampFresh } from "./webhooks.js";
|
package/src/keys.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
// Public-key file parsing shared by the CLI (and unit-testable in isolation).
|
|
2
2
|
|
|
3
|
-
export type KeyEntry = {
|
|
3
|
+
export type KeyEntry = {
|
|
4
|
+
key_id: string;
|
|
5
|
+
public_key: string;
|
|
6
|
+
key_status: string;
|
|
7
|
+
/** ADR-017 §1. Optional because key sets published before it carry none, and
|
|
8
|
+
* "no interval stated" is nothing to check rather than something the verifier
|
|
9
|
+
* failed to check. */
|
|
10
|
+
not_before?: string;
|
|
11
|
+
not_after?: string | null;
|
|
12
|
+
compromised_from?: string | null;
|
|
13
|
+
};
|
|
4
14
|
|
|
5
15
|
/**
|
|
6
16
|
* Normalize a parsed keys file to an array of key entries. Accepts a bare
|
package/src/models.ts
CHANGED
|
@@ -91,6 +91,8 @@ export interface System {
|
|
|
91
91
|
readonly connectorType: ConnectorType;
|
|
92
92
|
readonly subjectQuery: string;
|
|
93
93
|
readonly hashScope: HashScope;
|
|
94
|
+
/** Marked as holding PHI; changes the default proof mode to merkle. */
|
|
95
|
+
readonly phiInScope: boolean;
|
|
94
96
|
readonly maxRecords: number;
|
|
95
97
|
readonly maxBytes: number;
|
|
96
98
|
readonly queryTimeout: string;
|
|
@@ -144,6 +146,13 @@ export interface CertificateResponse {
|
|
|
144
146
|
readonly revokedAt: Date | undefined;
|
|
145
147
|
readonly revocationReason: string | undefined;
|
|
146
148
|
readonly certificate: Record<string, unknown>;
|
|
149
|
+
/**
|
|
150
|
+
* Raw enclave-signed status statement stapled by the server. Best-effort on
|
|
151
|
+
* the server side, so undefined when it could not be produced; GET
|
|
152
|
+
* /v1/certificates/{id}/status is the call that errors instead. Kept raw so
|
|
153
|
+
* it can be handed straight to verifyCertificateWithStatus().
|
|
154
|
+
*/
|
|
155
|
+
readonly statusStatement: Record<string, unknown> | undefined;
|
|
147
156
|
}
|
|
148
157
|
|
|
149
158
|
export interface RevocationStatus {
|
|
@@ -204,6 +213,9 @@ export interface Profile {
|
|
|
204
213
|
readonly id: string;
|
|
205
214
|
readonly name: string;
|
|
206
215
|
readonly email: string;
|
|
216
|
+
/** A new address waiting for the code mailed to it; `email` stays the
|
|
217
|
+
* current one until the change is confirmed from the dashboard. */
|
|
218
|
+
readonly pendingEmail: string | undefined;
|
|
207
219
|
readonly plan: string;
|
|
208
220
|
readonly planStartedAt: string | undefined;
|
|
209
221
|
readonly createdAt: string;
|
|
@@ -216,9 +228,9 @@ export interface Profile {
|
|
|
216
228
|
|
|
217
229
|
export interface SystemHealth {
|
|
218
230
|
readonly systemId: string;
|
|
219
|
-
readonly
|
|
220
|
-
readonly
|
|
221
|
-
readonly
|
|
231
|
+
readonly healthStatus: HealthStatus;
|
|
232
|
+
readonly healthCheckedAt: Date | undefined;
|
|
233
|
+
readonly healthError: string | undefined;
|
|
222
234
|
}
|
|
223
235
|
|
|
224
236
|
// ---------------------------------------------------------------------------
|
|
@@ -231,8 +243,14 @@ export interface BatchAttestationResponse {
|
|
|
231
243
|
}
|
|
232
244
|
|
|
233
245
|
export interface BatchAttestationError {
|
|
234
|
-
|
|
246
|
+
/** Position in the submitted subjectIdentifiers list. index is the durable
|
|
247
|
+
* key: subjectIdentifier is verbatim on the live response, but a replayed
|
|
248
|
+
* (Idempotency-Key) response carries a "sha256:<hex>" placeholder instead,
|
|
249
|
+
* because the cached copy never holds a raw identifier (PRIV-2). Do not key
|
|
250
|
+
* a retry on it after a replay. */
|
|
251
|
+
readonly index: number;
|
|
235
252
|
readonly error: string;
|
|
253
|
+
readonly subjectIdentifier: string;
|
|
236
254
|
}
|
|
237
255
|
|
|
238
256
|
// ---------------------------------------------------------------------------
|
|
@@ -264,6 +282,7 @@ export interface WebhookRotateResponse {
|
|
|
264
282
|
readonly id: string;
|
|
265
283
|
readonly url: string;
|
|
266
284
|
readonly newSecret: string;
|
|
285
|
+
readonly rotationExpiresAt: Date | undefined;
|
|
267
286
|
}
|
|
268
287
|
|
|
269
288
|
export interface WebhookDelivery {
|
|
@@ -272,6 +291,7 @@ export interface WebhookDelivery {
|
|
|
272
291
|
readonly eventType: string;
|
|
273
292
|
readonly errorMessage: string;
|
|
274
293
|
readonly attempts: number;
|
|
294
|
+
readonly nextAttemptAt: Date | undefined;
|
|
275
295
|
readonly createdAt: Date;
|
|
276
296
|
}
|
|
277
297
|
|
|
@@ -336,6 +356,7 @@ export function parseSystem(d: Raw): System {
|
|
|
336
356
|
// A server too old to record how the read-only guarantee was established
|
|
337
357
|
// has established nothing, so the absent field is "unknown" and never
|
|
338
358
|
// "verified_by_introspection".
|
|
359
|
+
phiInScope: d.phi_in_scope === true,
|
|
339
360
|
readOnlyEnforcement: (d.read_only_enforcement ?? "unknown") as ReadOnlyEnforcement,
|
|
340
361
|
};
|
|
341
362
|
}
|
|
@@ -393,6 +414,7 @@ export function parseCertificateResponse(d: Raw): CertificateResponse {
|
|
|
393
414
|
revokedAt: parseDtOpt(d.revoked_at),
|
|
394
415
|
revocationReason: d.revocation_reason ?? undefined,
|
|
395
416
|
certificate: d.certificate,
|
|
417
|
+
statusStatement: d.status_statement ?? undefined,
|
|
396
418
|
};
|
|
397
419
|
}
|
|
398
420
|
|
|
@@ -452,8 +474,9 @@ export function parseConsistencyProof(d: Raw): ConsistencyProof {
|
|
|
452
474
|
|
|
453
475
|
function parseBatchAttestationError(d: Raw): BatchAttestationError {
|
|
454
476
|
return {
|
|
455
|
-
|
|
477
|
+
index: d.index,
|
|
456
478
|
error: d.error,
|
|
479
|
+
subjectIdentifier: d.subject_identifier ?? "",
|
|
457
480
|
};
|
|
458
481
|
}
|
|
459
482
|
|
|
@@ -489,6 +512,7 @@ export function parseWebhookRotateResponse(d: Raw): WebhookRotateResponse {
|
|
|
489
512
|
id: d.id,
|
|
490
513
|
url: d.url,
|
|
491
514
|
newSecret: d.new_secret,
|
|
515
|
+
rotationExpiresAt: parseDtOpt(d.rotation_expires_at),
|
|
492
516
|
};
|
|
493
517
|
}
|
|
494
518
|
|
|
@@ -499,6 +523,7 @@ export function parseWebhookDelivery(d: Raw): WebhookDelivery {
|
|
|
499
523
|
eventType: d.event_type,
|
|
500
524
|
errorMessage: d.error_message,
|
|
501
525
|
attempts: d.attempts,
|
|
526
|
+
nextAttemptAt: parseDtOpt(d.next_attempt_at),
|
|
502
527
|
createdAt: parseDt(d.created_at),
|
|
503
528
|
};
|
|
504
529
|
}
|
|
@@ -541,6 +566,7 @@ export function parseProfile(d: Raw): Profile {
|
|
|
541
566
|
id: d.id,
|
|
542
567
|
name: d.name,
|
|
543
568
|
email: d.email,
|
|
569
|
+
pendingEmail: d.pending_email ?? undefined,
|
|
544
570
|
plan: d.plan,
|
|
545
571
|
planStartedAt: d.plan_started_at ?? undefined,
|
|
546
572
|
createdAt: d.created_at,
|
|
@@ -551,8 +577,8 @@ export function parseProfile(d: Raw): Profile {
|
|
|
551
577
|
export function parseSystemHealth(d: Raw): SystemHealth {
|
|
552
578
|
return {
|
|
553
579
|
systemId: d.system_id,
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
580
|
+
healthStatus: (d.health_status ?? "UNKNOWN") as HealthStatus,
|
|
581
|
+
healthCheckedAt: parseDtOpt(d.health_checked_at),
|
|
582
|
+
healthError: d.health_error ?? undefined,
|
|
557
583
|
};
|
|
558
584
|
}
|