@nervur-org/dock 0.3.1 → 0.4.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/GETTING_STARTED.md +22 -12
- package/{beings/GLOSSARY.md → GLOSSARY.md} +3 -3
- package/NOTICE +1 -1
- package/README.md +20 -16
- package/{beings/WORLDS.md → WORLDS.md} +6 -4
- package/api/route.ts +3 -3
- package/beings/avatar.ts +2 -2
- package/beings/carry.ts +2 -2
- package/beings/clock.ts +2 -2
- package/beings/courier.ts +2 -2
- package/beings/desk.ts +2 -2
- package/beings/doorbell.ts +2 -2
- package/beings/envoy.ts +2 -2
- package/beings/join.ts +2 -2
- package/beings/link.ts +5 -5
- package/beings/look.ts +1 -1
- package/beings/porter.ts +2 -2
- package/beings/presence.ts +1 -1
- package/beings/setup.ts +3 -3
- package/beings/side.ts +2 -2
- package/beings/user.ts +2 -2
- package/beings/way.ts +1 -1
- package/cli/client.ts +6 -6
- package/cli/daemon.ts +7 -7
- package/cli/estate/{quo.service → nervur.service} +12 -12
- package/cli/estate/org.nervur.plist +44 -0
- package/cli/estate.ts +6 -6
- package/cli/{quo.ts → nervur.ts} +43 -37
- package/cli/pilot.ts +3 -3
- package/cli/stand.ts +3 -3
- package/dist/api/route.d.ts +2 -2
- package/dist/api/route.js +2 -2
- package/dist/beings/avatar.d.ts +1 -1
- package/dist/beings/avatar.js +1 -1
- package/dist/beings/carry.d.ts +2 -2
- package/dist/beings/carry.js +1 -1
- package/dist/beings/clock.d.ts +2 -2
- package/dist/beings/clock.js +1 -1
- package/dist/beings/courier.d.ts +2 -2
- package/dist/beings/courier.js +1 -1
- package/dist/beings/desk.d.ts +3 -3
- package/dist/beings/desk.js +1 -1
- package/dist/beings/doorbell.d.ts +3 -3
- package/dist/beings/doorbell.js +1 -1
- package/dist/beings/envoy.d.ts +2 -2
- package/dist/beings/envoy.js +1 -1
- package/dist/beings/join.d.ts +2 -2
- package/dist/beings/link.d.ts +2 -2
- package/dist/beings/link.js +3 -3
- package/dist/beings/look.d.ts +1 -1
- package/dist/beings/porter.d.ts +2 -2
- package/dist/beings/porter.js +1 -1
- package/dist/beings/presence.d.ts +1 -1
- package/dist/beings/setup.d.ts +1 -1
- package/dist/beings/side.d.ts +1 -1
- package/dist/beings/side.js +1 -1
- package/dist/beings/user.d.ts +3 -3
- package/dist/beings/user.js +1 -1
- package/dist/beings/way.d.ts +1 -1
- package/dist/cli/client.js +4 -4
- package/dist/cli/daemon.d.ts +1 -1
- package/dist/cli/daemon.js +6 -6
- package/dist/cli/estate/{quo.service → nervur.service} +12 -12
- package/dist/cli/estate/org.nervur.plist +44 -0
- package/dist/cli/estate.js +6 -6
- package/dist/cli/{quo.js → nervur.js} +43 -37
- package/dist/cli/stand.d.ts +2 -2
- package/dist/dock/agents.d.ts +1 -1
- package/dist/dock/agents.js +1 -1
- package/dist/dock/apns.js +1 -1
- package/dist/dock/console.d.ts +1 -1
- package/dist/dock/dialers.d.ts +2 -2
- package/dist/dock/dialers.js +2 -2
- package/dist/dock/faculty.d.ts +2 -2
- package/dist/dock/faculty.js +1 -1
- package/dist/dock/grants.d.ts +1 -1
- package/dist/dock/grants.js +1 -1
- package/dist/dock/http2.js +1 -1
- package/dist/dock/index.d.ts +1 -1
- package/dist/dock/index.js +1 -1
- package/dist/dock/local.d.ts +2 -2
- package/dist/dock/location.d.ts +1 -1
- package/dist/dock/notifications.d.ts +1 -1
- package/dist/dock/notifications.js +1 -1
- package/dist/dock/push.d.ts +1 -1
- package/dist/dock/push.js +3 -3
- package/dist/dock/service.js +1 -1
- package/dist/dock/timer.d.ts +1 -1
- package/dist/harbor/browser.d.ts +2 -2
- package/dist/harbor/browser.js +4 -4
- package/dist/harbor/capacitor.d.ts +1 -1
- package/dist/harbor/capacitor.js +1 -1
- package/dist/harbor/disk.d.ts +4 -4
- package/dist/harbor/disk.js +5 -5
- package/dist/harbor/edge/edge.d.ts +2 -2
- package/dist/harbor/edge/edge.js +5 -5
- package/dist/harbor/edge/exercise.js +8 -8
- package/dist/harbor/edge/given.d.ts +1 -1
- package/dist/harbor/edge/platform.d.ts +1 -1
- package/dist/harbor/edge/storage.d.ts +1 -1
- package/dist/harbor/edge/storage.js +2 -2
- package/dist/harbor/edge/worker.js +2 -2
- package/dist/harbor/files.d.ts +1 -1
- package/dist/harbor/files.js +2 -2
- package/dist/harbor/http.d.ts +2 -2
- package/dist/harbor/http.js +1 -1
- package/dist/harbor/idb.d.ts +1 -1
- package/dist/harbor/idb.js +0 -0
- package/dist/harbor/quo.js +1 -1
- package/dist/harbor/seal.js +1 -1
- package/dist/harbor/sealed.d.ts +1 -1
- package/dist/harbor/sealed.js +4 -4
- package/dist/harbor/tauri.d.ts +1 -1
- package/dist/harbor/tauri.js +1 -1
- package/dist/harbor/ward.d.ts +1 -1
- package/dist/human/app.d.ts +2 -2
- package/dist/human/door.js +4 -4
- package/dist/human/guest.js +1 -1
- package/dist/human/html.d.ts +1 -1
- package/dist/human/html.js +1 -1
- package/dist/human/local.d.ts +1 -1
- package/dist/human/mark.js +2 -2
- package/dist/human/move.d.ts +2 -2
- package/dist/human/move.js +1 -1
- package/dist/human/screen.d.ts +1 -1
- package/dist/human/screen.js +3 -3
- package/dist/human/tab.bundle.txt +32 -32
- package/dist/human/tab.js +7 -7
- package/dist/human/tree.d.ts +1 -1
- package/dist/human/wake.d.ts +2 -2
- package/dist/human/wake.js +1 -1
- package/dist/human/web.d.ts +1 -1
- package/dist/human/web.js +4 -4
- package/dist/human/worker.bundle.txt +27 -27
- package/dist/human/worker.js +4 -4
- package/dist/human/worlds.d.ts +2 -2
- package/dist/human/worlds.js +4 -4
- package/dist/mcp/agent.d.ts +1 -1
- package/dist/mcp/allow.d.ts +1 -1
- package/dist/mcp/allow.js +2 -2
- package/dist/mcp/oauth.js +1 -1
- package/dist/mcp/runner.d.ts +1 -1
- package/dist/mcp/server.d.ts +2 -2
- package/dist/mcp/server.js +2 -2
- package/dock/agents.ts +2 -2
- package/dock/apns.ts +1 -1
- package/dock/console.ts +1 -1
- package/dock/dialers.ts +3 -3
- package/dock/faculty.ts +2 -2
- package/dock/grants.ts +2 -2
- package/dock/http2.ts +1 -1
- package/dock/index.ts +3 -3
- package/dock/local.ts +1 -1
- package/dock/location.ts +1 -1
- package/dock/notifications.ts +2 -2
- package/dock/push.ts +4 -4
- package/dock/service.ts +1 -1
- package/dock/timer.ts +1 -1
- package/harbor/browser.ts +5 -5
- package/harbor/capacitor.ts +2 -2
- package/harbor/disk.ts +8 -8
- package/harbor/edge/edge.ts +7 -7
- package/harbor/edge/exercise.ts +11 -11
- package/harbor/edge/given.ts +1 -1
- package/harbor/edge/platform.d.ts +1 -1
- package/harbor/edge/storage.ts +2 -2
- package/harbor/edge/worker.ts +2 -2
- package/harbor/edge/wrangler.toml +3 -3
- package/harbor/files.ts +2 -2
- package/harbor/http.ts +2 -2
- package/harbor/idb.ts +0 -0
- package/harbor/quo.ts +1 -1
- package/harbor/resolve.ts +1 -1
- package/harbor/seal.ts +1 -1
- package/harbor/sealed.ts +5 -5
- package/harbor/tauri.ts +2 -2
- package/harbor/ward.ts +1 -1
- package/human/app.ts +2 -2
- package/human/apps.ts +1 -1
- package/human/door.ts +4 -4
- package/human/guest.ts +2 -2
- package/human/html.ts +2 -2
- package/human/local.ts +1 -1
- package/human/mark.ts +2 -2
- package/human/move.ts +3 -3
- package/human/screen.ts +5 -5
- package/human/tab.bundle.txt +32 -32
- package/human/tab.ts +10 -10
- package/human/tree.ts +1 -1
- package/human/wake.ts +3 -3
- package/human/web.ts +5 -5
- package/human/worker.bundle.txt +27 -27
- package/human/worker.ts +6 -6
- package/human/worlds.ts +5 -5
- package/mcp/agent.ts +1 -1
- package/mcp/allow.ts +5 -5
- package/mcp/oauth.ts +1 -1
- package/mcp/runner.ts +1 -1
- package/mcp/server.ts +3 -3
- package/package.json +15 -7
- package/{api/quo-api.md → quo-api.md} +1 -1
- package/{beings/quo-dock.md → quo-dock.md} +74 -71
- package/{harbor/quo-harbor.md → quo-harbor.md} +54 -30
- package/{human/quo-human.md → quo-human.md} +7 -7
- package/{mcp/quo-mcp.md → quo-mcp.md} +10 -10
- package/cli/estate/systems.quo.plist +0 -44
- package/cli/quo-dock.md +0 -1942
- package/dist/cli/estate/systems.quo.plist +0 -44
- package/dock/quo-app-bells.md +0 -280
- package/dock/quo-dock.md +0 -1942
- /package/dist/cli/{quo.d.ts → nervur.d.ts} +0 -0
- /package/{beings/quo-app-bells.md → quo-app-bells.md} +0 -0
package/dist/harbor/browser.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { BeingClass } from '
|
|
2
|
-
import { Harbor, type Dialer, type Lend, type Store } from '
|
|
1
|
+
import type { BeingClass } from 'nervur';
|
|
2
|
+
import { Harbor, type Dialer, type Lend, type Store } from 'nervur/harbor';
|
|
3
3
|
export declare const BUILT_IN: Record<string, BeingClass>;
|
|
4
4
|
export declare class BrowserHarbor extends Harbor {
|
|
5
5
|
#private;
|
package/dist/harbor/browser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { User, Desk, Avatar, Presence, Courier } from '../beings/index.js';
|
|
2
|
-
import { Harbor, dial } from '
|
|
2
|
+
import { Harbor, dial } from 'nervur/harbor';
|
|
3
3
|
import { FACULTY_CLASSES, settled, stand } from '../dock/index.js';
|
|
4
4
|
import { Idb } from './idb.js';
|
|
5
5
|
export const BUILT_IN = { User, Desk, Avatar, Presence, Courier, ...FACULTY_CLASSES };
|
|
@@ -11,10 +11,10 @@ export class BrowserHarbor extends Harbor {
|
|
|
11
11
|
// `lend` is what this box lends the beings of the wards it hosts: a name
|
|
12
12
|
// to an invitation on a being of its own ward. `stand` builds one; a bare
|
|
13
13
|
// tab hands none and every name answers null.
|
|
14
|
-
constructor(store = '
|
|
14
|
+
constructor(store = 'nervur', classes = {}, lend) {
|
|
15
15
|
const s = typeof store === 'string' ? new Idb(store) : store;
|
|
16
16
|
super(s, async () => ({ ...BUILT_IN, ...classes }), lend);
|
|
17
|
-
this.name = typeof store === 'string' ? store : '
|
|
17
|
+
this.name = typeof store === 'string' ? store : 'nervur';
|
|
18
18
|
this.#locked = typeof store === 'string';
|
|
19
19
|
}
|
|
20
20
|
// What this box lends, by name. A bare tab says nothing, stands no ward of
|
|
@@ -67,7 +67,7 @@ export class BrowserHarbor extends Harbor {
|
|
|
67
67
|
if (!locks)
|
|
68
68
|
return; // no web locks on this terrain: nothing vouches, as in the memory harbor
|
|
69
69
|
const granted = await new Promise((ok) => {
|
|
70
|
-
void locks.request(`
|
|
70
|
+
void locks.request(`nervur:${this.name}`, { ifAvailable: true }, (lock) => {
|
|
71
71
|
if (!lock) {
|
|
72
72
|
ok(false);
|
|
73
73
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Directory } from '@capacitor/filesystem';
|
|
2
|
-
import type { BeingClass, JsonObject } from '
|
|
2
|
+
import type { BeingClass, JsonObject } from 'nervur';
|
|
3
3
|
import { Location, Notifications, type Token, type Where } from '../dock/index.ts';
|
|
4
4
|
import { BrowserHarbor } from './browser.ts';
|
|
5
5
|
import { Sealed, type Files, type Secrets } from './sealed.ts';
|
package/dist/harbor/capacitor.js
CHANGED
|
@@ -158,7 +158,7 @@ export function phoneEar(sandbox = false, within = 10_000, named = {}) {
|
|
|
158
158
|
// The app's one harbor, booted, lending the phone's faculties to its wards,
|
|
159
159
|
// told `wake` every time the app comes to the foreground, since a phone
|
|
160
160
|
// asleep loses its sockets silently.
|
|
161
|
-
export async function nativeHarbor(name = '
|
|
161
|
+
export async function nativeHarbor(name = 'nervur', classes = {}) {
|
|
162
162
|
const h = new BrowserHarbor(await Native.open(name), { ...PHONE_FACULTIES, ...classes });
|
|
163
163
|
await h.stand(phoneLent);
|
|
164
164
|
await h.boot();
|
package/dist/harbor/disk.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { BeingClass } from '
|
|
2
|
-
import { Harbor, type Hosted, type Lend } from '
|
|
3
|
-
export type { Hosted, Bound } from '
|
|
4
|
-
export type { WardRecord } from '
|
|
1
|
+
import type { BeingClass } from 'nervur';
|
|
2
|
+
import { Harbor, type Hosted, type Lend } from 'nervur/harbor';
|
|
3
|
+
export type { Hosted, Bound } from 'nervur/harbor';
|
|
4
|
+
export type { WardRecord } from 'nervur/harbor';
|
|
5
5
|
export declare const BUILT_IN: Record<string, BeingClass>;
|
|
6
6
|
export declare function defaultWard(marked: string[], hosted: string[]): string;
|
|
7
7
|
export declare class DiskHarbor extends Harbor {
|
package/dist/harbor/disk.js
CHANGED
|
@@ -20,7 +20,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
20
20
|
// tab/index.ts the classes for the tab, served bundled by the web route: human/web.ts
|
|
21
21
|
// design/ the face this world wears: tokens.css, fonts.css, fonts/, served by the web route
|
|
22
22
|
// wards/<name>/ seed, rows/, ward.json, or one sealed
|
|
23
|
-
// blob when the daemon holds
|
|
23
|
+
// blob when the daemon holds NERVUR_SEED_KEY: see files.ts
|
|
24
24
|
// reach.json the directory's hints
|
|
25
25
|
import { mkdir, readFile, writeFile, unlink, stat } from 'node:fs/promises';
|
|
26
26
|
import { existsSync } from 'node:fs';
|
|
@@ -30,13 +30,13 @@ import { register } from 'node:module';
|
|
|
30
30
|
import process from 'node:process';
|
|
31
31
|
import { User, Desk, Avatar, Presence, Clock, Courier } from '../beings/index.js';
|
|
32
32
|
import { setup } from '../beings/setup.js';
|
|
33
|
-
import { Harbor, DEFAULT_CODE } from '
|
|
33
|
+
import { Harbor, DEFAULT_CODE } from 'nervur/harbor';
|
|
34
34
|
import { FACULTY_CLASSES, settled, stand } from '../dock/index.js';
|
|
35
35
|
import { Files } from './files.js';
|
|
36
36
|
export const BUILT_IN = { User, Desk, Avatar, Presence, Clock, Courier, ...FACULTY_CLASSES };
|
|
37
37
|
// The default ward, the one a caller means when naming none: the one marked,
|
|
38
38
|
// or the one ward hosted when there is exactly one, which is every harbor an
|
|
39
|
-
// adopter stands with one `
|
|
39
|
+
// adopter stands with one `nervur init`. Several wards and none marked is
|
|
40
40
|
// refused by name, since agents and a door would otherwise hang off a
|
|
41
41
|
// guess. The dock ward is furniture, never a candidate.
|
|
42
42
|
export function defaultWard(marked, hosted) {
|
|
@@ -52,7 +52,7 @@ export function defaultWard(marked, hosted) {
|
|
|
52
52
|
if (first !== undefined && more.length === 0)
|
|
53
53
|
return first;
|
|
54
54
|
const names = first === undefined ? [] : [first, ...more];
|
|
55
|
-
throw new Error(names.length === 0 ? 'this device hosts no ward: run `
|
|
55
|
+
throw new Error(names.length === 0 ? 'this device hosts no ward: run `nervur init`' : `this device hosts ${names.join(', ')} and says which is the default: nervur default <name>`);
|
|
56
56
|
}
|
|
57
57
|
// Folders held by a harbor in this process. The lease file names a pid, and
|
|
58
58
|
// a second harbor in the same pid would pass that check while still being a
|
|
@@ -152,7 +152,7 @@ export class DiskHarbor extends Harbor {
|
|
|
152
152
|
// The key the environment gives, the edge's name for it: from the
|
|
153
153
|
// Keychain through the app that spawned this daemon, or nothing on a
|
|
154
154
|
// droplet, whose folder stays plain under its file modes.
|
|
155
|
-
super(new Files(abs, process.env.
|
|
155
|
+
super(new Files(abs, process.env.NERVUR_SEED_KEY), async (rec) => ({ ...BUILT_IN, ...own, ...(await loadClasses(isAbsolute(rec.code) ? rec.code : join(abs, rec.code))) }), lend);
|
|
156
156
|
this.dir = abs;
|
|
157
157
|
}
|
|
158
158
|
// What this box lends, by name. Set before `boot` and read there; a box
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { BeingClass } from '
|
|
2
|
-
import { Harbor, Socket as Held } from '
|
|
1
|
+
import type { BeingClass } from 'nervur';
|
|
2
|
+
import { Harbor, Socket as Held } from 'nervur/harbor';
|
|
3
3
|
import { type Folder } from '../../human/web.ts';
|
|
4
4
|
import { Grants } from '../../dock/grants.ts';
|
|
5
5
|
import { type Routes } from '../../mcp/route.ts';
|
package/dist/harbor/edge/edge.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { isSilence } from '
|
|
1
|
+
import { isSilence } from 'nervur';
|
|
2
2
|
import { User, Desk, Avatar, Clock } from '../../beings/index.js';
|
|
3
3
|
import { setup } from '../../beings/setup.js';
|
|
4
|
-
import { Harbor, Socket as Held } from '
|
|
4
|
+
import { Harbor, Socket as Held } from 'nervur/harbor';
|
|
5
5
|
import { quoRoute } from '../quo.js';
|
|
6
6
|
import { webRoute } from '../../human/web.js';
|
|
7
7
|
import { DOCK, TIMER, Console, facultyOf, settled, stand } from '../../dock/index.js';
|
|
@@ -44,9 +44,9 @@ export class EdgeHarbor extends Harbor {
|
|
|
44
44
|
// says nothing, so it stands no ward of its own, as a command on a disk
|
|
45
45
|
// folder stands none.
|
|
46
46
|
static async open(state, env, deployed = {}) {
|
|
47
|
-
if (!env.
|
|
48
|
-
throw new Error('no
|
|
49
|
-
const harbor = new EdgeHarbor(new DurableStorage(state.storage, await sealKey(env.
|
|
47
|
+
if (!env.NERVUR_SEED_KEY)
|
|
48
|
+
throw new Error('no NERVUR_SEED_KEY: a seed is never kept plain on the edge');
|
|
49
|
+
const harbor = new EdgeHarbor(new DurableStorage(state.storage, await sealKey(env.NERVUR_SEED_KEY)), env.NERVUR_ROOT, deployed);
|
|
50
50
|
harbor.lent = LENT;
|
|
51
51
|
return harbor;
|
|
52
52
|
}
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
// crosses the route. Down is the reach refused on both; migrate lifts seed,
|
|
7
7
|
// partition and record out of one view into the other and boots there. It
|
|
8
8
|
// reports rather than throws, so the worker hands the list back and Node
|
|
9
|
-
// asserts on it. Only with `
|
|
10
|
-
import { conform, conformStore, conformReach } from '
|
|
11
|
-
import { request as byRequest } from '
|
|
12
|
-
import { Printer, Shop, Customer, Echo, Member } from '
|
|
9
|
+
// asserts on it. Only with `NERVUR_EXERCISE` set, which a deployment never sets.
|
|
10
|
+
import { conform, conformStore, conformReach } from 'nervur/conformance';
|
|
11
|
+
import { request as byRequest } from 'nervur/harbor';
|
|
12
|
+
import { Printer, Shop, Customer, Echo, Member } from 'nervur/conformance';
|
|
13
13
|
import { EdgeHarbor } from './edge.js';
|
|
14
14
|
import { DurableStorage } from './storage.js';
|
|
15
15
|
import { ROW_CEILING } from './given.js';
|
|
16
|
-
import { told } from '
|
|
16
|
+
import { told } from 'nervur';
|
|
17
17
|
import { sealKey } from '../seal.js';
|
|
18
18
|
const assert = {
|
|
19
19
|
equal(a, b, m) {
|
|
@@ -31,7 +31,7 @@ const DEPLOYED = { classes: { Printer, Shop, Customer, Echo, Member } };
|
|
|
31
31
|
// The harbors the exercise made, by sub name, for the router below.
|
|
32
32
|
const subs = new Map();
|
|
33
33
|
async function pair(state, env, run) {
|
|
34
|
-
const key = await sealKey(env.
|
|
34
|
+
const key = await sealKey(env.NERVUR_SEED_KEY ?? '');
|
|
35
35
|
const names = [`a-${run}-${Date.now()}`, `b-${run}-${Date.now()}`];
|
|
36
36
|
const harbors = names.map((n) => new EdgeHarbor(new DurableStorage(state.storage, key, `x:${n}:`), undefined, DEPLOYED));
|
|
37
37
|
for (const [i, h] of harbors.entries()) {
|
|
@@ -159,7 +159,7 @@ export async function exercise(request, base, path, state, env) {
|
|
|
159
159
|
const test = (name, opts, fn) => {
|
|
160
160
|
queued.push({ name, skip: opts.skip ?? false, fn });
|
|
161
161
|
};
|
|
162
|
-
const key = await sealKey(env.
|
|
162
|
+
const key = await sealKey(env.NERVUR_SEED_KEY ?? '');
|
|
163
163
|
let views = 0;
|
|
164
164
|
conformStore('durable storage', async () => new DurableStorage(state.storage, key, `s:${views++}:${Date.now()}:`), { test });
|
|
165
165
|
let lines = 0;
|
|
@@ -180,7 +180,7 @@ export async function exercise(request, base, path, state, env) {
|
|
|
180
180
|
// the same refusal. That the number a deployment runs under is the
|
|
181
181
|
// platform's own is the line below it, which asks the store directly.
|
|
182
182
|
test('[edge] a row past the object s ceiling is refused, the arrival that wrote it fails at the door, and she stands at what is kept', {}, async () => {
|
|
183
|
-
const key = await sealKey(env.
|
|
183
|
+
const key = await sealKey(env.NERVUR_SEED_KEY ?? '');
|
|
184
184
|
const small = 8_000;
|
|
185
185
|
const h = new EdgeHarbor(new DurableStorage(state.storage, key, `c:${Date.now()}:`, small), undefined, DEPLOYED);
|
|
186
186
|
await h.ready();
|
|
@@ -24,7 +24,7 @@ export type Storage = Rows & {
|
|
|
24
24
|
export type State = { id: { toString(): string; name?: string }; storage: Storage };
|
|
25
25
|
export type Stub = { fetch(input: string | Request, init?: RequestInit): Promise<Response> };
|
|
26
26
|
export type Namespace = { idFromName(name: string): unknown; get(id: unknown): Stub };
|
|
27
|
-
export type Env = { HARBOR: Namespace;
|
|
27
|
+
export type Env = { HARBOR: Namespace; NERVUR_SEED_KEY?: string; NERVUR_ROOT?: string; NERVUR_EXERCISE?: string };
|
|
28
28
|
// The server end of a WebSocketPair: the standard surface plus accept.
|
|
29
29
|
export type ServerSocket = { accept(): void; readyState: number; binaryType: string; send(data: string | Uint8Array): void; close(): void; addEventListener(type: string, fn: (e: never) => void): void };
|
|
30
30
|
declare global {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Kept, type Store, type WardRecord } from '
|
|
1
|
+
import { type Kept, type Store, type WardRecord } from 'nervur/harbor';
|
|
2
2
|
import { type Store as DanceStore } from '../../mcp/oauth.ts';
|
|
3
3
|
import type { Folder } from '../../human/web.ts';
|
|
4
4
|
import { type SettingsStore } from './given.ts';
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// value would write every being in it down whenever any one was asked.
|
|
8
8
|
//
|
|
9
9
|
// The seed is kept sealed under a
|
|
10
|
-
// key from the platform's secrets, `
|
|
10
|
+
// key from the platform's secrets, `NERVUR_SEED_KEY`, with the seal in
|
|
11
11
|
// `../seal.ts`, so the storage holds ciphertext and the secret store holds
|
|
12
12
|
// the one key, which is what the harbor document's table says the edge
|
|
13
13
|
// does. Values cross as JSON, as they do into a file, because the ward
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// own settings, under `settings`, and the design a world wears, one row per
|
|
17
17
|
// file under `design:<file>`, because the object is the whole of what this
|
|
18
18
|
// terrain has to keep anything in.
|
|
19
|
-
import { fromRows, rowsIn, rowsOf } from '
|
|
19
|
+
import { fromRows, rowsIn, rowsOf } from 'nervur/harbor';
|
|
20
20
|
import { seal, open } from '../seal.js';
|
|
21
21
|
import { emptyDance } from '../../mcp/oauth.js';
|
|
22
22
|
import { ROW_CEILING } from './given.js';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// edge is `<origin>/h/<name>/quo`, and its health `<origin>/h/<name>/health`.
|
|
6
6
|
// `wrangler.toml` beside this file names the class and the secrets.
|
|
7
7
|
//
|
|
8
|
-
// One thing lives here for the terrain test alone: with `
|
|
8
|
+
// One thing lives here for the terrain test alone: with `NERVUR_EXERCISE` set,
|
|
9
9
|
// which no deployment sets, `/exercise` runs the library's conformance
|
|
10
10
|
// suite inside the platform against two harbors in this one object, over
|
|
11
11
|
// two prefixed views of its storage, reaching each other by request
|
|
@@ -51,7 +51,7 @@ export class Quo {
|
|
|
51
51
|
// Where this harbor answers, as the world outside sees it: the routes a
|
|
52
52
|
// page hands its tab are these unless a root has named public ones.
|
|
53
53
|
const base = `${url.origin}/h/${m[1]}`;
|
|
54
|
-
if (this.env.
|
|
54
|
+
if (this.env.NERVUR_EXERCISE && (path === '/exercise' || path.startsWith('/x/')))
|
|
55
55
|
return exercise(request, base, path, this.state, this.env);
|
|
56
56
|
return (await this.harbor()).fetch(request, path, base);
|
|
57
57
|
}
|
package/dist/harbor/files.d.ts
CHANGED
package/dist/harbor/files.js
CHANGED
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
import { mkdir, readFile, writeFile, rename, readdir, rm, chmod } from 'node:fs/promises';
|
|
34
34
|
import { existsSync } from 'node:fs';
|
|
35
35
|
import { join } from 'node:path';
|
|
36
|
-
import { arithmetic } from '
|
|
37
|
-
import { HEAD, fromRows, rowsIn, rowsOf } from '
|
|
36
|
+
import { arithmetic } from 'nervur/ward';
|
|
37
|
+
import { HEAD, fromRows, rowsIn, rowsOf } from 'nervur/harbor';
|
|
38
38
|
import { sealKey, seal, open } from './seal.js';
|
|
39
39
|
const { hex, unhex } = arithmetic;
|
|
40
40
|
// A row's file. The head has a name of its own so that the empty key it goes
|
package/dist/harbor/http.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Server as HttpServer } from 'node:http';
|
|
2
|
-
import { Socket as Held } from '
|
|
3
|
-
import type { Dialer } from '
|
|
2
|
+
import { Socket as Held } from 'nervur/harbor';
|
|
3
|
+
import type { Dialer } from 'nervur/harbor';
|
|
4
4
|
import type { DiskHarbor } from './disk.ts';
|
|
5
5
|
export type Handler = (req: Request, rest: string) => Response | undefined | Promise<Response | undefined>;
|
|
6
6
|
export type Http = {
|
package/dist/harbor/http.js
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
import { createServer as createHttp } from 'node:http';
|
|
29
29
|
import { Readable } from 'node:stream';
|
|
30
30
|
import { WebSocketServer } from 'ws';
|
|
31
|
-
import { Socket as Held } from '
|
|
31
|
+
import { Socket as Held } from 'nervur/harbor';
|
|
32
32
|
// What a request may carry, on the doors that read a body: enough for any ask
|
|
33
33
|
// a ward seals, and not a body chosen by whoever is on the other end.
|
|
34
34
|
// The bytes are a `Uint8Array` and not a `Buffer`: a route runs on every
|
package/dist/harbor/idb.d.ts
CHANGED
package/dist/harbor/idb.js
CHANGED
|
Binary file
|
package/dist/harbor/quo.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// own door in `http.ts`, and a `WebSocketPair` at the edge, in the harbor
|
|
14
14
|
// there. What a dialer's socket becomes once it is held is the library's
|
|
15
15
|
// `Socket` on both.
|
|
16
|
-
import { SUITE } from '
|
|
16
|
+
import { SUITE } from 'nervur/harbor';
|
|
17
17
|
import { readAll } from './http.js';
|
|
18
18
|
// The route is public and carries sealed bytes, so any origin may POST
|
|
19
19
|
// to it: a tab on a world's web. reaching another world's quo. is the
|
package/dist/harbor/seal.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// environment, the phone under a key from the Keychain. AES-GCM under a
|
|
6
6
|
// 32-byte key, a fresh nonce each time, nonce and ciphertext together as
|
|
7
7
|
// hex. WebCrypto only, so it runs wherever a store does.
|
|
8
|
-
import { arithmetic } from '
|
|
8
|
+
import { arithmetic } from 'nervur/ward';
|
|
9
9
|
const { hex, unhex } = arithmetic;
|
|
10
10
|
// Bytes as the platform's crypto wants them: over a plain ArrayBuffer.
|
|
11
11
|
const plain = (b) => new Uint8Array(b);
|
package/dist/harbor/sealed.d.ts
CHANGED
package/dist/harbor/sealed.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
//
|
|
8
8
|
// <files>/<harbor>/wards/<name>.sealed
|
|
9
9
|
// <files>/<harbor>/reach.json
|
|
10
|
-
// <secrets>:
|
|
10
|
+
// <secrets>: nervur-<harbor> 32 bytes as hex
|
|
11
11
|
//
|
|
12
12
|
// Custody is the backup question, and opening the store answers it: a key
|
|
13
13
|
// with no folder is a reinstall, and the stale key is deleted; a folder
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// What a platform gives is two small things, files and secrets, and the
|
|
18
18
|
// rest is here once: the phone hands its plugins, the desk hands its core,
|
|
19
19
|
// and the memory harbor hands a map, which is where the rule is proven.
|
|
20
|
-
import { arithmetic } from '
|
|
20
|
+
import { arithmetic } from 'nervur/ward';
|
|
21
21
|
import { sealKey, seal, open } from './seal.js';
|
|
22
22
|
const { hex, unhex } = arithmetic;
|
|
23
23
|
export class Sealed {
|
|
@@ -33,7 +33,7 @@ export class Sealed {
|
|
|
33
33
|
// Open one harbor's store, applying the custody rule, minting the key and
|
|
34
34
|
// the folder when this is a fresh install.
|
|
35
35
|
static async open(harbor, files, secrets) {
|
|
36
|
-
const item = `
|
|
36
|
+
const item = `nervur-${harbor}`;
|
|
37
37
|
const root = `quo/${harbor}`;
|
|
38
38
|
let secret = await secrets.get(item);
|
|
39
39
|
const folder = await files.exists(root);
|
|
@@ -54,7 +54,7 @@ export class Sealed {
|
|
|
54
54
|
// Everything this harbor has, key and files: what a person does by hand
|
|
55
55
|
// to leave a device, and what a test does between two openings.
|
|
56
56
|
static async wipe(harbor, files, secrets) {
|
|
57
|
-
await secrets.remove(`
|
|
57
|
+
await secrets.remove(`nervur-${harbor}`);
|
|
58
58
|
if (await files.exists(`quo/${harbor}`))
|
|
59
59
|
await files.rmdir(`quo/${harbor}`);
|
|
60
60
|
}
|
package/dist/harbor/tauri.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BeingClass, JsonObject } from '
|
|
1
|
+
import type { BeingClass, JsonObject } from 'nervur';
|
|
2
2
|
import { Notifications } from '../dock/index.ts';
|
|
3
3
|
import { BrowserHarbor } from './browser.ts';
|
|
4
4
|
import { type Files, type Secrets } from './sealed.ts';
|
package/dist/harbor/tauri.js
CHANGED
|
@@ -45,7 +45,7 @@ export function deskSecrets(core) {
|
|
|
45
45
|
// wards. The core hands the faculty its notification center by being in
|
|
46
46
|
// the class body the harbor holds, which is the one place a terrain's
|
|
47
47
|
// body may hold a live object.
|
|
48
|
-
export async function deskHarbor(core, name = '
|
|
48
|
+
export async function deskHarbor(core, name = 'nervur', classes = {}) {
|
|
49
49
|
class Center extends DeskNotifications {
|
|
50
50
|
constructor(stance) {
|
|
51
51
|
super(stance, core);
|
package/dist/harbor/ward.d.ts
CHANGED
package/dist/human/app.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Harbor } from '
|
|
2
|
-
import type { Invitation, JsonObject } from '
|
|
1
|
+
import type { Harbor } from 'nervur/harbor';
|
|
2
|
+
import type { Invitation, JsonObject } from 'nervur';
|
|
3
3
|
import { type Joined, type World } from './worlds.ts';
|
|
4
4
|
import { type Bell } from './wake.ts';
|
|
5
5
|
import type { Token } from '../dock/index.ts';
|
package/dist/human/door.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// The door page: what a stranger sees where nothing lets them in. No
|
|
3
3
|
// invitation in the fragment, no relation in this tab's harbor, and nobody
|
|
4
4
|
// at the ward's door; or a harbor's root with no world to list. It is
|
|
5
|
-
//
|
|
5
|
+
// the dock's page and not the estate's: it says what this is and that a world
|
|
6
6
|
// here is entered by a link someone sends you, and it asks for nothing,
|
|
7
7
|
// since there is nothing a stranger could type that would let them in. A
|
|
8
8
|
// world that wants a face of its own has a public being with a page and a
|
|
@@ -18,7 +18,7 @@ export function doorTree(at) {
|
|
|
18
18
|
as: 'hero',
|
|
19
19
|
of: [
|
|
20
20
|
{ kind: 'image', src: MARK, alt: '' },
|
|
21
|
-
{ kind: 'text', text: '
|
|
21
|
+
{ kind: 'text', text: 'Nervur', role: 'title' },
|
|
22
22
|
{ kind: 'text', text: at.world ? `${at.world} at ${at.host}` : at.host, role: 'label' },
|
|
23
23
|
{ kind: 'text', text: at.world ? 'This world is entered by invitation.' : 'The worlds here are entered by invitation.', role: 'lead' },
|
|
24
24
|
{ kind: 'text', text: 'An invitation is a link someone sends you. Open it here, and you are in: no account, no password, nothing to type. What you can do inside is what the world shows you, and it is yours to keep on this device.' },
|
|
@@ -53,12 +53,12 @@ export function heldTree(at) {
|
|
|
53
53
|
export function held(at) {
|
|
54
54
|
return `<main data-door>${paint(heldTree(at), nobody)}</main>`;
|
|
55
55
|
}
|
|
56
|
-
// The policy every page
|
|
56
|
+
// The policy every page the dock writes itself is served under, wherever it is
|
|
57
57
|
// served from. These pages run no script and want none, so nothing but
|
|
58
58
|
// their own form is allowed anywhere, an image is the mark and therefore
|
|
59
59
|
// data, and no referer carries what brought a human here off the page.
|
|
60
60
|
export const POLICY = "default-src 'none'; style-src 'unsafe-inline'; img-src data:; form-action 'self'; base-uri 'none'; frame-ancestors 'none'";
|
|
61
|
-
// A painter for
|
|
61
|
+
// A painter for the dock's own pages. It is `nobody` with links painted, and
|
|
62
62
|
// that is sound where the other painter's caution is not: the vouching rule
|
|
63
63
|
// exists because a far being names a place and the side cannot know where
|
|
64
64
|
// she is sending a human. On these pages the dock wrote the address itself,
|
package/dist/human/guest.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// convention of the dock's like `hello`, `look` and `page`: a public being
|
|
14
14
|
// of any class takes proofs by writing an ask under that name, and one that
|
|
15
15
|
// writes none has no proof way in and loses nothing else.
|
|
16
|
-
import { isSilence, isWord, wordOf } from '
|
|
16
|
+
import { isSilence, isWord, wordOf } from 'nervur';
|
|
17
17
|
export function guest(avatar, ward) {
|
|
18
18
|
const at = { ward };
|
|
19
19
|
return {
|
package/dist/human/html.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Answer, Ask, Blueprint, Json, JsonObject } from '
|
|
1
|
+
import type { Answer, Ask, Blueprint, Json, JsonObject } from 'nervur';
|
|
2
2
|
import { type Word } from '../beings/side.ts';
|
|
3
3
|
import { hintFor, type Look, type Hint } from '../beings/look.ts';
|
|
4
4
|
import { type Node } from './tree.ts';
|
package/dist/human/html.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SILENCE_TEXT, UNREACHED_TEXT, word, wordText } from '../beings/side.js';
|
|
2
2
|
import { hint, hintFor, sanitise, groups as grouped, presentation } from '../beings/look.js';
|
|
3
3
|
import { paint, titled } from './tree.js';
|
|
4
|
-
import { isInvitation } from '
|
|
4
|
+
import { isInvitation } from 'nervur';
|
|
5
5
|
import { link } from '../beings/link.js';
|
|
6
6
|
export const escape = (s) => s.replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c] ?? c);
|
|
7
7
|
const props = (schema) => Object.entries((schema?.properties ?? {}));
|
package/dist/human/local.d.ts
CHANGED
package/dist/human/mark.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// The mark: a ring with a gap and a point at the centre, one being's voice
|
|
3
|
-
// reaching another's door. It is the one mark
|
|
4
|
-
// door page, on the desk app's dock icon and on the phone's home screen,
|
|
3
|
+
// reaching another's door. It is the one mark the dock and the app wear, on
|
|
4
|
+
// the door page, on the desk app's dock icon and on the phone's home screen,
|
|
5
5
|
// and it is drawn once here so those can never drift apart.
|
|
6
6
|
//
|
|
7
7
|
// The glyph is strokes on nothing, coloured by whoever draws it: the door
|
package/dist/human/move.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Harbor } from '
|
|
2
|
-
import type { Invitation } from '
|
|
1
|
+
import type { Harbor } from 'nervur/harbor';
|
|
2
|
+
import type { Invitation } from 'nervur';
|
|
3
3
|
import { type World } from './worlds.ts';
|
|
4
4
|
export declare const COURIER = "courier";
|
|
5
5
|
export type Giving = {
|
package/dist/human/move.js
CHANGED
package/dist/human/screen.d.ts
CHANGED
package/dist/human/screen.js
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
// through `html.ts`, calls the avatar when a form comes back, and re-asks
|
|
7
7
|
// her describe after each call, so a digest that moved is a page that
|
|
8
8
|
// moved. A push is appended and shown the moment it lands.
|
|
9
|
-
import { digest } from '
|
|
9
|
+
import { digest } from 'nervur';
|
|
10
10
|
import { word } from '../beings/side.js';
|
|
11
|
-
import { isInvitation } from '
|
|
11
|
+
import { isInvitation } from 'nervur';
|
|
12
12
|
import { page, values, hintFor, mine, asks, standing, stands } from './html.js';
|
|
13
13
|
import { sanitiseTree, answersIn } from './tree.js';
|
|
14
14
|
import { groups, sanitise } from '../beings/look.js';
|
|
15
|
-
import { isSilence, isWord } from '
|
|
15
|
+
import { isSilence, isWord } from 'nervur';
|
|
16
16
|
export async function screenSide(avatar, surface, options = {}) {
|
|
17
17
|
const after = options.after ?? (async () => { });
|
|
18
18
|
const notice = options.notice ?? '';
|