@orqenix/mesh-transport-core 0.6.0-phase-6
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/LICENSE +19 -0
- package/README.md +7 -0
- package/dist/canonical.d.ts +3 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/canonical.js +29 -0
- package/dist/canonical.js.map +1 -0
- package/dist/envelope.d.ts +13 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +92 -0
- package/dist/envelope.js.map +1 -0
- package/dist/errors.d.ts +46 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +101 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/loopback.d.ts +17 -0
- package/dist/loopback.d.ts.map +1 -0
- package/dist/loopback.js +117 -0
- package/dist/loopback.js.map +1 -0
- package/dist/registry.d.ts +22 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +38 -0
- package/dist/registry.js.map +1 -0
- package/dist/state-machine.d.ts +13 -0
- package/dist/state-machine.d.ts.map +1 -0
- package/dist/state-machine.js +52 -0
- package/dist/state-machine.js.map +1 -0
- package/dist/types.d.ts +91 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
Copyright 2026 Milo Nguyen and Orqenix contributors
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
you may not use this file except in compliance with the License.
|
|
9
|
+
You may obtain a copy of the License at
|
|
10
|
+
|
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
|
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
See the License for the specific language governing permissions and
|
|
17
|
+
limitations under the License.
|
|
18
|
+
|
|
19
|
+
[Full Apache 2.0 text: include verbatim from https://www.apache.org/licenses/LICENSE-2.0.txt]
|
package/README.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# @orqenix/mesh-transport-core
|
|
2
|
+
|
|
3
|
+
Transport-agnostic foundation for the Orqenix mesh.
|
|
4
|
+
|
|
5
|
+
Provides the `MeshTransport` interface, canonical msgpack envelope (`MeshRequest`/`MeshResponse`), `TransportRegistry`, lifecycle state machine, typed error taxonomy, and a `LoopbackTransport` reference implementation.
|
|
6
|
+
|
|
7
|
+
Part of [Phase 6](https://github.com/milosaysyolo/Orqenix/tree/main/docs/cr-v7.2/chapter-2-transport-abstraction.md). No HTTP or libp2p code lives here; those land in subsequent parts.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAgB3C;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAMhE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function canonicalize(value) {
|
|
2
|
+
if (value === null || value === undefined)
|
|
3
|
+
return value;
|
|
4
|
+
if (value instanceof Uint8Array)
|
|
5
|
+
return value;
|
|
6
|
+
if (Array.isArray(value)) {
|
|
7
|
+
return value.map((v) => canonicalize(v));
|
|
8
|
+
}
|
|
9
|
+
if (typeof value === 'object') {
|
|
10
|
+
const obj = value;
|
|
11
|
+
const sortedKeys = Object.keys(obj).sort();
|
|
12
|
+
const out = {};
|
|
13
|
+
for (const k of sortedKeys) {
|
|
14
|
+
out[k] = canonicalize(obj[k]);
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
export function bytesEqual(a, b) {
|
|
21
|
+
if (a.length !== b.length)
|
|
22
|
+
return false;
|
|
23
|
+
for (let i = 0; i < a.length; i++) {
|
|
24
|
+
if (a[i] !== b[i])
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=canonical.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAI,KAAQ;IACtC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,KAAK,YAAY,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAiB,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,KAAgC,CAAC;QAC7C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,GAAG,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,GAAmB,CAAC;IAC7B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAa,EAAE,CAAa;IACrD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MeshRequest, MeshResponse } from './types.js';
|
|
2
|
+
/** Generate a new ULID request id. */
|
|
3
|
+
export declare function newRequestId(): string;
|
|
4
|
+
/** Structural validation for a MeshRequest. Cheap and synchronous. */
|
|
5
|
+
export declare function validateRequest(req: MeshRequest): void;
|
|
6
|
+
export declare function validateResponse(resp: MeshResponse): void;
|
|
7
|
+
export declare function encodeRequest(req: MeshRequest): Uint8Array;
|
|
8
|
+
export declare function decodeRequest(buf: Uint8Array): MeshRequest;
|
|
9
|
+
export declare function encodeResponse(resp: MeshResponse): Uint8Array;
|
|
10
|
+
export declare function decodeResponse(buf: Uint8Array): MeshResponse;
|
|
11
|
+
/** Byte-equality helper for tests. */
|
|
12
|
+
export { bytesEqual } from './canonical.js';
|
|
13
|
+
//# sourceMappingURL=envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAa5D,sCAAsC;AACtC,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAqBD,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAgBtD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAMzD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,UAAU,CAI1D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,WAAW,CAI1D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,UAAU,CAI7D;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,YAAY,CAI5D;AAED,sCAAsC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/envelope.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// packages/mesh-transport-core/src/envelope.ts
|
|
2
|
+
/**
|
|
3
|
+
* Canonical msgpack envelope encode/decode.
|
|
4
|
+
* Agent note: encoding rules per CR v7.2 Chapter 2.3: sorted keys, smallest int width,
|
|
5
|
+
* binary as bin family, no floats. Encoded output must be byte-stable for equal inputs.
|
|
6
|
+
*/
|
|
7
|
+
import { Packr, Unpackr } from 'msgpackr';
|
|
8
|
+
import { ulid } from 'ulidx';
|
|
9
|
+
import { canonicalize } from './canonical.js';
|
|
10
|
+
const packr = new Packr({
|
|
11
|
+
useRecords: false,
|
|
12
|
+
variableMapSize: true,
|
|
13
|
+
encodeUndefinedAsNil: true,
|
|
14
|
+
});
|
|
15
|
+
const unpackr = new Unpackr({
|
|
16
|
+
useRecords: false,
|
|
17
|
+
});
|
|
18
|
+
/** Generate a new ULID request id. */
|
|
19
|
+
export function newRequestId() {
|
|
20
|
+
return ulid();
|
|
21
|
+
}
|
|
22
|
+
/** Reject any object containing non-integer numeric values. Envelope fields are integer or string. */
|
|
23
|
+
function assertNoFloats(value, path = '$') {
|
|
24
|
+
if (typeof value === 'number') {
|
|
25
|
+
if (!Number.isFinite(value) || !Number.isInteger(value)) {
|
|
26
|
+
throw new Error(`envelope: non-integer number at ${path}`);
|
|
27
|
+
}
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (value === null || typeof value !== 'object')
|
|
31
|
+
return;
|
|
32
|
+
if (value instanceof Uint8Array)
|
|
33
|
+
return;
|
|
34
|
+
if (Array.isArray(value)) {
|
|
35
|
+
value.forEach((v, i) => assertNoFloats(v, `${path}[${i}]`));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
for (const [k, v] of Object.entries(value)) {
|
|
39
|
+
assertNoFloats(v, `${path}.${k}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Structural validation for a MeshRequest. Cheap and synchronous. */
|
|
43
|
+
export function validateRequest(req) {
|
|
44
|
+
if (!req || typeof req !== 'object')
|
|
45
|
+
throw new Error('envelope: request not an object');
|
|
46
|
+
for (const k of ['id', 'fromScope', 'toScope', 'capability', 'method']) {
|
|
47
|
+
if (typeof req[k] !== 'string' || req[k].length === 0) {
|
|
48
|
+
throw new Error(`envelope: field ${k} missing or empty`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (!(req.payload instanceof Uint8Array)) {
|
|
52
|
+
throw new Error('envelope: payload must be Uint8Array');
|
|
53
|
+
}
|
|
54
|
+
if (!Number.isInteger(req.deadlineMs) || req.deadlineMs <= 0) {
|
|
55
|
+
throw new Error('envelope: deadlineMs must be a positive integer');
|
|
56
|
+
}
|
|
57
|
+
if (!req.trace || typeof req.trace.traceparent !== 'string') {
|
|
58
|
+
throw new Error('envelope: trace.traceparent missing');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export function validateResponse(resp) {
|
|
62
|
+
if (!resp || typeof resp !== 'object')
|
|
63
|
+
throw new Error('envelope: response not an object');
|
|
64
|
+
if (typeof resp.id !== 'string' || resp.id.length === 0)
|
|
65
|
+
throw new Error('envelope: response.id missing');
|
|
66
|
+
if (!['ok', 'denied', 'error', 'timeout'].includes(resp.status)) {
|
|
67
|
+
throw new Error('envelope: response.status not in enum');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function encodeRequest(req) {
|
|
71
|
+
validateRequest(req);
|
|
72
|
+
assertNoFloats(req);
|
|
73
|
+
return packr.pack(canonicalize(req));
|
|
74
|
+
}
|
|
75
|
+
export function decodeRequest(buf) {
|
|
76
|
+
const obj = unpackr.unpack(buf);
|
|
77
|
+
validateRequest(obj);
|
|
78
|
+
return obj;
|
|
79
|
+
}
|
|
80
|
+
export function encodeResponse(resp) {
|
|
81
|
+
validateResponse(resp);
|
|
82
|
+
assertNoFloats(resp);
|
|
83
|
+
return packr.pack(canonicalize(resp));
|
|
84
|
+
}
|
|
85
|
+
export function decodeResponse(buf) {
|
|
86
|
+
const obj = unpackr.unpack(buf);
|
|
87
|
+
validateResponse(obj);
|
|
88
|
+
return obj;
|
|
89
|
+
}
|
|
90
|
+
/** Byte-equality helper for tests. */
|
|
91
|
+
export { bytesEqual } from './canonical.js';
|
|
92
|
+
//# sourceMappingURL=envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed error taxonomy and error-to-MeshResponse mapping.
|
|
3
|
+
* Agent note: messages must be sanitized; no stack frames or filesystem paths.
|
|
4
|
+
*/
|
|
5
|
+
import type { MeshResponse } from './types.js';
|
|
6
|
+
export declare const ErrorCode: {
|
|
7
|
+
readonly TRANSPORT: "E_TRANSPORT";
|
|
8
|
+
readonly TIMEOUT: "E_TIMEOUT";
|
|
9
|
+
readonly HANDLER: "E_HANDLER";
|
|
10
|
+
readonly UNKNOWN: "E_UNKNOWN";
|
|
11
|
+
readonly CAP_MISSING: "E_CAP_MISSING";
|
|
12
|
+
readonly CAP_MALFORMED: "E_CAP_MALFORMED";
|
|
13
|
+
readonly CAP_INVALID: "E_CAP_INVALID";
|
|
14
|
+
readonly CAP_SIG_INVALID: "E_CAP_SIG_INVALID";
|
|
15
|
+
readonly CAP_EXPIRED: "E_CAP_EXPIRED";
|
|
16
|
+
readonly CAP_SUBJECT_MISMATCH: "E_CAP_SUBJECT_MISMATCH";
|
|
17
|
+
readonly CAP_ISSUER_MISMATCH: "E_CAP_ISSUER_MISMATCH";
|
|
18
|
+
readonly CAP_METHOD_NOT_ALLOWED: "E_CAP_METHOD_NOT_ALLOWED";
|
|
19
|
+
readonly IDENTITY_SIG_INVALID: "E_IDENTITY_SIG_INVALID";
|
|
20
|
+
readonly ENVELOPE_MISMATCH: "E_ENVELOPE_MISMATCH";
|
|
21
|
+
readonly ILLEGAL_STATE: "E_ILLEGAL_STATE";
|
|
22
|
+
};
|
|
23
|
+
export type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
24
|
+
export declare class TransportError extends Error {
|
|
25
|
+
readonly code: ErrorCodeValue;
|
|
26
|
+
constructor(message: string, code?: ErrorCodeValue);
|
|
27
|
+
}
|
|
28
|
+
export declare class CapabilityError extends Error {
|
|
29
|
+
readonly code: ErrorCodeValue;
|
|
30
|
+
constructor(message: string, code?: ErrorCodeValue);
|
|
31
|
+
}
|
|
32
|
+
export declare class DeadlineExceeded extends Error {
|
|
33
|
+
readonly code: "E_TIMEOUT";
|
|
34
|
+
constructor(message?: string);
|
|
35
|
+
}
|
|
36
|
+
export declare class HandlerError extends Error {
|
|
37
|
+
readonly code: "E_HANDLER";
|
|
38
|
+
constructor(message: string);
|
|
39
|
+
}
|
|
40
|
+
export declare class IllegalStateError extends Error {
|
|
41
|
+
readonly code: "E_ILLEGAL_STATE";
|
|
42
|
+
constructor(message: string);
|
|
43
|
+
}
|
|
44
|
+
/** Map a thrown error into a MeshResponse with the correct status and a sanitized message. */
|
|
45
|
+
export declare function toMeshResponse(id: string, err: unknown): MeshResponse;
|
|
46
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA;;;GAGG;AACH,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,YAAY,CAAC;AAE3D,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;CAgBZ,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAExE,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;gBAClB,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,cAAoC;CAKxE;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;gBAClB,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,cAAsC;CAK1E;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,cAAqB;gBACtB,OAAO,SAAsB;CAI1C;AAED,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,cAAqB;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,oBAA2B;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAUD,8FAA8F;AAC9F,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,YAAY,CAkCrE"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export const ErrorCode = {
|
|
2
|
+
TRANSPORT: 'E_TRANSPORT',
|
|
3
|
+
TIMEOUT: 'E_TIMEOUT',
|
|
4
|
+
HANDLER: 'E_HANDLER',
|
|
5
|
+
UNKNOWN: 'E_UNKNOWN',
|
|
6
|
+
CAP_MISSING: 'E_CAP_MISSING',
|
|
7
|
+
CAP_MALFORMED: 'E_CAP_MALFORMED',
|
|
8
|
+
CAP_INVALID: 'E_CAP_INVALID',
|
|
9
|
+
CAP_SIG_INVALID: 'E_CAP_SIG_INVALID',
|
|
10
|
+
CAP_EXPIRED: 'E_CAP_EXPIRED',
|
|
11
|
+
CAP_SUBJECT_MISMATCH: 'E_CAP_SUBJECT_MISMATCH',
|
|
12
|
+
CAP_ISSUER_MISMATCH: 'E_CAP_ISSUER_MISMATCH',
|
|
13
|
+
CAP_METHOD_NOT_ALLOWED: 'E_CAP_METHOD_NOT_ALLOWED',
|
|
14
|
+
IDENTITY_SIG_INVALID: 'E_IDENTITY_SIG_INVALID',
|
|
15
|
+
ENVELOPE_MISMATCH: 'E_ENVELOPE_MISMATCH',
|
|
16
|
+
ILLEGAL_STATE: 'E_ILLEGAL_STATE',
|
|
17
|
+
};
|
|
18
|
+
export class TransportError extends Error {
|
|
19
|
+
code;
|
|
20
|
+
constructor(message, code = ErrorCode.TRANSPORT) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = 'TransportError';
|
|
23
|
+
this.code = code;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export class CapabilityError extends Error {
|
|
27
|
+
code;
|
|
28
|
+
constructor(message, code = ErrorCode.CAP_INVALID) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = 'CapabilityError';
|
|
31
|
+
this.code = code;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export class DeadlineExceeded extends Error {
|
|
35
|
+
code = ErrorCode.TIMEOUT;
|
|
36
|
+
constructor(message = 'deadline exceeded') {
|
|
37
|
+
super(message);
|
|
38
|
+
this.name = 'DeadlineExceeded';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export class HandlerError extends Error {
|
|
42
|
+
code = ErrorCode.HANDLER;
|
|
43
|
+
constructor(message) {
|
|
44
|
+
super(message);
|
|
45
|
+
this.name = 'HandlerError';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export class IllegalStateError extends Error {
|
|
49
|
+
code = ErrorCode.ILLEGAL_STATE;
|
|
50
|
+
constructor(message) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.name = 'IllegalStateError';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Strip stack frames and filesystem paths from a free-form message. */
|
|
56
|
+
function sanitize(msg) {
|
|
57
|
+
// Remove anything that looks like a stack frame: "at foo (path:line)" or "/abs/path.ts"
|
|
58
|
+
const noFrames = msg.replace(/\s*at\s+\S+\s*\([^)]*\)/g, '');
|
|
59
|
+
const noPaths = noFrames.replace(/(?:\/|\\)[\w./\\-]+\.(?:ts|js|mjs|cjs)/g, '<file>');
|
|
60
|
+
return noPaths.split('\n')[0].trim().slice(0, 256);
|
|
61
|
+
}
|
|
62
|
+
/** Map a thrown error into a MeshResponse with the correct status and a sanitized message. */
|
|
63
|
+
export function toMeshResponse(id, err) {
|
|
64
|
+
let status = 'error';
|
|
65
|
+
let code = ErrorCode.UNKNOWN;
|
|
66
|
+
let raw = 'unknown error';
|
|
67
|
+
if (err instanceof CapabilityError) {
|
|
68
|
+
status = 'denied';
|
|
69
|
+
code = err.code;
|
|
70
|
+
raw = err.message;
|
|
71
|
+
}
|
|
72
|
+
else if (err instanceof DeadlineExceeded) {
|
|
73
|
+
status = 'timeout';
|
|
74
|
+
code = err.code;
|
|
75
|
+
raw = err.message;
|
|
76
|
+
}
|
|
77
|
+
else if (err instanceof HandlerError) {
|
|
78
|
+
status = 'error';
|
|
79
|
+
code = err.code;
|
|
80
|
+
raw = err.message;
|
|
81
|
+
}
|
|
82
|
+
else if (err instanceof TransportError) {
|
|
83
|
+
status = 'error';
|
|
84
|
+
code = err.code;
|
|
85
|
+
raw = err.message;
|
|
86
|
+
}
|
|
87
|
+
else if (err instanceof IllegalStateError) {
|
|
88
|
+
status = 'error';
|
|
89
|
+
code = err.code;
|
|
90
|
+
raw = err.message;
|
|
91
|
+
}
|
|
92
|
+
else if (err instanceof Error) {
|
|
93
|
+
raw = err.message;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
id,
|
|
97
|
+
status,
|
|
98
|
+
error: { code, message: sanitize(raw) },
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './errors.js';
|
|
3
|
+
export * from './envelope.js';
|
|
4
|
+
export * from './state-machine.js';
|
|
5
|
+
export * from './registry.js';
|
|
6
|
+
export * from './loopback.js';
|
|
7
|
+
export * from './canonical.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// packages/mesh-transport-core/src/index.ts
|
|
2
|
+
export * from './types.js';
|
|
3
|
+
export * from './errors.js';
|
|
4
|
+
export * from './envelope.js';
|
|
5
|
+
export * from './state-machine.js';
|
|
6
|
+
export * from './registry.js';
|
|
7
|
+
export * from './loopback.js';
|
|
8
|
+
export * from './canonical.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MeshAddress, MeshRequest, MeshResponse, MeshTransport, PeerInfo, ScopeId, SendOpts, TransportCtx } from './types.js';
|
|
2
|
+
type Handler = (req: MeshRequest, ctx: TransportCtx) => Promise<MeshResponse>;
|
|
3
|
+
export declare class LoopbackTransport implements MeshTransport {
|
|
4
|
+
readonly kind: "loopback";
|
|
5
|
+
readonly localScopeId: ScopeId;
|
|
6
|
+
private lifecycle;
|
|
7
|
+
private handler?;
|
|
8
|
+
private connectedAt;
|
|
9
|
+
constructor(localScopeId: ScopeId);
|
|
10
|
+
start(): Promise<void>;
|
|
11
|
+
stop(): Promise<void>;
|
|
12
|
+
onRequest(handler: Handler): void;
|
|
13
|
+
send(target: MeshAddress, req: MeshRequest, opts?: SendOpts): Promise<MeshResponse>;
|
|
14
|
+
peers(): PeerInfo[];
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=loopback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loopback.d.ts","sourceRoot":"","sources":["../src/loopback.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,KAAK,OAAO,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAK9E,qBAAa,iBAAkB,YAAW,aAAa;IACrD,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAU;IACpC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,OAAO,CAAC,CAAU;IAC1B,OAAO,CAAC,WAAW,CAAK;gBAEZ,YAAY,EAAE,OAAO;IAI3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAetB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAQ3B,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IA0BzF,KAAK,IAAI,QAAQ,EAAE;CAapB"}
|
package/dist/loopback.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// packages/mesh-transport-core/src/loopback.ts
|
|
2
|
+
/**
|
|
3
|
+
* LoopbackTransport: in-process reference implementation.
|
|
4
|
+
* Agent note: NOT a production transport. Used as a test harness and as a worked
|
|
5
|
+
* example for Parts 2 to 4. It connects two local scopes through a shared in-process bus.
|
|
6
|
+
*/
|
|
7
|
+
import { TransportLifecycle } from './state-machine.js';
|
|
8
|
+
import { DeadlineExceeded, IllegalStateError, toMeshResponse } from './errors.js';
|
|
9
|
+
/** Shared in-process bus keyed by ScopeId. */
|
|
10
|
+
const BUS = new Map();
|
|
11
|
+
export class LoopbackTransport {
|
|
12
|
+
kind = 'loopback';
|
|
13
|
+
localScopeId;
|
|
14
|
+
lifecycle = new TransportLifecycle();
|
|
15
|
+
handler;
|
|
16
|
+
connectedAt = 0;
|
|
17
|
+
constructor(localScopeId) {
|
|
18
|
+
this.localScopeId = localScopeId;
|
|
19
|
+
}
|
|
20
|
+
async start() {
|
|
21
|
+
if (!this.lifecycle.assertCanStart())
|
|
22
|
+
return; // idempotent
|
|
23
|
+
this.lifecycle.transition('Starting');
|
|
24
|
+
try {
|
|
25
|
+
// Register on the bus only if a handler has been provided. If not yet,
|
|
26
|
+
// we still go Running and register lazily in onRequest().
|
|
27
|
+
if (this.handler)
|
|
28
|
+
BUS.set(this.localScopeId, this.handler);
|
|
29
|
+
this.connectedAt = Date.now();
|
|
30
|
+
this.lifecycle.transition('Running');
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
this.lifecycle.transition('Failed');
|
|
34
|
+
throw e;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async stop() {
|
|
38
|
+
if (!this.lifecycle.assertCanStop())
|
|
39
|
+
return; // idempotent
|
|
40
|
+
this.lifecycle.transition('Stopping');
|
|
41
|
+
try {
|
|
42
|
+
BUS.delete(this.localScopeId);
|
|
43
|
+
this.handler = undefined;
|
|
44
|
+
this.connectedAt = 0;
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
this.lifecycle.transition('Stopped');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
onRequest(handler) {
|
|
51
|
+
this.lifecycle.assertCanRegisterHandler();
|
|
52
|
+
this.handler = handler;
|
|
53
|
+
if (this.lifecycle.state === 'Running') {
|
|
54
|
+
BUS.set(this.localScopeId, handler);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async send(target, req, opts) {
|
|
58
|
+
this.lifecycle.assertCanSend();
|
|
59
|
+
if (target.kind !== 'loopback') {
|
|
60
|
+
return toMeshResponse(req.id, new IllegalStateError(`loopback cannot reach ${target.kind}`));
|
|
61
|
+
}
|
|
62
|
+
const peerHandler = BUS.get(target.scopeId);
|
|
63
|
+
if (!peerHandler) {
|
|
64
|
+
return toMeshResponse(req.id, new IllegalStateError('peer not present on loopback bus'));
|
|
65
|
+
}
|
|
66
|
+
const ctx = {
|
|
67
|
+
authenticatedScope: req.fromScope, // loopback trusts in-process identity (test only)
|
|
68
|
+
peerId: 'loopback',
|
|
69
|
+
remoteAddr: 'inproc',
|
|
70
|
+
};
|
|
71
|
+
const deadlineDelta = Math.max(0, req.deadlineMs - Date.now());
|
|
72
|
+
const perAttemptMs = Math.min(deadlineDelta, opts?.timeoutMs ?? deadlineDelta);
|
|
73
|
+
try {
|
|
74
|
+
return await raceWithDeadline(peerHandler(req, ctx), perAttemptMs, opts?.signal);
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
return toMeshResponse(req.id, e);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
peers() {
|
|
81
|
+
if (this.lifecycle.state !== 'Running')
|
|
82
|
+
return [];
|
|
83
|
+
const list = [];
|
|
84
|
+
for (const scopeId of BUS.keys()) {
|
|
85
|
+
if (scopeId === this.localScopeId)
|
|
86
|
+
continue;
|
|
87
|
+
list.push({
|
|
88
|
+
scopeId,
|
|
89
|
+
transport: 'loopback',
|
|
90
|
+
connectedAt: this.connectedAt,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return list;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function raceWithDeadline(p, ms, signal) {
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
const t = setTimeout(() => reject(new DeadlineExceeded()), Math.max(0, ms));
|
|
99
|
+
const onAbort = () => {
|
|
100
|
+
clearTimeout(t);
|
|
101
|
+
reject(new DeadlineExceeded('aborted'));
|
|
102
|
+
};
|
|
103
|
+
if (signal) {
|
|
104
|
+
if (signal.aborted)
|
|
105
|
+
return onAbort();
|
|
106
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
107
|
+
}
|
|
108
|
+
p.then((v) => {
|
|
109
|
+
clearTimeout(t);
|
|
110
|
+
resolve(v);
|
|
111
|
+
}, (e) => {
|
|
112
|
+
clearTimeout(t);
|
|
113
|
+
reject(e);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=loopback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loopback.js","sourceRoot":"","sources":["../src/loopback.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DefaultTransportRegistry implements TransportRegistry.
|
|
3
|
+
* Agent note: this class is the seam for a future Pro-only Rust accelerator
|
|
4
|
+
* (rust-libp2p via NAPI-RS) at Phase 7+. Do not embed transport-specific logic here.
|
|
5
|
+
*/
|
|
6
|
+
import type { MeshTransport, ScopeId, TransportRegistry } from './types.js';
|
|
7
|
+
export declare class DefaultTransportRegistry implements TransportRegistry {
|
|
8
|
+
private entries;
|
|
9
|
+
private counter;
|
|
10
|
+
register(t: MeshTransport): void;
|
|
11
|
+
unregister(kind: string): void;
|
|
12
|
+
get(kind: string): MeshTransport | undefined;
|
|
13
|
+
all(): MeshTransport[];
|
|
14
|
+
/**
|
|
15
|
+
* Return transports that can currently reach `scopeId`.
|
|
16
|
+
* Phase 6 Part 1 returns all registered transports; richer reachability
|
|
17
|
+
* (peer membership, circuit breaker filtering) lands with Parts 5 and 9.
|
|
18
|
+
* Ordering is deterministic: by transport kind ascending, then registration order.
|
|
19
|
+
*/
|
|
20
|
+
reachable(_scopeId: ScopeId): MeshTransport[];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAO5E,qBAAa,wBAAyB,YAAW,iBAAiB;IAChE,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,OAAO,CAAK;IAEpB,QAAQ,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI;IAOhC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI5C,GAAG,IAAI,aAAa,EAAE;IAMtB;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,EAAE,OAAO,GAAG,aAAa,EAAE;CAS9C"}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export class DefaultTransportRegistry {
|
|
2
|
+
entries = new Map();
|
|
3
|
+
counter = 0;
|
|
4
|
+
register(t) {
|
|
5
|
+
if (this.entries.has(t.kind)) {
|
|
6
|
+
throw new Error(`transport already registered: ${t.kind}`);
|
|
7
|
+
}
|
|
8
|
+
this.entries.set(t.kind, { transport: t, order: this.counter++ });
|
|
9
|
+
}
|
|
10
|
+
unregister(kind) {
|
|
11
|
+
this.entries.delete(kind);
|
|
12
|
+
}
|
|
13
|
+
get(kind) {
|
|
14
|
+
return this.entries.get(kind)?.transport;
|
|
15
|
+
}
|
|
16
|
+
all() {
|
|
17
|
+
return [...this.entries.values()]
|
|
18
|
+
.sort((a, b) => a.order - b.order)
|
|
19
|
+
.map((e) => e.transport);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Return transports that can currently reach `scopeId`.
|
|
23
|
+
* Phase 6 Part 1 returns all registered transports; richer reachability
|
|
24
|
+
* (peer membership, circuit breaker filtering) lands with Parts 5 and 9.
|
|
25
|
+
* Ordering is deterministic: by transport kind ascending, then registration order.
|
|
26
|
+
*/
|
|
27
|
+
reachable(_scopeId) {
|
|
28
|
+
return [...this.entries.values()]
|
|
29
|
+
.sort((a, b) => {
|
|
30
|
+
const byKind = a.transport.kind.localeCompare(b.transport.kind);
|
|
31
|
+
if (byKind !== 0)
|
|
32
|
+
return byKind;
|
|
33
|
+
return a.order - b.order;
|
|
34
|
+
})
|
|
35
|
+
.map((e) => e.transport);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAaA,MAAM,OAAO,wBAAwB;IAC3B,OAAO,GAAG,IAAI,GAAG,EAAiB,CAAC;IACnC,OAAO,GAAG,CAAC,CAAC;IAEpB,QAAQ,CAAC,CAAgB;QACvB,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC3C,CAAC;IAED,GAAG;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;aAC9B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;aACjC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,QAAiB;QACzB,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;aAC9B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACb,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAChE,IAAI,MAAM,KAAK,CAAC;gBAAE,OAAO,MAAM,CAAC;YAChC,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;QAC3B,CAAC,CAAC;aACD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type TransportState = 'Created' | 'Starting' | 'Running' | 'Stopping' | 'Stopped' | 'Failed';
|
|
2
|
+
export declare class TransportLifecycle {
|
|
3
|
+
private _state;
|
|
4
|
+
get state(): TransportState;
|
|
5
|
+
transition(next: TransportState): void;
|
|
6
|
+
/** start() is idempotent on Running; allowed on Created/Stopped. */
|
|
7
|
+
assertCanStart(): boolean;
|
|
8
|
+
/** stop() is idempotent on Stopped/Stopping; allowed almost anywhere else. */
|
|
9
|
+
assertCanStop(): boolean;
|
|
10
|
+
assertCanSend(): void;
|
|
11
|
+
assertCanRegisterHandler(): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=state-machine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../src/state-machine.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,UAAU,GACV,SAAS,GACT,UAAU,GACV,SAAS,GACT,QAAQ,CAAC;AAWb,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAA6B;IAE3C,IAAI,KAAK,IAAI,cAAc,CAE1B;IAED,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAUtC,oEAAoE;IACpE,cAAc,IAAI,OAAO;IAMzB,8EAA8E;IAC9E,aAAa,IAAI,OAAO;IAKxB,aAAa,IAAI,IAAI;IAMrB,wBAAwB,IAAI,IAAI;CAKjC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// packages/mesh-transport-core/src/state-machine.ts
|
|
2
|
+
/**
|
|
3
|
+
* Transport lifecycle state machine per CR v7.2 Chapter 2.4.
|
|
4
|
+
* Agent note: this is the single place where state transitions are guarded.
|
|
5
|
+
*/
|
|
6
|
+
import { IllegalStateError } from './errors.js';
|
|
7
|
+
const ALLOWED = {
|
|
8
|
+
Created: ['Starting', 'Stopped'],
|
|
9
|
+
Starting: ['Running', 'Failed', 'Stopping'],
|
|
10
|
+
Running: ['Stopping', 'Failed'],
|
|
11
|
+
Stopping: ['Stopped'],
|
|
12
|
+
Stopped: ['Starting'],
|
|
13
|
+
Failed: ['Stopping'],
|
|
14
|
+
};
|
|
15
|
+
export class TransportLifecycle {
|
|
16
|
+
_state = 'Created';
|
|
17
|
+
get state() {
|
|
18
|
+
return this._state;
|
|
19
|
+
}
|
|
20
|
+
transition(next) {
|
|
21
|
+
const allowed = ALLOWED[this._state];
|
|
22
|
+
if (!allowed.includes(next)) {
|
|
23
|
+
throw new IllegalStateError(`illegal transport transition: ${this._state} -> ${next}`);
|
|
24
|
+
}
|
|
25
|
+
this._state = next;
|
|
26
|
+
}
|
|
27
|
+
/** start() is idempotent on Running; allowed on Created/Stopped. */
|
|
28
|
+
assertCanStart() {
|
|
29
|
+
if (this._state === 'Running' || this._state === 'Starting')
|
|
30
|
+
return false; // no-op
|
|
31
|
+
if (this._state === 'Created' || this._state === 'Stopped')
|
|
32
|
+
return true;
|
|
33
|
+
throw new IllegalStateError(`cannot start in state ${this._state}`);
|
|
34
|
+
}
|
|
35
|
+
/** stop() is idempotent on Stopped/Stopping; allowed almost anywhere else. */
|
|
36
|
+
assertCanStop() {
|
|
37
|
+
if (this._state === 'Stopped' || this._state === 'Stopping')
|
|
38
|
+
return false; // no-op
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
assertCanSend() {
|
|
42
|
+
if (this._state !== 'Running') {
|
|
43
|
+
throw new IllegalStateError(`cannot send in state ${this._state}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
assertCanRegisterHandler() {
|
|
47
|
+
if (this._state === 'Stopping') {
|
|
48
|
+
throw new IllegalStateError(`cannot register handler in state Stopping`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=state-machine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-machine.js","sourceRoot":"","sources":["../src/state-machine.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD;;;GAGG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAUhD,MAAM,OAAO,GAA0D;IACrE,OAAO,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC;IAChC,QAAQ,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC;IAC3C,OAAO,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC/B,QAAQ,EAAE,CAAC,SAAS,CAAC;IACrB,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,MAAM,EAAE,CAAC,UAAU,CAAC;CACrB,CAAC;AAEF,MAAM,OAAO,kBAAkB;IACrB,MAAM,GAAmB,SAAS,CAAC;IAE3C,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,UAAU,CAAC,IAAoB;QAC7B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,iBAAiB,CACzB,iCAAiC,IAAI,CAAC,MAAM,OAAO,IAAI,EAAE,CAC1D,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,oEAAoE;IACpE,cAAc;QACZ,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU;YAAE,OAAO,KAAK,CAAC,CAAC,QAAQ;QACnF,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACxE,MAAM,IAAI,iBAAiB,CAAC,yBAAyB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,8EAA8E;IAC9E,aAAa;QACX,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU;YAAE,OAAO,KAAK,CAAC,CAAC,QAAQ;QACnF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,aAAa;QACX,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,iBAAiB,CAAC,wBAAwB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED,wBAAwB;QACtB,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC/B,MAAM,IAAI,iBAAiB,CAAC,2CAA2C,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;CACF"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public type surface for the transport-agnostic mesh layer.
|
|
3
|
+
* Agent note: this file is API-stable. Adding fields requires a CR amendment.
|
|
4
|
+
*/
|
|
5
|
+
/** Branded scope identifier (BLAKE3 of scope Ed25519 public key, base32). */
|
|
6
|
+
export type ScopeId = string & {
|
|
7
|
+
readonly __brand: 'ScopeId';
|
|
8
|
+
};
|
|
9
|
+
/** Branded opaque capability token; structural fields live in the security package. */
|
|
10
|
+
export type CapabilityToken = string & {
|
|
11
|
+
readonly __brand: 'CapabilityToken';
|
|
12
|
+
};
|
|
13
|
+
/** Address used by a concrete transport to reach a peer. Opaque to the router. */
|
|
14
|
+
export type MeshAddress = {
|
|
15
|
+
kind: 'http';
|
|
16
|
+
baseUrl: string;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'libp2p';
|
|
19
|
+
multiaddr: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'loopback';
|
|
22
|
+
scopeId: ScopeId;
|
|
23
|
+
};
|
|
24
|
+
/** Cooperative cancellation and per-attempt soft timeout. */
|
|
25
|
+
export interface SendOpts {
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
timeoutMs?: number;
|
|
28
|
+
}
|
|
29
|
+
/** Context surfaced to the inbound handler after identity verification. */
|
|
30
|
+
export interface TransportCtx {
|
|
31
|
+
peerId?: string;
|
|
32
|
+
remoteAddr?: string;
|
|
33
|
+
authenticatedScope: ScopeId;
|
|
34
|
+
}
|
|
35
|
+
/** Snapshot entry returned by peers(). */
|
|
36
|
+
export interface PeerInfo {
|
|
37
|
+
scopeId: ScopeId;
|
|
38
|
+
peerId?: string;
|
|
39
|
+
transport: 'http' | 'libp2p' | 'loopback' | string;
|
|
40
|
+
connectedAt: number;
|
|
41
|
+
rttMs?: number;
|
|
42
|
+
}
|
|
43
|
+
/** W3C trace context propagated through every envelope. */
|
|
44
|
+
export interface TraceContext {
|
|
45
|
+
traceparent: string;
|
|
46
|
+
tracestate?: string;
|
|
47
|
+
}
|
|
48
|
+
/** Final, exhaustive status enum for a MeshResponse. */
|
|
49
|
+
export type MeshStatus = 'ok' | 'denied' | 'error' | 'timeout';
|
|
50
|
+
/** Canonical wire-level request shape, serialized as msgpack. */
|
|
51
|
+
export interface MeshRequest {
|
|
52
|
+
id: string;
|
|
53
|
+
fromScope: ScopeId;
|
|
54
|
+
toScope: ScopeId;
|
|
55
|
+
capability: CapabilityToken;
|
|
56
|
+
method: string;
|
|
57
|
+
payload: Uint8Array;
|
|
58
|
+
deadlineMs: number;
|
|
59
|
+
trace: TraceContext;
|
|
60
|
+
}
|
|
61
|
+
/** Canonical wire-level response shape. */
|
|
62
|
+
export interface MeshResponse {
|
|
63
|
+
id: string;
|
|
64
|
+
status: MeshStatus;
|
|
65
|
+
payload?: Uint8Array;
|
|
66
|
+
/** Populated only when status = 'error' or 'denied'. Must never include a stack trace. */
|
|
67
|
+
error?: {
|
|
68
|
+
code: string;
|
|
69
|
+
message: string;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** The interface every concrete transport implements. */
|
|
73
|
+
export interface MeshTransport {
|
|
74
|
+
readonly kind: 'http' | 'libp2p' | 'loopback' | string;
|
|
75
|
+
readonly localScopeId: ScopeId;
|
|
76
|
+
start(): Promise<void>;
|
|
77
|
+
stop(): Promise<void>;
|
|
78
|
+
send(target: MeshAddress, req: MeshRequest, opts?: SendOpts): Promise<MeshResponse>;
|
|
79
|
+
onRequest(handler: (req: MeshRequest, ctx: TransportCtx) => Promise<MeshResponse>): void;
|
|
80
|
+
peers(): PeerInfo[];
|
|
81
|
+
}
|
|
82
|
+
/** Holds active transports; the seam for a future Pro Rust accelerator (Phase 7+). */
|
|
83
|
+
export interface TransportRegistry {
|
|
84
|
+
register(t: MeshTransport): void;
|
|
85
|
+
unregister(kind: string): void;
|
|
86
|
+
get(kind: string): MeshTransport | undefined;
|
|
87
|
+
all(): MeshTransport[];
|
|
88
|
+
/** Deterministic ordering across repeated calls when health is unchanged. */
|
|
89
|
+
reachable(scopeId: ScopeId): MeshTransport[];
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C;;;GAGG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@orqenix/mesh-transport-core",
|
|
3
|
+
"version": "0.6.0-phase-6",
|
|
4
|
+
"description": "Transport-agnostic foundation for the Orqenix mesh: MeshTransport interface, canonical envelope, registry, lifecycle, and loopback reference transport.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"CHANGELOG.md"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"msgpackr": "^1.11.0",
|
|
24
|
+
"ulidx": "^2.4.1"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^22.7.0",
|
|
28
|
+
"@vitest/coverage-v8": "^2.1.0",
|
|
29
|
+
"tsx": "^4.19.0",
|
|
30
|
+
"typescript": "^5.6.0",
|
|
31
|
+
"vitest": "^2.1.0"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public",
|
|
35
|
+
"provenance": false
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=22.0.0"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc -p tsconfig.json",
|
|
42
|
+
"test": "vitest run --coverage",
|
|
43
|
+
"test:watch": "vitest",
|
|
44
|
+
"gate:G36": "tsx ../../scripts/gates/G36-transport-abstraction.ts"
|
|
45
|
+
}
|
|
46
|
+
}
|