@dcasegr/skein 0.0.0-stage → 0.1.1

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 +522 -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 +773 -0
  89. package/dist/host/router.js +2389 -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,139 @@
1
+ // Installing an app (#72, #76, #77, #79, #143; docs/APPS.md §3): root's client. An
2
+ // app is a tree (a directory or a git repository) with etc/app.json;
3
+ // installing it into an instance is root-signed messages to the kernel's
4
+ // admin boxes — the kernel's own operations on its tables — nothing else, and
5
+ // no key (#143: the deployer is root, and grants itself nothing):
6
+ //
7
+ // 1. objects the tree's git objects, the modules its bin/*.wasm carry (a
8
+ // shell program's modules and support files too, #83), a program
9
+ // record per program, and the **app record** (below)
10
+ // — ≤ 1 MiB bundles; no bundle names a root (an app never
11
+ // becomes `main`)
12
+ // 2. head {name: "<app>/app", tree: <the app record>}: the app's root head, under its
13
+ // own name (owner = the app).
14
+ // 3. dispatch one per route the manifest asks for (#77, #143): {op: "add", row: {transport,
15
+ // address, prefix?, filters?, program?: <the handler's role's program record>,
16
+ // fn?, …settings, app}} — a box under the app's (#128: "" or `<app>` → `<app>`,
17
+ // "x" → `<app>/x`), an http address under /<app>/, a libp2p topic or protocol as
18
+ // written; the filters named in full (an own filter `<app>.<name>`); a read
19
+ // route (no handler) with no program.
20
+ // 4. start the manifest's `start.body`, into the app's box
21
+ //
22
+ // The **app record** is the head's root: the manifest as installed, so "what
23
+ // does this head provide" is one read (`head("<app>/app")`, `get`):
24
+ //
25
+ // {kind: "app", name, version, programs: {<role>: <program record CID>},
26
+ // routes: [<route as the manifest wrote it: relative addresses, handlers, filters as written>],
27
+ // filters?: {<filter>: <handler>}, roles?: {<role>: [<fn>…]},
28
+ // config?, provides, requires, start?, stop?, description?, tree: <the app's git tree>,
29
+ // state?: <the app's own state>}
30
+ //
31
+ // `state` is the app's: its handler advances the head to the record with
32
+ // `state` replaced (the SDK's app.Call.setState). An install over an earlier
33
+ // version carries `state` over, removes the routes the earlier record had and
34
+ // the new one does not, and sends `start` again (the restart). Uninstall:
35
+ // `stop`, then every route removed; the heads are left.
36
+ //
37
+ // **Write scope** (#77, #79): an app's programs write only heads under
38
+ // `<app>/` (the kernel's rule, by the program record's `app`). No alias head,
39
+ // no form before #77. Who may run an app's functions is its `roles`' and
40
+ // root's grants (#143), never the install's.
41
+ //
42
+ // **Two paths to the tree** (#91; docs/APPS.md §3). This client reads it from
43
+ // a directory or clones a repository itself (`readApp`, `fetchApp`:
44
+ // `skein install`, #124; a coding-session tool). Or the instance already holds
45
+ // it: the git app (shruggr/skein-git) cloned one commit into the store by
46
+ // hash and answered {tree, app}; `readStoredApp` reads that tree out of the
47
+ // store (reads are open), and the same `planInstall` rebuilds the app record
48
+ // — whose CID must be the git app's `app` — with nothing left to send but
49
+ // `head`, `dispatch` and `start`.
50
+ import { spawnSync } from "node:child_process";
51
+ import { existsSync, mkdtempSync, readFileSync, statSync } from "node:fs";
52
+ import { tmpdir } from "node:os";
53
+ import { join, resolve } from "node:path";
54
+ import { hashDir } from "../client/client.js";
55
+ import { defaultIgnore } from "../dev/scan.js";
56
+ import { currentDispatch } from "../runtime/dispatch.js";
57
+ import { headTree } from "../runtime/heads.js";
58
+ import { addressBook } from "./deploy.js";
59
+ import { checkManifest } from "./manifest.js";
60
+ import { appHead, parseManifest } from "./plan.js";
61
+ // The plan — what an install or an uninstall sends, read from an instance
62
+ // view — is ./plan.ts, which runs in a browser too (the management site,
63
+ // shruggr/skein-site, #92, plans an install over the explorer's reads).
64
+ export * from "./plan.js";
65
+ /** What a tree carries that is not the app: build output, dependencies, VCS. */
66
+ export function appIgnore(rel) {
67
+ const base = rel.slice(rel.lastIndexOf("/") + 1);
68
+ return defaultIgnore(rel) || base === "zig-out" || base === ".zig-cache" || base === "zig-pkg";
69
+ }
70
+ /** Read and check the app in `dir`. */
71
+ export async function readApp(dir) {
72
+ const p = join(dir, "etc/app.json");
73
+ if (!existsSync(p))
74
+ throw new Error(`${dir}: no etc/app.json (an app is a tree with a manifest: docs/APPS.md §2)`);
75
+ const json = parseManifest(readFileSync(p, "utf8"));
76
+ const isFile = (rel) => existsSync(join(dir, rel)) && statSync(join(dir, rel)).isFile();
77
+ const checked = checkManifest(json, isFile);
78
+ const { root, records } = await hashDir(dir, { ignore: appIgnore });
79
+ return { root, records, checked, read: (rel) => (isFile(rel) ? new Uint8Array(readFileSync(join(dir, rel))) : undefined) };
80
+ }
81
+ /**
82
+ * Where the app is: a directory, or a git repository URL (`<url>` or
83
+ * `<url>#<rev>`) cloned into a temporary directory.
84
+ */
85
+ export function fetchApp(spec) {
86
+ if (existsSync(spec) && statSync(spec).isDirectory())
87
+ return resolve(spec);
88
+ if (!/^(https?:\/\/|git@|ssh:\/\/|file:\/\/)/.test(spec))
89
+ throw new Error(`${spec}: not a directory or a git URL`);
90
+ const [url, rev] = spec.split("#");
91
+ const dir = join(mkdtempSync(join(tmpdir(), "skein-app-")), "app");
92
+ const git = (...args) => {
93
+ const r = spawnSync("git", args, { encoding: "utf8" });
94
+ if (r.status !== 0)
95
+ throw new Error(`git ${args.join(" ")}: ${r.stderr.trim() || `exit ${r.status}`}`);
96
+ };
97
+ git("clone", "-q", ...(rev ? [] : ["--depth", "1"]), url, dir);
98
+ if (rev)
99
+ git("-C", dir, "checkout", "-q", rev);
100
+ return dir;
101
+ }
102
+ // ---------------------------------------------------------------- the instance as the client sees it
103
+ /** The view of an instance's store file (the CLI's, the tests'). */
104
+ export async function instanceView(store) {
105
+ let g;
106
+ for await (const { entry } of store.log.entries(0)) {
107
+ const c = entry.genesis;
108
+ if (c)
109
+ g = await store.get(c);
110
+ break;
111
+ }
112
+ if (!g)
113
+ throw new Error("the instance's store has no genesis yet");
114
+ const heads = typeof store.heads === "function" ? store.heads() : [];
115
+ return {
116
+ store,
117
+ identity: g.identity instanceof Uint8Array ? Buffer.from(g.identity).toString("hex") : String(g.identity),
118
+ programs: (g.programs ?? {}),
119
+ addressBook: await addressBook(store),
120
+ heads,
121
+ dispatch: (await currentDispatch(store)) ?? [],
122
+ };
123
+ }
124
+ /** The root holders (hex) as the head `grants` names them (#143; none: an unclaimed image). */
125
+ export async function rootOf(store) {
126
+ const root = await headTree(store, "grants");
127
+ if (!root)
128
+ return [];
129
+ const g = await store.get(root).catch(() => undefined);
130
+ return g?.kind === "grants" ? (g.roles?.root ?? []).map((k) => Buffer.from(k).toString("hex")) : [];
131
+ }
132
+ /** The app record a head's root is, if it is one. */
133
+ export async function appRecordOf(store, name) {
134
+ const root = await headTree(store, appHead(name));
135
+ if (!root)
136
+ return undefined;
137
+ const r = await store.get(root).catch(() => undefined);
138
+ return r && r.kind === "app" ? { cid: root, record: r } : undefined;
139
+ }
@@ -0,0 +1,227 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ /**
3
+ * A handle: one hostname label (lower-case letters, digits and "-", at most
4
+ * 63, no "-" at either end), so `<handle>.<domain>` is the instance's origin.
5
+ * The one grammar for every row (H22): `add`, the instance manager's
6
+ * `create`, a mailbox instance.
7
+ */
8
+ export declare const HANDLE: RegExp;
9
+ /**
10
+ * A path-only handle (#161): a token id `<txid>_<vout>` (64 lower-case hex digits, `_`, the output
11
+ * index). Not a hostname label, so its instance is published under no hostname: it is reached at
12
+ * `/@<handle>/…` on the host's origin only (Router.target, originOf). Everything else about its row is
13
+ * a row's.
14
+ */
15
+ export declare const TOKEN_HANDLE: RegExp;
16
+ /** Whether `handle` is a handle this host takes (#161): a hostname label (HANDLE), or a path-only token id (TOKEN_HANDLE). */
17
+ export declare const validHandle: (handle: string) => boolean;
18
+ /** Whether `handle` is path-only (#161): a token id, reached by `/@<handle>` and never by a hostname. */
19
+ export declare const pathOnly: (handle: string) => boolean;
20
+ export type Status = "enabled" | "disabled";
21
+ export type Kind = "agent" | "mailbox";
22
+ /** One row of the fuel ledger. */
23
+ export interface Ledger {
24
+ instance: string;
25
+ caller: string;
26
+ op: string;
27
+ calls: number;
28
+ fuel: number;
29
+ updated_at: string;
30
+ }
31
+ export interface InstanceRow {
32
+ handle: string;
33
+ domain: string;
34
+ identity: string | null;
35
+ store: string;
36
+ tree: string | null;
37
+ source: string | null;
38
+ /** JSON array of handles, `["*"]` for every other row; null: none. See knowsOf. */
39
+ knows: string | null;
40
+ status: Status;
41
+ created_at: string;
42
+ kind?: Kind;
43
+ /** A mailbox instance's: whose mailbox it is (hex). */
44
+ owner?: string | null;
45
+ /**
46
+ * JSON array of the overlay names (gossip topics and lookup services alike) a bare-host POST /submit
47
+ * or /lookup naming them is routed to this instance by (#137: what the instance manager's create or
48
+ * start named; Router.overlayTarget); null: none. See topicsOf.
49
+ */
50
+ topics?: string | null;
51
+ }
52
+ /** The fields `add` sets; absent ones keep their value (or the column's default on insert). */
53
+ export type RowFields = Partial<Omit<InstanceRow, "handle" | "created_at">>;
54
+ /** The overlay names a row is routed by (#137): its `topics` column, a list (none: empty). */
55
+ export declare function topicsOf(row: Pick<InstanceRow, "topics">): string[];
56
+ /** The handles a row knows: a list, or "all" (every other enabled row). */
57
+ export declare function knowsOf(row: Pick<InstanceRow, "knows">): string[] | "all";
58
+ /** The `knows` column for a list of handles (`*` among them: everyone); an empty list is null. */
59
+ export declare function knowsColumn(handles: string[] | "all"): string | null;
60
+ export declare class HostDb {
61
+ readonly db: DatabaseSync;
62
+ /** `readOnly`: an existing file, read only (an instance's resolver beside the supervisor): no schema, no migration. */
63
+ constructor(path: string, o?: {
64
+ readOnly?: boolean;
65
+ });
66
+ /**
67
+ * Insert `handle`, or update the given fields of the row that has it (so a
68
+ * provisioning script can run again). A new row needs `store`.
69
+ */
70
+ add(handle: string, f: RowFields, now?: Date): InstanceRow;
71
+ get(handle: string): InstanceRow | undefined;
72
+ /**
73
+ * The identity handle@domain names (BRC-169's answer): an agent's own, or
74
+ * the owner of a mailbox instance (whose mailbox the instance is).
75
+ */
76
+ identityOf(handle: string, domain: string): string | undefined;
77
+ list(status?: Status): InstanceRow[];
78
+ /** Set which handles a row knows (knowsColumn); false if there is no such row. */
79
+ setKnows(handle: string, handles: string[] | "all"): boolean;
80
+ /** Set the overlay names a row is routed by (#137; topicsOf); an empty list is null; false if there is no such row. */
81
+ setTopics(handle: string, topics: string[]): boolean;
82
+ /** Set a row's status; false if there is no such row. */
83
+ setStatus(handle: string, status: Status): boolean;
84
+ /** Remove the row (not its store or wallet); false if there was none. */
85
+ remove(handle: string): boolean;
86
+ /** The enabled mailbox instance for identity `owner` (hex). */
87
+ /** A beat kept from `peer` on `handle`'s overlay `topic` (sync): upserted with its addresses (kept when none are known now). */
88
+ seenPeer(handle: string, topic: string, peer: string, addrs: string[], now: number): void;
89
+ /** The peers `handle`'s overlay `topic` heard beats from, the latest first. */
90
+ topicPeers(handle: string, topic: string): Array<{
91
+ peer: string;
92
+ addrs: string[];
93
+ lastSeen: number;
94
+ }>;
95
+ /** Forget the peers not heard from since `before` (ms). → how many rows went. */
96
+ prunePeers(before: number): number;
97
+ mailboxOf(owner: string): InstanceRow | undefined;
98
+ /** Add calls and fuel to the ledger (#40): `rows` aggregated by (instance, caller, op). */
99
+ charge(rows: Array<{
100
+ instance: string;
101
+ caller: string;
102
+ op: string;
103
+ calls: number;
104
+ fuel: number;
105
+ }>, now?: Date): void;
106
+ ledger(instance?: string): Ledger[];
107
+ /** The last event id taken from an SSE stream (#58), if any. */
108
+ cursor(stream: string): string | undefined;
109
+ setCursor(stream: string, id: string, now?: Date): void;
110
+ /** Note a status as routed (#58); false if it was already. */
111
+ markStatus(txid: string, status: string, now?: Date): boolean;
112
+ hasStatus(txid: string, status: string): boolean;
113
+ /** Queue a broadcast (#65, arc.ts), due now; one already queued keeps its schedule and gains `instance`. */
114
+ queueBroadcast(txid: string, body: Uint8Array, instance: string, now: number): void;
115
+ /** The queued broadcasts due at `now`, oldest first. */
116
+ dueBroadcasts(now: number): Array<{
117
+ txid: string;
118
+ body: Uint8Array;
119
+ instances: string[];
120
+ attempts: number;
121
+ since: number;
122
+ }>;
123
+ /** When the next queued broadcast is due (ms), if any. */
124
+ nextBroadcastAt(): number | undefined;
125
+ /** A queued broadcast Arcade did not take: one more attempt, posted again at `next`. */
126
+ retryBroadcast(txid: string, next: number, error: string): void;
127
+ /** A broadcast Arcade answered (or one given up): off the queue. */
128
+ unqueueBroadcast(txid: string): void;
129
+ /** The queue as it stands. */
130
+ broadcasts(): Array<{
131
+ txid: string;
132
+ attempts: number;
133
+ next: number;
134
+ error?: string;
135
+ }>;
136
+ /** Keep a cron schedule (#69): an instance's, by name (a later one replaces it). */
137
+ saveSchedule(s: {
138
+ instance: string;
139
+ name: string;
140
+ recipient: string;
141
+ spec: Uint8Array;
142
+ request: string;
143
+ next: number;
144
+ }): void;
145
+ /** Drop an instance's schedule; false if it had none by that name. */
146
+ dropSchedule(instance: string, name: string): boolean;
147
+ /** Every kept schedule. */
148
+ schedules(): Array<{
149
+ instance: string;
150
+ name: string;
151
+ recipient: string;
152
+ spec: Uint8Array;
153
+ request: string;
154
+ next: number;
155
+ }>;
156
+ /** The enabled row whose identity is `identity`. */
157
+ byIdentity(identity: string): InstanceRow | undefined;
158
+ /** A host setting (#90), if set. */
159
+ setting(key: string): string | undefined;
160
+ setSetting(key: string, value: string): void;
161
+ /** An object of the default image's chain part (#132), if held. */
162
+ imageBlock(cid: string): Uint8Array | undefined;
163
+ /** One write of the image's chain part (#132): objects put, objects dropped, settings set — all or nothing. */
164
+ writeImage(puts: Map<string, Uint8Array>, drops: Set<string>, settings: Record<string, string>): void;
165
+ /** A billed instance as last read (#130); asleep: when it went asleep (ms) is kept from the first time seen. */
166
+ setBilling(instance: string, b: {
167
+ host?: string;
168
+ tally?: bigint;
169
+ allocation?: bigint;
170
+ asleep: boolean;
171
+ mismatch?: string;
172
+ }, now: number, at?: Date): void;
173
+ billing(instance: string): {
174
+ instance: string;
175
+ host: string | null;
176
+ tally: string | null;
177
+ allocation: string | null;
178
+ asleep_since: number | null;
179
+ mismatch: string | null;
180
+ updated_at: string;
181
+ } | undefined;
182
+ billings(): Array<{
183
+ instance: string;
184
+ host: string | null;
185
+ tally: string | null;
186
+ allocation: string | null;
187
+ asleep_since: number | null;
188
+ mismatch: string | null;
189
+ updated_at: string;
190
+ }>;
191
+ /** The instances asleep since before `now - graceMs` (#130: the host may reclaim them). */
192
+ reclaimable(now: number, graceMs: number): Array<{
193
+ instance: string;
194
+ asleep_since: number;
195
+ }>;
196
+ forgetBilling(instance: string): void;
197
+ /** A period ticked (#130): its log record and CID. */
198
+ billingTick(instance: string, at: number, log: string, record: Uint8Array): void;
199
+ billingTicks(instance: string): Array<{
200
+ at: number;
201
+ log: string;
202
+ record: Uint8Array;
203
+ }>;
204
+ /** A payment taken (#130); false if it was already. */
205
+ billingPayment(p: {
206
+ instance: string;
207
+ txid: string;
208
+ amount: number;
209
+ at: number;
210
+ beef: Uint8Array;
211
+ remittance: unknown;
212
+ ours: boolean;
213
+ checkpoint?: string;
214
+ }): boolean;
215
+ billingPayments(instance?: string): Array<{
216
+ instance: string;
217
+ txid: string;
218
+ amount: number;
219
+ at: number;
220
+ ours: boolean;
221
+ checkpoint: string | null;
222
+ remittance: string;
223
+ }>;
224
+ /** The host skein (#90): the operator's instance (`skein-host init`), the one row whose identity reaches the instance manager. */
225
+ hostSkein(): InstanceRow | undefined;
226
+ close(): void;
227
+ }