@hadoku/rooms-server 0.45.7 → 0.45.9

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.
@@ -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 (or, deprecated, a friend key) beats a device id beats
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.
@@ -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;AA6ChC,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;OAKG;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;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB,CAwB/E"}
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, isUsableAccountId, resolveParticipantTier, PARTICIPANT_ID_DIGEST_LENGTH, } from '@wolffm/rooms-protocol';
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 friend key produce unrelated participants.
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
- * any friend key could present it as its DEVICE id and land on that
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 friend key IS the credential and never leaves this module. The body of an
39
- * `fk:`/`dev:` id is a truncated SHA-256 of it, which cannot be reversed — see
40
- * `participantHandle` in rooms-protocol for the part you may show a room.
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 (or, deprecated, a friend key) beats a device id beats
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, isUsableAccountId(input.accountId)
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.7",
3
+ "version": "0.45.9",
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.7"
25
+ "@wolffm/rooms-protocol": "npm:@hadoku/rooms-protocol@0.45.9"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "socket.io": "^4.8.3"