@dcasegr/skein 0.0.0-stage → 0.1.2

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.
Files changed (176) hide show
  1. package/README.md +525 -2
  2. package/bin/skein-host.js +22 -0
  3. package/bin/skein.js +8 -0
  4. package/dist/client/admin-cli.d.ts +10 -0
  5. package/dist/client/admin-cli.js +370 -0
  6. package/dist/client/admin.d.ts +139 -0
  7. package/dist/client/admin.js +256 -0
  8. package/dist/client/bundle.d.ts +9 -0
  9. package/dist/client/bundle.js +34 -0
  10. package/dist/client/cli.d.ts +44 -0
  11. package/dist/client/cli.js +306 -0
  12. package/dist/client/client.d.ts +161 -0
  13. package/dist/client/client.js +237 -0
  14. package/dist/client/config.d.ts +18 -0
  15. package/dist/client/config.js +31 -0
  16. package/dist/client/conversation.d.ts +62 -0
  17. package/dist/client/conversation.js +113 -0
  18. package/dist/client/raw.d.ts +94 -0
  19. package/dist/client/raw.js +154 -0
  20. package/dist/client/target.d.ts +34 -0
  21. package/dist/client/target.js +158 -0
  22. package/dist/dev/cli.d.ts +8 -0
  23. package/dist/dev/cli.js +248 -0
  24. package/dist/dev/scan.d.ts +15 -0
  25. package/dist/dev/scan.js +173 -0
  26. package/dist/envelope-cbor.d.ts +110 -0
  27. package/dist/envelope-cbor.js +160 -0
  28. package/dist/envelope.d.ts +38 -0
  29. package/dist/envelope.js +101 -0
  30. package/dist/host/arc.d.ts +131 -0
  31. package/dist/host/arc.js +425 -0
  32. package/dist/host/billing.d.ts +102 -0
  33. package/dist/host/billing.js +167 -0
  34. package/dist/host/boot.d.ts +246 -0
  35. package/dist/host/boot.js +643 -0
  36. package/dist/host/cli.d.ts +57 -0
  37. package/dist/host/cli.js +1253 -0
  38. package/dist/host/clock.d.ts +3 -0
  39. package/dist/host/clock.js +8 -0
  40. package/dist/host/control.d.ts +45 -0
  41. package/dist/host/control.js +170 -0
  42. package/dist/host/cron.d.ts +99 -0
  43. package/dist/host/cron.js +196 -0
  44. package/dist/host/deliver.d.ts +53 -0
  45. package/dist/host/deliver.js +251 -0
  46. package/dist/host/deploy.d.ts +29 -0
  47. package/dist/host/deploy.js +55 -0
  48. package/dist/host/door-answer.d.ts +24 -0
  49. package/dist/host/door-answer.js +21 -0
  50. package/dist/host/events.d.ts +89 -0
  51. package/dist/host/events.js +222 -0
  52. package/dist/host/fake-arcade.d.ts +40 -0
  53. package/dist/host/fake-arcade.js +149 -0
  54. package/dist/host/fake-discovery.d.ts +4 -0
  55. package/dist/host/fake-discovery.js +58 -0
  56. package/dist/host/feeds.d.ts +127 -0
  57. package/dist/host/feeds.js +422 -0
  58. package/dist/host/frontdoor.d.ts +92 -0
  59. package/dist/host/frontdoor.js +172 -0
  60. package/dist/host/genesis.d.ts +259 -0
  61. package/dist/host/genesis.js +353 -0
  62. package/dist/host/handles.d.ts +40 -0
  63. package/dist/host/handles.js +88 -0
  64. package/dist/host/hostenv.d.ts +30 -0
  65. package/dist/host/hostenv.js +83 -0
  66. package/dist/host/image-chain.d.ts +127 -0
  67. package/dist/host/image-chain.js +440 -0
  68. package/dist/host/install.d.ts +22 -0
  69. package/dist/host/install.js +139 -0
  70. package/dist/host/instances.d.ts +227 -0
  71. package/dist/host/instances.js +430 -0
  72. package/dist/host/kernel.d.ts +246 -0
  73. package/dist/host/kernel.js +603 -0
  74. package/dist/host/liveness.d.ts +65 -0
  75. package/dist/host/liveness.js +155 -0
  76. package/dist/host/manifest.d.ts +160 -0
  77. package/dist/host/manifest.js +597 -0
  78. package/dist/host/p2p.d.ts +337 -0
  79. package/dist/host/p2p.js +1002 -0
  80. package/dist/host/packet.d.ts +121 -0
  81. package/dist/host/packet.js +562 -0
  82. package/dist/host/plan.d.ts +154 -0
  83. package/dist/host/plan.js +418 -0
  84. package/dist/host/providers.d.ts +238 -0
  85. package/dist/host/providers.js +565 -0
  86. package/dist/host/roster.d.ts +72 -0
  87. package/dist/host/roster.js +172 -0
  88. package/dist/host/router.d.ts +782 -0
  89. package/dist/host/router.js +2411 -0
  90. package/dist/host/signer.d.ts +49 -0
  91. package/dist/host/signer.js +167 -0
  92. package/dist/host/store-sqlite.d.ts +39 -0
  93. package/dist/host/store-sqlite.js +170 -0
  94. package/dist/host/stores.d.ts +43 -0
  95. package/dist/host/stores.js +342 -0
  96. package/dist/host/sync.d.ts +121 -0
  97. package/dist/host/sync.js +467 -0
  98. package/dist/host/testbeef.d.ts +21 -0
  99. package/dist/host/testbeef.js +37 -0
  100. package/dist/host/testhost.d.ts +149 -0
  101. package/dist/host/testhost.js +211 -0
  102. package/dist/host/vcdiff.d.ts +9 -0
  103. package/dist/host/vcdiff.js +210 -0
  104. package/dist/host/wasm-kernel.d.ts +87 -0
  105. package/dist/host/wasm-kernel.js +296 -0
  106. package/dist/host/wasm-worker.d.ts +1 -0
  107. package/dist/host/wasm-worker.js +186 -0
  108. package/dist/peers/cron.d.ts +33 -0
  109. package/dist/peers/cron.js +75 -0
  110. package/dist/peers/infer-main.d.ts +2 -0
  111. package/dist/peers/infer-main.js +74 -0
  112. package/dist/peers/infer.d.ts +163 -0
  113. package/dist/peers/infer.js +367 -0
  114. package/dist/runtime/beef.d.ts +28 -0
  115. package/dist/runtime/beef.js +107 -0
  116. package/dist/runtime/bitcoin.d.ts +36 -0
  117. package/dist/runtime/bitcoin.js +141 -0
  118. package/dist/runtime/cid.d.ts +14 -0
  119. package/dist/runtime/cid.js +51 -0
  120. package/dist/runtime/dispatch.d.ts +92 -0
  121. package/dist/runtime/dispatch.js +142 -0
  122. package/dist/runtime/envelope.d.ts +60 -0
  123. package/dist/runtime/envelope.js +101 -0
  124. package/dist/runtime/heads.d.ts +25 -0
  125. package/dist/runtime/heads.js +37 -0
  126. package/dist/runtime/identity.d.ts +28 -0
  127. package/dist/runtime/identity.js +67 -0
  128. package/dist/runtime/index-store.d.ts +152 -0
  129. package/dist/runtime/index-store.js +715 -0
  130. package/dist/runtime/log.d.ts +62 -0
  131. package/dist/runtime/log.js +104 -0
  132. package/dist/runtime/programs.d.ts +30 -0
  133. package/dist/runtime/programs.js +61 -0
  134. package/dist/runtime/records.d.ts +135 -0
  135. package/dist/runtime/records.js +149 -0
  136. package/dist/runtime/sqlite.d.ts +33 -0
  137. package/dist/runtime/sqlite.js +604 -0
  138. package/dist/runtime/store.d.ts +141 -0
  139. package/dist/runtime/store.js +24 -0
  140. package/dist/runtime/syscalls.d.ts +9 -0
  141. package/dist/runtime/syscalls.js +41 -0
  142. package/dist/runtime/tree.d.ts +60 -0
  143. package/dist/runtime/tree.js +196 -0
  144. package/dist/runtime/types.d.ts +100 -0
  145. package/dist/runtime/types.js +7 -0
  146. package/dist/testapps.d.ts +101 -0
  147. package/dist/testapps.js +275 -0
  148. package/dist/testkit.d.ts +25 -0
  149. package/dist/testkit.js +48 -0
  150. package/dist/wallet.d.ts +35 -0
  151. package/dist/wallet.js +87 -0
  152. package/images/README.md +68 -0
  153. package/images/default/README.md +38 -0
  154. package/images/default/bin/frontdoor.cid +1 -0
  155. package/images/default/bin/frontdoor.json +5 -0
  156. package/images/default/bin/messagebox.cid +1 -0
  157. package/images/default/bin/messagebox.json +8 -0
  158. package/images/default/bin/wallet.cid +1 -0
  159. package/images/default/bin/wallet.json +14 -0
  160. package/images/default/etc/config.json +1 -0
  161. package/images/default/etc/dispatch.json +82 -0
  162. package/images/host/etc/apps.json +8 -0
  163. package/kernel-zig/README.md +1247 -0
  164. package/kernel-zig/web/client.js +65 -0
  165. package/kernel-zig/web/kernel.d.ts +59 -0
  166. package/kernel-zig/web/kernel.js +329 -0
  167. package/kernel-zig/web/store.js +67 -0
  168. package/kernel-zig/web/worker.js +79 -0
  169. package/kernel-zig/zig-out/web/skein-kernel.wasm +0 -0
  170. package/package.json +77 -4
  171. package/wasm/README.md +35 -0
  172. package/wasm/frontdoor.wasm +0 -0
  173. package/wasm/messagebox.wasm +0 -0
  174. package/wasm/resolve.wasm +0 -0
  175. package/wasm/wallet.wasm +0 -0
  176. package/wasm/wire-probe.wasm +0 -0
@@ -0,0 +1,172 @@
1
+ // The host's side of an instance's front door (#68, #66): a light router.
2
+ // A request a transport carries in is appended as received — one `request`
3
+ // entry, the raw request its record (method, path, headers with the
4
+ // x-bsv-auth-* ones, body) — and nothing is verified here. The kernel steps
5
+ // the instance's middleware (the front door) on it as the request's own
6
+ // thread; the host holds the client's connection until that thread comes to
7
+ // rest for good (finished or errored, not waiting) and answers with what
8
+ // the thread's last step answered, signed on the client's session inside.
9
+ // However many entries the thread takes, the client sees one answer; past
10
+ // the wait's bound it gets 503 + Retry-After and the thread goes on.
11
+ //
12
+ // A route whose answer is a read of live state (the explorer) answers
13
+ // {read}: the thread verified it and ended, and the answer is one kernel
14
+ // `call` of the front door's fn "read", signed there (not recorded).
15
+ //
16
+ // Sessions are state (#68): the front door keeps them as records (head
17
+ // `frontdoor/sessions`); this side holds none.
18
+ //
19
+ // One table (#143; docs/MESSAGES.md "The front door"). Every HTTP request
20
+ // goes to the kernel's door: its route matched (exact path, then the longest
21
+ // prefix), the route's filters run (kernel.brc104 — the session and signature
22
+ // — kernel.beef, an app's own), the gate checked. What passes is admitted —
23
+ // one entry — and its thread waited on (frontDoor). What a filter rejects or
24
+ // answers, and what the gate refuses, writes nothing: the door's answer comes
25
+ // back at once (DoorAnswered) and the front door's fn "respond" signs it on
26
+ // the request's session when the request is signed (a call: nothing logged).
27
+ // A read route — filters only, no handler — is such an answer: the host
28
+ // serves it by the door, as a call, its fuel on the host's meter. The
29
+ // handshake (/.well-known/auth) is a route of its own (the front door's).
30
+ import * as dagCbor from "@ipld/dag-cbor";
31
+ import { encode } from "../runtime/cid.js";
32
+ import { stampMs } from "../runtime/log.js";
33
+ import { now as clockNow } from "./clock.js";
34
+ import { DoorAnswered } from "./door-answer.js";
35
+ /** How long a synchronous client waits on its request's thread by default (ms): SKEIN_ANSWER_WAIT_MS, else two minutes. */
36
+ export const ANSWER_WAIT_MS = Number(process.env.SKEIN_ANSWER_WAIT_MS) > 0 ? Number(process.env.SKEIN_ANSWER_WAIT_MS) : 120_000;
37
+ /** The Retry-After (s) a client that waited past the bound, or met a host shutting down, is told. */
38
+ export const RETRY_AFTER_S = 5;
39
+ const jsonBody = (v) => new TextEncoder().encode(JSON.stringify(v));
40
+ /** 503 + Retry-After: the wait's bound passed (the thread goes on), or the host is shutting down. */
41
+ export function unavailable(description, extra = {}) {
42
+ return { status: 503, headers: { "content-type": "application/json", "retry-after": String(RETRY_AFTER_S) }, body: jsonBody({ status: "error", code: "ERR_UNAVAILABLE", description }), ...extra };
43
+ }
44
+ /** Lower-cased header names, one value each (joined with ", "). */
45
+ export function headerMap(h) {
46
+ const out = {};
47
+ const add = (k, v) => { if (v !== undefined)
48
+ out[k.toLowerCase()] = Array.isArray(v) ? v.join(", ") : v; };
49
+ if (h instanceof Headers)
50
+ h.forEach((v, k) => add(k, v));
51
+ else
52
+ for (const [k, v] of Object.entries(h))
53
+ add(k, v);
54
+ return out;
55
+ }
56
+ /**
57
+ * Append a package as received (#68): one `request` entry naming it and its
58
+ * transport. The record goes with the frame, not into the store (#121): the
59
+ * kernel's door matches the route, runs its filters and the gate, and puts
60
+ * the package as it hands it back (a BEEF's bytes never stored), so the entry
61
+ * written — its CID, returned — may name another record than this. A package
62
+ * the door turns away or answers writes nothing (#143): DoorAnswered.
63
+ */
64
+ export async function appendRequest(k, transport, record, time = clockNow()) {
65
+ return await k.admit({ request: cidOf(record), transport }, { request: record }, time);
66
+ }
67
+ /** An HTTP request's record (log.zig: {kind: "http", method, path, route, query, headers, body}). */
68
+ export function httpRecord(req) {
69
+ return { kind: "http", method: req.method, path: req.path, route: req.route ?? req.path, query: req.query, headers: req.headers, body: req.body };
70
+ }
71
+ /**
72
+ * One HTTP request through the instance: appended, then waited on (#66)
73
+ * until its thread comes to rest or `waitMs` passes (503 + Retry-After).
74
+ * `stop`, when it settles first, answers 503 too (the host shutting down).
75
+ */
76
+ export async function frontDoor(k, req, o = {}) {
77
+ const now = o.now ?? clockNow();
78
+ let entry;
79
+ try {
80
+ entry = await appendRequest(k, "http", httpRecord(req), now);
81
+ }
82
+ catch (e) {
83
+ if (e instanceof DoorAnswered)
84
+ return await doorAnswer(k, e.answer, req, now);
85
+ throw e;
86
+ }
87
+ const waited = k.answer(entry, o.waitMs ?? ANSWER_WAIT_MS);
88
+ const a = o.stop ? await Promise.race([waited, o.stop.then(() => undefined)]) : await waited;
89
+ if (!a)
90
+ return unavailable("the host is shutting down", { entry });
91
+ return await httpAnswer(k, entry, a, req);
92
+ }
93
+ /**
94
+ * A request thread's answer as the HTTP response: its last step's, a read after it, or 500/503.
95
+ * `req`, the request as received: a door refusal of a signed one is answered by the front door.
96
+ */
97
+ export async function httpAnswer(k, entry, a, req) {
98
+ const at = { entry, ...(a.thread ? { thread: a.thread } : {}) };
99
+ void req;
100
+ if (a.state === "errored")
101
+ return { status: 500, headers: { "content-type": "application/json" }, body: jsonBody({ status: "error", code: "ERR_FRONT_DOOR", description: a.error }), ...at };
102
+ if (a.state !== "finished")
103
+ return unavailable(`not answered yet (its thread is ${a.state}): try again`, at);
104
+ const r = dagCbor.decode(a.answer);
105
+ if (r.read !== undefined && r.status === undefined) {
106
+ const caller = r.read?.caller instanceof Uint8Array ? { caller: Buffer.from(r.read.caller).toString("hex") } : {};
107
+ // A read of live state (the explorer): the front door answers it as a call, and signs it there.
108
+ const c = await k.invoke("frontdoor", "read", dagCbor.encode({ request: await requestOf(k, entry), read: r.read }));
109
+ if (!c.ok)
110
+ return { status: 500, headers: { "content-type": "application/json" }, body: jsonBody({ status: "error", code: "ERR_FRONT_DOOR", description: c.error }), fuel: c.fuel, ...caller, ...at };
111
+ const x = dagCbor.decode(c.result);
112
+ return { status: x.status, headers: x.headers ?? {}, body: x.body ?? new Uint8Array(), fuel: c.fuel, ...caller, ...at };
113
+ }
114
+ if (typeof r.status !== "number")
115
+ return { status: 500, headers: { "content-type": "application/json" }, body: jsonBody({ status: "error", code: "ERR_FRONT_DOOR", description: "the request's thread ended with no answer" }), ...at };
116
+ return { status: r.status, headers: r.headers ?? {}, body: r.body ?? new Uint8Array(), ...at };
117
+ }
118
+ /**
119
+ * The door's answer without an entry (#143: a filter's rejection or answer — a read route's — or the
120
+ * gate's refusal), as the HTTP response: a signed request gets it signed on its session — a
121
+ * front-door call (fn "respond") with the request as received, at the request's time — and an
122
+ * unsigned one, or one whose session does not verify (unknown, expired: the stock client shakes
123
+ * hands again), gets it plain.
124
+ */
125
+ export async function doorAnswer(k, d, req, now = clockNow()) {
126
+ const meter = { fuel: d.fuel, ...(d.principal ? { caller: Buffer.from(d.principal).toString("hex") } : {}) };
127
+ const plain = d.kind === "answer"
128
+ ? { status: d.status, headers: { ...(d.headers ?? {}), "content-type": d.type ?? d.headers?.["content-type"] ?? "application/json" }, body: d.body ?? new Uint8Array(), ...meter }
129
+ : { status: d.status, headers: { "content-type": "application/json" }, body: jsonBody({ status: "error", code: d.code ?? "ERR_REFUSED", description: d.reason ?? "refused" }), ...meter };
130
+ if (!isSigned(req.headers))
131
+ return plain;
132
+ const arg = d.kind === "answer"
133
+ ? { request: httpRecord(req), answer: { status: d.status, ...(d.type ? { type: d.type } : {}), ...(d.headers ? { headers: d.headers } : {}), body: d.body ?? new Uint8Array() } }
134
+ : { request: httpRecord(req), refused: { status: d.status, code: d.code ?? "ERR_REFUSED", reason: d.reason ?? "refused" } };
135
+ const c = await k.invoke("frontdoor", "respond", dagCbor.encode(arg), { now: stampMs(now) });
136
+ if (!c.ok)
137
+ return plain;
138
+ const x = dagCbor.decode(c.result);
139
+ return { status: x.status, headers: x.headers ?? {}, body: x.body ?? new Uint8Array(), ...meter, fuel: d.fuel + c.fuel };
140
+ }
141
+ /** The request record an entry names. */
142
+ async function requestOf(k, entry) {
143
+ const e = await k.store.get(entry);
144
+ if (!e.request)
145
+ throw new Error(`${entry} is not a request entry`);
146
+ return e.request;
147
+ }
148
+ // ---------------------------------------------------------------- one table (#143)
149
+ /** The BRC-104 handshake's path: a route of its own (the front door's fn "handshake"). */
150
+ export const HANDSHAKE_PATH = "/.well-known/auth";
151
+ /** Whether a request carries BRC-104 headers (x-bsv-auth-*): a signed request. */
152
+ export const isSigned = (headers) => Object.keys(headers).some((h) => h.toLowerCase().startsWith("x-bsv-auth-"));
153
+ /**
154
+ * One HTTP request through the kernel's door (#143): its route's filters decide — admitted and
155
+ * waited on, or answered at once with nothing logged (a read route; a rejection; the gate's refusal).
156
+ */
157
+ export async function serveHttp(k, req, o = {}) {
158
+ return await frontDoor(k, req, o);
159
+ }
160
+ /** A fetch over one instance's door (serveHttp), no socket: for a client in a test, or a URL of the host's own. */
161
+ export function frontDoorFetch(k, o = {}) {
162
+ return (async (input, init = {}) => {
163
+ const url = new URL(typeof input === "string" || input instanceof URL ? input : input.url);
164
+ const req = input instanceof Request ? input : new Request(url, init);
165
+ const body = new Uint8Array(await req.arrayBuffer());
166
+ const fr = { method: req.method, path: url.pathname, route: o.route ? o.route(url.pathname) : url.pathname, query: url.search, headers: headerMap(req.headers), body };
167
+ const a = await serveHttp(k, fr, { now: o.now?.(), waitMs: o.waitMs });
168
+ o.onAnswer?.(a);
169
+ return new Response(a.body.length ? Buffer.from(a.body) : null, { status: a.status, headers: a.headers });
170
+ });
171
+ }
172
+ export const cidOf = (v) => encode(v).cid;
@@ -0,0 +1,259 @@
1
+ import type { CID } from "multiformats/cid";
2
+ import { type DispatchRow, type Transport } from "../runtime/dispatch.ts";
3
+ import type { Stamp } from "../runtime/syscalls.ts";
4
+ import type { KernelSurface as Kernel } from "./kernel.ts";
5
+ import type { FeedSpec } from "./feeds.ts";
6
+ /** Session expiry (#33 part 2, #40): the instance's own policy, judged against the session record's stamp (a day). */
7
+ export declare const SESSION_DEFAULTS: Record<string, string>;
8
+ export declare const keyBytes: (hex: string) => Uint8Array;
9
+ export declare const keyHex: (k: unknown) => string;
10
+ type Named = {
11
+ handle: string;
12
+ domain: string;
13
+ };
14
+ /** What the host brings to a genesis: the instance's own facts and the parties it knows. */
15
+ export interface Genesis2Config {
16
+ identity: string;
17
+ /**
18
+ * The initial root holders (hex; #143). Absent or empty: an image (#89) — a genesis with no root
19
+ * holder; its routes carry the claim route, and root comes with the claim. The host skein's is
20
+ * the operator's key (#142).
21
+ */
22
+ root?: string[];
23
+ handle: string;
24
+ domain: string;
25
+ infer?: string;
26
+ /** The first root holder's handle, for `names` (a code genesis). */
27
+ ownerHandle?: Named;
28
+ inferHandle?: Named;
29
+ /**
30
+ * The host's defaults. Code genesis: over DEFAULTS, whole. A system tree:
31
+ * only what the tree's config leaves unset (its behaviour comes from its tree).
32
+ */
33
+ defaults?: Record<string, string>;
34
+ /** Explicit host overrides (dev: SKEIN_FUEL_PER_STEP) that win even over a tree's config; `warn` says so when they do. */
35
+ overrides?: Record<string, string>;
36
+ warn?(line: string): void;
37
+ /** More box routes, after these (e.g. the wallet's boxes, #29): a box and its handler program record. */
38
+ subscriptions?: Array<{
39
+ box: string;
40
+ handler: CID;
41
+ }>;
42
+ /** More routes of any transport (#77), after these: the route as a system writes it (handler names resolved against the programs). */
43
+ dispatch?: DispatchSpec[];
44
+ /** Feeds the host holds for the instance (code genesis; a tree's config names its own). */
45
+ feeds?: FeedSpec[];
46
+ /** Code genesis (#51): libp2p for the instance (a tree's config names its own). */
47
+ libp2p?: Libp2pSpec;
48
+ /** Write scopes of genesis-wired programs beyond STOCK_SCOPES (#77): program name → head names (a prefix ends in `/`). */
49
+ scopes?: Record<string, string[]>;
50
+ /** A mailbox instance (#40): only the front door and the messagebox, keeping mail for its root from anyone. */
51
+ mailbox?: boolean;
52
+ /** The root holder's messagebox URL (#40): the one peer a genesis names (`defaults.ownerMessagebox`). */
53
+ ownerMessagebox?: string;
54
+ /** Where the instance's own domain resolves (`defaults.resolveOrigin`): the host's origin in dev. */
55
+ resolveOrigin?: string;
56
+ /**
57
+ * The network the whole host runs on (SKEIN_NETWORK: `main` | `test` | `regtest`), written as
58
+ * `defaults.walletNetwork` at the host's fill-ins level (a tree's config and `overrides` win).
59
+ * A network fact, not a host fact: the chain app takes its network from it (`config.chain.network`).
60
+ */
61
+ network?: string;
62
+ /**
63
+ * The address book's seed (#70): the host's providers (their keys, `local`,
64
+ * address = name; #126: no role) and, when the host knows it, the root holder's mailbox. Written
65
+ * into the head `peers` when the genesis is processed.
66
+ */
67
+ addressBook?: AddressSeed[];
68
+ /**
69
+ * The host's providers by name (hex keys: fetch, waker, cron, libp2p,
70
+ * status), for a config key written `$<name>` (`peers`, `names`).
71
+ */
72
+ providers?: Record<string, string>;
73
+ /**
74
+ * #142: an installed app's config at birth, by app name, merged over its manifest's `config` as an
75
+ * install's `--config` is (the host skein's onboard: domain, origin, name, note from host.env).
76
+ */
77
+ appConfig?: Record<string, Record<string, unknown>>;
78
+ }
79
+ /** One address book entry a genesis seeds (#70): key → transport and address. */
80
+ export interface AddressSeed {
81
+ key: Uint8Array;
82
+ transport: "mailbox" | "libp2p" | "local";
83
+ address: string;
84
+ handle?: string;
85
+ domain?: string;
86
+ }
87
+ /**
88
+ * A route as a system writes it (etc/dispatch.json, #77, #143): `transport`
89
+ * defaults to `mailbox`; `address` a box (`*`: any box), an event's box, an
90
+ * HTTP path (with `prefix: true` for a prefix), a libp2p topic or
91
+ * `/<protocol>`; `filters` what runs before anything is recorded
92
+ * ("kernel.brc104", "kernel.beef", "<app>.<filter>"); `program` a program name
93
+ * (bin/<name>), a program record's CID, or `kernel` (an admin route: `fn` the
94
+ * operation — objects, head, dispatch, peers, grant, claim, tick), absent for a
95
+ * read route (http: its filters answer); `fn` a handler's function; anything
96
+ * else a handler's own setting (a file handler's `root`, `index`). No `sender`
97
+ * (#143).
98
+ */
99
+ export interface DispatchSpec {
100
+ transport?: Transport;
101
+ address: string;
102
+ prefix?: boolean;
103
+ filters?: string[];
104
+ program?: string;
105
+ fn?: string;
106
+ [setting: string]: unknown;
107
+ }
108
+ /**
109
+ * The kernel's admin operations (#77, #143: and `grant`), one per table, each gated by root. Every
110
+ * genesis carries their routes — `{address: <op>, program: kernel, fn: <op>}` — ahead of its own
111
+ * (#31: a bare genesis is the tables and the admin routes; a bundle adds what its apps ask for).
112
+ * Delegating is a grant (root, or an app's role), never another route.
113
+ */
114
+ export declare const ADMIN_OPS: readonly ["objects", "head", "dispatch", "peers", "grant"];
115
+ export declare const ADMIN_ROWS: DispatchSpec[];
116
+ /** What a kernel route may name: the admin operations, the claim (#89), and the host's tick (#130: the host row, billing.ts). */
117
+ export declare const KERNEL_OPS: readonly ["objects", "head", "dispatch", "peers", "grant", "claim", "tick"];
118
+ /**
119
+ * The claim route (#89, #143): an image's route to the kernel. A message in box `claim`, from anyone:
120
+ * root is granted to its sender (#127) and this route removed (a second claim finds no route). The
121
+ * claimant's own message (`skein claim`), or a claim signed before the instance existed, which the
122
+ * host's instance manager forwards as its first entry before the hostname is published
123
+ * (Router.createInstance).
124
+ */
125
+ export declare const CLAIM_ROW: DispatchSpec;
126
+ /** The BRC-103 handshake's route (#143): the front door's, no filters (it makes the session). */
127
+ export declare const HANDSHAKE_ROW: DispatchSpec;
128
+ /**
129
+ * The stock HTTP routes (#40, #143): the BRC-33 messagebox, at the root and under /messagebox (where
130
+ * older clients were pointed), behind kernel.brc104 (a session: the caller is its key); the
131
+ * explorer's route (the front door's `explore`: log, threads, heads, records as JSON), behind
132
+ * kernel.brc104 and gated by root (STOCK_ROLES); the handshake.
133
+ */
134
+ export declare const STOCK_HTTP: DispatchSpec[];
135
+ /** What gates the genesis's own programs' functions (#143): the explorer is root's. */
136
+ export declare const STOCK_ROLES: Record<string, string[]>;
137
+ /**
138
+ * The stock seed (#77), after the admin routes: the reserved box the host admits events into, `:ack`
139
+ * (the messagebox moves a reader's pointer: an event, #143); and the stock HTTP routes. No `run`, no
140
+ * `chat` (#83): the shell and the chat loop are apps. No `register` box (#40): registration is
141
+ * application wiring.
142
+ */
143
+ export declare const STOCK_DISPATCH: DispatchSpec[];
144
+ /**
145
+ * A mailbox instance's seed (#40): the messagebox's acknowledgements, and every message in any box to
146
+ * the messagebox (kept for its root; a mailbox exists only where such a route does).
147
+ */
148
+ export declare const MAILBOX_DISPATCH: DispatchSpec[];
149
+ /**
150
+ * The write scopes of the stock genesis-wired programs (#77): the heads each
151
+ * may advance, by program name. The front door's sessions; the messagebox's
152
+ * lists (#126: its outbound sessions are the kernel's, authfetch); the wallet's records (#79: `wallet/…`, its
153
+ * coins, actions, drafts and outputs — the chain is the chain app's). The
154
+ * resolve program's records (#87: `resolve/peers`, what a BRC-169 lookup
155
+ * found — never the address book, which only root's `peers` messages
156
+ * change; the messagebox's delivery reads them for a key the address book
157
+ * does not name).
158
+ */
159
+ export declare const STOCK_SCOPES: Record<string, string[]>;
160
+ /** A system's config (etc/config.json): every field optional; keys in hex, `$self`, `$infer` or a provider's `$<name>`. */
161
+ export interface ConfigSpec {
162
+ defaults?: Record<string, string>;
163
+ peers?: Record<string, string>;
164
+ names?: Array<{
165
+ identityKey: string;
166
+ handle: string;
167
+ domain: string;
168
+ }>;
169
+ collect?: string[];
170
+ feeds?: FeedSpec[];
171
+ /** The root holder as a peer (#40): its messagebox URL — the one peer a genesis names. */
172
+ owner?: {
173
+ messagebox?: string;
174
+ };
175
+ /** libp2p (#51): the topics the host subscribes for the instance, the protocols it serves, the node's own listen addresses. */
176
+ libp2p?: Libp2pSpec;
177
+ /** Write scopes of the tree's genesis-wired programs (#77), over STOCK_SCOPES: program name → head names (a prefix ends in `/`). */
178
+ scopes?: Record<string, string[]>;
179
+ /** What gates the tree's genesis-wired programs' functions (#143), over STOCK_ROLES: {<role>: ["<program>.<fn>"]}. */
180
+ roles?: Record<string, string[]>;
181
+ }
182
+ /**
183
+ * libp2p as a system writes it (etc/config.json `libp2p`, #51): `topics` the
184
+ * host's node subscribes (each message a front-door step; its `libp2p` route
185
+ * comes from etc/dispatch.json), `protocols` it serves, each naming its
186
+ * handler — a program (bin/ name or CID; fn "libp2p") or {program, fn} —
187
+ * which becomes its route (unless the tree has one), `listen` this node's
188
+ * addresses over the host's.
189
+ */
190
+ export interface Libp2pSpec {
191
+ topics?: string[];
192
+ protocols?: Record<string, string | {
193
+ program: string;
194
+ fn?: string;
195
+ }>;
196
+ listen?: string[];
197
+ }
198
+ /** A system resolved for one instance: what its genesis says besides who it is. */
199
+ export interface System {
200
+ programs: Record<string, CID>;
201
+ /** The route table's seed (#77), programs resolved. */
202
+ dispatch: DispatchRow[];
203
+ /** What gates the genesis's own programs' functions (#143). */
204
+ roles: Record<string, string[]>;
205
+ scopes: Record<string, string[]>;
206
+ peers?: Record<string, Uint8Array>;
207
+ defaults: Record<string, string>;
208
+ names: Array<{
209
+ identityKey: Uint8Array;
210
+ handle: string;
211
+ domain: string;
212
+ }>;
213
+ collect: string[];
214
+ /** The system tree (a git tree CID): `main` starts there. */
215
+ tree?: CID;
216
+ feeds?: FeedSpec[];
217
+ /** libp2p (#51): what the host's libp2p node does for the instance. */
218
+ libp2p?: {
219
+ topics: string[];
220
+ protocols: string[];
221
+ listen?: string[];
222
+ };
223
+ /** #141: heads the genesis sets (an image's installed apps: `<app>/app`), name → record CID. */
224
+ heads?: Record<string, CID>;
225
+ }
226
+ /** A system's libp2p, checked: the genesis's `libp2p` and the routes its protocols add (those the tree lacks). */
227
+ export declare function libp2pIn(spec: Libp2pSpec | undefined, specs: DispatchSpec[]): {
228
+ libp2p?: System["libp2p"];
229
+ specs: DispatchSpec[];
230
+ };
231
+ /** A key as a system writes it: hex, or `$self` / `$infer` (the host's), or a provider's `$<name>` (Genesis2Config.providers). */
232
+ export declare function keyOf(s: string, c: Pick<Genesis2Config, "infer" | "providers"> & {
233
+ identity?: string;
234
+ }): Uint8Array;
235
+ /** A `$<name>` that this host has no provider for. */
236
+ export declare class NoProvider extends Error {
237
+ readonly provider: string;
238
+ constructor(provider: string);
239
+ }
240
+ /** The routes of a system's specs (etc/dispatch.json, #77, #143), programs resolved; a route to a program the system lacks is dropped. */
241
+ export declare function rowsOf(specs: DispatchSpec[], programs: Record<string, CID>): DispatchRow[];
242
+ /**
243
+ * Resolve a system's routes, config and programs for one instance (both genesis paths). `specs` is
244
+ * its etc/dispatch.json. The order: the admin routes (every genesis), the dispatch specs, the
245
+ * host's extra box routes and routes, then the protocols' routes. A route with an admin route's key
246
+ * is left out (the kernel's operation keeps the box), with a warning.
247
+ */
248
+ export declare function resolveSystem(c: Genesis2Config, programs: Record<string, CID>, config?: ConfigSpec, tree?: CID, specs?: DispatchSpec[]): System;
249
+ /** The stock system in code: the kernel's pinned programs (its `programs` frame) and the stock seed. */
250
+ export declare function codeSystem(c: Genesis2Config, programs: Record<string, CID>): System;
251
+ /** The genesis record: who the instance is, and its system. */
252
+ export declare function genesisRecord(c: Pick<Genesis2Config, "identity" | "root" | "handle" | "domain" | "addressBook">, s: System): Record<string, unknown>;
253
+ /** The genesis record for a new instance over the kernel's programs (name → program record CID): code genesis. */
254
+ export declare function genesis2(c: Genesis2Config, programs: Record<string, CID>): Record<string, unknown>;
255
+ /** Write a genesis over `s` into an empty store through its kernel; the entry's CID. */
256
+ export declare function writeSystemGenesis(k: Kernel, c: Genesis2Config, s: System, time?: Stamp): Promise<CID>;
257
+ /** Code genesis (the stock system) into an empty store; the entry's CID. */
258
+ export declare function writeGenesis(k: Kernel, c: Genesis2Config, time?: Stamp): Promise<CID>;
259
+ export {};