@project-chip/matter.js 0.9.2 → 0.9.4
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/CommissioningServer.d.ts.map +1 -1
- package/dist/cjs/CommissioningServer.js +0 -1
- package/dist/cjs/CommissioningServer.js.map +2 -2
- package/dist/cjs/MatterDevice.d.ts +3 -0
- package/dist/cjs/MatterDevice.d.ts.map +1 -1
- package/dist/cjs/MatterDevice.js +21 -7
- package/dist/cjs/MatterDevice.js.map +2 -2
- package/dist/cjs/behavior/AccessControl.js +2 -2
- package/dist/cjs/behavior/AccessControl.js.map +2 -2
- package/dist/cjs/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.d.ts +1 -0
- package/dist/cjs/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.d.ts.map +1 -1
- package/dist/cjs/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.js +14 -0
- package/dist/cjs/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.js.map +2 -2
- package/dist/cjs/behavior/definitions/operational-credentials/OperationalCredentialsServer.d.ts.map +1 -1
- package/dist/cjs/behavior/definitions/operational-credentials/OperationalCredentialsServer.js +11 -2
- package/dist/cjs/behavior/definitions/operational-credentials/OperationalCredentialsServer.js.map +2 -2
- package/dist/cjs/behavior/state/transaction/Transaction.d.ts +18 -18
- package/dist/cjs/certificate/CertificateManager.d.ts.map +1 -1
- package/dist/cjs/certificate/CertificateManager.js +1 -0
- package/dist/cjs/certificate/CertificateManager.js.map +2 -2
- package/dist/cjs/certificate/CertificationDeclarationManager.d.ts +1 -1
- package/dist/cjs/certificate/CertificationDeclarationManager.d.ts.map +1 -1
- package/dist/cjs/certificate/CertificationDeclarationManager.js +3 -2
- package/dist/cjs/certificate/CertificationDeclarationManager.js.map +2 -2
- package/dist/cjs/cluster/server/AccessControlServer.js.map +1 -1
- package/dist/cjs/cluster/server/AttributeServer.d.ts +9 -0
- package/dist/cjs/cluster/server/AttributeServer.d.ts.map +1 -1
- package/dist/cjs/cluster/server/AttributeServer.js +62 -0
- package/dist/cjs/cluster/server/AttributeServer.js.map +3 -3
- package/dist/cjs/cluster/server/ClusterServer.d.ts.map +1 -1
- package/dist/cjs/cluster/server/ClusterServer.js +8 -1
- package/dist/cjs/cluster/server/ClusterServer.js.map +2 -2
- package/dist/cjs/cluster/server/ClusterServerTypes.d.ts +3 -3
- package/dist/cjs/cluster/server/ClusterServerTypes.d.ts.map +1 -1
- package/dist/cjs/cluster/server/ClusterServerTypes.js.map +1 -1
- package/dist/cjs/cluster/server/EventServer.d.ts +8 -2
- package/dist/cjs/cluster/server/EventServer.d.ts.map +1 -1
- package/dist/cjs/cluster/server/EventServer.js +33 -7
- package/dist/cjs/cluster/server/EventServer.js.map +2 -2
- package/dist/cjs/cluster/server/OperationalCredentialsServer.d.ts.map +1 -1
- package/dist/cjs/cluster/server/OperationalCredentialsServer.js +31 -8
- package/dist/cjs/cluster/server/OperationalCredentialsServer.js.map +2 -2
- package/dist/cjs/common/FailsafeContext.d.ts +1 -0
- package/dist/cjs/common/FailsafeContext.d.ts.map +1 -1
- package/dist/cjs/common/FailsafeContext.js +16 -2
- package/dist/cjs/common/FailsafeContext.js.map +2 -2
- package/dist/cjs/crypto/Crypto.d.ts +1 -1
- package/dist/cjs/crypto/Crypto.d.ts.map +1 -1
- package/dist/cjs/crypto/Crypto.js +2 -2
- package/dist/cjs/crypto/Crypto.js.map +2 -2
- package/dist/cjs/device/LegacyInteractionServer.d.ts +2 -2
- package/dist/cjs/device/LegacyInteractionServer.d.ts.map +1 -1
- package/dist/cjs/device/LegacyInteractionServer.js +13 -1
- package/dist/cjs/device/LegacyInteractionServer.js.map +2 -2
- package/dist/cjs/fabric/Fabric.d.ts +1 -0
- package/dist/cjs/fabric/Fabric.d.ts.map +1 -1
- package/dist/cjs/fabric/Fabric.js +5 -0
- package/dist/cjs/fabric/Fabric.js.map +2 -2
- package/dist/cjs/fabric/FabricManager.d.ts +1 -0
- package/dist/cjs/fabric/FabricManager.d.ts.map +1 -1
- package/dist/cjs/fabric/FabricManager.js +2 -1
- package/dist/cjs/fabric/FabricManager.js.map +2 -2
- package/dist/cjs/model/models/EventModel.d.ts +1 -0
- package/dist/cjs/model/models/EventModel.d.ts.map +1 -1
- package/dist/cjs/model/models/EventModel.js +3 -0
- package/dist/cjs/model/models/EventModel.js.map +2 -2
- package/dist/cjs/model/models/FieldModel.d.ts +1 -0
- package/dist/cjs/model/models/FieldModel.d.ts.map +1 -1
- package/dist/cjs/model/models/FieldModel.js +3 -0
- package/dist/cjs/model/models/FieldModel.js.map +2 -2
- package/dist/cjs/node/server/TransactionalInteractionServer.d.ts +2 -2
- package/dist/cjs/node/server/TransactionalInteractionServer.d.ts.map +1 -1
- package/dist/cjs/node/server/TransactionalInteractionServer.js +0 -2
- package/dist/cjs/node/server/TransactionalInteractionServer.js.map +2 -2
- package/dist/cjs/protocol/interaction/AttributeDataEncoder.d.ts +6 -3
- package/dist/cjs/protocol/interaction/AttributeDataEncoder.d.ts.map +1 -1
- package/dist/cjs/protocol/interaction/AttributeDataEncoder.js +14 -8
- package/dist/cjs/protocol/interaction/AttributeDataEncoder.js.map +2 -2
- package/dist/cjs/protocol/interaction/EventHandler.d.ts.map +1 -1
- package/dist/cjs/protocol/interaction/EventHandler.js +1 -3
- package/dist/cjs/protocol/interaction/EventHandler.js.map +2 -2
- package/dist/cjs/protocol/interaction/InteractionClient.js +1 -1
- package/dist/cjs/protocol/interaction/InteractionClient.js.map +2 -2
- package/dist/cjs/protocol/interaction/InteractionEndpointStructure.d.ts +3 -3
- package/dist/cjs/protocol/interaction/InteractionEndpointStructure.d.ts.map +1 -1
- package/dist/cjs/protocol/interaction/InteractionEndpointStructure.js +1 -0
- package/dist/cjs/protocol/interaction/InteractionEndpointStructure.js.map +2 -2
- package/dist/cjs/protocol/interaction/InteractionMessenger.d.ts +1 -1
- package/dist/cjs/protocol/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/cjs/protocol/interaction/InteractionMessenger.js +11 -4
- package/dist/cjs/protocol/interaction/InteractionMessenger.js.map +2 -2
- package/dist/cjs/protocol/interaction/InteractionServer.d.ts +5 -6
- package/dist/cjs/protocol/interaction/InteractionServer.d.ts.map +1 -1
- package/dist/cjs/protocol/interaction/InteractionServer.js +44 -37
- package/dist/cjs/protocol/interaction/InteractionServer.js.map +2 -2
- package/dist/cjs/protocol/interaction/SubscriptionHandler.d.ts +31 -12
- package/dist/cjs/protocol/interaction/SubscriptionHandler.d.ts.map +1 -1
- package/dist/cjs/protocol/interaction/SubscriptionHandler.js +161 -69
- package/dist/cjs/protocol/interaction/SubscriptionHandler.js.map +3 -3
- package/dist/cjs/session/SecureSession.d.ts.map +1 -1
- package/dist/cjs/session/SecureSession.js +2 -1
- package/dist/cjs/session/SecureSession.js.map +2 -2
- package/dist/cjs/session/SessionManager.d.ts +2 -0
- package/dist/cjs/session/SessionManager.d.ts.map +1 -1
- package/dist/cjs/session/SessionManager.js +7 -0
- package/dist/cjs/session/SessionManager.js.map +2 -2
- package/dist/cjs/tlv/TlvArray.d.ts +2 -2
- package/dist/cjs/tlv/TlvArray.d.ts.map +1 -1
- package/dist/cjs/tlv/TlvArray.js +2 -2
- package/dist/cjs/tlv/TlvArray.js.map +2 -2
- package/dist/cjs/tlv/TlvNullable.d.ts +2 -2
- package/dist/cjs/tlv/TlvNullable.d.ts.map +1 -1
- package/dist/cjs/tlv/TlvNullable.js +2 -2
- package/dist/cjs/tlv/TlvNullable.js.map +2 -2
- package/dist/cjs/tlv/TlvObject.d.ts +2 -2
- package/dist/cjs/tlv/TlvObject.d.ts.map +1 -1
- package/dist/cjs/tlv/TlvObject.js +18 -12
- package/dist/cjs/tlv/TlvObject.js.map +2 -2
- package/dist/cjs/tlv/TlvSchema.d.ts +14 -2
- package/dist/cjs/tlv/TlvSchema.d.ts.map +1 -1
- package/dist/cjs/tlv/TlvSchema.js +2 -2
- package/dist/cjs/tlv/TlvSchema.js.map +2 -2
- package/dist/cjs/tlv/TlvWrapper.d.ts +2 -2
- package/dist/cjs/tlv/TlvWrapper.d.ts.map +1 -1
- package/dist/cjs/tlv/TlvWrapper.js +2 -2
- package/dist/cjs/tlv/TlvWrapper.js.map +2 -2
- package/dist/esm/CommissioningServer.d.ts.map +1 -1
- package/dist/esm/CommissioningServer.js +0 -1
- package/dist/esm/CommissioningServer.js.map +2 -2
- package/dist/esm/MatterDevice.d.ts +3 -0
- package/dist/esm/MatterDevice.d.ts.map +1 -1
- package/dist/esm/MatterDevice.js +21 -7
- package/dist/esm/MatterDevice.js.map +2 -2
- package/dist/esm/behavior/AccessControl.js +2 -2
- package/dist/esm/behavior/AccessControl.js.map +2 -2
- package/dist/esm/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.d.ts +1 -0
- package/dist/esm/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.d.ts.map +1 -1
- package/dist/esm/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.js +15 -1
- package/dist/esm/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.js.map +2 -2
- package/dist/esm/behavior/definitions/operational-credentials/OperationalCredentialsServer.d.ts.map +1 -1
- package/dist/esm/behavior/definitions/operational-credentials/OperationalCredentialsServer.js +11 -2
- package/dist/esm/behavior/definitions/operational-credentials/OperationalCredentialsServer.js.map +2 -2
- package/dist/esm/behavior/state/transaction/Transaction.d.ts +18 -18
- package/dist/esm/certificate/CertificateManager.d.ts.map +1 -1
- package/dist/esm/certificate/CertificateManager.js +1 -0
- package/dist/esm/certificate/CertificateManager.js.map +2 -2
- package/dist/esm/certificate/CertificationDeclarationManager.d.ts +1 -1
- package/dist/esm/certificate/CertificationDeclarationManager.d.ts.map +1 -1
- package/dist/esm/certificate/CertificationDeclarationManager.js +3 -2
- package/dist/esm/certificate/CertificationDeclarationManager.js.map +2 -2
- package/dist/esm/cluster/server/AccessControlServer.js.map +1 -1
- package/dist/esm/cluster/server/AttributeServer.d.ts +9 -0
- package/dist/esm/cluster/server/AttributeServer.d.ts.map +1 -1
- package/dist/esm/cluster/server/AttributeServer.js +69 -1
- package/dist/esm/cluster/server/AttributeServer.js.map +2 -2
- package/dist/esm/cluster/server/ClusterServer.d.ts.map +1 -1
- package/dist/esm/cluster/server/ClusterServer.js +9 -2
- package/dist/esm/cluster/server/ClusterServer.js.map +2 -2
- package/dist/esm/cluster/server/ClusterServerTypes.d.ts +3 -3
- package/dist/esm/cluster/server/ClusterServerTypes.d.ts.map +1 -1
- package/dist/esm/cluster/server/ClusterServerTypes.js.map +1 -1
- package/dist/esm/cluster/server/EventServer.d.ts +8 -2
- package/dist/esm/cluster/server/EventServer.d.ts.map +1 -1
- package/dist/esm/cluster/server/EventServer.js +33 -7
- package/dist/esm/cluster/server/EventServer.js.map +2 -2
- package/dist/esm/cluster/server/OperationalCredentialsServer.d.ts.map +1 -1
- package/dist/esm/cluster/server/OperationalCredentialsServer.js +31 -8
- package/dist/esm/cluster/server/OperationalCredentialsServer.js.map +2 -2
- package/dist/esm/common/FailsafeContext.d.ts +1 -0
- package/dist/esm/common/FailsafeContext.d.ts.map +1 -1
- package/dist/esm/common/FailsafeContext.js +17 -3
- package/dist/esm/common/FailsafeContext.js.map +2 -2
- package/dist/esm/crypto/Crypto.d.ts +1 -1
- package/dist/esm/crypto/Crypto.d.ts.map +1 -1
- package/dist/esm/crypto/Crypto.js +2 -2
- package/dist/esm/crypto/Crypto.js.map +2 -2
- package/dist/esm/device/LegacyInteractionServer.d.ts +2 -2
- package/dist/esm/device/LegacyInteractionServer.d.ts.map +1 -1
- package/dist/esm/device/LegacyInteractionServer.js +13 -1
- package/dist/esm/device/LegacyInteractionServer.js.map +2 -2
- package/dist/esm/fabric/Fabric.d.ts +1 -0
- package/dist/esm/fabric/Fabric.d.ts.map +1 -1
- package/dist/esm/fabric/Fabric.js +5 -0
- package/dist/esm/fabric/Fabric.js.map +2 -2
- package/dist/esm/fabric/FabricManager.d.ts +1 -0
- package/dist/esm/fabric/FabricManager.d.ts.map +1 -1
- package/dist/esm/fabric/FabricManager.js +2 -1
- package/dist/esm/fabric/FabricManager.js.map +2 -2
- package/dist/esm/model/models/EventModel.d.ts +1 -0
- package/dist/esm/model/models/EventModel.d.ts.map +1 -1
- package/dist/esm/model/models/EventModel.js +3 -0
- package/dist/esm/model/models/EventModel.js.map +2 -2
- package/dist/esm/model/models/FieldModel.d.ts +1 -0
- package/dist/esm/model/models/FieldModel.d.ts.map +1 -1
- package/dist/esm/model/models/FieldModel.js +3 -0
- package/dist/esm/model/models/FieldModel.js.map +2 -2
- package/dist/esm/node/server/TransactionalInteractionServer.d.ts +2 -2
- package/dist/esm/node/server/TransactionalInteractionServer.d.ts.map +1 -1
- package/dist/esm/node/server/TransactionalInteractionServer.js +0 -2
- package/dist/esm/node/server/TransactionalInteractionServer.js.map +2 -2
- package/dist/esm/protocol/interaction/AttributeDataEncoder.d.ts +6 -3
- package/dist/esm/protocol/interaction/AttributeDataEncoder.d.ts.map +1 -1
- package/dist/esm/protocol/interaction/AttributeDataEncoder.js +14 -8
- package/dist/esm/protocol/interaction/AttributeDataEncoder.js.map +2 -2
- package/dist/esm/protocol/interaction/EventHandler.d.ts.map +1 -1
- package/dist/esm/protocol/interaction/EventHandler.js +1 -3
- package/dist/esm/protocol/interaction/EventHandler.js.map +2 -2
- package/dist/esm/protocol/interaction/InteractionClient.js +1 -1
- package/dist/esm/protocol/interaction/InteractionClient.js.map +2 -2
- package/dist/esm/protocol/interaction/InteractionEndpointStructure.d.ts +3 -3
- package/dist/esm/protocol/interaction/InteractionEndpointStructure.d.ts.map +1 -1
- package/dist/esm/protocol/interaction/InteractionEndpointStructure.js +1 -0
- package/dist/esm/protocol/interaction/InteractionEndpointStructure.js.map +2 -2
- package/dist/esm/protocol/interaction/InteractionMessenger.d.ts +1 -1
- package/dist/esm/protocol/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/esm/protocol/interaction/InteractionMessenger.js +11 -4
- package/dist/esm/protocol/interaction/InteractionMessenger.js.map +2 -2
- package/dist/esm/protocol/interaction/InteractionServer.d.ts +5 -6
- package/dist/esm/protocol/interaction/InteractionServer.d.ts.map +1 -1
- package/dist/esm/protocol/interaction/InteractionServer.js +44 -37
- package/dist/esm/protocol/interaction/InteractionServer.js.map +2 -2
- package/dist/esm/protocol/interaction/SubscriptionHandler.d.ts +31 -12
- package/dist/esm/protocol/interaction/SubscriptionHandler.d.ts.map +1 -1
- package/dist/esm/protocol/interaction/SubscriptionHandler.js +161 -69
- package/dist/esm/protocol/interaction/SubscriptionHandler.js.map +3 -3
- package/dist/esm/session/SecureSession.d.ts.map +1 -1
- package/dist/esm/session/SecureSession.js +2 -1
- package/dist/esm/session/SecureSession.js.map +2 -2
- package/dist/esm/session/SessionManager.d.ts +2 -0
- package/dist/esm/session/SessionManager.d.ts.map +1 -1
- package/dist/esm/session/SessionManager.js +7 -0
- package/dist/esm/session/SessionManager.js.map +2 -2
- package/dist/esm/tlv/TlvArray.d.ts +2 -2
- package/dist/esm/tlv/TlvArray.d.ts.map +1 -1
- package/dist/esm/tlv/TlvArray.js +2 -2
- package/dist/esm/tlv/TlvArray.js.map +2 -2
- package/dist/esm/tlv/TlvNullable.d.ts +2 -2
- package/dist/esm/tlv/TlvNullable.d.ts.map +1 -1
- package/dist/esm/tlv/TlvNullable.js +2 -2
- package/dist/esm/tlv/TlvNullable.js.map +2 -2
- package/dist/esm/tlv/TlvObject.d.ts +2 -2
- package/dist/esm/tlv/TlvObject.d.ts.map +1 -1
- package/dist/esm/tlv/TlvObject.js +19 -13
- package/dist/esm/tlv/TlvObject.js.map +2 -2
- package/dist/esm/tlv/TlvSchema.d.ts +14 -2
- package/dist/esm/tlv/TlvSchema.d.ts.map +1 -1
- package/dist/esm/tlv/TlvSchema.js +2 -2
- package/dist/esm/tlv/TlvSchema.js.map +2 -2
- package/dist/esm/tlv/TlvWrapper.d.ts +2 -2
- package/dist/esm/tlv/TlvWrapper.d.ts.map +1 -1
- package/dist/esm/tlv/TlvWrapper.js +2 -2
- package/dist/esm/tlv/TlvWrapper.js.map +2 -2
- package/package.json +3 -3
- package/src/CommissioningServer.ts +0 -1
- package/src/MatterDevice.ts +34 -7
- package/src/behavior/AccessControl.ts +2 -2
- package/src/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.ts +21 -1
- package/src/behavior/definitions/operational-credentials/OperationalCredentialsServer.ts +13 -0
- package/src/certificate/CertificateManager.ts +1 -2
- package/src/certificate/CertificationDeclarationManager.ts +2 -2
- package/src/cluster/server/AccessControlServer.ts +3 -3
- package/src/cluster/server/AttributeServer.ts +79 -1
- package/src/cluster/server/ClusterServer.ts +9 -2
- package/src/cluster/server/ClusterServerTypes.ts +3 -3
- package/src/cluster/server/EventServer.ts +57 -10
- package/src/cluster/server/OperationalCredentialsServer.ts +35 -5
- package/src/common/FailsafeContext.ts +19 -7
- package/src/crypto/Crypto.ts +1 -1
- package/src/device/LegacyInteractionServer.ts +15 -4
- package/src/fabric/Fabric.ts +6 -0
- package/src/fabric/FabricManager.ts +1 -0
- package/src/model/models/EventModel.ts +4 -0
- package/src/model/models/FieldModel.ts +4 -0
- package/src/node/server/TransactionalInteractionServer.ts +2 -4
- package/src/protocol/interaction/AttributeDataEncoder.ts +20 -9
- package/src/protocol/interaction/EventHandler.ts +1 -3
- package/src/protocol/interaction/InteractionClient.ts +1 -1
- package/src/protocol/interaction/InteractionEndpointStructure.ts +4 -4
- package/src/protocol/interaction/InteractionMessenger.ts +12 -3
- package/src/protocol/interaction/InteractionServer.ts +53 -52
- package/src/protocol/interaction/SubscriptionHandler.ts +215 -92
- package/src/session/SecureSession.ts +2 -1
- package/src/session/SessionManager.ts +9 -0
- package/src/tlv/TlvArray.ts +3 -3
- package/src/tlv/TlvNullable.ts +3 -3
- package/src/tlv/TlvObject.ts +20 -14
- package/src/tlv/TlvSchema.ts +17 -3
- package/src/tlv/TlvWrapper.ts +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/MatterDevice.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Important note: This file is part of the legacy matter-node (internal) API and should not be used anymore directly!\n * Please use the new API classes!\n * @deprecated\n */\n\nimport {\n DEVICE_ANNOUNCEMENT_DURATION_MS,\n DEVICE_ANNOUNCEMENT_INTERVAL_MS,\n} from \"./behavior/definitions/administrator-commissioning/AdministratorCommissioningConstants.js\";\nimport { CommissioningOptions } from \"./behavior/system/commissioning/CommissioningOptions.js\";\nimport { AdministratorCommissioning } from \"./cluster/definitions/AdministratorCommissioningCluster.js\";\n\nimport { Channel } from \"./common/Channel.js\";\nimport { FailsafeContext } from \"./common/FailsafeContext.js\";\nimport { InstanceBroadcaster } from \"./common/InstanceBroadcaster.js\";\nimport { Lifecycle } from \"./common/Lifecycle.js\";\nimport { InternalError, MatterFlowError } from \"./common/MatterError.js\";\nimport { Scanner } from \"./common/Scanner.js\";\nimport { TransportInterface } from \"./common/TransportInterface.js\";\nimport { Crypto } from \"./crypto/Crypto.js\";\nimport { FabricIndex } from \"./datatype/FabricIndex.js\";\nimport { NodeId } from \"./datatype/NodeId.js\";\nimport { Fabric } from \"./fabric/Fabric.js\";\nimport { FabricAction, FabricManager } from \"./fabric/FabricManager.js\";\nimport { Diagnostic } from \"./log/Diagnostic.js\";\nimport { Logger } from \"./log/Logger.js\";\nimport { NetInterface, isNetworkInterface } from \"./net/NetInterface.js\";\nimport { NetworkError } from \"./net/Network.js\";\nimport { ChannelManager } from \"./protocol/ChannelManager.js\";\nimport { ExchangeManager } from \"./protocol/ExchangeManager.js\";\nimport { ProtocolHandler } from \"./protocol/ProtocolHandler.js\";\nimport { StatusCode, StatusResponseError } from \"./protocol/interaction/StatusCode.js\";\nimport { SecureChannelProtocol } from \"./protocol/securechannel/SecureChannelProtocol.js\";\nimport { Session } from \"./session/Session.js\";\nimport { ResumptionRecord, SessionManager } from \"./session/SessionManager.js\";\nimport { PaseServer } from \"./session/pase/PaseServer.js\";\nimport { StorageContext } from \"./storage/StorageContext.js\";\nimport { Time, Timer } from \"./time/Time.js\";\nimport { AsyncConstruction, asyncNew } from \"./util/AsyncConstruction.js\";\nimport { ByteArray } from \"./util/ByteArray.js\";\nimport { Mutex } from \"./util/Mutex.js\";\n\nconst logger = Logger.get(\"MatterDevice\");\n\nexport class MatterDevice {\n private readonly scanners = new Array<Scanner>();\n private readonly broadcasters = new Array<InstanceBroadcaster>();\n private readonly transportInterfaces = new Array<TransportInterface | NetInterface>();\n private readonly channelManager: ChannelManager;\n private readonly secureChannelProtocol = new SecureChannelProtocol(() => this.endCommissioning());\n private activeCommissioningMode = AdministratorCommissioning.CommissioningWindowStatus.WindowNotOpen;\n private activeCommissioningEndCallback?: () => void;\n private announceInterval: Timer;\n private announcementStartedTime: number | null = null;\n #isClosing = false;\n readonly #exchangeManager;\n readonly #fabricManager: FabricManager;\n readonly #sessionManager: SessionManager<MatterDevice>;\n #failsafeContext?: FailsafeContext;\n\n // Currently we do not put much effort into synchronizing announcements as it probably isn't really necessary. But\n // this mutex prevents automated announcements from piling up and allows us to ensure announcements are complete\n // on close\n #announcementMutex = new Mutex(this);\n #construction: AsyncConstruction<MatterDevice>;\n\n get construction() {\n return this.#construction;\n }\n\n static async create(\n sessionStorage: StorageContext,\n fabricStorage: StorageContext,\n getCommissioningConfig: () => CommissioningOptions.Configuration,\n minimumCaseSessionsPerFabricAndNode = 3,\n commissioningChangedCallback: (fabricIndex: FabricIndex, fabricAction: FabricAction) => void,\n sessionChangedCallback: (fabricIndex: FabricIndex) => void,\n ) {\n return asyncNew(\n MatterDevice,\n sessionStorage,\n fabricStorage,\n getCommissioningConfig,\n minimumCaseSessionsPerFabricAndNode,\n commissioningChangedCallback,\n sessionChangedCallback,\n );\n }\n\n constructor(\n readonly sessionStorage: StorageContext,\n readonly fabricStorage: StorageContext,\n private readonly getCommissioningConfig: () => CommissioningOptions.Configuration,\n minimumCaseSessionsPerFabricAndNode: number,\n private readonly commissioningChangedCallback: (fabricIndex: FabricIndex, fabricAction: FabricAction) => void,\n private readonly sessionChangedCallback: (fabricIndex: FabricIndex) => void,\n ) {\n this.channelManager = new ChannelManager(minimumCaseSessionsPerFabricAndNode);\n\n this.#fabricManager = new FabricManager(fabricStorage);\n\n this.#fabricManager.events.deleted.on(async fabric => {\n const { fabricIndex, rootNodeId } = fabric;\n // When fabric is removed, also remove the resumption record\n await this.#sessionManager.removeResumptionRecord(rootNodeId);\n this.commissioningChangedCallback(fabricIndex, FabricAction.Removed);\n if (this.#fabricManager.getFabrics().length === 0) {\n // Last fabric got removed, so expire all announcements\n await this.expireAllFabricAnnouncements();\n }\n });\n this.#fabricManager.events.updated.on(({ fabricIndex }) =>\n this.commissioningChangedCallback(fabricIndex, FabricAction.Updated),\n );\n\n this.#sessionManager = new SessionManager(this, sessionStorage);\n\n this.#exchangeManager = new ExchangeManager<MatterDevice>(this.#sessionManager, this.channelManager);\n\n this.addProtocolHandler(this.secureChannelProtocol);\n\n this.announceInterval = Time.getPeriodicTimer(\"Server node announcement\", DEVICE_ANNOUNCEMENT_INTERVAL_MS, () =>\n // Announcement needs to await a previous announcement because otherwise in testing at least announcement\n // may crash if started simultaneously\n this.#announcementMutex.run(() => this.announce()),\n );\n\n this.#sessionManager.sessionOpened.on(session => {\n if (session.fabric) {\n this.sessionChangedCallback(session.fabric.fabricIndex);\n }\n });\n\n this.#sessionManager.sessionClosed.on(async session => {\n if (!session.closingAfterExchangeFinished) {\n // Delayed closing is executed when exchange is closed\n await this.exchangeManager.closeSession(session);\n }\n const currentFabric = session.fabric;\n if (currentFabric !== undefined) {\n this.sessionChangedCallback(currentFabric.fabricIndex);\n }\n if (this.isClosing) {\n return;\n }\n // When a session closes, announce existing fabrics again so that controller can detect the device again.\n // When session was closed and no fabric exist anymore then this is triggering a factory reset in upper layer\n // and it would be not good to announce a commissionable device and then reset that again with the factory reset\n if (this.#fabricManager.getFabrics().length > 0 || !currentFabric) {\n await this.startAnnouncement();\n }\n });\n\n this.#sessionManager.subscriptionsChanged.on(session => {\n const currentFabric = session.fabric;\n if (currentFabric !== undefined) {\n this.sessionChangedCallback(currentFabric.fabricIndex);\n }\n });\n\n this.#construction = AsyncConstruction(this, async () => {\n await this.#fabricManager.initFromStorage();\n\n // Attach added events delayed because initialization from storage would else trigger it\n this.#fabricManager.events.added.on(({ fabricIndex }) =>\n this.commissioningChangedCallback(fabricIndex, FabricAction.Added),\n );\n\n await this.#sessionManager.initFromStorage(this.#fabricManager.getFabrics());\n });\n }\n\n get fabricManager() {\n return this.#fabricManager;\n }\n\n get sessionManager() {\n return this.#sessionManager;\n }\n\n get exchangeManager() {\n return this.#exchangeManager;\n }\n\n get failsafeContext() {\n this.assertFailSafeArmed();\n return this.#failsafeContext as FailsafeContext;\n }\n\n get isClosing() {\n return this.#isClosing;\n }\n\n async beginTimed(failsafeContext: FailsafeContext) {\n await failsafeContext.construction;\n\n this.#failsafeContext = failsafeContext;\n\n this.#fabricManager.events.added.on(fabric => {\n const fabrics = this.#fabricManager.getFabrics();\n this.sendFabricAnnouncements(fabrics, true).catch(error =>\n logger.warn(`Error sending Fabric announcement for Index ${fabric.fabricIndex}`, error),\n );\n logger.info(\"Announce done\", Diagnostic.dict({ fabric: fabric.fabricId, fabricIndex: fabric.fabricIndex }));\n });\n\n failsafeContext.commissioned.on(async () => await this.endCommissioning());\n\n failsafeContext.construction.change.on(status => {\n if (status === Lifecycle.Status.Destroyed) {\n this.#failsafeContext = undefined;\n }\n });\n }\n\n assertFailSafeArmed(message?: string) {\n if (this.isFailsafeArmed()) return;\n throw new StatusResponseError(\n message ?? \"Failsafe timer needs to be armed to execute this action.\",\n StatusCode.FailsafeRequired,\n );\n }\n\n isFailsafeArmed() {\n return this.#failsafeContext !== undefined;\n }\n\n addScanner(scanner: Scanner) {\n this.scanners.push(scanner);\n return this;\n }\n\n hasBroadcaster(broadcaster: InstanceBroadcaster) {\n return this.broadcasters.includes(broadcaster);\n }\n\n addBroadcaster(broadcaster: InstanceBroadcaster) {\n this.broadcasters.push(broadcaster);\n return this;\n }\n\n async deleteBroadcaster(broadcaster: InstanceBroadcaster) {\n const pos = this.broadcasters.findIndex(b => b === broadcaster);\n if (pos !== -1) {\n this.broadcasters.splice(pos, 1);\n await broadcaster.expireAllAnnouncements();\n }\n }\n\n addTransportInterface(transport: TransportInterface) {\n this.exchangeManager.addTransportInterface(transport);\n this.transportInterfaces.push(transport);\n return this;\n }\n\n async deleteTransportInterface(transport: TransportInterface) {\n const pos = this.transportInterfaces.findIndex(t => t === transport);\n if (pos !== -1) {\n this.transportInterfaces.splice(pos, 1);\n await transport.close();\n }\n }\n\n hasProtocolHandler(protocolId: number) {\n return this.exchangeManager.hasProtocolHandler(protocolId);\n }\n\n addProtocolHandler(protocol: ProtocolHandler<MatterDevice>) {\n this.exchangeManager.addProtocolHandler(protocol);\n return this;\n }\n\n async start() {\n await this.startAnnouncement();\n }\n\n async startAnnouncement() {\n if (this.isClosing) return;\n if (this.announceInterval.isRunning) {\n this.announceInterval.stop();\n }\n this.announcementStartedTime = Time.nowMs();\n this.announceInterval.start();\n await this.announce();\n }\n\n async expireAllFabricAnnouncements() {\n for (const broadcaster of this.broadcasters) {\n await broadcaster.expireAllAnnouncements();\n }\n }\n\n async announce(announceOnce = false) {\n if (!announceOnce) {\n // Stop announcement if duration is reached\n if (\n this.announcementStartedTime !== null &&\n Time.nowMs() - this.announcementStartedTime > DEVICE_ANNOUNCEMENT_DURATION_MS\n ) {\n await this.endCommissioning();\n logger.debug(\"Announcement duration reached, stop announcing\");\n return;\n }\n if (this.activeCommissioningMode !== AdministratorCommissioning.CommissioningWindowStatus.WindowNotOpen) {\n // Re-Announce but do not re-set Fabrics\n for (const broadcaster of this.broadcasters) {\n await broadcaster.announce();\n }\n return;\n }\n }\n const fabrics = this.#fabricManager.getFabrics();\n if (fabrics.length) {\n let fabricsWithoutSessions = 0;\n for (const fabric of fabrics) {\n const session = this.#sessionManager.getSessionForNode(fabric, fabric.rootNodeId);\n if (session === undefined || !session.isSecure || session.numberOfActiveSubscriptions === 0) {\n fabricsWithoutSessions++;\n logger.debug(\"Announcing\", Diagnostic.dict({ fabric: fabric.fabricId }));\n }\n }\n for (const broadcaster of this.broadcasters) {\n await broadcaster.setFabrics(fabrics);\n if (fabricsWithoutSessions > 0) {\n await broadcaster.announce();\n }\n }\n } else {\n // No fabric paired yet, so announce as \"ready for commissioning\"\n // And expire operational Fabric announcements (if fabric got just deleted)\n await this.expireAllFabricAnnouncements();\n await this.allowBasicCommissioning();\n }\n }\n\n private async announceAsCommissionable(\n mode: AdministratorCommissioning.CommissioningWindowStatus,\n activeCommissioningEndCallback?: () => void,\n discriminator?: number,\n ) {\n if (this.activeCommissioningMode !== AdministratorCommissioning.CommissioningWindowStatus.WindowNotOpen) {\n throw new InternalError(\n `Commissioning window already open with different mode (${this.activeCommissioningMode})!`,\n );\n }\n if (this.activeCommissioningEndCallback !== undefined) {\n throw new InternalError(\"Commissioning window already open with different callback!\");\n }\n this.activeCommissioningMode = mode;\n if (activeCommissioningEndCallback !== undefined) {\n this.activeCommissioningEndCallback = activeCommissioningEndCallback;\n }\n // MDNS is sent in parallel\n // TODO - untracked promise\n this.sendCommissionableAnnouncement(mode, discriminator).catch(error =>\n logger.warn(\"Error sending announcement\", error),\n );\n }\n\n async sendCommissionableAnnouncement(\n mode: AdministratorCommissioning.CommissioningWindowStatus,\n discriminator?: number,\n ) {\n const commissioningConfig = this.getCommissioningConfig();\n for (const broadcaster of this.broadcasters) {\n await broadcaster.setCommissionMode(\n mode === AdministratorCommissioning.CommissioningWindowStatus.EnhancedWindowOpen ? 2 : 1,\n {\n ...commissioningConfig.productDescription,\n discriminator: discriminator ?? commissioningConfig.discriminator,\n },\n );\n }\n await this.startAnnouncement();\n }\n\n async getNextAvailableSessionId() {\n return this.#sessionManager.getNextAvailableSessionId();\n }\n\n findFabricFromDestinationId(destinationId: ByteArray, peerRandom: ByteArray) {\n return this.#fabricManager.findFabricFromDestinationId(destinationId, peerRandom);\n }\n\n async sendFabricAnnouncements(fabrics: Fabric[], expireCommissioningAnnouncement = false) {\n for (const broadcaster of this.broadcasters) {\n await broadcaster.setFabrics(fabrics, expireCommissioningAnnouncement);\n await broadcaster.announce();\n }\n }\n\n getFabricByIndex(fabricIndex: FabricIndex) {\n return this.#fabricManager.getFabrics().find(fabric => fabric.fabricIndex === fabricIndex);\n }\n\n initiateExchange(fabric: Fabric, nodeId: NodeId, protocolId: number) {\n return this.exchangeManager.initiateExchange(fabric, nodeId, protocolId);\n }\n\n findResumptionRecordById(resumptionId: ByteArray) {\n return this.#sessionManager.findResumptionRecordById(resumptionId);\n }\n\n async saveResumptionRecord(resumptionRecord: ResumptionRecord) {\n return this.#sessionManager.saveResumptionRecord(resumptionRecord);\n }\n\n getFabrics() {\n return this.#fabricManager.getFabrics();\n }\n\n isCommissioned() {\n return !!this.#fabricManager.getFabrics().length;\n }\n\n async allowEnhancedCommissioning(\n discriminator: number,\n paseServer: PaseServer,\n commissioningEndCallback: () => void,\n ) {\n if (this.activeCommissioningMode === AdministratorCommissioning.CommissioningWindowStatus.BasicWindowOpen) {\n throw new MatterFlowError(\n \"Basic commissioning window is already open! Can not set Enhanced commissioning mode.\",\n );\n }\n\n this.secureChannelProtocol.setPaseCommissioner(paseServer);\n await this.announceAsCommissionable(\n AdministratorCommissioning.CommissioningWindowStatus.EnhancedWindowOpen,\n commissioningEndCallback,\n discriminator,\n );\n }\n\n async allowBasicCommissioning(commissioningEndCallback?: () => void) {\n if (this.activeCommissioningMode === AdministratorCommissioning.CommissioningWindowStatus.EnhancedWindowOpen) {\n throw new MatterFlowError(\n \"Enhanced commissioning window is already open! Can not set Basic commissioning mode.\",\n );\n }\n\n this.secureChannelProtocol.setPaseCommissioner(\n await PaseServer.fromPin(this.getCommissioningConfig().passcode, {\n iterations: 1000,\n salt: Crypto.get().getRandomData(32),\n }),\n );\n\n await this.announceAsCommissionable(\n AdministratorCommissioning.CommissioningWindowStatus.BasicWindowOpen,\n commissioningEndCallback,\n );\n }\n\n async endCommissioning() {\n logger.debug(\"Commissioning mode ended, stop announcements.\");\n // Remove PASE responder when we close enhanced commissioning window or node is commissioned\n if (\n this.activeCommissioningMode === AdministratorCommissioning.CommissioningWindowStatus.EnhancedWindowOpen ||\n this.isCommissioned()\n ) {\n this.secureChannelProtocol.removePaseCommissioner();\n }\n this.activeCommissioningMode = AdministratorCommissioning.CommissioningWindowStatus.WindowNotOpen;\n this.announceInterval.stop();\n this.announcementStartedTime = null;\n if (this.activeCommissioningEndCallback !== undefined) {\n const activeCommissioningEndCallback = this.activeCommissioningEndCallback;\n this.activeCommissioningEndCallback = undefined;\n activeCommissioningEndCallback();\n }\n for (const broadcaster of this.broadcasters) {\n await broadcaster.expireCommissioningAnnouncement();\n }\n logger.info(\"All announcements expired\");\n }\n\n existsOpenPaseSession() {\n return !!this.#sessionManager.getPaseSession();\n }\n\n async findDevice(\n fabric: Fabric,\n nodeId: NodeId,\n timeOutSeconds = 5,\n ): Promise<undefined | { session: Session<MatterDevice>; channel: Channel<ByteArray> }> {\n // TODO: return the first not undefined answer or undefined\n const device = await this.scanners[0].findOperationalDevice(fabric, nodeId, timeOutSeconds);\n if (device === undefined) return undefined;\n const session = this.#sessionManager.getSessionForNode(fabric, nodeId);\n if (session === undefined) return undefined;\n // TODO: have the interface and scanner linked\n const networkInterface = this.transportInterfaces.find(netInterface => isNetworkInterface(netInterface));\n if (networkInterface === undefined || !isNetworkInterface(networkInterface)) {\n throw new NetworkError(\"No network interface found\");\n } // TODO meeehhh\n return { session, channel: await networkInterface.openChannel(device.addresses[0]) };\n }\n\n async close() {\n this.#isClosing = true;\n await this.endCommissioning();\n await this.#announcementMutex;\n for (const broadcaster of this.broadcasters) {\n await broadcaster.close();\n }\n if (this.#failsafeContext) {\n await this.#failsafeContext.close();\n this.#failsafeContext = undefined;\n }\n await this.exchangeManager.close();\n await this.#sessionManager.close();\n await this.channelManager.close();\n for (const transportInterface of this.transportInterfaces) {\n await transportInterface.close();\n }\n }\n\n getActiveSessionInformation() {\n return this.#sessionManager.getActiveSessionInformation();\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA,iDAGO;AAEP,+CAA2C;AAK3C,uBAA0B;AAC1B,yBAA+C;AAG/C,oBAAuB;AAIvB,2BAA4C;AAC5C,wBAA2B;AAC3B,oBAAuB;AACvB,0BAAiD;AACjD,qBAA6B;AAC7B,4BAA+B;AAC/B,6BAAgC;AAEhC,wBAAgD;AAChD,mCAAsC;AAEtC,4BAAiD;AACjD,wBAA2B;AAE3B,kBAA4B;AAC5B,+BAA4C;AAE5C,mBAAsB;AA/CtB;AAAA;AAAA;AAAA;AAAA;AAiDA,MAAM,SAAS,qBAAO,IAAI,cAAc;AAEjC,MAAM,aAAa;AAAA,
|
|
4
|
+
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Important note: This file is part of the legacy matter-node (internal) API and should not be used anymore directly!\n * Please use the new API classes!\n * @deprecated\n */\n\nimport {\n DEVICE_ANNOUNCEMENT_DURATION_MS,\n DEVICE_ANNOUNCEMENT_INTERVAL_MS,\n} from \"./behavior/definitions/administrator-commissioning/AdministratorCommissioningConstants.js\";\nimport { CommissioningOptions } from \"./behavior/system/commissioning/CommissioningOptions.js\";\nimport { AdministratorCommissioning } from \"./cluster/definitions/AdministratorCommissioningCluster.js\";\n\nimport { Channel } from \"./common/Channel.js\";\nimport { FailsafeContext } from \"./common/FailsafeContext.js\";\nimport { InstanceBroadcaster } from \"./common/InstanceBroadcaster.js\";\nimport { Lifecycle } from \"./common/Lifecycle.js\";\nimport { InternalError, MatterFlowError } from \"./common/MatterError.js\";\nimport { Scanner } from \"./common/Scanner.js\";\nimport { TransportInterface } from \"./common/TransportInterface.js\";\nimport { Crypto } from \"./crypto/Crypto.js\";\nimport { FabricIndex } from \"./datatype/FabricIndex.js\";\nimport { NodeId } from \"./datatype/NodeId.js\";\nimport { Fabric } from \"./fabric/Fabric.js\";\nimport { FabricAction, FabricManager } from \"./fabric/FabricManager.js\";\nimport { Diagnostic } from \"./log/Diagnostic.js\";\nimport { Logger } from \"./log/Logger.js\";\nimport { NetInterface, isNetworkInterface } from \"./net/NetInterface.js\";\nimport { NetworkError } from \"./net/Network.js\";\nimport { ChannelManager } from \"./protocol/ChannelManager.js\";\nimport { ExchangeManager } from \"./protocol/ExchangeManager.js\";\nimport { ProtocolHandler } from \"./protocol/ProtocolHandler.js\";\nimport { StatusCode, StatusResponseError } from \"./protocol/interaction/StatusCode.js\";\nimport { SecureChannelProtocol } from \"./protocol/securechannel/SecureChannelProtocol.js\";\nimport { Session } from \"./session/Session.js\";\nimport { ResumptionRecord, SessionManager } from \"./session/SessionManager.js\";\nimport { PaseServer } from \"./session/pase/PaseServer.js\";\nimport { StorageContext } from \"./storage/StorageContext.js\";\nimport { Time, Timer } from \"./time/Time.js\";\nimport { AsyncConstruction, asyncNew } from \"./util/AsyncConstruction.js\";\nimport { ByteArray } from \"./util/ByteArray.js\";\nimport { Mutex } from \"./util/Mutex.js\";\n\nconst logger = Logger.get(\"MatterDevice\");\n\nexport class MatterDevice {\n private readonly scanners = new Array<Scanner>();\n private readonly broadcasters = new Array<InstanceBroadcaster>();\n private readonly transportInterfaces = new Array<TransportInterface | NetInterface>();\n private readonly channelManager: ChannelManager;\n private readonly secureChannelProtocol = new SecureChannelProtocol(() => this.endCommissioning());\n private activeCommissioningMode = AdministratorCommissioning.CommissioningWindowStatus.WindowNotOpen;\n private activeCommissioningDiscriminator?: number;\n private activeCommissioningEndCallback?: () => void;\n private announceInterval: Timer;\n private announcementStartedTime: number | null = null;\n #isClosing = false;\n readonly #exchangeManager;\n readonly #fabricManager: FabricManager;\n readonly #sessionManager: SessionManager<MatterDevice>;\n #failsafeContext?: FailsafeContext;\n\n // Currently we do not put much effort into synchronizing announcements as it probably isn't really necessary. But\n // this mutex prevents automated announcements from piling up and allows us to ensure announcements are complete\n // on close\n #announcementMutex = new Mutex(this);\n #construction: AsyncConstruction<MatterDevice>;\n\n get construction() {\n return this.#construction;\n }\n\n static async create(\n sessionStorage: StorageContext,\n fabricStorage: StorageContext,\n getCommissioningConfig: () => CommissioningOptions.Configuration,\n minimumCaseSessionsPerFabricAndNode = 3,\n commissioningChangedCallback: (fabricIndex: FabricIndex, fabricAction: FabricAction) => void,\n sessionChangedCallback: (fabricIndex: FabricIndex) => void,\n ) {\n return asyncNew(\n MatterDevice,\n sessionStorage,\n fabricStorage,\n getCommissioningConfig,\n minimumCaseSessionsPerFabricAndNode,\n commissioningChangedCallback,\n sessionChangedCallback,\n );\n }\n\n constructor(\n readonly sessionStorage: StorageContext,\n readonly fabricStorage: StorageContext,\n private readonly getCommissioningConfig: () => CommissioningOptions.Configuration,\n minimumCaseSessionsPerFabricAndNode: number,\n private readonly commissioningChangedCallback: (fabricIndex: FabricIndex, fabricAction: FabricAction) => void,\n private readonly sessionChangedCallback: (fabricIndex: FabricIndex) => void,\n ) {\n this.channelManager = new ChannelManager(minimumCaseSessionsPerFabricAndNode);\n\n this.#fabricManager = new FabricManager(fabricStorage);\n\n this.#fabricManager.events.deleted.on(async fabric => {\n const { fabricIndex, rootNodeId } = fabric;\n // When fabric is removed, also remove the resumption record\n await this.#sessionManager.removeResumptionRecord(rootNodeId);\n this.commissioningChangedCallback(fabricIndex, FabricAction.Removed);\n if (this.#fabricManager.getFabrics().length === 0) {\n // Last fabric got removed, so expire all announcements\n await this.expireAllFabricAnnouncements();\n }\n // If a commissioning window is open then we reannounce this because it was ended as fabric got added\n this.reAnnounceAsCommissionable();\n });\n this.#fabricManager.events.updated.on(({ fabricIndex }) =>\n this.commissioningChangedCallback(fabricIndex, FabricAction.Updated),\n );\n\n this.#sessionManager = new SessionManager(this, sessionStorage);\n\n this.#exchangeManager = new ExchangeManager<MatterDevice>(this.#sessionManager, this.channelManager);\n\n this.addProtocolHandler(this.secureChannelProtocol);\n\n this.announceInterval = Time.getPeriodicTimer(\"Server node announcement\", DEVICE_ANNOUNCEMENT_INTERVAL_MS, () =>\n // Announcement needs to await a previous announcement because otherwise in testing at least announcement\n // may crash if started simultaneously\n this.#announcementMutex.run(() => this.announce()),\n );\n\n this.#sessionManager.sessionOpened.on(session => {\n if (session.fabric) {\n this.sessionChangedCallback(session.fabric.fabricIndex);\n }\n });\n\n this.#sessionManager.sessionClosed.on(async session => {\n if (!session.closingAfterExchangeFinished) {\n // Delayed closing is executed when exchange is closed\n await this.exchangeManager.closeSession(session);\n }\n\n const currentFabricIndex = session.fabric?.fabricIndex;\n if (currentFabricIndex !== undefined) {\n this.sessionChangedCallback(currentFabricIndex);\n }\n\n if (this.isClosing) {\n return;\n }\n\n // Verify if the session associated fabric still exists\n const existingSessionFabric =\n currentFabricIndex === undefined ? undefined : this.getFabricByIndex(currentFabricIndex)?.fabricIndex;\n\n // When a session closes, announce existing fabrics again so that controller can detect the device again.\n // When session was closed and no fabric exist anymore then this is triggering a factory reset in upper layer\n // and it would be not good to announce a commissionable device and then reset that again with the factory reset\n if (this.#fabricManager.getFabrics().length > 0 || session.isPase || !existingSessionFabric) {\n this.startAnnouncement().catch(error => logger.warn(`Error while announcing`, error));\n }\n });\n\n this.#sessionManager.subscriptionsChanged.on(session => {\n const currentFabric = session.fabric;\n if (currentFabric !== undefined) {\n this.sessionChangedCallback(currentFabric.fabricIndex);\n }\n });\n\n this.#construction = AsyncConstruction(this, async () => {\n await this.#fabricManager.initFromStorage();\n\n // Attach added events delayed because initialization from storage would else trigger it\n this.#fabricManager.events.added.on(({ fabricIndex }) =>\n this.commissioningChangedCallback(fabricIndex, FabricAction.Added),\n );\n\n await this.#sessionManager.initFromStorage(this.#fabricManager.getFabrics());\n });\n }\n\n get fabricManager() {\n return this.#fabricManager;\n }\n\n get sessionManager() {\n return this.#sessionManager;\n }\n\n get exchangeManager() {\n return this.#exchangeManager;\n }\n\n get failsafeContext() {\n this.assertFailSafeArmed();\n return this.#failsafeContext as FailsafeContext;\n }\n\n get isClosing() {\n return this.#isClosing;\n }\n\n async beginTimed(failsafeContext: FailsafeContext) {\n await failsafeContext.construction;\n\n this.#failsafeContext = failsafeContext;\n\n this.#fabricManager.events.added.on(fabric => {\n const fabrics = this.#fabricManager.getFabrics();\n this.sendFabricAnnouncements(fabrics, true).catch(error =>\n logger.warn(`Error sending Fabric announcement for Index ${fabric.fabricIndex}`, error),\n );\n logger.info(\"Announce done\", Diagnostic.dict({ fabric: fabric.fabricId, fabricIndex: fabric.fabricIndex }));\n });\n\n failsafeContext.commissioned.on(async () => await this.endCommissioning());\n\n failsafeContext.construction.change.on(status => {\n if (status === Lifecycle.Status.Destroyed) {\n this.#failsafeContext = undefined;\n }\n });\n }\n\n assertFailSafeArmed(message?: string) {\n if (this.isFailsafeArmed()) return;\n throw new StatusResponseError(\n message ?? \"Failsafe timer needs to be armed to execute this action.\",\n StatusCode.FailsafeRequired,\n );\n }\n\n isFailsafeArmed() {\n return this.#failsafeContext !== undefined;\n }\n\n addScanner(scanner: Scanner) {\n this.scanners.push(scanner);\n return this;\n }\n\n hasBroadcaster(broadcaster: InstanceBroadcaster) {\n return this.broadcasters.includes(broadcaster);\n }\n\n addBroadcaster(broadcaster: InstanceBroadcaster) {\n this.broadcasters.push(broadcaster);\n return this;\n }\n\n async deleteBroadcaster(broadcaster: InstanceBroadcaster) {\n const pos = this.broadcasters.findIndex(b => b === broadcaster);\n if (pos !== -1) {\n this.broadcasters.splice(pos, 1);\n await broadcaster.expireAllAnnouncements();\n }\n }\n\n addTransportInterface(transport: TransportInterface) {\n this.exchangeManager.addTransportInterface(transport);\n this.transportInterfaces.push(transport);\n return this;\n }\n\n async deleteTransportInterface(transport: TransportInterface) {\n const pos = this.transportInterfaces.findIndex(t => t === transport);\n if (pos !== -1) {\n this.transportInterfaces.splice(pos, 1);\n await transport.close();\n }\n }\n\n hasProtocolHandler(protocolId: number) {\n return this.exchangeManager.hasProtocolHandler(protocolId);\n }\n\n addProtocolHandler(protocol: ProtocolHandler<MatterDevice>) {\n this.exchangeManager.addProtocolHandler(protocol);\n return this;\n }\n\n async start() {\n await this.startAnnouncement();\n }\n\n async startAnnouncement() {\n if (this.isClosing) return;\n if (this.announceInterval.isRunning) {\n this.announceInterval.stop();\n }\n this.announcementStartedTime = Time.nowMs();\n this.announceInterval.start();\n await this.announce();\n }\n\n async expireAllFabricAnnouncements() {\n for (const broadcaster of this.broadcasters) {\n await broadcaster.expireFabricAnnouncement();\n }\n }\n\n async announce(announceOnce = false) {\n if (!announceOnce) {\n // Stop announcement if duration is reached\n if (\n this.announcementStartedTime !== null &&\n Time.nowMs() - this.announcementStartedTime > DEVICE_ANNOUNCEMENT_DURATION_MS\n ) {\n await this.endCommissioning();\n logger.debug(\"Announcement duration reached, stop announcing\");\n return;\n }\n if (this.activeCommissioningMode !== AdministratorCommissioning.CommissioningWindowStatus.WindowNotOpen) {\n // Re-Announce but do not re-set Fabrics\n for (const broadcaster of this.broadcasters) {\n await broadcaster.announce();\n }\n return;\n }\n }\n const fabrics = this.#fabricManager.getFabrics();\n if (fabrics.length) {\n let fabricsWithoutSessions = 0;\n for (const fabric of fabrics) {\n const session = this.#sessionManager.getSessionForNode(fabric, fabric.rootNodeId);\n if (session === undefined || !session.isSecure || session.numberOfActiveSubscriptions === 0) {\n fabricsWithoutSessions++;\n logger.debug(\"Announcing\", Diagnostic.dict({ fabric: fabric.fabricId }));\n }\n }\n for (const broadcaster of this.broadcasters) {\n await broadcaster.setFabrics(fabrics);\n if (\n fabricsWithoutSessions > 0 ||\n this.activeCommissioningMode !== AdministratorCommissioning.CommissioningWindowStatus.WindowNotOpen\n ) {\n await broadcaster.announce();\n }\n }\n } else {\n // No fabric paired yet, so announce as \"ready for commissioning\"\n // And expire operational Fabric announcements (if fabric got just deleted)\n await this.expireAllFabricAnnouncements();\n await this.allowBasicCommissioning();\n }\n }\n\n private async announceAsCommissionable(\n mode: AdministratorCommissioning.CommissioningWindowStatus,\n activeCommissioningEndCallback?: () => void,\n discriminator?: number,\n ) {\n if (this.activeCommissioningMode !== AdministratorCommissioning.CommissioningWindowStatus.WindowNotOpen) {\n throw new InternalError(\n `Commissioning window already open with different mode (${this.activeCommissioningMode})!`,\n );\n }\n if (this.activeCommissioningEndCallback !== undefined) {\n throw new InternalError(\"Commissioning window already open with different callback!\");\n }\n this.activeCommissioningMode = mode;\n this.activeCommissioningDiscriminator = discriminator;\n if (activeCommissioningEndCallback !== undefined) {\n this.activeCommissioningEndCallback = activeCommissioningEndCallback;\n }\n // MDNS is sent in parallel\n // TODO - untracked promise\n this.sendCommissionableAnnouncement(mode, discriminator).catch(error =>\n logger.warn(\"Error sending announcement\", error),\n );\n }\n\n reAnnounceAsCommissionable() {\n if (this.activeCommissioningMode === AdministratorCommissioning.CommissioningWindowStatus.WindowNotOpen) {\n return;\n }\n this.sendCommissionableAnnouncement(this.activeCommissioningMode, this.activeCommissioningDiscriminator).catch(\n error => logger.warn(\"Error sending announcement\", error),\n );\n }\n\n async sendCommissionableAnnouncement(\n mode: AdministratorCommissioning.CommissioningWindowStatus,\n discriminator?: number,\n ) {\n const commissioningConfig = this.getCommissioningConfig();\n for (const broadcaster of this.broadcasters) {\n await broadcaster.setCommissionMode(\n mode === AdministratorCommissioning.CommissioningWindowStatus.EnhancedWindowOpen ? 2 : 1,\n {\n ...commissioningConfig.productDescription,\n discriminator: discriminator ?? commissioningConfig.discriminator,\n },\n );\n }\n await this.startAnnouncement();\n }\n\n async getNextAvailableSessionId() {\n return this.#sessionManager.getNextAvailableSessionId();\n }\n\n findFabricFromDestinationId(destinationId: ByteArray, peerRandom: ByteArray) {\n return this.#fabricManager.findFabricFromDestinationId(destinationId, peerRandom);\n }\n\n async sendFabricAnnouncements(fabrics: Fabric[], expireCommissioningAnnouncement = false) {\n for (const broadcaster of this.broadcasters) {\n await broadcaster.setFabrics(fabrics, expireCommissioningAnnouncement);\n await broadcaster.announce();\n }\n }\n\n getFabricByIndex(fabricIndex: FabricIndex) {\n return this.#fabricManager.getFabrics().find(fabric => fabric.fabricIndex === fabricIndex);\n }\n\n initiateExchange(fabric: Fabric, nodeId: NodeId, protocolId: number) {\n return this.exchangeManager.initiateExchange(fabric, nodeId, protocolId);\n }\n\n findResumptionRecordById(resumptionId: ByteArray) {\n return this.#sessionManager.findResumptionRecordById(resumptionId);\n }\n\n async saveResumptionRecord(resumptionRecord: ResumptionRecord) {\n return this.#sessionManager.saveResumptionRecord(resumptionRecord);\n }\n\n getFabrics() {\n return this.#fabricManager.getFabrics();\n }\n\n isCommissioned() {\n return !!this.#fabricManager.getFabrics().length;\n }\n\n async allowEnhancedCommissioning(\n discriminator: number,\n paseServer: PaseServer,\n commissioningEndCallback: () => void,\n ) {\n if (this.activeCommissioningMode === AdministratorCommissioning.CommissioningWindowStatus.BasicWindowOpen) {\n throw new MatterFlowError(\n \"Basic commissioning window is already open! Can not set Enhanced commissioning mode.\",\n );\n }\n\n this.secureChannelProtocol.setPaseCommissioner(paseServer);\n await this.announceAsCommissionable(\n AdministratorCommissioning.CommissioningWindowStatus.EnhancedWindowOpen,\n commissioningEndCallback,\n discriminator,\n );\n }\n\n async allowBasicCommissioning(commissioningEndCallback?: () => void) {\n if (this.activeCommissioningMode === AdministratorCommissioning.CommissioningWindowStatus.EnhancedWindowOpen) {\n throw new MatterFlowError(\n \"Enhanced commissioning window is already open! Can not set Basic commissioning mode.\",\n );\n }\n\n this.secureChannelProtocol.setPaseCommissioner(\n await PaseServer.fromPin(this.getCommissioningConfig().passcode, {\n iterations: 1000,\n salt: Crypto.get().getRandomData(32),\n }),\n );\n\n await this.announceAsCommissionable(\n AdministratorCommissioning.CommissioningWindowStatus.BasicWindowOpen,\n commissioningEndCallback,\n );\n }\n\n async endCommissioning() {\n logger.debug(\"Commissioning mode ended, stop announcements.\");\n // Remove PASE responder when we close enhanced commissioning window or node is commissioned\n if (\n this.activeCommissioningMode === AdministratorCommissioning.CommissioningWindowStatus.EnhancedWindowOpen ||\n this.isCommissioned()\n ) {\n this.secureChannelProtocol.removePaseCommissioner();\n }\n this.activeCommissioningMode = AdministratorCommissioning.CommissioningWindowStatus.WindowNotOpen;\n this.announceInterval.stop();\n this.announcementStartedTime = null;\n if (this.activeCommissioningEndCallback !== undefined) {\n const activeCommissioningEndCallback = this.activeCommissioningEndCallback;\n this.activeCommissioningEndCallback = undefined;\n activeCommissioningEndCallback();\n }\n for (const broadcaster of this.broadcasters) {\n await broadcaster.expireCommissioningAnnouncement();\n }\n logger.info(\"All announcements expired\");\n }\n\n existsOpenPaseSession() {\n return !!this.#sessionManager.getPaseSession();\n }\n\n async findDevice(\n fabric: Fabric,\n nodeId: NodeId,\n timeOutSeconds = 5,\n ): Promise<undefined | { session: Session<MatterDevice>; channel: Channel<ByteArray> }> {\n // TODO: return the first not undefined answer or undefined\n const device = await this.scanners[0].findOperationalDevice(fabric, nodeId, timeOutSeconds);\n if (device === undefined) return undefined;\n const session = this.#sessionManager.getSessionForNode(fabric, nodeId);\n if (session === undefined) return undefined;\n // TODO: have the interface and scanner linked\n const networkInterface = this.transportInterfaces.find(netInterface => isNetworkInterface(netInterface));\n if (networkInterface === undefined || !isNetworkInterface(networkInterface)) {\n throw new NetworkError(\"No network interface found\");\n } // TODO meeehhh\n return { session, channel: await networkInterface.openChannel(device.addresses[0]) };\n }\n\n async clearSubscriptionsForNode(fabricIndex: FabricIndex, peerNodeId: NodeId, flushSubscriptions?: boolean) {\n await this.#sessionManager.clearSubscriptionsForNode(fabricIndex, peerNodeId, flushSubscriptions);\n }\n\n async close() {\n this.#isClosing = true;\n await this.endCommissioning();\n await this.#announcementMutex;\n for (const broadcaster of this.broadcasters) {\n await broadcaster.close();\n }\n if (this.#failsafeContext) {\n await this.#failsafeContext.close();\n this.#failsafeContext = undefined;\n }\n await this.exchangeManager.close();\n await this.#sessionManager.close();\n await this.channelManager.close();\n for (const transportInterface of this.transportInterfaces) {\n await transportInterface.close();\n }\n }\n\n getActiveSessionInformation() {\n return this.#sessionManager.getActiveSessionInformation();\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA,iDAGO;AAEP,+CAA2C;AAK3C,uBAA0B;AAC1B,yBAA+C;AAG/C,oBAAuB;AAIvB,2BAA4C;AAC5C,wBAA2B;AAC3B,oBAAuB;AACvB,0BAAiD;AACjD,qBAA6B;AAC7B,4BAA+B;AAC/B,6BAAgC;AAEhC,wBAAgD;AAChD,mCAAsC;AAEtC,4BAAiD;AACjD,wBAA2B;AAE3B,kBAA4B;AAC5B,+BAA4C;AAE5C,mBAAsB;AA/CtB;AAAA;AAAA;AAAA;AAAA;AAiDA,MAAM,SAAS,qBAAO,IAAI,cAAc;AAEjC,MAAM,aAAa;AAAA,EA8CtB,YACa,gBACA,eACQ,wBACjB,qCACiB,8BACA,wBACnB;AANW;AACA;AACQ;AAEA;AACA;AAnDrB,SAAiB,WAAW,IAAI,MAAe;AAC/C,SAAiB,eAAe,IAAI,MAA2B;AAC/D,SAAiB,sBAAsB,IAAI,MAAyC;AAEpF,SAAiB,wBAAwB,IAAI,mDAAsB,MAAM,KAAK,iBAAiB,CAAC;AAChG,SAAQ,0BAA0B,oEAA2B,0BAA0B;AAIvF,SAAQ,0BAAyC;AACjD,sBAAa;AASb;AAAA;AAAA;AAAA,8BAAqB,IAAI,mBAAM,IAAI;AAkC/B,SAAK,iBAAiB,IAAI,qCAAe,mCAAmC;AAE5E,SAAK,iBAAiB,IAAI,mCAAc,aAAa;AAErD,SAAK,eAAe,OAAO,QAAQ,GAAG,OAAM,WAAU;AAClD,YAAM,EAAE,aAAa,WAAW,IAAI;AAEpC,YAAM,KAAK,gBAAgB,uBAAuB,UAAU;AAC5D,WAAK,6BAA6B,aAAa,kCAAa,OAAO;AACnE,UAAI,KAAK,eAAe,WAAW,EAAE,WAAW,GAAG;AAE/C,cAAM,KAAK,6BAA6B;AAAA,MAC5C;AAEA,WAAK,2BAA2B;AAAA,IACpC,CAAC;AACD,SAAK,eAAe,OAAO,QAAQ;AAAA,MAAG,CAAC,EAAE,YAAY,MACjD,KAAK,6BAA6B,aAAa,kCAAa,OAAO;AAAA,IACvE;AAEA,SAAK,kBAAkB,IAAI,qCAAe,MAAM,cAAc;AAE9D,SAAK,mBAAmB,IAAI,uCAA8B,KAAK,iBAAiB,KAAK,cAAc;AAEnG,SAAK,mBAAmB,KAAK,qBAAqB;AAElD,SAAK,mBAAmB,iBAAK;AAAA,MAAiB;AAAA,MAA4B;AAAA,MAAiC;AAAA;AAAA;AAAA,QAGvG,KAAK,mBAAmB,IAAI,MAAM,KAAK,SAAS,CAAC;AAAA;AAAA,IACrD;AAEA,SAAK,gBAAgB,cAAc,GAAG,aAAW;AAC7C,UAAI,QAAQ,QAAQ;AAChB,aAAK,uBAAuB,QAAQ,OAAO,WAAW;AAAA,MAC1D;AAAA,IACJ,CAAC;AAED,SAAK,gBAAgB,cAAc,GAAG,OAAM,YAAW;AACnD,UAAI,CAAC,QAAQ,8BAA8B;AAEvC,cAAM,KAAK,gBAAgB,aAAa,OAAO;AAAA,MACnD;AAEA,YAAM,qBAAqB,QAAQ,QAAQ;AAC3C,UAAI,uBAAuB,QAAW;AAClC,aAAK,uBAAuB,kBAAkB;AAAA,MAClD;AAEA,UAAI,KAAK,WAAW;AAChB;AAAA,MACJ;AAGA,YAAM,wBACF,uBAAuB,SAAY,SAAY,KAAK,iBAAiB,kBAAkB,GAAG;AAK9F,UAAI,KAAK,eAAe,WAAW,EAAE,SAAS,KAAK,QAAQ,UAAU,CAAC,uBAAuB;AACzF,aAAK,kBAAkB,EAAE,MAAM,WAAS,OAAO,KAAK,0BAA0B,KAAK,CAAC;AAAA,MACxF;AAAA,IACJ,CAAC;AAED,SAAK,gBAAgB,qBAAqB,GAAG,aAAW;AACpD,YAAM,gBAAgB,QAAQ;AAC9B,UAAI,kBAAkB,QAAW;AAC7B,aAAK,uBAAuB,cAAc,WAAW;AAAA,MACzD;AAAA,IACJ,CAAC;AAED,SAAK,oBAAgB,4CAAkB,MAAM,YAAY;AACrD,YAAM,KAAK,eAAe,gBAAgB;AAG1C,WAAK,eAAe,OAAO,MAAM;AAAA,QAAG,CAAC,EAAE,YAAY,MAC/C,KAAK,6BAA6B,aAAa,kCAAa,KAAK;AAAA,MACrE;AAEA,YAAM,KAAK,gBAAgB,gBAAgB,KAAK,eAAe,WAAW,CAAC;AAAA,IAC/E,CAAC;AAAA,EACL;AAAA,EA7HA;AAAA,EACS;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EAKA;AAAA,EACA;AAAA,EAEA,IAAI,eAAe;AACf,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,aAAa,OACT,gBACA,eACA,wBACA,sCAAsC,GACtC,8BACA,wBACF;AACE,eAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA,EA8FA,IAAI,gBAAgB;AAChB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAI,iBAAiB;AACjB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAI,kBAAkB;AAClB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAI,kBAAkB;AAClB,SAAK,oBAAoB;AACzB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAI,YAAY;AACZ,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,WAAW,iBAAkC;AAC/C,UAAM,gBAAgB;AAEtB,SAAK,mBAAmB;AAExB,SAAK,eAAe,OAAO,MAAM,GAAG,YAAU;AAC1C,YAAM,UAAU,KAAK,eAAe,WAAW;AAC/C,WAAK,wBAAwB,SAAS,IAAI,EAAE;AAAA,QAAM,WAC9C,OAAO,KAAK,+CAA+C,OAAO,WAAW,IAAI,KAAK;AAAA,MAC1F;AACA,aAAO,KAAK,iBAAiB,6BAAW,KAAK,EAAE,QAAQ,OAAO,UAAU,aAAa,OAAO,YAAY,CAAC,CAAC;AAAA,IAC9G,CAAC;AAED,oBAAgB,aAAa,GAAG,YAAY,MAAM,KAAK,iBAAiB,CAAC;AAEzE,oBAAgB,aAAa,OAAO,GAAG,YAAU;AAC7C,UAAI,WAAW,2BAAU,OAAO,WAAW;AACvC,aAAK,mBAAmB;AAAA,MAC5B;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EAEA,oBAAoB,SAAkB;AAClC,QAAI,KAAK,gBAAgB,EAAG;AAC5B,UAAM,IAAI;AAAA,MACN,WAAW;AAAA,MACX,6BAAW;AAAA,IACf;AAAA,EACJ;AAAA,EAEA,kBAAkB;AACd,WAAO,KAAK,qBAAqB;AAAA,EACrC;AAAA,EAEA,WAAW,SAAkB;AACzB,SAAK,SAAS,KAAK,OAAO;AAC1B,WAAO;AAAA,EACX;AAAA,EAEA,eAAe,aAAkC;AAC7C,WAAO,KAAK,aAAa,SAAS,WAAW;AAAA,EACjD;AAAA,EAEA,eAAe,aAAkC;AAC7C,SAAK,aAAa,KAAK,WAAW;AAClC,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,kBAAkB,aAAkC;AACtD,UAAM,MAAM,KAAK,aAAa,UAAU,OAAK,MAAM,WAAW;AAC9D,QAAI,QAAQ,IAAI;AACZ,WAAK,aAAa,OAAO,KAAK,CAAC;AAC/B,YAAM,YAAY,uBAAuB;AAAA,IAC7C;AAAA,EACJ;AAAA,EAEA,sBAAsB,WAA+B;AACjD,SAAK,gBAAgB,sBAAsB,SAAS;AACpD,SAAK,oBAAoB,KAAK,SAAS;AACvC,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,yBAAyB,WAA+B;AAC1D,UAAM,MAAM,KAAK,oBAAoB,UAAU,OAAK,MAAM,SAAS;AACnE,QAAI,QAAQ,IAAI;AACZ,WAAK,oBAAoB,OAAO,KAAK,CAAC;AACtC,YAAM,UAAU,MAAM;AAAA,IAC1B;AAAA,EACJ;AAAA,EAEA,mBAAmB,YAAoB;AACnC,WAAO,KAAK,gBAAgB,mBAAmB,UAAU;AAAA,EAC7D;AAAA,EAEA,mBAAmB,UAAyC;AACxD,SAAK,gBAAgB,mBAAmB,QAAQ;AAChD,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,QAAQ;AACV,UAAM,KAAK,kBAAkB;AAAA,EACjC;AAAA,EAEA,MAAM,oBAAoB;AACtB,QAAI,KAAK,UAAW;AACpB,QAAI,KAAK,iBAAiB,WAAW;AACjC,WAAK,iBAAiB,KAAK;AAAA,IAC/B;AACA,SAAK,0BAA0B,iBAAK,MAAM;AAC1C,SAAK,iBAAiB,MAAM;AAC5B,UAAM,KAAK,SAAS;AAAA,EACxB;AAAA,EAEA,MAAM,+BAA+B;AACjC,eAAW,eAAe,KAAK,cAAc;AACzC,YAAM,YAAY,yBAAyB;AAAA,IAC/C;AAAA,EACJ;AAAA,EAEA,MAAM,SAAS,eAAe,OAAO;AACjC,QAAI,CAAC,cAAc;AAEf,UACI,KAAK,4BAA4B,QACjC,iBAAK,MAAM,IAAI,KAAK,0BAA0B,4EAChD;AACE,cAAM,KAAK,iBAAiB;AAC5B,eAAO,MAAM,gDAAgD;AAC7D;AAAA,MACJ;AACA,UAAI,KAAK,4BAA4B,oEAA2B,0BAA0B,eAAe;AAErG,mBAAW,eAAe,KAAK,cAAc;AACzC,gBAAM,YAAY,SAAS;AAAA,QAC/B;AACA;AAAA,MACJ;AAAA,IACJ;AACA,UAAM,UAAU,KAAK,eAAe,WAAW;AAC/C,QAAI,QAAQ,QAAQ;AAChB,UAAI,yBAAyB;AAC7B,iBAAW,UAAU,SAAS;AAC1B,cAAM,UAAU,KAAK,gBAAgB,kBAAkB,QAAQ,OAAO,UAAU;AAChF,YAAI,YAAY,UAAa,CAAC,QAAQ,YAAY,QAAQ,gCAAgC,GAAG;AACzF;AACA,iBAAO,MAAM,cAAc,6BAAW,KAAK,EAAE,QAAQ,OAAO,SAAS,CAAC,CAAC;AAAA,QAC3E;AAAA,MACJ;AACA,iBAAW,eAAe,KAAK,cAAc;AACzC,cAAM,YAAY,WAAW,OAAO;AACpC,YACI,yBAAyB,KACzB,KAAK,4BAA4B,oEAA2B,0BAA0B,eACxF;AACE,gBAAM,YAAY,SAAS;AAAA,QAC/B;AAAA,MACJ;AAAA,IACJ,OAAO;AAGH,YAAM,KAAK,6BAA6B;AACxC,YAAM,KAAK,wBAAwB;AAAA,IACvC;AAAA,EACJ;AAAA,EAEA,MAAc,yBACV,MACA,gCACA,eACF;AACE,QAAI,KAAK,4BAA4B,oEAA2B,0BAA0B,eAAe;AACrG,YAAM,IAAI;AAAA,QACN,0DAA0D,KAAK,uBAAuB;AAAA,MAC1F;AAAA,IACJ;AACA,QAAI,KAAK,mCAAmC,QAAW;AACnD,YAAM,IAAI,iCAAc,4DAA4D;AAAA,IACxF;AACA,SAAK,0BAA0B;AAC/B,SAAK,mCAAmC;AACxC,QAAI,mCAAmC,QAAW;AAC9C,WAAK,iCAAiC;AAAA,IAC1C;AAGA,SAAK,+BAA+B,MAAM,aAAa,EAAE;AAAA,MAAM,WAC3D,OAAO,KAAK,8BAA8B,KAAK;AAAA,IACnD;AAAA,EACJ;AAAA,EAEA,6BAA6B;AACzB,QAAI,KAAK,4BAA4B,oEAA2B,0BAA0B,eAAe;AACrG;AAAA,IACJ;AACA,SAAK,+BAA+B,KAAK,yBAAyB,KAAK,gCAAgC,EAAE;AAAA,MACrG,WAAS,OAAO,KAAK,8BAA8B,KAAK;AAAA,IAC5D;AAAA,EACJ;AAAA,EAEA,MAAM,+BACF,MACA,eACF;AACE,UAAM,sBAAsB,KAAK,uBAAuB;AACxD,eAAW,eAAe,KAAK,cAAc;AACzC,YAAM,YAAY;AAAA,QACd,SAAS,oEAA2B,0BAA0B,qBAAqB,IAAI;AAAA,QACvF;AAAA,UACI,GAAG,oBAAoB;AAAA,UACvB,eAAe,iBAAiB,oBAAoB;AAAA,QACxD;AAAA,MACJ;AAAA,IACJ;AACA,UAAM,KAAK,kBAAkB;AAAA,EACjC;AAAA,EAEA,MAAM,4BAA4B;AAC9B,WAAO,KAAK,gBAAgB,0BAA0B;AAAA,EAC1D;AAAA,EAEA,4BAA4B,eAA0B,YAAuB;AACzE,WAAO,KAAK,eAAe,4BAA4B,eAAe,UAAU;AAAA,EACpF;AAAA,EAEA,MAAM,wBAAwB,SAAmB,kCAAkC,OAAO;AACtF,eAAW,eAAe,KAAK,cAAc;AACzC,YAAM,YAAY,WAAW,SAAS,+BAA+B;AACrE,YAAM,YAAY,SAAS;AAAA,IAC/B;AAAA,EACJ;AAAA,EAEA,iBAAiB,aAA0B;AACvC,WAAO,KAAK,eAAe,WAAW,EAAE,KAAK,YAAU,OAAO,gBAAgB,WAAW;AAAA,EAC7F;AAAA,EAEA,iBAAiB,QAAgB,QAAgB,YAAoB;AACjE,WAAO,KAAK,gBAAgB,iBAAiB,QAAQ,QAAQ,UAAU;AAAA,EAC3E;AAAA,EAEA,yBAAyB,cAAyB;AAC9C,WAAO,KAAK,gBAAgB,yBAAyB,YAAY;AAAA,EACrE;AAAA,EAEA,MAAM,qBAAqB,kBAAoC;AAC3D,WAAO,KAAK,gBAAgB,qBAAqB,gBAAgB;AAAA,EACrE;AAAA,EAEA,aAAa;AACT,WAAO,KAAK,eAAe,WAAW;AAAA,EAC1C;AAAA,EAEA,iBAAiB;AACb,WAAO,CAAC,CAAC,KAAK,eAAe,WAAW,EAAE;AAAA,EAC9C;AAAA,EAEA,MAAM,2BACF,eACA,YACA,0BACF;AACE,QAAI,KAAK,4BAA4B,oEAA2B,0BAA0B,iBAAiB;AACvG,YAAM,IAAI;AAAA,QACN;AAAA,MACJ;AAAA,IACJ;AAEA,SAAK,sBAAsB,oBAAoB,UAAU;AACzD,UAAM,KAAK;AAAA,MACP,oEAA2B,0BAA0B;AAAA,MACrD;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,wBAAwB,0BAAuC;AACjE,QAAI,KAAK,4BAA4B,oEAA2B,0BAA0B,oBAAoB;AAC1G,YAAM,IAAI;AAAA,QACN;AAAA,MACJ;AAAA,IACJ;AAEA,SAAK,sBAAsB;AAAA,MACvB,MAAM,6BAAW,QAAQ,KAAK,uBAAuB,EAAE,UAAU;AAAA,QAC7D,YAAY;AAAA,QACZ,MAAM,qBAAO,IAAI,EAAE,cAAc,EAAE;AAAA,MACvC,CAAC;AAAA,IACL;AAEA,UAAM,KAAK;AAAA,MACP,oEAA2B,0BAA0B;AAAA,MACrD;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,mBAAmB;AACrB,WAAO,MAAM,+CAA+C;AAE5D,QACI,KAAK,4BAA4B,oEAA2B,0BAA0B,sBACtF,KAAK,eAAe,GACtB;AACE,WAAK,sBAAsB,uBAAuB;AAAA,IACtD;AACA,SAAK,0BAA0B,oEAA2B,0BAA0B;AACpF,SAAK,iBAAiB,KAAK;AAC3B,SAAK,0BAA0B;AAC/B,QAAI,KAAK,mCAAmC,QAAW;AACnD,YAAM,iCAAiC,KAAK;AAC5C,WAAK,iCAAiC;AACtC,qCAA+B;AAAA,IACnC;AACA,eAAW,eAAe,KAAK,cAAc;AACzC,YAAM,YAAY,gCAAgC;AAAA,IACtD;AACA,WAAO,KAAK,2BAA2B;AAAA,EAC3C;AAAA,EAEA,wBAAwB;AACpB,WAAO,CAAC,CAAC,KAAK,gBAAgB,eAAe;AAAA,EACjD;AAAA,EAEA,MAAM,WACF,QACA,QACA,iBAAiB,GACmE;AAEpF,UAAM,SAAS,MAAM,KAAK,SAAS,CAAC,EAAE,sBAAsB,QAAQ,QAAQ,cAAc;AAC1F,QAAI,WAAW,OAAW,QAAO;AACjC,UAAM,UAAU,KAAK,gBAAgB,kBAAkB,QAAQ,MAAM;AACrE,QAAI,YAAY,OAAW,QAAO;AAElC,UAAM,mBAAmB,KAAK,oBAAoB,KAAK,sBAAgB,wCAAmB,YAAY,CAAC;AACvG,QAAI,qBAAqB,UAAa,KAAC,wCAAmB,gBAAgB,GAAG;AACzE,YAAM,IAAI,4BAAa,4BAA4B;AAAA,IACvD;AACA,WAAO,EAAE,SAAS,SAAS,MAAM,iBAAiB,YAAY,OAAO,UAAU,CAAC,CAAC,EAAE;AAAA,EACvF;AAAA,EAEA,MAAM,0BAA0B,aAA0B,YAAoB,oBAA8B;AACxG,UAAM,KAAK,gBAAgB,0BAA0B,aAAa,YAAY,kBAAkB;AAAA,EACpG;AAAA,EAEA,MAAM,QAAQ;AACV,SAAK,aAAa;AAClB,UAAM,KAAK,iBAAiB;AAC5B,UAAM,KAAK;AACX,eAAW,eAAe,KAAK,cAAc;AACzC,YAAM,YAAY,MAAM;AAAA,IAC5B;AACA,QAAI,KAAK,kBAAkB;AACvB,YAAM,KAAK,iBAAiB,MAAM;AAClC,WAAK,mBAAmB;AAAA,IAC5B;AACA,UAAM,KAAK,gBAAgB,MAAM;AACjC,UAAM,KAAK,gBAAgB,MAAM;AACjC,UAAM,KAAK,eAAe,MAAM;AAChC,eAAW,sBAAsB,KAAK,qBAAqB;AACvD,YAAM,mBAAmB,MAAM;AAAA,IACnC;AAAA,EACJ;AAAA,EAEA,8BAA8B;AAC1B,WAAO,KAAK,gBAAgB,4BAA4B;AAAA,EAC5D;AACJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -117,7 +117,7 @@ function dataEnforcerFor(schema) {
|
|
|
117
117
|
);
|
|
118
118
|
}
|
|
119
119
|
if (location?.owningFabric && location.owningFabric !== session.fabric) {
|
|
120
|
-
throw new import_errors.
|
|
120
|
+
throw new import_errors.ReadError(
|
|
121
121
|
location,
|
|
122
122
|
"Permission denied: Owning/accessing fabric mismatch",
|
|
123
123
|
import_StatusCode.StatusCode.UnsupportedAccess
|
|
@@ -133,7 +133,7 @@ function dataEnforcerFor(schema) {
|
|
|
133
133
|
if (session.fabric === void 0) {
|
|
134
134
|
return false;
|
|
135
135
|
}
|
|
136
|
-
if (
|
|
136
|
+
if (location?.owningFabric && location.owningFabric !== session.fabric) {
|
|
137
137
|
return false;
|
|
138
138
|
}
|
|
139
139
|
return wrappedMayRead(session, location);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/behavior/AccessControl.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { AccessLevel } from \"../cluster/Cluster.js\";\nimport { ClusterId } from \"../datatype/ClusterId.js\";\nimport { FabricIndex } from \"../datatype/FabricIndex.js\";\nimport { SubjectId } from \"../datatype/SubjectId.js\";\nimport { DataModelPath } from \"../endpoint/DataModelPath.js\";\nimport { Access } from \"../model/aspects/index.js\";\nimport { ElementTag } from \"../model/index.js\";\nimport { ValueModel } from \"../model/models/index.js\";\nimport { StatusCode } from \"../protocol/interaction/StatusCode.js\";\nimport { InvokeError, ReadError, SchemaImplementationError, WriteError } from \"./errors.js\";\nimport { Schema } from \"./supervision/Schema.js\";\n\nconst cache = new WeakMap<Schema, AccessControl>();\n\n/**\n * Enforces access control for a specific schema.\n */\nexport interface AccessControl {\n /**\n * Operational access control metadata.\n */\n limits: AccessControl.Limits;\n\n /**\n * Assert read is authorized.\n */\n authorizeRead: AccessControl.Assertion;\n\n /**\n * Determine if read is authorized.\n */\n mayRead: AccessControl.Verification;\n\n /**\n * Assert write is authorized.\n */\n authorizeWrite: AccessControl.Assertion;\n\n /**\n * Determine if write is authorized.\n */\n mayWrite: AccessControl.Verification;\n\n /**\n * Assert invoke is authorized.\n */\n authorizeInvoke: AccessControl.Assertion;\n\n /**\n * Determine if invoke is authorized.\n */\n mayInvoke: AccessControl.Verification;\n}\n\n/**\n * Obtain an enforcer for specific schema.\n *\n * This is central to security. Implementation is explicit, all objects are involved are frozen and cache is stored as\n * module-private.\n *\n * Pure function; returned value is cached.\n */\nexport function AccessControl(schema: Schema) {\n let enforcer = cache.get(schema);\n if (enforcer === undefined) {\n enforcer = enforcerFor(schema);\n }\n return enforcer;\n}\n\nexport namespace AccessControl {\n /**\n * Operational access control metadata for a schema.\n */\n export interface Limits {\n readonly readable: boolean;\n readonly readLevel: AccessLevel;\n\n readonly writable: boolean;\n readonly writeLevel: AccessLevel;\n\n readonly fabricScoped: boolean;\n readonly fabricSensitive: boolean;\n\n readonly timed: boolean;\n }\n\n /**\n * A function that asserts access control requirements are met.\n */\n export type Assertion = (session: Session, location: Location) => void;\n\n /**\n * A function that returns true if access control requirements are met.\n */\n export type Verification = (session: Session, location: Location) => boolean;\n\n /**\n * Metadata that varies with position in the data model.\n */\n export interface Location {\n /**\n * The diagnostic path to the location.\n */\n path: DataModelPath;\n\n /**\n * The owning behavior.\n */\n cluster?: ClusterId;\n\n /**\n * The fabric that owns the data subtree. Undefined or {@link FabricIndex.NO_FABRIC} disables fabric\n * enforcement.\n */\n owningFabric?: FabricIndex;\n\n /**\n * The access levels already retrieved for this location. With this subtree elements can access the same\n * access levels without re-evaluating.\n */\n accessLevels?: AccessLevel[];\n }\n\n /**\n * Authorization metadata that varies with session.\n */\n export interface Session {\n /**\n * Checks if the authorized client has a certain Access Privilege granted.\n */\n authorizedFor(desiredAccessLevel: AccessLevel, location?: Location): boolean;\n\n /**\n * The fabric of the authorized client.\n */\n readonly fabric?: FabricIndex;\n\n /**\n * The authenticated {@link SubjectId} for online sessions.\n */\n readonly subject?: SubjectId;\n\n /**\n * If this is true, fabric-scoped lists are filtered to the accessing\n * fabric.\n */\n readonly fabricFiltered?: boolean;\n\n /**\n * If this is true a timed transaction is in effect.\n */\n readonly timed?: boolean;\n\n /**\n * If this is true then data access levels are not enforced. Datatypes and command-related access controls are\n * active.\n */\n readonly command?: boolean;\n\n /**\n * If this is true then access levels are not enforced and all values are read/write. Datatypes are still\n * enforced.\n *\n * Tracks \"offline\" rather than \"online\" because this makes the safer mode (full enforcement) the default.\n */\n offline?: boolean;\n }\n}\n\nObject.freeze(AccessControl);\n\nfunction enforcerFor(schema: Schema): AccessControl {\n if (schema.tag === ElementTag.Command) {\n return commandEnforcerFor(schema);\n }\n return dataEnforcerFor(schema);\n}\n\nfunction dataEnforcerFor(schema: Schema): AccessControl {\n const limits = limitsFor(schema);\n\n let mayRead: AccessControl.Verification = (session, location) => {\n if (session.offline || session.command) {\n return true;\n }\n\n return session.authorizedFor(limits.readLevel, location);\n };\n\n let mayWrite: AccessControl.Verification = (session, location) => {\n if (session.offline || session.command) {\n return true;\n }\n\n return session.authorizedFor(limits.writeLevel, location);\n };\n\n let authorizeRead: AccessControl.Assertion = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n\n if (session.authorizedFor(limits.readLevel, location)) {\n return;\n }\n\n throw new ReadError(location, \"Permission denied\", StatusCode.UnsupportedAccess);\n };\n\n let authorizeWrite: AccessControl.Assertion = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n\n if (session.authorizedFor(limits.writeLevel, location)) {\n return;\n }\n\n throw new WriteError(location, \"Permission denied\", StatusCode.UnsupportedAccess);\n };\n\n if (limits.timed) {\n const wrappedAuthorizeWrite = authorizeWrite;\n const wrappedMayWrite = mayWrite;\n\n authorizeWrite = (session, location) => {\n if (!session.offline && !session.timed) {\n throw new WriteError(\n location,\n \"Permission denied because interaction is not timed\",\n StatusCode.NeedsTimedInteraction,\n );\n }\n wrappedAuthorizeWrite?.(session, location);\n };\n\n mayWrite = (session, location) => {\n if (!session.offline && !session.timed) {\n return false;\n }\n\n return wrappedMayWrite(session, location);\n };\n }\n\n if (limits.fabricSensitive) {\n const wrappedAuthorizeRead = authorizeRead;\n const wrappedMayRead = mayRead;\n const wrappedAuthorizeWrite = authorizeWrite;\n const wrappedMayWrite = mayWrite;\n\n authorizeRead = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n\n if (session.fabricFiltered) {\n if (session.fabric === undefined) {\n throw new ReadError(\n location,\n \"Permission denied: No accessing fabric\",\n StatusCode.UnsupportedAccess,\n );\n }\n\n if (location?.owningFabric && location.owningFabric !== session.fabric) {\n throw new WriteError(\n location,\n \"Permission denied: Owning/accessing fabric mismatch\",\n StatusCode.UnsupportedAccess,\n );\n }\n }\n\n wrappedAuthorizeRead(session, location);\n };\n\n mayRead = (session, location) => {\n if (session.offline || session.command) {\n return true;\n }\n\n if (session.fabric === undefined) {\n return false;\n }\n\n if (session.fabricFiltered && location?.owningFabric && location.owningFabric !== session.fabric) {\n return false;\n }\n\n return wrappedMayRead(session, location);\n };\n\n authorizeWrite = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n\n if (session.fabric === undefined) {\n throw new WriteError(location, \"Permission denied: No accessing fabric\", StatusCode.UnsupportedAccess);\n }\n\n if (location?.owningFabric && location.owningFabric !== session.fabric) {\n throw new WriteError(location, \"Permission denied: Owning/accessing fabric mismatch\");\n }\n\n wrappedAuthorizeWrite(session, location);\n };\n\n mayWrite = (session, location) => {\n if (session.offline || session.command) {\n return true;\n }\n\n if (session.fabric === undefined) {\n return false;\n }\n\n if (location?.owningFabric && location.owningFabric !== session.fabric) {\n return false;\n }\n\n return wrappedMayWrite(session, location);\n };\n }\n\n if (!limits.readable) {\n authorizeRead = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n\n throw new ReadError(location, \"Permission defined: Value is write-only\");\n };\n\n mayRead = session => {\n return !!session.offline || !!session.command;\n };\n }\n\n if (!limits.writable) {\n authorizeWrite = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n throw new WriteError(location, \"Permission denied: Value is read-only\");\n };\n\n mayWrite = session => {\n return !!session.offline || !!session.command;\n };\n }\n\n return Object.freeze({\n limits,\n authorizeRead,\n mayRead,\n authorizeWrite,\n mayWrite,\n\n authorizeInvoke(_session: AccessControl.Session, location: AccessControl.Location) {\n throw new SchemaImplementationError(location, \"Permission denied: Invoke request but non-command schema\");\n },\n\n mayInvoke() {\n return false;\n },\n } satisfies AccessControl);\n}\n\nfunction commandEnforcerFor(schema: Schema): AccessControl {\n const limits = limitsFor(schema);\n const timed = schema.effectiveAccess.timed;\n const fabric = schema.effectiveAccess.fabric;\n\n return {\n limits,\n\n authorizeRead(_session, location) {\n throw new SchemaImplementationError(location, \"Permission denied: Read request but command schema\");\n },\n\n mayRead() {\n return false;\n },\n\n authorizeWrite(_session, location) {\n throw new SchemaImplementationError(location, \"Permission denied: Write request but command schema\");\n },\n\n mayWrite() {\n return false;\n },\n\n authorizeInvoke(session, location) {\n if (session.offline) {\n return;\n }\n\n if (!session.command) {\n throw new InvokeError(location, \"Invoke attempt without command context\");\n }\n\n if (timed && !session.timed) {\n throw new InvokeError(\n location,\n \"Invoke attempt without required timed context\",\n StatusCode.TimedRequestMismatch,\n );\n }\n\n if (fabric && session.fabric === undefined) {\n throw new WriteError(location, \"Permission denied: No accessing fabric\", StatusCode.UnsupportedAccess);\n }\n\n if (session.authorizedFor(limits.writeLevel, location)) {\n return;\n }\n\n throw new InvokeError(location, \"Permission denied\", StatusCode.UnsupportedAccess);\n },\n\n mayInvoke(session, location) {\n if (session.offline) {\n return true;\n }\n\n if (!session.command) {\n return false;\n }\n\n if (timed && !session.timed) {\n return false;\n }\n\n if (fabric && session.fabric === undefined) {\n return false;\n }\n\n return session.authorizedFor(limits.writeLevel, location);\n },\n };\n}\n\nfunction limitsFor(schema: Schema) {\n const access = schema.effectiveAccess;\n const quality = schema instanceof ValueModel ? schema.effectiveQuality : undefined;\n\n // Special handling for fixed values - we treat any property owned by a fixed value as also read-only\n let fixed = quality?.fixed;\n for (let s = schema.parent; !fixed && s instanceof ValueModel; s = s.parent) {\n if (s.effectiveQuality.fixed) {\n fixed = true;\n }\n }\n\n const limits: AccessControl.Limits = Object.freeze({\n readable: access.readable,\n writable: access.writable && !fixed,\n fabricScoped: access.fabric === Access.Fabric.Scoped || access.fabric === Access.Fabric.Sensitive,\n fabricSensitive: access.fabric === Access.Fabric.Sensitive,\n timed: access.timed === true,\n\n // Official Matter defaults are View for read and Operate for write. However, the schema's effective access\n // should already have these defaults. Here we just adopt minimum needed rights as a safe fallback access level.\n readLevel: access.readPriv === undefined ? AccessLevel.View : Access.PrivilegeLevel[access.readPriv],\n writeLevel: access.writePriv === undefined ? AccessLevel.Operate : Access.PrivilegeLevel[access.writePriv],\n });\n\n return limits;\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { AccessLevel } from \"../cluster/Cluster.js\";\nimport { ClusterId } from \"../datatype/ClusterId.js\";\nimport { FabricIndex } from \"../datatype/FabricIndex.js\";\nimport { SubjectId } from \"../datatype/SubjectId.js\";\nimport { DataModelPath } from \"../endpoint/DataModelPath.js\";\nimport { Access } from \"../model/aspects/index.js\";\nimport { ElementTag } from \"../model/index.js\";\nimport { ValueModel } from \"../model/models/index.js\";\nimport { StatusCode } from \"../protocol/interaction/StatusCode.js\";\nimport { InvokeError, ReadError, SchemaImplementationError, WriteError } from \"./errors.js\";\nimport { Schema } from \"./supervision/Schema.js\";\n\nconst cache = new WeakMap<Schema, AccessControl>();\n\n/**\n * Enforces access control for a specific schema.\n */\nexport interface AccessControl {\n /**\n * Operational access control metadata.\n */\n limits: AccessControl.Limits;\n\n /**\n * Assert read is authorized.\n */\n authorizeRead: AccessControl.Assertion;\n\n /**\n * Determine if read is authorized.\n */\n mayRead: AccessControl.Verification;\n\n /**\n * Assert write is authorized.\n */\n authorizeWrite: AccessControl.Assertion;\n\n /**\n * Determine if write is authorized.\n */\n mayWrite: AccessControl.Verification;\n\n /**\n * Assert invoke is authorized.\n */\n authorizeInvoke: AccessControl.Assertion;\n\n /**\n * Determine if invoke is authorized.\n */\n mayInvoke: AccessControl.Verification;\n}\n\n/**\n * Obtain an enforcer for specific schema.\n *\n * This is central to security. Implementation is explicit, all objects are involved are frozen and cache is stored as\n * module-private.\n *\n * Pure function; returned value is cached.\n */\nexport function AccessControl(schema: Schema) {\n let enforcer = cache.get(schema);\n if (enforcer === undefined) {\n enforcer = enforcerFor(schema);\n }\n return enforcer;\n}\n\nexport namespace AccessControl {\n /**\n * Operational access control metadata for a schema.\n */\n export interface Limits {\n readonly readable: boolean;\n readonly readLevel: AccessLevel;\n\n readonly writable: boolean;\n readonly writeLevel: AccessLevel;\n\n readonly fabricScoped: boolean;\n readonly fabricSensitive: boolean;\n\n readonly timed: boolean;\n }\n\n /**\n * A function that asserts access control requirements are met.\n */\n export type Assertion = (session: Session, location: Location) => void;\n\n /**\n * A function that returns true if access control requirements are met.\n */\n export type Verification = (session: Session, location: Location) => boolean;\n\n /**\n * Metadata that varies with position in the data model.\n */\n export interface Location {\n /**\n * The diagnostic path to the location.\n */\n path: DataModelPath;\n\n /**\n * The owning behavior.\n */\n cluster?: ClusterId;\n\n /**\n * The fabric that owns the data subtree. Undefined or {@link FabricIndex.NO_FABRIC} disables fabric\n * enforcement.\n */\n owningFabric?: FabricIndex;\n\n /**\n * The access levels already retrieved for this location. With this subtree elements can access the same\n * access levels without re-evaluating.\n */\n accessLevels?: AccessLevel[];\n }\n\n /**\n * Authorization metadata that varies with session.\n */\n export interface Session {\n /**\n * Checks if the authorized client has a certain Access Privilege granted.\n */\n authorizedFor(desiredAccessLevel: AccessLevel, location?: Location): boolean;\n\n /**\n * The fabric of the authorized client.\n */\n readonly fabric?: FabricIndex;\n\n /**\n * The authenticated {@link SubjectId} for online sessions.\n */\n readonly subject?: SubjectId;\n\n /**\n * If this is true, fabric-scoped lists are filtered to the accessing\n * fabric.\n */\n readonly fabricFiltered?: boolean;\n\n /**\n * If this is true a timed transaction is in effect.\n */\n readonly timed?: boolean;\n\n /**\n * If this is true then data access levels are not enforced. Datatypes and command-related access controls are\n * active.\n */\n readonly command?: boolean;\n\n /**\n * If this is true then access levels are not enforced and all values are read/write. Datatypes are still\n * enforced.\n *\n * Tracks \"offline\" rather than \"online\" because this makes the safer mode (full enforcement) the default.\n */\n offline?: boolean;\n }\n}\n\nObject.freeze(AccessControl);\n\nfunction enforcerFor(schema: Schema): AccessControl {\n if (schema.tag === ElementTag.Command) {\n return commandEnforcerFor(schema);\n }\n return dataEnforcerFor(schema);\n}\n\nfunction dataEnforcerFor(schema: Schema): AccessControl {\n const limits = limitsFor(schema);\n\n let mayRead: AccessControl.Verification = (session, location) => {\n if (session.offline || session.command) {\n return true;\n }\n\n return session.authorizedFor(limits.readLevel, location);\n };\n\n let mayWrite: AccessControl.Verification = (session, location) => {\n if (session.offline || session.command) {\n return true;\n }\n\n return session.authorizedFor(limits.writeLevel, location);\n };\n\n let authorizeRead: AccessControl.Assertion = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n\n if (session.authorizedFor(limits.readLevel, location)) {\n return;\n }\n\n throw new ReadError(location, \"Permission denied\", StatusCode.UnsupportedAccess);\n };\n\n let authorizeWrite: AccessControl.Assertion = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n\n if (session.authorizedFor(limits.writeLevel, location)) {\n return;\n }\n\n throw new WriteError(location, \"Permission denied\", StatusCode.UnsupportedAccess);\n };\n\n if (limits.timed) {\n const wrappedAuthorizeWrite = authorizeWrite;\n const wrappedMayWrite = mayWrite;\n\n authorizeWrite = (session, location) => {\n if (!session.offline && !session.timed) {\n throw new WriteError(\n location,\n \"Permission denied because interaction is not timed\",\n StatusCode.NeedsTimedInteraction,\n );\n }\n wrappedAuthorizeWrite?.(session, location);\n };\n\n mayWrite = (session, location) => {\n if (!session.offline && !session.timed) {\n return false;\n }\n\n return wrappedMayWrite(session, location);\n };\n }\n\n if (limits.fabricSensitive) {\n const wrappedAuthorizeRead = authorizeRead;\n const wrappedMayRead = mayRead;\n const wrappedAuthorizeWrite = authorizeWrite;\n const wrappedMayWrite = mayWrite;\n\n authorizeRead = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n\n if (session.fabricFiltered) {\n if (session.fabric === undefined) {\n throw new ReadError(\n location,\n \"Permission denied: No accessing fabric\",\n StatusCode.UnsupportedAccess,\n );\n }\n\n if (location?.owningFabric && location.owningFabric !== session.fabric) {\n throw new ReadError(\n location,\n \"Permission denied: Owning/accessing fabric mismatch\",\n StatusCode.UnsupportedAccess,\n );\n }\n }\n\n wrappedAuthorizeRead(session, location);\n };\n\n mayRead = (session, location) => {\n if (session.offline || session.command) {\n return true;\n }\n\n if (session.fabric === undefined) {\n return false;\n }\n\n if (location?.owningFabric && location.owningFabric !== session.fabric) {\n return false;\n }\n\n return wrappedMayRead(session, location);\n };\n\n authorizeWrite = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n\n if (session.fabric === undefined) {\n throw new WriteError(location, \"Permission denied: No accessing fabric\", StatusCode.UnsupportedAccess);\n }\n\n if (location?.owningFabric && location.owningFabric !== session.fabric) {\n throw new WriteError(location, \"Permission denied: Owning/accessing fabric mismatch\");\n }\n\n wrappedAuthorizeWrite(session, location);\n };\n\n mayWrite = (session, location) => {\n if (session.offline || session.command) {\n return true;\n }\n\n if (session.fabric === undefined) {\n return false;\n }\n\n if (location?.owningFabric && location.owningFabric !== session.fabric) {\n return false;\n }\n\n return wrappedMayWrite(session, location);\n };\n }\n\n if (!limits.readable) {\n authorizeRead = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n\n throw new ReadError(location, \"Permission defined: Value is write-only\");\n };\n\n mayRead = session => {\n return !!session.offline || !!session.command;\n };\n }\n\n if (!limits.writable) {\n authorizeWrite = (session, location) => {\n if (session.offline || session.command) {\n return;\n }\n throw new WriteError(location, \"Permission denied: Value is read-only\");\n };\n\n mayWrite = session => {\n return !!session.offline || !!session.command;\n };\n }\n\n return Object.freeze({\n limits,\n authorizeRead,\n mayRead,\n authorizeWrite,\n mayWrite,\n\n authorizeInvoke(_session: AccessControl.Session, location: AccessControl.Location) {\n throw new SchemaImplementationError(location, \"Permission denied: Invoke request but non-command schema\");\n },\n\n mayInvoke() {\n return false;\n },\n } satisfies AccessControl);\n}\n\nfunction commandEnforcerFor(schema: Schema): AccessControl {\n const limits = limitsFor(schema);\n const timed = schema.effectiveAccess.timed;\n const fabric = schema.effectiveAccess.fabric;\n\n return {\n limits,\n\n authorizeRead(_session, location) {\n throw new SchemaImplementationError(location, \"Permission denied: Read request but command schema\");\n },\n\n mayRead() {\n return false;\n },\n\n authorizeWrite(_session, location) {\n throw new SchemaImplementationError(location, \"Permission denied: Write request but command schema\");\n },\n\n mayWrite() {\n return false;\n },\n\n authorizeInvoke(session, location) {\n if (session.offline) {\n return;\n }\n\n if (!session.command) {\n throw new InvokeError(location, \"Invoke attempt without command context\");\n }\n\n if (timed && !session.timed) {\n throw new InvokeError(\n location,\n \"Invoke attempt without required timed context\",\n StatusCode.TimedRequestMismatch,\n );\n }\n\n if (fabric && session.fabric === undefined) {\n throw new WriteError(location, \"Permission denied: No accessing fabric\", StatusCode.UnsupportedAccess);\n }\n\n if (session.authorizedFor(limits.writeLevel, location)) {\n return;\n }\n\n throw new InvokeError(location, \"Permission denied\", StatusCode.UnsupportedAccess);\n },\n\n mayInvoke(session, location) {\n if (session.offline) {\n return true;\n }\n\n if (!session.command) {\n return false;\n }\n\n if (timed && !session.timed) {\n return false;\n }\n\n if (fabric && session.fabric === undefined) {\n return false;\n }\n\n return session.authorizedFor(limits.writeLevel, location);\n },\n };\n}\n\nfunction limitsFor(schema: Schema) {\n const access = schema.effectiveAccess;\n const quality = schema instanceof ValueModel ? schema.effectiveQuality : undefined;\n\n // Special handling for fixed values - we treat any property owned by a fixed value as also read-only\n let fixed = quality?.fixed;\n for (let s = schema.parent; !fixed && s instanceof ValueModel; s = s.parent) {\n if (s.effectiveQuality.fixed) {\n fixed = true;\n }\n }\n\n const limits: AccessControl.Limits = Object.freeze({\n readable: access.readable,\n writable: access.writable && !fixed,\n fabricScoped: access.fabric === Access.Fabric.Scoped || access.fabric === Access.Fabric.Sensitive,\n fabricSensitive: access.fabric === Access.Fabric.Sensitive,\n timed: access.timed === true,\n\n // Official Matter defaults are View for read and Operate for write. However, the schema's effective access\n // should already have these defaults. Here we just adopt minimum needed rights as a safe fallback access level.\n readLevel: access.readPriv === undefined ? AccessLevel.View : Access.PrivilegeLevel[access.readPriv],\n writeLevel: access.writePriv === undefined ? AccessLevel.Operate : Access.PrivilegeLevel[access.writePriv],\n });\n\n return limits;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -27,5 +27,6 @@ export declare class ServerNodeFailsafeContext extends FailsafeContext {
|
|
|
27
27
|
restoreNetworkState(): Promise<void>;
|
|
28
28
|
revokeFabric(fabric: Fabric): Promise<void>;
|
|
29
29
|
restoreBreadcrumb(): Promise<void>;
|
|
30
|
+
rollback(): Promise<void>;
|
|
30
31
|
}
|
|
31
32
|
//# sourceMappingURL=ServerNodeFailsafeContext.d.ts.map
|
package/dist/cjs/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerNodeFailsafeContext.d.ts","sourceRoot":"","sources":["../../../../../src/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAGrE,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"ServerNodeFailsafeContext.d.ts","sourceRoot":"","sources":["../../../../../src/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAGrE,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAEnD,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAI7C;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,eAAe;;gBAiB9C,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,CAAC,OAAO;IAWxD;;;;;;;;;;OAUG;IACY,kBAAkB;IAsBlB,mBAAmB;IAanB,YAAY,CAAC,MAAM,EAAE,MAAM;IAM3B,iBAAiB;IAMjB,QAAQ;CA4C1B"}
|
|
@@ -23,6 +23,7 @@ __export(ServerNodeFailsafeContext_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(ServerNodeFailsafeContext_exports);
|
|
24
24
|
var import_FailsafeContext = require("../../../common/FailsafeContext.js");
|
|
25
25
|
var import_Lifecycle = require("../../../common/Lifecycle.js");
|
|
26
|
+
var import_FabricManager = require("../../../fabric/FabricManager.js");
|
|
26
27
|
var import_NetworkCommissioningBehavior = require("../network-commissioning/NetworkCommissioningBehavior.js");
|
|
27
28
|
/**
|
|
28
29
|
* @license
|
|
@@ -90,6 +91,19 @@ class ServerNodeFailsafeContext extends import_FailsafeContext.FailsafeContext {
|
|
|
90
91
|
agent.generalCommissioning.state.breadcrumb = 0;
|
|
91
92
|
});
|
|
92
93
|
}
|
|
94
|
+
async rollback() {
|
|
95
|
+
if (!this.fabricIndex && this.hasRootCert) {
|
|
96
|
+
try {
|
|
97
|
+
const fabricManager = this.#node.env.get(import_FabricManager.FabricManager);
|
|
98
|
+
fabricManager.events.failsafeClosed.emit();
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (!(error instanceof import_Lifecycle.UnsupportedDependencyError)) {
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return super.rollback();
|
|
106
|
+
}
|
|
93
107
|
/*
|
|
94
108
|
override async restoreFabric() {
|
|
95
109
|
await super.restoreFabric();
|
package/dist/cjs/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/behavior/definitions/general-commissioning/ServerNodeFailsafeContext.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { FailsafeContext } from \"../../../common/FailsafeContext.js\";\nimport { Lifecycle } from \"../../../common/Lifecycle.js\";\nimport { Endpoint } from \"../../../endpoint/Endpoint.js\";\nimport { Fabric } from \"../../../fabric/Fabric.js\";\nimport { Node } from \"../../../node/Node.js\";\nimport { Immutable } from \"../../../util/Type.js\";\nimport { NetworkCommissioningBehavior } from \"../network-commissioning/NetworkCommissioningBehavior.js\";\n\n/**\n * {@link FailsafeContext} for {@link Node} API.\n */\nexport class ServerNodeFailsafeContext extends FailsafeContext {\n #node: Node;\n #storedState?: {\n networks: Map<Endpoint, Immutable<NetworkCommissioningBehavior.State[\"networks\"]>>;\n /*\n\n When Fabrics are no longer managed centrally in FabricManager we need this. Maybe we change to this later,\n but now it is just here for reference because these changes are realized by events that are triggered by Fabric\n object changes. See also other commented out sections in this class.\n\n nocs: OperationalCredentialsBehavior.State[\"nocs\"];\n fabrics: OperationalCredentialsBehavior.State[\"fabrics\"];\n trustedRootCertificates: OperationalCredentialsBehavior.State[\"trustedRootCertificates\"];\n\n */\n };\n\n constructor(node: Node, options: FailsafeContext.Options) {\n super(options);\n this.#node = node;\n this.#node.env.set(FailsafeContext, this);\n this.construction.change.on(status => {\n if (status === Lifecycle.Status.Destroyed) {\n this.#node.env.delete(FailsafeContext, this);\n }\n });\n }\n\n /**\n * Persist endpoint credentials and network configurations for restoration if commissioning does not complete.\n *\n * The Matter 1.2 specification makes it pretty clear that Matter supports configuration of multiple network\n * interfaces (e.g. @see {@link MatterSpecification.v11.Core} \u00A7 11.8.8 and \u00A7 2.3.2).\n * {@link NetworkCommissioningCluster} of the primary interface is on the root endpoint. However it's not clear\n * where {@link NetworkCommissioningCluster} instances for secondary interfaces reside. To be on the safe side\n * we just assume any endpoint may support {@link NetworkCommissioningCluster}.\n *\n * TODO - it's recommended to reset all state if commissioning bails; currently we perform mandatory restore\n */\n override async storeEndpointState() {\n // const opcreds = this.#node.state.operationalCredentials;\n this.#storedState = {\n networks: new Map(),\n /*\n nocs: opcreds.nocs.map(noc => ({ ...noc })),\n fabrics: opcreds.fabrics.map(fabric => ({ ...fabric })),\n trustedRootCertificates: [...opcreds.trustedRootCertificates],\n */\n };\n\n if (!this.#node.behaviors.has(NetworkCommissioningBehavior)) {\n return;\n }\n\n this.#node.visit(endpoint => {\n if (endpoint.behaviors.has(NetworkCommissioningBehavior)) {\n this.#storedState?.networks.set(endpoint, endpoint.stateOf(NetworkCommissioningBehavior).networks);\n }\n });\n }\n\n override async restoreNetworkState() {\n await this.#node.act(async agent => {\n const context = agent.context;\n\n await this.#node.visit(async endpoint => {\n const networks = this.#storedState?.networks.get(endpoint);\n if (networks) {\n context.agentFor(endpoint).get(NetworkCommissioningBehavior).state.networks = [...networks];\n }\n });\n });\n }\n\n override async revokeFabric(fabric: Fabric) {\n await fabric.remove();\n\n // await this.#restoreOperationalCredentials();\n }\n\n override async restoreBreadcrumb() {\n await this.#node.act(agent => {\n agent.generalCommissioning.state.breadcrumb = 0;\n });\n }\n\n /*\n override async restoreFabric() {\n await super.restoreFabric();\n await this.#restoreOperationalCredentials();\n }\n\n async #restoreOperationalCredentials() {\n if (this.#operationalCredentialsRestored) {\n return;\n }\n\n const state = this.#storedState;\n if (state) {\n await this.#node.act(agent => {\n const opcreds = agent.operationalCredentials.state;\n opcreds.nocs = state.nocs;\n opcreds.fabrics = state.fabrics;\n opcreds.commissionedFabrics = opcreds.fabrics.length;\n opcreds.trustedRootCertificates = state.trustedRootCertificates;\n });\n }\n\n this.#operationalCredentialsRestored = true;\n }\n */\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,6BAAgC;AAChC,
|
|
4
|
+
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { FailsafeContext } from \"../../../common/FailsafeContext.js\";\nimport { Lifecycle, UnsupportedDependencyError } from \"../../../common/Lifecycle.js\";\nimport { Endpoint } from \"../../../endpoint/Endpoint.js\";\nimport { Fabric } from \"../../../fabric/Fabric.js\";\nimport { FabricManager } from \"../../../fabric/FabricManager.js\";\nimport { Node } from \"../../../node/Node.js\";\nimport { Immutable } from \"../../../util/Type.js\";\nimport { NetworkCommissioningBehavior } from \"../network-commissioning/NetworkCommissioningBehavior.js\";\n\n/**\n * {@link FailsafeContext} for {@link Node} API.\n */\nexport class ServerNodeFailsafeContext extends FailsafeContext {\n #node: Node;\n #storedState?: {\n networks: Map<Endpoint, Immutable<NetworkCommissioningBehavior.State[\"networks\"]>>;\n /*\n\n When Fabrics are no longer managed centrally in FabricManager we need this. Maybe we change to this later,\n but now it is just here for reference because these changes are realized by events that are triggered by Fabric\n object changes. See also other commented out sections in this class.\n\n nocs: OperationalCredentialsBehavior.State[\"nocs\"];\n fabrics: OperationalCredentialsBehavior.State[\"fabrics\"];\n trustedRootCertificates: OperationalCredentialsBehavior.State[\"trustedRootCertificates\"];\n\n */\n };\n\n constructor(node: Node, options: FailsafeContext.Options) {\n super(options);\n this.#node = node;\n this.#node.env.set(FailsafeContext, this);\n this.construction.change.on(status => {\n if (status === Lifecycle.Status.Destroyed) {\n this.#node.env.delete(FailsafeContext, this);\n }\n });\n }\n\n /**\n * Persist endpoint credentials and network configurations for restoration if commissioning does not complete.\n *\n * The Matter 1.2 specification makes it pretty clear that Matter supports configuration of multiple network\n * interfaces (e.g. @see {@link MatterSpecification.v11.Core} \u00A7 11.8.8 and \u00A7 2.3.2).\n * {@link NetworkCommissioningCluster} of the primary interface is on the root endpoint. However it's not clear\n * where {@link NetworkCommissioningCluster} instances for secondary interfaces reside. To be on the safe side\n * we just assume any endpoint may support {@link NetworkCommissioningCluster}.\n *\n * TODO - it's recommended to reset all state if commissioning bails; currently we perform mandatory restore\n */\n override async storeEndpointState() {\n // const opcreds = this.#node.state.operationalCredentials;\n this.#storedState = {\n networks: new Map(),\n /*\n nocs: opcreds.nocs.map(noc => ({ ...noc })),\n fabrics: opcreds.fabrics.map(fabric => ({ ...fabric })),\n trustedRootCertificates: [...opcreds.trustedRootCertificates],\n */\n };\n\n if (!this.#node.behaviors.has(NetworkCommissioningBehavior)) {\n return;\n }\n\n this.#node.visit(endpoint => {\n if (endpoint.behaviors.has(NetworkCommissioningBehavior)) {\n this.#storedState?.networks.set(endpoint, endpoint.stateOf(NetworkCommissioningBehavior).networks);\n }\n });\n }\n\n override async restoreNetworkState() {\n await this.#node.act(async agent => {\n const context = agent.context;\n\n await this.#node.visit(async endpoint => {\n const networks = this.#storedState?.networks.get(endpoint);\n if (networks) {\n context.agentFor(endpoint).get(NetworkCommissioningBehavior).state.networks = [...networks];\n }\n });\n });\n }\n\n override async revokeFabric(fabric: Fabric) {\n await fabric.remove();\n\n // await this.#restoreOperationalCredentials();\n }\n\n override async restoreBreadcrumb() {\n await this.#node.act(agent => {\n agent.generalCommissioning.state.breadcrumb = 0;\n });\n }\n\n override async rollback() {\n if (!this.fabricIndex && this.hasRootCert) {\n // Update the fabric details if needed (like Trusted Root certificates)\n // Only if fabric was not added because else all data gets updated anyway\n try {\n const fabricManager = this.#node.env.get(FabricManager);\n fabricManager.events.failsafeClosed.emit();\n } catch (error) {\n // UnsupportedDependencyError can happen when the node closes.\n // Then data are refreshed on next start anyway, so ignore this case\n if (!(error instanceof UnsupportedDependencyError)) {\n throw error;\n }\n }\n }\n\n return super.rollback();\n }\n\n /*\n override async restoreFabric() {\n await super.restoreFabric();\n await this.#restoreOperationalCredentials();\n }\n\n async #restoreOperationalCredentials() {\n if (this.#operationalCredentialsRestored) {\n return;\n }\n\n const state = this.#storedState;\n if (state) {\n await this.#node.act(agent => {\n const opcreds = agent.operationalCredentials.state;\n opcreds.nocs = state.nocs;\n opcreds.fabrics = state.fabrics;\n opcreds.commissionedFabrics = opcreds.fabrics.length;\n opcreds.trustedRootCertificates = state.trustedRootCertificates;\n });\n }\n\n this.#operationalCredentialsRestored = true;\n }\n */\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,6BAAgC;AAChC,uBAAsD;AAGtD,2BAA8B;AAG9B,0CAA6C;AAb7C;AAAA;AAAA;AAAA;AAAA;AAkBO,MAAM,kCAAkC,uCAAgB;AAAA,EAC3D;AAAA,EACA;AAAA,EAeA,YAAY,MAAY,SAAkC;AACtD,UAAM,OAAO;AACb,SAAK,QAAQ;AACb,SAAK,MAAM,IAAI,IAAI,wCAAiB,IAAI;AACxC,SAAK,aAAa,OAAO,GAAG,YAAU;AAClC,UAAI,WAAW,2BAAU,OAAO,WAAW;AACvC,aAAK,MAAM,IAAI,OAAO,wCAAiB,IAAI;AAAA,MAC/C;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAe,qBAAqB;AAEhC,SAAK,eAAe;AAAA,MAChB,UAAU,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMtB;AAEA,QAAI,CAAC,KAAK,MAAM,UAAU,IAAI,gEAA4B,GAAG;AACzD;AAAA,IACJ;AAEA,SAAK,MAAM,MAAM,cAAY;AACzB,UAAI,SAAS,UAAU,IAAI,gEAA4B,GAAG;AACtD,aAAK,cAAc,SAAS,IAAI,UAAU,SAAS,QAAQ,gEAA4B,EAAE,QAAQ;AAAA,MACrG;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EAEA,MAAe,sBAAsB;AACjC,UAAM,KAAK,MAAM,IAAI,OAAM,UAAS;AAChC,YAAM,UAAU,MAAM;AAEtB,YAAM,KAAK,MAAM,MAAM,OAAM,aAAY;AACrC,cAAM,WAAW,KAAK,cAAc,SAAS,IAAI,QAAQ;AACzD,YAAI,UAAU;AACV,kBAAQ,SAAS,QAAQ,EAAE,IAAI,gEAA4B,EAAE,MAAM,WAAW,CAAC,GAAG,QAAQ;AAAA,QAC9F;AAAA,MACJ,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AAAA,EAEA,MAAe,aAAa,QAAgB;AACxC,UAAM,OAAO,OAAO;AAAA,EAGxB;AAAA,EAEA,MAAe,oBAAoB;AAC/B,UAAM,KAAK,MAAM,IAAI,WAAS;AAC1B,YAAM,qBAAqB,MAAM,aAAa;AAAA,IAClD,CAAC;AAAA,EACL;AAAA,EAEA,MAAe,WAAW;AACtB,QAAI,CAAC,KAAK,eAAe,KAAK,aAAa;AAGvC,UAAI;AACA,cAAM,gBAAgB,KAAK,MAAM,IAAI,IAAI,kCAAa;AACtD,sBAAc,OAAO,eAAe,KAAK;AAAA,MAC7C,SAAS,OAAO;AAGZ,YAAI,EAAE,iBAAiB,8CAA6B;AAChD,gBAAM;AAAA,QACV;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO,MAAM,SAAS;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/cjs/behavior/definitions/operational-credentials/OperationalCredentialsServer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OperationalCredentialsServer.d.ts","sourceRoot":"","sources":["../../../../../src/behavior/definitions/operational-credentials/OperationalCredentialsServer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,sBAAsB,EAAE,MAAM,+DAA+D,CAAC;
|
|
1
|
+
{"version":3,"file":"OperationalCredentialsServer.d.ts","sourceRoot":"","sources":["../../../../../src/behavior/definitions/operational-credentials/OperationalCredentialsServer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,sBAAsB,EAAE,MAAM,+DAA+D,CAAC;AAMvG,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAUzD,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAIvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EACH,aAAa,EACb,gCAAgC,EAChC,kBAAkB,EAClB,uBAAuB,EACvB,UAAU,EAEV,mBAAmB,EACnB,wBAAwB,EACxB,gBAAgB,EACnB,MAAM,sCAAsC,CAAC;AA+B9C;;;;;;;GAOG;AACH,qBAAa,4BAA6B,SAAQ,8BAA8B;;IACpE,QAAQ,EAAE,4BAA4B,CAAC,QAAQ,CAAC;IAChD,KAAK,EAAE,4BAA4B,CAAC,KAAK,CAAC;IAEzC,UAAU;IAUJ,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,EAAE,kBAAkB;;;;IAkB3D,UAAU,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,UAAU;;;;IA8BnD,uBAAuB,CAAC,EAAE,eAAe,EAAE,EAAE,uBAAuB;;;IAmDpE,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,EAAE,aAAa;;;;;IAqGxF,SAAS,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB;;;;;IAwDnD,iBAAiB,CAAC,EAAE,KAAK,EAAE,EAAE,wBAAwB;;;;;;;;;IAoBrD,YAAY,CAAC,EAAE,WAAW,EAAE,EAAE,mBAAmB;;;;;;;;;IAqBvD,yBAAyB,CAAC,EAAE,iBAAiB,EAAE,EAAE,gCAAgC;IA8DpF,gBAAgB;CAyCzB;AAED,yBAAiB,4BAA4B,CAAC;IAC1C,MAAa,QAAQ;QACjB,aAAa,CAAC,EAAE,mBAAmB,CAAC;QACpC,kBAAkB,CAAC,EAAE,WAAW,CAAC;KACpC;IAED,MAAa,KAAM,SAAQ,8BAA8B,CAAC,KAAK;QAC3D;;;;;;;;WAQG;QACH,aAAa,CAAC,EAAE,mBAAmB,CAAC,UAAU,CAAa;QAE3D,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,CAAC,OAAO;;;KAOzE;CACJ"}
|
package/dist/cjs/behavior/definitions/operational-credentials/OperationalCredentialsServer.js
CHANGED
|
@@ -29,6 +29,7 @@ var import_FailsafeContext = require("../../../common/FailsafeContext.js");
|
|
|
29
29
|
var import_FailsafeTimer = require("../../../common/FailsafeTimer.js");
|
|
30
30
|
var import_MatterError = require("../../../common/MatterError.js");
|
|
31
31
|
var import_ValidationError = require("../../../common/ValidationError.js");
|
|
32
|
+
var import_Crypto = require("../../../crypto/Crypto.js");
|
|
32
33
|
var import_FabricIndex = require("../../../datatype/FabricIndex.js");
|
|
33
34
|
var import_Fabric = require("../../../fabric/Fabric.js");
|
|
34
35
|
var import_FabricManager = require("../../../fabric/FabricManager.js");
|
|
@@ -144,7 +145,7 @@ class OperationalCredentialsServer extends import_OperationalCredentialsBehavior
|
|
|
144
145
|
statusCode: import_OperationalCredentialsCluster.OperationalCredentials.NodeOperationalCertStatus.TableFull,
|
|
145
146
|
debugText: error.message
|
|
146
147
|
};
|
|
147
|
-
} else if (error instanceof import_CertificateManager.CertificateError || error instanceof import_ValidationError.ValidationError || error instanceof import_MatterError.UnexpectedDataError) {
|
|
148
|
+
} else if (error instanceof import_Crypto.CryptoVerifyError || error instanceof import_CertificateManager.CertificateError || error instanceof import_ValidationError.ValidationError || error instanceof import_MatterError.UnexpectedDataError) {
|
|
148
149
|
return {
|
|
149
150
|
statusCode: import_OperationalCredentialsCluster.OperationalCredentials.NodeOperationalCertStatus.InvalidNoc,
|
|
150
151
|
debugText: error.message
|
|
@@ -330,11 +331,15 @@ class OperationalCredentialsServer extends import_OperationalCredentialsBehavior
|
|
|
330
331
|
failsafeContext.setRootCert(rootCaCertificate);
|
|
331
332
|
} catch (error) {
|
|
332
333
|
logger.info("setting root certificate failed", error);
|
|
333
|
-
if (error instanceof import_CertificateManager.CertificateError || error instanceof import_ValidationError.ValidationError || error instanceof import_MatterError.UnexpectedDataError) {
|
|
334
|
+
if (error instanceof import_Crypto.CryptoVerifyError || error instanceof import_CertificateManager.CertificateError || error instanceof import_ValidationError.ValidationError || error instanceof import_MatterError.UnexpectedDataError) {
|
|
334
335
|
throw new import_StatusCode.StatusResponseError(error.message, import_StatusCode.StatusCode.InvalidCommand);
|
|
335
336
|
}
|
|
336
337
|
throw error;
|
|
337
338
|
}
|
|
339
|
+
const fabrics = this.endpoint.env.get(import_FabricManager.FabricManager).getFabrics();
|
|
340
|
+
const trustedRootCertificates = fabrics.map((fabric) => fabric.rootCert);
|
|
341
|
+
trustedRootCertificates.push(rootCaCertificate);
|
|
342
|
+
this.state.trustedRootCertificates = trustedRootCertificates;
|
|
338
343
|
}
|
|
339
344
|
async #updateFabrics() {
|
|
340
345
|
const fabrics = this.endpoint.env.get(import_FabricManager.FabricManager).getFabrics();
|
|
@@ -377,11 +382,15 @@ class OperationalCredentialsServer extends import_OperationalCredentialsBehavior
|
|
|
377
382
|
await this.#updateFabrics();
|
|
378
383
|
this.agent.get(import_CommissioningBehavior.CommissioningBehavior).handleFabricChange(fabricIndex, import_FabricManager.FabricAction.Removed);
|
|
379
384
|
}
|
|
385
|
+
async #handleFailsafeClosed() {
|
|
386
|
+
await this.#updateFabrics();
|
|
387
|
+
}
|
|
380
388
|
async #nodeOnline() {
|
|
381
389
|
const fabricManager = this.endpoint.env.get(import_FabricManager.FabricManager);
|
|
382
390
|
this.reactTo(fabricManager.events.added, this.#handleAddedFabric);
|
|
383
391
|
this.reactTo(fabricManager.events.updated, this.#handleUpdatedFabric);
|
|
384
392
|
this.reactTo(fabricManager.events.deleted, this.#handleRemovedFabric);
|
|
393
|
+
this.reactTo(fabricManager.events.failsafeClosed, this.#handleFailsafeClosed, { lock: true });
|
|
385
394
|
await this.#updateFabrics();
|
|
386
395
|
}
|
|
387
396
|
}
|
package/dist/cjs/behavior/definitions/operational-credentials/OperationalCredentialsServer.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/behavior/definitions/operational-credentials/OperationalCredentialsServer.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { CertificateError } from \"../../../certificate/CertificateManager.js\";\nimport { AccessLevel, Command } from \"../../../cluster/Cluster.js\";\nimport { AccessControl } from \"../../../cluster/definitions/AccessControlCluster.js\";\nimport { OperationalCredentials } from \"../../../cluster/definitions/OperationalCredentialsCluster.js\";\nimport { MatterFabricInvalidAdminSubjectError } from \"../../../common/FailsafeContext.js\";\nimport { MatterFabricConflictError } from \"../../../common/FailsafeTimer.js\";\nimport { MatterFlowError, UnexpectedDataError } from \"../../../common/MatterError.js\";\nimport { ValidationError } from \"../../../common/ValidationError.js\";\nimport { FabricIndex } from \"../../../datatype/FabricIndex.js\";\nimport { Endpoint } from \"../../../endpoint/Endpoint.js\";\nimport { Fabric, PublicKeyError } from \"../../../fabric/Fabric.js\";\nimport { FabricAction, FabricManager, FabricTableFullError } from \"../../../fabric/FabricManager.js\";\nimport { Logger } from \"../../../log/Logger.js\";\nimport type { Node } from \"../../../node/Node.js\";\nimport { StatusCode, StatusResponseError } from \"../../../protocol/interaction/StatusCode.js\";\nimport { assertSecureSession } from \"../../../session/SecureSession.js\";\nimport { TlvBoolean } from \"../../../tlv/TlvBoolean.js\";\nimport { TlvField, TlvObject, TlvOptionalField } from \"../../../tlv/TlvObject.js\";\nimport { TlvByteString } from \"../../../tlv/TlvString.js\";\nimport { Val } from \"../../state/Val.js\";\nimport { ValueSupervisor } from \"../../supervision/ValueSupervisor.js\";\nimport { CommissioningBehavior } from \"../../system/commissioning/CommissioningBehavior.js\";\nimport { ProductDescriptionServer } from \"../../system/product-description/ProductDescriptionServer.js\";\nimport { AccessControlServer } from \"../access-control/AccessControlServer.js\";\nimport { DeviceCertification } from \"./DeviceCertification.js\";\nimport { OperationalCredentialsBehavior } from \"./OperationalCredentialsBehavior.js\";\nimport {\n AddNocRequest,\n AddTrustedRootCertificateRequest,\n AttestationRequest,\n CertificateChainRequest,\n CsrRequest,\n NocResponse,\n RemoveFabricRequest,\n UpdateFabricLabelRequest,\n UpdateNocRequest,\n} from \"./OperationalCredentialsInterface.js\";\nimport { TlvAttestation, TlvCertSigningRequest } from \"./OperationalCredentialsTypes.js\";\n\nconst logger = Logger.get(\"OperationalCredentials\");\n\n/**\n * Monkey patching Tlv Structure of attestationRequest and csrRequest commands to prevent data validation of the nonce\n * fields to be handled as ConstraintError because we need to return a special error.\n * We do this to leave the model in fact for other validations and only apply the change for our Schema-aware Tlv parsing.\n */\nOperationalCredentials.Cluster.commands = {\n ...OperationalCredentials.Cluster.commands,\n attestationRequest: Command(\n 0x0,\n TlvObject({ attestationNonce: TlvField(0, TlvByteString) }),\n 0x1,\n OperationalCredentials.TlvAttestationResponse,\n { invokeAcl: AccessLevel.Administer },\n ),\n csrRequest: Command(\n 0x4,\n TlvObject({\n csrNonce: TlvField(0, TlvByteString),\n isForUpdateNoc: TlvOptionalField(1, TlvBoolean),\n }),\n 0x5,\n OperationalCredentials.TlvCsrResponse,\n { invokeAcl: AccessLevel.Administer },\n ),\n};\n\n/**\n * This is the default server implementation of OperationalCredentialsBehavior.\n *\n * TODO - currently \"source of truth\" for fabric data is persisted by FabricManager. If we remove some legacy code\n * paths we can move source of truth to here. Right now we just sync fabrics with MatterDevice. This sync is only as\n * comprehensive as required by current use cases. If fabrics are mutated directly on MatterDevice then this code will\n * require update.\n */\nexport class OperationalCredentialsServer extends OperationalCredentialsBehavior {\n declare internal: OperationalCredentialsServer.Internal;\n declare state: OperationalCredentialsServer.State;\n\n override initialize() {\n // maximum number of fabrics. Also FabricBuilder uses 254 as max!\n if (this.state.supportedFabrics === undefined) {\n this.state.supportedFabrics = 254;\n }\n this.state.commissionedFabrics = this.state.fabrics.length;\n\n this.reactTo((this.endpoint as Node).lifecycle.online, this.#nodeOnline);\n }\n\n override async attestationRequest({ attestationNonce }: AttestationRequest) {\n if (attestationNonce.length !== 32) {\n throw new StatusResponseError(\"Invalid attestation nonce length\", StatusCode.InvalidCommand);\n }\n\n const certification = await this.getCertification();\n\n const elements = TlvAttestation.encode({\n declaration: certification.declaration,\n attestationNonce: attestationNonce,\n timestamp: 0,\n });\n return {\n attestationElements: elements,\n attestationSignature: certification.sign(this.session, elements),\n };\n }\n\n override async csrRequest({ csrNonce, isForUpdateNoc }: CsrRequest) {\n if (csrNonce.length !== 32) {\n throw new StatusResponseError(\"Invalid csr nonce length\", StatusCode.InvalidCommand);\n }\n\n if (isForUpdateNoc && this.session.isPase) {\n throw new StatusResponseError(\n \"csrRequest for UpdateNoc received on a PASE session.\",\n StatusCode.InvalidCommand,\n );\n }\n\n const failsafeContext = this.session.context.failsafeContext;\n if (failsafeContext.fabricIndex !== undefined) {\n throw new StatusResponseError(\n `csrRequest received after ${failsafeContext.forUpdateNoc ? \"UpdateNOC\" : \"AddNOC\"} already invoked.`,\n StatusCode.ConstraintError,\n );\n }\n\n const certification = await this.getCertification();\n\n const certSigningRequest = failsafeContext.createCertificateSigningRequest(\n isForUpdateNoc ?? false,\n this.session.id,\n );\n const nocsrElements = TlvCertSigningRequest.encode({ certSigningRequest, csrNonce });\n return { nocsrElements, attestationSignature: certification.sign(this.session, nocsrElements) };\n }\n\n override async certificateChainRequest({ certificateType }: CertificateChainRequest) {\n const certification = await this.getCertification();\n\n switch (certificateType) {\n case OperationalCredentials.CertificateChainType.DacCertificate:\n return { certificate: certification.certificate };\n case OperationalCredentials.CertificateChainType.PaiCertificate:\n return { certificate: certification.intermediateCertificate };\n default:\n throw new StatusResponseError(\n `Unsupported certificate type: ${certificateType}`,\n StatusCode.InvalidCommand,\n );\n }\n }\n\n #mapNocErrors(error: unknown): NocResponse {\n if (error instanceof MatterFabricConflictError) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.FabricConflict,\n debugText: error.message,\n };\n } else if (error instanceof FabricTableFullError) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.TableFull,\n debugText: error.message,\n };\n } else if (\n error instanceof CertificateError ||\n error instanceof ValidationError ||\n error instanceof UnexpectedDataError\n ) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.InvalidNoc,\n debugText: error.message,\n };\n } else if (error instanceof PublicKeyError) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.InvalidPublicKey,\n debugText: error.message,\n };\n } else if (error instanceof MatterFabricInvalidAdminSubjectError) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.InvalidAdminSubject,\n debugText: error.message,\n };\n }\n throw error;\n }\n\n override async addNoc({ nocValue, icacValue, ipkValue, caseAdminSubject, adminVendorId }: AddNocRequest) {\n const failsafeContext = this.session.context.failsafeContext;\n\n if (failsafeContext.fabricIndex !== undefined) {\n throw new StatusResponseError(\n `addNoc received after ${failsafeContext.forUpdateNoc ? \"UpdateNOC\" : \"AddNOC\"} already invoked.`,\n StatusCode.ConstraintError,\n );\n }\n\n if (!failsafeContext.hasRootCert) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.InvalidNoc,\n debugText: \"Root certificate not found.\",\n };\n }\n\n if (failsafeContext.csrSessionId !== this.session.id) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.MissingCsr,\n debugText: \"CSR not found in failsafe context.\",\n };\n }\n\n if (failsafeContext.forUpdateNoc) {\n throw new StatusResponseError(\n `addNoc received after csr request was invoked for UpdateNOC.`,\n StatusCode.ConstraintError,\n );\n }\n\n const state = this.state;\n if (state.commissionedFabrics >= state.supportedFabrics) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.TableFull,\n debugText: `No more fabrics can be added because limit ${state.supportedFabrics} reached.`,\n };\n }\n\n let fabric: Fabric;\n try {\n fabric = await failsafeContext.buildFabric({\n nocValue,\n icacValue,\n adminVendorId,\n ipkValue,\n caseAdminSubject,\n });\n } catch (error) {\n logger.info(\"Building fabric for addNoc failed\", error);\n return this.#mapNocErrors(error);\n }\n\n // The receiver SHALL create and add a new Access Control Entry using the CaseAdminSubject field to grant\n // subsequent Administer access to an Administrator member of the new Fabric.\n const aclCluster = this.agent.get(AccessControlServer);\n aclCluster.state.acl.push({\n fabricIndex: fabric.fabricIndex,\n privilege: AccessControl.AccessControlEntryPrivilege.Administer,\n authMode: AccessControl.AccessControlEntryAuthMode.Case,\n subjects: [caseAdminSubject],\n targets: null, // entire node\n });\n\n await failsafeContext.addFabric(fabric);\n\n try {\n if (this.session.isPase) {\n logger.debug(`Add Fabric ${fabric.fabricIndex} to PASE session ${this.session.name}.`);\n this.session.addAssociatedFabric(fabric);\n }\n\n // Update attributes\n const existingFabricIndex = this.state.fabrics.findIndex(f => f.fabricIndex === fabric.fabricIndex);\n const existingNocIndex = this.state.nocs.findIndex(n => n.fabricIndex === fabric.fabricIndex);\n if (existingFabricIndex !== -1 || existingNocIndex !== -1) {\n throw new MatterFlowError(\n `FabricIndex ${fabric.fabricIndex} already exists in state. This should not happen.`,\n );\n }\n } catch (e) {\n // Fabric insertion into MatterDevice is not currently transactional so we need to remove manually\n await fabric.remove(this.session.id);\n throw e;\n }\n\n // TODO The incoming IPKValue SHALL be stored in the Fabric-scoped slot within the Group Key Management cluster\n // (see KeySetWrite), for subsequent use during CASE.\n\n // TODO If the current secure session was established with PASE, the receiver SHALL: a. Augment the secure\n // session context with the FabricIndex generated above, such that subsequent interactions have the proper\n // accessing fabric.\n\n logger.info(`addNoc success, adminVendorId ${adminVendorId}, caseAdminSubject ${caseAdminSubject}`);\n\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.Ok,\n fabricIndex: fabric.fabricIndex,\n };\n }\n\n override async updateNoc({ nocValue, icacValue }: UpdateNocRequest) {\n assertSecureSession(this.session);\n\n const device = this.session.context;\n\n const timedOp = device.failsafeContext;\n\n if (timedOp.fabricIndex !== undefined) {\n throw new StatusResponseError(\n `updateNoc received after ${timedOp.forUpdateNoc ? \"UpdateNOC\" : \"AddNOC\"} already invoked.`,\n StatusCode.ConstraintError,\n );\n }\n\n if (timedOp.forUpdateNoc) {\n throw new StatusResponseError(\n `addNoc received after csr request was invoked for UpdateNOC.`,\n StatusCode.ConstraintError,\n );\n }\n\n if (timedOp.hasRootCert) {\n throw new StatusResponseError(\n \"Trusted root certificate added in this session which is now allowed for UpdateNOC.\",\n StatusCode.ConstraintError,\n );\n }\n\n if (!timedOp.forUpdateNoc) {\n throw new StatusResponseError(\"csrRequest not invoked for UpdateNOC.\", StatusCode.ConstraintError);\n }\n\n if (this.session.associatedFabric.fabricIndex !== timedOp.associatedFabric?.fabricIndex) {\n throw new StatusResponseError(\n \"Fabric of this session and the failsafe context do not match.\",\n StatusCode.ConstraintError,\n );\n }\n\n // Build a new Fabric with the updated NOC and ICAC\n try {\n const updateFabric = await timedOp.buildUpdatedFabric(nocValue, icacValue);\n\n // update FabricManager and Resumption records but leave current session intact\n await timedOp.updateFabric(updateFabric);\n\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.Ok,\n fabricIndex: updateFabric.fabricIndex,\n };\n } catch (error) {\n logger.info(\"Building fabric for updateNoc failed\", error);\n return this.#mapNocErrors(error);\n }\n }\n\n override async updateFabricLabel({ label }: UpdateFabricLabelRequest) {\n const fabric = this.session.associatedFabric;\n\n const currentFabricIndex = fabric.fabricIndex;\n const device = this.session.context;\n const conflictingLabelFabric = device\n .getFabrics()\n .find(f => f.label === label && f.fabricIndex !== currentFabricIndex);\n if (conflictingLabelFabric !== undefined) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.LabelConflict,\n debugText: `Label ${label} already used by fabric ${conflictingLabelFabric.fabricIndex}`,\n };\n }\n\n await fabric.setLabel(label);\n\n return { statusCode: OperationalCredentials.NodeOperationalCertStatus.Ok, fabricIndex: fabric.fabricIndex };\n }\n\n override async removeFabric({ fabricIndex }: RemoveFabricRequest) {\n const device = this.session.context;\n\n const fabric = device.getFabricByIndex(fabricIndex);\n\n if (fabric === undefined) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.InvalidFabricIndex,\n debugText: `Fabric ${fabricIndex} not found`,\n };\n }\n\n await fabric.remove(this.session.id);\n // The state is updated on removal via commissionedFabricChanged event, see constructor\n\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.Ok,\n fabricIndex,\n };\n }\n\n override addTrustedRootCertificate({ rootCaCertificate }: AddTrustedRootCertificateRequest) {\n const failsafeContext = this.session.context.failsafeContext;\n\n if (failsafeContext.hasRootCert) {\n throw new StatusResponseError(\n \"Trusted root certificate already added in this FailSafe context.\",\n StatusCode.ConstraintError,\n );\n }\n\n if (failsafeContext.fabricIndex !== undefined) {\n throw new StatusResponseError(\n `Can not add trusted root certificates after ${failsafeContext.forUpdateNoc ? \"UpdateNOC\" : \"AddNOC\"}.`,\n StatusCode.ConstraintError,\n );\n }\n\n try {\n failsafeContext.setRootCert(rootCaCertificate);\n } catch (error) {\n logger.info(\"setting root certificate failed\", error);\n if (\n error instanceof CertificateError ||\n error instanceof ValidationError ||\n error instanceof UnexpectedDataError\n ) {\n throw new StatusResponseError(error.message, StatusCode.InvalidCommand);\n }\n throw error;\n }\n }\n\n async #updateFabrics() {\n const fabrics = this.endpoint.env.get(FabricManager).getFabrics();\n this.state.fabrics = fabrics.map(fabric => ({\n fabricId: fabric.fabricId,\n label: fabric.label,\n nodeId: fabric.nodeId,\n rootPublicKey: fabric.rootPublicKey,\n vendorId: fabric.rootVendorId,\n fabricIndex: fabric.fabricIndex,\n }));\n\n this.state.nocs = fabrics.map(fabric => ({\n noc: fabric.operationalCert,\n icac: fabric.intermediateCACert ?? null,\n fabricIndex: fabric.fabricIndex,\n }));\n\n this.state.trustedRootCertificates = fabrics.map(fabric => fabric.rootCert);\n\n this.state.commissionedFabrics = fabrics.length;\n\n await this.context.transaction.commit();\n }\n\n async getCertification() {\n const certification =\n this.internal.certification ??\n (this.internal.certification = new DeviceCertification(\n this.state.certification,\n this.agent.get(ProductDescriptionServer).state,\n ));\n\n if (!certification.construction.ready) {\n await certification.construction;\n }\n return certification;\n }\n\n async #handleAddedFabric({ fabricIndex }: Fabric) {\n await this.#updateFabrics();\n this.agent.get(CommissioningBehavior).handleFabricChange(fabricIndex, FabricAction.Added);\n }\n\n async #handleUpdatedFabric({ fabricIndex }: Fabric) {\n await this.#updateFabrics();\n this.agent.get(CommissioningBehavior).handleFabricChange(fabricIndex, FabricAction.Updated);\n }\n\n async #handleRemovedFabric({ fabricIndex }: Fabric) {\n await this.#updateFabrics();\n this.agent.get(CommissioningBehavior).handleFabricChange(fabricIndex, FabricAction.Removed);\n }\n\n async #nodeOnline() {\n const fabricManager = this.endpoint.env.get(FabricManager);\n this.reactTo(fabricManager.events.added, this.#handleAddedFabric);\n this.reactTo(fabricManager.events.updated, this.#handleUpdatedFabric);\n this.reactTo(fabricManager.events.deleted, this.#handleRemovedFabric);\n await this.#updateFabrics();\n }\n}\n\nexport namespace OperationalCredentialsServer {\n export class Internal {\n certification?: DeviceCertification;\n commissionedFabric?: FabricIndex;\n }\n\n export class State extends OperationalCredentialsBehavior.State {\n /**\n * Device certification information.\n *\n * Device certification provides a cryptographic certificate that asserts the official status of a device.\n * Production consumer-facing devices are certified by the CSA.\n *\n * Development devices and those intended for personal use may use a development certificate. This is the\n * default if you do not provide an official certification in {@link ServerOptions.certification}.\n */\n certification?: DeviceCertification.Definition = undefined;\n\n [Val.properties](_endpoint: Endpoint, session: ValueSupervisor.Session) {\n return {\n get currentFabricIndex() {\n return session.fabric ?? FabricIndex.NO_FABRIC;\n },\n };\n }\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,gCAAiC;AACjC,qBAAqC;AACrC,kCAA8B;AAC9B,2CAAuC;AACvC,6BAAqD;AACrD,2BAA0C;AAC1C,yBAAqD;AACrD,6BAAgC;AAChC,yBAA4B;AAE5B,oBAAuC;AACvC,2BAAkE;AAClE,oBAAuB;AAEvB,wBAAgD;AAChD,2BAAoC;AACpC,wBAA2B;AAC3B,uBAAsD;AACtD,uBAA8B;AAC9B,iBAAoB;AAEpB,mCAAsC;AACtC,sCAAyC;AACzC,iCAAoC;AACpC,iCAAoC;AACpC,4CAA+C;AAY/C,yCAAsD;
|
|
4
|
+
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { CertificateError } from \"../../../certificate/CertificateManager.js\";\nimport { AccessLevel, Command } from \"../../../cluster/Cluster.js\";\nimport { AccessControl } from \"../../../cluster/definitions/AccessControlCluster.js\";\nimport { OperationalCredentials } from \"../../../cluster/definitions/OperationalCredentialsCluster.js\";\nimport { MatterFabricInvalidAdminSubjectError } from \"../../../common/FailsafeContext.js\";\nimport { MatterFabricConflictError } from \"../../../common/FailsafeTimer.js\";\nimport { MatterFlowError, UnexpectedDataError } from \"../../../common/MatterError.js\";\nimport { ValidationError } from \"../../../common/ValidationError.js\";\nimport { CryptoVerifyError } from \"../../../crypto/Crypto.js\";\nimport { FabricIndex } from \"../../../datatype/FabricIndex.js\";\nimport { Endpoint } from \"../../../endpoint/Endpoint.js\";\nimport { Fabric, PublicKeyError } from \"../../../fabric/Fabric.js\";\nimport { FabricAction, FabricManager, FabricTableFullError } from \"../../../fabric/FabricManager.js\";\nimport { Logger } from \"../../../log/Logger.js\";\nimport type { Node } from \"../../../node/Node.js\";\nimport { StatusCode, StatusResponseError } from \"../../../protocol/interaction/StatusCode.js\";\nimport { assertSecureSession } from \"../../../session/SecureSession.js\";\nimport { TlvBoolean } from \"../../../tlv/TlvBoolean.js\";\nimport { TlvField, TlvObject, TlvOptionalField } from \"../../../tlv/TlvObject.js\";\nimport { TlvByteString } from \"../../../tlv/TlvString.js\";\nimport { Val } from \"../../state/Val.js\";\nimport { ValueSupervisor } from \"../../supervision/ValueSupervisor.js\";\nimport { CommissioningBehavior } from \"../../system/commissioning/CommissioningBehavior.js\";\nimport { ProductDescriptionServer } from \"../../system/product-description/ProductDescriptionServer.js\";\nimport { AccessControlServer } from \"../access-control/AccessControlServer.js\";\nimport { DeviceCertification } from \"./DeviceCertification.js\";\nimport { OperationalCredentialsBehavior } from \"./OperationalCredentialsBehavior.js\";\nimport {\n AddNocRequest,\n AddTrustedRootCertificateRequest,\n AttestationRequest,\n CertificateChainRequest,\n CsrRequest,\n NocResponse,\n RemoveFabricRequest,\n UpdateFabricLabelRequest,\n UpdateNocRequest,\n} from \"./OperationalCredentialsInterface.js\";\nimport { TlvAttestation, TlvCertSigningRequest } from \"./OperationalCredentialsTypes.js\";\n\nconst logger = Logger.get(\"OperationalCredentials\");\n\n/**\n * Monkey patching Tlv Structure of attestationRequest and csrRequest commands to prevent data validation of the nonce\n * fields to be handled as ConstraintError because we need to return a special error.\n * We do this to leave the model in fact for other validations and only apply the change for our Schema-aware Tlv parsing.\n */\nOperationalCredentials.Cluster.commands = {\n ...OperationalCredentials.Cluster.commands,\n attestationRequest: Command(\n 0x0,\n TlvObject({ attestationNonce: TlvField(0, TlvByteString) }),\n 0x1,\n OperationalCredentials.TlvAttestationResponse,\n { invokeAcl: AccessLevel.Administer },\n ),\n csrRequest: Command(\n 0x4,\n TlvObject({\n csrNonce: TlvField(0, TlvByteString),\n isForUpdateNoc: TlvOptionalField(1, TlvBoolean),\n }),\n 0x5,\n OperationalCredentials.TlvCsrResponse,\n { invokeAcl: AccessLevel.Administer },\n ),\n};\n\n/**\n * This is the default server implementation of OperationalCredentialsBehavior.\n *\n * TODO - currently \"source of truth\" for fabric data is persisted by FabricManager. If we remove some legacy code\n * paths we can move source of truth to here. Right now we just sync fabrics with MatterDevice. This sync is only as\n * comprehensive as required by current use cases. If fabrics are mutated directly on MatterDevice then this code will\n * require update.\n */\nexport class OperationalCredentialsServer extends OperationalCredentialsBehavior {\n declare internal: OperationalCredentialsServer.Internal;\n declare state: OperationalCredentialsServer.State;\n\n override initialize() {\n // maximum number of fabrics. Also FabricBuilder uses 254 as max!\n if (this.state.supportedFabrics === undefined) {\n this.state.supportedFabrics = 254;\n }\n this.state.commissionedFabrics = this.state.fabrics.length;\n\n this.reactTo((this.endpoint as Node).lifecycle.online, this.#nodeOnline);\n }\n\n override async attestationRequest({ attestationNonce }: AttestationRequest) {\n if (attestationNonce.length !== 32) {\n throw new StatusResponseError(\"Invalid attestation nonce length\", StatusCode.InvalidCommand);\n }\n\n const certification = await this.getCertification();\n\n const elements = TlvAttestation.encode({\n declaration: certification.declaration,\n attestationNonce: attestationNonce,\n timestamp: 0,\n });\n return {\n attestationElements: elements,\n attestationSignature: certification.sign(this.session, elements),\n };\n }\n\n override async csrRequest({ csrNonce, isForUpdateNoc }: CsrRequest) {\n if (csrNonce.length !== 32) {\n throw new StatusResponseError(\"Invalid csr nonce length\", StatusCode.InvalidCommand);\n }\n\n if (isForUpdateNoc && this.session.isPase) {\n throw new StatusResponseError(\n \"csrRequest for UpdateNoc received on a PASE session.\",\n StatusCode.InvalidCommand,\n );\n }\n\n const failsafeContext = this.session.context.failsafeContext;\n if (failsafeContext.fabricIndex !== undefined) {\n throw new StatusResponseError(\n `csrRequest received after ${failsafeContext.forUpdateNoc ? \"UpdateNOC\" : \"AddNOC\"} already invoked.`,\n StatusCode.ConstraintError,\n );\n }\n\n const certification = await this.getCertification();\n\n const certSigningRequest = failsafeContext.createCertificateSigningRequest(\n isForUpdateNoc ?? false,\n this.session.id,\n );\n const nocsrElements = TlvCertSigningRequest.encode({ certSigningRequest, csrNonce });\n return { nocsrElements, attestationSignature: certification.sign(this.session, nocsrElements) };\n }\n\n override async certificateChainRequest({ certificateType }: CertificateChainRequest) {\n const certification = await this.getCertification();\n\n switch (certificateType) {\n case OperationalCredentials.CertificateChainType.DacCertificate:\n return { certificate: certification.certificate };\n case OperationalCredentials.CertificateChainType.PaiCertificate:\n return { certificate: certification.intermediateCertificate };\n default:\n throw new StatusResponseError(\n `Unsupported certificate type: ${certificateType}`,\n StatusCode.InvalidCommand,\n );\n }\n }\n\n #mapNocErrors(error: unknown): NocResponse {\n if (error instanceof MatterFabricConflictError) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.FabricConflict,\n debugText: error.message,\n };\n } else if (error instanceof FabricTableFullError) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.TableFull,\n debugText: error.message,\n };\n } else if (\n error instanceof CryptoVerifyError ||\n error instanceof CertificateError ||\n error instanceof ValidationError ||\n error instanceof UnexpectedDataError\n ) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.InvalidNoc,\n debugText: error.message,\n };\n } else if (error instanceof PublicKeyError) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.InvalidPublicKey,\n debugText: error.message,\n };\n } else if (error instanceof MatterFabricInvalidAdminSubjectError) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.InvalidAdminSubject,\n debugText: error.message,\n };\n }\n throw error;\n }\n\n override async addNoc({ nocValue, icacValue, ipkValue, caseAdminSubject, adminVendorId }: AddNocRequest) {\n const failsafeContext = this.session.context.failsafeContext;\n\n if (failsafeContext.fabricIndex !== undefined) {\n throw new StatusResponseError(\n `addNoc received after ${failsafeContext.forUpdateNoc ? \"UpdateNOC\" : \"AddNOC\"} already invoked.`,\n StatusCode.ConstraintError,\n );\n }\n\n if (!failsafeContext.hasRootCert) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.InvalidNoc,\n debugText: \"Root certificate not found.\",\n };\n }\n\n if (failsafeContext.csrSessionId !== this.session.id) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.MissingCsr,\n debugText: \"CSR not found in failsafe context.\",\n };\n }\n\n if (failsafeContext.forUpdateNoc) {\n throw new StatusResponseError(\n `addNoc received after csr request was invoked for UpdateNOC.`,\n StatusCode.ConstraintError,\n );\n }\n\n const state = this.state;\n if (state.commissionedFabrics >= state.supportedFabrics) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.TableFull,\n debugText: `No more fabrics can be added because limit ${state.supportedFabrics} reached.`,\n };\n }\n\n let fabric: Fabric;\n try {\n fabric = await failsafeContext.buildFabric({\n nocValue,\n icacValue,\n adminVendorId,\n ipkValue,\n caseAdminSubject,\n });\n } catch (error) {\n logger.info(\"Building fabric for addNoc failed\", error);\n return this.#mapNocErrors(error);\n }\n\n // The receiver SHALL create and add a new Access Control Entry using the CaseAdminSubject field to grant\n // subsequent Administer access to an Administrator member of the new Fabric.\n const aclCluster = this.agent.get(AccessControlServer);\n aclCluster.state.acl.push({\n fabricIndex: fabric.fabricIndex,\n privilege: AccessControl.AccessControlEntryPrivilege.Administer,\n authMode: AccessControl.AccessControlEntryAuthMode.Case,\n subjects: [caseAdminSubject],\n targets: null, // entire node\n });\n\n await failsafeContext.addFabric(fabric);\n\n try {\n if (this.session.isPase) {\n logger.debug(`Add Fabric ${fabric.fabricIndex} to PASE session ${this.session.name}.`);\n this.session.addAssociatedFabric(fabric);\n }\n\n // Update attributes\n const existingFabricIndex = this.state.fabrics.findIndex(f => f.fabricIndex === fabric.fabricIndex);\n const existingNocIndex = this.state.nocs.findIndex(n => n.fabricIndex === fabric.fabricIndex);\n if (existingFabricIndex !== -1 || existingNocIndex !== -1) {\n throw new MatterFlowError(\n `FabricIndex ${fabric.fabricIndex} already exists in state. This should not happen.`,\n );\n }\n } catch (e) {\n // Fabric insertion into MatterDevice is not currently transactional so we need to remove manually\n await fabric.remove(this.session.id);\n throw e;\n }\n\n // TODO The incoming IPKValue SHALL be stored in the Fabric-scoped slot within the Group Key Management cluster\n // (see KeySetWrite), for subsequent use during CASE.\n\n // TODO If the current secure session was established with PASE, the receiver SHALL: a. Augment the secure\n // session context with the FabricIndex generated above, such that subsequent interactions have the proper\n // accessing fabric.\n\n logger.info(`addNoc success, adminVendorId ${adminVendorId}, caseAdminSubject ${caseAdminSubject}`);\n\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.Ok,\n fabricIndex: fabric.fabricIndex,\n };\n }\n\n override async updateNoc({ nocValue, icacValue }: UpdateNocRequest) {\n assertSecureSession(this.session);\n\n const device = this.session.context;\n\n const timedOp = device.failsafeContext;\n\n if (timedOp.fabricIndex !== undefined) {\n throw new StatusResponseError(\n `updateNoc received after ${timedOp.forUpdateNoc ? \"UpdateNOC\" : \"AddNOC\"} already invoked.`,\n StatusCode.ConstraintError,\n );\n }\n\n if (timedOp.forUpdateNoc) {\n throw new StatusResponseError(\n `addNoc received after csr request was invoked for UpdateNOC.`,\n StatusCode.ConstraintError,\n );\n }\n\n if (timedOp.hasRootCert) {\n throw new StatusResponseError(\n \"Trusted root certificate added in this session which is now allowed for UpdateNOC.\",\n StatusCode.ConstraintError,\n );\n }\n\n if (!timedOp.forUpdateNoc) {\n throw new StatusResponseError(\"csrRequest not invoked for UpdateNOC.\", StatusCode.ConstraintError);\n }\n\n if (this.session.associatedFabric.fabricIndex !== timedOp.associatedFabric?.fabricIndex) {\n throw new StatusResponseError(\n \"Fabric of this session and the failsafe context do not match.\",\n StatusCode.ConstraintError,\n );\n }\n\n // Build a new Fabric with the updated NOC and ICAC\n try {\n const updateFabric = await timedOp.buildUpdatedFabric(nocValue, icacValue);\n\n // update FabricManager and Resumption records but leave current session intact\n await timedOp.updateFabric(updateFabric);\n\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.Ok,\n fabricIndex: updateFabric.fabricIndex,\n };\n } catch (error) {\n logger.info(\"Building fabric for updateNoc failed\", error);\n return this.#mapNocErrors(error);\n }\n }\n\n override async updateFabricLabel({ label }: UpdateFabricLabelRequest) {\n const fabric = this.session.associatedFabric;\n\n const currentFabricIndex = fabric.fabricIndex;\n const device = this.session.context;\n const conflictingLabelFabric = device\n .getFabrics()\n .find(f => f.label === label && f.fabricIndex !== currentFabricIndex);\n if (conflictingLabelFabric !== undefined) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.LabelConflict,\n debugText: `Label ${label} already used by fabric ${conflictingLabelFabric.fabricIndex}`,\n };\n }\n\n await fabric.setLabel(label);\n\n return { statusCode: OperationalCredentials.NodeOperationalCertStatus.Ok, fabricIndex: fabric.fabricIndex };\n }\n\n override async removeFabric({ fabricIndex }: RemoveFabricRequest) {\n const device = this.session.context;\n\n const fabric = device.getFabricByIndex(fabricIndex);\n\n if (fabric === undefined) {\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.InvalidFabricIndex,\n debugText: `Fabric ${fabricIndex} not found`,\n };\n }\n\n await fabric.remove(this.session.id);\n // The state is updated on removal via commissionedFabricChanged event, see constructor\n\n return {\n statusCode: OperationalCredentials.NodeOperationalCertStatus.Ok,\n fabricIndex,\n };\n }\n\n override addTrustedRootCertificate({ rootCaCertificate }: AddTrustedRootCertificateRequest) {\n const failsafeContext = this.session.context.failsafeContext;\n\n if (failsafeContext.hasRootCert) {\n throw new StatusResponseError(\n \"Trusted root certificate already added in this FailSafe context.\",\n StatusCode.ConstraintError,\n );\n }\n\n if (failsafeContext.fabricIndex !== undefined) {\n throw new StatusResponseError(\n `Can not add trusted root certificates after ${failsafeContext.forUpdateNoc ? \"UpdateNOC\" : \"AddNOC\"}.`,\n StatusCode.ConstraintError,\n );\n }\n\n try {\n failsafeContext.setRootCert(rootCaCertificate);\n } catch (error) {\n logger.info(\"setting root certificate failed\", error);\n if (\n error instanceof CryptoVerifyError ||\n error instanceof CertificateError ||\n error instanceof ValidationError ||\n error instanceof UnexpectedDataError\n ) {\n throw new StatusResponseError(error.message, StatusCode.InvalidCommand);\n }\n throw error;\n }\n\n const fabrics = this.endpoint.env.get(FabricManager).getFabrics();\n const trustedRootCertificates = fabrics.map(fabric => fabric.rootCert);\n trustedRootCertificates.push(rootCaCertificate);\n this.state.trustedRootCertificates = trustedRootCertificates;\n }\n\n async #updateFabrics() {\n const fabrics = this.endpoint.env.get(FabricManager).getFabrics();\n this.state.fabrics = fabrics.map(fabric => ({\n fabricId: fabric.fabricId,\n label: fabric.label,\n nodeId: fabric.nodeId,\n rootPublicKey: fabric.rootPublicKey,\n vendorId: fabric.rootVendorId,\n fabricIndex: fabric.fabricIndex,\n }));\n\n this.state.nocs = fabrics.map(fabric => ({\n noc: fabric.operationalCert,\n icac: fabric.intermediateCACert ?? null,\n fabricIndex: fabric.fabricIndex,\n }));\n\n this.state.trustedRootCertificates = fabrics.map(fabric => fabric.rootCert);\n\n this.state.commissionedFabrics = fabrics.length;\n\n await this.context.transaction.commit();\n }\n\n async getCertification() {\n const certification =\n this.internal.certification ??\n (this.internal.certification = new DeviceCertification(\n this.state.certification,\n this.agent.get(ProductDescriptionServer).state,\n ));\n\n if (!certification.construction.ready) {\n await certification.construction;\n }\n return certification;\n }\n\n async #handleAddedFabric({ fabricIndex }: Fabric) {\n await this.#updateFabrics();\n this.agent.get(CommissioningBehavior).handleFabricChange(fabricIndex, FabricAction.Added);\n }\n\n async #handleUpdatedFabric({ fabricIndex }: Fabric) {\n await this.#updateFabrics();\n this.agent.get(CommissioningBehavior).handleFabricChange(fabricIndex, FabricAction.Updated);\n }\n\n async #handleRemovedFabric({ fabricIndex }: Fabric) {\n await this.#updateFabrics();\n this.agent.get(CommissioningBehavior).handleFabricChange(fabricIndex, FabricAction.Removed);\n }\n\n async #handleFailsafeClosed() {\n await this.#updateFabrics();\n }\n\n async #nodeOnline() {\n const fabricManager = this.endpoint.env.get(FabricManager);\n this.reactTo(fabricManager.events.added, this.#handleAddedFabric);\n this.reactTo(fabricManager.events.updated, this.#handleUpdatedFabric);\n this.reactTo(fabricManager.events.deleted, this.#handleRemovedFabric);\n this.reactTo(fabricManager.events.failsafeClosed, this.#handleFailsafeClosed, { lock: true });\n await this.#updateFabrics();\n }\n}\n\nexport namespace OperationalCredentialsServer {\n export class Internal {\n certification?: DeviceCertification;\n commissionedFabric?: FabricIndex;\n }\n\n export class State extends OperationalCredentialsBehavior.State {\n /**\n * Device certification information.\n *\n * Device certification provides a cryptographic certificate that asserts the official status of a device.\n * Production consumer-facing devices are certified by the CSA.\n *\n * Development devices and those intended for personal use may use a development certificate. This is the\n * default if you do not provide an official certification in {@link ServerOptions.certification}.\n */\n certification?: DeviceCertification.Definition = undefined;\n\n [Val.properties](_endpoint: Endpoint, session: ValueSupervisor.Session) {\n return {\n get currentFabricIndex() {\n return session.fabric ?? FabricIndex.NO_FABRIC;\n },\n };\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["OperationalCredentialsServer"]
|
|
7
7
|
}
|