@matter/model 0.18.0 → 0.18.1-alpha.0-20261111-b84c5d1bc

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.
Files changed (209) hide show
  1. package/dist/cjs/decoration/decorators/index.d.ts +1 -0
  2. package/dist/cjs/decoration/decorators/index.d.ts.map +1 -1
  3. package/dist/cjs/decoration/decorators/index.js +1 -0
  4. package/dist/cjs/decoration/decorators/index.js.map +1 -1
  5. package/dist/cjs/decoration/decorators/secret.d.ts +13 -0
  6. package/dist/cjs/decoration/decorators/secret.d.ts.map +1 -0
  7. package/dist/cjs/decoration/decorators/secret.js +40 -0
  8. package/dist/cjs/decoration/decorators/secret.js.map +6 -0
  9. package/dist/cjs/decoration/semantics/ClassSemantics.d.ts +8 -1
  10. package/dist/cjs/decoration/semantics/ClassSemantics.d.ts.map +1 -1
  11. package/dist/cjs/decoration/semantics/ClassSemantics.js +11 -0
  12. package/dist/cjs/decoration/semantics/ClassSemantics.js.map +1 -1
  13. package/dist/cjs/decoration/semantics/Semantics.d.ts.map +1 -1
  14. package/dist/cjs/decoration/semantics/Semantics.js +3 -0
  15. package/dist/cjs/decoration/semantics/Semantics.js.map +1 -1
  16. package/dist/cjs/elements/ValueElement.d.ts +5 -0
  17. package/dist/cjs/elements/ValueElement.d.ts.map +1 -1
  18. package/dist/cjs/elements/ValueElement.js.map +1 -1
  19. package/dist/cjs/logic/ModelDiff.d.ts.map +1 -1
  20. package/dist/cjs/logic/ModelDiff.js +2 -1
  21. package/dist/cjs/logic/ModelDiff.js.map +1 -1
  22. package/dist/cjs/logic/SecretRedaction.d.ts +42 -0
  23. package/dist/cjs/logic/SecretRedaction.d.ts.map +1 -0
  24. package/dist/cjs/logic/SecretRedaction.js +130 -0
  25. package/dist/cjs/logic/SecretRedaction.js.map +6 -0
  26. package/dist/cjs/logic/SelectDefaultValue.d.ts.map +1 -1
  27. package/dist/cjs/logic/SelectDefaultValue.js +5 -0
  28. package/dist/cjs/logic/SelectDefaultValue.js.map +1 -1
  29. package/dist/cjs/logic/definition-validation/ValueValidator.d.ts.map +1 -1
  30. package/dist/cjs/logic/definition-validation/ValueValidator.js +1 -0
  31. package/dist/cjs/logic/definition-validation/ValueValidator.js.map +1 -1
  32. package/dist/cjs/logic/index.d.ts +1 -0
  33. package/dist/cjs/logic/index.d.ts.map +1 -1
  34. package/dist/cjs/logic/index.js +1 -0
  35. package/dist/cjs/logic/index.js.map +1 -1
  36. package/dist/cjs/models/AttributeModel.d.ts +9 -0
  37. package/dist/cjs/models/AttributeModel.d.ts.map +1 -1
  38. package/dist/cjs/models/AttributeModel.js +11 -0
  39. package/dist/cjs/models/AttributeModel.js.map +1 -1
  40. package/dist/cjs/models/CommandModel.d.ts +1 -0
  41. package/dist/cjs/models/CommandModel.d.ts.map +1 -1
  42. package/dist/cjs/models/EventModel.d.ts +1 -0
  43. package/dist/cjs/models/EventModel.d.ts.map +1 -1
  44. package/dist/cjs/models/ValueModel.d.ts +16 -0
  45. package/dist/cjs/models/ValueModel.d.ts.map +1 -1
  46. package/dist/cjs/models/ValueModel.js +27 -0
  47. package/dist/cjs/models/ValueModel.js.map +1 -1
  48. package/dist/cjs/standard/elements/account-login.element.js +2 -2
  49. package/dist/cjs/standard/elements/account-login.element.js.map +1 -1
  50. package/dist/cjs/standard/elements/administrator-commissioning.element.js +1 -1
  51. package/dist/cjs/standard/elements/administrator-commissioning.element.js.map +1 -1
  52. package/dist/cjs/standard/elements/commissioner-control.element.js +1 -1
  53. package/dist/cjs/standard/elements/commissioner-control.element.js.map +1 -1
  54. package/dist/cjs/standard/elements/content-control.element.js +4 -4
  55. package/dist/cjs/standard/elements/content-control.element.js.map +1 -1
  56. package/dist/cjs/standard/elements/door-lock-cluster.element.js +8 -7
  57. package/dist/cjs/standard/elements/door-lock-cluster.element.js.map +1 -1
  58. package/dist/cjs/standard/elements/general-diagnostics.element.js +2 -2
  59. package/dist/cjs/standard/elements/general-diagnostics.element.js.map +1 -1
  60. package/dist/cjs/standard/elements/group-key-management.element.d.ts.map +1 -1
  61. package/dist/cjs/standard/elements/group-key-management.element.js +30 -3
  62. package/dist/cjs/standard/elements/group-key-management.element.js.map +1 -1
  63. package/dist/cjs/standard/elements/groupcast.element.js +2 -2
  64. package/dist/cjs/standard/elements/groupcast.element.js.map +1 -1
  65. package/dist/cjs/standard/elements/icd-management.element.d.ts.map +1 -1
  66. package/dist/cjs/standard/elements/icd-management.element.js +13 -4
  67. package/dist/cjs/standard/elements/icd-management.element.js.map +1 -1
  68. package/dist/cjs/standard/elements/joint-fabric-administrator-cluster.element.js +1 -1
  69. package/dist/cjs/standard/elements/joint-fabric-administrator-cluster.element.js.map +1 -1
  70. package/dist/cjs/standard/elements/joint-fabric-datastore.element.d.ts.map +1 -1
  71. package/dist/cjs/standard/elements/joint-fabric-datastore.element.js +27 -3
  72. package/dist/cjs/standard/elements/joint-fabric-datastore.element.js.map +1 -1
  73. package/dist/cjs/standard/elements/network-commissioning.element.d.ts.map +1 -1
  74. package/dist/cjs/standard/elements/network-commissioning.element.js +9 -2
  75. package/dist/cjs/standard/elements/network-commissioning.element.js.map +1 -1
  76. package/dist/cjs/standard/elements/operational-credentials.element.js +1 -1
  77. package/dist/cjs/standard/elements/operational-credentials.element.js.map +1 -1
  78. package/dist/cjs/standard/elements/thread-border-router-management.element.js +3 -3
  79. package/dist/cjs/standard/elements/thread-border-router-management.element.js.map +1 -1
  80. package/dist/cjs/standard/elements/thread-network-directory.element.d.ts.map +1 -1
  81. package/dist/cjs/standard/elements/thread-network-directory.element.js +16 -2
  82. package/dist/cjs/standard/elements/thread-network-directory.element.js.map +1 -1
  83. package/dist/cjs/standard/elements/unit-localization.element.d.ts.map +1 -1
  84. package/dist/cjs/standard/elements/unit-localization.element.js +9 -3
  85. package/dist/cjs/standard/elements/unit-localization.element.js.map +1 -1
  86. package/dist/cjs/standard/elements/web-rtc-transport-definitions.element.js +1 -1
  87. package/dist/cjs/standard/elements/web-rtc-transport-definitions.element.js.map +1 -1
  88. package/dist/cjs/standard/elements/wi-fi-network-management.element.js +1 -1
  89. package/dist/cjs/standard/elements/wi-fi-network-management.element.js.map +1 -1
  90. package/dist/esm/decoration/decorators/index.d.ts +1 -0
  91. package/dist/esm/decoration/decorators/index.d.ts.map +1 -1
  92. package/dist/esm/decoration/decorators/index.js +1 -0
  93. package/dist/esm/decoration/decorators/index.js.map +1 -1
  94. package/dist/esm/decoration/decorators/secret.d.ts +13 -0
  95. package/dist/esm/decoration/decorators/secret.d.ts.map +1 -0
  96. package/dist/esm/decoration/decorators/secret.js +20 -0
  97. package/dist/esm/decoration/decorators/secret.js.map +6 -0
  98. package/dist/esm/decoration/semantics/ClassSemantics.d.ts +8 -1
  99. package/dist/esm/decoration/semantics/ClassSemantics.d.ts.map +1 -1
  100. package/dist/esm/decoration/semantics/ClassSemantics.js +11 -0
  101. package/dist/esm/decoration/semantics/ClassSemantics.js.map +1 -1
  102. package/dist/esm/decoration/semantics/Semantics.d.ts.map +1 -1
  103. package/dist/esm/decoration/semantics/Semantics.js +3 -0
  104. package/dist/esm/decoration/semantics/Semantics.js.map +1 -1
  105. package/dist/esm/elements/ValueElement.d.ts +5 -0
  106. package/dist/esm/elements/ValueElement.d.ts.map +1 -1
  107. package/dist/esm/elements/ValueElement.js.map +1 -1
  108. package/dist/esm/logic/ModelDiff.d.ts.map +1 -1
  109. package/dist/esm/logic/ModelDiff.js +2 -1
  110. package/dist/esm/logic/ModelDiff.js.map +1 -1
  111. package/dist/esm/logic/SecretRedaction.d.ts +42 -0
  112. package/dist/esm/logic/SecretRedaction.d.ts.map +1 -0
  113. package/dist/esm/logic/SecretRedaction.js +110 -0
  114. package/dist/esm/logic/SecretRedaction.js.map +6 -0
  115. package/dist/esm/logic/SelectDefaultValue.d.ts.map +1 -1
  116. package/dist/esm/logic/SelectDefaultValue.js +5 -0
  117. package/dist/esm/logic/SelectDefaultValue.js.map +1 -1
  118. package/dist/esm/logic/definition-validation/ValueValidator.d.ts.map +1 -1
  119. package/dist/esm/logic/definition-validation/ValueValidator.js +1 -0
  120. package/dist/esm/logic/definition-validation/ValueValidator.js.map +1 -1
  121. package/dist/esm/logic/index.d.ts +1 -0
  122. package/dist/esm/logic/index.d.ts.map +1 -1
  123. package/dist/esm/logic/index.js +1 -0
  124. package/dist/esm/logic/index.js.map +1 -1
  125. package/dist/esm/models/AttributeModel.d.ts +9 -0
  126. package/dist/esm/models/AttributeModel.d.ts.map +1 -1
  127. package/dist/esm/models/AttributeModel.js +11 -0
  128. package/dist/esm/models/AttributeModel.js.map +1 -1
  129. package/dist/esm/models/CommandModel.d.ts +1 -0
  130. package/dist/esm/models/CommandModel.d.ts.map +1 -1
  131. package/dist/esm/models/EventModel.d.ts +1 -0
  132. package/dist/esm/models/EventModel.d.ts.map +1 -1
  133. package/dist/esm/models/ValueModel.d.ts +16 -0
  134. package/dist/esm/models/ValueModel.d.ts.map +1 -1
  135. package/dist/esm/models/ValueModel.js +27 -0
  136. package/dist/esm/models/ValueModel.js.map +1 -1
  137. package/dist/esm/standard/elements/account-login.element.js +2 -2
  138. package/dist/esm/standard/elements/account-login.element.js.map +1 -1
  139. package/dist/esm/standard/elements/administrator-commissioning.element.js +1 -1
  140. package/dist/esm/standard/elements/administrator-commissioning.element.js.map +1 -1
  141. package/dist/esm/standard/elements/commissioner-control.element.js +1 -1
  142. package/dist/esm/standard/elements/commissioner-control.element.js.map +1 -1
  143. package/dist/esm/standard/elements/content-control.element.js +4 -4
  144. package/dist/esm/standard/elements/content-control.element.js.map +1 -1
  145. package/dist/esm/standard/elements/door-lock-cluster.element.js +8 -7
  146. package/dist/esm/standard/elements/door-lock-cluster.element.js.map +1 -1
  147. package/dist/esm/standard/elements/general-diagnostics.element.js +2 -2
  148. package/dist/esm/standard/elements/general-diagnostics.element.js.map +1 -1
  149. package/dist/esm/standard/elements/group-key-management.element.d.ts.map +1 -1
  150. package/dist/esm/standard/elements/group-key-management.element.js +30 -3
  151. package/dist/esm/standard/elements/group-key-management.element.js.map +1 -1
  152. package/dist/esm/standard/elements/groupcast.element.js +2 -2
  153. package/dist/esm/standard/elements/groupcast.element.js.map +1 -1
  154. package/dist/esm/standard/elements/icd-management.element.d.ts.map +1 -1
  155. package/dist/esm/standard/elements/icd-management.element.js +13 -4
  156. package/dist/esm/standard/elements/icd-management.element.js.map +1 -1
  157. package/dist/esm/standard/elements/joint-fabric-administrator-cluster.element.js +1 -1
  158. package/dist/esm/standard/elements/joint-fabric-administrator-cluster.element.js.map +1 -1
  159. package/dist/esm/standard/elements/joint-fabric-datastore.element.d.ts.map +1 -1
  160. package/dist/esm/standard/elements/joint-fabric-datastore.element.js +27 -3
  161. package/dist/esm/standard/elements/joint-fabric-datastore.element.js.map +1 -1
  162. package/dist/esm/standard/elements/network-commissioning.element.d.ts.map +1 -1
  163. package/dist/esm/standard/elements/network-commissioning.element.js +9 -2
  164. package/dist/esm/standard/elements/network-commissioning.element.js.map +1 -1
  165. package/dist/esm/standard/elements/operational-credentials.element.js +1 -1
  166. package/dist/esm/standard/elements/operational-credentials.element.js.map +1 -1
  167. package/dist/esm/standard/elements/thread-border-router-management.element.js +3 -3
  168. package/dist/esm/standard/elements/thread-border-router-management.element.js.map +1 -1
  169. package/dist/esm/standard/elements/thread-network-directory.element.d.ts.map +1 -1
  170. package/dist/esm/standard/elements/thread-network-directory.element.js +16 -2
  171. package/dist/esm/standard/elements/thread-network-directory.element.js.map +1 -1
  172. package/dist/esm/standard/elements/unit-localization.element.d.ts.map +1 -1
  173. package/dist/esm/standard/elements/unit-localization.element.js +9 -3
  174. package/dist/esm/standard/elements/unit-localization.element.js.map +1 -1
  175. package/dist/esm/standard/elements/web-rtc-transport-definitions.element.js +1 -1
  176. package/dist/esm/standard/elements/web-rtc-transport-definitions.element.js.map +1 -1
  177. package/dist/esm/standard/elements/wi-fi-network-management.element.js +1 -1
  178. package/dist/esm/standard/elements/wi-fi-network-management.element.js.map +1 -1
  179. package/package.json +3 -3
  180. package/src/decoration/decorators/index.ts +1 -0
  181. package/src/decoration/decorators/secret.ts +23 -0
  182. package/src/decoration/semantics/ClassSemantics.ts +20 -1
  183. package/src/decoration/semantics/Semantics.ts +4 -0
  184. package/src/elements/ValueElement.ts +6 -0
  185. package/src/logic/ModelDiff.ts +2 -1
  186. package/src/logic/SecretRedaction.ts +147 -0
  187. package/src/logic/SelectDefaultValue.ts +7 -0
  188. package/src/logic/definition-validation/ValueValidator.ts +1 -0
  189. package/src/logic/index.ts +1 -0
  190. package/src/models/AttributeModel.ts +12 -0
  191. package/src/models/ValueModel.ts +29 -0
  192. package/src/standard/elements/account-login.element.ts +2 -2
  193. package/src/standard/elements/administrator-commissioning.element.ts +1 -1
  194. package/src/standard/elements/commissioner-control.element.ts +1 -1
  195. package/src/standard/elements/content-control.element.ts +4 -4
  196. package/src/standard/elements/door-lock-cluster.element.ts +8 -8
  197. package/src/standard/elements/general-diagnostics.element.ts +2 -2
  198. package/src/standard/elements/group-key-management.element.ts +12 -3
  199. package/src/standard/elements/groupcast.element.ts +2 -2
  200. package/src/standard/elements/icd-management.element.ts +7 -4
  201. package/src/standard/elements/joint-fabric-administrator-cluster.element.ts +1 -1
  202. package/src/standard/elements/joint-fabric-datastore.element.ts +12 -3
  203. package/src/standard/elements/network-commissioning.element.ts +5 -2
  204. package/src/standard/elements/operational-credentials.element.ts +1 -1
  205. package/src/standard/elements/thread-border-router-management.element.ts +3 -3
  206. package/src/standard/elements/thread-network-directory.element.ts +10 -2
  207. package/src/standard/elements/unit-localization.element.ts +4 -3
  208. package/src/standard/elements/web-rtc-transport-definitions.element.ts +1 -1
  209. package/src/standard/elements/wi-fi-network-management.element.ts +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/standard/elements/wi-fi-network-management.element.ts"],
4
- "mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,SAAS,wBAAwB;AACjC;AAAA,EACI,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,OACb;AAEA,MAAM,wBAAwB;AAAA,EACjC,EAAE,MAAM,yBAAyB,IAAI,MAAO,gBAAgB,cAAc;AAAA,EAC1E,UAAU,EAAE,MAAM,mBAAmB,IAAI,OAAQ,MAAM,mBAAmB,SAAS,EAAE,CAAC;AAAA,EACtF,UAAU,EAAE,MAAM,QAAQ,IAAI,GAAK,MAAM,UAAU,QAAQ,OAAO,aAAa,KAAK,YAAY,WAAW,SAAS,MAAM,CAAC;AAAA,EAC3H,UAAU,EAAE,MAAM,uBAAuB,IAAI,GAAK,MAAM,UAAU,QAAQ,OAAO,aAAa,KAAK,SAAS,MAAM,CAAC;AAAA,EACnH,QAAQ;AAAA,IACJ,MAAM;AAAA,IAA4B,IAAI;AAAA,IAAK,QAAQ;AAAA,IAAK,aAAa;AAAA,IAAK,WAAW;AAAA,IACrF,UAAU;AAAA,EACd,CAAC;AAAA,EACD;AAAA,IACI,EAAE,MAAM,6BAA6B,IAAI,GAAK,aAAa,KAAK,WAAW,WAAW;AAAA,IACtF,MAAM,EAAE,MAAM,cAAc,IAAI,GAAK,MAAM,UAAU,aAAa,KAAK,YAAY,SAAS,CAAC;AAAA,EACjG;AACJ;AAEA,iBAAiB,SAAS,KAAK,qBAAqB;",
4
+ "mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,SAAS,wBAAwB;AACjC;AAAA,EACI,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,OACb;AAEA,MAAM,wBAAwB;AAAA,EACjC,EAAE,MAAM,yBAAyB,IAAI,MAAO,gBAAgB,cAAc;AAAA,EAC1E,UAAU,EAAE,MAAM,mBAAmB,IAAI,OAAQ,MAAM,mBAAmB,SAAS,EAAE,CAAC;AAAA,EACtF,UAAU,EAAE,MAAM,QAAQ,IAAI,GAAK,MAAM,UAAU,QAAQ,OAAO,aAAa,KAAK,YAAY,WAAW,SAAS,MAAM,CAAC;AAAA,EAC3H,UAAU,EAAE,MAAM,uBAAuB,IAAI,GAAK,MAAM,UAAU,QAAQ,OAAO,aAAa,KAAK,SAAS,MAAM,CAAC;AAAA,EACnH,QAAQ;AAAA,IACJ,MAAM;AAAA,IAA4B,IAAI;AAAA,IAAK,QAAQ;AAAA,IAAK,aAAa;AAAA,IAAK,WAAW;AAAA,IACrF,UAAU;AAAA,EACd,CAAC;AAAA,EACD;AAAA,IACI,EAAE,MAAM,6BAA6B,IAAI,GAAK,aAAa,KAAK,WAAW,WAAW;AAAA,IACtF,MAAM,EAAE,MAAM,cAAc,IAAI,GAAK,MAAM,UAAU,aAAa,KAAK,YAAY,UAAU,UAAU,KAAK,CAAC;AAAA,EACjH;AACJ;AAEA,iBAAiB,SAAS,KAAK,qBAAqB;",
5
5
  "names": []
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matter/model",
3
- "version": "0.18.0",
3
+ "version": "0.18.1-alpha.0-20261111-b84c5d1bc",
4
4
  "description": "Matter data model",
5
5
  "keywords": [
6
6
  "iot",
@@ -30,10 +30,10 @@
30
30
  "coverage": "c8 matter-test esm"
31
31
  },
32
32
  "dependencies": {
33
- "@matter/general": "0.18.0"
33
+ "@matter/general": "0.18.1-alpha.0-20261111-b84c5d1bc"
34
34
  },
35
35
  "devDependencies": {
36
- "@matter/testing": "0.18.0"
36
+ "@matter/testing": "0.18.1-alpha.0-20261111-b84c5d1bc"
37
37
  },
38
38
  "files": [
39
39
  "dist/**/*",
@@ -16,4 +16,5 @@ export * from "./mandatory.js";
16
16
  export * from "./nonvolatile.js";
17
17
  export * from "./nullable.js";
18
18
  export * from "./response.js";
19
+ export * from "./secret.js";
19
20
  export * from "./writable.js";
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2026 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { InvalidMetadataError } from "#decoration/errors.js";
8
+ import { FieldSemantics } from "#decoration/semantics/FieldSemantics.js";
9
+ import { ValueModel } from "#models/ValueModel.js";
10
+ import { Decorator } from "@matter/general";
11
+
12
+ /**
13
+ * Mark a field as secret, such as a key or a password. Log output replaces its value with a placeholder.
14
+ *
15
+ * @see {@link ValueModel.isSecret}
16
+ */
17
+ export const secret = Decorator<Decorator.PropertyCollector>((_target, context) => {
18
+ const model = FieldSemantics.of(context).mutableModel;
19
+ if (!(model instanceof ValueModel)) {
20
+ throw new InvalidMetadataError("Only value models may be secret");
21
+ }
22
+ model.isSecret = true;
23
+ });
@@ -47,6 +47,7 @@ interface MatterMetadata {
47
47
  export class ClassSemantics extends Semantics {
48
48
  #new?: ClassSemantics.Constructor;
49
49
  #definedFields?: Map<string, FieldSemantics>;
50
+ #afterFinalizeFailure?: { error: unknown };
50
51
 
51
52
  /**
52
53
  * The model that represents the semantics for this class.
@@ -293,6 +294,9 @@ export class ClassSemantics extends Semantics {
293
294
 
294
295
  override finalize() {
295
296
  if (this.isFinal) {
297
+ if (this.#afterFinalizeFailure) {
298
+ throw this.#afterFinalizeFailure.error;
299
+ }
296
300
  return;
297
301
  }
298
302
 
@@ -308,6 +312,13 @@ export class ClassSemantics extends Semantics {
308
312
 
309
313
  // Apply base finalization
310
314
  super.finalize();
315
+
316
+ try {
317
+ this.#new?.[ClassSemantics.afterFinalize]?.(this);
318
+ } catch (error) {
319
+ this.#afterFinalizeFailure = { error };
320
+ throw error;
321
+ }
311
322
  }
312
323
 
313
324
  #applyBaseSemantics() {
@@ -375,9 +386,16 @@ export namespace ClassSemantics {
375
386
  */
376
387
  export interface Constructor extends NewableFunction {
377
388
  /**
378
- * If present, invoked for custom decoration after installing constructor.
389
+ * If present, invoked for custom decoration at the start of finalization, before fields and model are final.
379
390
  */
380
391
  [extend]?: (semantics: ClassSemantics) => void;
392
+
393
+ /**
394
+ * If present, invoked once the class's model is final, for logic that needs the complete model. Runs once. An
395
+ * error it throws reaches the caller that triggered finalization and every later {@link ClassSemantics.finalize},
396
+ * so the class stays unusable rather than appearing valid without what the hook adds.
397
+ */
398
+ [afterFinalize]?: (semantics: ClassSemantics) => void;
381
399
  }
382
400
 
383
401
  /**
@@ -386,4 +404,5 @@ export namespace ClassSemantics {
386
404
  export type Source = Constructor | DecoratorContext | ClassSemantics;
387
405
 
388
406
  export const extend = Symbol("extend");
407
+ export const afterFinalize = Symbol("afterFinalize");
389
408
  }
@@ -158,6 +158,10 @@ export abstract class Semantics {
158
158
  replacement.quality = original.quality;
159
159
  }
160
160
 
161
+ if ("isSecret" in original && "isSecret" in replacement) {
162
+ replacement.isSecret = original.isSecret;
163
+ }
164
+
161
165
  this.#localModel = replacement;
162
166
  }
163
167
 
@@ -46,6 +46,12 @@ export type ValueElement = BaseElement & {
46
46
  */
47
47
  byteSize?: ValueElement.ByteSize;
48
48
 
49
+ /**
50
+ * The value is a secret such as a key, a passcode or a network credential. Log output replaces the value with a
51
+ * placeholder. This is a matter.js extension; the Matter specification has no such quality.
52
+ */
53
+ isSecret?: boolean;
54
+
49
55
  /**
50
56
  * The default value for the element.
51
57
  */
@@ -93,7 +93,7 @@ function propertyChangesOf(from: Model, to: Model) {
93
93
  return changes;
94
94
  }
95
95
 
96
- /** Documentation, how a local override applies, and whether the element came from a seed model */
96
+ /** Documentation, how a local override applies, whether the element came from a seed model and the matter.js secret mark */
97
97
  const IGNORED_PROPERTIES = new Set([
98
98
  "tag",
99
99
  "name",
@@ -105,6 +105,7 @@ const IGNORED_PROPERTIES = new Set([
105
105
  "asOf",
106
106
  "until",
107
107
  "isSeed",
108
+ "isSecret",
108
109
  ]);
109
110
 
110
111
  /**
@@ -0,0 +1,147 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2026 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Logger } from "@matter/general";
8
+ import { Metatype } from "../common/Metatype.js";
9
+ import type { ClusterModel } from "../models/ClusterModel.js";
10
+ import type { ValueModel } from "../models/ValueModel.js";
11
+
12
+ /**
13
+ * Removes values marked {@link ValueModel.effectiveIsSecret} from data before it is logged.
14
+ *
15
+ * The redacting functions return their input unchanged while {@link Logger.redactSecrets} is false.
16
+ */
17
+ export namespace SecretRedaction {
18
+ /**
19
+ * The text that replaces each secret value in the output of {@link redact}.
20
+ */
21
+ export const PLACEHOLDER = "(redacted)";
22
+
23
+ const containsSecretCache = new WeakMap<ValueModel, boolean>();
24
+
25
+ /**
26
+ * Return {@link value} with every value that {@link model} marks as secret replaced by {@link PLACEHOLDER}.
27
+ *
28
+ * The result is a copy wherever a secret was replaced, so the secret is not reachable from it. The input is not
29
+ * modified. Without a model or without a secret in the model the input is returned as is. Properties the model
30
+ * does not define stay unchanged.
31
+ */
32
+ export function redact(model: ValueModel | undefined, value: unknown): unknown {
33
+ if (!Logger.redactSecrets || model === undefined || !containsSecret(model)) {
34
+ return value;
35
+ }
36
+ return redactValue(model, value);
37
+ }
38
+
39
+ /**
40
+ * {@link redact} for a single entry of the list {@link listModel} describes, such as an entry a chunked write
41
+ * appends. The entry is replaced if the list itself is secret.
42
+ */
43
+ export function redactEntry(listModel: ValueModel | undefined, entry: unknown): unknown {
44
+ if (Logger.redactSecrets && listModel?.effectiveIsSecret && entry !== undefined && entry !== null) {
45
+ return PLACEHOLDER;
46
+ }
47
+ return redact(listModel?.listEntry, entry);
48
+ }
49
+
50
+ /**
51
+ * {@link redact} for attribute values of {@link cluster} keyed by property name, such as the state of a cluster.
52
+ */
53
+ export function redactAttributes(cluster: ClusterModel, values: object): object {
54
+ const attributes = [...cluster.attributes];
55
+ if (!Logger.redactSecrets || !attributes.some(containsSecret)) {
56
+ return values;
57
+ }
58
+ return redactProperties(attributes, values);
59
+ }
60
+
61
+ /**
62
+ * Whether {@link model} or any of its members, at any depth, is secret.
63
+ *
64
+ * Results are cached per model, so a model must be marked secret before data of it is first redacted.
65
+ */
66
+ export function containsSecret(model: ValueModel): boolean {
67
+ let result = containsSecretCache.get(model);
68
+ if (result === undefined) {
69
+ result = searchSecret(model, new Set());
70
+ containsSecretCache.set(model, result);
71
+ }
72
+ return result;
73
+ }
74
+
75
+ function searchSecret(model: ValueModel, visiting: Set<ValueModel>): boolean {
76
+ if (model.effectiveIsSecret) {
77
+ return true;
78
+ }
79
+ if (visiting.has(model)) {
80
+ return false;
81
+ }
82
+ visiting.add(model);
83
+ for (const child of childModelsOf(model)) {
84
+ if (searchSecret(child, visiting)) {
85
+ return true;
86
+ }
87
+ }
88
+ return false;
89
+ }
90
+
91
+ function redactValue(model: ValueModel, value: unknown): unknown {
92
+ if (value === undefined || value === null) {
93
+ return value;
94
+ }
95
+
96
+ if (model.effectiveIsSecret) {
97
+ return PLACEHOLDER;
98
+ }
99
+
100
+ if (!containsSecret(model)) {
101
+ return value;
102
+ }
103
+
104
+ switch (model.effectiveMetatype) {
105
+ case Metatype.array: {
106
+ const entry = model.listEntry;
107
+ if (entry === undefined || !Array.isArray(value)) {
108
+ return value;
109
+ }
110
+ return value.map(item => redactValue(entry, item));
111
+ }
112
+
113
+ case Metatype.object: {
114
+ if (typeof value !== "object" || Array.isArray(value)) {
115
+ return value;
116
+ }
117
+ return redactProperties(model.members, value);
118
+ }
119
+ }
120
+
121
+ return value;
122
+ }
123
+
124
+ function redactProperties(members: Iterable<ValueModel>, value: object) {
125
+ const result: Record<string, unknown> = { ...value };
126
+ for (const member of members) {
127
+ const name = member.propertyName;
128
+ if (name in result) {
129
+ result[name] = redactValue(member, result[name]);
130
+ }
131
+ }
132
+ return result;
133
+ }
134
+
135
+ function childModelsOf(model: ValueModel): Iterable<ValueModel> {
136
+ switch (model.effectiveMetatype) {
137
+ case Metatype.array: {
138
+ const entry = model.listEntry;
139
+ return entry === undefined ? [] : [entry];
140
+ }
141
+
142
+ case Metatype.object:
143
+ return model.members;
144
+ }
145
+ return [];
146
+ }
147
+ }
@@ -5,7 +5,9 @@
5
5
  */
6
6
 
7
7
  import { FieldValue, Metatype } from "../common/index.js";
8
+ import { AttributeModel, ClusterModel } from "../models/index.js";
8
9
  import type { ValueModel } from "../models/ValueModel.js";
10
+ import { ClusterRevision } from "../standard/elements/definitions.js";
9
11
  import { DecodedBitmap } from "./DecodedBitmap.js";
10
12
  import { DefaultValue } from "./DefaultValue.js";
11
13
  import type { Scope } from "./Scope.js";
@@ -23,6 +25,11 @@ export function SelectDefaultValue(scope: Scope, member: ValueModel): unknown {
23
25
  return;
24
26
  }
25
27
 
28
+ // A cluster outside the standard model shares the global ClusterRevision, which states no default
29
+ if (member instanceof AttributeModel && member.id === ClusterRevision.id && scope.owner instanceof ClusterModel) {
30
+ return scope.owner.revision;
31
+ }
32
+
26
33
  return defaultValueForMetatype(scope, member);
27
34
  }
28
35
 
@@ -90,6 +90,7 @@ export class ValueValidator<T extends ValueModel> extends ModelValidator<T> {
90
90
  this.validateProperty({ name: "access", type: Access });
91
91
  this.validateProperty({ name: "quality", type: Quality });
92
92
  this.validateProperty({ name: "metatype", type: Metatype });
93
+ this.validateProperty({ name: "isSecret", type: "boolean" });
93
94
 
94
95
  this.#validateAspect("conformance");
95
96
  this.model.conformance.validateReferences(this, name => this.resolveReference(name));
@@ -21,6 +21,7 @@ export * from "./ModelVariantTraversal.js";
21
21
  export * from "./RequirementApplicability.js";
22
22
  export * from "./RequirementResolver.js";
23
23
  export * from "./Scope.js";
24
+ export * from "./SecretRedaction.js";
24
25
  export * from "./SelectDefaultValue.js";
25
26
  export * from "./ValidateModel.js";
26
27
  import "./definition-validation/index.js";
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import { Access } from "../aspects/Access.js";
8
+ import { Metatype } from "../common/Metatype.js";
8
9
  import { AttributeElement } from "../elements/index.js";
9
10
  import { Model } from "./Model.js";
10
11
  import { PropertyModel } from "./PropertyModel.js";
@@ -31,6 +32,17 @@ export class AttributeModel extends PropertyModel<AttributeElement> implements A
31
32
  return fabric === Access.Fabric.Scoped || fabric === Access.Fabric.Sensitive;
32
33
  }
33
34
 
35
+ /**
36
+ * Whether the attribute is a fabric-scoped list: a list with fabric-scoped (`F`) or fabric-sensitive (`S`) access.
37
+ *
38
+ * @see {@link MatterSpecification.v161.Core} § 7.6.4.1
39
+ * @see {@link MatterSpecification.v161.Core} § 7.6.5.1
40
+ * @see {@link MatterSpecification.v161.Core} § 7.19.1.8.1
41
+ */
42
+ override get fabricScopedList() {
43
+ return this.fabricScoped && this.effectiveMetatype === Metatype.array;
44
+ }
45
+
34
46
  /**
35
47
  * Whether the attribute is fabric-sensitive; a read returns only the accessing fabric's entries of its list.
36
48
  *
@@ -27,6 +27,7 @@ export abstract class ValueModel<T extends ValueElement = ValueElement>
27
27
  byteSize?: ValueElement.ByteSize;
28
28
  default?: FieldValue;
29
29
  metatype?: Metatype;
30
+ isSecret?: boolean;
30
31
  override isType? = true;
31
32
 
32
33
  #constraint: Constraint;
@@ -74,6 +75,19 @@ export abstract class ValueModel<T extends ValueElement = ValueElement>
74
75
  return new ModelTraversal().findAspect(this, "quality", Quality) ?? this.#quality;
75
76
  }
76
77
 
78
+ /**
79
+ * Whether this model or a model in its {@link base} chain is marked {@link ValueElement.isSecret}. The chain
80
+ * includes the field a derived cluster's field shadows if both have the same type or the derived field has none.
81
+ */
82
+ get effectiveIsSecret(): boolean {
83
+ for (let model: ValueModel | undefined = this; model !== undefined; model = model.base) {
84
+ if (model.isSecret) {
85
+ return true;
86
+ }
87
+ }
88
+ return false;
89
+ }
90
+
77
91
  get fields() {
78
92
  return Scope(this).membersOf(this, { tags: [ElementTag.Field] }) as ModelIndex<FieldModel>;
79
93
  }
@@ -152,6 +166,19 @@ export abstract class ValueModel<T extends ValueElement = ValueElement>
152
166
  return new ModelTraversal().findDefiningModel(this);
153
167
  }
154
168
 
169
+ /**
170
+ * Whether the value is a list whose entries a session of one fabric may see filtered by its fabric: a list with
171
+ * fabric-scoped (`F`) access. An `AttributeModel` also counts fabric-sensitive (`S`) access, which on a
172
+ * struct field only hides that field from other fabrics.
173
+ *
174
+ * @see {@link MatterSpecification.v161.Core} § 7.6.4.1
175
+ * @see {@link MatterSpecification.v161.Core} § 7.6.5.1
176
+ * @see {@link MatterSpecification.v161.Core} § 7.19.1.8.1
177
+ */
178
+ get fabricScopedList() {
179
+ return this.effectiveAccess.fabric === Access.Fabric.Scoped && this.effectiveMetatype === Metatype.array;
180
+ }
181
+
155
182
  /**
156
183
  * Get the entry type for lists, if any.
157
184
  */
@@ -320,6 +347,7 @@ export abstract class ValueModel<T extends ValueElement = ValueElement>
320
347
 
321
348
  this.byteSize = definition.byteSize;
322
349
  this.default = definition.default;
350
+ this.isSecret = definition.isSecret;
323
351
  this.#constraint = Constraint.create(definition.constraint);
324
352
  this.#conformance = Conformance.create(definition.conformance);
325
353
  this.#access = Access.create(definition.access);
@@ -336,6 +364,7 @@ export abstract class ValueModel<T extends ValueElement = ValueElement>
336
364
  return super.toElement(omitResources, {
337
365
  byteSize: this.byteSize,
338
366
  default: this.default,
367
+ isSecret: this.isSecret,
339
368
  constraint: this.#constraint.valueOf(),
340
369
  conformance: this.#conformance.valueOf(),
341
370
  access: this.#access.valueOf(),
@@ -33,13 +33,13 @@ export const AccountLogin = Cluster(
33
33
 
34
34
  Command(
35
35
  { name: "GetSetupPinResponse", id: 0x1, access: "F", conformance: "M", direction: "response" },
36
- Field({ name: "SetupPin", id: 0x0, type: "string", conformance: "M", constraint: "desc" })
36
+ Field({ name: "SetupPin", id: 0x0, type: "string", conformance: "M", constraint: "desc", isSecret: true })
37
37
  ),
38
38
 
39
39
  Command(
40
40
  { name: "Login", id: 0x2, access: "F A T", conformance: "M", direction: "request", response: "status" },
41
41
  Field({ name: "TempAccountIdentifier", id: 0x0, type: "string", conformance: "M", constraint: "16 to 100" }),
42
- Field({ name: "SetupPin", id: 0x1, type: "string", conformance: "M", constraint: "min 8" }),
42
+ Field({ name: "SetupPin", id: 0x1, type: "string", conformance: "M", constraint: "min 8", isSecret: true }),
43
43
  Field({ name: "Node", id: 0x2, type: "node-id", conformance: "O" })
44
44
  ),
45
45
 
@@ -32,7 +32,7 @@ export const AdministratorCommissioning = Cluster(
32
32
  response: "status"
33
33
  },
34
34
  Field({ name: "CommissioningTimeout", id: 0x0, type: "uint16", conformance: "M", constraint: "desc" }),
35
- Field({ name: "PakePasscodeVerifier", id: 0x1, type: "octstr", conformance: "M", constraint: "97" }),
35
+ Field({ name: "PakePasscodeVerifier", id: 0x1, type: "octstr", conformance: "M", constraint: "97", isSecret: true }),
36
36
  Field({ name: "Discriminator", id: 0x2, type: "uint16", conformance: "M", constraint: "0 to 4095" }),
37
37
  Field({ name: "Iterations", id: 0x3, type: "uint32", conformance: "M", constraint: "1000 to 100000" }),
38
38
  Field({ name: "Salt", id: 0x4, type: "octstr", conformance: "M", constraint: "16 to 32" })
@@ -58,7 +58,7 @@ export const CommissionerControl = Cluster(
58
58
  Command(
59
59
  { name: "ReverseOpenCommissioningWindow", id: 0x2, conformance: "M", direction: "response" },
60
60
  Field({ name: "CommissioningTimeout", id: 0x0, type: "uint16", conformance: "M", constraint: "desc" }),
61
- Field({ name: "PakePasscodeVerifier", id: 0x1, type: "octstr", conformance: "M", constraint: "97" }),
61
+ Field({ name: "PakePasscodeVerifier", id: 0x1, type: "octstr", conformance: "M", constraint: "97", isSecret: true }),
62
62
  Field({ name: "Discriminator", id: 0x2, type: "uint16", conformance: "M", constraint: "max 4095" }),
63
63
  Field({ name: "Iterations", id: 0x3, type: "uint32", conformance: "M", constraint: "1000 to 100000" }),
64
64
  Field({ name: "Salt", id: 0x4, type: "octstr", conformance: "M", constraint: "16 to 32" })
@@ -76,19 +76,19 @@ export const ContentControl = Cluster(
76
76
  Event({ name: "EnteringBlockContentTimeWindow", id: 0x1, access: "V", conformance: "BTW", priority: "info" }),
77
77
  Command(
78
78
  { name: "UpdatePin", id: 0x0, access: "M T", conformance: "PM", direction: "request", response: "status" },
79
- Field({ name: "OldPin", id: 0x0, type: "string", conformance: "M", constraint: "max 6" }),
80
- Field({ name: "NewPin", id: 0x1, type: "string", conformance: "M", constraint: "max 6" })
79
+ Field({ name: "OldPin", id: 0x0, type: "string", conformance: "M", constraint: "max 6", isSecret: true }),
80
+ Field({ name: "NewPin", id: 0x1, type: "string", conformance: "M", constraint: "max 6", isSecret: true })
81
81
  ),
82
82
  Command({ name: "ResetPin", id: 0x1, access: "A T", conformance: "PM", direction: "request", response: "ResetPinResponse" }),
83
83
  Command(
84
84
  { name: "ResetPinResponse", id: 0x2, conformance: "PM", direction: "response" },
85
- Field({ name: "PinCode", id: 0x0, type: "string", conformance: "M", constraint: "max 6" })
85
+ Field({ name: "PinCode", id: 0x0, type: "string", conformance: "M", constraint: "max 6", isSecret: true })
86
86
  ),
87
87
  Command({ name: "Enable", id: 0x3, access: "M T", conformance: "M", direction: "request", response: "status" }),
88
88
  Command({ name: "Disable", id: 0x4, access: "M T", conformance: "M", direction: "request", response: "status" }),
89
89
  Command(
90
90
  { name: "AddBonusTime", id: 0x5, access: "O", conformance: "ST", direction: "request", response: "status" },
91
- Field({ name: "PinCode", id: 0x0, type: "string", conformance: "O", constraint: "max 6" }),
91
+ Field({ name: "PinCode", id: 0x0, type: "string", conformance: "O", constraint: "max 6", isSecret: true }),
92
92
  Field({ name: "BonusTime", id: 0x1, type: "elapsed-s", conformance: "M", constraint: "desc", default: 300 })
93
93
  ),
94
94
 
@@ -148,7 +148,7 @@ export const DoorLock = Cluster(
148
148
 
149
149
  Attribute({
150
150
  name: "AliroGroupResolvingKey", id: 0x84, type: "octstr", access: "R A", conformance: "ALBU",
151
- constraint: "16", quality: "X"
151
+ constraint: "16", isSecret: true, quality: "X"
152
152
  }),
153
153
 
154
154
  Attribute(
@@ -228,11 +228,11 @@ export const DoorLock = Cluster(
228
228
 
229
229
  Command(
230
230
  { name: "LockDoor", id: 0x0, access: "O T", conformance: "M", direction: "request", response: "status" },
231
- Field({ name: "PinCode", id: 0x0, type: "octstr", conformance: "[COTA & PIN]" })
231
+ Field({ name: "PinCode", id: 0x0, type: "octstr", conformance: "[COTA & PIN]", isSecret: true })
232
232
  ),
233
233
  Command(
234
234
  { name: "UnlockDoor", id: 0x1, access: "O T", conformance: "M", direction: "request", response: "status" },
235
- Field({ name: "PinCode", id: 0x0, type: "octstr", conformance: "[COTA & PIN]" })
235
+ Field({ name: "PinCode", id: 0x0, type: "octstr", conformance: "[COTA & PIN]", isSecret: true })
236
236
  ),
237
237
  Command({ name: "Toggle", id: 0x2, access: "O T", conformance: "X", direction: "request", response: "status" }),
238
238
 
@@ -242,7 +242,7 @@ export const DoorLock = Cluster(
242
242
  response: "status"
243
243
  },
244
244
  Field({ name: "Timeout", id: 0x0, type: "uint16", conformance: "M" }),
245
- Field({ name: "PinCode", id: 0x1, type: "octstr", conformance: "[COTA & PIN]" })
245
+ Field({ name: "PinCode", id: 0x1, type: "octstr", conformance: "[COTA & PIN]", isSecret: true })
246
246
  ),
247
247
 
248
248
  Command(
@@ -501,7 +501,7 @@ export const DoorLock = Cluster(
501
501
  },
502
502
  Field({ name: "OperationType", id: 0x0, type: "DataOperationTypeEnum", conformance: "M", constraint: "add, modify" }),
503
503
  Field({ name: "Credential", id: 0x1, type: "CredentialStruct", conformance: "M" }),
504
- Field({ name: "CredentialData", id: 0x2, type: "octstr", conformance: "M", constraint: "desc" }),
504
+ Field({ name: "CredentialData", id: 0x2, type: "octstr", conformance: "M", constraint: "desc", isSecret: true }),
505
505
  Field({
506
506
  name: "UserIndex", id: 0x3, type: "uint16", conformance: "M",
507
507
  constraint: "1 to numberOfTotalUsersSupported", quality: "X"
@@ -558,7 +558,7 @@ export const DoorLock = Cluster(
558
558
 
559
559
  Command(
560
560
  { name: "UnboltDoor", id: 0x27, access: "O T", conformance: "UBOLT", direction: "request", response: "status" },
561
- Field({ name: "PinCode", id: 0x0, type: "octstr", conformance: "[COTA & PIN]" })
561
+ Field({ name: "PinCode", id: 0x0, type: "octstr", conformance: "[COTA & PIN]", isSecret: true })
562
562
  ),
563
563
 
564
564
  Command(
@@ -566,10 +566,10 @@ export const DoorLock = Cluster(
566
566
  name: "SetAliroReaderConfig", id: 0x28, access: "A T", conformance: "ALIRO", direction: "request",
567
567
  response: "status"
568
568
  },
569
- Field({ name: "SigningKey", id: 0x0, type: "octstr", conformance: "M", constraint: "32" }),
569
+ Field({ name: "SigningKey", id: 0x0, type: "octstr", conformance: "M", constraint: "32", isSecret: true }),
570
570
  Field({ name: "VerificationKey", id: 0x1, type: "octstr", conformance: "M", constraint: "65" }),
571
571
  Field({ name: "GroupIdentifier", id: 0x2, type: "octstr", conformance: "M", constraint: "16" }),
572
- Field({ name: "GroupResolvingKey", id: 0x3, type: "octstr", conformance: "ALBU", constraint: "16" })
572
+ Field({ name: "GroupResolvingKey", id: 0x3, type: "octstr", conformance: "ALBU", constraint: "16", isSecret: true })
573
573
  ),
574
574
 
575
575
  Command({
@@ -92,7 +92,7 @@ export const GeneralDiagnostics = Cluster(
92
92
  ),
93
93
  Command(
94
94
  { name: "TestEventTrigger", id: 0x0, access: "M", conformance: "M", direction: "request", response: "status" },
95
- Field({ name: "EnableKey", id: 0x0, type: "octstr", conformance: "M", constraint: "16" }),
95
+ Field({ name: "EnableKey", id: 0x0, type: "octstr", conformance: "M", constraint: "16", isSecret: true }),
96
96
  Field({ name: "EventTrigger", id: 0x1, type: "uint64", conformance: "M" })
97
97
  ),
98
98
  Command({
@@ -110,7 +110,7 @@ export const GeneralDiagnostics = Cluster(
110
110
  name: "PayloadTestRequest", id: 0x3, access: "M", conformance: "DMTEST", direction: "request",
111
111
  response: "PayloadTestResponse"
112
112
  },
113
- Field({ name: "EnableKey", id: 0x0, type: "octstr", conformance: "M", constraint: "16" }),
113
+ Field({ name: "EnableKey", id: 0x0, type: "octstr", conformance: "M", constraint: "16", isSecret: true }),
114
114
  Field({ name: "Value", id: 0x1, type: "uint8", conformance: "M" }),
115
115
  Field({ name: "Count", id: 0x2, type: "uint16", conformance: "M", constraint: "max 2048" })
116
116
  ),
@@ -114,11 +114,20 @@ export const GroupKeyManagement = Cluster(
114
114
  { name: "GroupKeySetStruct", type: "struct" },
115
115
  Field({ name: "GroupKeySetId", id: 0x0, type: "uint16", access: "F", conformance: "M" }),
116
116
  Field({ name: "GroupKeySecurityPolicy", id: 0x1, type: "GroupKeySecurityPolicyEnum", access: "F", conformance: "M" }),
117
- Field({ name: "EpochKey0", id: 0x2, type: "octstr", access: "F", conformance: "M", constraint: "16", quality: "X" }),
117
+ Field({
118
+ name: "EpochKey0", id: 0x2, type: "octstr", access: "F", conformance: "M", constraint: "16",
119
+ isSecret: true, quality: "X"
120
+ }),
118
121
  Field({ name: "EpochStartTime0", id: 0x3, type: "epoch-us", access: "F", conformance: "M", quality: "X" }),
119
- Field({ name: "EpochKey1", id: 0x4, type: "octstr", access: "F", conformance: "M", constraint: "16", quality: "X" }),
122
+ Field({
123
+ name: "EpochKey1", id: 0x4, type: "octstr", access: "F", conformance: "M", constraint: "16",
124
+ isSecret: true, quality: "X"
125
+ }),
120
126
  Field({ name: "EpochStartTime1", id: 0x5, type: "epoch-us", access: "F", conformance: "M", quality: "X" }),
121
- Field({ name: "EpochKey2", id: 0x6, type: "octstr", access: "F", conformance: "M", constraint: "16", quality: "X" }),
127
+ Field({
128
+ name: "EpochKey2", id: 0x6, type: "octstr", access: "F", conformance: "M", constraint: "16",
129
+ isSecret: true, quality: "X"
130
+ }),
122
131
  Field({ name: "EpochStartTime2", id: 0x7, type: "epoch-us", access: "F", conformance: "M", quality: "X" }),
123
132
  Field({
124
133
  name: "GroupKeyMulticastPolicy", id: 0x8, type: "GroupKeyMulticastPolicyEnum", access: "F",
@@ -67,7 +67,7 @@ export const Groupcast = Cluster(
67
67
  Field({ name: "entry", type: "endpoint-no" })
68
68
  ),
69
69
  Field({ name: "KeySetId", id: 0x2, type: "uint16", conformance: "M", constraint: "min 1" }),
70
- Field({ name: "Key", id: 0x3, type: "octstr", conformance: "O", constraint: "16" }),
70
+ Field({ name: "Key", id: 0x3, type: "octstr", conformance: "O", constraint: "16", isSecret: true }),
71
71
  Field({ name: "UseAuxiliaryAcl", id: 0x4, type: "bool", conformance: "[LN]" }),
72
72
  Field({ name: "ReplaceEndpoints", id: 0x5, type: "bool", conformance: "[LN]" }),
73
73
  Field({ name: "McastAddrPolicy", id: 0x6, type: "MulticastAddrPolicyEnum", conformance: "O" })
@@ -98,7 +98,7 @@ export const Groupcast = Cluster(
98
98
  { name: "UpdateGroupKey", id: 0x3, access: "F M", conformance: "M", direction: "request", response: "status" },
99
99
  Field({ name: "GroupId", id: 0x0, type: "group-id", conformance: "M", constraint: "min 1" }),
100
100
  Field({ name: "KeySetId", id: 0x1, type: "uint16", conformance: "M", constraint: "min 1" }),
101
- Field({ name: "Key", id: 0x2, type: "octstr", conformance: "O", constraint: "16" })
101
+ Field({ name: "Key", id: 0x2, type: "octstr", conformance: "O", constraint: "16", isSecret: true })
102
102
  ),
103
103
 
104
104
  Command(