@net-mesh/sdk 0.19.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/dist/deck.d.ts ADDED
@@ -0,0 +1,342 @@
1
+ /**
2
+ * Deck SDK — operator-side TypeScript wrapper.
3
+ *
4
+ * Sits on top of the napi-rs binding at `@net-mesh/core`. Adds:
5
+ *
6
+ * - {@link DeckSdkError} typed Error subclass that parses the
7
+ * substrate `<<deck-sdk-kind:KIND>>MSG` envelope.
8
+ * - Auto-JSON-parsing for `status()` and `snapshots()`.
9
+ * - `AsyncIterable<unknown>` (parsed `MeshOsSnapshot` JSON) / `AsyncIterable<StatusSummary>`
10
+ * wrappers over the raw `nextSnapshot()` / `nextSummary()`
11
+ * methods.
12
+ *
13
+ * Slice 1 ships client + admin (all 9 methods) + snapshot/status
14
+ * streams + operator identity. Audit / logs / failures land in
15
+ * slice 2; ICE in slice 3.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { MeshOsDaemonSdk } from '@net-mesh/sdk/meshos';
20
+ * import { DeckClient, OperatorIdentity } from '@net-mesh/sdk/deck';
21
+ *
22
+ * const sdk = await MeshOsDaemonSdk.start();
23
+ * const identity = OperatorIdentity.generate();
24
+ * const client = await DeckClient.fromMeshos(sdk, identity);
25
+ *
26
+ * const commit = await client.admin.enterMaintenance(0xABCDn, 600_000n);
27
+ * console.log(`committed at ${commit.commitId} kind=${commit.eventKind}`);
28
+ *
29
+ * for await (const snap of client.snapshots()) {
30
+ * // snap is a parsed object
31
+ * break;
32
+ * }
33
+ *
34
+ * await sdk.shutdown();
35
+ * ```
36
+ */
37
+ import { AdminCommands as NapiAdmin, AuditQuery as NapiAuditQuery, IceCommands as NapiIceCommands, IceProposal as NapiIceProposal, OperatorIdentity, OperatorRegistry as NapiOperatorRegistry, SimulatedIceProposal as NapiSimulatedIceProposal } from '@net-mesh/core';
38
+ import { MeshOsDaemonSdk, type MeshOsConfig } from './meshos.js';
39
+ export declare class DeckSdkError extends Error {
40
+ readonly kind: string;
41
+ constructor(kind: string, message: string);
42
+ static fromCaught(err: unknown): DeckSdkError | Error;
43
+ }
44
+ export { OperatorIdentity };
45
+ export interface ChainCommit {
46
+ commitId: bigint;
47
+ operatorId: bigint;
48
+ eventKind: string;
49
+ committedAtMs: bigint;
50
+ }
51
+ export interface PeerCounts {
52
+ healthy: number;
53
+ degraded: number;
54
+ unreachable: number;
55
+ unknown: number;
56
+ }
57
+ export interface DaemonCounts {
58
+ running: number;
59
+ starting: number;
60
+ stopping: number;
61
+ stopped: number;
62
+ backingOff: number;
63
+ crashLooping: number;
64
+ }
65
+ export interface StatusSummary {
66
+ peers: PeerCounts;
67
+ daemons: DaemonCounts;
68
+ replicaChains: number;
69
+ avoidListEntries: number;
70
+ recentlyEmittedCount: number;
71
+ recentFailureCount: number;
72
+ adminAuditRingDepth: number;
73
+ freezeRemainingMs: bigint | null;
74
+ localMaintenanceActive: boolean;
75
+ }
76
+ export interface DeckClientConfig {
77
+ snapshotPollIntervalMs?: bigint;
78
+ iceSignatureThreshold?: number;
79
+ }
80
+ export declare class AdminCommands {
81
+ private readonly raw;
82
+ constructor(raw: NapiAdmin);
83
+ drain(node: bigint, drainForMs: bigint): Promise<ChainCommit>;
84
+ enterMaintenance(node: bigint, drainForMs?: bigint | null): Promise<ChainCommit>;
85
+ exitMaintenance(node: bigint): Promise<ChainCommit>;
86
+ cordon(node: bigint): Promise<ChainCommit>;
87
+ uncordon(node: bigint): Promise<ChainCommit>;
88
+ dropReplicas(node: bigint, chains: bigint[]): Promise<ChainCommit>;
89
+ invalidatePlacement(node: bigint): Promise<ChainCommit>;
90
+ restartAllDaemons(node: bigint): Promise<ChainCommit>;
91
+ clearAvoidList(node: bigint): Promise<ChainCommit>;
92
+ }
93
+ export declare class DeckClient {
94
+ private readonly raw;
95
+ private constructor();
96
+ /**
97
+ * Construct a deck client that owns a private supervisor
98
+ * runtime. Mirrors the cdylib's `net_deck_client_new`
99
+ * (operator-only mode) for consumers without a separately-
100
+ * managed `MeshOsDaemonSdk`.
101
+ *
102
+ * `operatorSeed` must be exactly 32 bytes of ed25519 seed
103
+ * material. Call `.close()` (or use `await using`) to drain
104
+ * the supervisor at end of scope; otherwise the runtime
105
+ * releases on GC.
106
+ */
107
+ static new(operatorSeed: Buffer, meshosConfig?: MeshOsConfig, deckConfig?: DeckClientConfig): Promise<DeckClient>;
108
+ /**
109
+ * Construct against a running `MeshOsDaemonSdk`. Reuses the
110
+ * SDK's tokio runtime so streams + admin commits run on the
111
+ * same supervisor scheduler.
112
+ */
113
+ static fromMeshos(sdk: MeshOsDaemonSdk, identity: OperatorIdentity, config?: DeckClientConfig): Promise<DeckClient>;
114
+ /**
115
+ * Tear down the private supervisor runtime if this client owns
116
+ * one (constructed via `DeckClient.new`). No-op for clients
117
+ * built via `fromMeshos` against an externally-managed SDK.
118
+ * Idempotent: subsequent calls return without throwing.
119
+ */
120
+ close(): Promise<void>;
121
+ /**
122
+ * `await using` hook so `await using deck = await DeckClient.new(...)`
123
+ * drains the supervisor at scope exit.
124
+ */
125
+ [Symbol.asyncDispose](): Promise<void>;
126
+ /** Operator identity bound to this client. */
127
+ identity(): OperatorIdentity;
128
+ /** Typed admin-event surface. */
129
+ get admin(): AdminCommands;
130
+ /** Break-glass surface. Returns `IceCommands` whose factories
131
+ * produce `IceProposal`s. Each must be `.simulate()`-d
132
+ * (yielding a `SimulatedIceProposal`) before `.commit(...)`. */
133
+ get ice(): IceCommands;
134
+ /**
135
+ * One-shot read of the latest `MeshOsSnapshot` (parsed JSON;
136
+ * `unknown` because the substrate snapshot's exact shape isn't
137
+ * mirrored in the TS surface — consumers cast or use a runtime
138
+ * validator).
139
+ */
140
+ status(): unknown;
141
+ /** One-shot read of the rolled-up `StatusSummary`. */
142
+ statusSummary(): StatusSummary;
143
+ /**
144
+ * Live snapshot stream as `AsyncIterable<unknown>` (parsed `MeshOsSnapshot` JSON). JSON
145
+ * parsing happens automatically.
146
+ *
147
+ * Async on the napi side because the substrate creates a
148
+ * `tokio::time::Interval` that needs a runtime context.
149
+ */
150
+ snapshots(): Promise<AsyncIterable<unknown> & {
151
+ close: () => Promise<void>;
152
+ }>;
153
+ /** Live status-summary stream. */
154
+ statusSummaryStream(): Promise<AsyncIterable<StatusSummary> & {
155
+ close: () => Promise<void>;
156
+ }>;
157
+ /**
158
+ * Fluent admin-audit query builder. Chain `.recent(n)` /
159
+ * `.byOperator(id)` / `.between(start, end)` / `.forceOnly()` /
160
+ * `.since(seq)` before calling `.collect()` (eager list of
161
+ * parsed audit records) or `.stream()` (`AsyncIterable`).
162
+ */
163
+ audit(): AuditQuery;
164
+ /**
165
+ * Subscribe to the runtime's log ring. Returns an
166
+ * `AsyncIterable<LogRecord>`. Filter fields are all optional
167
+ * — missing fields match every record.
168
+ */
169
+ subscribeLogs(filter?: LogFilter): Promise<AsyncIterable<LogRecord> & {
170
+ close: () => Promise<void>;
171
+ }>;
172
+ /**
173
+ * Subscribe to the executor failure ring starting at
174
+ * `sinceSeq + 1`. Pass `0n` (or omit) to start from whatever
175
+ * is still in the ring.
176
+ */
177
+ subscribeFailures(sinceSeq?: bigint): Promise<AsyncIterable<FailureRecord> & {
178
+ close: () => Promise<void>;
179
+ }>;
180
+ }
181
+ export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error';
182
+ export interface LogFilter {
183
+ minLevel?: LogLevel;
184
+ daemonId?: bigint;
185
+ nodeId?: bigint;
186
+ sinceSeq?: bigint;
187
+ }
188
+ export interface LogRecord {
189
+ seq: bigint;
190
+ tsMs: bigint;
191
+ level: LogLevel;
192
+ daemonId: bigint | null;
193
+ nodeId: bigint | null;
194
+ message: string;
195
+ }
196
+ export interface FailureRecord {
197
+ seq: bigint;
198
+ source: string;
199
+ reason: string;
200
+ recordedAtMs: bigint;
201
+ }
202
+ export type AdminAuditRecord = Record<string, unknown>;
203
+ /**
204
+ * Fluent admin-audit query builder.
205
+ *
206
+ * @example
207
+ * ```ts
208
+ * const records = await client.audit()
209
+ * .recent(100)
210
+ * .byOperator(operatorId)
211
+ * .forceOnly()
212
+ * .collect();
213
+ *
214
+ * for await (const record of (await client.audit().since(lastSeq).stream())) {
215
+ * handle(record);
216
+ * }
217
+ * ```
218
+ */
219
+ export declare class AuditQuery {
220
+ private readonly raw;
221
+ constructor(raw: NapiAuditQuery);
222
+ recent(limit: number): AuditQuery;
223
+ byOperator(operatorId: bigint): AuditQuery;
224
+ between(startMs: bigint, endMs: bigint): AuditQuery;
225
+ forceOnly(): AuditQuery;
226
+ since(seq: bigint): AuditQuery;
227
+ /** Eager — returns a list of audit records (JSON-parsed into
228
+ * native objects). */
229
+ collect(): Promise<AdminAuditRecord[]>;
230
+ /** Async iterator over audit records. */
231
+ stream(): Promise<AsyncIterable<AdminAuditRecord> & {
232
+ close: () => Promise<void>;
233
+ }>;
234
+ }
235
+ /** Avoid-list flush scope discriminated union. */
236
+ export type AvoidScope = {
237
+ kind: 'global';
238
+ } | {
239
+ kind: 'local';
240
+ node: bigint;
241
+ } | {
242
+ kind: 'onPeer';
243
+ peer: bigint;
244
+ };
245
+ /** Signature pair carried by ICE commits. `signature` must be 64
246
+ * ed25519 bytes (the substrate verifier rejects malformed sigs
247
+ * with kind `signature_invalid`). */
248
+ export interface OperatorSignature {
249
+ operatorId: bigint;
250
+ signature: Buffer;
251
+ }
252
+ export type BlastRadius = Record<string, unknown>;
253
+ export declare class IceCommands {
254
+ private readonly raw;
255
+ constructor(raw: NapiIceCommands);
256
+ freezeCluster(ttlMs: bigint): IceProposal;
257
+ flushAvoidLists(scope: AvoidScope): IceProposal;
258
+ forceEvictReplica(chain: bigint, victim: bigint): IceProposal;
259
+ /** Propose force-restarting a daemon. `id` is the registry-
260
+ * local daemon id; `name` is `MeshDaemon::name()`. */
261
+ forceRestartDaemon(id: bigint, name: string): IceProposal;
262
+ forceCutover(chain: bigint, target: bigint): IceProposal;
263
+ killMigration(migration: bigint): IceProposal;
264
+ thawCluster(): IceProposal;
265
+ }
266
+ /** Pre-simulation ICE proposal. No `commit` method —
267
+ * `simulate()` must run first. */
268
+ export declare class IceProposal {
269
+ private readonly raw;
270
+ constructor(raw: NapiIceProposal);
271
+ get issuedAtMs(): bigint;
272
+ /** Pre-execution preview. Consumes the proposal — subsequent
273
+ * `simulate()` calls throw `DeckSdkError(kind: "already_simulated")`. */
274
+ simulate(): Promise<SimulatedIceProposal>;
275
+ }
276
+ /** A simulated ICE proposal. Only class exposing `commit`. */
277
+ export declare class SimulatedIceProposal {
278
+ private readonly raw;
279
+ constructor(raw: NapiSimulatedIceProposal);
280
+ get issuedAtMs(): bigint;
281
+ /** Pre-execution blast radius, parsed from the binding's JSON. */
282
+ blastRadius(): Promise<BlastRadius>;
283
+ /** Blake3 digest of the blast radius (32 bytes). */
284
+ blastHash(): Promise<Buffer>;
285
+ /** Commit with operator signatures. Consumes the proposal —
286
+ * subsequent calls throw `already_committed`. */
287
+ commit(signatures: OperatorSignature[]): Promise<ChainCommit>;
288
+ }
289
+ /** Cluster operator-policy registry. Authoring tool for the
290
+ * substrate's known-operator set; offline-friendly verifier for
291
+ * bundles before invoking
292
+ * {@link SimulatedIceProposal.commit}.
293
+ *
294
+ * Mutations are thread-safe at the napi binding layer. */
295
+ export declare class OperatorRegistry {
296
+ constructor(raw?: NapiOperatorRegistry);
297
+ /** Insert an operator's 32-byte ed25519 public key under
298
+ * `operatorId`. */
299
+ insert(operatorId: bigint, publicKey: Buffer): void;
300
+ /** Register an `OperatorIdentity`'s public key under its
301
+ * derived operator id. */
302
+ register(identity: OperatorIdentity): void;
303
+ /** `true` iff `operatorId` is registered. */
304
+ contains(operatorId: bigint): boolean;
305
+ /** Number of registered operators. */
306
+ get size(): number;
307
+ /** `true` iff no operators are registered. */
308
+ isEmpty(): boolean;
309
+ /** Verify a single signature over `payload`. Throws
310
+ * `DeckSdkError` with the substrate's stable kind discriminator
311
+ * (`not_authorized`, `signature_invalid`, etc.). */
312
+ verify(signature: OperatorSignature, payload: Buffer): void;
313
+ /** Verify every signature in the bundle and confirm at least
314
+ * `threshold` *distinct* operator ids signed `payload`. */
315
+ verifyBundle(signatures: OperatorSignature[], payload: Buffer, threshold: number): void;
316
+ }
317
+ /** Substrate-side admin commit verifier. Bundles an
318
+ * {@link OperatorRegistry} snapshot with the cluster's signature
319
+ * threshold + freshness/skew/ICE-cooldown windows. Useful for
320
+ * offline unit testing of operator-policy decisions.
321
+ *
322
+ * Constructors snapshot the registry at build time — later
323
+ * mutations on the source registry are not reflected. Rebuild
324
+ * the verifier after every policy change. */
325
+ export declare class AdminVerifier {
326
+ private readonly raw;
327
+ private constructor();
328
+ /** Build a verifier with `threshold` minimum signatures and
329
+ * the substrate defaults (300s freshness, 30s future-skew,
330
+ * 300s ICE cooldown). `threshold = 0` is clamped to `1`. */
331
+ static new(registry: OperatorRegistry, threshold: number): AdminVerifier;
332
+ /** Build with explicit freshness + future-skew windows and
333
+ * the default ICE cooldown. */
334
+ static withFreshness(registry: OperatorRegistry, threshold: number, freshnessWindowMs: bigint, futureSkewMs: bigint): AdminVerifier;
335
+ /** Build with every policy knob explicit. Primarily for tests
336
+ * that need a short cooldown window. */
337
+ static withFullPolicy(registry: OperatorRegistry, threshold: number, freshnessWindowMs: bigint, futureSkewMs: bigint, iceCooldownMs: bigint): AdminVerifier;
338
+ get threshold(): number;
339
+ get freshnessWindowMs(): bigint;
340
+ get futureSkewMs(): bigint;
341
+ get iceCooldownMs(): bigint;
342
+ }