browsermesh-kernel 0.1.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/LICENSE +21 -0
- package/README.md +59 -0
- package/package.json +25 -0
- package/src/byte-stream.mjs +258 -0
- package/src/caps.mjs +102 -0
- package/src/chaos.mjs +151 -0
- package/src/clock.mjs +80 -0
- package/src/constants.mjs +85 -0
- package/src/env.mjs +56 -0
- package/src/errors.mjs +148 -0
- package/src/index.d.ts +826 -0
- package/src/index.mjs +73 -0
- package/src/kernel.mjs +155 -0
- package/src/logger.mjs +182 -0
- package/src/message-port.mjs +93 -0
- package/src/resource-table.mjs +164 -0
- package/src/rng.mjs +76 -0
- package/src/service-registry.mjs +167 -0
- package/src/signal.mjs +122 -0
- package/src/stdio.mjs +62 -0
- package/src/tracer.mjs +117 -0
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,826 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kernel — Capability-secure browser microkernel.
|
|
3
|
+
*
|
|
4
|
+
* Provides resource handles, ByteStreams, IPC, service mesh, structured
|
|
5
|
+
* tracing, chaos engineering, and tenant isolation — all with zero npm
|
|
6
|
+
* dependencies, pure ES modules.
|
|
7
|
+
*
|
|
8
|
+
* @module kernel
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// ── Constants ────────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
/** Default configuration values used across the kernel. */
|
|
14
|
+
export declare const KERNEL_DEFAULTS: Readonly<{
|
|
15
|
+
/** Maximum entries in a ResourceTable. */
|
|
16
|
+
MAX_RESOURCE_TABLE_SIZE: 4096;
|
|
17
|
+
/** Default highWaterMark for ByteStream pipes. */
|
|
18
|
+
DEFAULT_STREAM_BUFFER_SIZE: 1024;
|
|
19
|
+
/** Default ring buffer size for Tracer events. */
|
|
20
|
+
DEFAULT_TRACER_CAPACITY: 1024;
|
|
21
|
+
/** Default ring buffer size for Logger entries. */
|
|
22
|
+
DEFAULT_LOGGER_CAPACITY: 1024;
|
|
23
|
+
}>;
|
|
24
|
+
|
|
25
|
+
/** Capability tags for tenant access control. */
|
|
26
|
+
export declare const KERNEL_CAP: Readonly<{
|
|
27
|
+
/** Access to networking subsystems. */
|
|
28
|
+
NET: 'net';
|
|
29
|
+
/** Access to filesystem operations. */
|
|
30
|
+
FS: 'fs';
|
|
31
|
+
/** Access to clock/time primitives. */
|
|
32
|
+
CLOCK: 'clock';
|
|
33
|
+
/** Access to random number generation. */
|
|
34
|
+
RNG: 'rng';
|
|
35
|
+
/** Access to inter-process communication. */
|
|
36
|
+
IPC: 'ipc';
|
|
37
|
+
/** Access to standard I/O streams. */
|
|
38
|
+
STDIO: 'stdio';
|
|
39
|
+
/** Access to the tracing subsystem. */
|
|
40
|
+
TRACE: 'trace';
|
|
41
|
+
/** Access to chaos engineering controls. */
|
|
42
|
+
CHAOS: 'chaos';
|
|
43
|
+
/** Access to environment variables. */
|
|
44
|
+
ENV: 'env';
|
|
45
|
+
/** Access to signal handling. */
|
|
46
|
+
SIGNAL: 'signal';
|
|
47
|
+
/** Access to mesh networking and P2P operations. */
|
|
48
|
+
MESH: 'mesh';
|
|
49
|
+
/** Access to payment channels and credit ledgers. */
|
|
50
|
+
PAYMENT: 'payment';
|
|
51
|
+
/** Access to voting and consensus protocols. */
|
|
52
|
+
CONSENSUS: 'consensus';
|
|
53
|
+
/** Wildcard granting all capabilities. */
|
|
54
|
+
ALL: '*';
|
|
55
|
+
}>;
|
|
56
|
+
|
|
57
|
+
/** Union of all valid KERNEL_CAP values. */
|
|
58
|
+
export type KernelCapTag =
|
|
59
|
+
| 'net' | 'fs' | 'clock' | 'rng' | 'ipc'
|
|
60
|
+
| 'stdio' | 'trace' | 'chaos' | 'env' | 'signal'
|
|
61
|
+
| 'mesh' | 'payment' | 'consensus' | '*';
|
|
62
|
+
|
|
63
|
+
/** Machine-readable error codes used by kernel error classes. */
|
|
64
|
+
export declare const KERNEL_ERROR: Readonly<{
|
|
65
|
+
/** Resource handle not found in table. */
|
|
66
|
+
ENOHANDLE: 'ENOHANDLE';
|
|
67
|
+
/** Resource handle exists but type mismatch. */
|
|
68
|
+
EHANDLETYPE: 'EHANDLETYPE';
|
|
69
|
+
/** Resource table at maximum capacity. */
|
|
70
|
+
ETABLEFULL: 'ETABLEFULL';
|
|
71
|
+
/** Operation on a closed ByteStream. */
|
|
72
|
+
ESTREAMCLOSED: 'ESTREAMCLOSED';
|
|
73
|
+
/** Capability not granted to tenant. */
|
|
74
|
+
ECAPDENIED: 'ECAPDENIED';
|
|
75
|
+
/** Name or resource already registered. */
|
|
76
|
+
EALREADY: 'EALREADY';
|
|
77
|
+
/** Named resource not found. */
|
|
78
|
+
ENOTFOUND: 'ENOTFOUND';
|
|
79
|
+
/** Operation interrupted by signal. */
|
|
80
|
+
ESIGNAL: 'ESIGNAL';
|
|
81
|
+
}>;
|
|
82
|
+
|
|
83
|
+
/** Union of all valid KERNEL_ERROR codes. */
|
|
84
|
+
export type KernelErrorCode =
|
|
85
|
+
| 'ENOHANDLE' | 'EHANDLETYPE' | 'ETABLEFULL' | 'ESTREAMCLOSED'
|
|
86
|
+
| 'ECAPDENIED' | 'EALREADY' | 'ENOTFOUND' | 'ESIGNAL';
|
|
87
|
+
|
|
88
|
+
// ── Errors ───────────────────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
/** Base error class for all kernel errors. */
|
|
91
|
+
export declare class KernelError extends Error {
|
|
92
|
+
/** Machine-readable error code. */
|
|
93
|
+
readonly code: KernelErrorCode;
|
|
94
|
+
constructor(message: string, code: string);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Thrown when a resource handle is not found in the ResourceTable. */
|
|
98
|
+
export declare class HandleNotFoundError extends KernelError {
|
|
99
|
+
/** The handle that was not found. */
|
|
100
|
+
readonly handle: string;
|
|
101
|
+
readonly code: 'ENOHANDLE';
|
|
102
|
+
constructor(handle: string);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Thrown when a resource handle exists but its type does not match the expected type. */
|
|
106
|
+
export declare class HandleTypeMismatchError extends KernelError {
|
|
107
|
+
/** The handle that was accessed. */
|
|
108
|
+
readonly handle: string;
|
|
109
|
+
/** The expected resource type. */
|
|
110
|
+
readonly expected: string;
|
|
111
|
+
/** The actual resource type. */
|
|
112
|
+
readonly actual: string;
|
|
113
|
+
readonly code: 'EHANDLETYPE';
|
|
114
|
+
constructor(handle: string, expected: string, actual: string);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Thrown when the ResourceTable has reached its maximum capacity. */
|
|
118
|
+
export declare class TableFullError extends KernelError {
|
|
119
|
+
/** The table's maximum capacity. */
|
|
120
|
+
readonly maxSize: number;
|
|
121
|
+
readonly code: 'ETABLEFULL';
|
|
122
|
+
constructor(maxSize: number);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Thrown when attempting to operate on a closed ByteStream. */
|
|
126
|
+
export declare class StreamClosedError extends KernelError {
|
|
127
|
+
readonly code: 'ESTREAMCLOSED';
|
|
128
|
+
constructor();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Thrown when a tenant lacks the required capability for an operation. */
|
|
132
|
+
export declare class CapabilityDeniedError extends KernelError {
|
|
133
|
+
/** The capability that was required but not granted. */
|
|
134
|
+
readonly capability: string;
|
|
135
|
+
readonly code: 'ECAPDENIED';
|
|
136
|
+
constructor(capability: string);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Thrown when attempting to register a name or resource that already exists. */
|
|
140
|
+
export declare class AlreadyRegisteredError extends KernelError {
|
|
141
|
+
/** The name that was already registered. */
|
|
142
|
+
readonly identifier: string;
|
|
143
|
+
readonly code: 'EALREADY';
|
|
144
|
+
constructor(identifier: string);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Thrown when a named resource is not found in a registry or lookup. */
|
|
148
|
+
export declare class NotFoundError extends KernelError {
|
|
149
|
+
/** The name that was not found. */
|
|
150
|
+
readonly identifier: string;
|
|
151
|
+
readonly code: 'ENOTFOUND';
|
|
152
|
+
constructor(identifier: string);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ── ResourceTable ────────────────────────────────────────────────────
|
|
156
|
+
|
|
157
|
+
/** An entry stored in the ResourceTable. */
|
|
158
|
+
export interface ResourceEntry {
|
|
159
|
+
type: string;
|
|
160
|
+
value: unknown;
|
|
161
|
+
owner: string;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Options for the ResourceTable constructor. */
|
|
165
|
+
export interface ResourceTableOptions {
|
|
166
|
+
/** Maximum number of entries. Defaults to 4096. */
|
|
167
|
+
maxSize?: number;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** A bounded, handle-keyed resource table with ownership tracking. */
|
|
171
|
+
export declare class ResourceTable {
|
|
172
|
+
constructor(opts?: ResourceTableOptions);
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Allocate a new handle for a resource.
|
|
176
|
+
* @returns The allocated handle (e.g. `'res_1'`).
|
|
177
|
+
* @throws {TableFullError} If the table is at maximum capacity.
|
|
178
|
+
*/
|
|
179
|
+
allocate(type: string, value: unknown, owner: string): string;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Get a resource entry by handle.
|
|
183
|
+
* @throws {HandleNotFoundError} If the handle does not exist.
|
|
184
|
+
*/
|
|
185
|
+
get(handle: string): ResourceEntry;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Get a resource value by handle, verifying the expected type.
|
|
189
|
+
* @throws {HandleNotFoundError} If the handle does not exist.
|
|
190
|
+
* @throws {HandleTypeMismatchError} If the resource type does not match.
|
|
191
|
+
*/
|
|
192
|
+
getTyped(handle: string, type: string): unknown;
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Transfer ownership of a resource to a new owner.
|
|
196
|
+
* @throws {HandleNotFoundError} If the handle does not exist.
|
|
197
|
+
*/
|
|
198
|
+
transfer(handle: string, newOwner: string): void;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Drop (remove) a resource from the table.
|
|
202
|
+
* @returns The resource value that was removed.
|
|
203
|
+
* @throws {HandleNotFoundError} If the handle does not exist.
|
|
204
|
+
*/
|
|
205
|
+
drop(handle: string): unknown;
|
|
206
|
+
|
|
207
|
+
/** Check whether a handle exists in the table. */
|
|
208
|
+
has(handle: string): boolean;
|
|
209
|
+
|
|
210
|
+
/** List all handles owned by a given owner. */
|
|
211
|
+
listByOwner(owner: string): string[];
|
|
212
|
+
|
|
213
|
+
/** List all handles of a given type. */
|
|
214
|
+
listByType(type: string): string[];
|
|
215
|
+
|
|
216
|
+
/** Current number of entries. */
|
|
217
|
+
readonly size: number;
|
|
218
|
+
|
|
219
|
+
/** Remove all entries from the table. */
|
|
220
|
+
clear(): void;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ── ByteStream ───────────────────────────────────────────────────────
|
|
224
|
+
|
|
225
|
+
/** Symbol used to tag objects as ByteStream-compliant. */
|
|
226
|
+
export declare const BYTE_STREAM: unique symbol;
|
|
227
|
+
|
|
228
|
+
/** Duck-typed ByteStream protocol interface. */
|
|
229
|
+
export interface ByteStream {
|
|
230
|
+
[BYTE_STREAM]: true;
|
|
231
|
+
read(): Promise<unknown | null>;
|
|
232
|
+
write(data: unknown): Promise<void>;
|
|
233
|
+
close(): Promise<void>;
|
|
234
|
+
readonly closed: boolean;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** A transform applied to ByteStream data via compose(). */
|
|
238
|
+
export interface ByteStreamTransform {
|
|
239
|
+
transform(chunk: Uint8Array): Uint8Array | Promise<Uint8Array>;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** Options for createPipe(). */
|
|
243
|
+
export interface CreatePipeOptions {
|
|
244
|
+
/** Maximum queue depth. Defaults to 1024. */
|
|
245
|
+
highWaterMark?: number;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Check whether an object conforms to the ByteStream protocol.
|
|
250
|
+
* A ByteStream must have `read`, `write`, and `close` methods.
|
|
251
|
+
*/
|
|
252
|
+
export declare function isByteStream(obj: unknown): obj is ByteStream;
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Tag an object with the ByteStream symbol. Idempotent.
|
|
256
|
+
*/
|
|
257
|
+
export declare function asByteStream<T extends { read: Function; write: Function; close: Function }>(obj: T): T & { [BYTE_STREAM]: true };
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Create an in-memory pipe returning `[reader, writer]` ByteStreams.
|
|
261
|
+
* Data written to `writer` can be read from `reader`.
|
|
262
|
+
*/
|
|
263
|
+
export declare function createPipe(opts?: CreatePipeOptions): [ByteStream, ByteStream];
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Pipe all data from a source ByteStream to a destination ByteStream.
|
|
267
|
+
* Reads from src until null (EOF), writes each chunk to dst.
|
|
268
|
+
*/
|
|
269
|
+
export declare function pipe(src: ByteStream, dst: ByteStream): Promise<void>;
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Create a sink ByteStream that discards all writes and returns null on read.
|
|
273
|
+
*/
|
|
274
|
+
export declare function devNull(): ByteStream;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Compose one or more transforms onto a ByteStream, returning a new
|
|
278
|
+
* ByteStream that applies the transforms in order on read and in
|
|
279
|
+
* reverse order on write.
|
|
280
|
+
*/
|
|
281
|
+
export declare function compose(stream: ByteStream, ...transforms: ByteStreamTransform[]): ByteStream;
|
|
282
|
+
|
|
283
|
+
// ── Clock ────────────────────────────────────────────────────────────
|
|
284
|
+
|
|
285
|
+
/** Options for the Clock constructor. */
|
|
286
|
+
export interface ClockOptions {
|
|
287
|
+
/** Monotonic time source (ms). */
|
|
288
|
+
monoFn?: () => number;
|
|
289
|
+
/** Wall-clock time source (ms since epoch). */
|
|
290
|
+
wallFn?: () => number;
|
|
291
|
+
/** Async sleep implementation. */
|
|
292
|
+
sleepFn?: (ms: number) => Promise<void>;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** Clock providing monotonic and wall-clock time plus async sleep. */
|
|
296
|
+
export declare class Clock {
|
|
297
|
+
constructor(opts?: ClockOptions);
|
|
298
|
+
|
|
299
|
+
/** Get the current monotonic time in milliseconds. */
|
|
300
|
+
nowMonotonic(): number;
|
|
301
|
+
|
|
302
|
+
/** Get the current wall-clock time in milliseconds since the Unix epoch. */
|
|
303
|
+
nowWall(): number;
|
|
304
|
+
|
|
305
|
+
/** Sleep for the given number of milliseconds. */
|
|
306
|
+
sleep(ms: number): Promise<void>;
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Create a fixed (deterministic) clock for testing.
|
|
310
|
+
* The clock always returns the same values unless manually advanced.
|
|
311
|
+
*/
|
|
312
|
+
static fixed(mono: number, wall: number): Clock;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// ── RNG ──────────────────────────────────────────────────────────────
|
|
316
|
+
|
|
317
|
+
/** Options for the RNG constructor. */
|
|
318
|
+
export interface RNGOptions {
|
|
319
|
+
/** Custom byte source. */
|
|
320
|
+
getFn?: (n: number) => Uint8Array;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/** Random number generator with crypto and seeded modes. */
|
|
324
|
+
export declare class RNG {
|
|
325
|
+
constructor(opts?: RNGOptions);
|
|
326
|
+
|
|
327
|
+
/** Get `n` random bytes. */
|
|
328
|
+
get(n: number): Uint8Array;
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Create a deterministic seeded RNG using xorshift128+.
|
|
332
|
+
* The same seed always produces the same sequence of bytes.
|
|
333
|
+
*/
|
|
334
|
+
static seeded(seed: number): RNG;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ── Capabilities ─────────────────────────────────────────────────────
|
|
338
|
+
|
|
339
|
+
/** Frozen capabilities object returned by buildCaps(). */
|
|
340
|
+
export interface Caps {
|
|
341
|
+
readonly clock?: Clock;
|
|
342
|
+
readonly rng?: RNG;
|
|
343
|
+
readonly net?: true;
|
|
344
|
+
readonly fs?: true;
|
|
345
|
+
readonly ipc?: ServiceRegistry;
|
|
346
|
+
readonly stdio?: true;
|
|
347
|
+
readonly trace?: Tracer;
|
|
348
|
+
readonly chaos?: ChaosEngine;
|
|
349
|
+
readonly env?: true;
|
|
350
|
+
readonly signal?: true;
|
|
351
|
+
readonly _granted: readonly string[];
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Build a frozen capabilities object from granted capability tags.
|
|
356
|
+
* Each granted tag maps to the corresponding kernel subsystem reference.
|
|
357
|
+
*/
|
|
358
|
+
export declare function buildCaps(kernel: Kernel, grantedCaps: string[]): Readonly<Caps>;
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Require that a capability tag is present in a caps object.
|
|
362
|
+
* @throws {CapabilityDeniedError} If the capability is not granted.
|
|
363
|
+
*/
|
|
364
|
+
export declare function requireCap(caps: Caps, capTag: string): void;
|
|
365
|
+
|
|
366
|
+
/** Builder class for constructing capabilities (alternative to buildCaps). */
|
|
367
|
+
export declare class CapsBuilder {
|
|
368
|
+
/**
|
|
369
|
+
* Build capabilities from kernel and granted tags.
|
|
370
|
+
*/
|
|
371
|
+
build(kernel: Kernel, grantedCaps: string[]): Readonly<Caps>;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// ── MessagePort / IPC ────────────────────────────────────────────────
|
|
375
|
+
|
|
376
|
+
/** Message handler callback type. */
|
|
377
|
+
export type MessageHandler = (msg: unknown, transfers?: unknown[]) => void;
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* A message endpoint. Part of a channel pair created by createChannel().
|
|
381
|
+
* Posting to one port delivers to the peer's listeners in FIFO order.
|
|
382
|
+
*/
|
|
383
|
+
export declare class KernelMessagePort {
|
|
384
|
+
/**
|
|
385
|
+
* Post a structured message. Delivered to the peer port's listeners.
|
|
386
|
+
* @throws {StreamClosedError} If this port has been closed.
|
|
387
|
+
*/
|
|
388
|
+
post(msg: unknown, transfers?: unknown[]): void;
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Register a callback to receive messages.
|
|
392
|
+
* @returns Unsubscribe function.
|
|
393
|
+
*/
|
|
394
|
+
onMessage(cb: MessageHandler): () => void;
|
|
395
|
+
|
|
396
|
+
/** Close the port. Subsequent post() calls throw StreamClosedError. */
|
|
397
|
+
close(): void;
|
|
398
|
+
|
|
399
|
+
/** Whether this port has been closed. */
|
|
400
|
+
readonly closed: boolean;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Create a connected pair of KernelMessagePorts.
|
|
405
|
+
* Posting to portA delivers to portB's listeners, and vice versa.
|
|
406
|
+
*/
|
|
407
|
+
export declare function createChannel(): [KernelMessagePort, KernelMessagePort];
|
|
408
|
+
|
|
409
|
+
// ── ServiceRegistry ──────────────────────────────────────────────────
|
|
410
|
+
|
|
411
|
+
/** An entry in the ServiceRegistry. */
|
|
412
|
+
export interface ServiceEntry {
|
|
413
|
+
name: string;
|
|
414
|
+
listener: unknown;
|
|
415
|
+
metadata: Record<string, unknown>;
|
|
416
|
+
owner: string | null;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/** Options for ServiceRegistry.register(). */
|
|
420
|
+
export interface ServiceRegisterOptions {
|
|
421
|
+
/** Arbitrary metadata about the service. */
|
|
422
|
+
metadata?: Record<string, unknown>;
|
|
423
|
+
/** Owner identifier. */
|
|
424
|
+
owner?: string;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/** Registry for named services with lifecycle event callbacks. */
|
|
428
|
+
export declare class ServiceRegistry {
|
|
429
|
+
/**
|
|
430
|
+
* Register a named service.
|
|
431
|
+
* @throws {AlreadyRegisteredError} If the name is already registered.
|
|
432
|
+
*/
|
|
433
|
+
register(name: string, listener: unknown, opts?: ServiceRegisterOptions): void;
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Unregister a named service.
|
|
437
|
+
* @throws {NotFoundError} If the name is not registered.
|
|
438
|
+
*/
|
|
439
|
+
unregister(name: string): void;
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Look up a service by name. If not found locally, calls onLookupMiss hooks.
|
|
443
|
+
* @throws {NotFoundError} If the service is not found.
|
|
444
|
+
*/
|
|
445
|
+
lookup(name: string): Promise<ServiceEntry>;
|
|
446
|
+
|
|
447
|
+
/** Check whether a service is registered. */
|
|
448
|
+
has(name: string): boolean;
|
|
449
|
+
|
|
450
|
+
/** List all registered service names. */
|
|
451
|
+
list(): string[];
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Register a callback for service registration events.
|
|
455
|
+
* @returns Unsubscribe function.
|
|
456
|
+
*/
|
|
457
|
+
onRegister(cb: (entry: ServiceEntry) => void): () => void;
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Register a callback for service unregistration events.
|
|
461
|
+
* @returns Unsubscribe function.
|
|
462
|
+
*/
|
|
463
|
+
onUnregister(cb: (entry: ServiceEntry) => void): () => void;
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Register a hook called when lookup() misses locally.
|
|
467
|
+
* Hook receives the service name and may return a service entry or null.
|
|
468
|
+
* @returns Unsubscribe function.
|
|
469
|
+
*/
|
|
470
|
+
onLookupMiss(cb: (name: string) => Promise<ServiceEntry | null>): () => void;
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Register a remote service entry (for distributed service awareness).
|
|
474
|
+
* @throws {AlreadyRegisteredError} If the name is already registered.
|
|
475
|
+
*/
|
|
476
|
+
registerRemote(name: string, nodeId: string, metadata?: Record<string, unknown>): void;
|
|
477
|
+
|
|
478
|
+
/** Remove all registered services and callbacks. */
|
|
479
|
+
clear(): void;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// ── Tracer ───────────────────────────────────────────────────────────
|
|
483
|
+
|
|
484
|
+
/** A stamped trace event. */
|
|
485
|
+
export interface TraceEvent {
|
|
486
|
+
id: number;
|
|
487
|
+
timestamp: number;
|
|
488
|
+
type: string;
|
|
489
|
+
[key: string]: unknown;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/** Options for the Tracer constructor. */
|
|
493
|
+
export interface TracerOptions {
|
|
494
|
+
/** Maximum events in the ring buffer. Defaults to 1024. */
|
|
495
|
+
capacity?: number;
|
|
496
|
+
/** Clock instance with nowMonotonic(). Falls back to performance.now(). */
|
|
497
|
+
clock?: Clock;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/** Structured event tracer with ring buffer storage and async iteration. */
|
|
501
|
+
export declare class Tracer {
|
|
502
|
+
constructor(opts?: TracerOptions);
|
|
503
|
+
|
|
504
|
+
/** Emit a trace event. The event is auto-stamped with `id` and `timestamp`. */
|
|
505
|
+
emit(event: { type: string; [key: string]: unknown }): void;
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Get an AsyncIterable of trace events. Each consumer gets an independent
|
|
509
|
+
* iterator that yields events as they are emitted. Does not replay past events.
|
|
510
|
+
*/
|
|
511
|
+
events(): AsyncIterable<TraceEvent>;
|
|
512
|
+
|
|
513
|
+
/** Get a snapshot of all currently buffered events. */
|
|
514
|
+
snapshot(): TraceEvent[];
|
|
515
|
+
|
|
516
|
+
/** Clear all buffered events. */
|
|
517
|
+
clear(): void;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// ── Logger ───────────────────────────────────────────────────────────
|
|
521
|
+
|
|
522
|
+
/** Log level constants. */
|
|
523
|
+
export declare const LOG_LEVEL: Readonly<{
|
|
524
|
+
DEBUG: 0;
|
|
525
|
+
INFO: 1;
|
|
526
|
+
WARN: 2;
|
|
527
|
+
ERROR: 3;
|
|
528
|
+
}>;
|
|
529
|
+
|
|
530
|
+
/** Union of LOG_LEVEL numeric values. */
|
|
531
|
+
export type LogLevelValue = 0 | 1 | 2 | 3;
|
|
532
|
+
|
|
533
|
+
/** A buffered log entry. */
|
|
534
|
+
export interface LogEntry {
|
|
535
|
+
level: LogLevelValue;
|
|
536
|
+
module: string;
|
|
537
|
+
message: string;
|
|
538
|
+
data: Record<string, unknown> | null;
|
|
539
|
+
timestamp: number;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/** A scoped logger returned by Logger.forModule(). */
|
|
543
|
+
export interface ModuleLogger {
|
|
544
|
+
debug(message: string, data?: Record<string, unknown>): void;
|
|
545
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
546
|
+
warn(message: string, data?: Record<string, unknown>): void;
|
|
547
|
+
error(message: string, data?: Record<string, unknown>): void;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/** Options for the Logger constructor. */
|
|
551
|
+
export interface LoggerOptions {
|
|
552
|
+
/** Maximum log entries in buffer. Defaults to 1024. */
|
|
553
|
+
capacity?: number;
|
|
554
|
+
/** Optional Tracer to pipe log entries to. */
|
|
555
|
+
tracer?: Tracer;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/** Options for Logger.entries() and Logger.snapshot(). */
|
|
559
|
+
export interface LogFilterOptions {
|
|
560
|
+
/** Filter by module name. */
|
|
561
|
+
module?: string;
|
|
562
|
+
/** Minimum log level (LOG_LEVEL constant). */
|
|
563
|
+
minLevel?: LogLevelValue;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/** Structured logger with per-module tagging and async iteration. */
|
|
567
|
+
export declare class Logger {
|
|
568
|
+
constructor(opts?: LoggerOptions);
|
|
569
|
+
|
|
570
|
+
/** Log a debug message. */
|
|
571
|
+
debug(module: string, message: string, data?: Record<string, unknown>): void;
|
|
572
|
+
|
|
573
|
+
/** Log an info message. */
|
|
574
|
+
info(module: string, message: string, data?: Record<string, unknown>): void;
|
|
575
|
+
|
|
576
|
+
/** Log a warning message. */
|
|
577
|
+
warn(module: string, message: string, data?: Record<string, unknown>): void;
|
|
578
|
+
|
|
579
|
+
/** Log an error message. */
|
|
580
|
+
error(module: string, message: string, data?: Record<string, unknown>): void;
|
|
581
|
+
|
|
582
|
+
/** Create a scoped logger for a specific module. */
|
|
583
|
+
forModule(name: string): ModuleLogger;
|
|
584
|
+
|
|
585
|
+
/** Get an AsyncIterable of log entries, optionally filtered. */
|
|
586
|
+
entries(opts?: LogFilterOptions): AsyncIterable<LogEntry>;
|
|
587
|
+
|
|
588
|
+
/** Get a snapshot of all currently buffered entries. */
|
|
589
|
+
snapshot(opts?: LogFilterOptions): LogEntry[];
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// ── ChaosEngine ──────────────────────────────────────────────────────
|
|
593
|
+
|
|
594
|
+
/** Configuration for the ChaosEngine. */
|
|
595
|
+
export interface ChaosConfig {
|
|
596
|
+
/** Added latency in ms. Defaults to 0. */
|
|
597
|
+
latencyMs?: number;
|
|
598
|
+
/** Drop probability (0-1). Defaults to 0. */
|
|
599
|
+
dropRate?: number;
|
|
600
|
+
/** Disconnect probability (0-1). Defaults to 0. */
|
|
601
|
+
disconnectRate?: number;
|
|
602
|
+
/** Addresses to partition. Defaults to []. */
|
|
603
|
+
partitionTargets?: string[];
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/** Options for the ChaosEngine constructor. */
|
|
607
|
+
export interface ChaosEngineOptions {
|
|
608
|
+
/** RNG instance for deterministic fault patterns. */
|
|
609
|
+
rng?: RNG;
|
|
610
|
+
/** Clock instance for delay implementation. */
|
|
611
|
+
clock?: Clock;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/** Fault injection engine with global and per-scope configuration. */
|
|
615
|
+
export declare class ChaosEngine {
|
|
616
|
+
constructor(opts?: ChaosEngineOptions);
|
|
617
|
+
|
|
618
|
+
/** Enable the chaos engine. */
|
|
619
|
+
enable(): void;
|
|
620
|
+
|
|
621
|
+
/** Disable the chaos engine. */
|
|
622
|
+
disable(): void;
|
|
623
|
+
|
|
624
|
+
/** Whether the engine is enabled. */
|
|
625
|
+
readonly enabled: boolean;
|
|
626
|
+
|
|
627
|
+
/** Configure global fault injection defaults. */
|
|
628
|
+
configure(config: ChaosConfig): void;
|
|
629
|
+
|
|
630
|
+
/** Configure fault injection for a specific scope (overrides global). */
|
|
631
|
+
configureScope(scopeId: string, config: ChaosConfig): void;
|
|
632
|
+
|
|
633
|
+
/** Remove scope-specific configuration, falling back to global defaults. */
|
|
634
|
+
removeScopeConfig(scopeId: string): void;
|
|
635
|
+
|
|
636
|
+
/** Maybe inject latency delay. */
|
|
637
|
+
maybeDelay(scopeId?: string): Promise<void>;
|
|
638
|
+
|
|
639
|
+
/** Check whether a packet/message should be dropped. */
|
|
640
|
+
shouldDrop(scopeId?: string): boolean;
|
|
641
|
+
|
|
642
|
+
/** Check whether a connection should be forcibly disconnected. */
|
|
643
|
+
shouldDisconnect(scopeId?: string): boolean;
|
|
644
|
+
|
|
645
|
+
/** Check whether an address is partitioned (unreachable). */
|
|
646
|
+
isPartitioned(addr: string, scopeId?: string): boolean;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// ── Environment ──────────────────────────────────────────────────────
|
|
650
|
+
|
|
651
|
+
/** Immutable environment variable store. */
|
|
652
|
+
export declare class Environment {
|
|
653
|
+
constructor(vars?: Record<string, string>);
|
|
654
|
+
|
|
655
|
+
/** Get an environment variable by key. */
|
|
656
|
+
get(key: string): string | undefined;
|
|
657
|
+
|
|
658
|
+
/** Check whether an environment variable exists. */
|
|
659
|
+
has(key: string): boolean;
|
|
660
|
+
|
|
661
|
+
/** Get a frozen copy of all environment variables. */
|
|
662
|
+
all(): Readonly<Record<string, string>>;
|
|
663
|
+
|
|
664
|
+
/** Number of environment variables. */
|
|
665
|
+
readonly size: number;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// ── Signal ───────────────────────────────────────────────────────────
|
|
669
|
+
|
|
670
|
+
/** Signal name constants. */
|
|
671
|
+
export declare const SIGNAL: Readonly<{
|
|
672
|
+
TERM: 'TERM';
|
|
673
|
+
INT: 'INT';
|
|
674
|
+
HUP: 'HUP';
|
|
675
|
+
}>;
|
|
676
|
+
|
|
677
|
+
/** Union of valid signal names. */
|
|
678
|
+
export type SignalName = 'TERM' | 'INT' | 'HUP';
|
|
679
|
+
|
|
680
|
+
/** Signal controller providing named signal dispatch and AbortSignal integration. */
|
|
681
|
+
export declare class SignalController {
|
|
682
|
+
/**
|
|
683
|
+
* Fire a named signal. All registered callbacks and AbortSignals
|
|
684
|
+
* for this signal name are triggered.
|
|
685
|
+
*/
|
|
686
|
+
signal(name: string): void;
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Register a callback for a named signal.
|
|
690
|
+
* @returns Unsubscribe function.
|
|
691
|
+
*/
|
|
692
|
+
onSignal(name: string, cb: () => void): () => void;
|
|
693
|
+
|
|
694
|
+
/** Get an AbortSignal that aborts when the named signal fires. */
|
|
695
|
+
abortSignal(name: string): AbortSignal;
|
|
696
|
+
|
|
697
|
+
/** Check whether a signal has been fired. */
|
|
698
|
+
hasFired(name: string): boolean;
|
|
699
|
+
|
|
700
|
+
/** Reset a signal so it can be fired again. */
|
|
701
|
+
reset(name: string): void;
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Get a composite AbortSignal that aborts on either TERM or INT.
|
|
705
|
+
* Useful for graceful shutdown scenarios.
|
|
706
|
+
*/
|
|
707
|
+
readonly shutdownSignal: AbortSignal;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// ── Stdio ────────────────────────────────────────────────────────────
|
|
711
|
+
|
|
712
|
+
/** Options for the Stdio constructor. */
|
|
713
|
+
export interface StdioOptions {
|
|
714
|
+
/** Input ByteStream (defaults to devNull). */
|
|
715
|
+
stdin?: ByteStream;
|
|
716
|
+
/** Output ByteStream (defaults to devNull). */
|
|
717
|
+
stdout?: ByteStream;
|
|
718
|
+
/** Error ByteStream (defaults to devNull). */
|
|
719
|
+
stderr?: ByteStream;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/** Standard I/O container wrapping ByteStream-compatible streams. */
|
|
723
|
+
export declare class Stdio {
|
|
724
|
+
constructor(opts?: StdioOptions);
|
|
725
|
+
|
|
726
|
+
/** Standard input stream. */
|
|
727
|
+
readonly stdin: ByteStream;
|
|
728
|
+
|
|
729
|
+
/** Standard output stream. */
|
|
730
|
+
readonly stdout: ByteStream;
|
|
731
|
+
|
|
732
|
+
/** Standard error stream. */
|
|
733
|
+
readonly stderr: ByteStream;
|
|
734
|
+
|
|
735
|
+
/** Write text to stdout (without trailing newline). */
|
|
736
|
+
print(text: string): Promise<void>;
|
|
737
|
+
|
|
738
|
+
/** Write text to stdout with a trailing newline. */
|
|
739
|
+
println(text: string): Promise<void>;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// ── Kernel Facade ────────────────────────────────────────────────────
|
|
743
|
+
|
|
744
|
+
/** A tenant created by Kernel.createTenant(). */
|
|
745
|
+
export interface Tenant {
|
|
746
|
+
/** Unique tenant identifier (e.g. `'tenant_1'`). */
|
|
747
|
+
id: string;
|
|
748
|
+
/** Frozen capabilities object scoped to the tenant's grants. */
|
|
749
|
+
caps: Readonly<Caps>;
|
|
750
|
+
/** Immutable per-tenant environment variables. */
|
|
751
|
+
env: Environment;
|
|
752
|
+
/** Per-tenant standard I/O streams. */
|
|
753
|
+
stdio: Stdio;
|
|
754
|
+
/** Per-tenant signal controller. */
|
|
755
|
+
signals: SignalController;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/** Options for Kernel.createTenant(). */
|
|
759
|
+
export interface CreateTenantOptions {
|
|
760
|
+
/** KERNEL_CAP tags to grant. Defaults to []. */
|
|
761
|
+
capabilities?: string[];
|
|
762
|
+
/** Tenant environment variables. Defaults to {}. */
|
|
763
|
+
env?: Record<string, string>;
|
|
764
|
+
/** Tenant stdio streams. */
|
|
765
|
+
stdio?: StdioOptions;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
/** Options for the Kernel constructor. */
|
|
769
|
+
export interface KernelOptions {
|
|
770
|
+
/** Clock instance (defaults to real clock). */
|
|
771
|
+
clock?: Clock;
|
|
772
|
+
/** RNG instance (defaults to crypto RNG). */
|
|
773
|
+
rng?: RNG;
|
|
774
|
+
/** Options for Tracer constructor. */
|
|
775
|
+
tracerOpts?: TracerOptions;
|
|
776
|
+
/** Options for Logger constructor. */
|
|
777
|
+
loggerOpts?: LoggerOptions;
|
|
778
|
+
/** Options for ResourceTable constructor. */
|
|
779
|
+
resourceOpts?: ResourceTableOptions;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/** The Kernel facade. Creates and wires all subsystems. */
|
|
783
|
+
export declare class Kernel {
|
|
784
|
+
constructor(opts?: KernelOptions);
|
|
785
|
+
|
|
786
|
+
/** The kernel's resource table. */
|
|
787
|
+
readonly resources: ResourceTable;
|
|
788
|
+
|
|
789
|
+
/** The kernel clock. */
|
|
790
|
+
readonly clock: Clock;
|
|
791
|
+
|
|
792
|
+
/** The kernel RNG. */
|
|
793
|
+
readonly rng: RNG;
|
|
794
|
+
|
|
795
|
+
/** The kernel tracer. */
|
|
796
|
+
readonly tracer: Tracer;
|
|
797
|
+
|
|
798
|
+
/** The kernel logger. */
|
|
799
|
+
readonly log: Logger;
|
|
800
|
+
|
|
801
|
+
/** The chaos engine. */
|
|
802
|
+
readonly chaos: ChaosEngine;
|
|
803
|
+
|
|
804
|
+
/** The service registry. */
|
|
805
|
+
readonly services: ServiceRegistry;
|
|
806
|
+
|
|
807
|
+
/** The signal controller. */
|
|
808
|
+
readonly signals: SignalController;
|
|
809
|
+
|
|
810
|
+
/**
|
|
811
|
+
* Create a new tenant with scoped capabilities.
|
|
812
|
+
*/
|
|
813
|
+
createTenant(opts?: CreateTenantOptions): Tenant;
|
|
814
|
+
|
|
815
|
+
/** Destroy a tenant, dropping all owned resources. */
|
|
816
|
+
destroyTenant(tenantId: string): void;
|
|
817
|
+
|
|
818
|
+
/** Get a tenant by ID. */
|
|
819
|
+
getTenant(tenantId: string): Tenant | undefined;
|
|
820
|
+
|
|
821
|
+
/** List all tenant IDs. */
|
|
822
|
+
listTenants(): string[];
|
|
823
|
+
|
|
824
|
+
/** Close the kernel, destroying all tenants and clearing all subsystems. */
|
|
825
|
+
close(): void;
|
|
826
|
+
}
|