@metamask/permission-controller 12.1.1 → 12.2.0

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 (46) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/dist/Caveat.cjs.map +1 -1
  3. package/dist/Caveat.mjs.map +1 -1
  4. package/dist/PermissionController.cjs +406 -642
  5. package/dist/PermissionController.cjs.map +1 -1
  6. package/dist/PermissionController.d.cts +8 -268
  7. package/dist/PermissionController.d.cts.map +1 -1
  8. package/dist/PermissionController.d.mts +8 -268
  9. package/dist/PermissionController.d.mts.map +1 -1
  10. package/dist/PermissionController.mjs +406 -642
  11. package/dist/PermissionController.mjs.map +1 -1
  12. package/dist/SubjectMetadataController.cjs +42 -40
  13. package/dist/SubjectMetadataController.cjs.map +1 -1
  14. package/dist/SubjectMetadataController.d.cts +1 -17
  15. package/dist/SubjectMetadataController.d.cts.map +1 -1
  16. package/dist/SubjectMetadataController.d.mts +1 -17
  17. package/dist/SubjectMetadataController.d.mts.map +1 -1
  18. package/dist/SubjectMetadataController.mjs +42 -40
  19. package/dist/SubjectMetadataController.mjs.map +1 -1
  20. package/dist/errors.cjs +8 -7
  21. package/dist/errors.cjs.map +1 -1
  22. package/dist/errors.d.cts +4 -9
  23. package/dist/errors.d.cts.map +1 -1
  24. package/dist/errors.d.mts +4 -9
  25. package/dist/errors.d.mts.map +1 -1
  26. package/dist/errors.mjs +1 -0
  27. package/dist/errors.mjs.map +1 -1
  28. package/dist/permission-middleware.cjs +1 -1
  29. package/dist/permission-middleware.cjs.map +1 -1
  30. package/dist/permission-middleware.d.cts +4 -3
  31. package/dist/permission-middleware.d.cts.map +1 -1
  32. package/dist/permission-middleware.d.mts +4 -3
  33. package/dist/permission-middleware.d.mts.map +1 -1
  34. package/dist/permission-middleware.mjs +1 -1
  35. package/dist/permission-middleware.mjs.map +1 -1
  36. package/dist/rpc-methods/revokePermissions.cjs.map +1 -1
  37. package/dist/rpc-methods/revokePermissions.d.cts +1 -1
  38. package/dist/rpc-methods/revokePermissions.d.cts.map +1 -1
  39. package/dist/rpc-methods/revokePermissions.d.mts +1 -1
  40. package/dist/rpc-methods/revokePermissions.d.mts.map +1 -1
  41. package/dist/rpc-methods/revokePermissions.mjs.map +1 -1
  42. package/dist/utils.cjs.map +1 -1
  43. package/dist/utils.d.cts.map +1 -1
  44. package/dist/utils.d.mts.map +1 -1
  45. package/dist/utils.mjs.map +1 -1
  46. package/package.json +4 -7
package/CHANGELOG.md CHANGED
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [12.2.0]
11
+
12
+ ### Added
13
+
14
+ - Add `PermissionController:getCaveat` action ([#7303](https://github.com/MetaMask/core/pull/7303))
15
+
16
+ ### Changed
17
+
18
+ - Upgrade `@metamask/utils` from `^11.8.1` to `^11.9.0` ([#7511](https://github.com/MetaMask/core/pull/7511))
19
+ - Move peer dependencies for controller and service packages to direct dependencies ([#7209](https://github.com/MetaMask/core/pull/7209))
20
+ - The dependencies moved are:
21
+ - `@metamask/approval-controller` (^8.0.0)
22
+ - In clients, it is now possible for multiple versions of these packages to exist in the dependency tree.
23
+ - For example, this scenario would be valid: a client relies on `@metamask/controller-a` 1.0.0 and `@metamask/controller-b` 1.0.0, and `@metamask/controller-b` depends on `@metamask/controller-a` 1.1.0.
24
+ - Note, however, that the versions specified in the client's `package.json` always "win", and you are expected to keep them up to date so as not to break controller and service intercommunication.
25
+ - Bump `@metamask/controller-utils` from `^11.16.0` to `^11.17.0` ([#7534](https://github.com/MetaMask/core/pull/7534))
26
+
10
27
  ## [12.1.1]
11
28
 
12
29
  ### Changed
@@ -372,7 +389,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
372
389
 
373
390
  All changes listed after this point were applied to this package following the monorepo conversion.
374
391
 
375
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/permission-controller@12.1.1...HEAD
392
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/permission-controller@12.2.0...HEAD
393
+ [12.2.0]: https://github.com/MetaMask/core/compare/@metamask/permission-controller@12.1.1...@metamask/permission-controller@12.2.0
376
394
  [12.1.1]: https://github.com/MetaMask/core/compare/@metamask/permission-controller@12.1.0...@metamask/permission-controller@12.1.1
377
395
  [12.1.0]: https://github.com/MetaMask/core/compare/@metamask/permission-controller@12.0.0...@metamask/permission-controller@12.1.0
378
396
  [12.0.0]: https://github.com/MetaMask/core/compare/@metamask/permission-controller@11.1.1...@metamask/permission-controller@12.0.0
@@ -1 +1 @@
1
- {"version":3,"file":"Caveat.cjs","sourceRoot":"","sources":["../src/Caveat.ts"],"names":[],"mappings":";;;AACA,2CAA8C;AAE9C,yCAGkB;AAOlB,iDAA8C;AA+Q9C;;;;;GAKG;AACH,SAAgB,qCAAqC,CACnD,aAA4C;IAE5C,OAAO,IAAA,mBAAW,EAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AACjD,CAAC;AAJD,sFAIC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,mBAAmB,CAGjC,oBAAwE,EACxE,UAA0C,EAAE,iCAAiC;AAC7E,oBAAkE;IAElE,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;IAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,IAAI,SAAS,GAAG,KAAK,EACnB,IAAuE,EACvE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAEhC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,aAAa,GACjB,oBAAoB,CAAC,MAAM,CAAC,IAAoC,CAAC,CAAC;QACpE,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,oCAA2B,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,CAAC,qCAAqC,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1D,MAAM,IAAI,yCAAgC,CACxC,aAAa,EACb,2BAAc,CAAC,gBAAgB,CAChC,CAAC;QACJ,CAAC;QACD,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAjCD,kDAiCC","sourcesContent":["import type { Json } from '@metamask/utils';\nimport { hasProperty } from '@metamask/utils';\n\nimport {\n CaveatSpecificationMismatchError,\n UnrecognizedCaveatTypeError,\n} from './errors';\nimport type {\n AsyncRestrictedMethod,\n RestrictedMethod,\n PermissionConstraint,\n RestrictedMethodParameters,\n} from './Permission';\nimport { PermissionType } from './Permission';\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { PermissionController } from './PermissionController';\n\nexport type CaveatConstraint = {\n /**\n * The type of the caveat. The type is presumed to be meaningful in the\n * context of the capability it is associated with.\n *\n * In MetaMask, every permission can only have one caveat of each type.\n */\n readonly type: string;\n\n /**\n * Any additional data necessary to enforce the caveat.\n */\n readonly value: Json;\n};\n\n/**\n * A `ZCAP-LD`-like caveat object. A caveat is associated with a particular\n * permission, and stored in its `caveats` array. Conceptually, a caveat is\n * an arbitrary attenuation of the authority granted by its associated\n * permission. It is the responsibility of the host to interpret and apply\n * the restriction represented by a caveat.\n *\n * @template Type - The type of the caveat.\n * @template Value - The value associated with the caveat.\n */\nexport type Caveat<Type extends string, Value extends Json> = {\n /**\n * The type of the caveat. The type is presumed to be meaningful in the\n * context of the capability it is associated with.\n *\n * In MetaMask, every permission can only have one caveat of each type.\n */\n readonly type: Type;\n\n /**\n * Any additional data necessary to enforce the caveat.\n */\n readonly value: Value;\n};\n\n// Next, we define types used for specifying caveats at the consumer layer,\n// and a function for applying caveats to a restricted method request. This is\n// Accomplished by decorating the restricted method implementation with the\n// the corresponding caveat functions.\n\n/**\n * A function for applying caveats to a restricted method request.\n *\n * @template ParentCaveat - The caveat type associated with this decorator.\n * @param decorated - The restricted method implementation to be decorated.\n * The method may have already been decorated with other caveats.\n * @param caveat - The caveat object.\n * @returns The decorated restricted method implementation.\n */\nexport type CaveatDecorator<ParentCaveat extends CaveatConstraint> = (\n decorated: AsyncRestrictedMethod<RestrictedMethodParameters, Json>,\n caveat: ParentCaveat,\n) => AsyncRestrictedMethod<RestrictedMethodParameters, Json>;\n\n/**\n * Extracts a caveat value type from a caveat decorator.\n *\n * @template Decorator - The {@link CaveatDecorator} to extract a caveat value\n * type from.\n */\ntype ExtractCaveatValueFromDecorator<\n Decorator extends CaveatDecorator<CaveatConstraint>,\n> = Decorator extends (\n decorated: AsyncRestrictedMethod<RestrictedMethodParameters, Json>,\n caveat: infer ParentCaveat,\n) => AsyncRestrictedMethod<RestrictedMethodParameters, Json>\n ? ParentCaveat extends CaveatConstraint\n ? ParentCaveat['value']\n : never\n : never;\n\n/**\n * A function for validating caveats of a particular type.\n *\n * @see `validator` in {@link CaveatSpecificationBase} for more details.\n * @template ParentCaveat - The caveat type associated with this validator.\n * @param caveat - The caveat object to validate.\n * @param origin - The origin associated with the parent permission.\n * @param target - The target of the parent permission.\n */\nexport type CaveatValidator<ParentCaveat extends CaveatConstraint> = (\n caveat: { type: ParentCaveat['type']; value: unknown },\n origin?: string,\n target?: string,\n) => void;\n\n/**\n * A map of caveat type strings to {@link CaveatDiff} values.\n */\nexport type CaveatDiffMap<ParentCaveat extends CaveatConstraint> = {\n [CaveatType in ParentCaveat['type']]: ParentCaveat['value'];\n};\n\n/**\n * A function that merges two caveat values of the same type. The values must be\n * merged in the fashion of a right-biased union.\n *\n * @see `ARCHITECTURE.md` for more details.\n * @template Value - The type of the values to merge.\n * @param leftValue - The left-hand value.\n * @param rightValue - The right-hand value.\n * @returns `[newValue, diff]`, i.e. the merged value and the diff between the left value\n * and the new value. The diff must be expressed in the same type as the value itself.\n */\nexport type CaveatValueMerger<Value extends Json> = (\n leftValue: Value,\n rightValue: Value,\n) => [Value, Value] | [];\n\nexport type CaveatSpecificationBase = {\n /**\n * The string type of the caveat.\n */\n type: string;\n\n /**\n * The validator function used to validate caveats of the associated type\n * whenever they are constructed or mutated.\n *\n * The validator should throw an appropriate JSON-RPC error if validation fails.\n *\n * If no validator is specified, no validation of caveat values will be\n * performed. In instances where caveats are mutated but a permission's caveat\n * array has not changed, any corresponding permission validator will not be\n * called. For this reason, permission validators **must not** be relied upon\n * to validate caveats.\n */\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n validator?: CaveatValidator<any>;\n\n /**\n * The merger function used to merge a pair of values of the associated caveat type\n * during incremental permission requests. The values must be merged in the fashion\n * of a right-biased union.\n *\n * @see `ARCHITECTURE.md` for more details.\n */\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n merger?: CaveatValueMerger<any>;\n};\n\nexport type RestrictedMethodCaveatSpecificationConstraint =\n CaveatSpecificationBase & {\n /**\n * The decorator function used to apply the caveat to restricted method\n * requests.\n */\n decorator: CaveatDecorator<CaveatConstraint>;\n };\n\nexport type EndowmentCaveatSpecificationConstraint = CaveatSpecificationBase;\n\n/**\n * The constraint for caveat specification objects. Every {@link Caveat}\n * supported by a {@link PermissionController} must have an associated\n * specification, which is the source of truth for all caveat-related types.\n * In addition, a caveat specification may include a decorator function used\n * to apply the caveat's attenuation to a restricted method. It may also include\n * a validator function specified by the consumer.\n *\n * See the README for more details.\n */\nexport type CaveatSpecificationConstraint =\n | RestrictedMethodCaveatSpecificationConstraint\n | EndowmentCaveatSpecificationConstraint;\n\n/**\n * Options for {@link CaveatSpecificationBuilder} functions.\n */\ntype CaveatSpecificationBuilderOptions<\n DecoratorHooks extends Record<string, unknown>,\n ValidatorHooks extends Record<string, unknown>,\n> = {\n type?: string;\n decoratorHooks?: DecoratorHooks;\n validatorHooks?: ValidatorHooks;\n};\n\n/**\n * A function that builds caveat specifications. Modules that specify caveats\n * for external consumption should make this their primary / default export so\n * that host applications can use them to generate concrete specifications\n * tailored to their requirements.\n */\nexport type CaveatSpecificationBuilder<\n Options extends CaveatSpecificationBuilderOptions<\n Record<string, unknown>,\n Record<string, unknown>\n >,\n Specification extends CaveatSpecificationConstraint,\n> = (options: Options) => Specification;\n\n/**\n * A caveat specification export object, containing the\n * {@link CaveatSpecificationBuilder} function and \"hook name\" objects.\n */\nexport type CaveatSpecificationBuilderExportConstraint = {\n specificationBuilder: CaveatSpecificationBuilder<\n CaveatSpecificationBuilderOptions<\n Record<string, unknown>,\n Record<string, unknown>\n >,\n CaveatSpecificationConstraint\n >;\n decoratorHookNames?: Record<string, true>;\n validatorHookNames?: Record<string, true>;\n};\n\n/**\n * The specifications for all caveats supported by a particular\n * {@link PermissionController}.\n *\n * @template Specifications - The union of all {@link CaveatSpecificationConstraint} types.\n */\nexport type CaveatSpecificationMap<\n CaveatSpecification extends CaveatSpecificationConstraint,\n> = Record<CaveatSpecification['type'], CaveatSpecification>;\n\n/**\n * Extracts the union of all caveat types specified by the given\n * {@link CaveatSpecificationConstraint} type.\n *\n * @template CaveatSpecification - The {@link CaveatSpecificationConstraint} to extract a\n * caveat type union from.\n */\nexport type ExtractCaveats<\n CaveatSpecification extends CaveatSpecificationConstraint,\n> = CaveatSpecification extends RestrictedMethodCaveatSpecificationConstraint\n ? Caveat<\n CaveatSpecification['type'],\n ExtractCaveatValueFromDecorator<\n RestrictedMethodCaveatSpecificationConstraint['decorator']\n >\n >\n : Caveat<CaveatSpecification['type'], Json>;\n\n/**\n * Extracts the type of a specific {@link Caveat} from a union of caveat\n * specifications.\n *\n * @template CaveatSpecifications - The union of all caveat specifications.\n * @template CaveatType - The type of the caveat to extract.\n */\nexport type ExtractCaveat<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n CaveatType extends string,\n> = Extract<ExtractCaveats<CaveatSpecifications>, { type: CaveatType }>;\n\n/**\n * Extracts the value type of a specific {@link Caveat} from a union of caveat\n * specifications.\n *\n * @template CaveatSpecifications - The union of all caveat specifications.\n * @template CaveatType - The type of the caveat whose value to extract.\n */\nexport type ExtractCaveatValue<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n CaveatType extends string,\n> = ExtractCaveat<CaveatSpecifications, CaveatType>['value'];\n\n/**\n * Determines whether a caveat specification is a restricted method caveat specification.\n *\n * @param specification - The caveat specification.\n * @returns True if the caveat specification is a restricted method caveat specification, otherwise false.\n */\nexport function isRestrictedMethodCaveatSpecification(\n specification: CaveatSpecificationConstraint,\n): specification is RestrictedMethodCaveatSpecificationConstraint {\n return hasProperty(specification, 'decorator');\n}\n\n/**\n * Decorate a restricted method implementation with its caveats.\n *\n * Note that all caveat functions (i.e. the argument and return value of the\n * decorator) must be awaited.\n *\n * @param methodImplementation - The restricted method implementation\n * @param permission - The origin's potential permission\n * @param caveatSpecifications - All caveat implementations\n * @returns The decorated method implementation\n */\nexport function decorateWithCaveats<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n>(\n methodImplementation: RestrictedMethod<RestrictedMethodParameters, Json>,\n permission: Readonly<PermissionConstraint>, // bound to the requesting origin\n caveatSpecifications: CaveatSpecificationMap<CaveatSpecifications>, // all caveat implementations\n): RestrictedMethod<RestrictedMethodParameters, Json> {\n const { caveats } = permission;\n if (!caveats) {\n return methodImplementation;\n }\n\n let decorated = async (\n args: Parameters<RestrictedMethod<RestrictedMethodParameters, Json>>[0],\n ) => methodImplementation(args);\n\n for (const caveat of caveats) {\n const specification =\n caveatSpecifications[caveat.type as CaveatSpecifications['type']];\n if (!specification) {\n throw new UnrecognizedCaveatTypeError(caveat.type);\n }\n\n if (!isRestrictedMethodCaveatSpecification(specification)) {\n throw new CaveatSpecificationMismatchError(\n specification,\n PermissionType.RestrictedMethod,\n );\n }\n decorated = specification.decorator(decorated, caveat);\n }\n\n return decorated;\n}\n"]}
1
+ {"version":3,"file":"Caveat.cjs","sourceRoot":"","sources":["../src/Caveat.ts"],"names":[],"mappings":";;;AACA,2CAA8C;AAE9C,yCAGkB;AAOlB,iDAA8C;AA+Q9C;;;;;GAKG;AACH,SAAgB,qCAAqC,CACnD,aAA4C;IAE5C,OAAO,IAAA,mBAAW,EAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AACjD,CAAC;AAJD,sFAIC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,mBAAmB,CAGjC,oBAAwE,EACxE,UAA0C,EAAE,iCAAiC;AAC7E,oBAAkE;IAElE,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;IAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,IAAI,SAAS,GAAG,KAAK,EACnB,IAAuE,EACxD,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAE/C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,aAAa,GACjB,oBAAoB,CAAC,MAAM,CAAC,IAAoC,CAAC,CAAC;QACpE,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,oCAA2B,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,CAAC,qCAAqC,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1D,MAAM,IAAI,yCAAgC,CACxC,aAAa,EACb,2BAAc,CAAC,gBAAgB,CAChC,CAAC;QACJ,CAAC;QACD,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAjCD,kDAiCC","sourcesContent":["import type { Json } from '@metamask/utils';\nimport { hasProperty } from '@metamask/utils';\n\nimport {\n CaveatSpecificationMismatchError,\n UnrecognizedCaveatTypeError,\n} from './errors';\nimport type {\n AsyncRestrictedMethod,\n RestrictedMethod,\n PermissionConstraint,\n RestrictedMethodParameters,\n} from './Permission';\nimport { PermissionType } from './Permission';\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { PermissionController } from './PermissionController';\n\nexport type CaveatConstraint = {\n /**\n * The type of the caveat. The type is presumed to be meaningful in the\n * context of the capability it is associated with.\n *\n * In MetaMask, every permission can only have one caveat of each type.\n */\n readonly type: string;\n\n /**\n * Any additional data necessary to enforce the caveat.\n */\n readonly value: Json;\n};\n\n/**\n * A `ZCAP-LD`-like caveat object. A caveat is associated with a particular\n * permission, and stored in its `caveats` array. Conceptually, a caveat is\n * an arbitrary attenuation of the authority granted by its associated\n * permission. It is the responsibility of the host to interpret and apply\n * the restriction represented by a caveat.\n *\n * @template Type - The type of the caveat.\n * @template Value - The value associated with the caveat.\n */\nexport type Caveat<Type extends string, Value extends Json> = {\n /**\n * The type of the caveat. The type is presumed to be meaningful in the\n * context of the capability it is associated with.\n *\n * In MetaMask, every permission can only have one caveat of each type.\n */\n readonly type: Type;\n\n /**\n * Any additional data necessary to enforce the caveat.\n */\n readonly value: Value;\n};\n\n// Next, we define types used for specifying caveats at the consumer layer,\n// and a function for applying caveats to a restricted method request. This is\n// Accomplished by decorating the restricted method implementation with the\n// the corresponding caveat functions.\n\n/**\n * A function for applying caveats to a restricted method request.\n *\n * @template ParentCaveat - The caveat type associated with this decorator.\n * @param decorated - The restricted method implementation to be decorated.\n * The method may have already been decorated with other caveats.\n * @param caveat - The caveat object.\n * @returns The decorated restricted method implementation.\n */\nexport type CaveatDecorator<ParentCaveat extends CaveatConstraint> = (\n decorated: AsyncRestrictedMethod<RestrictedMethodParameters, Json>,\n caveat: ParentCaveat,\n) => AsyncRestrictedMethod<RestrictedMethodParameters, Json>;\n\n/**\n * Extracts a caveat value type from a caveat decorator.\n *\n * @template Decorator - The {@link CaveatDecorator} to extract a caveat value\n * type from.\n */\ntype ExtractCaveatValueFromDecorator<\n Decorator extends CaveatDecorator<CaveatConstraint>,\n> = Decorator extends (\n decorated: AsyncRestrictedMethod<RestrictedMethodParameters, Json>,\n caveat: infer ParentCaveat,\n) => AsyncRestrictedMethod<RestrictedMethodParameters, Json>\n ? ParentCaveat extends CaveatConstraint\n ? ParentCaveat['value']\n : never\n : never;\n\n/**\n * A function for validating caveats of a particular type.\n *\n * @see `validator` in {@link CaveatSpecificationBase} for more details.\n * @template ParentCaveat - The caveat type associated with this validator.\n * @param caveat - The caveat object to validate.\n * @param origin - The origin associated with the parent permission.\n * @param target - The target of the parent permission.\n */\nexport type CaveatValidator<ParentCaveat extends CaveatConstraint> = (\n caveat: { type: ParentCaveat['type']; value: unknown },\n origin?: string,\n target?: string,\n) => void;\n\n/**\n * A map of caveat type strings to {@link CaveatDiff} values.\n */\nexport type CaveatDiffMap<ParentCaveat extends CaveatConstraint> = {\n [CaveatType in ParentCaveat['type']]: ParentCaveat['value'];\n};\n\n/**\n * A function that merges two caveat values of the same type. The values must be\n * merged in the fashion of a right-biased union.\n *\n * @see `ARCHITECTURE.md` for more details.\n * @template Value - The type of the values to merge.\n * @param leftValue - The left-hand value.\n * @param rightValue - The right-hand value.\n * @returns `[newValue, diff]`, i.e. the merged value and the diff between the left value\n * and the new value. The diff must be expressed in the same type as the value itself.\n */\nexport type CaveatValueMerger<Value extends Json> = (\n leftValue: Value,\n rightValue: Value,\n) => [Value, Value] | [];\n\nexport type CaveatSpecificationBase = {\n /**\n * The string type of the caveat.\n */\n type: string;\n\n /**\n * The validator function used to validate caveats of the associated type\n * whenever they are constructed or mutated.\n *\n * The validator should throw an appropriate JSON-RPC error if validation fails.\n *\n * If no validator is specified, no validation of caveat values will be\n * performed. In instances where caveats are mutated but a permission's caveat\n * array has not changed, any corresponding permission validator will not be\n * called. For this reason, permission validators **must not** be relied upon\n * to validate caveats.\n */\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n validator?: CaveatValidator<any>;\n\n /**\n * The merger function used to merge a pair of values of the associated caveat type\n * during incremental permission requests. The values must be merged in the fashion\n * of a right-biased union.\n *\n * @see `ARCHITECTURE.md` for more details.\n */\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n merger?: CaveatValueMerger<any>;\n};\n\nexport type RestrictedMethodCaveatSpecificationConstraint =\n CaveatSpecificationBase & {\n /**\n * The decorator function used to apply the caveat to restricted method\n * requests.\n */\n decorator: CaveatDecorator<CaveatConstraint>;\n };\n\nexport type EndowmentCaveatSpecificationConstraint = CaveatSpecificationBase;\n\n/**\n * The constraint for caveat specification objects. Every {@link Caveat}\n * supported by a {@link PermissionController} must have an associated\n * specification, which is the source of truth for all caveat-related types.\n * In addition, a caveat specification may include a decorator function used\n * to apply the caveat's attenuation to a restricted method. It may also include\n * a validator function specified by the consumer.\n *\n * See the README for more details.\n */\nexport type CaveatSpecificationConstraint =\n | RestrictedMethodCaveatSpecificationConstraint\n | EndowmentCaveatSpecificationConstraint;\n\n/**\n * Options for {@link CaveatSpecificationBuilder} functions.\n */\ntype CaveatSpecificationBuilderOptions<\n DecoratorHooks extends Record<string, unknown>,\n ValidatorHooks extends Record<string, unknown>,\n> = {\n type?: string;\n decoratorHooks?: DecoratorHooks;\n validatorHooks?: ValidatorHooks;\n};\n\n/**\n * A function that builds caveat specifications. Modules that specify caveats\n * for external consumption should make this their primary / default export so\n * that host applications can use them to generate concrete specifications\n * tailored to their requirements.\n */\nexport type CaveatSpecificationBuilder<\n Options extends CaveatSpecificationBuilderOptions<\n Record<string, unknown>,\n Record<string, unknown>\n >,\n Specification extends CaveatSpecificationConstraint,\n> = (options: Options) => Specification;\n\n/**\n * A caveat specification export object, containing the\n * {@link CaveatSpecificationBuilder} function and \"hook name\" objects.\n */\nexport type CaveatSpecificationBuilderExportConstraint = {\n specificationBuilder: CaveatSpecificationBuilder<\n CaveatSpecificationBuilderOptions<\n Record<string, unknown>,\n Record<string, unknown>\n >,\n CaveatSpecificationConstraint\n >;\n decoratorHookNames?: Record<string, true>;\n validatorHookNames?: Record<string, true>;\n};\n\n/**\n * The specifications for all caveats supported by a particular\n * {@link PermissionController}.\n *\n * @template Specifications - The union of all {@link CaveatSpecificationConstraint} types.\n */\nexport type CaveatSpecificationMap<\n CaveatSpecification extends CaveatSpecificationConstraint,\n> = Record<CaveatSpecification['type'], CaveatSpecification>;\n\n/**\n * Extracts the union of all caveat types specified by the given\n * {@link CaveatSpecificationConstraint} type.\n *\n * @template CaveatSpecification - The {@link CaveatSpecificationConstraint} to extract a\n * caveat type union from.\n */\nexport type ExtractCaveats<\n CaveatSpecification extends CaveatSpecificationConstraint,\n> = CaveatSpecification extends RestrictedMethodCaveatSpecificationConstraint\n ? Caveat<\n CaveatSpecification['type'],\n ExtractCaveatValueFromDecorator<\n RestrictedMethodCaveatSpecificationConstraint['decorator']\n >\n >\n : Caveat<CaveatSpecification['type'], Json>;\n\n/**\n * Extracts the type of a specific {@link Caveat} from a union of caveat\n * specifications.\n *\n * @template CaveatSpecifications - The union of all caveat specifications.\n * @template CaveatType - The type of the caveat to extract.\n */\nexport type ExtractCaveat<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n CaveatType extends string,\n> = Extract<ExtractCaveats<CaveatSpecifications>, { type: CaveatType }>;\n\n/**\n * Extracts the value type of a specific {@link Caveat} from a union of caveat\n * specifications.\n *\n * @template CaveatSpecifications - The union of all caveat specifications.\n * @template CaveatType - The type of the caveat whose value to extract.\n */\nexport type ExtractCaveatValue<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n CaveatType extends string,\n> = ExtractCaveat<CaveatSpecifications, CaveatType>['value'];\n\n/**\n * Determines whether a caveat specification is a restricted method caveat specification.\n *\n * @param specification - The caveat specification.\n * @returns True if the caveat specification is a restricted method caveat specification, otherwise false.\n */\nexport function isRestrictedMethodCaveatSpecification(\n specification: CaveatSpecificationConstraint,\n): specification is RestrictedMethodCaveatSpecificationConstraint {\n return hasProperty(specification, 'decorator');\n}\n\n/**\n * Decorate a restricted method implementation with its caveats.\n *\n * Note that all caveat functions (i.e. the argument and return value of the\n * decorator) must be awaited.\n *\n * @param methodImplementation - The restricted method implementation\n * @param permission - The origin's potential permission\n * @param caveatSpecifications - All caveat implementations\n * @returns The decorated method implementation\n */\nexport function decorateWithCaveats<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n>(\n methodImplementation: RestrictedMethod<RestrictedMethodParameters, Json>,\n permission: Readonly<PermissionConstraint>, // bound to the requesting origin\n caveatSpecifications: CaveatSpecificationMap<CaveatSpecifications>, // all caveat implementations\n): RestrictedMethod<RestrictedMethodParameters, Json> {\n const { caveats } = permission;\n if (!caveats) {\n return methodImplementation;\n }\n\n let decorated = async (\n args: Parameters<RestrictedMethod<RestrictedMethodParameters, Json>>[0],\n ): Promise<Json> => methodImplementation(args);\n\n for (const caveat of caveats) {\n const specification =\n caveatSpecifications[caveat.type as CaveatSpecifications['type']];\n if (!specification) {\n throw new UnrecognizedCaveatTypeError(caveat.type);\n }\n\n if (!isRestrictedMethodCaveatSpecification(specification)) {\n throw new CaveatSpecificationMismatchError(\n specification,\n PermissionType.RestrictedMethod,\n );\n }\n decorated = specification.decorator(decorated, caveat);\n }\n\n return decorated;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Caveat.mjs","sourceRoot":"","sources":["../src/Caveat.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,wBAAwB;AAE9C,OAAO,EACL,gCAAgC,EAChC,2BAA2B,EAC5B,qBAAiB;AAOlB,OAAO,EAAE,cAAc,EAAE,yBAAqB;AA+Q9C;;;;;GAKG;AACH,MAAM,UAAU,qCAAqC,CACnD,aAA4C;IAE5C,OAAO,WAAW,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAGjC,oBAAwE,EACxE,UAA0C,EAAE,iCAAiC;AAC7E,oBAAkE;IAElE,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;IAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,IAAI,SAAS,GAAG,KAAK,EACnB,IAAuE,EACvE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAEhC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,aAAa,GACjB,oBAAoB,CAAC,MAAM,CAAC,IAAoC,CAAC,CAAC;QACpE,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,2BAA2B,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,CAAC,qCAAqC,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1D,MAAM,IAAI,gCAAgC,CACxC,aAAa,EACb,cAAc,CAAC,gBAAgB,CAChC,CAAC;QACJ,CAAC;QACD,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import type { Json } from '@metamask/utils';\nimport { hasProperty } from '@metamask/utils';\n\nimport {\n CaveatSpecificationMismatchError,\n UnrecognizedCaveatTypeError,\n} from './errors';\nimport type {\n AsyncRestrictedMethod,\n RestrictedMethod,\n PermissionConstraint,\n RestrictedMethodParameters,\n} from './Permission';\nimport { PermissionType } from './Permission';\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { PermissionController } from './PermissionController';\n\nexport type CaveatConstraint = {\n /**\n * The type of the caveat. The type is presumed to be meaningful in the\n * context of the capability it is associated with.\n *\n * In MetaMask, every permission can only have one caveat of each type.\n */\n readonly type: string;\n\n /**\n * Any additional data necessary to enforce the caveat.\n */\n readonly value: Json;\n};\n\n/**\n * A `ZCAP-LD`-like caveat object. A caveat is associated with a particular\n * permission, and stored in its `caveats` array. Conceptually, a caveat is\n * an arbitrary attenuation of the authority granted by its associated\n * permission. It is the responsibility of the host to interpret and apply\n * the restriction represented by a caveat.\n *\n * @template Type - The type of the caveat.\n * @template Value - The value associated with the caveat.\n */\nexport type Caveat<Type extends string, Value extends Json> = {\n /**\n * The type of the caveat. The type is presumed to be meaningful in the\n * context of the capability it is associated with.\n *\n * In MetaMask, every permission can only have one caveat of each type.\n */\n readonly type: Type;\n\n /**\n * Any additional data necessary to enforce the caveat.\n */\n readonly value: Value;\n};\n\n// Next, we define types used for specifying caveats at the consumer layer,\n// and a function for applying caveats to a restricted method request. This is\n// Accomplished by decorating the restricted method implementation with the\n// the corresponding caveat functions.\n\n/**\n * A function for applying caveats to a restricted method request.\n *\n * @template ParentCaveat - The caveat type associated with this decorator.\n * @param decorated - The restricted method implementation to be decorated.\n * The method may have already been decorated with other caveats.\n * @param caveat - The caveat object.\n * @returns The decorated restricted method implementation.\n */\nexport type CaveatDecorator<ParentCaveat extends CaveatConstraint> = (\n decorated: AsyncRestrictedMethod<RestrictedMethodParameters, Json>,\n caveat: ParentCaveat,\n) => AsyncRestrictedMethod<RestrictedMethodParameters, Json>;\n\n/**\n * Extracts a caveat value type from a caveat decorator.\n *\n * @template Decorator - The {@link CaveatDecorator} to extract a caveat value\n * type from.\n */\ntype ExtractCaveatValueFromDecorator<\n Decorator extends CaveatDecorator<CaveatConstraint>,\n> = Decorator extends (\n decorated: AsyncRestrictedMethod<RestrictedMethodParameters, Json>,\n caveat: infer ParentCaveat,\n) => AsyncRestrictedMethod<RestrictedMethodParameters, Json>\n ? ParentCaveat extends CaveatConstraint\n ? ParentCaveat['value']\n : never\n : never;\n\n/**\n * A function for validating caveats of a particular type.\n *\n * @see `validator` in {@link CaveatSpecificationBase} for more details.\n * @template ParentCaveat - The caveat type associated with this validator.\n * @param caveat - The caveat object to validate.\n * @param origin - The origin associated with the parent permission.\n * @param target - The target of the parent permission.\n */\nexport type CaveatValidator<ParentCaveat extends CaveatConstraint> = (\n caveat: { type: ParentCaveat['type']; value: unknown },\n origin?: string,\n target?: string,\n) => void;\n\n/**\n * A map of caveat type strings to {@link CaveatDiff} values.\n */\nexport type CaveatDiffMap<ParentCaveat extends CaveatConstraint> = {\n [CaveatType in ParentCaveat['type']]: ParentCaveat['value'];\n};\n\n/**\n * A function that merges two caveat values of the same type. The values must be\n * merged in the fashion of a right-biased union.\n *\n * @see `ARCHITECTURE.md` for more details.\n * @template Value - The type of the values to merge.\n * @param leftValue - The left-hand value.\n * @param rightValue - The right-hand value.\n * @returns `[newValue, diff]`, i.e. the merged value and the diff between the left value\n * and the new value. The diff must be expressed in the same type as the value itself.\n */\nexport type CaveatValueMerger<Value extends Json> = (\n leftValue: Value,\n rightValue: Value,\n) => [Value, Value] | [];\n\nexport type CaveatSpecificationBase = {\n /**\n * The string type of the caveat.\n */\n type: string;\n\n /**\n * The validator function used to validate caveats of the associated type\n * whenever they are constructed or mutated.\n *\n * The validator should throw an appropriate JSON-RPC error if validation fails.\n *\n * If no validator is specified, no validation of caveat values will be\n * performed. In instances where caveats are mutated but a permission's caveat\n * array has not changed, any corresponding permission validator will not be\n * called. For this reason, permission validators **must not** be relied upon\n * to validate caveats.\n */\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n validator?: CaveatValidator<any>;\n\n /**\n * The merger function used to merge a pair of values of the associated caveat type\n * during incremental permission requests. The values must be merged in the fashion\n * of a right-biased union.\n *\n * @see `ARCHITECTURE.md` for more details.\n */\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n merger?: CaveatValueMerger<any>;\n};\n\nexport type RestrictedMethodCaveatSpecificationConstraint =\n CaveatSpecificationBase & {\n /**\n * The decorator function used to apply the caveat to restricted method\n * requests.\n */\n decorator: CaveatDecorator<CaveatConstraint>;\n };\n\nexport type EndowmentCaveatSpecificationConstraint = CaveatSpecificationBase;\n\n/**\n * The constraint for caveat specification objects. Every {@link Caveat}\n * supported by a {@link PermissionController} must have an associated\n * specification, which is the source of truth for all caveat-related types.\n * In addition, a caveat specification may include a decorator function used\n * to apply the caveat's attenuation to a restricted method. It may also include\n * a validator function specified by the consumer.\n *\n * See the README for more details.\n */\nexport type CaveatSpecificationConstraint =\n | RestrictedMethodCaveatSpecificationConstraint\n | EndowmentCaveatSpecificationConstraint;\n\n/**\n * Options for {@link CaveatSpecificationBuilder} functions.\n */\ntype CaveatSpecificationBuilderOptions<\n DecoratorHooks extends Record<string, unknown>,\n ValidatorHooks extends Record<string, unknown>,\n> = {\n type?: string;\n decoratorHooks?: DecoratorHooks;\n validatorHooks?: ValidatorHooks;\n};\n\n/**\n * A function that builds caveat specifications. Modules that specify caveats\n * for external consumption should make this their primary / default export so\n * that host applications can use them to generate concrete specifications\n * tailored to their requirements.\n */\nexport type CaveatSpecificationBuilder<\n Options extends CaveatSpecificationBuilderOptions<\n Record<string, unknown>,\n Record<string, unknown>\n >,\n Specification extends CaveatSpecificationConstraint,\n> = (options: Options) => Specification;\n\n/**\n * A caveat specification export object, containing the\n * {@link CaveatSpecificationBuilder} function and \"hook name\" objects.\n */\nexport type CaveatSpecificationBuilderExportConstraint = {\n specificationBuilder: CaveatSpecificationBuilder<\n CaveatSpecificationBuilderOptions<\n Record<string, unknown>,\n Record<string, unknown>\n >,\n CaveatSpecificationConstraint\n >;\n decoratorHookNames?: Record<string, true>;\n validatorHookNames?: Record<string, true>;\n};\n\n/**\n * The specifications for all caveats supported by a particular\n * {@link PermissionController}.\n *\n * @template Specifications - The union of all {@link CaveatSpecificationConstraint} types.\n */\nexport type CaveatSpecificationMap<\n CaveatSpecification extends CaveatSpecificationConstraint,\n> = Record<CaveatSpecification['type'], CaveatSpecification>;\n\n/**\n * Extracts the union of all caveat types specified by the given\n * {@link CaveatSpecificationConstraint} type.\n *\n * @template CaveatSpecification - The {@link CaveatSpecificationConstraint} to extract a\n * caveat type union from.\n */\nexport type ExtractCaveats<\n CaveatSpecification extends CaveatSpecificationConstraint,\n> = CaveatSpecification extends RestrictedMethodCaveatSpecificationConstraint\n ? Caveat<\n CaveatSpecification['type'],\n ExtractCaveatValueFromDecorator<\n RestrictedMethodCaveatSpecificationConstraint['decorator']\n >\n >\n : Caveat<CaveatSpecification['type'], Json>;\n\n/**\n * Extracts the type of a specific {@link Caveat} from a union of caveat\n * specifications.\n *\n * @template CaveatSpecifications - The union of all caveat specifications.\n * @template CaveatType - The type of the caveat to extract.\n */\nexport type ExtractCaveat<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n CaveatType extends string,\n> = Extract<ExtractCaveats<CaveatSpecifications>, { type: CaveatType }>;\n\n/**\n * Extracts the value type of a specific {@link Caveat} from a union of caveat\n * specifications.\n *\n * @template CaveatSpecifications - The union of all caveat specifications.\n * @template CaveatType - The type of the caveat whose value to extract.\n */\nexport type ExtractCaveatValue<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n CaveatType extends string,\n> = ExtractCaveat<CaveatSpecifications, CaveatType>['value'];\n\n/**\n * Determines whether a caveat specification is a restricted method caveat specification.\n *\n * @param specification - The caveat specification.\n * @returns True if the caveat specification is a restricted method caveat specification, otherwise false.\n */\nexport function isRestrictedMethodCaveatSpecification(\n specification: CaveatSpecificationConstraint,\n): specification is RestrictedMethodCaveatSpecificationConstraint {\n return hasProperty(specification, 'decorator');\n}\n\n/**\n * Decorate a restricted method implementation with its caveats.\n *\n * Note that all caveat functions (i.e. the argument and return value of the\n * decorator) must be awaited.\n *\n * @param methodImplementation - The restricted method implementation\n * @param permission - The origin's potential permission\n * @param caveatSpecifications - All caveat implementations\n * @returns The decorated method implementation\n */\nexport function decorateWithCaveats<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n>(\n methodImplementation: RestrictedMethod<RestrictedMethodParameters, Json>,\n permission: Readonly<PermissionConstraint>, // bound to the requesting origin\n caveatSpecifications: CaveatSpecificationMap<CaveatSpecifications>, // all caveat implementations\n): RestrictedMethod<RestrictedMethodParameters, Json> {\n const { caveats } = permission;\n if (!caveats) {\n return methodImplementation;\n }\n\n let decorated = async (\n args: Parameters<RestrictedMethod<RestrictedMethodParameters, Json>>[0],\n ) => methodImplementation(args);\n\n for (const caveat of caveats) {\n const specification =\n caveatSpecifications[caveat.type as CaveatSpecifications['type']];\n if (!specification) {\n throw new UnrecognizedCaveatTypeError(caveat.type);\n }\n\n if (!isRestrictedMethodCaveatSpecification(specification)) {\n throw new CaveatSpecificationMismatchError(\n specification,\n PermissionType.RestrictedMethod,\n );\n }\n decorated = specification.decorator(decorated, caveat);\n }\n\n return decorated;\n}\n"]}
1
+ {"version":3,"file":"Caveat.mjs","sourceRoot":"","sources":["../src/Caveat.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,wBAAwB;AAE9C,OAAO,EACL,gCAAgC,EAChC,2BAA2B,EAC5B,qBAAiB;AAOlB,OAAO,EAAE,cAAc,EAAE,yBAAqB;AA+Q9C;;;;;GAKG;AACH,MAAM,UAAU,qCAAqC,CACnD,aAA4C;IAE5C,OAAO,WAAW,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAGjC,oBAAwE,EACxE,UAA0C,EAAE,iCAAiC;AAC7E,oBAAkE;IAElE,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;IAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,IAAI,SAAS,GAAG,KAAK,EACnB,IAAuE,EACxD,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAE/C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,aAAa,GACjB,oBAAoB,CAAC,MAAM,CAAC,IAAoC,CAAC,CAAC;QACpE,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,2BAA2B,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,CAAC,qCAAqC,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1D,MAAM,IAAI,gCAAgC,CACxC,aAAa,EACb,cAAc,CAAC,gBAAgB,CAChC,CAAC;QACJ,CAAC;QACD,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import type { Json } from '@metamask/utils';\nimport { hasProperty } from '@metamask/utils';\n\nimport {\n CaveatSpecificationMismatchError,\n UnrecognizedCaveatTypeError,\n} from './errors';\nimport type {\n AsyncRestrictedMethod,\n RestrictedMethod,\n PermissionConstraint,\n RestrictedMethodParameters,\n} from './Permission';\nimport { PermissionType } from './Permission';\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { PermissionController } from './PermissionController';\n\nexport type CaveatConstraint = {\n /**\n * The type of the caveat. The type is presumed to be meaningful in the\n * context of the capability it is associated with.\n *\n * In MetaMask, every permission can only have one caveat of each type.\n */\n readonly type: string;\n\n /**\n * Any additional data necessary to enforce the caveat.\n */\n readonly value: Json;\n};\n\n/**\n * A `ZCAP-LD`-like caveat object. A caveat is associated with a particular\n * permission, and stored in its `caveats` array. Conceptually, a caveat is\n * an arbitrary attenuation of the authority granted by its associated\n * permission. It is the responsibility of the host to interpret and apply\n * the restriction represented by a caveat.\n *\n * @template Type - The type of the caveat.\n * @template Value - The value associated with the caveat.\n */\nexport type Caveat<Type extends string, Value extends Json> = {\n /**\n * The type of the caveat. The type is presumed to be meaningful in the\n * context of the capability it is associated with.\n *\n * In MetaMask, every permission can only have one caveat of each type.\n */\n readonly type: Type;\n\n /**\n * Any additional data necessary to enforce the caveat.\n */\n readonly value: Value;\n};\n\n// Next, we define types used for specifying caveats at the consumer layer,\n// and a function for applying caveats to a restricted method request. This is\n// Accomplished by decorating the restricted method implementation with the\n// the corresponding caveat functions.\n\n/**\n * A function for applying caveats to a restricted method request.\n *\n * @template ParentCaveat - The caveat type associated with this decorator.\n * @param decorated - The restricted method implementation to be decorated.\n * The method may have already been decorated with other caveats.\n * @param caveat - The caveat object.\n * @returns The decorated restricted method implementation.\n */\nexport type CaveatDecorator<ParentCaveat extends CaveatConstraint> = (\n decorated: AsyncRestrictedMethod<RestrictedMethodParameters, Json>,\n caveat: ParentCaveat,\n) => AsyncRestrictedMethod<RestrictedMethodParameters, Json>;\n\n/**\n * Extracts a caveat value type from a caveat decorator.\n *\n * @template Decorator - The {@link CaveatDecorator} to extract a caveat value\n * type from.\n */\ntype ExtractCaveatValueFromDecorator<\n Decorator extends CaveatDecorator<CaveatConstraint>,\n> = Decorator extends (\n decorated: AsyncRestrictedMethod<RestrictedMethodParameters, Json>,\n caveat: infer ParentCaveat,\n) => AsyncRestrictedMethod<RestrictedMethodParameters, Json>\n ? ParentCaveat extends CaveatConstraint\n ? ParentCaveat['value']\n : never\n : never;\n\n/**\n * A function for validating caveats of a particular type.\n *\n * @see `validator` in {@link CaveatSpecificationBase} for more details.\n * @template ParentCaveat - The caveat type associated with this validator.\n * @param caveat - The caveat object to validate.\n * @param origin - The origin associated with the parent permission.\n * @param target - The target of the parent permission.\n */\nexport type CaveatValidator<ParentCaveat extends CaveatConstraint> = (\n caveat: { type: ParentCaveat['type']; value: unknown },\n origin?: string,\n target?: string,\n) => void;\n\n/**\n * A map of caveat type strings to {@link CaveatDiff} values.\n */\nexport type CaveatDiffMap<ParentCaveat extends CaveatConstraint> = {\n [CaveatType in ParentCaveat['type']]: ParentCaveat['value'];\n};\n\n/**\n * A function that merges two caveat values of the same type. The values must be\n * merged in the fashion of a right-biased union.\n *\n * @see `ARCHITECTURE.md` for more details.\n * @template Value - The type of the values to merge.\n * @param leftValue - The left-hand value.\n * @param rightValue - The right-hand value.\n * @returns `[newValue, diff]`, i.e. the merged value and the diff between the left value\n * and the new value. The diff must be expressed in the same type as the value itself.\n */\nexport type CaveatValueMerger<Value extends Json> = (\n leftValue: Value,\n rightValue: Value,\n) => [Value, Value] | [];\n\nexport type CaveatSpecificationBase = {\n /**\n * The string type of the caveat.\n */\n type: string;\n\n /**\n * The validator function used to validate caveats of the associated type\n * whenever they are constructed or mutated.\n *\n * The validator should throw an appropriate JSON-RPC error if validation fails.\n *\n * If no validator is specified, no validation of caveat values will be\n * performed. In instances where caveats are mutated but a permission's caveat\n * array has not changed, any corresponding permission validator will not be\n * called. For this reason, permission validators **must not** be relied upon\n * to validate caveats.\n */\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n validator?: CaveatValidator<any>;\n\n /**\n * The merger function used to merge a pair of values of the associated caveat type\n * during incremental permission requests. The values must be merged in the fashion\n * of a right-biased union.\n *\n * @see `ARCHITECTURE.md` for more details.\n */\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n merger?: CaveatValueMerger<any>;\n};\n\nexport type RestrictedMethodCaveatSpecificationConstraint =\n CaveatSpecificationBase & {\n /**\n * The decorator function used to apply the caveat to restricted method\n * requests.\n */\n decorator: CaveatDecorator<CaveatConstraint>;\n };\n\nexport type EndowmentCaveatSpecificationConstraint = CaveatSpecificationBase;\n\n/**\n * The constraint for caveat specification objects. Every {@link Caveat}\n * supported by a {@link PermissionController} must have an associated\n * specification, which is the source of truth for all caveat-related types.\n * In addition, a caveat specification may include a decorator function used\n * to apply the caveat's attenuation to a restricted method. It may also include\n * a validator function specified by the consumer.\n *\n * See the README for more details.\n */\nexport type CaveatSpecificationConstraint =\n | RestrictedMethodCaveatSpecificationConstraint\n | EndowmentCaveatSpecificationConstraint;\n\n/**\n * Options for {@link CaveatSpecificationBuilder} functions.\n */\ntype CaveatSpecificationBuilderOptions<\n DecoratorHooks extends Record<string, unknown>,\n ValidatorHooks extends Record<string, unknown>,\n> = {\n type?: string;\n decoratorHooks?: DecoratorHooks;\n validatorHooks?: ValidatorHooks;\n};\n\n/**\n * A function that builds caveat specifications. Modules that specify caveats\n * for external consumption should make this their primary / default export so\n * that host applications can use them to generate concrete specifications\n * tailored to their requirements.\n */\nexport type CaveatSpecificationBuilder<\n Options extends CaveatSpecificationBuilderOptions<\n Record<string, unknown>,\n Record<string, unknown>\n >,\n Specification extends CaveatSpecificationConstraint,\n> = (options: Options) => Specification;\n\n/**\n * A caveat specification export object, containing the\n * {@link CaveatSpecificationBuilder} function and \"hook name\" objects.\n */\nexport type CaveatSpecificationBuilderExportConstraint = {\n specificationBuilder: CaveatSpecificationBuilder<\n CaveatSpecificationBuilderOptions<\n Record<string, unknown>,\n Record<string, unknown>\n >,\n CaveatSpecificationConstraint\n >;\n decoratorHookNames?: Record<string, true>;\n validatorHookNames?: Record<string, true>;\n};\n\n/**\n * The specifications for all caveats supported by a particular\n * {@link PermissionController}.\n *\n * @template Specifications - The union of all {@link CaveatSpecificationConstraint} types.\n */\nexport type CaveatSpecificationMap<\n CaveatSpecification extends CaveatSpecificationConstraint,\n> = Record<CaveatSpecification['type'], CaveatSpecification>;\n\n/**\n * Extracts the union of all caveat types specified by the given\n * {@link CaveatSpecificationConstraint} type.\n *\n * @template CaveatSpecification - The {@link CaveatSpecificationConstraint} to extract a\n * caveat type union from.\n */\nexport type ExtractCaveats<\n CaveatSpecification extends CaveatSpecificationConstraint,\n> = CaveatSpecification extends RestrictedMethodCaveatSpecificationConstraint\n ? Caveat<\n CaveatSpecification['type'],\n ExtractCaveatValueFromDecorator<\n RestrictedMethodCaveatSpecificationConstraint['decorator']\n >\n >\n : Caveat<CaveatSpecification['type'], Json>;\n\n/**\n * Extracts the type of a specific {@link Caveat} from a union of caveat\n * specifications.\n *\n * @template CaveatSpecifications - The union of all caveat specifications.\n * @template CaveatType - The type of the caveat to extract.\n */\nexport type ExtractCaveat<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n CaveatType extends string,\n> = Extract<ExtractCaveats<CaveatSpecifications>, { type: CaveatType }>;\n\n/**\n * Extracts the value type of a specific {@link Caveat} from a union of caveat\n * specifications.\n *\n * @template CaveatSpecifications - The union of all caveat specifications.\n * @template CaveatType - The type of the caveat whose value to extract.\n */\nexport type ExtractCaveatValue<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n CaveatType extends string,\n> = ExtractCaveat<CaveatSpecifications, CaveatType>['value'];\n\n/**\n * Determines whether a caveat specification is a restricted method caveat specification.\n *\n * @param specification - The caveat specification.\n * @returns True if the caveat specification is a restricted method caveat specification, otherwise false.\n */\nexport function isRestrictedMethodCaveatSpecification(\n specification: CaveatSpecificationConstraint,\n): specification is RestrictedMethodCaveatSpecificationConstraint {\n return hasProperty(specification, 'decorator');\n}\n\n/**\n * Decorate a restricted method implementation with its caveats.\n *\n * Note that all caveat functions (i.e. the argument and return value of the\n * decorator) must be awaited.\n *\n * @param methodImplementation - The restricted method implementation\n * @param permission - The origin's potential permission\n * @param caveatSpecifications - All caveat implementations\n * @returns The decorated method implementation\n */\nexport function decorateWithCaveats<\n CaveatSpecifications extends CaveatSpecificationConstraint,\n>(\n methodImplementation: RestrictedMethod<RestrictedMethodParameters, Json>,\n permission: Readonly<PermissionConstraint>, // bound to the requesting origin\n caveatSpecifications: CaveatSpecificationMap<CaveatSpecifications>, // all caveat implementations\n): RestrictedMethod<RestrictedMethodParameters, Json> {\n const { caveats } = permission;\n if (!caveats) {\n return methodImplementation;\n }\n\n let decorated = async (\n args: Parameters<RestrictedMethod<RestrictedMethodParameters, Json>>[0],\n ): Promise<Json> => methodImplementation(args);\n\n for (const caveat of caveats) {\n const specification =\n caveatSpecifications[caveat.type as CaveatSpecifications['type']];\n if (!specification) {\n throw new UnrecognizedCaveatTypeError(caveat.type);\n }\n\n if (!isRestrictedMethodCaveatSpecification(specification)) {\n throw new CaveatSpecificationMismatchError(\n specification,\n PermissionType.RestrictedMethod,\n );\n }\n decorated = specification.decorator(decorated, caveat);\n }\n\n return decorated;\n}\n"]}