@dcasegr/skein 0.1.1 → 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.
package/README.md CHANGED
@@ -82,7 +82,10 @@ every user skein: the front door, the messagebox, the wallet, and one row
82
82
  to the kernel, `claim`, from anyone: the first claim's sender owns it
83
83
  (#127), so claim it first thing. The host signs no user's claim; `skein
84
84
  claim --messagebox <url>` names where the instance reaches its owner. A
85
- second claim is refused. It has no apps (#152). After the claim, install
85
+ second claim is refused. `GET <its origin>/.well-known/skein` answers
86
+ `{handle, identity, origin, claimed}` (the host's read: whether anyone
87
+ holds root yet); `GET /skeins?key=<key>` lists the instances a key is root
88
+ on. It has no apps (#152). After the claim, install
86
89
  the chain, git and site apps by message, and root's route `/` to the site:
87
90
 
88
91
  ```
@@ -732,6 +732,15 @@ export declare class Router {
732
732
  * in a wallet tracks them). Unsigned, anyone; mailbox instances are not listed.
733
733
  */
734
734
  private skeinsHeldBy;
735
+ /**
736
+ * GET /.well-known/skein at an instance's origin (its hostname, `/@<handle>/`, or the root instance's
737
+ * hostname): `{handle, identity, origin, claimed}` — `claimed` whether its head `grants` names a root
738
+ * holder (an image instance nobody has claimed: false). Read from its store read-only, no kernel, as
739
+ * /skeins does. Unsigned, anyone; 404 for no instance. "Am I root" is /skeins?key=<identity>.
740
+ */
741
+ private instanceCard;
742
+ /** The keys an instance's head `grants` names root (#143), its store read read-only; none when it has no store yet. */
743
+ private rootsOf;
735
744
  /** A forwarded request, held among the in-flight ones (shutdown answers them 503). */
736
745
  private held;
737
746
  /**
@@ -27,6 +27,8 @@
27
27
  // With no host skein: 404 (tests may answer them with a fixture: `discovery`).
28
28
  // GET /skeins?key=<hex> at the host's own origin: the skeins here whose head `grants` names the key
29
29
  // among root's holders, [{handle, identity, url}] (no wallet token tracks them)
30
+ // GET /.well-known/skein at an instance's origin (its hostname, /@<handle>/, the root instance's): {handle,
31
+ // identity, origin, claimed} — claimed: its head `grants` names a root holder
30
32
  // GET /.well-known/skein-host at every host name, an instance's too (#103): {origin, domain} — this
31
33
  // router's origin and the handle domain (the onboarding app's
32
34
  // config.onboard.domain), for a page an instance serves (the management
@@ -2060,6 +2062,9 @@ export class Router {
2060
2062
  return await this.held(this.forward(o.handle, url.pathname, url, req));
2061
2063
  }
2062
2064
  const serve = async (x) => {
2065
+ // The instance's own card, the host's read (no program): whether anyone holds root yet.
2066
+ if (req.method === "GET" && x.route === "/.well-known/skein")
2067
+ return await this.instanceCard(x.handle);
2063
2068
  // #138: the liveness tool's read, the host's own (no program).
2064
2069
  const live = req.method === "GET" ? /^\/([^/]+)\/\.live\/([^/]+)$/.exec(x.route) : null;
2065
2070
  if (live)
@@ -2183,24 +2188,41 @@ export class Router {
2183
2188
  return json(400, { status: "error", code: "ERR_BAD_REQUEST", description: "key: an identity key (33 bytes, hex)" });
2184
2189
  const out = [];
2185
2190
  for (const row of this.o.db.list("enabled")) {
2186
- if (row.kind === "mailbox" || !row.identity || !storeExists(storeSpec(row)))
2191
+ if (row.kind === "mailbox" || !row.identity)
2187
2192
  continue;
2188
- let roots;
2189
- const s = openStoreFile(storeSpec(row), { readOnly: true });
2190
- try {
2191
- roots = await rootOf(s);
2192
- }
2193
- catch {
2194
- roots = [];
2195
- }
2196
- finally {
2197
- s.close();
2198
- }
2199
- if (roots.includes(key))
2193
+ if ((await this.rootsOf(row)).includes(key))
2200
2194
  out.push({ handle: row.handle, identity: row.identity, url: this.originOf(row.handle) });
2201
2195
  }
2202
2196
  return json(200, out);
2203
2197
  }
2198
+ /**
2199
+ * GET /.well-known/skein at an instance's origin (its hostname, `/@<handle>/`, or the root instance's
2200
+ * hostname): `{handle, identity, origin, claimed}` — `claimed` whether its head `grants` names a root
2201
+ * holder (an image instance nobody has claimed: false). Read from its store read-only, no kernel, as
2202
+ * /skeins does. Unsigned, anyone; 404 for no instance. "Am I root" is /skeins?key=<identity>.
2203
+ */
2204
+ async instanceCard(handle) {
2205
+ const row = this.o.db.get(handle);
2206
+ if (!row?.identity)
2207
+ return json(404, { status: "error", code: "ERR_NOT_FOUND", description: `no instance ${handle} here` });
2208
+ return json(200, { handle, identity: row.identity, origin: this.originOf(handle), claimed: (await this.rootsOf(row)).length > 0 });
2209
+ }
2210
+ /** The keys an instance's head `grants` names root (#143), its store read read-only; none when it has no store yet. */
2211
+ async rootsOf(row) {
2212
+ const spec = storeSpec(row);
2213
+ if (!storeExists(spec))
2214
+ return [];
2215
+ const s = openStoreFile(spec, { readOnly: true });
2216
+ try {
2217
+ return await rootOf(s);
2218
+ }
2219
+ catch {
2220
+ return [];
2221
+ }
2222
+ finally {
2223
+ s.close();
2224
+ }
2225
+ }
2204
2226
  /** A forwarded request, held among the in-flight ones (shutdown answers them 503). */
2205
2227
  async held(p) {
2206
2228
  this.inflight.add(p);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcasegr/skein",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "A deterministic WASI machine over a content-addressed graph: the node host (it loads the wasm kernel, kernel-zig built for the web target), the client, its peers, and dev tools.",
5
5
  "type": "module",
6
6
  "bin": {