@volter/teams 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/admission.mjs +2 -1
- package/channel.mjs +10 -3
- package/package.json +1 -1
- package/server/machine-link.mjs +2 -2
package/admission.mjs
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
// { id, caps, targets } rows from the caller's machine grants (design §11).
|
|
5
5
|
//
|
|
6
6
|
// Targets: `<kind>:<name>` for the kinds a product serves on this machine
|
|
7
|
-
// (the harness: `pane:<contextKey>`, `runtime:<id>`, `root:<path>`, `port:<pane>/<n
|
|
7
|
+
// (the harness: `pane:<contextKey>`, `runtime:<id>`, `root:<path>`, `port:<pane>/<n>`,
|
|
8
|
+
// `mail:<address>` for one session's mailbox),
|
|
8
9
|
// `<kind>:*` for every target of one kind, or `*` (operate and view only).
|
|
9
10
|
// `root:<path>` covers the path and everything under it.
|
|
10
11
|
|
package/channel.mjs
CHANGED
|
@@ -182,10 +182,17 @@ export class Channel extends EventEmitter {
|
|
|
182
182
|
this._streams = new Map();
|
|
183
183
|
this._nextStream = initiator ? 1 : 2;
|
|
184
184
|
this.closed = false;
|
|
185
|
+
// A broken channel ends every open stream with the reason, so each caller's
|
|
186
|
+
// request fails with it; 'error' is emitted only to someone listening for it,
|
|
187
|
+
// never as an uncaught exception that takes the process down.
|
|
188
|
+
const failed = (error) => {
|
|
189
|
+
this.error ??= error;
|
|
190
|
+
if (this.listenerCount('error') > 0) this.emit('error', error);
|
|
191
|
+
};
|
|
185
192
|
frameReader(
|
|
186
193
|
socket,
|
|
187
194
|
(frame) => this._onEnvelope(JSON.parse(frame.toString('utf8'))),
|
|
188
|
-
|
|
195
|
+
failed,
|
|
189
196
|
);
|
|
190
197
|
// The hello left the socket paused with any early frames unshifted; our reader is on now.
|
|
191
198
|
socket.resume();
|
|
@@ -196,12 +203,12 @@ export class Channel extends EventEmitter {
|
|
|
196
203
|
this.closed = true;
|
|
197
204
|
for (const stream of this._streams.values()) {
|
|
198
205
|
stream.closed = true;
|
|
199
|
-
stream._deliver('close', 'connection closed');
|
|
206
|
+
stream._deliver('close', this.error ? `connection closed: ${this.error.message}` : 'connection closed');
|
|
200
207
|
}
|
|
201
208
|
this._streams.clear();
|
|
202
209
|
this.emit('close');
|
|
203
210
|
});
|
|
204
|
-
socket.on('error',
|
|
211
|
+
socket.on('error', failed);
|
|
205
212
|
}
|
|
206
213
|
|
|
207
214
|
_onEnvelope(envelope) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/teams",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Volter Teams, the neutral team plane: machine identity and daemon core, the local door and server link, admission from machine grants, product doors, and the Teams server's neutral routes (company RFC 0008).",
|
|
6
6
|
"license": "MIT",
|
package/server/machine-link.mjs
CHANGED
|
@@ -19,8 +19,8 @@ import { delegatedAccessOf, delegatedPrincipal, looksDelegated } from './delegat
|
|
|
19
19
|
|
|
20
20
|
const LINK_PROTOCOL = 'supercode-machine-link.v1';
|
|
21
21
|
const CHANNEL_PROTOCOL = 'supercode-machine-channel.v1';
|
|
22
|
-
/** The machine daemon's door vocabulary: operate (operator: harness.v1 and launch) and the participant caps its doors check. */
|
|
23
|
-
const CAPS = new Set(['operate', 'view', 'observe', 'interact', 'control', 'files', 'ports']);
|
|
22
|
+
/** The machine daemon's door vocabulary: operate (operator: harness.v1 and launch) and the participant caps its doors check. `mail` writes one message into a session there (`mail:*`, or `mail:<address>` for one session). */
|
|
23
|
+
const CAPS = new Set(['operate', 'view', 'observe', 'interact', 'control', 'files', 'ports', 'mail']);
|
|
24
24
|
// A target is `*` or `<kind>:<name>`. The server checks shape only: which kinds a machine
|
|
25
25
|
// serves is the daemon's business, and a grant on a kind it does not serve covers nothing.
|
|
26
26
|
const TARGET = /^(\*|root:(\*|\/[^\x00-\x1f]{0,4095})|(?!root:)[a-z][a-z0-9-]{0,31}:[^\x00-\x1f]{1,4096})$/;
|