@livedesk/hub 0.1.76 → 0.1.77

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livedesk/hub",
3
- "version": "0.1.76",
3
+ "version": "0.1.77",
4
4
  "description": "VuvoDesk local Hub API and browser frame bridge",
5
5
  "type": "module",
6
6
  "main": "src/server.js",
@@ -15,15 +15,15 @@ const clients = [6, 3, 1, 5, 2, 4].map(slotNumber => ({
15
15
  }));
16
16
 
17
17
  test('Hub and browser choose the same stable Free, Plus, Pro, and Team device owners', () => {
18
- for (const limit of [5, 20, 50, Number.POSITIVE_INFINITY]) {
18
+ for (const limit of [3, 20, 50, Number.POSITIVE_INFINITY]) {
19
19
  assert.deepEqual(
20
20
  stableHubPlanAllowedDeviceIds(clients, limit),
21
21
  stableBrowserPlanAllowedDeviceIds(clients, limit)
22
22
  );
23
23
  }
24
24
  assert.deepEqual(
25
- stableHubPlanAllowedDeviceIds(clients, 5),
26
- ['client-1', 'client-2', 'client-3', 'client-4', 'client-5']
25
+ stableHubPlanAllowedDeviceIds(clients, 3),
26
+ ['client-1', 'client-2', 'client-3']
27
27
  );
28
28
  });
29
29
 
@@ -66,10 +66,10 @@ test('finite plans reject the exact excess Client instead of counting request wi
66
66
 
67
67
  test('a Team to Free downgrade changes one bounded snapshot and preserves stable owners', () => {
68
68
  const unlimited = createPlanDeviceAccessSnapshot(clients, Number.POSITIVE_INFINITY, 1);
69
- const downgraded = createPlanDeviceAccessSnapshot(clients, 5, 2);
69
+ const downgraded = createPlanDeviceAccessSnapshot(clients, 3, 2);
70
70
  assert.equal(planDeviceAccessSnapshotChanged(unlimited, downgraded), true);
71
- assert.deepEqual(downgraded.allowedDeviceIds, ['client-1', 'client-2', 'client-3', 'client-4', 'client-5']);
72
- assert.deepEqual(downgraded.blockedDeviceIds, ['client-6']);
71
+ assert.deepEqual(downgraded.allowedDeviceIds, ['client-1', 'client-2', 'client-3']);
72
+ assert.deepEqual(downgraded.blockedDeviceIds, ['client-6', 'client-5', 'client-4']);
73
73
  assert.equal(planDeviceAccessSnapshotChanged(downgraded, {
74
74
  ...downgraded,
75
75
  generation: 3,
@@ -90,12 +90,12 @@ test('the exact Hub manager stays controllable without consuming a Client slot',
90
90
  const snapshot = createPlanDeviceAccessSnapshot([
91
91
  ...clients,
92
92
  { deviceId: 'hub-manager', slotNumber: 0, connected: true }
93
- ], 5, 8, { exemptDeviceIds: ['hub-manager'] });
93
+ ], 3, 8, { exemptDeviceIds: ['hub-manager'] });
94
94
 
95
95
  assert.deepEqual(snapshot.connectedDeviceIds, clients.map(client => client.deviceId));
96
96
  assert.deepEqual(snapshot.exemptConnectedDeviceIds, ['hub-manager']);
97
97
  assert.equal(snapshot.allowedDeviceIdSet.has('hub-manager'), true);
98
- assert.deepEqual(snapshot.blockedDeviceIds, ['client-6']);
98
+ assert.deepEqual(snapshot.blockedDeviceIds, ['client-6', 'client-5', 'client-4']);
99
99
  assert.deepEqual(partitionPlanDeviceIds(['hub-manager', 'client-6'], snapshot), {
100
100
  allowedDeviceIds: ['hub-manager'],
101
101
  blockedDeviceIds: ['client-6']
package/src/remote-hub.js CHANGED
@@ -11621,9 +11621,18 @@ export function createRemoteHub(options = {}) {
11621
11621
  }
11622
11622
 
11623
11623
  function startLiveStream(deviceId, options = {}) {
11624
- const device = devices.get(String(deviceId || ''));
11625
- const denied = policyError(device);
11626
- if (denied) return { ok: false, error: denied };
11624
+ const device = devices.get(String(deviceId || ''));
11625
+ const denied = policyError(device);
11626
+ if (denied) return { ok: false, error: denied };
11627
+ const expectedSessionId = safeString(options.expectedSessionId, 160);
11628
+ if (expectedSessionId && device?.sessionId && expectedSessionId !== device.sessionId) {
11629
+ // A delayed Wall restoration cannot create capture on a replacement
11630
+ // Client session. This is a retired intent, not a successful start.
11631
+ return {
11632
+ ok: true, skipped: true, staleOwner: true,
11633
+ retainedNewerOwner: true, reason: 'wall-restore-session-replaced'
11634
+ };
11635
+ }
11627
11636
  if (device?.synthetic !== true
11628
11637
  && device?.connected
11629
11638
  && !isDeviceConnectionFresh(device)) {
package/src/server.js CHANGED
@@ -177,7 +177,7 @@ const atlasPool = new Mode4AtlasPool({
177
177
  });
178
178
  const inputClients = new Set();
179
179
  const audioClients = new Set();
180
- const FREE_DEVICE_LIMIT = 5;
180
+ const FREE_DEVICE_LIMIT = 3;
181
181
  const PLUS_DEVICE_LIMIT = 20;
182
182
  const PRO_DEVICE_LIMIT = 50;
183
183
  const LICENSE_VERIFY_MAX_AGE_MS = 6 * 60 * 60 * 1000;