{"version":3,"file":"PermissionController.cjs","sourceRoot":"","sources":["../src/PermissionController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n  ApprovalControllerAcceptRequestAction,\n  ApprovalControllerAddRequestAction,\n  ApprovalControllerHasRequestAction,\n  ApprovalControllerRejectRequestAction,\n} from '@metamask/approval-controller';\nimport type {\n  StateMetadata,\n  ControllerGetStateAction,\n  ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { NonEmptyArray } from '@metamask/controller-utils';\nimport {\n  isNonEmptyArray,\n  isPlainObject,\n  isValidJson,\n} from '@metamask/controller-utils';\nimport type {\n  Messenger,\n  ActionConstraint,\n  EventConstraint,\n} from '@metamask/messenger';\nimport { JsonRpcError } from '@metamask/rpc-errors';\nimport { hasProperty } from '@metamask/utils';\nimport type { Json, Mutable } from '@metamask/utils';\nimport deepFreeze from 'deep-freeze-strict';\nimport { castDraft, produce as immerProduce } from 'immer';\nimport type { Draft } from 'immer';\nimport { nanoid } from 'nanoid';\n\nimport type {\n  CaveatConstraint,\n  CaveatDiffMap,\n  CaveatSpecificationConstraint,\n  CaveatSpecificationMap,\n  CaveatValueMerger,\n  ExtractCaveat,\n  ExtractCaveats,\n  ExtractCaveatValue,\n} from './Caveat';\nimport {\n  decorateWithCaveats,\n  isRestrictedMethodCaveatSpecification,\n} from './Caveat';\nimport {\n  CaveatAlreadyExistsError,\n  CaveatDoesNotExistError,\n  CaveatInvalidJsonError,\n  CaveatMergerDoesNotExistError,\n  CaveatMergeTypeMismatchError,\n  CaveatMissingValueError,\n  CaveatSpecificationMismatchError,\n  DuplicateCaveatError,\n  EndowmentPermissionDoesNotExistError,\n  ForbiddenCaveatError,\n  internalError,\n  InvalidApprovedPermissionError,\n  InvalidCaveatError,\n  InvalidCaveatFieldsError,\n  InvalidCaveatsPropertyError,\n  InvalidCaveatTypeError,\n  InvalidMergedPermissionsError,\n  invalidParams,\n  InvalidSubjectIdentifierError,\n  methodNotFound,\n  PermissionDoesNotExistError,\n  PermissionsRequestNotFoundError,\n  unauthorized,\n  UnrecognizedCaveatTypeError,\n  UnrecognizedSubjectError,\n  userRejectedRequest,\n} from './errors';\nimport type {\n  EndowmentSpecificationConstraint,\n  ExtractAllowedCaveatTypes,\n  ExtractPermissionSpecification,\n  OriginString,\n  PermissionConstraint,\n  PermissionSpecificationConstraint,\n  PermissionSpecificationMap,\n  RequestedPermissions,\n  RestrictedMethod,\n  RestrictedMethodParameters,\n  RestrictedMethodSpecificationConstraint,\n  SideEffectHandler,\n  ValidPermission,\n  ValidPermissionSpecification,\n} from './Permission';\nimport {\n  constructPermission,\n  findCaveat,\n  hasSpecificationType,\n  PermissionType,\n} from './Permission';\nimport type { PermissionControllerMethodActions } from './PermissionController-method-action-types';\nimport type { SubjectMetadataControllerGetSubjectMetadataAction } from './SubjectMetadataController-method-action-types';\nimport { collectUniqueAndPairedCaveats, MethodNames } from './utils';\n\n/**\n * Flags for controlling the validation behavior of certain internal methods.\n */\ntype PermissionValidationFlags = {\n  invokePermissionValidator: boolean;\n  performCaveatValidation: boolean;\n};\n\n/**\n * Metadata associated with {@link PermissionController} subjects.\n */\nexport type PermissionSubjectMetadata = {\n  origin: OriginString;\n};\n\n/**\n * Metadata associated with permission requests.\n */\nexport type PermissionsRequestMetadata = PermissionSubjectMetadata & {\n  id: string;\n  [key: string]: Json;\n};\n\n/**\n * A diff produced by an incremental permissions request.\n */\nexport type PermissionDiffMap<\n  TargetName extends string,\n  AllowedCaveats extends CaveatConstraint,\n> = Record<TargetName, CaveatDiffMap<AllowedCaveats>>;\n\n/**\n * Used for prompting the user about a proposed new permission.\n * Includes information about the grantee subject, requested permissions, the\n * diff relative to the previously granted permissions (if relevant), and any\n * additional information added by the consumer.\n *\n * All properties except `diff` and `permissions` are passed to any factories\n * for the requested permissions.\n */\nexport type PermissionsRequest = {\n  metadata: PermissionsRequestMetadata;\n  permissions: RequestedPermissions;\n  [key: string]: Json;\n} & {\n  diff?: {\n    currentPermissions: SubjectPermissions<PermissionConstraint>;\n    permissionDiffMap: PermissionDiffMap<string, CaveatConstraint>;\n  };\n};\n\n/**\n * Metadata associated with an approved permission request.\n */\ntype ApprovedPermissionsMetadata = {\n  data?: Record<string, unknown>;\n  id: string;\n  origin: OriginString;\n};\n\nexport type SideEffects = {\n  permittedHandlers: Record<\n    string,\n    SideEffectHandler<ActionConstraint, EventConstraint>\n  >;\n  failureHandlers: Record<\n    string,\n    SideEffectHandler<ActionConstraint, EventConstraint>\n  >;\n};\n\n/**\n * The name of the {@link PermissionController}.\n */\nconst controllerName = 'PermissionController';\n\nconst MESSENGER_EXPOSED_METHODS = [\n  'clearState',\n  'executeRestrictedMethod',\n  'getEndowments',\n  'getSubjectNames',\n  'getPermissions',\n  'hasPermission',\n  'hasPermissions',\n  'hasUnrestrictedMethod',\n  'grantPermissions',\n  'grantPermissionsIncremental',\n  'requestPermissions',\n  'requestPermissionsIncremental',\n  'revokeAllPermissions',\n  'revokePermissionForAllSubjects',\n  'revokePermissions',\n  'updateCaveat',\n  'getCaveat',\n] as const;\n\n/**\n * Permissions associated with a {@link PermissionController} subject.\n */\nexport type SubjectPermissions<Permission extends PermissionConstraint> =\n  Record<Permission['parentCapability'], Permission>;\n\n/**\n * Permissions and metadata associated with a {@link PermissionController}\n * subject.\n */\nexport type PermissionSubjectEntry<\n  SubjectPermission extends PermissionConstraint,\n> = {\n  origin: SubjectPermission['invoker'];\n  permissions: SubjectPermissions<SubjectPermission>;\n};\n\n/**\n * All subjects of a {@link PermissionController}.\n *\n * @template SubjectPermission - The permissions of the subject.\n */\nexport type PermissionControllerSubjects<\n  SubjectPermission extends PermissionConstraint,\n> = Record<\n  SubjectPermission['invoker'],\n  PermissionSubjectEntry<SubjectPermission>\n>;\n\n/**\n * The state of a {@link PermissionController}.\n *\n * @template Permission - The controller's permission type union.\n */\nexport type PermissionControllerState<Permission> =\n  Permission extends PermissionConstraint\n    ? {\n        subjects: PermissionControllerSubjects<Permission>;\n      }\n    : never;\n\n/**\n * Get the state metadata of the {@link PermissionController}.\n *\n * @template Permission - The controller's permission type union.\n * @returns The state metadata\n */\nfunction getStateMetadata<\n  Permission extends PermissionConstraint,\n>(): StateMetadata<PermissionControllerState<Permission>> {\n  return {\n    subjects: {\n      includeInStateLogs: true,\n      includeInDebugSnapshot: true,\n      persist: true,\n      usedInUi: true,\n    },\n  } as StateMetadata<PermissionControllerState<Permission>>;\n}\n\n/**\n * Get the default state of the {@link PermissionController}.\n *\n * @template Permission - The controller's permission type union.\n * @returns The default state of the controller\n */\nfunction getDefaultState<\n  Permission extends PermissionConstraint,\n>(): PermissionControllerState<Permission> {\n  return { subjects: {} } as PermissionControllerState<Permission>;\n}\n\n/**\n * Gets the state of the {@link PermissionController}.\n */\nexport type PermissionControllerGetStateAction = ControllerGetStateAction<\n  typeof controllerName,\n  PermissionControllerState<PermissionConstraint>\n>;\n\n/**\n * Gets the state of the {@link PermissionController}.\n *\n * @deprecated Use `PermissionControllerGetStateAction` instead.\n */\nexport type GetPermissionControllerState = PermissionControllerGetStateAction;\n\n/**\n * Gets the names of all subjects from the {@link PermissionController}.\n *\n * @deprecated Use `PermissionControllerGetSubjectNamesAction` instead.\n */\nexport type GetSubjects = {\n  type: `${typeof controllerName}:getSubjectNames`;\n  handler: () => (keyof PermissionControllerSubjects<PermissionConstraint>)[];\n};\n\n/**\n * Gets the permissions for specified subject.\n *\n * @deprecated Use `PermissionControllerGetPermissionsAction` instead.\n */\nexport type GetPermissions = {\n  type: `${typeof controllerName}:getPermissions`;\n  handler: GenericPermissionController['getPermissions'];\n};\n\n/**\n * Checks whether the specified subject has any permissions.\n *\n * @deprecated Use `PermissionControllerHasPermissionAction` instead.\n */\nexport type HasPermissions = {\n  type: `${typeof controllerName}:hasPermissions`;\n  handler: GenericPermissionController['hasPermissions'];\n};\n\n/**\n * Checks whether the specified subject has a specific permission.\n *\n * @deprecated Use `PermissionControllerHasPermissionAction` instead.\n */\nexport type HasPermission = {\n  type: `${typeof controllerName}:hasPermission`;\n  handler: GenericPermissionController['hasPermission'];\n};\n\n/**\n * Directly grants given permissions for a specified origin without requesting user approval.\n *\n * @deprecated Use `PermissionControllerGrantPermissionsAction` instead.\n */\nexport type GrantPermissions = {\n  type: `${typeof controllerName}:grantPermissions`;\n  handler: GenericPermissionController['grantPermissions'];\n};\n\n/**\n * Directly grants given permissions for a specified origin without requesting user approval.\n *\n * @deprecated Use `PermissionControllerGrantPermissionsIncrementalAction`\n * instead.\n */\nexport type GrantPermissionsIncremental = {\n  type: `${typeof controllerName}:grantPermissionsIncremental`;\n  handler: GenericPermissionController['grantPermissionsIncremental'];\n};\n\n/**\n * Requests given permissions for a specified origin.\n *\n * @deprecated Use `PermissionControllerRequestPermissionsAction` instead.\n */\nexport type RequestPermissions = {\n  type: `${typeof controllerName}:requestPermissions`;\n  handler: GenericPermissionController['requestPermissions'];\n};\n\n/**\n * Requests given permissions for a specified origin.\n *\n * @deprecated Use `PermissionControllerRequestPermissionsAction` instead.\n */\nexport type RequestPermissionsIncremental = {\n  type: `${typeof controllerName}:requestPermissionsIncremental`;\n  handler: GenericPermissionController['requestPermissionsIncremental'];\n};\n\n/**\n * Removes the specified permissions for each origin.\n *\n * @deprecated Use `PermissionControllerRevokePermissionsAction` instead.\n */\nexport type RevokePermissions = {\n  type: `${typeof controllerName}:revokePermissions`;\n  handler: GenericPermissionController['revokePermissions'];\n};\n\n/**\n * Removes all permissions for a given origin.\n *\n * @deprecated Use `PermissionControllerRevokeAllPermissionAction` instead.\n */\nexport type RevokeAllPermissions = {\n  type: `${typeof controllerName}:revokeAllPermissions`;\n  handler: GenericPermissionController['revokeAllPermissions'];\n};\n\n/**\n * Revokes all permissions corresponding to the specified target for all subjects.\n * Does nothing if no subjects or no such permission exists.\n *\n * @deprecated Use `PermissionControllerRevokePermissionForAllSubjectsAction`\n * instead.\n */\nexport type RevokePermissionForAllSubjects = {\n  type: `${typeof controllerName}:revokePermissionForAllSubjects`;\n  handler: GenericPermissionController['revokePermissionForAllSubjects'];\n};\n\n/**\n * Updates a caveat value for a specified caveat type belonging to a specific target and origin.\n *\n * @deprecated Use `PermissionControllerUpdateCaveatAction` instead.\n */\nexport type UpdateCaveat = {\n  type: `${typeof controllerName}:updateCaveat`;\n  handler: GenericPermissionController['updateCaveat'];\n};\n\n/**\n * Get a caveat value for a specified caveat type belonging to a specific target and origin.\n *\n * @deprecated Use `PermissionControllerGetCaveatAction` instead.\n */\nexport type GetCaveat = {\n  type: `${typeof controllerName}:getCaveat`;\n  handler: GenericPermissionController['getCaveat'];\n};\n\n/**\n * Clears all permissions from the {@link PermissionController}.\n *\n * @deprecated Use `PermissionControllerClearStateAction` instead.\n */\nexport type ClearPermissions = {\n  type: `${typeof controllerName}:clearPermissions`;\n  handler: () => void;\n};\n\n/**\n * Gets the endowments for the given subject and permission.\n *\n * @deprecated Use `PermissionControllerGetEndowmentsAction` instead.\n */\nexport type GetEndowments = {\n  type: `${typeof controllerName}:getEndowments`;\n  handler: GenericPermissionController['getEndowments'];\n};\n\n/**\n * The {@link Messenger} actions of the {@link PermissionController}.\n */\nexport type PermissionControllerActions =\n  | PermissionControllerGetStateAction\n  | PermissionControllerMethodActions;\n\n/**\n * The generic state change event of the {@link PermissionController}.\n */\nexport type PermissionControllerStateChange = ControllerStateChangeEvent<\n  typeof controllerName,\n  PermissionControllerState<PermissionConstraint>\n>;\n\n/**\n * The {@link Messenger} events of the {@link PermissionController}.\n *\n * The permission controller only emits its generic state change events.\n * Consumers should use selector subscriptions to subscribe to relevant\n * substate.\n */\nexport type PermissionControllerEvents = PermissionControllerStateChange;\n\n/**\n * The external {@link Messenger} actions available to the\n * {@link PermissionController}.\n */\ntype AllowedActions =\n  | ApprovalControllerAddRequestAction\n  | ApprovalControllerHasRequestAction\n  | ApprovalControllerAcceptRequestAction\n  | ApprovalControllerRejectRequestAction\n  | SubjectMetadataControllerGetSubjectMetadataAction;\n\n/**\n * The messenger of the {@link PermissionController}.\n */\nexport type PermissionControllerMessenger = Messenger<\n  typeof controllerName,\n  PermissionControllerActions | AllowedActions,\n  PermissionControllerEvents\n>;\n\nexport type SideEffectMessenger<\n  Actions extends ActionConstraint,\n  Events extends EventConstraint,\n> = Messenger<typeof controllerName, Actions | AllowedActions, Events>;\n\n/**\n * A generic {@link PermissionController}.\n */\nexport type GenericPermissionController = PermissionController<\n  PermissionSpecificationConstraint,\n  CaveatSpecificationConstraint\n>;\n\n/**\n * Describes the possible results of a {@link CaveatMutator} function.\n */\nexport enum CaveatMutatorOperation {\n  Noop = 0,\n  UpdateValue = 1,\n  DeleteCaveat = 2,\n  RevokePermission = 3,\n}\n\n/**\n * Given a caveat value, returns a {@link CaveatMutatorOperation} and, optionally,\n * a new caveat value.\n *\n * @see {@link PermissionController.updatePermissionsByCaveat} for more details.\n * @template Caveat - The caveat type for which this mutator is intended.\n * @param caveatValue - The existing value of the caveat being mutated.\n * @returns A tuple of the mutation result and, optionally, the new caveat\n * value.\n */\nexport type CaveatMutator<TargetCaveat extends CaveatConstraint> = (\n  caveatValue: TargetCaveat['value'],\n) => CaveatMutatorResult;\n\ntype CaveatMutatorResult =\n  | Readonly<{\n      operation: CaveatMutatorOperation.UpdateValue;\n      value: CaveatConstraint['value'];\n    }>\n  | Readonly<{\n      operation: Exclude<\n        CaveatMutatorOperation,\n        CaveatMutatorOperation.UpdateValue\n      >;\n    }>;\n\ntype MergeCaveatResult<CaveatType extends CaveatConstraint | undefined> =\n  CaveatType extends undefined\n    ? [CaveatConstraint, CaveatConstraint['value']]\n    : [CaveatConstraint, CaveatConstraint['value']] | [];\n\n/**\n * Extracts the permission(s) specified by the given permission and caveat\n * specifications.\n *\n * @template ControllerPermissionSpecification - The permission specification(s)\n * to extract from.\n * @template ControllerCaveatSpecification - The caveat specification(s) to\n * extract from. Necessary because {@link Permission} has a generic parameter\n * that describes the allowed caveats for the permission.\n */\nexport type ExtractPermission<\n  ControllerPermissionSpecification extends PermissionSpecificationConstraint,\n  ControllerCaveatSpecification extends CaveatSpecificationConstraint,\n> =\n  ControllerPermissionSpecification extends ValidPermissionSpecification<ControllerPermissionSpecification>\n    ? ValidPermission<\n        ControllerPermissionSpecification['targetName'],\n        ExtractCaveats<ControllerCaveatSpecification>\n      >\n    : never;\n\n/**\n * Extracts the restricted method permission(s) specified by the given\n * permission and caveat specifications.\n *\n * @template ControllerPermissionSpecification - The permission specification(s)\n * to extract from.\n * @template ControllerCaveatSpecification - The caveat specification(s) to\n * extract from. Necessary because {@link Permission} has a generic parameter\n * that describes the allowed caveats for the permission.\n */\nexport type ExtractRestrictedMethodPermission<\n  ControllerPermissionSpecification extends PermissionSpecificationConstraint,\n  ControllerCaveatSpecification extends CaveatSpecificationConstraint,\n> = ExtractPermission<\n  Extract<\n    ControllerPermissionSpecification,\n    RestrictedMethodSpecificationConstraint\n  >,\n  ControllerCaveatSpecification\n>;\n\n/**\n * Extracts the endowment permission(s) specified by the given permission and\n * caveat specifications.\n *\n * @template ControllerPermissionSpecification - The permission specification(s)\n * to extract from.\n * @template ControllerCaveatSpecification - The caveat specification(s) to\n * extract from. Necessary because {@link Permission} has a generic parameter\n * that describes the allowed caveats for the permission.\n */\nexport type ExtractEndowmentPermission<\n  ControllerPermissionSpecification extends PermissionSpecificationConstraint,\n  ControllerCaveatSpecification extends CaveatSpecificationConstraint,\n> = ExtractPermission<\n  Extract<ControllerPermissionSpecification, EndowmentSpecificationConstraint>,\n  ControllerCaveatSpecification\n>;\n\n/**\n * Options for the {@link PermissionController} constructor.\n *\n * @template ControllerPermissionSpecification - A union of the types of all\n * permission specifications available to the controller. Any referenced caveats\n * must be included in the controller's caveat specifications.\n * @template ControllerCaveatSpecification - A union of the types of all\n * caveat specifications available to the controller.\n */\nexport type PermissionControllerOptions<\n  ControllerPermissionSpecification extends PermissionSpecificationConstraint,\n  ControllerCaveatSpecification extends CaveatSpecificationConstraint,\n> = {\n  messenger: PermissionControllerMessenger;\n  caveatSpecifications: CaveatSpecificationMap<ControllerCaveatSpecification>;\n  permissionSpecifications: PermissionSpecificationMap<ControllerPermissionSpecification>;\n  unrestrictedMethods: readonly string[];\n  state?: Partial<\n    PermissionControllerState<\n      ExtractPermission<\n        ControllerPermissionSpecification,\n        ControllerCaveatSpecification\n      >\n    >\n  >;\n};\n\n/**\n * The permission controller. See the [Architecture](../ARCHITECTURE.md)\n * document for details.\n *\n * Assumes the existence of an {@link ApprovalController} reachable via the\n * {@link Messenger}.\n *\n * @template ControllerPermissionSpecification - A union of the types of all\n * permission specifications available to the controller. Any referenced caveats\n * must be included in the controller's caveat specifications.\n * @template ControllerCaveatSpecification - A union of the types of all\n * caveat specifications available to the controller.\n */\nexport class PermissionController<\n  ControllerPermissionSpecification extends PermissionSpecificationConstraint =\n    PermissionSpecificationConstraint,\n  ControllerCaveatSpecification extends CaveatSpecificationConstraint =\n    CaveatSpecificationConstraint,\n> extends BaseController<\n  typeof controllerName,\n  PermissionControllerState<\n    ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >\n  >,\n  PermissionControllerMessenger\n> {\n  readonly #caveatSpecifications: Readonly<\n    CaveatSpecificationMap<ControllerCaveatSpecification>\n  >;\n\n  readonly #permissionSpecifications: Readonly<\n    PermissionSpecificationMap<ControllerPermissionSpecification>\n  >;\n\n  readonly #unrestrictedMethods: ReadonlySet<string>;\n\n  /**\n   * The names of all JSON-RPC methods that will be ignored by the controller.\n   *\n   * @returns The names of all unrestricted JSON-RPC methods\n   */\n  public get unrestrictedMethods(): ReadonlySet<string> {\n    return this.#unrestrictedMethods;\n  }\n\n  /**\n   * Checks whether the given method was declared as unrestricted at\n   * construction time. Methods unknown to the controller return `false` and\n   * would be treated as restricted by callers such as the permission\n   * middleware.\n   *\n   * @param method - The name of the method to check.\n   * @returns Whether the method is unrestricted.\n   */\n  hasUnrestrictedMethod(method: string): boolean {\n    return this.#unrestrictedMethods.has(method);\n  }\n\n  /**\n   * Constructs the PermissionController.\n   *\n   * @param options - Permission controller options.\n   * @param options.caveatSpecifications - The specifications of all caveats\n   * available to the controller. See {@link CaveatSpecificationMap} and the\n   * documentation for more details.\n   * @param options.permissionSpecifications - The specifications of all\n   * permissions available to the controller. See\n   * {@link PermissionSpecificationMap} and the README for more details.\n   * @param options.unrestrictedMethods - The callable names of all JSON-RPC\n   * methods ignored by the new controller.\n   * @param options.messenger - The messenger. See\n   * {@link BaseController} for more information.\n   * @param options.state - Existing state to hydrate the controller with at\n   * initialization.\n   */\n  constructor(\n    options: PermissionControllerOptions<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >,\n  ) {\n    const {\n      caveatSpecifications,\n      permissionSpecifications,\n      unrestrictedMethods,\n      messenger,\n      state = {},\n    } = options;\n\n    super({\n      name: controllerName,\n      metadata:\n        getStateMetadata<\n          ExtractPermission<\n            ControllerPermissionSpecification,\n            ControllerCaveatSpecification\n          >\n        >(),\n      messenger,\n      state: {\n        ...getDefaultState<\n          ExtractPermission<\n            ControllerPermissionSpecification,\n            ControllerCaveatSpecification\n          >\n        >(),\n        ...state,\n      },\n    });\n\n    this.#unrestrictedMethods = new Set(unrestrictedMethods);\n    this.#caveatSpecifications = deepFreeze({ ...caveatSpecifications });\n\n    this.#validatePermissionSpecifications(\n      permissionSpecifications,\n      this.#caveatSpecifications,\n    );\n\n    this.#permissionSpecifications = deepFreeze({\n      ...permissionSpecifications,\n    });\n\n    this.messenger.registerMethodActionHandlers(\n      this,\n      MESSENGER_EXPOSED_METHODS,\n    );\n  }\n\n  /**\n   * Gets a permission specification.\n   *\n   * @param targetName - The name of the permission specification to get.\n   * @returns The permission specification with the specified target name.\n   */\n  #getPermissionSpecification<\n    TargetName extends ControllerPermissionSpecification['targetName'],\n  >(\n    targetName: TargetName,\n  ): ExtractPermissionSpecification<\n    ControllerPermissionSpecification,\n    TargetName\n  > {\n    return this.#permissionSpecifications[targetName];\n  }\n\n  /**\n   * Gets a caveat specification.\n   *\n   * @param caveatType - The type of the caveat specification to get.\n   * @returns The caveat specification with the specified type.\n   */\n  #getCaveatSpecification<\n    CaveatType extends ControllerCaveatSpecification['type'],\n  >(caveatType: CaveatType): ControllerCaveatSpecification {\n    return this.#caveatSpecifications[caveatType];\n  }\n\n  /**\n   * Gets the merger function for the specified caveat. Throws if no\n   * merger exists.\n   *\n   * @param caveatType - The type of the caveat whose merger to get.\n   * @returns The caveat value merger function for the specified caveat type.\n   */\n  #expectGetCaveatMerger<\n    CaveatType extends ControllerCaveatSpecification['type'],\n  >(caveatType: CaveatType): CaveatValueMerger<Json> {\n    const { merger } = this.#getCaveatSpecification(caveatType);\n\n    if (merger === undefined) {\n      throw new CaveatMergerDoesNotExistError(caveatType);\n    }\n    return merger;\n  }\n\n  /**\n   * Constructor helper for validating permission specifications.\n   *\n   * Throws an error if validation fails.\n   *\n   * @param permissionSpecifications - The permission specifications passed to\n   * this controller's constructor.\n   * @param caveatSpecifications - The caveat specifications passed to this\n   * controller.\n   */\n  #validatePermissionSpecifications(\n    permissionSpecifications: PermissionSpecificationMap<ControllerPermissionSpecification>,\n    caveatSpecifications: CaveatSpecificationMap<ControllerCaveatSpecification>,\n  ): void {\n    Object.entries<ControllerPermissionSpecification>(\n      permissionSpecifications,\n    ).forEach(\n      ([\n        targetName,\n        { permissionType, targetName: innerTargetName, allowedCaveats },\n      ]) => {\n        if (!permissionType || !hasProperty(PermissionType, permissionType)) {\n          throw new Error(`Invalid permission type: \"${permissionType}\"`);\n        }\n\n        if (!targetName) {\n          throw new Error(`Invalid permission target name: \"${targetName}\"`);\n        }\n\n        if (targetName !== innerTargetName) {\n          throw new Error(\n            `Invalid permission specification: target name \"${targetName}\" must match specification.targetName value \"${innerTargetName}\".`,\n          );\n        }\n\n        if (allowedCaveats) {\n          allowedCaveats.forEach((caveatType) => {\n            if (!hasProperty(caveatSpecifications, caveatType)) {\n              throw new UnrecognizedCaveatTypeError(caveatType);\n            }\n\n            const specification =\n              caveatSpecifications[\n                caveatType as ControllerCaveatSpecification['type']\n              ];\n            const isRestrictedMethodCaveat =\n              isRestrictedMethodCaveatSpecification(specification);\n\n            if (\n              (permissionType === PermissionType.RestrictedMethod &&\n                !isRestrictedMethodCaveat) ||\n              (permissionType === PermissionType.Endowment &&\n                isRestrictedMethodCaveat)\n            ) {\n              throw new CaveatSpecificationMismatchError(\n                specification,\n                permissionType,\n              );\n            }\n          });\n        }\n      },\n    );\n  }\n\n  /**\n   * Clears the state of the controller.\n   */\n  clearState(): void {\n    this.update((_draftState) => {\n      return {\n        ...getDefaultState<\n          ExtractPermission<\n            ControllerPermissionSpecification,\n            ControllerCaveatSpecification\n          >\n        >(),\n      };\n    });\n  }\n\n  /**\n   * Gets the permission specification corresponding to the given permission\n   * type and target name. Throws an error if the target name does not\n   * correspond to a permission, or if the specification is not of the\n   * given permission type.\n   *\n   * @template Type - The type of the permission specification to get.\n   * @param permissionType - The type of the permission specification to get.\n   * @param targetName - The name of the permission whose specification to get.\n   * @param requestingOrigin - The origin of the requesting subject. Will be\n   * added to any thrown errors.\n   * @returns The specification object corresponding to the given type and\n   * target name.\n   */\n  #getTypedPermissionSpecification<Type extends PermissionType>(\n    permissionType: Type,\n    targetName: string,\n    requestingOrigin: string,\n  ): ControllerPermissionSpecification & { permissionType: Type } {\n    const failureError =\n      permissionType === PermissionType.RestrictedMethod\n        ? methodNotFound(targetName, { origin: requestingOrigin })\n        : new EndowmentPermissionDoesNotExistError(\n            targetName,\n            requestingOrigin,\n          );\n\n    if (!this.#targetExists(targetName)) {\n      throw failureError;\n    }\n\n    const specification = this.#getPermissionSpecification(targetName);\n    if (!hasSpecificationType(specification, permissionType)) {\n      throw failureError;\n    }\n\n    return specification;\n  }\n\n  /**\n   * Gets the implementation of the specified restricted method.\n   *\n   * A JSON-RPC error is thrown if the method does not exist.\n   *\n   * @see {@link PermissionController.executeRestrictedMethod} for internal usage.\n   * @param method - The name of the restricted method.\n   * @param origin - The origin associated with the request for the restricted\n   * method.\n   * @returns The restricted method implementation.\n   */\n  #getRestrictedMethod(\n    method: string,\n    origin: string,\n  ): RestrictedMethod<RestrictedMethodParameters, Json> {\n    return this.#getTypedPermissionSpecification(\n      PermissionType.RestrictedMethod,\n      method,\n      origin,\n    ).methodImplementation;\n  }\n\n  /**\n   * Gets a list of all origins of subjects.\n   *\n   * @returns The origins (i.e. IDs) of all subjects.\n   */\n  getSubjectNames(): OriginString[] {\n    return Object.keys(this.state.subjects);\n  }\n\n  /**\n   * Gets the permission for the specified target of the subject corresponding\n   * to the specified origin.\n   *\n   * @param origin - The origin of the subject.\n   * @param targetName - The method name as invoked by a third party (i.e., not\n   * a method key).\n   * @returns The permission if it exists, or undefined otherwise.\n   */\n  getPermission<\n    SubjectPermission extends ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >,\n  >(\n    origin: OriginString,\n    targetName: SubjectPermission['parentCapability'],\n  ): SubjectPermission | undefined {\n    return this.state.subjects[origin]?.permissions[targetName] as\n      | SubjectPermission\n      | undefined;\n  }\n\n  /**\n   * Gets all permissions for the specified subject, if any.\n   *\n   * @param origin - The origin of the subject.\n   * @returns The permissions of the subject, if any.\n   */\n  getPermissions(\n    origin: OriginString,\n  ):\n    | SubjectPermissions<\n        ValidPermission<string, ExtractCaveats<ControllerCaveatSpecification>>\n      >\n    | undefined {\n    return this.state.subjects[origin]?.permissions;\n  }\n\n  /**\n   * Checks whether the subject with the specified origin has the specified\n   * permission.\n   *\n   * @param origin - The origin of the subject.\n   * @param target - The target name of the permission.\n   * @returns Whether the subject has the permission.\n   */\n  hasPermission(\n    origin: OriginString,\n    target: ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n  ): boolean {\n    return Boolean(this.getPermission(origin, target));\n  }\n\n  /**\n   * Checks whether the subject with the specified origin has any permissions.\n   * Use this if you want to know if a subject \"exists\".\n   *\n   * @param origin - The origin of the subject to check.\n   * @returns Whether the subject has any permissions.\n   */\n  hasPermissions(origin: OriginString): boolean {\n    return Boolean(this.state.subjects[origin]);\n  }\n\n  /**\n   * Revokes all permissions from the specified origin.\n   *\n   * Throws an error if the origin has no permissions.\n   *\n   * @param origin - The origin whose permissions to revoke.\n   */\n  revokeAllPermissions(origin: OriginString): void {\n    this.update((draftState) => {\n      if (!draftState.subjects[origin]) {\n        throw new UnrecognizedSubjectError(origin);\n      }\n      delete draftState.subjects[origin];\n    });\n  }\n\n  /**\n   * Revokes the specified permission from the subject with the specified\n   * origin.\n   *\n   * Throws an error if the subject or the permission does not exist.\n   *\n   * @param origin - The origin of the subject whose permission to revoke.\n   * @param target - The target name of the permission to revoke.\n   */\n  revokePermission(\n    origin: OriginString,\n    target: ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n  ): void {\n    this.revokePermissions({ [origin]: [target] });\n  }\n\n  /**\n   * Revokes the specified permissions from the specified subjects.\n   *\n   * Throws an error if any of the subjects or permissions do not exist.\n   *\n   * @param subjectsAndPermissions - An object mapping subject origins\n   * to arrays of permission target names to revoke.\n   */\n  revokePermissions(\n    subjectsAndPermissions: Record<\n      OriginString,\n      NonEmptyArray<\n        ExtractPermission<\n          ControllerPermissionSpecification,\n          ControllerCaveatSpecification\n        >['parentCapability']\n      >\n    >,\n  ): void {\n    this.update((draftState) => {\n      Object.keys(subjectsAndPermissions).forEach((origin) => {\n        if (!hasProperty(draftState.subjects, origin)) {\n          throw new UnrecognizedSubjectError(origin);\n        }\n\n        subjectsAndPermissions[origin].forEach((target) => {\n          const { permissions } = draftState.subjects[origin];\n          if (!hasProperty(permissions as Record<string, unknown>, target)) {\n            throw new PermissionDoesNotExistError(origin, target);\n          }\n\n          this.#deletePermission(draftState.subjects, origin, target);\n        });\n      });\n    });\n  }\n\n  /**\n   * Revokes all permissions corresponding to the specified target for all subjects.\n   * Does nothing if no subjects or no such permission exists.\n   *\n   * @param target - The name of the target to revoke all permissions for.\n   */\n  revokePermissionForAllSubjects(\n    target: ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n  ): void {\n    if (this.getSubjectNames().length === 0) {\n      return;\n    }\n\n    this.update((draftState) => {\n      Object.entries(draftState.subjects).forEach(([origin, subject]) => {\n        const { permissions } = subject;\n\n        if (hasProperty(permissions as Record<string, unknown>, target)) {\n          this.#deletePermission(draftState.subjects, origin, target);\n        }\n      });\n    });\n  }\n\n  /**\n   * Deletes the permission identified by the given origin and target. If the\n   * permission is the single remaining permission of its subject, the subject\n   * is also deleted.\n   *\n   * @param subjects - The draft permission controller subjects.\n   * @param origin - The origin of the subject associated with the permission\n   * to delete.\n   * @param target - The target name of the permission to delete.\n   */\n  #deletePermission(\n    subjects: Draft<PermissionControllerSubjects<PermissionConstraint>>,\n    origin: OriginString,\n    target: ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n  ): void {\n    const { permissions } = subjects[origin];\n    if (Object.keys(permissions).length > 1) {\n      delete permissions[target];\n    } else {\n      delete subjects[origin];\n    }\n  }\n\n  /**\n   * Checks whether the permission of the subject corresponding to the given\n   * origin has a caveat of the specified type.\n   *\n   * Throws an error if the subject does not have a permission with the\n   * specified target name.\n   *\n   * @template TargetName - The permission target name. Should be inferred.\n   * @template CaveatType - The valid caveat types for the permission. Should\n   * be inferred.\n   * @param origin - The origin of the subject.\n   * @param target - The target name of the permission.\n   * @param caveatType - The type of the caveat to check for.\n   * @returns Whether the permission has the specified caveat.\n   */\n  hasCaveat<\n    TargetName extends ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n    CaveatType extends\n      ExtractAllowedCaveatTypes<ControllerPermissionSpecification>,\n  >(origin: OriginString, target: TargetName, caveatType: CaveatType): boolean {\n    return Boolean(this.getCaveat(origin, target, caveatType));\n  }\n\n  /**\n   * Gets the caveat of the specified type, if any, for the permission of\n   * the subject corresponding to the given origin.\n   *\n   * Throws an error if the subject does not have a permission with the\n   * specified target name.\n   *\n   * @template TargetName - The permission target name. Should be inferred.\n   * @template CaveatType - The valid caveat types for the permission. Should\n   * be inferred.\n   * @param origin - The origin of the subject.\n   * @param target - The target name of the permission.\n   * @param caveatType - The type of the caveat to get.\n   * @returns The caveat, or `undefined` if no such caveat exists.\n   */\n  getCaveat<\n    TargetName extends ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n    CaveatType extends\n      ExtractAllowedCaveatTypes<ControllerPermissionSpecification>,\n  >(\n    origin: OriginString,\n    target: TargetName,\n    caveatType: CaveatType,\n  ): ExtractCaveat<ControllerCaveatSpecification, CaveatType> | undefined {\n    const permission = this.getPermission(origin, target);\n    if (!permission) {\n      throw new PermissionDoesNotExistError(origin, target);\n    }\n\n    return findCaveat(permission, caveatType) as\n      | ExtractCaveat<ControllerCaveatSpecification, CaveatType>\n      | undefined;\n  }\n\n  /**\n   * Adds a caveat of the specified type, with the specified caveat value, to\n   * the permission corresponding to the given subject origin and permission\n   * target.\n   *\n   * For modifying existing caveats, use\n   * {@link PermissionController.updateCaveat}.\n   *\n   * Throws an error if no such permission exists, or if the caveat already\n   * exists.\n   *\n   * @template TargetName - The permission target name. Should be inferred.\n   * @template CaveatType - The valid caveat types for the permission. Should\n   * be inferred.\n   * @param origin - The origin of the subject.\n   * @param target - The target name of the permission.\n   * @param caveatType - The type of the caveat to add.\n   * @param caveatValue - The value of the caveat to add.\n   */\n  addCaveat<\n    TargetName extends ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n    CaveatType extends\n      ExtractAllowedCaveatTypes<ControllerPermissionSpecification>,\n  >(\n    origin: OriginString,\n    target: TargetName,\n    caveatType: CaveatType,\n    caveatValue: ExtractCaveatValue<ControllerCaveatSpecification, CaveatType>,\n  ): void {\n    if (this.hasCaveat(origin, target, caveatType)) {\n      throw new CaveatAlreadyExistsError(origin, target, caveatType);\n    }\n\n    this.#setCaveat(origin, target, caveatType, caveatValue);\n  }\n\n  /**\n   * Updates the value of the caveat of the specified type belonging to the\n   * permission corresponding to the given subject origin and permission\n   * target.\n   *\n   * For adding new caveats, use\n   * {@link PermissionController.addCaveat}.\n   *\n   * Throws an error if no such permission or caveat exists.\n   *\n   * @template TargetName - The permission target name. Should be inferred.\n   * @template CaveatType - The valid caveat types for the permission. Should\n   * be inferred.\n   * @param origin - The origin of the subject.\n   * @param target - The target name of the permission.\n   * @param caveatType - The type of the caveat to update.\n   * @param caveatValue - The new value of the caveat.\n   */\n  updateCaveat<\n    TargetName extends ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n    CaveatType extends\n      ExtractAllowedCaveatTypes<ControllerPermissionSpecification>,\n    CaveatValue extends ExtractCaveatValue<\n      ControllerCaveatSpecification,\n      CaveatType\n    >,\n  >(\n    origin: OriginString,\n    target: TargetName,\n    caveatType: CaveatType,\n    caveatValue: CaveatValue,\n  ): void {\n    if (!this.hasCaveat(origin, target, caveatType)) {\n      throw new CaveatDoesNotExistError(origin, target, caveatType);\n    }\n\n    this.#setCaveat(origin, target, caveatType, caveatValue);\n  }\n\n  /**\n   * Sets the specified caveat on the specified permission. Overwrites existing\n   * caveats of the same type in-place (preserving array order), and adds the\n   * caveat to the end of the array otherwise.\n   *\n   * Throws an error if the permission does not exist or fails to validate after\n   * its caveats have been modified.\n   *\n   * @see {@link PermissionController.addCaveat}\n   * @see {@link PermissionController.updateCaveat}\n   * @template TargetName - The permission target name. Should be inferred.\n   * @template CaveatType - The valid caveat types for the permission. Should\n   * be inferred.\n   * @param origin - The origin of the subject.\n   * @param target - The target name of the permission.\n   * @param caveatType - The type of the caveat to set.\n   * @param caveatValue - The value of the caveat to set.\n   */\n  #setCaveat<\n    TargetName extends ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n    CaveatType extends\n      ExtractAllowedCaveatTypes<ControllerPermissionSpecification>,\n  >(\n    origin: OriginString,\n    target: TargetName,\n    caveatType: CaveatType,\n    caveatValue: ExtractCaveatValue<ControllerCaveatSpecification, CaveatType>,\n  ): void {\n    this.update((draftState) => {\n      const subject = draftState.subjects[origin];\n\n      // Unreachable because `hasCaveat` is always called before this, and it\n      // throws if permissions are missing. TypeScript needs this, however.\n      /* istanbul ignore if */\n      if (!subject) {\n        throw new UnrecognizedSubjectError(origin);\n      }\n\n      const permission = subject.permissions[target];\n\n      /* istanbul ignore if: practically impossible, but TypeScript wants it */\n      if (!permission) {\n        throw new PermissionDoesNotExistError(origin, target);\n      }\n\n      const caveat = {\n        type: caveatType,\n        value: caveatValue,\n      };\n      this.#validateCaveat(caveat, origin, target);\n\n      let addedCaveat = false;\n      if (permission.caveats) {\n        const caveatIndex = permission.caveats.findIndex(\n          (existingCaveat) => existingCaveat.type === caveat.type,\n        );\n\n        if (caveatIndex === -1) {\n          permission.caveats.push(caveat);\n          addedCaveat = true;\n        } else {\n          permission.caveats.splice(caveatIndex, 1, caveat);\n        }\n      } else {\n        // At this point, we don't know if the specific permission is allowed\n        // to have caveats, but it should be impossible to call this method\n        // for a permission that may not have any caveats. If all else fails,\n        // the permission validator is also called.\n        // @ts-expect-error See above comment\n        permission.caveats = [caveat];\n        addedCaveat = true;\n      }\n\n      // Mutating a caveat does not warrant permission validation, but mutating\n      // the caveat array does.\n      if (addedCaveat) {\n        this.#validateModifiedPermission(permission, origin, {\n          invokePermissionValidator: true,\n          performCaveatValidation: false, // We just validated the caveat\n        });\n      }\n    });\n  }\n\n  /**\n   * Updates all caveats with the specified type for all subjects and\n   * permissions by applying the specified mutator function to them.\n   *\n   * ATTN: Permissions can be revoked entirely by the action of this method,\n   * read on for details.\n   *\n   * Caveat mutators are functions that receive a caveat value and return a\n   * tuple consisting of a {@link CaveatMutatorOperation} and, optionally, a new\n   * value to update the existing caveat with.\n   *\n   * For each caveat, depending on the mutator result, this method will:\n   * - Do nothing ({@link CaveatMutatorOperation.Noop})\n   * - Update the value of the caveat ({@link CaveatMutatorOperation.UpdateValue}). The caveat specification validator, if any, will be called after updating the value.\n   * - Delete the caveat ({@link CaveatMutatorOperation.DeleteCaveat}). The permission specification validator, if any, will be called after deleting the caveat.\n   * - Revoke the parent permission ({@link CaveatMutatorOperation.RevokePermission})\n   *\n   * This method throws if the validation of any caveat or permission fails.\n   *\n   * @param targetCaveatType - The type of the caveats to update.\n   * @param mutator - The mutator function which will be applied to all caveat\n   * values.\n   */\n  updatePermissionsByCaveat<\n    CaveatType extends ExtractCaveats<ControllerCaveatSpecification>['type'],\n    TargetCaveat extends ExtractCaveat<\n      ControllerCaveatSpecification,\n      CaveatType\n    >,\n  >(targetCaveatType: CaveatType, mutator: CaveatMutator<TargetCaveat>): void {\n    if (Object.keys(this.state.subjects).length === 0) {\n      return;\n    }\n\n    this.update((draftState) => {\n      Object.values(draftState.subjects).forEach((subject) => {\n        Object.values(subject.permissions).forEach((permission) => {\n          const { caveats } = permission;\n          const targetCaveat = caveats?.find(\n            ({ type }) => type === targetCaveatType,\n          );\n          if (!targetCaveat) {\n            return;\n          }\n\n          // The mutator may modify the caveat value in place, and must always\n          // return a valid mutation result.\n          const mutatorResult = mutator(targetCaveat.value);\n          const { operation } = mutatorResult;\n          switch (operation) {\n            case CaveatMutatorOperation.Noop:\n              break;\n\n            case CaveatMutatorOperation.UpdateValue:\n              // Typecast: `Mutable` is used here to assign to a readonly\n              // property. `targetConstraint` should already be mutable because\n              // it's part of a draft, but for some reason it's not. We can't\n              // use the more-correct `Draft` type here either because it\n              // results in an error.\n              (targetCaveat as Mutable<CaveatConstraint, 'value'>).value =\n                mutatorResult.value;\n\n              this.#validateCaveat(\n                targetCaveat,\n                subject.origin,\n                permission.parentCapability,\n              );\n              break;\n\n            case CaveatMutatorOperation.DeleteCaveat:\n              this.#deleteCaveat(permission, targetCaveatType, subject.origin);\n              break;\n\n            case CaveatMutatorOperation.RevokePermission:\n              this.#deletePermission(\n                draftState.subjects,\n                subject.origin,\n                permission.parentCapability,\n              );\n              break;\n\n            default: {\n              // Overriding as `never` is the expected result of exhaustiveness checking,\n              // and is intended to represent unchecked exception cases.\n              // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n              throw new Error(`Unrecognized mutation result: \"${operation}\"`);\n            }\n          }\n        });\n      });\n    });\n  }\n\n  /**\n   * Removes the caveat of the specified type from the permission corresponding\n   * to the given subject origin and target name.\n   *\n   * Throws an error if no such permission or caveat exists.\n   *\n   * @template TargetName - The permission target name. Should be inferred.\n   * @template CaveatType - The valid caveat types for the permission. Should\n   * be inferred.\n   * @param origin - The origin of the subject.\n   * @param target - The target name of the permission.\n   * @param caveatType - The type of the caveat to remove.\n   */\n  removeCaveat<\n    TargetName extends ControllerPermissionSpecification['targetName'],\n    CaveatType extends\n      ExtractAllowedCaveatTypes<ControllerPermissionSpecification>,\n  >(origin: OriginString, target: TargetName, caveatType: CaveatType): void {\n    this.update((draftState) => {\n      const permission = draftState.subjects[origin]?.permissions[target];\n      if (!permission) {\n        throw new PermissionDoesNotExistError(origin, target);\n      }\n\n      if (!permission.caveats) {\n        throw new CaveatDoesNotExistError(origin, target, caveatType);\n      }\n\n      this.#deleteCaveat(permission, caveatType, origin);\n    });\n  }\n\n  /**\n   * Deletes the specified caveat from the specified permission. If no caveats\n   * remain after deletion, the permission's caveat property is set to `null`.\n   * The permission is validated after being modified.\n   *\n   * Throws an error if the permission does not have a caveat with the specified\n   * type.\n   *\n   * @param permission - The permission whose caveat to delete.\n   * @param caveatType - The type of the caveat to delete.\n   * @param origin - The origin the permission subject.\n   */\n  #deleteCaveat<\n    CaveatType extends ExtractCaveats<ControllerCaveatSpecification>['type'],\n  >(\n    permission: Draft<PermissionConstraint>,\n    caveatType: CaveatType,\n    origin: OriginString,\n  ): void {\n    /* istanbul ignore if: not possible in our usage */\n    if (!permission.caveats) {\n      throw new CaveatDoesNotExistError(\n        origin,\n        permission.parentCapability,\n        caveatType,\n      );\n    }\n\n    const caveatIndex = permission.caveats.findIndex(\n      (existingCaveat) => existingCaveat.type === caveatType,\n    );\n\n    if (caveatIndex === -1) {\n      throw new CaveatDoesNotExistError(\n        origin,\n        permission.parentCapability,\n        caveatType,\n      );\n    }\n\n    if (permission.caveats.length === 1) {\n      permission.caveats = null;\n    } else {\n      permission.caveats.splice(caveatIndex, 1);\n    }\n\n    this.#validateModifiedPermission(permission, origin, {\n      invokePermissionValidator: true,\n      performCaveatValidation: false, // No caveat object was mutated\n    });\n  }\n\n  /**\n   * Validates the specified modified permission. Should **always** be invoked\n   * on a permission when its caveat array has been mutated.\n   *\n   * Just like {@link PermissionController.#validatePermission}, except that the\n   * corresponding target name and specification are retrieved first, and an\n   * error is thrown if the target name does not exist.\n   *\n   * @param permission - The modified permission to validate.\n   * @param origin - The origin associated with the permission.\n   * @param validationFlags - Validation flags. See {@link PermissionController.#validatePermission}.\n   */\n  #validateModifiedPermission(\n    permission: Draft<PermissionConstraint>,\n    origin: OriginString,\n    validationFlags: PermissionValidationFlags,\n  ): void {\n    /* istanbul ignore if: this should be impossible */\n    if (!this.#targetExists(permission.parentCapability)) {\n      throw new Error(\n        `Fatal: Existing permission target \"${permission.parentCapability}\" has no specification.`,\n      );\n    }\n\n    this.#validatePermission(\n      this.#getPermissionSpecification(permission.parentCapability),\n      permission as PermissionConstraint,\n      origin,\n      validationFlags,\n    );\n  }\n\n  /**\n   * Verifies the existence the specified permission target, i.e. whether it has\n   * a specification.\n   *\n   * @param target - The requested permission target.\n   * @returns Whether the permission target exists.\n   */\n  #targetExists(\n    target: string,\n  ): target is ControllerPermissionSpecification['targetName'] {\n    return hasProperty(this.#permissionSpecifications, target);\n  }\n\n  /**\n   * Grants _approved_ permissions to the specified subject. Every permission and\n   * caveat is stringently validated—including by calling their specification\n   * validators—and an error is thrown if validation fails.\n   *\n   * ATTN: This method does **not** prompt the user for approval. User consent must\n   * first be obtained through some other means.\n   *\n   * @see {@link PermissionController.requestPermissions} For initiating a\n   * permissions request requiring user approval.\n   * @param options - Options bag.\n   * @param options.approvedPermissions - The requested permissions approved by\n   * the user.\n   * @param options.requestData - Permission request data. Passed to permission\n   * factory functions.\n   * @param options.preserveExistingPermissions - Whether to preserve the\n   * subject's existing permissions.\n   * @param options.subject - The subject to grant permissions to.\n   * @returns The subject's new permission state. It may or may not have changed.\n   */\n  grantPermissions({\n    approvedPermissions,\n    requestData,\n    preserveExistingPermissions = true,\n    subject,\n  }: {\n    approvedPermissions: RequestedPermissions;\n    subject: PermissionSubjectMetadata;\n    preserveExistingPermissions?: boolean;\n    requestData?: Record<string, unknown>;\n  }): Partial<\n    SubjectPermissions<\n      ExtractPermission<\n        ControllerPermissionSpecification,\n        ControllerCaveatSpecification\n      >\n    >\n  > {\n    return this.#applyGrantedPermissions({\n      approvedPermissions,\n      subject,\n      mergePermissions: false,\n      preserveExistingPermissions,\n      requestData,\n    });\n  }\n\n  /**\n   * Incrementally grants _approved_ permissions to the specified subject. Every\n   * permission and caveat is stringently validated—including by calling their\n   * specification validators—and an error is thrown if validation fails.\n   *\n   * ATTN: This method does **not** prompt the user for approval. User consent must\n   * first be obtained through some other means.\n   *\n   * @see {@link PermissionController.requestPermissionsIncremental} For initiating\n   * an incremental permissions request requiring user approval.\n   * @param options - Options bag.\n   * @param options.approvedPermissions - The requested permissions approved by\n   * the user.\n   * @param options.requestData - Permission request data. Passed to permission\n   * factory functions.\n   * @param options.subject - The subject to grant permissions to.\n   * @returns The subject's new permission state. It may or may not have changed.\n   */\n  grantPermissionsIncremental({\n    approvedPermissions,\n    requestData,\n    subject,\n  }: {\n    approvedPermissions: RequestedPermissions;\n    subject: PermissionSubjectMetadata;\n    requestData?: Record<string, unknown>;\n  }): Partial<\n    SubjectPermissions<\n      ExtractPermission<\n        ControllerPermissionSpecification,\n        ControllerCaveatSpecification\n      >\n    >\n  > {\n    return this.#applyGrantedPermissions({\n      approvedPermissions,\n      subject,\n      mergePermissions: true,\n      preserveExistingPermissions: true,\n      requestData,\n    });\n  }\n\n  #applyGrantedPermissions({\n    approvedPermissions,\n    subject,\n    mergePermissions,\n    preserveExistingPermissions,\n    requestData,\n  }: {\n    approvedPermissions: RequestedPermissions;\n    subject: PermissionSubjectMetadata;\n    mergePermissions: boolean;\n    preserveExistingPermissions: boolean;\n    requestData?: Record<string, unknown>;\n  }): Partial<\n    SubjectPermissions<\n      ExtractPermission<\n        ControllerPermissionSpecification,\n        ControllerCaveatSpecification\n      >\n    >\n  > {\n    const { origin } = subject;\n\n    if (!origin || typeof origin !== 'string') {\n      throw new InvalidSubjectIdentifierError(origin);\n    }\n\n    const permissions = (\n      preserveExistingPermissions\n        ? {\n            ...this.getPermissions(origin),\n          }\n        : {}\n    ) as SubjectPermissions<\n      ExtractPermission<\n        ControllerPermissionSpecification,\n        ControllerCaveatSpecification\n      >\n    >;\n\n    for (const [requestedTarget, approvedPermission] of Object.entries(\n      approvedPermissions,\n    )) {\n      if (!this.#targetExists(requestedTarget)) {\n        throw methodNotFound(requestedTarget);\n      }\n\n      if (\n        approvedPermission.parentCapability !== undefined &&\n        requestedTarget !== approvedPermission.parentCapability\n      ) {\n        throw new InvalidApprovedPermissionError(\n          origin,\n          requestedTarget,\n          approvedPermission,\n        );\n      }\n\n      // We have verified that the target exists, and reassign it to change its\n      // type.\n      const targetName = requestedTarget as ExtractPermission<\n        ControllerPermissionSpecification,\n        ControllerCaveatSpecification\n      >['parentCapability'];\n      const specification = this.#getPermissionSpecification(targetName);\n\n      // The requested caveats are validated here.\n      const caveats = this.#constructCaveats(\n        origin,\n        targetName,\n        approvedPermission.caveats,\n      );\n\n      const permissionOptions = {\n        caveats,\n        invoker: origin,\n        target: targetName,\n      };\n\n      let permission: ExtractPermission<\n        ControllerPermissionSpecification,\n        ControllerCaveatSpecification\n      >;\n      if (specification.factory) {\n        permission = specification.factory(permissionOptions, requestData);\n      } else {\n        permission = constructPermission(permissionOptions);\n      }\n\n      if (mergePermissions) {\n        permission = this.#mergePermission(\n          permissions[targetName],\n          permission,\n        )[0];\n      }\n\n      this.#validatePermission(specification, permission, origin, {\n        invokePermissionValidator: true,\n        performCaveatValidation: true,\n      });\n      permissions[targetName] = permission;\n    }\n\n    this.#setValidatedPermissions(origin, permissions);\n    return permissions;\n  }\n\n  /**\n   * Validates the specified permission by:\n   * - Ensuring that if `subjectTypes` is specified, the subject requesting the permission is of a type in the list.\n   * - Ensuring that its `caveats` property is either `null` or a non-empty array.\n   * - Ensuring that it only includes caveats allowed by its specification.\n   * - Ensuring that it includes no duplicate caveats (by caveat type).\n   * - Validating each caveat object, if `performCaveatValidation` is `true`.\n   * - Calling the validator of its specification, if one exists and `invokePermissionValidator` is `true`.\n   *\n   * An error is thrown if validation fails.\n   *\n   * @param specification - The specification of the permission.\n   * @param permission - The permission to validate.\n   * @param origin - The origin associated with the permission.\n   * @param validationOptions - Validation options.\n   * @param validationOptions.invokePermissionValidator - Whether to invoke the\n   * permission's consumer-specified validator function, if any.\n   * @param validationOptions.performCaveatValidation - Whether to invoke\n   * {@link PermissionController.#validateCaveat} on each of the permission's\n   * caveats.\n   */\n  #validatePermission(\n    specification: PermissionSpecificationConstraint,\n    permission: PermissionConstraint,\n    origin: OriginString,\n    {\n      invokePermissionValidator,\n      performCaveatValidation,\n    }: PermissionValidationFlags,\n  ): void {\n    const { allowedCaveats, validator, targetName } = specification;\n\n    if (\n      specification.subjectTypes?.length &&\n      specification.subjectTypes.length > 0\n    ) {\n      const metadata = this.messenger.call(\n        'SubjectMetadataController:getSubjectMetadata',\n        origin,\n      );\n\n      if (\n        !metadata ||\n        metadata.subjectType === null ||\n        !specification.subjectTypes.includes(metadata.subjectType)\n      ) {\n        throw specification.permissionType === PermissionType.RestrictedMethod\n          ? methodNotFound(targetName, { origin })\n          : new EndowmentPermissionDoesNotExistError(targetName, origin);\n      }\n    }\n\n    if (hasProperty(permission, 'caveats')) {\n      const { caveats } = permission;\n\n      if (caveats !== null && !(Array.isArray(caveats) && caveats.length > 0)) {\n        throw new InvalidCaveatsPropertyError(origin, targetName, caveats);\n      }\n\n      const seenCaveatTypes = new Set<string>();\n      caveats?.forEach((caveat) => {\n        if (performCaveatValidation) {\n          this.#validateCaveat(caveat, origin, targetName);\n        }\n\n        if (!allowedCaveats?.includes(caveat.type)) {\n          throw new ForbiddenCaveatError(caveat.type, origin, targetName);\n        }\n\n        if (seenCaveatTypes.has(caveat.type)) {\n          throw new DuplicateCaveatError(caveat.type, origin, targetName);\n        }\n        seenCaveatTypes.add(caveat.type);\n      });\n    }\n\n    if (invokePermissionValidator && validator) {\n      validator(permission, origin, targetName);\n    }\n  }\n\n  /**\n   * Assigns the specified permissions to the subject with the given origin.\n   * Overwrites all existing permissions, and creates a subject entry if it\n   * doesn't already exist.\n   *\n   * ATTN: Assumes that the new permissions have been validated.\n   *\n   * @param origin - The origin of the grantee subject.\n   * @param permissions - The new permissions for the grantee subject.\n   */\n  #setValidatedPermissions(\n    origin: OriginString,\n    permissions: Record<\n      string,\n      ExtractPermission<\n        ControllerPermissionSpecification,\n        ControllerCaveatSpecification\n      >\n    >,\n  ): void {\n    this.update((draftState) => {\n      if (!draftState.subjects[origin]) {\n        draftState.subjects[origin] = { origin, permissions: {} };\n      }\n\n      draftState.subjects[origin].permissions = castDraft(permissions);\n    });\n  }\n\n  /**\n   * Validates the requested caveats for the permission of the specified\n   * subject origin and target name and returns the validated caveat array.\n   *\n   * Throws an error if validation fails.\n   *\n   * @param origin - The origin of the permission subject.\n   * @param target - The permission target name.\n   * @param requestedCaveats - The requested caveats to construct.\n   * @returns The constructed caveats.\n   */\n  #constructCaveats(\n    origin: OriginString,\n    target: ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n    requestedCaveats?: unknown[] | null,\n  ): NonEmptyArray<ExtractCaveats<ControllerCaveatSpecification>> | undefined {\n    const caveatArray = requestedCaveats?.map((requestedCaveat) => {\n      this.#validateCaveat(requestedCaveat, origin, target);\n\n      // Reassign so that we have a fresh object.\n      const { type, value } = requestedCaveat as CaveatConstraint;\n      return { type, value } as ExtractCaveats<ControllerCaveatSpecification>;\n    });\n\n    return caveatArray && isNonEmptyArray(caveatArray)\n      ? caveatArray\n      : undefined;\n  }\n\n  /**\n   * This methods validates that the specified caveat is an object with the\n   * expected properties and types. It also ensures that a caveat specification\n   * exists for the requested caveat type, and calls the specification\n   * validator, if it exists, on the caveat object.\n   *\n   * Throws an error if validation fails.\n   *\n   * @param caveat - The caveat object to validate.\n   * @param origin - The origin associated with the subject of the parent\n   * permission.\n   * @param target - The target name associated with the parent permission.\n   */\n  #validateCaveat(caveat: unknown, origin: OriginString, target: string): void {\n    if (!isPlainObject(caveat)) {\n      throw new InvalidCaveatError(caveat, origin, target);\n    }\n\n    if (Object.keys(caveat).length !== 2) {\n      throw new InvalidCaveatFieldsError(caveat, origin, target);\n    }\n\n    if (typeof caveat.type !== 'string') {\n      throw new InvalidCaveatTypeError(caveat, origin, target);\n    }\n\n    const specification = this.#getCaveatSpecification(caveat.type);\n    if (!specification) {\n      throw new UnrecognizedCaveatTypeError(caveat.type, origin, target);\n    }\n\n    if (!hasProperty(caveat, 'value') || caveat.value === undefined) {\n      throw new CaveatMissingValueError(caveat, origin, target);\n    }\n\n    if (!isValidJson(caveat.value)) {\n      throw new CaveatInvalidJsonError(caveat, origin, target);\n    }\n\n    // Typecast: TypeScript still believes that the caveat is a PlainObject.\n    specification.validator?.(caveat as CaveatConstraint, origin, target);\n  }\n\n  /**\n   * Initiates a permission request that requires user approval.\n   *\n   * Either this or {@link PermissionController.requestPermissionsIncremental}\n   * should always be used to grant additional permissions to a subject,\n   * unless user approval has been obtained through some other means.\n   *\n   * Permissions are validated at every step of the approval process, and this\n   * method will reject if validation fails.\n   *\n   * @see {@link ApprovalController} For the user approval logic.\n   * @see {@link PermissionController.acceptPermissionsRequest} For the method\n   * that _accepts_ the request and resolves the user approval promise.\n   * @see {@link PermissionController.rejectPermissionsRequest} For the method\n   * that _rejects_ the request and the user approval promise.\n   * @param subject - The grantee subject.\n   * @param requestedPermissions - The requested permissions.\n   * @param options - Additional options.\n   * @param options.id - The id of the permissions request. Defaults to a unique\n   * id.\n   * @param options.preserveExistingPermissions - Whether to preserve the\n   * subject's existing permissions. Defaults to `true`.\n   * @param options.metadata - Additional metadata about the permission request.\n   * @returns The granted permissions and request metadata.\n   */\n  async requestPermissions(\n    subject: PermissionSubjectMetadata,\n    requestedPermissions: RequestedPermissions,\n    options: {\n      id?: string;\n      preserveExistingPermissions?: boolean;\n      metadata?: Record<string, Json>;\n    } = {},\n  ): Promise<\n    [\n      Partial<\n        SubjectPermissions<\n          ExtractPermission<\n            ControllerPermissionSpecification,\n            ControllerCaveatSpecification\n          >\n        >\n      >,\n      ApprovedPermissionsMetadata,\n    ]\n  > {\n    const { origin } = subject;\n    const { id = nanoid(), preserveExistingPermissions = true } = options;\n    this.#validateRequestedPermissions(origin, requestedPermissions);\n\n    const metadata = {\n      ...options.metadata,\n      id,\n      origin,\n    };\n\n    const permissionsRequest: PermissionsRequest = {\n      metadata,\n      permissions: requestedPermissions,\n    };\n\n    const approvedRequest = await this.#requestUserApproval(permissionsRequest);\n    return await this.#handleApprovedPermissions({\n      subject,\n      metadata,\n      preserveExistingPermissions,\n      approvedRequest,\n    });\n  }\n\n  /**\n   * Initiates an incremental permission request that prompts for user approval.\n   * Incremental permission requests allow the caller to replace existing and/or\n   * add brand new permissions and caveats for the specified subject.\n   *\n   * Incremental permission request are merged with the subject's existing permissions\n   * through a right-biased union, where the incremental permission are the right-hand\n   * side of the merger. If both sides of the merger specify the same caveats for a\n   * given permission, the caveats are merged using their specification's caveat value\n   * merger property.\n   *\n   * Either this or {@link PermissionController.requestPermissions} should\n   * always be used to grant additional permissions to a subject, unless user\n   * approval has been obtained through some other means.\n   *\n   * Permissions are validated at every step of the approval process, and this\n   * method will reject if validation fails.\n   *\n   * @see {@link ApprovalController} For the user approval logic.\n   * @see {@link PermissionController.acceptPermissionsRequest} For the method\n   * that _accepts_ the request and resolves the user approval promise.\n   * @see {@link PermissionController.rejectPermissionsRequest} For the method\n   * that _rejects_ the request and the user approval promise.\n   * @param subject - The grantee subject.\n   * @param requestedPermissions - The requested permissions.\n   * @param options - Additional options.\n   * @param options.id - The id of the permissions request. Defaults to a unique\n   * id.\n   * @param options.metadata - Additional metadata about the permission request.\n   * @returns The granted permissions and request metadata.\n   */\n  async requestPermissionsIncremental(\n    subject: PermissionSubjectMetadata,\n    requestedPermissions: RequestedPermissions,\n    options: {\n      id?: string;\n      metadata?: Record<string, Json>;\n    } = {},\n  ): Promise<\n    | [\n        Partial<\n          SubjectPermissions<\n            ExtractPermission<\n              ControllerPermissionSpecification,\n              ControllerCaveatSpecification\n            >\n          >\n        >,\n        ApprovedPermissionsMetadata,\n      ]\n    | []\n  > {\n    const { origin } = subject;\n    const { id = nanoid() } = options;\n    this.#validateRequestedPermissions(origin, requestedPermissions);\n\n    const currentPermissions = this.getPermissions(origin) ?? {};\n    const [newPermissions, permissionDiffMap] =\n      this.#mergeIncrementalPermissions(\n        currentPermissions,\n        requestedPermissions,\n      );\n\n    // The second undefined check is just for type narrowing purposes. These values\n    // will always be jointly defined or undefined.\n    if (newPermissions === undefined || permissionDiffMap === undefined) {\n      return [];\n    }\n\n    try {\n      // It does not spark joy to run this validation again after the merger operation.\n      // But, optimizing this procedure is probably not worth it, especially considering\n      // that the worst-case scenario for validation degrades to the below function call.\n      this.#validateRequestedPermissions(origin, newPermissions);\n    } catch (error) {\n      if (error instanceof Error) {\n        throw new InvalidMergedPermissionsError(\n          origin,\n          error,\n          permissionDiffMap,\n        );\n      }\n      /* istanbul ignore next: This should be impossible */\n      throw internalError('Unrecognized error type', { error });\n    }\n\n    const metadata = {\n      ...options.metadata,\n      id,\n      origin,\n    };\n\n    const permissionsRequest: PermissionsRequest = {\n      metadata,\n      permissions: newPermissions,\n      diff: {\n        currentPermissions,\n        permissionDiffMap,\n      },\n    };\n\n    const approvedRequest = await this.#requestUserApproval(permissionsRequest);\n    return await this.#handleApprovedPermissions({\n      subject,\n      metadata,\n      preserveExistingPermissions: false,\n      approvedRequest,\n    });\n  }\n\n  /**\n   * Validates requested permissions. Throws if validation fails.\n   *\n   * This method ensures that the requested permissions are a properly\n   * formatted {@link RequestedPermissions} object, and performs the same\n   * validation as {@link PermissionController.grantPermissions}, except that\n   * consumer-specified permission validator functions are not called, since\n   * they are only called on fully constructed, approved permissions that are\n   * otherwise completely valid.\n   *\n   * Unrecognzied properties on requested permissions are ignored.\n   *\n   * @param origin - The origin of the grantee subject.\n   * @param requestedPermissions - The requested permissions.\n   */\n  #validateRequestedPermissions(\n    origin: OriginString,\n    requestedPermissions: unknown,\n  ): void {\n    if (!isPlainObject(requestedPermissions)) {\n      throw invalidParams({\n        message: `Requested permissions for origin \"${origin}\" is not a plain object.`,\n        data: { origin, requestedPermissions },\n      });\n    }\n\n    if (Object.keys(requestedPermissions).length === 0) {\n      throw invalidParams({\n        message: `Permissions request for origin \"${origin}\" contains no permissions.`,\n        data: { requestedPermissions },\n      });\n    }\n\n    for (const targetName of Object.keys(requestedPermissions)) {\n      const permission = requestedPermissions[targetName];\n\n      if (!this.#targetExists(targetName)) {\n        throw methodNotFound(targetName, { origin, requestedPermissions });\n      }\n\n      if (\n        !isPlainObject(permission) ||\n        (permission.parentCapability !== undefined &&\n          targetName !== permission.parentCapability)\n      ) {\n        throw invalidParams({\n          message: `Permissions request for origin \"${origin}\" contains invalid requested permission(s).`,\n          data: { origin, requestedPermissions },\n        });\n      }\n\n      // Here we validate the permission without invoking its validator, if any.\n      // The validator will be invoked after the permission has been approved.\n      this.#validatePermission(\n        this.#getPermissionSpecification(targetName),\n        // Typecast: The permission is still a \"PlainObject\" here.\n        permission as PermissionConstraint,\n        origin,\n        { invokePermissionValidator: false, performCaveatValidation: true },\n      );\n    }\n  }\n\n  /**\n   * Merges a set of incrementally requested permissions into the existing permissions of\n   * the requesting subject. The merge is a right-biased union, where the existing\n   * permissions are the left-hand side, and the incrementally requested permissions are\n   * the right-hand side.\n   *\n   * @param existingPermissions - The subject's existing permissions.\n   * @param incrementalRequestedPermissions - The requested permissions to merge.\n   * @returns The merged permissions and the resulting diff.\n   */\n  #mergeIncrementalPermissions(\n    existingPermissions: Exclude<\n      ReturnType<typeof this.getPermissions>,\n      undefined\n    >,\n    incrementalRequestedPermissions: RequestedPermissions,\n  ):\n    | [\n        SubjectPermissions<\n          ValidPermission<string, ExtractCaveats<ControllerCaveatSpecification>>\n        >,\n        PermissionDiffMap<string, CaveatConstraint>,\n      ]\n    | [] {\n    const permissionDiffMap: PermissionDiffMap<string, CaveatConstraint> = {};\n\n    // Use immer's produce as a convenience for calculating the new permissions\n    // without mutating the existing permissions or committing the results to state.\n    const newPermissions = immerProduce(\n      existingPermissions,\n      (draftExistingPermissions) => {\n        const leftPermissions =\n          draftExistingPermissions as RequestedPermissions;\n\n        Object.entries(incrementalRequestedPermissions).forEach(\n          ([targetName, rightPermission]) => {\n            const leftPermission: Partial<PermissionConstraint> | undefined =\n              leftPermissions[targetName];\n\n            const [newPermission, caveatsDiff] = this.#mergePermission(\n              leftPermission ?? {},\n              rightPermission,\n            );\n\n            if (\n              leftPermission === undefined ||\n              Object.keys(caveatsDiff).length > 0\n            ) {\n              leftPermissions[targetName] = newPermission;\n              permissionDiffMap[targetName] = caveatsDiff;\n            }\n            // Otherwise, leave the left permission as-is; its authority has\n            // not changed.\n          },\n        );\n      },\n    );\n\n    if (Object.keys(permissionDiffMap).length === 0) {\n      return [];\n    }\n    return [newPermissions, permissionDiffMap];\n  }\n\n  /**\n   * Performs a right-biased union between two permissions. The task of merging caveats\n   * of the same type between the two permissions is delegated to the corresponding\n   * caveat type's merger implementation.\n   *\n   * Throws if the left-hand and right-hand permissions both have a caveat whose\n   * specification does not provide a caveat value merger function.\n   *\n   * @param leftPermission - The left-hand permission to merge.\n   * @param rightPermission - The right-hand permission to merge.\n   * @returns The merged permission.\n   */\n  #mergePermission<\n    PermissionType extends Partial<PermissionConstraint> | PermissionConstraint,\n  >(\n    leftPermission: PermissionType | undefined,\n    rightPermission: PermissionType,\n  ): [PermissionType, CaveatDiffMap<CaveatConstraint>] {\n    const { caveatPairs, leftUniqueCaveats, rightUniqueCaveats } =\n      collectUniqueAndPairedCaveats(leftPermission, rightPermission);\n\n    const [mergedCaveats, caveatDiffMap] = caveatPairs.reduce<\n      [CaveatConstraint[], CaveatDiffMap<CaveatConstraint>]\n    >(\n      ([caveats, diffMap], [leftCaveat, rightCaveat]) => {\n        const [newCaveat, diff] = this.#mergeCaveat(leftCaveat, rightCaveat);\n\n        if (newCaveat !== undefined && diff !== undefined) {\n          caveats.push(newCaveat);\n          diffMap[newCaveat.type] = diff;\n        } else {\n          caveats.push(leftCaveat);\n        }\n\n        return [caveats, diffMap];\n      },\n      [[], {}],\n    );\n\n    const mergedRightUniqueCaveats = rightUniqueCaveats.map((caveat) => {\n      const [newCaveat, diff] = this.#mergeCaveat(undefined, caveat);\n\n      caveatDiffMap[newCaveat.type] = diff;\n      return newCaveat;\n    });\n\n    const allCaveats = [\n      ...mergedCaveats,\n      ...leftUniqueCaveats,\n      ...mergedRightUniqueCaveats,\n    ];\n\n    const newPermission = {\n      ...leftPermission,\n      ...rightPermission,\n      ...(allCaveats.length > 0\n        ? { caveats: allCaveats as NonEmptyArray<CaveatConstraint> }\n        : {}),\n    };\n\n    return [newPermission, caveatDiffMap];\n  }\n\n  /**\n   * Merges two caveats of the same type. The task of merging the values of the\n   * two caveats is delegated to the corresponding caveat type's merger implementation.\n   *\n   * @param leftCaveat - The left-hand caveat to merge.\n   * @param rightCaveat - The right-hand caveat to merge.\n   * @returns The merged caveat and the diff between the two caveats.\n   */\n  #mergeCaveat<\n    RightCaveat extends CaveatConstraint,\n    LeftCaveat extends RightCaveat | undefined,\n  >(\n    leftCaveat: LeftCaveat,\n    rightCaveat: RightCaveat,\n  ): MergeCaveatResult<LeftCaveat> {\n    /* istanbul ignore if: This should be impossible */\n    if (leftCaveat !== undefined && leftCaveat.type !== rightCaveat.type) {\n      throw new CaveatMergeTypeMismatchError(leftCaveat.type, rightCaveat.type);\n    }\n\n    const merger = this.#expectGetCaveatMerger(rightCaveat.type);\n\n    if (leftCaveat === undefined) {\n      return [\n        {\n          ...rightCaveat,\n        },\n        rightCaveat.value,\n      ];\n    }\n\n    const [newValue, diff] = merger(leftCaveat.value, rightCaveat.value);\n\n    return newValue !== undefined && diff !== undefined\n      ? [\n          {\n            type: rightCaveat.type,\n            value: newValue,\n          },\n          diff,\n        ]\n      : ([] as MergeCaveatResult<LeftCaveat>);\n  }\n\n  /**\n   * Adds a request to the {@link ApprovalController} using the\n   * {@link ApprovalControllerAddRequestAction} action. Also validates the resulting approved\n   * permissions request, and throws an error if validation fails.\n   *\n   * @param permissionsRequest - The permissions request object.\n   * @returns The approved permissions request object.\n   */\n  async #requestUserApproval(\n    permissionsRequest: PermissionsRequest,\n  ): Promise<PermissionsRequest> {\n    const { origin, id } = permissionsRequest.metadata;\n    const approvedRequest = await this.messenger.call(\n      'ApprovalController:addRequest',\n      {\n        id,\n        origin,\n        requestData: permissionsRequest,\n        type: MethodNames.RequestPermissions,\n      },\n      true,\n    );\n\n    this.#validateApprovedPermissions(approvedRequest, { id, origin });\n    return approvedRequest as PermissionsRequest;\n  }\n\n  /**\n   * Accepts a permissions request that has been approved by the user. This\n   * method should be called after the user has approved the request and the\n   * {@link ApprovalController} has resolved the user approval promise.\n   *\n   * @param options - Options bag.\n   * @param options.subject - The subject to grant permissions to.\n   * @param options.metadata - The metadata of the approved permissions request.\n   * @param options.preserveExistingPermissions - Whether to preserve the\n   * subject's existing permissions.\n   * @param options.approvedRequest - The approved permissions request to handle.\n   * @returns The granted permissions and request metadata.\n   */\n  async #handleApprovedPermissions({\n    subject,\n    metadata,\n    preserveExistingPermissions,\n    approvedRequest,\n  }: {\n    subject: PermissionSubjectMetadata;\n    metadata: PermissionsRequest['metadata'];\n    preserveExistingPermissions: boolean;\n    approvedRequest: PermissionsRequest;\n  }): Promise<\n    [ReturnType<typeof this.grantPermissions>, ApprovedPermissionsMetadata]\n  > {\n    const { permissions: approvedPermissions, ...requestData } =\n      approvedRequest;\n    const approvedMetadata: ApprovedPermissionsMetadata = { ...metadata };\n\n    const sideEffects = this.#getSideEffects(approvedPermissions);\n    if (Object.values(sideEffects.permittedHandlers).length > 0) {\n      const sideEffectsData = await this.#executeSideEffects(\n        sideEffects,\n        approvedRequest,\n      );\n\n      approvedMetadata.data = Object.keys(sideEffects.permittedHandlers).reduce(\n        (acc, permission, i) => ({ [permission]: sideEffectsData[i], ...acc }),\n        {},\n      );\n    }\n\n    return [\n      this.grantPermissions({\n        subject,\n        approvedPermissions,\n        preserveExistingPermissions,\n        requestData,\n      }),\n      approvedMetadata,\n    ];\n  }\n\n  /**\n   * Reunites all the side-effects (onPermitted and onFailure) of the requested permissions inside a record of arrays.\n   *\n   * @param permissions - The approved permissions.\n   * @returns The {@link SideEffects} object containing the handlers arrays.\n   */\n  #getSideEffects(permissions: RequestedPermissions): SideEffects {\n    return Object.keys(permissions).reduce<SideEffects>(\n      (sideEffectList, targetName) => {\n        if (this.#targetExists(targetName)) {\n          const specification = this.#getPermissionSpecification(targetName);\n\n          if (specification.sideEffect) {\n            sideEffectList.permittedHandlers[targetName] =\n              specification.sideEffect.onPermitted;\n\n            if (specification.sideEffect.onFailure) {\n              sideEffectList.failureHandlers[targetName] =\n                specification.sideEffect.onFailure;\n            }\n          }\n        }\n        return sideEffectList;\n      },\n      { permittedHandlers: {}, failureHandlers: {} },\n    );\n  }\n\n  /**\n   * Executes the side-effects of the approved permissions while handling the errors if any.\n   * It will pass an instance of the {@link messenger} and the request data associated with the permission request to the handlers through its params.\n   *\n   * @param sideEffects - the side-effect record created by {@link #getSideEffects}\n   * @param requestData - the permissions requestData.\n   * @returns the value returned by all the `onPermitted` handlers in an array.\n   */\n  async #executeSideEffects(\n    sideEffects: SideEffects,\n    requestData: PermissionsRequest,\n  ): Promise<unknown[]> {\n    const { permittedHandlers, failureHandlers } = sideEffects;\n    const params = {\n      requestData,\n      messenger: this.messenger,\n    };\n\n    const promiseResults = await Promise.allSettled(\n      Object.values(permittedHandlers).map((permittedHandler) =>\n        permittedHandler(params),\n      ),\n    );\n\n    // lib.es2020.promise.d.ts does not export its types so we're using a simple type.\n    const rejectedHandlers = promiseResults.filter(\n      (promise) => promise.status === 'rejected',\n    ) as { status: 'rejected'; reason: Error }[];\n\n    if (rejectedHandlers.length > 0) {\n      const failureHandlersList = Object.values(failureHandlers);\n      if (failureHandlersList.length > 0) {\n        try {\n          await Promise.all(\n            failureHandlersList.map((failureHandler) => failureHandler(params)),\n          );\n        } catch (error) {\n          throw internalError('Unexpected error in side-effects', { error });\n        }\n      }\n      const reasons = rejectedHandlers.map((handler) => handler.reason);\n\n      reasons.forEach((reason) => {\n        console.error(reason);\n      });\n\n      throw reasons.length > 1\n        ? internalError(\n            'Multiple errors occurred during side-effects execution',\n            { errors: reasons },\n          )\n        : reasons[0];\n    }\n\n    // lib.es2020.promise.d.ts does not export its types so we're using a simple type.\n    return (promiseResults as { status: 'fulfilled'; value: unknown }[]).map(\n      ({ value }) => value,\n    );\n  }\n\n  /**\n   * Validates an approved {@link PermissionsRequest} object. The approved\n   * request must have the required `metadata` and `permissions` properties,\n   * the `id` and `origin` of the `metadata` must match the original request\n   * metadata, and the requested permissions must be valid per\n   * {@link PermissionController.#validateRequestedPermissions}. Any extra\n   * metadata properties are ignored.\n   *\n   * An error is thrown if validation fails.\n   *\n   * @param approvedRequest - The approved permissions request object.\n   * @param originalMetadata - The original request metadata.\n   */\n  #validateApprovedPermissions(\n    approvedRequest: unknown,\n    originalMetadata: PermissionsRequestMetadata,\n  ): void {\n    const { id, origin } = originalMetadata;\n\n    if (\n      !isPlainObject(approvedRequest) ||\n      !isPlainObject(approvedRequest.metadata)\n    ) {\n      throw internalError(\n        `Approved permissions request for subject \"${origin}\" is invalid.`,\n        { data: { approvedRequest } },\n      );\n    }\n\n    const {\n      metadata: { id: newId, origin: newOrigin },\n      permissions,\n    } = approvedRequest;\n\n    if (newId !== id) {\n      throw internalError(\n        `Approved permissions request for subject \"${origin}\" mutated its id.`,\n        { originalId: id, mutatedId: newId },\n      );\n    }\n\n    if (newOrigin !== origin) {\n      throw internalError(\n        `Approved permissions request for subject \"${origin}\" mutated its origin.`,\n        { originalOrigin: origin, mutatedOrigin: newOrigin },\n      );\n    }\n\n    try {\n      this.#validateRequestedPermissions(origin, permissions);\n    } catch (error) {\n      if (error instanceof Error) {\n        // Re-throw as an internal error; we should never receive invalid approved\n        // permissions.\n        throw internalError(\n          `Invalid approved permissions request: ${error.message}`,\n          error instanceof JsonRpcError ? error.data : undefined,\n        );\n      }\n      /* istanbul ignore next: This should be impossible */\n      throw internalError('Unrecognized error type', { error });\n    }\n  }\n\n  /**\n   * Accepts a permissions request created by\n   * {@link PermissionController.requestPermissions}.\n   *\n   * @param request - The permissions request.\n   */\n  async acceptPermissionsRequest(request: PermissionsRequest): Promise<void> {\n    const { id } = request.metadata;\n\n    if (!this.#hasApprovalRequest({ id })) {\n      throw new PermissionsRequestNotFoundError(id);\n    }\n\n    if (Object.keys(request.permissions).length === 0) {\n      this.#rejectPermissionsRequest(\n        id,\n        invalidParams({\n          message: 'Must request at least one permission.',\n        }),\n      );\n      return;\n    }\n\n    try {\n      await this.messenger.call(\n        'ApprovalController:acceptRequest',\n        id,\n        request,\n      );\n    } catch (error) {\n      // If accepting unexpectedly fails, reject the request and re-throw the\n      // error\n      this.#rejectPermissionsRequest(id, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Rejects a permissions request created by\n   * {@link PermissionController.requestPermissions}.\n   *\n   * @param id - The id of the request to be rejected.\n   */\n  async rejectPermissionsRequest(id: string): Promise<void> {\n    if (!this.#hasApprovalRequest({ id })) {\n      throw new PermissionsRequestNotFoundError(id);\n    }\n\n    this.#rejectPermissionsRequest(id, userRejectedRequest());\n  }\n\n  /**\n   * Checks whether the {@link ApprovalController} has a particular permissions\n   * request.\n   *\n   * @see {@link PermissionController.acceptPermissionsRequest} and\n   * {@link PermissionController.rejectPermissionsRequest} for usage.\n   * @param options - The {@link ApprovalControllerHasRequestAction} options.\n   * @param options.id - The id of the approval request to check for.\n   * @returns Whether the specified request exists.\n   */\n  #hasApprovalRequest(options: { id: string }): boolean {\n    return this.messenger.call('ApprovalController:hasRequest', options);\n  }\n\n  /**\n   * Rejects the permissions request with the specified id, with the specified\n   * error as the reason. This method is effectively a wrapper around a\n   * messenger call for the `ApprovalController:rejectRequest` action.\n   *\n   * @see {@link PermissionController.acceptPermissionsRequest} and\n   * {@link PermissionController.rejectPermissionsRequest} for usage.\n   * @param id - The id of the request to reject.\n   * @param error - The error associated with the rejection.\n   * @returns Nothing\n   */\n  #rejectPermissionsRequest(id: string, error: unknown): void {\n    return this.messenger.call('ApprovalController:rejectRequest', id, error);\n  }\n\n  /**\n   * Gets the subject's endowments per the specified endowment permission.\n   * Throws if the subject does not have the required permission or if the\n   * permission is not an endowment permission.\n   *\n   * @param origin - The origin of the subject whose endowments to retrieve.\n   * @param targetName - The name of the endowment permission. This must be a\n   * valid permission target name.\n   * @param requestData - Additional data associated with the request, if any.\n   * Forwarded to the endowment getter function for the permission.\n   * @returns The endowments, if any.\n   */\n  async getEndowments(\n    origin: string,\n    targetName: ExtractEndowmentPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n    requestData?: unknown,\n  ): Promise<Json> {\n    if (!this.hasPermission(origin, targetName)) {\n      throw unauthorized({ data: { origin, targetName } });\n    }\n\n    return this.#getTypedPermissionSpecification(\n      PermissionType.Endowment,\n      targetName,\n      origin,\n    ).endowmentGetter({ origin, requestData });\n  }\n\n  /**\n   * Executes a restricted method as the subject with the given origin.\n   * The specified params, if any, will be passed to the method implementation.\n   *\n   * ATTN: Great caution should be exercised in the use of this method.\n   * Methods that cause side effects or affect application state should\n   * be avoided.\n   *\n   * This method will first attempt to retrieve the requested restricted method\n   * implementation, throwing if it does not exist. The method will then be\n   * invoked as though the subject with the specified origin had invoked it with\n   * the specified parameters. This means that any existing caveats will be\n   * applied to the restricted method, and this method will throw if the\n   * restricted method or its caveat decorators throw.\n   *\n   * In addition, this method will throw if the subject does not have a\n   * permission for the specified restricted method.\n   *\n   * @param origin - The origin of the subject to execute the method on behalf\n   * of.\n   * @param targetName - The name of the method to execute. This must be a valid\n   * permission target name.\n   * @param params - The parameters to pass to the method implementation.\n   * @returns The result of the executed method.\n   */\n  async executeRestrictedMethod(\n    origin: OriginString,\n    targetName: ExtractRestrictedMethodPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n    params?: RestrictedMethodParameters,\n  ): Promise<Json> {\n    // Throws if the method does not exist\n    const methodImplementation = this.#getRestrictedMethod(targetName, origin);\n\n    const result = await this.#executeRestrictedMethod(\n      methodImplementation,\n      { origin },\n      targetName,\n      params,\n    );\n\n    // This is impossible if the restricted method implementation is typed correctly,\n    // but we maintain it for backwards compatibility.\n    if (result === undefined) {\n      throw new Error(\n        `Request for method \"${targetName}\" as origin \"${origin}\" returned no result.`,\n      );\n    }\n\n    return result;\n  }\n\n  /**\n   * An internal method used in {@link PermissionController.executeRestrictedMethod}.\n   * Calls the specified restricted method implementation after decorating it\n   * with the caveats of its permission. Throws if the subject does not have the\n   * requisite permission.\n   *\n   * ATTN: Parameter validation is the responsibility of the caller, or\n   * the restricted method implementation in the case of `params`.\n   *\n   * @see {@link PermissionController.executeRestrictedMethod} for usage.\n   * @param methodImplementation - The implementation of the method to call.\n   * @param subject - Metadata about the subject that made the request.\n   * @param method - The method name\n   * @param params - Params needed for executing the restricted method\n   * @returns The result of the restricted method implementation\n   */\n  #executeRestrictedMethod(\n    methodImplementation: RestrictedMethod<RestrictedMethodParameters, Json>,\n    subject: PermissionSubjectMetadata,\n    method: ExtractPermission<\n      ControllerPermissionSpecification,\n      ControllerCaveatSpecification\n    >['parentCapability'],\n    params: RestrictedMethodParameters = [],\n  ): ReturnType<RestrictedMethod<RestrictedMethodParameters, Json>> {\n    const { origin } = subject;\n\n    const permission = this.getPermission(origin, method);\n    if (!permission) {\n      throw unauthorized({ data: { origin, method } });\n    }\n\n    return decorateWithCaveats(\n      methodImplementation,\n      permission,\n      this.#caveatSpecifications,\n    )({ method, params, context: { origin } });\n  }\n}\n"]}