@hadoku/rooms-server 0.45.7 → 0.45.8
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/dist/identity.d.ts +1 -9
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +12 -11
- package/package.json +2 -2
package/dist/identity.d.ts
CHANGED
|
@@ -8,13 +8,6 @@ export interface DeriveParticipantInput {
|
|
|
8
8
|
* bypassed the edge could set.
|
|
9
9
|
*/
|
|
10
10
|
accountId?: string | null;
|
|
11
|
-
/**
|
|
12
|
-
* DEPRECATED account material — the raw `X-User-Key` credential. Used only
|
|
13
|
-
* when no `accountId` is given. An id derived from it changes whenever the
|
|
14
|
-
* key rotates, so a consumer still passing it should resolve the userId and
|
|
15
|
-
* pass that instead.
|
|
16
|
-
*/
|
|
17
|
-
friendKey?: string | null;
|
|
18
11
|
/**
|
|
19
12
|
* A stable-but-unproven browser id. CLIENT-ASSERTED, so `device` is NOT an
|
|
20
13
|
* authorization boundary — gate power on `isAuthenticatedTier`, never on
|
|
@@ -35,8 +28,7 @@ export type ParticipantIdDeriver = (input: DeriveParticipantInput) => DerivedPar
|
|
|
35
28
|
* A FACTORY rather than a `(input, domain)` function so the domain is chosen
|
|
36
29
|
* once, at module scope, and no call site can mint a second identity space for
|
|
37
30
|
* the same person by passing a different string. The highest available tier
|
|
38
|
-
* wins: an account id
|
|
39
|
-
* the socket id; an account id beats a friend key. Account material present
|
|
31
|
+
* wins: an account id beats a device id beats the socket id. Account material present
|
|
40
32
|
* alongside a device id ignores the device id entirely —
|
|
41
33
|
* preferring the client-controlled input while authenticated is the one
|
|
42
34
|
* combination that lets somebody hold two identities at once.
|
package/dist/identity.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EAKvB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EAKvB,MAAM,wBAAwB,CAAC;AA8ChC,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,aAAa,CAAC;IAClB,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,sBAAsB,KAAK,kBAAkB,CAAC;AASzF;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB,CAyB/E"}
|
package/dist/identity.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { formatParticipantId,
|
|
2
|
+
import { formatParticipantId, resolveParticipantTier, PARTICIPANT_ID_DIGEST_LENGTH, } from '@wolffm/rooms-protocol';
|
|
3
3
|
/**
|
|
4
4
|
* Participant identity — the DERIVATION half.
|
|
5
5
|
*
|
|
@@ -18,7 +18,7 @@ import { formatParticipantId, isUsableAccountId, resolveParticipantTier, PARTICI
|
|
|
18
18
|
* ## The DOMAIN is the app's, and it is required
|
|
19
19
|
*
|
|
20
20
|
* Ids minted under one domain agree only with ids minted under that domain, so
|
|
21
|
-
* two hadoku apps hashing the same
|
|
21
|
+
* two hadoku apps hashing the same userId produce unrelated participants.
|
|
22
22
|
* That is deliberate: a room in one app must not be able to assert a person's
|
|
23
23
|
* identity in another, and an app that leaks its ids does not leak everyone
|
|
24
24
|
* else's. VERSION the string (`hadoku.<app>.participant.v1`) so changing the
|
|
@@ -27,7 +27,7 @@ import { formatParticipantId, isUsableAccountId, resolveParticipantTier, PARTICI
|
|
|
27
27
|
* ## Per-TIER separation is enforced here, not by the caller
|
|
28
28
|
*
|
|
29
29
|
* The tier is hashed in alongside the domain. Without it, a client that learned
|
|
30
|
-
*
|
|
30
|
+
* someone's userId could present it as its DEVICE id and land on that
|
|
31
31
|
* authenticated participant's identity — collapsing the tier distinction the
|
|
32
32
|
* whole scheme rests on, silently. An earlier version left this to the caller
|
|
33
33
|
* by asking for two domain strings; a caller that passed the same string twice
|
|
@@ -35,9 +35,10 @@ import { formatParticipantId, isUsableAccountId, resolveParticipantTier, PARTICI
|
|
|
35
35
|
*
|
|
36
36
|
* ## What comes out is safe to log, ship and show
|
|
37
37
|
*
|
|
38
|
-
* The
|
|
39
|
-
*
|
|
40
|
-
*
|
|
38
|
+
* The body of an `fk:`/`dev:` id is a truncated SHA-256 of its material, which
|
|
39
|
+
* cannot be reversed — see `participantHandle` in rooms-protocol for the part
|
|
40
|
+
* you may show a room. The friend key (the credential) is never material: it
|
|
41
|
+
* was, as a deprecated account input, until R12 removed it.
|
|
41
42
|
*/
|
|
42
43
|
/** Separator: U+001F cannot appear in a header value, so fields cannot run together. */
|
|
43
44
|
const SEP = '\u001f';
|
|
@@ -53,8 +54,7 @@ function digest(domain, tier, material) {
|
|
|
53
54
|
* A FACTORY rather than a `(input, domain)` function so the domain is chosen
|
|
54
55
|
* once, at module scope, and no call site can mint a second identity space for
|
|
55
56
|
* the same person by passing a different string. The highest available tier
|
|
56
|
-
* wins: an account id
|
|
57
|
-
* the socket id; an account id beats a friend key. Account material present
|
|
57
|
+
* wins: an account id beats a device id beats the socket id. Account material present
|
|
58
58
|
* alongside a device id ignores the device id entirely —
|
|
59
59
|
* preferring the client-controlled input while authenticated is the one
|
|
60
60
|
* combination that lets somebody hold two identities at once.
|
|
@@ -68,10 +68,11 @@ export function createParticipantIdDeriver(domain) {
|
|
|
68
68
|
case 'account':
|
|
69
69
|
// The material is LABELLED so a userId and a credential can never
|
|
70
70
|
// digest to the same body, whatever their values.
|
|
71
|
+
// `account` is reached only through a usable accountId (see
|
|
72
|
+
// resolveParticipantTier). The credential is never material: an id
|
|
73
|
+
// hashed from a key detaches on rotation (R7, R12).
|
|
71
74
|
return {
|
|
72
|
-
id: formatParticipantId(tier,
|
|
73
|
-
? digest(domain, tier, `uid${SEP}${input.accountId}`)
|
|
74
|
-
: digest(domain, tier, input.friendKey)),
|
|
75
|
+
id: formatParticipantId(tier, digest(domain, tier, `uid${SEP}${input.accountId}`)),
|
|
75
76
|
tier,
|
|
76
77
|
};
|
|
77
78
|
case 'device':
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hadoku/rooms-server",
|
|
3
|
-
"version": "0.45.
|
|
3
|
+
"version": "0.45.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Room lifecycle, membership, seating, identity and backpressure-aware emit for a socket.io server.",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"directory": "packages/rooms-server"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@wolffm/rooms-protocol": "npm:@hadoku/rooms-protocol@0.45.
|
|
25
|
+
"@wolffm/rooms-protocol": "npm:@hadoku/rooms-protocol@0.45.8"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"socket.io": "^4.8.3"
|