wire-mesh-core 1.3.0 → 1.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.
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/domain/room-path.ts
|
|
3
|
+
/**
|
|
4
|
+
* Room paths — the naming and parsing convention core/room's device-keyed membership uses, mirroring spec/room.cddl's own owner-named-room-path/dm-room-path grammar exactly: an owner-named room is `<owner-hex>/<local-name>`, trust rooted at the owner named in the path; a DM is the bytewise-ascending sorted pair `<lower-hex>+<higher-hex>`, trust rooted at the verifier itself rather than either named party (see room.cddl's own comments for why that asymmetry is load-bearing, not incidental).
|
|
5
|
+
*/
|
|
6
|
+
const DEVICE_ID_HEX_PATTERN = /^[0-9a-f]{64}$/;
|
|
7
|
+
const LOCAL_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
8
|
+
const SLUG_INVALID_RUN = /[^A-Za-z0-9_-]+/g;
|
|
9
|
+
function assertDeviceIdHex(value, label) {
|
|
10
|
+
if (!DEVICE_ID_HEX_PATTERN.test(value)) throw new Error(`expected ${label} to be a 64-character lowercase hex device-id, got ${JSON.stringify(value)}`);
|
|
11
|
+
}
|
|
12
|
+
/** `<owner-hex>/<local-name>`. localName must already satisfy [A-Za-z0-9_-]+ -- run an untrusted name through slugRoomName first. */
|
|
13
|
+
function ownerNamedRoomPath(owner, localName) {
|
|
14
|
+
assertDeviceIdHex(owner, "owner");
|
|
15
|
+
if (!LOCAL_NAME_PATTERN.test(localName)) throw new Error(`expected localName to match [A-Za-z0-9_-]+, got ${JSON.stringify(localName)}`);
|
|
16
|
+
return `${owner}/${localName}`;
|
|
17
|
+
}
|
|
18
|
+
/** `<lower-hex>+<higher-hex>`, the bytewise-ascending sorted pair. Refuses a==b outright: a path naming the same device twice is not a valid DM path at all, and a self-DM is a purely local concept a consumer models its own way, needing no path. */
|
|
19
|
+
function dmRoomPath(a, b) {
|
|
20
|
+
assertDeviceIdHex(a, "a");
|
|
21
|
+
assertDeviceIdHex(b, "b");
|
|
22
|
+
if (a === b) throw new Error(`a DM room path cannot name the same device twice (${a})`);
|
|
23
|
+
return a < b ? `${a}+${b}` : `${b}+${a}`;
|
|
24
|
+
}
|
|
25
|
+
/** Parses a room-path back into its owner-named or DM shape. Throws on anything matching neither -- there is no third path shape. */
|
|
26
|
+
function parseRoomPath(path) {
|
|
27
|
+
const slashIndex = path.indexOf("/");
|
|
28
|
+
if (slashIndex !== -1) {
|
|
29
|
+
const owner = path.slice(0, slashIndex);
|
|
30
|
+
const localName = path.slice(slashIndex + 1);
|
|
31
|
+
if (DEVICE_ID_HEX_PATTERN.test(owner) && LOCAL_NAME_PATTERN.test(localName)) return {
|
|
32
|
+
kind: "owner-named",
|
|
33
|
+
owner,
|
|
34
|
+
localName
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const plusIndex = path.indexOf("+");
|
|
38
|
+
if (plusIndex !== -1) {
|
|
39
|
+
const first = path.slice(0, plusIndex);
|
|
40
|
+
const second = path.slice(plusIndex + 1);
|
|
41
|
+
if (DEVICE_ID_HEX_PATTERN.test(first) && DEVICE_ID_HEX_PATTERN.test(second) && first !== second) return {
|
|
42
|
+
kind: "dm",
|
|
43
|
+
participants: [first, second]
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
throw new Error(`${JSON.stringify(path)} is not a valid room-path`);
|
|
47
|
+
}
|
|
48
|
+
/** Sanitises an arbitrary name (e.g. a directory basename) into a valid room-path localName by replacing every run of characters outside [A-Za-z0-9_-] with a single hyphen. Throws if nothing valid remains. */
|
|
49
|
+
function slugRoomName(name) {
|
|
50
|
+
const slug = name.replace(SLUG_INVALID_RUN, "-").replace(/^-+|-+$/g, "");
|
|
51
|
+
if (slug.length === 0) throw new Error(`${JSON.stringify(name)} has no valid room-name characters to slug`);
|
|
52
|
+
return slug;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
exports.dmRoomPath = dmRoomPath;
|
|
56
|
+
exports.ownerNamedRoomPath = ownerNamedRoomPath;
|
|
57
|
+
exports.parseRoomPath = parseRoomPath;
|
|
58
|
+
exports.slugRoomName = slugRoomName;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/domain/room-path.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Room paths — the naming and parsing convention core/room's device-keyed membership uses, mirroring spec/room.cddl's own owner-named-room-path/dm-room-path grammar exactly: an owner-named room is `<owner-hex>/<local-name>`, trust rooted at the owner named in the path; a DM is the bytewise-ascending sorted pair `<lower-hex>+<higher-hex>`, trust rooted at the verifier itself rather than either named party (see room.cddl's own comments for why that asymmetry is load-bearing, not incidental).
|
|
4
|
+
*/
|
|
5
|
+
/** `<owner-hex>/<local-name>`. localName must already satisfy [A-Za-z0-9_-]+ -- run an untrusted name through slugRoomName first. */
|
|
6
|
+
export declare function ownerNamedRoomPath(owner: string, localName: string): string;
|
|
7
|
+
/** `<lower-hex>+<higher-hex>`, the bytewise-ascending sorted pair. Refuses a==b outright: a path naming the same device twice is not a valid DM path at all, and a self-DM is a purely local concept a consumer models its own way, needing no path. */
|
|
8
|
+
export declare function dmRoomPath(a: string, b: string): string;
|
|
9
|
+
export type ParsedRoomPath = {
|
|
10
|
+
kind: "owner-named";
|
|
11
|
+
owner: string;
|
|
12
|
+
localName: string;
|
|
13
|
+
} | {
|
|
14
|
+
kind: "dm";
|
|
15
|
+
participants: [string, string];
|
|
16
|
+
};
|
|
17
|
+
/** Parses a room-path back into its owner-named or DM shape. Throws on anything matching neither -- there is no third path shape. */
|
|
18
|
+
export declare function parseRoomPath(path: string): ParsedRoomPath;
|
|
19
|
+
/** Sanitises an arbitrary name (e.g. a directory basename) into a valid room-path localName by replacing every run of characters outside [A-Za-z0-9_-] with a single hyphen. Throws if nothing valid remains. */
|
|
20
|
+
export declare function slugRoomName(name: string): string;
|
|
21
|
+
//#endregion
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/domain/room-path.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Room paths — the naming and parsing convention core/room's device-keyed membership uses, mirroring spec/room.cddl's own owner-named-room-path/dm-room-path grammar exactly: an owner-named room is `<owner-hex>/<local-name>`, trust rooted at the owner named in the path; a DM is the bytewise-ascending sorted pair `<lower-hex>+<higher-hex>`, trust rooted at the verifier itself rather than either named party (see room.cddl's own comments for why that asymmetry is load-bearing, not incidental).
|
|
4
|
+
*/
|
|
5
|
+
/** `<owner-hex>/<local-name>`. localName must already satisfy [A-Za-z0-9_-]+ -- run an untrusted name through slugRoomName first. */
|
|
6
|
+
export declare function ownerNamedRoomPath(owner: string, localName: string): string;
|
|
7
|
+
/** `<lower-hex>+<higher-hex>`, the bytewise-ascending sorted pair. Refuses a==b outright: a path naming the same device twice is not a valid DM path at all, and a self-DM is a purely local concept a consumer models its own way, needing no path. */
|
|
8
|
+
export declare function dmRoomPath(a: string, b: string): string;
|
|
9
|
+
export type ParsedRoomPath = {
|
|
10
|
+
kind: "owner-named";
|
|
11
|
+
owner: string;
|
|
12
|
+
localName: string;
|
|
13
|
+
} | {
|
|
14
|
+
kind: "dm";
|
|
15
|
+
participants: [string, string];
|
|
16
|
+
};
|
|
17
|
+
/** Parses a room-path back into its owner-named or DM shape. Throws on anything matching neither -- there is no third path shape. */
|
|
18
|
+
export declare function parseRoomPath(path: string): ParsedRoomPath;
|
|
19
|
+
/** Sanitises an arbitrary name (e.g. a directory basename) into a valid room-path localName by replacing every run of characters outside [A-Za-z0-9_-] with a single hyphen. Throws if nothing valid remains. */
|
|
20
|
+
export declare function slugRoomName(name: string): string;
|
|
21
|
+
//#endregion
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//#region src/domain/room-path.ts
|
|
2
|
+
/**
|
|
3
|
+
* Room paths — the naming and parsing convention core/room's device-keyed membership uses, mirroring spec/room.cddl's own owner-named-room-path/dm-room-path grammar exactly: an owner-named room is `<owner-hex>/<local-name>`, trust rooted at the owner named in the path; a DM is the bytewise-ascending sorted pair `<lower-hex>+<higher-hex>`, trust rooted at the verifier itself rather than either named party (see room.cddl's own comments for why that asymmetry is load-bearing, not incidental).
|
|
4
|
+
*/
|
|
5
|
+
const DEVICE_ID_HEX_PATTERN = /^[0-9a-f]{64}$/;
|
|
6
|
+
const LOCAL_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
7
|
+
const SLUG_INVALID_RUN = /[^A-Za-z0-9_-]+/g;
|
|
8
|
+
function assertDeviceIdHex(value, label) {
|
|
9
|
+
if (!DEVICE_ID_HEX_PATTERN.test(value)) throw new Error(`expected ${label} to be a 64-character lowercase hex device-id, got ${JSON.stringify(value)}`);
|
|
10
|
+
}
|
|
11
|
+
/** `<owner-hex>/<local-name>`. localName must already satisfy [A-Za-z0-9_-]+ -- run an untrusted name through slugRoomName first. */
|
|
12
|
+
function ownerNamedRoomPath(owner, localName) {
|
|
13
|
+
assertDeviceIdHex(owner, "owner");
|
|
14
|
+
if (!LOCAL_NAME_PATTERN.test(localName)) throw new Error(`expected localName to match [A-Za-z0-9_-]+, got ${JSON.stringify(localName)}`);
|
|
15
|
+
return `${owner}/${localName}`;
|
|
16
|
+
}
|
|
17
|
+
/** `<lower-hex>+<higher-hex>`, the bytewise-ascending sorted pair. Refuses a==b outright: a path naming the same device twice is not a valid DM path at all, and a self-DM is a purely local concept a consumer models its own way, needing no path. */
|
|
18
|
+
function dmRoomPath(a, b) {
|
|
19
|
+
assertDeviceIdHex(a, "a");
|
|
20
|
+
assertDeviceIdHex(b, "b");
|
|
21
|
+
if (a === b) throw new Error(`a DM room path cannot name the same device twice (${a})`);
|
|
22
|
+
return a < b ? `${a}+${b}` : `${b}+${a}`;
|
|
23
|
+
}
|
|
24
|
+
/** Parses a room-path back into its owner-named or DM shape. Throws on anything matching neither -- there is no third path shape. */
|
|
25
|
+
function parseRoomPath(path) {
|
|
26
|
+
const slashIndex = path.indexOf("/");
|
|
27
|
+
if (slashIndex !== -1) {
|
|
28
|
+
const owner = path.slice(0, slashIndex);
|
|
29
|
+
const localName = path.slice(slashIndex + 1);
|
|
30
|
+
if (DEVICE_ID_HEX_PATTERN.test(owner) && LOCAL_NAME_PATTERN.test(localName)) return {
|
|
31
|
+
kind: "owner-named",
|
|
32
|
+
owner,
|
|
33
|
+
localName
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const plusIndex = path.indexOf("+");
|
|
37
|
+
if (plusIndex !== -1) {
|
|
38
|
+
const first = path.slice(0, plusIndex);
|
|
39
|
+
const second = path.slice(plusIndex + 1);
|
|
40
|
+
if (DEVICE_ID_HEX_PATTERN.test(first) && DEVICE_ID_HEX_PATTERN.test(second) && first !== second) return {
|
|
41
|
+
kind: "dm",
|
|
42
|
+
participants: [first, second]
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`${JSON.stringify(path)} is not a valid room-path`);
|
|
46
|
+
}
|
|
47
|
+
/** Sanitises an arbitrary name (e.g. a directory basename) into a valid room-path localName by replacing every run of characters outside [A-Za-z0-9_-] with a single hyphen. Throws if nothing valid remains. */
|
|
48
|
+
function slugRoomName(name) {
|
|
49
|
+
const slug = name.replace(SLUG_INVALID_RUN, "-").replace(/^-+|-+$/g, "");
|
|
50
|
+
if (slug.length === 0) throw new Error(`${JSON.stringify(name)} has no valid room-name characters to slug`);
|
|
51
|
+
return slug;
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { dmRoomPath, ownerNamedRoomPath, parseRoomPath, slugRoomName };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wire-mesh-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"packageManager": "pnpm@10.33.0",
|
|
6
6
|
"repository": {
|
|
@@ -100,6 +100,10 @@
|
|
|
100
100
|
"import": "./dist/domain/revocation-view.mjs",
|
|
101
101
|
"require": "./dist/domain/revocation-view.cjs"
|
|
102
102
|
},
|
|
103
|
+
"./domain/room-path": {
|
|
104
|
+
"import": "./dist/domain/room-path.mjs",
|
|
105
|
+
"require": "./dist/domain/room-path.cjs"
|
|
106
|
+
},
|
|
103
107
|
"./domain/tokens": {
|
|
104
108
|
"import": "./dist/domain/tokens.mjs",
|
|
105
109
|
"require": "./dist/domain/tokens.cjs"
|