@matter/protocol 0.14.1-alpha.0-20250605-9fc134af0 → 0.14.1-alpha.0-20250607-a93593303
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/cjs/action/server/AccessControl.d.ts +5 -7
- package/dist/cjs/action/server/AccessControl.d.ts.map +1 -1
- package/dist/cjs/action/server/AccessControl.js.map +1 -1
- package/dist/cjs/action/server/AttributeWriteResponse.d.ts.map +1 -1
- package/dist/cjs/action/server/AttributeWriteResponse.js +23 -0
- package/dist/cjs/action/server/AttributeWriteResponse.js.map +1 -1
- package/dist/cjs/action/server/CommandInvokeResponse.d.ts.map +1 -1
- package/dist/cjs/action/server/CommandInvokeResponse.js +24 -1
- package/dist/cjs/action/server/CommandInvokeResponse.js.map +1 -1
- package/dist/cjs/action/server/DataResponse.d.ts +1 -1
- package/dist/cjs/action/server/DataResponse.d.ts.map +1 -1
- package/dist/cjs/action/server/Subject.d.ts +25 -0
- package/dist/cjs/action/server/Subject.d.ts.map +1 -0
- package/dist/cjs/action/server/Subject.js +54 -0
- package/dist/cjs/action/server/Subject.js.map +6 -0
- package/dist/cjs/action/server/index.d.ts +1 -0
- package/dist/cjs/action/server/index.d.ts.map +1 -1
- package/dist/cjs/action/server/index.js +1 -0
- package/dist/cjs/action/server/index.js.map +1 -1
- package/dist/cjs/certificate/DeviceCertification.d.ts +2 -2
- package/dist/cjs/certificate/DeviceCertification.d.ts.map +1 -1
- package/dist/cjs/certificate/DeviceCertification.js.map +1 -1
- package/dist/cjs/cluster/client/AttributeClient.d.ts +3 -3
- package/dist/cjs/cluster/client/AttributeClient.d.ts.map +1 -1
- package/dist/cjs/cluster/client/AttributeClient.js +14 -2
- package/dist/cjs/cluster/client/AttributeClient.js.map +1 -1
- package/dist/cjs/cluster/client/ClusterClient.d.ts +3 -2
- package/dist/cjs/cluster/client/ClusterClient.d.ts.map +1 -1
- package/dist/cjs/cluster/client/ClusterClient.js +66 -1
- package/dist/cjs/cluster/client/ClusterClient.js.map +1 -1
- package/dist/cjs/cluster/client/ClusterClientTypes.d.ts +36 -8
- package/dist/cjs/cluster/client/ClusterClientTypes.d.ts.map +1 -1
- package/dist/cjs/cluster/client/EventClient.d.ts +3 -3
- package/dist/cjs/cluster/client/EventClient.d.ts.map +1 -1
- package/dist/cjs/cluster/client/EventClient.js +7 -0
- package/dist/cjs/cluster/client/EventClient.js.map +1 -1
- package/dist/cjs/codec/MessageCodec.d.ts.map +1 -1
- package/dist/cjs/codec/MessageCodec.js +31 -6
- package/dist/cjs/codec/MessageCodec.js.map +1 -1
- package/dist/cjs/fabric/Fabric.d.ts +20 -30
- package/dist/cjs/fabric/Fabric.d.ts.map +1 -1
- package/dist/cjs/fabric/Fabric.js +38 -62
- package/dist/cjs/fabric/Fabric.js.map +2 -2
- package/dist/cjs/fabric/FabricManager.d.ts.map +1 -1
- package/dist/cjs/fabric/FabricManager.js +10 -4
- package/dist/cjs/fabric/FabricManager.js.map +1 -1
- package/dist/cjs/groups/FabricGroupsManager.d.ts +46 -0
- package/dist/cjs/groups/FabricGroupsManager.d.ts.map +1 -0
- package/dist/cjs/groups/FabricGroupsManager.js +155 -0
- package/dist/cjs/groups/FabricGroupsManager.js.map +6 -0
- package/dist/cjs/groups/Groups.d.ts +34 -0
- package/dist/cjs/groups/Groups.d.ts.map +1 -0
- package/dist/cjs/groups/Groups.js +89 -0
- package/dist/cjs/groups/Groups.js.map +6 -0
- package/dist/cjs/groups/KeySets.d.ts +64 -0
- package/dist/cjs/groups/KeySets.d.ts.map +1 -0
- package/dist/cjs/groups/KeySets.js +179 -0
- package/dist/cjs/groups/KeySets.js.map +6 -0
- package/dist/cjs/groups/MessagingState.d.ts +24 -0
- package/dist/cjs/groups/MessagingState.d.ts.map +1 -0
- package/dist/cjs/groups/MessagingState.js +91 -0
- package/dist/cjs/groups/MessagingState.js.map +6 -0
- package/dist/cjs/groups/index.d.ts +8 -0
- package/dist/cjs/groups/index.d.ts.map +1 -0
- package/dist/cjs/groups/index.js +25 -0
- package/dist/cjs/groups/index.js.map +6 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interaction/AccessControlManager.d.ts +4 -13
- package/dist/cjs/interaction/AccessControlManager.d.ts.map +1 -1
- package/dist/cjs/interaction/AccessControlManager.js +38 -47
- package/dist/cjs/interaction/AccessControlManager.js.map +1 -1
- package/dist/cjs/interaction/InteractionClient.d.ts +5 -4
- package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionClient.js +53 -3
- package/dist/cjs/interaction/InteractionClient.js.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.js +15 -0
- package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
- package/dist/cjs/interaction/Subscription.d.ts +3 -3
- package/dist/cjs/interaction/Subscription.d.ts.map +1 -1
- package/dist/cjs/interaction/Subscription.js.map +1 -1
- package/dist/cjs/peer/PeerAddress.d.ts +1 -0
- package/dist/cjs/peer/PeerAddress.d.ts.map +1 -1
- package/dist/cjs/peer/PeerAddress.js +5 -0
- package/dist/cjs/peer/PeerAddress.js.map +1 -1
- package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
- package/dist/cjs/peer/PeerSet.js +31 -2
- package/dist/cjs/peer/PeerSet.js.map +1 -1
- package/dist/cjs/protocol/ChannelManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ChannelManager.js +7 -8
- package/dist/cjs/protocol/ChannelManager.js.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.js +39 -25
- package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
- package/dist/cjs/protocol/MessageExchange.d.ts +1 -1
- package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/cjs/protocol/MessageExchange.js +32 -4
- package/dist/cjs/protocol/MessageExchange.js.map +1 -1
- package/dist/cjs/protocol/MessageReceptionState.d.ts +1 -1
- package/dist/cjs/securechannel/SecureChannelProtocol.js +1 -1
- package/dist/cjs/securechannel/SecureChannelProtocol.js.map +1 -1
- package/dist/cjs/session/GroupSession.d.ts +56 -0
- package/dist/cjs/session/GroupSession.d.ts.map +1 -0
- package/dist/cjs/session/GroupSession.js +188 -0
- package/dist/cjs/session/GroupSession.js.map +6 -0
- package/dist/cjs/session/InsecureSession.d.ts +2 -1
- package/dist/cjs/session/InsecureSession.d.ts.map +1 -1
- package/dist/cjs/session/InsecureSession.js +3 -2
- package/dist/cjs/session/InsecureSession.js.map +1 -1
- package/dist/cjs/session/NodeSession.d.ts +88 -0
- package/dist/cjs/session/NodeSession.d.ts.map +1 -0
- package/dist/cjs/session/NodeSession.js +318 -0
- package/dist/cjs/session/NodeSession.js.map +6 -0
- package/dist/cjs/session/SecureSession.d.ts +10 -75
- package/dist/cjs/session/SecureSession.d.ts.map +1 -1
- package/dist/cjs/session/SecureSession.js +9 -280
- package/dist/cjs/session/SecureSession.js.map +2 -2
- package/dist/cjs/session/Session.d.ts +6 -5
- package/dist/cjs/session/Session.d.ts.map +1 -1
- package/dist/cjs/session/Session.js +11 -1
- package/dist/cjs/session/Session.js.map +1 -1
- package/dist/cjs/session/SessionManager.d.ts +27 -9
- package/dist/cjs/session/SessionManager.d.ts.map +1 -1
- package/dist/cjs/session/SessionManager.js +83 -5
- package/dist/cjs/session/SessionManager.js.map +2 -2
- package/dist/cjs/session/case/CaseClient.d.ts +1 -1
- package/dist/cjs/session/case/CaseClient.js +2 -2
- package/dist/cjs/session/case/CaseClient.js.map +1 -1
- package/dist/cjs/session/index.d.ts +2 -0
- package/dist/cjs/session/index.d.ts.map +1 -1
- package/dist/cjs/session/index.js +2 -0
- package/dist/cjs/session/index.js.map +1 -1
- package/dist/cjs/session/pase/PaseClient.d.ts +1 -1
- package/dist/esm/action/server/AccessControl.d.ts +5 -7
- package/dist/esm/action/server/AccessControl.d.ts.map +1 -1
- package/dist/esm/action/server/AccessControl.js.map +1 -1
- package/dist/esm/action/server/AttributeWriteResponse.d.ts.map +1 -1
- package/dist/esm/action/server/AttributeWriteResponse.js +23 -0
- package/dist/esm/action/server/AttributeWriteResponse.js.map +1 -1
- package/dist/esm/action/server/CommandInvokeResponse.d.ts.map +1 -1
- package/dist/esm/action/server/CommandInvokeResponse.js +24 -1
- package/dist/esm/action/server/CommandInvokeResponse.js.map +1 -1
- package/dist/esm/action/server/DataResponse.d.ts +1 -1
- package/dist/esm/action/server/DataResponse.d.ts.map +1 -1
- package/dist/esm/action/server/Subject.d.ts +25 -0
- package/dist/esm/action/server/Subject.d.ts.map +1 -0
- package/dist/esm/action/server/Subject.js +34 -0
- package/dist/esm/action/server/Subject.js.map +6 -0
- package/dist/esm/action/server/index.d.ts +1 -0
- package/dist/esm/action/server/index.d.ts.map +1 -1
- package/dist/esm/action/server/index.js +1 -0
- package/dist/esm/action/server/index.js.map +1 -1
- package/dist/esm/certificate/DeviceCertification.d.ts +2 -2
- package/dist/esm/certificate/DeviceCertification.d.ts.map +1 -1
- package/dist/esm/certificate/DeviceCertification.js.map +1 -1
- package/dist/esm/cluster/client/AttributeClient.d.ts +3 -3
- package/dist/esm/cluster/client/AttributeClient.d.ts.map +1 -1
- package/dist/esm/cluster/client/AttributeClient.js +13 -1
- package/dist/esm/cluster/client/AttributeClient.js.map +1 -1
- package/dist/esm/cluster/client/ClusterClient.d.ts +3 -2
- package/dist/esm/cluster/client/ClusterClient.d.ts.map +1 -1
- package/dist/esm/cluster/client/ClusterClient.js +67 -2
- package/dist/esm/cluster/client/ClusterClient.js.map +1 -1
- package/dist/esm/cluster/client/ClusterClientTypes.d.ts +36 -8
- package/dist/esm/cluster/client/ClusterClientTypes.d.ts.map +1 -1
- package/dist/esm/cluster/client/EventClient.d.ts +3 -3
- package/dist/esm/cluster/client/EventClient.d.ts.map +1 -1
- package/dist/esm/cluster/client/EventClient.js +7 -0
- package/dist/esm/cluster/client/EventClient.js.map +1 -1
- package/dist/esm/codec/MessageCodec.d.ts.map +1 -1
- package/dist/esm/codec/MessageCodec.js +41 -7
- package/dist/esm/codec/MessageCodec.js.map +1 -1
- package/dist/esm/fabric/Fabric.d.ts +20 -30
- package/dist/esm/fabric/Fabric.d.ts.map +1 -1
- package/dist/esm/fabric/Fabric.js +38 -62
- package/dist/esm/fabric/Fabric.js.map +2 -2
- package/dist/esm/fabric/FabricManager.d.ts.map +1 -1
- package/dist/esm/fabric/FabricManager.js +10 -4
- package/dist/esm/fabric/FabricManager.js.map +1 -1
- package/dist/esm/groups/FabricGroupsManager.d.ts +46 -0
- package/dist/esm/groups/FabricGroupsManager.d.ts.map +1 -0
- package/dist/esm/groups/FabricGroupsManager.js +135 -0
- package/dist/esm/groups/FabricGroupsManager.js.map +6 -0
- package/dist/esm/groups/Groups.d.ts +34 -0
- package/dist/esm/groups/Groups.d.ts.map +1 -0
- package/dist/esm/groups/Groups.js +69 -0
- package/dist/esm/groups/Groups.js.map +6 -0
- package/dist/esm/groups/KeySets.d.ts +64 -0
- package/dist/esm/groups/KeySets.d.ts.map +1 -0
- package/dist/esm/groups/KeySets.js +159 -0
- package/dist/esm/groups/KeySets.js.map +6 -0
- package/dist/esm/groups/MessagingState.d.ts +24 -0
- package/dist/esm/groups/MessagingState.d.ts.map +1 -0
- package/dist/esm/groups/MessagingState.js +71 -0
- package/dist/esm/groups/MessagingState.js.map +6 -0
- package/dist/esm/groups/index.d.ts +8 -0
- package/dist/esm/groups/index.d.ts.map +1 -0
- package/dist/esm/groups/index.js +8 -0
- package/dist/esm/groups/index.js.map +6 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interaction/AccessControlManager.d.ts +4 -13
- package/dist/esm/interaction/AccessControlManager.d.ts.map +1 -1
- package/dist/esm/interaction/AccessControlManager.js +39 -48
- package/dist/esm/interaction/AccessControlManager.js.map +1 -1
- package/dist/esm/interaction/InteractionClient.d.ts +5 -4
- package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionClient.js +54 -4
- package/dist/esm/interaction/InteractionClient.js.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.js +15 -0
- package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
- package/dist/esm/interaction/Subscription.d.ts +3 -3
- package/dist/esm/interaction/Subscription.d.ts.map +1 -1
- package/dist/esm/interaction/Subscription.js.map +1 -1
- package/dist/esm/peer/PeerAddress.d.ts +1 -0
- package/dist/esm/peer/PeerAddress.d.ts.map +1 -1
- package/dist/esm/peer/PeerAddress.js +5 -0
- package/dist/esm/peer/PeerAddress.js.map +1 -1
- package/dist/esm/peer/PeerSet.d.ts.map +1 -1
- package/dist/esm/peer/PeerSet.js +33 -3
- package/dist/esm/peer/PeerSet.js.map +1 -1
- package/dist/esm/protocol/ChannelManager.d.ts.map +1 -1
- package/dist/esm/protocol/ChannelManager.js +7 -8
- package/dist/esm/protocol/ChannelManager.js.map +1 -1
- package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeManager.js +41 -27
- package/dist/esm/protocol/ExchangeManager.js.map +1 -1
- package/dist/esm/protocol/MessageExchange.d.ts +1 -1
- package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/esm/protocol/MessageExchange.js +39 -5
- package/dist/esm/protocol/MessageExchange.js.map +1 -1
- package/dist/esm/protocol/MessageReceptionState.d.ts +1 -1
- package/dist/esm/securechannel/SecureChannelProtocol.js +2 -2
- package/dist/esm/securechannel/SecureChannelProtocol.js.map +1 -1
- package/dist/esm/session/GroupSession.d.ts +56 -0
- package/dist/esm/session/GroupSession.d.ts.map +1 -0
- package/dist/esm/session/GroupSession.js +177 -0
- package/dist/esm/session/GroupSession.js.map +6 -0
- package/dist/esm/session/InsecureSession.d.ts +2 -1
- package/dist/esm/session/InsecureSession.d.ts.map +1 -1
- package/dist/esm/session/InsecureSession.js +3 -2
- package/dist/esm/session/InsecureSession.js.map +1 -1
- package/dist/esm/session/NodeSession.d.ts +88 -0
- package/dist/esm/session/NodeSession.d.ts.map +1 -0
- package/dist/esm/session/NodeSession.js +298 -0
- package/dist/esm/session/NodeSession.js.map +6 -0
- package/dist/esm/session/SecureSession.d.ts +10 -75
- package/dist/esm/session/SecureSession.d.ts.map +1 -1
- package/dist/esm/session/SecureSession.js +10 -291
- package/dist/esm/session/SecureSession.js.map +2 -2
- package/dist/esm/session/Session.d.ts +6 -5
- package/dist/esm/session/Session.d.ts.map +1 -1
- package/dist/esm/session/Session.js +12 -2
- package/dist/esm/session/Session.js.map +1 -1
- package/dist/esm/session/SessionManager.d.ts +27 -9
- package/dist/esm/session/SessionManager.d.ts.map +1 -1
- package/dist/esm/session/SessionManager.js +84 -6
- package/dist/esm/session/SessionManager.js.map +1 -1
- package/dist/esm/session/case/CaseClient.d.ts +1 -1
- package/dist/esm/session/case/CaseClient.js +2 -2
- package/dist/esm/session/case/CaseClient.js.map +1 -1
- package/dist/esm/session/index.d.ts +2 -0
- package/dist/esm/session/index.d.ts.map +1 -1
- package/dist/esm/session/index.js +2 -0
- package/dist/esm/session/index.js.map +1 -1
- package/dist/esm/session/pase/PaseClient.d.ts +1 -1
- package/package.json +6 -6
- package/src/action/server/AccessControl.ts +4 -7
- package/src/action/server/AttributeWriteResponse.ts +29 -7
- package/src/action/server/CommandInvokeResponse.ts +28 -7
- package/src/action/server/DataResponse.ts +1 -1
- package/src/action/server/Subject.ts +45 -0
- package/src/action/server/index.ts +1 -0
- package/src/certificate/DeviceCertification.ts +2 -2
- package/src/cluster/client/AttributeClient.ts +15 -3
- package/src/cluster/client/ClusterClient.ts +97 -4
- package/src/cluster/client/ClusterClientTypes.ts +45 -9
- package/src/cluster/client/EventClient.ts +9 -2
- package/src/codec/MessageCodec.ts +49 -8
- package/src/fabric/Fabric.ts +51 -85
- package/src/fabric/FabricManager.ts +11 -4
- package/src/groups/FabricGroupsManager.ts +164 -0
- package/src/groups/Groups.ts +81 -0
- package/src/groups/KeySets.ts +194 -0
- package/src/groups/MessagingState.ts +76 -0
- package/src/groups/index.ts +8 -0
- package/src/index.ts +1 -0
- package/src/interaction/AccessControlManager.ts +49 -81
- package/src/interaction/InteractionClient.ts +66 -6
- package/src/interaction/InteractionMessenger.ts +15 -0
- package/src/interaction/Subscription.ts +3 -3
- package/src/peer/PeerAddress.ts +4 -0
- package/src/peer/PeerSet.ts +39 -4
- package/src/protocol/ChannelManager.ts +7 -9
- package/src/protocol/ExchangeManager.ts +51 -35
- package/src/protocol/MessageExchange.ts +42 -7
- package/src/protocol/MessageReceptionState.ts +2 -2
- package/src/securechannel/SecureChannelProtocol.ts +2 -2
- package/src/session/GroupSession.ts +223 -0
- package/src/session/InsecureSession.ts +3 -2
- package/src/session/NodeSession.ts +367 -0
- package/src/session/SecureSession.ts +14 -363
- package/src/session/Session.ts +17 -6
- package/src/session/SessionManager.ts +94 -14
- package/src/session/case/CaseClient.ts +2 -2
- package/src/session/index.ts +2 -3
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { GroupKeyManagement } from "#clusters/group-key-management";
|
|
8
|
+
import { BasicSet, Bytes, Crypto, DataReader, ImplementationError, MatterFlowError, Time } from "#general";
|
|
9
|
+
|
|
10
|
+
export const GROUP_KEY_INFO = Bytes.fromString("GroupKeyHash");
|
|
11
|
+
|
|
12
|
+
export class KeySets<T extends OperationalKeySet> extends BasicSet<T> {
|
|
13
|
+
/** Operational enhanced structure for fast access based on the group session id. */
|
|
14
|
+
readonly #sessions = new Map<number, { keySetId: number; key: Uint8Array }[]>();
|
|
15
|
+
|
|
16
|
+
get sessions() {
|
|
17
|
+
return this.#sessions;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override add(item: T): void {
|
|
21
|
+
this.delete("groupKeySetId", item.groupKeySetId); // Remove any existing item with the same groupKeySetId
|
|
22
|
+
super.add(item);
|
|
23
|
+
this.#updateSessions();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
override delete<F extends keyof T>(itemOrField: T | F, value?: T[F]): boolean {
|
|
27
|
+
const deleted = super.delete(itemOrField as any, value as any);
|
|
28
|
+
if (deleted) {
|
|
29
|
+
this.#updateSessions();
|
|
30
|
+
}
|
|
31
|
+
return deleted;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
forId(groupKeySetId: number): OperationalKeySet | undefined {
|
|
35
|
+
return this.get("groupKeySetId", groupKeySetId);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Return an operative list of operational keys, start time and their session IDs for a specified
|
|
40
|
+
* group key set id. This is mainly used for receiving messages.
|
|
41
|
+
*/
|
|
42
|
+
allKeysForId(keySetId: number) {
|
|
43
|
+
const groupKeySet = this.forId(keySetId);
|
|
44
|
+
if (groupKeySet === undefined) {
|
|
45
|
+
throw new MatterFlowError(`GroupKeySet for groupKeySet ${keySetId} not found.`);
|
|
46
|
+
}
|
|
47
|
+
const operationalKeys = Array<{ key: Uint8Array; sessionId?: number; startTime: number | bigint }>();
|
|
48
|
+
const {
|
|
49
|
+
operationalEpochKey0,
|
|
50
|
+
groupSessionId0,
|
|
51
|
+
epochStartTime0,
|
|
52
|
+
operationalEpochKey1,
|
|
53
|
+
groupSessionId1,
|
|
54
|
+
epochStartTime1,
|
|
55
|
+
operationalEpochKey2,
|
|
56
|
+
groupSessionId2,
|
|
57
|
+
epochStartTime2,
|
|
58
|
+
} = groupKeySet;
|
|
59
|
+
if (operationalEpochKey0 === null || epochStartTime0 === null || (keySetId !== 0 && groupSessionId0 === null)) {
|
|
60
|
+
// should never happen, but just in case
|
|
61
|
+
throw new MatterFlowError(`EpochKey0 for groupKeySet ${keySetId} not found.`);
|
|
62
|
+
}
|
|
63
|
+
operationalKeys.push({
|
|
64
|
+
key: operationalEpochKey0,
|
|
65
|
+
sessionId: groupSessionId0 !== null ? groupSessionId0 : undefined,
|
|
66
|
+
startTime: epochStartTime0,
|
|
67
|
+
});
|
|
68
|
+
if (operationalEpochKey1 !== null && groupSessionId1 !== null && epochStartTime1 !== null) {
|
|
69
|
+
operationalKeys.push({ key: operationalEpochKey1, sessionId: groupSessionId1, startTime: epochStartTime1 });
|
|
70
|
+
}
|
|
71
|
+
if (operationalEpochKey2 !== null && groupSessionId2 !== null && epochStartTime2 !== null) {
|
|
72
|
+
operationalKeys.push({ key: operationalEpochKey2, sessionId: groupSessionId2, startTime: epochStartTime2 });
|
|
73
|
+
}
|
|
74
|
+
return operationalKeys;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Returns the current operational group key for a given group KeySet Id and returns the keys, start time and
|
|
79
|
+
* their session IDs. This is mainly used for sending messages.
|
|
80
|
+
*/
|
|
81
|
+
currentKeyForId(keySetId: number) {
|
|
82
|
+
const operationalKeys = this.allKeysForId(keySetId);
|
|
83
|
+
if (operationalKeys.length === 0) {
|
|
84
|
+
throw new MatterFlowError(`No operational keys found for groupKeySet ${keySetId}.`);
|
|
85
|
+
}
|
|
86
|
+
if (keySetId === 0) {
|
|
87
|
+
// Groups: For the generation of the Destination Identifier, the originator SHALL use the operational group key with
|
|
88
|
+
// the second newest EpochStartTime, if one exists, otherwise it SHALL use the single operational group key available.
|
|
89
|
+
// @see {@link MatterSpecification.v14.Core} § 4.14.2.6.
|
|
90
|
+
if (operationalKeys.length > 2) {
|
|
91
|
+
return operationalKeys[1];
|
|
92
|
+
}
|
|
93
|
+
return operationalKeys[0];
|
|
94
|
+
} else {
|
|
95
|
+
// Nodes sending group messages SHALL use operational group keys that are derived from the current
|
|
96
|
+
// epoch key (specifically, the epoch key with the latest start time that is not in the future).
|
|
97
|
+
// TODO Nodes that cannot reliably keep track of time calculate the current epoch key as described in
|
|
98
|
+
// Section 4.17.3.4, “Epoch Key Rotation without Time Synchronization”.
|
|
99
|
+
const now = Time.nowUs();
|
|
100
|
+
const relevantKeys = operationalKeys.filter(({ startTime }) => startTime <= now);
|
|
101
|
+
if (relevantKeys.length === 0) {
|
|
102
|
+
throw new ImplementationError(
|
|
103
|
+
`No operational keys found for groupKeySet ${keySetId} that are not in the future.`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
return relevantKeys[operationalKeys.length - 1];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Returns the group key set for a given group key set id in the official data format from the Group key Management
|
|
112
|
+
* cluster.
|
|
113
|
+
*/
|
|
114
|
+
asGroupKeySet(groupKeySetId: number) {
|
|
115
|
+
const groupKeySet = this.forId(groupKeySetId);
|
|
116
|
+
if (groupKeySet === undefined) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const {
|
|
121
|
+
epochKey0,
|
|
122
|
+
epochStartTime0,
|
|
123
|
+
epochKey1,
|
|
124
|
+
epochStartTime1,
|
|
125
|
+
epochKey2,
|
|
126
|
+
epochStartTime2,
|
|
127
|
+
groupKeySecurityPolicy,
|
|
128
|
+
groupKeyMulticastPolicy,
|
|
129
|
+
} = groupKeySet;
|
|
130
|
+
return {
|
|
131
|
+
groupKeySetId,
|
|
132
|
+
epochKey0,
|
|
133
|
+
epochStartTime0,
|
|
134
|
+
epochKey1,
|
|
135
|
+
epochStartTime1,
|
|
136
|
+
epochKey2,
|
|
137
|
+
epochStartTime2,
|
|
138
|
+
groupKeySecurityPolicy,
|
|
139
|
+
groupKeyMulticastPolicy,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Calculates a group session id based on the operational group key. */
|
|
144
|
+
async sessionIdFromKey(operationalGroupKey: Uint8Array) {
|
|
145
|
+
// GroupKeyHash is an array of 2 bytes (16 bits) per Crypto_KDF
|
|
146
|
+
const groupKeyHash = await Crypto.hkdf(operationalGroupKey, new Uint8Array(), GROUP_KEY_INFO, 2);
|
|
147
|
+
|
|
148
|
+
// GroupSessionId is computed by considering the GroupKeyHash as a Big-Endian value. GroupSessionId is a scalar.
|
|
149
|
+
// Its use in fields within messages may cause a re-serialization into a different byte order than the one used
|
|
150
|
+
// for initial generation.
|
|
151
|
+
return new DataReader(groupKeyHash).readUInt16();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Updates the group session map based on the current group key sets.
|
|
156
|
+
* This is used to quickly find the operational keys by their group session id.
|
|
157
|
+
*/
|
|
158
|
+
#updateSessions() {
|
|
159
|
+
this.#sessions.clear();
|
|
160
|
+
for (const [id, keySet] of this.mapOf("groupKeySetId").entries()) {
|
|
161
|
+
if (id === 0) {
|
|
162
|
+
// Skip the default group key set (0), as it is not used for operational keys
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (keySet.groupSessionId0 !== null) {
|
|
166
|
+
const list = this.#sessions.get(keySet.groupSessionId0) ?? [];
|
|
167
|
+
list.push({ key: keySet.operationalEpochKey0, keySetId: id });
|
|
168
|
+
this.#sessions.set(keySet.groupSessionId0, list);
|
|
169
|
+
}
|
|
170
|
+
if (keySet.groupSessionId1 !== null && keySet.operationalEpochKey1 !== null) {
|
|
171
|
+
const list = this.#sessions.get(keySet.groupSessionId1) ?? [];
|
|
172
|
+
list.push({ key: keySet.operationalEpochKey1, keySetId: id });
|
|
173
|
+
this.#sessions.set(keySet.groupSessionId1, list);
|
|
174
|
+
}
|
|
175
|
+
if (keySet.groupSessionId2 !== null && keySet.operationalEpochKey2 !== null) {
|
|
176
|
+
const list = this.#sessions.get(keySet.groupSessionId2) ?? [];
|
|
177
|
+
list.push({ key: keySet.operationalEpochKey2, keySetId: id });
|
|
178
|
+
this.#sessions.set(keySet.groupSessionId2, list);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export type GroupKeySet = GroupKeyManagement.GroupKeySet;
|
|
185
|
+
|
|
186
|
+
/** Enhanced structure of GroupKeySet to include operational data for easier operational processing. */
|
|
187
|
+
export type OperationalKeySet = GroupKeySet & {
|
|
188
|
+
operationalEpochKey0: Uint8Array;
|
|
189
|
+
groupSessionId0: number | null;
|
|
190
|
+
operationalEpochKey1: Uint8Array | null;
|
|
191
|
+
groupSessionId1: number | null;
|
|
192
|
+
operationalEpochKey2: Uint8Array | null;
|
|
193
|
+
groupSessionId2: number | null;
|
|
194
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { Bytes, ImplementationError, InternalError, StorageContext } from "#general";
|
|
7
|
+
import { PersistedMessageCounter } from "#protocol/MessageCounter.js";
|
|
8
|
+
import { MessageReceptionStateEncryptedWithRollover } from "#protocol/MessageReceptionState.js";
|
|
9
|
+
import { NodeId } from "#types";
|
|
10
|
+
|
|
11
|
+
export class MessagingState {
|
|
12
|
+
/**
|
|
13
|
+
* Message counter for sending data messages to a group per Operational key. No need to scope to a source node
|
|
14
|
+
* because we are the sending node
|
|
15
|
+
* TODO: For management: Make sure to start rotating the key early enough that a former counter-value is not used
|
|
16
|
+
* again for the same key.
|
|
17
|
+
*/
|
|
18
|
+
readonly #groupDataCounters = new Map<string, PersistedMessageCounter>();
|
|
19
|
+
|
|
20
|
+
/** Message reception state for data messages per Operational key and source node. */
|
|
21
|
+
readonly #messageDataReceptionState = new Map<string, Map<NodeId, MessageReceptionStateEncryptedWithRollover>>();
|
|
22
|
+
#storage?: StorageContext;
|
|
23
|
+
|
|
24
|
+
constructor(storage?: StorageContext) {
|
|
25
|
+
if (storage !== undefined) {
|
|
26
|
+
this.#storage = storage;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
set storage(storage: StorageContext) {
|
|
31
|
+
if (this.#storage !== undefined) {
|
|
32
|
+
throw new InternalError("Storage context can only be set once.");
|
|
33
|
+
}
|
|
34
|
+
this.#storage = storage;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Return the message counter for sending messages to a group with the given operational key.
|
|
39
|
+
*/
|
|
40
|
+
counterFor(operationalKey: Uint8Array) {
|
|
41
|
+
if (!this.#storage) {
|
|
42
|
+
throw new ImplementationError("Group session cannot be created without storage context.");
|
|
43
|
+
}
|
|
44
|
+
const operationalKeyHex = Bytes.toHex(operationalKey);
|
|
45
|
+
let counter = this.#groupDataCounters.get(operationalKeyHex);
|
|
46
|
+
if (counter === undefined) {
|
|
47
|
+
counter = new PersistedMessageCounter(this.#storage, `${operationalKeyHex}-data`);
|
|
48
|
+
this.#groupDataCounters.set(operationalKeyHex, counter);
|
|
49
|
+
}
|
|
50
|
+
return counter;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async removeCounter(key: Uint8Array, forDelete = false) {
|
|
54
|
+
const operationalKeyHex = Bytes.toHex(key);
|
|
55
|
+
this.#groupDataCounters.delete(operationalKeyHex);
|
|
56
|
+
if (forDelete) {
|
|
57
|
+
// If we are deleting the group key set, also delete the persisted counter values
|
|
58
|
+
await this.#storage?.delete(`${operationalKeyHex}-data`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Returns the message reception state for a given source node id and operational key.
|
|
64
|
+
*/
|
|
65
|
+
receptionStateFor(sourceNodeId: NodeId, operationalKey: Uint8Array) {
|
|
66
|
+
const operationalKeyHex = Bytes.toHex(operationalKey);
|
|
67
|
+
let receptionState = this.#messageDataReceptionState.get(operationalKeyHex)?.get(sourceNodeId);
|
|
68
|
+
if (receptionState === undefined) {
|
|
69
|
+
receptionState = new MessageReceptionStateEncryptedWithRollover();
|
|
70
|
+
const keyMap = this.#messageDataReceptionState.get(operationalKeyHex) ?? new Map();
|
|
71
|
+
keyMap.set(sourceNodeId, receptionState);
|
|
72
|
+
this.#messageDataReceptionState.set(operationalKeyHex, keyMap);
|
|
73
|
+
}
|
|
74
|
+
return receptionState;
|
|
75
|
+
}
|
|
76
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from "./codec/index.js";
|
|
|
12
12
|
export * from "./common/index.js";
|
|
13
13
|
export * from "./events/index.js";
|
|
14
14
|
export * from "./fabric/index.js";
|
|
15
|
+
export * from "./groups/index.js";
|
|
15
16
|
export * from "./interaction/index.js";
|
|
16
17
|
export * from "./mdns/index.js";
|
|
17
18
|
export * from "./peer/index.js";
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* Copyright 2022-2023 Project CHIP Authors
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
+
import { Subject } from "#action/server/Subject.js";
|
|
6
7
|
import { AccessControl } from "#clusters/access-control";
|
|
7
|
-
import {
|
|
8
|
+
import { MatterFlowError } from "#general";
|
|
8
9
|
import { AccessLevel } from "#model";
|
|
9
10
|
import {
|
|
10
11
|
CaseAuthenticatedTag,
|
|
@@ -15,11 +16,9 @@ import {
|
|
|
15
16
|
NodeId,
|
|
16
17
|
StatusCode,
|
|
17
18
|
StatusResponseError,
|
|
19
|
+
SubjectId,
|
|
18
20
|
} from "#types";
|
|
19
|
-
import {
|
|
20
|
-
import { SecureSession } from "../session/SecureSession.js";
|
|
21
|
-
|
|
22
|
-
const logger = Logger.get("AccessControlManager");
|
|
21
|
+
import { AccessControl as AccessControlContext } from "../action/server/AccessControl.js";
|
|
23
22
|
|
|
24
23
|
export type AclEntry = Omit<AccessControl.AccessControlEntry, "privilege"> & {
|
|
25
24
|
privilege: AccessLevel;
|
|
@@ -49,7 +48,7 @@ enum AuthModeNone {
|
|
|
49
48
|
export type IncomingSubjectDescriptor = {
|
|
50
49
|
isCommissioning: boolean;
|
|
51
50
|
authMode: AccessControl.AccessControlEntryAuthMode | AuthModeNone;
|
|
52
|
-
subjects:
|
|
51
|
+
subjects: SubjectId[];
|
|
53
52
|
fabricIndex: FabricIndex;
|
|
54
53
|
};
|
|
55
54
|
|
|
@@ -98,22 +97,24 @@ export class AccessControlManager {
|
|
|
98
97
|
/**
|
|
99
98
|
* Get the Access Control List for a given fabric.
|
|
100
99
|
*/
|
|
101
|
-
#getAccessControlEntriesForFabric(
|
|
102
|
-
return this.#aclList.filter(entry => entry.fabricIndex ===
|
|
100
|
+
#getAccessControlEntriesForFabric(fabricIndex: FabricIndex): AclList {
|
|
101
|
+
return this.#aclList.filter(entry => entry.fabricIndex === fabricIndex);
|
|
103
102
|
}
|
|
104
103
|
|
|
105
104
|
/**
|
|
106
105
|
* Subjects must match exactly, or both are CAT with matching CAT ID and acceptable CAT version
|
|
107
106
|
*/
|
|
108
|
-
#subjectMatches(aclSubject:
|
|
109
|
-
if (aclSubject === isdSubject) {
|
|
107
|
+
#subjectMatches(aclSubject: SubjectId, isdSubject: SubjectId): boolean {
|
|
108
|
+
if (BigInt(aclSubject) === BigInt(isdSubject)) {
|
|
110
109
|
return true;
|
|
111
110
|
}
|
|
112
|
-
|
|
111
|
+
const aclNode = NodeId(aclSubject);
|
|
112
|
+
const isdNode = NodeId(isdSubject);
|
|
113
|
+
if (!NodeId.isCaseAuthenticatedTag(aclNode) || !NodeId.isCaseAuthenticatedTag(isdNode)) {
|
|
113
114
|
return false;
|
|
114
115
|
}
|
|
115
|
-
const aclSubjectCat = NodeId.extractAsCaseAuthenticatedTag(
|
|
116
|
-
const isdSubjectCat = NodeId.extractAsCaseAuthenticatedTag(
|
|
116
|
+
const aclSubjectCat = NodeId.extractAsCaseAuthenticatedTag(aclNode);
|
|
117
|
+
const isdSubjectCat = NodeId.extractAsCaseAuthenticatedTag(isdNode);
|
|
117
118
|
return (
|
|
118
119
|
CaseAuthenticatedTag.getIdentifyValue(aclSubjectCat) ===
|
|
119
120
|
CaseAuthenticatedTag.getIdentifyValue(isdSubjectCat) &&
|
|
@@ -149,40 +150,16 @@ export class AccessControlManager {
|
|
|
149
150
|
}
|
|
150
151
|
|
|
151
152
|
/**
|
|
152
|
-
*
|
|
153
|
+
* Determines the granted privileges for the given session, endpoint, and cluster ID and returns them.
|
|
153
154
|
*/
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
getGrantedPrivileges(
|
|
156
|
+
context: AccessControlContext.Session,
|
|
156
157
|
endpoint: AclEndpointContext,
|
|
157
158
|
clusterId: ClusterId,
|
|
158
|
-
|
|
159
|
-
): boolean {
|
|
160
|
-
const grantedPrivileges = this.getGrantedPrivileges(session, endpoint, clusterId);
|
|
161
|
-
if (grantedPrivileges.includes(privilege)) {
|
|
162
|
-
return true;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
logger.notice(
|
|
166
|
-
`Failed access control check for ${endpoint.id}/0x${toHex(clusterId)} and fabricIndex ${session.associatedFabric.fabricIndex}, acl=`,
|
|
167
|
-
this.#getAccessControlEntriesForFabric(session.associatedFabric),
|
|
168
|
-
"with ISD=",
|
|
169
|
-
this.#getIsdFromMessage(session),
|
|
170
|
-
"granted privileges=",
|
|
171
|
-
grantedPrivileges,
|
|
172
|
-
"not contains",
|
|
173
|
-
privilege,
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Determines the granted privileges for the given session, endpoint, and cluster ID and returns them.
|
|
181
|
-
*/
|
|
182
|
-
getGrantedPrivileges(session: SecureSession, endpoint: AclEndpointContext, clusterId: ClusterId): AccessLevel[] {
|
|
159
|
+
): AccessLevel[] {
|
|
183
160
|
const endpointId = endpoint.id;
|
|
184
|
-
const fabric =
|
|
185
|
-
const subjectDesc = this.#getIsdFromMessage(
|
|
161
|
+
const fabric = context.fabric;
|
|
162
|
+
const subjectDesc = this.#getIsdFromMessage(context);
|
|
186
163
|
const acl = fabric ? this.#getAccessControlEntriesForFabric(fabric) : [ImplicitDefaultPaseAclEntry];
|
|
187
164
|
|
|
188
165
|
// Granted privileges set is initially empty
|
|
@@ -203,17 +180,11 @@ export class AccessControlManager {
|
|
|
203
180
|
// other than the implicit PASE entry, which we will not see explicitly in the
|
|
204
181
|
// access control list
|
|
205
182
|
if (aclEntry.fabricIndex === FabricIndex.NO_FABRIC || aclEntry.fabricIndex !== subjectDesc.fabricIndex) {
|
|
206
|
-
logger.debug(
|
|
207
|
-
"Skipping ACL entry with mismatched fabric index",
|
|
208
|
-
aclEntry.fabricIndex,
|
|
209
|
-
subjectDesc.fabricIndex,
|
|
210
|
-
);
|
|
211
183
|
continue;
|
|
212
184
|
}
|
|
213
185
|
|
|
214
186
|
// Auth mode must match
|
|
215
187
|
if (aclEntry.authMode !== subjectDesc.authMode) {
|
|
216
|
-
logger.debug("Skipping ACL entry with mismatched auth mode", aclEntry.authMode, subjectDesc.authMode);
|
|
217
188
|
continue;
|
|
218
189
|
}
|
|
219
190
|
|
|
@@ -304,50 +275,47 @@ export class AccessControlManager {
|
|
|
304
275
|
/**
|
|
305
276
|
* Determines the Incoming Subject Descriptor (ISD) from the given session.
|
|
306
277
|
*/
|
|
307
|
-
#getIsdFromMessage(session:
|
|
308
|
-
const
|
|
278
|
+
#getIsdFromMessage(session: AccessControlContext.Session) {
|
|
279
|
+
const fabricIndex = session.fabric;
|
|
309
280
|
const isd: IncomingSubjectDescriptor = {
|
|
310
281
|
isCommissioning: false,
|
|
311
282
|
authMode: AuthModeNone.None,
|
|
312
|
-
subjects: new Array<
|
|
283
|
+
subjects: new Array<SubjectId>(),
|
|
313
284
|
fabricIndex: FabricIndex.NO_FABRIC,
|
|
314
285
|
};
|
|
315
286
|
|
|
316
|
-
|
|
287
|
+
const { subject } = session;
|
|
288
|
+
if (subject === undefined) {
|
|
289
|
+
throw new MatterFlowError("ACL error: ACL checks require an authorized subject");
|
|
290
|
+
}
|
|
291
|
+
if (subject.id === NodeId.UNSPECIFIED_NODE_ID) {
|
|
292
|
+
// Pase Session
|
|
317
293
|
isd.authMode = AccessControl.AccessControlEntryAuthMode.Pase;
|
|
318
294
|
isd.isCommissioning = true; // Or how "commissioning channel" is defined?
|
|
319
|
-
isd.subjects.push(NodeId
|
|
320
|
-
if (
|
|
321
|
-
isd.fabricIndex =
|
|
295
|
+
isd.subjects.push(NodeId.UNSPECIFIED_NODE_ID); // Default Commissioning Passcode ID
|
|
296
|
+
if (fabricIndex !== undefined && fabricIndex !== FabricIndex.NO_FABRIC) {
|
|
297
|
+
isd.fabricIndex = fabricIndex;
|
|
322
298
|
}
|
|
323
|
-
} else {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
// isd.AuthMode = AuthModeEnum.Group
|
|
334
|
-
// isd.Subjects.append(group_id)
|
|
335
|
-
// isd.FabricIndex = sessions_metadata.get_fabric_index(message)
|
|
336
|
-
// assert(isd.FabricIndex != 0) # cannot be zero
|
|
337
|
-
//
|
|
338
|
-
// isd.authMode = AccessControl.AccessControlEntryAuthMode.Group;
|
|
339
|
-
// } else {
|
|
340
|
-
|
|
299
|
+
} else if (Subject.isGroup(subject)) {
|
|
300
|
+
if (fabricIndex === undefined || fabricIndex === FabricIndex.NO_FABRIC) {
|
|
301
|
+
throw new MatterFlowError("ACL error: fabric needs to be associated for group sessions");
|
|
302
|
+
}
|
|
303
|
+
if (subject.hasValidMapping) {
|
|
304
|
+
isd.authMode = AccessControl.AccessControlEntryAuthMode.Group;
|
|
305
|
+
isd.subjects.push(subject.id);
|
|
306
|
+
isd.fabricIndex = fabricIndex;
|
|
307
|
+
}
|
|
308
|
+
} else if (Subject.isNode(subject)) {
|
|
341
309
|
// CASE session
|
|
310
|
+
if (fabricIndex === undefined || fabricIndex === FabricIndex.NO_FABRIC) {
|
|
311
|
+
throw new MatterFlowError("ACL error: Case session must be associated with a fabric");
|
|
312
|
+
}
|
|
342
313
|
isd.authMode = AccessControl.AccessControlEntryAuthMode.Case;
|
|
343
|
-
isd.subjects.push(
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
// }
|
|
347
|
-
if (fabric === undefined) {
|
|
348
|
-
throw new MatterFlowError("ACL error: fabric is undefined");
|
|
314
|
+
isd.subjects.push(subject.id);
|
|
315
|
+
if (subject.catSubjects !== undefined) {
|
|
316
|
+
isd.subjects.push(...subject.catSubjects);
|
|
349
317
|
}
|
|
350
|
-
isd.fabricIndex =
|
|
318
|
+
isd.fabricIndex = fabricIndex;
|
|
351
319
|
}
|
|
352
320
|
|
|
353
321
|
return isd;
|