@openzeppelin/guardian-operator-client 0.14.3 → 0.14.7
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 +319 -8
- package/dist/http.d.ts +158 -2
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +909 -11
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/permissions.d.ts +15 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +13 -0
- package/dist/permissions.js.map +1 -0
- package/dist/server-types.d.ts +35 -0
- package/dist/server-types.d.ts.map +1 -1
- package/dist/server-types.js +5 -1
- package/dist/server-types.js.map +1 -1
- package/dist/types.d.ts +403 -7
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,19 +42,196 @@ const verified = await client.verify({
|
|
|
42
42
|
console.log(verified.operatorId);
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
### List Accounts
|
|
45
|
+
### List Accounts (Paginated)
|
|
46
46
|
|
|
47
47
|
```typescript
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
console.log(
|
|
48
|
+
// Default page size is 50; max is 500.
|
|
49
|
+
const page = await client.listAccounts({ limit: 50 });
|
|
50
|
+
console.log(page.items[0]?.accountId);
|
|
51
|
+
|
|
52
|
+
// Resume the next page with the cursor from the previous response.
|
|
53
|
+
if (page.nextCursor !== null) {
|
|
54
|
+
const next = await client.listAccounts({
|
|
55
|
+
limit: 50,
|
|
56
|
+
cursor: page.nextCursor,
|
|
57
|
+
});
|
|
58
|
+
console.log(next.items.length);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Filter by pause state. Omit `paused` for all accounts.
|
|
62
|
+
const pausedOnly = await client.listAccounts({ paused: true });
|
|
63
|
+
const activeOnly = await client.listAccounts({ paused: false });
|
|
51
64
|
```
|
|
52
65
|
|
|
53
66
|
### Fetch One Account
|
|
54
67
|
|
|
68
|
+
`getAccount()` returns the bare `DashboardAccountDetail` — there is no
|
|
69
|
+
`{ success, account }` wrapper. Read fields directly on the response.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
const detail = await client.getAccount('0x...');
|
|
73
|
+
console.log(detail.authorizedSignerIds);
|
|
74
|
+
console.log(detail.currentCommitment, detail.stateUpdatedAt);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Decoded Account Snapshot
|
|
78
|
+
|
|
79
|
+
Returns the decoded state (vault contents, pending-candidate flag) at
|
|
80
|
+
the commitment Guardian last canonicalized for the account. Sourced
|
|
81
|
+
from Guardian's stored state — no live Miden RPC calls.
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
const snapshot = await client.getAccountSnapshot('0x...');
|
|
85
|
+
console.log(snapshot.commitment, snapshot.updatedAt);
|
|
86
|
+
if (snapshot.hasPendingCandidate) {
|
|
87
|
+
console.warn('vault may be stale — candidate delta in flight');
|
|
88
|
+
}
|
|
89
|
+
for (const asset of snapshot.vault.fungible) {
|
|
90
|
+
console.log(asset.faucetId, asset.amount);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Inventory And Health Snapshot
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const info = await client.getDashboardInfo();
|
|
98
|
+
console.log(info.totalAccountCount, info.environment);
|
|
99
|
+
console.log(info.deltaStatusCounts.candidate);
|
|
100
|
+
console.log(info.inFlightProposalCount);
|
|
101
|
+
if (info.serviceStatus === 'degraded') {
|
|
102
|
+
console.warn('degraded aggregates:', info.degradedAggregates);
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Per-Account Delta Feed
|
|
107
|
+
|
|
108
|
+
Each entry carries the dashboard-ready activity fields spread directly
|
|
109
|
+
at L1 (feature 007). `category` is the server-curated coarse
|
|
110
|
+
classification; `assets` (array) / `counterparty` / `noteCounts` are
|
|
111
|
+
derived from the on-chain `TransactionSummary`; `proposalType` echoes
|
|
112
|
+
the operator's intent label for multisig commits. All five fields are
|
|
113
|
+
optional — absent fields mean "not derivable from this row" (EVM
|
|
114
|
+
deltas, pre-feature-007 historical rows whose proposal was already
|
|
115
|
+
deleted, or undecodable payloads).
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
const page = await client.listAccountDeltas('0x...', { limit: 50 });
|
|
119
|
+
for (const entry of page.items) {
|
|
120
|
+
console.log(entry.nonce, entry.status, entry.statusTimestamp);
|
|
121
|
+
if (entry.category) {
|
|
122
|
+
console.log('category:', entry.category);
|
|
123
|
+
console.log('notes:', entry.noteCounts);
|
|
124
|
+
if (entry.proposalType) {
|
|
125
|
+
console.log('proposal type:', entry.proposalType);
|
|
126
|
+
}
|
|
127
|
+
if (entry.assets && entry.assets.length > 0) {
|
|
128
|
+
for (const a of entry.assets) {
|
|
129
|
+
console.log('asset:', a.assetId, a.amount);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
// No dashboard fields → render as "metadata unavailable", not as
|
|
134
|
+
// zero-valued defaults. Reasons listed above.
|
|
135
|
+
console.log('metadata unavailable');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
For the full structured projection of a single delta (decoded input /
|
|
141
|
+
output notes, vault changes, storage changes, plus the full
|
|
142
|
+
`proposal` intent block), call `getAccountDeltaDetail`:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const detail = await client.getAccountDeltaDetail('0x...', entry.nonce);
|
|
146
|
+
console.log('input notes:', detail.inputNotes.length);
|
|
147
|
+
console.log('vault changes:', detail.vaultChanges);
|
|
148
|
+
if (detail.proposal) {
|
|
149
|
+
console.log('proposal intent:', detail.proposal);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Debug: include the raw base64 TransactionSummary blob in the
|
|
153
|
+
// response so you can sanity-check the server's projection against
|
|
154
|
+
// the on-disk bytes.
|
|
155
|
+
const debug = await client.getAccountDeltaDetail('0x...', entry.nonce, {
|
|
156
|
+
includeRaw: true,
|
|
157
|
+
});
|
|
158
|
+
console.log('raw bytes (base64):', debug.rawTransactionSummary);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Per-Account In-Flight Proposals
|
|
162
|
+
|
|
163
|
+
Single-key Miden accounts and EVM accounts always return an empty
|
|
164
|
+
proposal queue.
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const page = await client.listAccountProposals('0x...', { limit: 50 });
|
|
168
|
+
for (const entry of page.items) {
|
|
169
|
+
console.log(
|
|
170
|
+
entry.commitment,
|
|
171
|
+
entry.signaturesCollected,
|
|
172
|
+
'/',
|
|
173
|
+
entry.signaturesRequired,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Pause / Unpause Account
|
|
179
|
+
|
|
180
|
+
Both endpoints require the `accounts:pause` permission and are
|
|
181
|
+
idempotent. Re-pausing an already-paused account returns success with
|
|
182
|
+
the original `pausedAt` and `pausedReason` preserved (first-writer
|
|
183
|
+
wins). `reason` is required on pause (non-empty, ≤ 512 chars) and
|
|
184
|
+
optional on unpause.
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
const paused = await client.pauseAccount('0x...', 'compliance review');
|
|
188
|
+
console.log(paused.pausedAt, paused.pausedReason);
|
|
189
|
+
|
|
190
|
+
await client.unpauseAccount('0x...', 'cleared by legal');
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
While an account is paused, mutating endpoints (delta submission,
|
|
194
|
+
proposal creation, proposal signing) reject with HTTP 409 and code
|
|
195
|
+
`account_paused` (normalized by the client from the server wire code
|
|
196
|
+
`GUARDIAN_ACCOUNT_PAUSED`). Account setup paths (`configureAccount`,
|
|
197
|
+
EVM register) are admin operations and remain available while paused.
|
|
198
|
+
Read endpoints — including `listAccounts({ paused: true })` and
|
|
199
|
+
`getAccount()` — continue to work and surface `pausedAt` /
|
|
200
|
+
`pausedReason` on the response.
|
|
201
|
+
|
|
202
|
+
### Cross-Account Delta Feed
|
|
203
|
+
|
|
204
|
+
Paginated newest-first by `status_timestamp DESC`. The optional
|
|
205
|
+
`status` filter accepts a single status or an array; the wrapper
|
|
206
|
+
serializes the array to a comma-separated query parameter.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
const page = await client.listGlobalDeltas({
|
|
210
|
+
limit: 50,
|
|
211
|
+
status: ['candidate', 'canonical'],
|
|
212
|
+
});
|
|
213
|
+
for (const entry of page.items) {
|
|
214
|
+
console.log(entry.accountId, entry.nonce, entry.status);
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Cross-Account In-Flight Proposal Feed
|
|
219
|
+
|
|
220
|
+
Paginated newest-first by `originating_timestamp DESC`. There is no
|
|
221
|
+
`status` filter — every entry is in-flight by definition. EVM accounts
|
|
222
|
+
do not appear in v1.
|
|
223
|
+
|
|
55
224
|
```typescript
|
|
56
|
-
const
|
|
57
|
-
|
|
225
|
+
const page = await client.listGlobalProposals({ limit: 50 });
|
|
226
|
+
for (const entry of page.items) {
|
|
227
|
+
console.log(
|
|
228
|
+
entry.accountId,
|
|
229
|
+
entry.commitment,
|
|
230
|
+
entry.signaturesCollected,
|
|
231
|
+
'/',
|
|
232
|
+
entry.signaturesRequired,
|
|
233
|
+
);
|
|
234
|
+
}
|
|
58
235
|
```
|
|
59
236
|
|
|
60
237
|
### Logout
|
|
@@ -63,6 +240,33 @@ console.log(response.account.authorizedSignerIds);
|
|
|
63
240
|
await client.logout();
|
|
64
241
|
```
|
|
65
242
|
|
|
243
|
+
## Pagination Shape
|
|
244
|
+
|
|
245
|
+
Every paginated dashboard endpoint returns a `PagedResult<T>` envelope:
|
|
246
|
+
|
|
247
|
+
```jsonc
|
|
248
|
+
{
|
|
249
|
+
"items": [ /* T entries */ ],
|
|
250
|
+
"next_cursor": "string | null" // null at end of list
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
- `limit` defaults to `50` and is capped at `500`. A bare `?limit=`
|
|
255
|
+
(present but empty) is treated as omitted; out-of-range values
|
|
256
|
+
return `400 invalid_limit`.
|
|
257
|
+
- `cursor` is opaque, server-signed, and tied to a specific endpoint
|
|
258
|
+
kind (e.g. an account-list cursor cannot be replayed on the
|
|
259
|
+
deltas endpoint). Tampered or stale cursors return
|
|
260
|
+
`400 invalid_cursor`. There is no client-visible TTL.
|
|
261
|
+
- A `cursor` may be supplied without a `limit`; the default of 50
|
|
262
|
+
applies.
|
|
263
|
+
- The account list endpoint sorts by `(updated_at DESC, account_id
|
|
264
|
+
ASC)`. Concurrent updates to `updated_at` MAY cause an account to
|
|
265
|
+
be skipped or repeated across a traversal — documented expected
|
|
266
|
+
behavior of cursor pagination over a mutable sort key. All other
|
|
267
|
+
paginated endpoints sort by an immutable per-account `nonce` (or
|
|
268
|
+
`(nonce, commitment)` for proposals) and are fully stable.
|
|
269
|
+
|
|
66
270
|
## Cookie Transport
|
|
67
271
|
|
|
68
272
|
The Guardian operator session is cookie-based. This package does not manage a
|
|
@@ -75,13 +279,36 @@ appropriate for your runtime.
|
|
|
75
279
|
import {
|
|
76
280
|
GuardianOperatorContractError,
|
|
77
281
|
GuardianOperatorHttpError,
|
|
282
|
+
isDashboardErrorCode,
|
|
78
283
|
} from '@openzeppelin/guardian-operator-client';
|
|
79
284
|
|
|
80
285
|
try {
|
|
81
|
-
await client.listAccounts();
|
|
286
|
+
await client.listAccounts({ limit: 9999 });
|
|
82
287
|
} catch (error) {
|
|
83
288
|
if (error instanceof GuardianOperatorHttpError) {
|
|
84
|
-
|
|
289
|
+
// Stable machine-readable code lives on `error.data.code`.
|
|
290
|
+
// Branch on it rather than on `error.status` or
|
|
291
|
+
// `error.data.error` (the human message).
|
|
292
|
+
const code = error.data?.code;
|
|
293
|
+
if (code && isDashboardErrorCode(code)) {
|
|
294
|
+
switch (code) {
|
|
295
|
+
case 'invalid_limit':
|
|
296
|
+
case 'invalid_cursor':
|
|
297
|
+
case 'invalid_status_filter':
|
|
298
|
+
// Caller bug — fix the request.
|
|
299
|
+
break;
|
|
300
|
+
case 'account_not_found':
|
|
301
|
+
// Path-addressed account does not exist.
|
|
302
|
+
break;
|
|
303
|
+
case 'data_unavailable':
|
|
304
|
+
// Metadata exists but storage cannot be read; retry later.
|
|
305
|
+
break;
|
|
306
|
+
case 'authentication_failed':
|
|
307
|
+
// Operator session is missing, tampered, or expired —
|
|
308
|
+
// re-issue the challenge / verify flow.
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
85
312
|
}
|
|
86
313
|
|
|
87
314
|
if (error instanceof GuardianOperatorContractError) {
|
|
@@ -89,3 +316,87 @@ try {
|
|
|
89
316
|
}
|
|
90
317
|
}
|
|
91
318
|
```
|
|
319
|
+
|
|
320
|
+
The dashboard error taxonomy (feature `005-operator-dashboard-metrics`
|
|
321
|
+
FR-028) is:
|
|
322
|
+
|
|
323
|
+
| HTTP | Body `code` | When |
|
|
324
|
+
|------|-------------|------|
|
|
325
|
+
| 401 | `authentication_failed` | missing / tampered / expired operator session |
|
|
326
|
+
| 403 | `GUARDIAN_INSUFFICIENT_OPERATOR_PERMISSION` | operator session is valid but lacks one or more route-required permissions (feature `006-operator-authz`) |
|
|
327
|
+
| 404 | `account_not_found` | path-addressed account does not exist |
|
|
328
|
+
| 400 | `invalid_cursor` | tampered, malformed, or stale cursor |
|
|
329
|
+
| 400 | `invalid_limit` | `limit` outside `[1, 500]` |
|
|
330
|
+
| 400 | `invalid_status_filter` | global delta feed `status` filter is unknown or malformed |
|
|
331
|
+
| 409 | `account_paused` | mutating call against a paused account; error details carry `pausedAt` and `pausedReason`. Wire code `GUARDIAN_ACCOUNT_PAUSED` is normalized by the client. |
|
|
332
|
+
| 503 | `data_unavailable` | metadata exists but underlying records cannot be read |
|
|
333
|
+
|
|
334
|
+
### Operator Authorization (feature `006-operator-authz`)
|
|
335
|
+
|
|
336
|
+
The dashboard now enforces per-operator permissions on every route. The
|
|
337
|
+
allowlist JSON consumed by `GUARDIAN_OPERATOR_PUBLIC_KEYS_JSON` /
|
|
338
|
+
`_FILE` / `_SECRET_ID` accepts a **heterogeneous** array of two element
|
|
339
|
+
shapes:
|
|
340
|
+
|
|
341
|
+
```jsonc
|
|
342
|
+
[
|
|
343
|
+
// Legacy element: bare hex string → `{dashboard:read}` only.
|
|
344
|
+
"0x094f145ec43583db3ca443f43a67545c...",
|
|
345
|
+
|
|
346
|
+
// Structured element: explicit permission set.
|
|
347
|
+
{
|
|
348
|
+
"public_key": "0x0944089753530e9104cc9fc4...",
|
|
349
|
+
"permissions": ["dashboard:read", "accounts:pause"]
|
|
350
|
+
},
|
|
351
|
+
|
|
352
|
+
// Explicit-deny element: loads, but denies every authorization
|
|
353
|
+
// check (different from omitting the operator entirely).
|
|
354
|
+
{
|
|
355
|
+
"public_key": "0x0a11...",
|
|
356
|
+
"permissions": []
|
|
357
|
+
}
|
|
358
|
+
]
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Recognized permissions in v1: `dashboard:read`, `accounts:pause`,
|
|
362
|
+
`policies:write`.
|
|
363
|
+
|
|
364
|
+
When the server denies a request for insufficient permissions, the
|
|
365
|
+
response body extends the existing flat envelope additively:
|
|
366
|
+
|
|
367
|
+
```json
|
|
368
|
+
{
|
|
369
|
+
"success": false,
|
|
370
|
+
"code": "GUARDIAN_INSUFFICIENT_OPERATOR_PERMISSION",
|
|
371
|
+
"error": "Operator lacks required permissions: accounts:pause",
|
|
372
|
+
"missing_permissions": ["accounts:pause"],
|
|
373
|
+
"retryable": false
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
`parseErrorBody` and the `GuardianOperatorHttpErrorData` shape both
|
|
378
|
+
expose `missingPermissions` and `retryable` for this code; the fields
|
|
379
|
+
are `undefined` for every other code.
|
|
380
|
+
|
|
381
|
+
For UI gating, call `getSession()` to read the authenticated
|
|
382
|
+
operator's live permission set and compare entries against the
|
|
383
|
+
exported wire-string constants:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
import {
|
|
387
|
+
ACCOUNTS_PAUSE,
|
|
388
|
+
DASHBOARD_READ,
|
|
389
|
+
GuardianOperatorHttpClient,
|
|
390
|
+
} from '@openzeppelin/guardian-operator-client';
|
|
391
|
+
|
|
392
|
+
const client = new GuardianOperatorHttpClient('https://guardian.example');
|
|
393
|
+
const { permissions } = await client.getSession();
|
|
394
|
+
|
|
395
|
+
const canPause = permissions.includes(ACCOUNTS_PAUSE);
|
|
396
|
+
const canRead = permissions.includes(DASHBOARD_READ);
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
The session endpoint re-reads permissions from the allowlist on every
|
|
400
|
+
call, so allowlist edits take effect without re-login. The server is
|
|
401
|
+
still the source of truth on every mutating endpoint — the client
|
|
402
|
+
MUST NOT short-circuit a request based on its own capability check.
|
package/dist/http.d.ts
CHANGED
|
@@ -1,4 +1,70 @@
|
|
|
1
|
-
import type { DashboardAccountResponse,
|
|
1
|
+
import type { DashboardAccountResponse, DashboardAccountSnapshot, DashboardAccountSummary, DashboardDeltaDetail, DashboardDeltaEntry, DashboardErrorCode, DashboardGlobalDeltaEntry, DashboardGlobalProposalEntry, DashboardInfoResponse, DashboardProposalEntry, GlobalDeltasOptions, DeltaDetailOptions, GuardianOperatorHttpClientOptions, GuardianOperatorHttpErrorData, LogoutOperatorResponse, OperatorChallengeResponse, PagedResult, PauseAccountResponse, SessionInfoResponse, UnpauseAccountResponse, VerifyOperatorRequest, VerifyOperatorResponse } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Common pagination query options for the new dashboard feeds
|
|
4
|
+
* endpoints. Spec reference: `005-operator-dashboard-metrics` FR-001.
|
|
5
|
+
*/
|
|
6
|
+
export interface PaginationOptions {
|
|
7
|
+
/** Page size; default 50 server-side, max 500. */
|
|
8
|
+
limit?: number;
|
|
9
|
+
/** Opaque cursor token from a prior page's `nextCursor`. */
|
|
10
|
+
cursor?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Options for {@link GuardianOperatorHttpClient.listAccounts}. Extends
|
|
14
|
+
* {@link PaginationOptions} with a tri-state pause filter: `true` for
|
|
15
|
+
* paused accounts only, `false` for active only, omitted for all.
|
|
16
|
+
*/
|
|
17
|
+
export interface ListAccountsOptions extends PaginationOptions {
|
|
18
|
+
paused?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Result of parsing an error response body. The {@link code} field is
|
|
22
|
+
* narrowed to {@link DashboardErrorCode} when the server emitted one of
|
|
23
|
+
* the dashboard error codes; otherwise it is forwarded as a raw string
|
|
24
|
+
* (or `null` if the body was missing/malformed).
|
|
25
|
+
*/
|
|
26
|
+
export interface ParsedErrorBody {
|
|
27
|
+
code: DashboardErrorCode | string | null;
|
|
28
|
+
message: string | null;
|
|
29
|
+
retryAfterSecs?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Populated only when `code === 'insufficient_operator_permission'`.
|
|
32
|
+
* Lists the permission strings the route required that the
|
|
33
|
+
* authenticated operator does not hold, lexicographically sorted by
|
|
34
|
+
* the server (feature 006-operator-authz FR-017).
|
|
35
|
+
*/
|
|
36
|
+
missingPermissions?: readonly string[];
|
|
37
|
+
/**
|
|
38
|
+
* `false` for permission denials and account-paused rejections;
|
|
39
|
+
* absent for every other code.
|
|
40
|
+
*/
|
|
41
|
+
retryable?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Populated only when `code === 'account_paused'`. RFC 3339 UTC
|
|
44
|
+
* timestamp of the original pause.
|
|
45
|
+
*/
|
|
46
|
+
pausedAt?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Populated only when `code === 'account_paused'`. May be `null`
|
|
49
|
+
* for forward compatibility (the v1 server always emits a
|
|
50
|
+
* non-null reason).
|
|
51
|
+
*/
|
|
52
|
+
pausedReason?: string | null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Parse an error response body into a typed `{ code, message }` shape.
|
|
56
|
+
* Clients SHOULD branch on `code` rather than on the HTTP status alone
|
|
57
|
+
* — see FR-028 of `005-operator-dashboard-metrics`.
|
|
58
|
+
*
|
|
59
|
+
* Accepts either a `Response` (fetch result) or a pre-read JSON body.
|
|
60
|
+
* Returns `{ code: null, message: null }` when the body is absent or
|
|
61
|
+
* malformed; never throws.
|
|
62
|
+
*/
|
|
63
|
+
export declare function parseErrorBody(response: Response | unknown): Promise<ParsedErrorBody>;
|
|
64
|
+
/**
|
|
65
|
+
* Type guard narrowing an arbitrary string to {@link DashboardErrorCode}.
|
|
66
|
+
*/
|
|
67
|
+
export declare function isDashboardErrorCode(value: string): value is DashboardErrorCode;
|
|
2
68
|
export declare class GuardianOperatorHttpError extends Error {
|
|
3
69
|
readonly status: number;
|
|
4
70
|
readonly statusText: string;
|
|
@@ -21,8 +87,98 @@ export declare class GuardianOperatorHttpClient {
|
|
|
21
87
|
challenge(commitment: string): Promise<OperatorChallengeResponse>;
|
|
22
88
|
verify(request: VerifyOperatorRequest): Promise<VerifyOperatorResponse>;
|
|
23
89
|
logout(): Promise<LogoutOperatorResponse>;
|
|
24
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Paginated account list per feature
|
|
92
|
+
* `005-operator-dashboard-metrics` US1 / FR-001..FR-008.
|
|
93
|
+
*
|
|
94
|
+
* **Breaking change vs. `003-operator-account-apis`**: the response
|
|
95
|
+
* is now a {@link PagedResult} envelope. The previous
|
|
96
|
+
* unparameterized full-inventory mode and `total_count` field are
|
|
97
|
+
* removed; aggregate inventory totals are exposed via
|
|
98
|
+
* {@link GuardianOperatorHttpClient.getDashboardInfo}. Callers that
|
|
99
|
+
* relied on `listAccounts()` must migrate to this method.
|
|
100
|
+
*/
|
|
101
|
+
listAccounts(options?: ListAccountsOptions): Promise<PagedResult<DashboardAccountSummary>>;
|
|
102
|
+
/**
|
|
103
|
+
* Return the authenticated operator's identity and effective
|
|
104
|
+
* permission set. Succeeds for any valid session, including
|
|
105
|
+
* operators with `permissions: []` (returns an empty array).
|
|
106
|
+
*/
|
|
107
|
+
getSession(): Promise<SessionInfoResponse>;
|
|
108
|
+
/**
|
|
109
|
+
* Inventory and lifecycle health snapshot per feature
|
|
110
|
+
* `005-operator-dashboard-metrics` US2 / FR-008..FR-012.
|
|
111
|
+
*/
|
|
112
|
+
getDashboardInfo(): Promise<DashboardInfoResponse>;
|
|
113
|
+
/**
|
|
114
|
+
* Pause mutating actions for the given account. Requires
|
|
115
|
+
* `accounts:pause`. Idempotent: re-pausing an already-paused account
|
|
116
|
+
* returns success with the original `pausedAt` preserved.
|
|
117
|
+
*/
|
|
118
|
+
pauseAccount(accountId: string, reason: string): Promise<PauseAccountResponse>;
|
|
119
|
+
/**
|
|
120
|
+
* Clear pause state for the given account. Requires `accounts:pause`.
|
|
121
|
+
* Idempotent: unpausing an already-active account returns success
|
|
122
|
+
* with no state change.
|
|
123
|
+
*/
|
|
124
|
+
unpauseAccount(accountId: string, reason?: string): Promise<UnpauseAccountResponse>;
|
|
25
125
|
getAccount(accountId: string): Promise<DashboardAccountResponse>;
|
|
126
|
+
/**
|
|
127
|
+
* Return a decoded snapshot of `accountId`'s stored state at the
|
|
128
|
+
* commitment Guardian last canonicalized — v1 surface exposes the
|
|
129
|
+
* fungible/non-fungible vault. The endpoint distinguishes its
|
|
130
|
+
* failure modes via the FR-045 error taxonomy:
|
|
131
|
+
*
|
|
132
|
+
* - `400 unsupported_for_network` — the account's `network_config`
|
|
133
|
+
* is EVM. The snapshot endpoint is Miden-only by construction;
|
|
134
|
+
* this is a permanent condition for the account on this surface,
|
|
135
|
+
* not a transient failure.
|
|
136
|
+
* - `404 account_not_found` — no metadata exists.
|
|
137
|
+
* - `503 account_data_unavailable` — metadata exists but the state
|
|
138
|
+
* row cannot be loaded, or the stored blob fails to deserialize
|
|
139
|
+
* as a Miden `Account`. Transient/recoverable.
|
|
140
|
+
*
|
|
141
|
+
* Spec reference: follow-up addition to `005-operator-dashboard-metrics`
|
|
142
|
+
* FR-043..FR-046.
|
|
143
|
+
*/
|
|
144
|
+
getAccountSnapshot(accountId: string): Promise<DashboardAccountSnapshot>;
|
|
145
|
+
/**
|
|
146
|
+
* List the per-account delta feed for `accountId`, paginated
|
|
147
|
+
* newest-first by `nonce DESC`. Spec reference:
|
|
148
|
+
* `005-operator-dashboard-metrics` US3.
|
|
149
|
+
*/
|
|
150
|
+
listAccountDeltas(accountId: string, options?: PaginationOptions): Promise<PagedResult<DashboardDeltaEntry>>;
|
|
151
|
+
/**
|
|
152
|
+
* Fetch the full detail projection of one canonical delta. The
|
|
153
|
+
* nonce is serialized as a canonical base-10 `u64` URL segment;
|
|
154
|
+
* unknown account and unknown nonce both surface as
|
|
155
|
+
* `404 delta_not_found`.
|
|
156
|
+
*/
|
|
157
|
+
getAccountDeltaDetail(accountId: string, nonce: number, options?: DeltaDetailOptions): Promise<DashboardDeltaDetail>;
|
|
158
|
+
/**
|
|
159
|
+
* List the per-account in-flight multisig proposal queue for
|
|
160
|
+
* `accountId`, paginated newest-first by `(nonce DESC, commitment
|
|
161
|
+
* DESC)`. Single-key Miden and EVM accounts always return an empty
|
|
162
|
+
* page per FR-017. Spec reference:
|
|
163
|
+
* `005-operator-dashboard-metrics` US4.
|
|
164
|
+
*/
|
|
165
|
+
listAccountProposals(accountId: string, options?: PaginationOptions): Promise<PagedResult<DashboardProposalEntry>>;
|
|
166
|
+
/**
|
|
167
|
+
* Cross-account delta feed. Paginated newest-first by
|
|
168
|
+
* `status_timestamp DESC`. The optional `status` filter accepts a
|
|
169
|
+
* single status or an array; the wrapper serializes the array to
|
|
170
|
+
* comma-separated. Spec reference:
|
|
171
|
+
* `005-operator-dashboard-metrics` US6.
|
|
172
|
+
*/
|
|
173
|
+
listGlobalDeltas(options?: GlobalDeltasOptions): Promise<PagedResult<DashboardGlobalDeltaEntry>>;
|
|
174
|
+
/**
|
|
175
|
+
* Cross-account in-flight proposal feed. Paginated newest-first by
|
|
176
|
+
* `originating_timestamp DESC`. Takes no `status` filter — every
|
|
177
|
+
* entry is in-flight by definition. EVM accounts do not appear in
|
|
178
|
+
* v1 per FR-017. Spec reference:
|
|
179
|
+
* `005-operator-dashboard-metrics` US7.
|
|
180
|
+
*/
|
|
181
|
+
listGlobalProposals(options?: PaginationOptions): Promise<PagedResult<DashboardGlobalProposalEntry>>;
|
|
26
182
|
private request;
|
|
27
183
|
private toHttpError;
|
|
28
184
|
}
|
package/dist/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|