{"version":3,"file":"Permission.cjs","sourceRoot":"","sources":["../src/Permission.ts"],"names":[],"mappings":";;;AAGA,mCAAgC;AAkJhC;;;;;;;;GAQG;AACH,SAAgB,mBAAmB,CAEjC,OAA4C;IAC5C,MAAM,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAEpD,OAAO;QACL,EAAE,EAAE,IAAA,eAAM,GAAE;QACZ,gBAAgB,EAAE,MAAM;QACxB,OAAO;QACP,OAAO;QACP,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE;KACP,CAAC;AACxB,CAAC;AAZD,kDAYC;AAED;;;;;;GAMG;AACH,SAAgB,UAAU,CACxB,UAAgC,EAChC,UAAkB;IAElB,OAAO,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;AAC1E,CAAC;AALD,gCAKC;AAgKD;;GAEG;AACH,IAAY,cAYX;AAZD,WAAY,cAAc;IACxB;;;OAGG;IACH,uDAAqC,CAAA;IAErC;;;OAGG;IACH,yCAAuB,CAAA;AACzB,CAAC,EAZW,cAAc,8BAAd,cAAc,QAYzB;AAyLD;;;;;;;;GAQG;AACH,SAAgB,oBAAoB,CAIlC,aAA4B,EAC5B,YAAkB;IAIlB,OAAO,aAAa,CAAC,cAAc,KAAK,YAAY,CAAC;AACvD,CAAC;AAVD,oDAUC","sourcesContent":["import type { NonEmptyArray } from '@metamask/controller-utils';\nimport type { ActionConstraint, EventConstraint } from '@metamask/messenger';\nimport type { Json } from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { CaveatConstraint, Caveat } from './Caveat';\nimport type {\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  PermissionController,\n  PermissionsRequest,\n  SideEffectMessenger,\n} from './PermissionController';\nimport type { SubjectType } from './SubjectMetadataController';\n\n/**\n * The origin of a subject.\n * Effectively the GUID of an entity that can have permissions.\n */\nexport type OriginString = string;\n\n/**\n * The name of a permission target.\n */\ntype TargetName = string;\n\n/**\n * A `ZCAP-LD`-like permission object. A permission is associated with a\n * particular `invoker`, which is the holder of the permission. Possessing the\n * permission grants access to a particular restricted resource, identified by\n * the `parentCapability`. The use of the restricted resource may be further\n * restricted by any `caveats` associated with the permission.\n *\n * See the README for details.\n */\nexport type PermissionConstraint = {\n  /**\n   * The context(s) in which this capability is meaningful.\n   *\n   * It is required by the standard, but we make it optional since there is only\n   * one context in our usage (i.e. the user's MetaMask instance).\n   */\n  readonly '@context'?: NonEmptyArray<string>;\n\n  /**\n   * The caveats of the permission.\n   *\n   * @see {@link Caveat} For more information.\n   */\n  readonly caveats: null | NonEmptyArray<CaveatConstraint>;\n\n  /**\n   * The creation date of the permission, in UNIX epoch time.\n   */\n  readonly date: number;\n\n  /**\n   * The GUID of the permission object.\n   */\n  readonly id: string;\n\n  /**\n   * The origin string of the subject that has the permission.\n   */\n  readonly invoker: OriginString;\n\n  /**\n   * A pointer to the resource that possession of the capability grants\n   * access to, for example a JSON-RPC method or endowment.\n   */\n  readonly parentCapability: string;\n};\n\n/**\n * A `ZCAP-LD`-like permission object. A permission is associated with a\n * particular `invoker`, which is the holder of the permission. Possessing the\n * permission grants access to a particular restricted resource, identified by\n * the `parentCapability`. The use of the restricted resource may be further\n * restricted by any `caveats` associated with the permission.\n *\n * See the README for details.\n *\n * @template Name - The name of the permission that the target corresponds to.\n * @template AllowedCaveat - A union of the allowed {@link Caveat} types\n * for the permission.\n */\nexport type ValidPermission<\n  Name extends TargetName,\n  AllowedCaveat extends CaveatConstraint,\n> = PermissionConstraint & {\n  /**\n   * The caveats of the permission.\n   *\n   * @see {@link Caveat} For more information.\n   */\n  readonly caveats: AllowedCaveat extends never\n    ? null\n    : NonEmptyArray<AllowedCaveat> | null;\n\n  /**\n   * A pointer to the resource that possession of the capability grants\n   * access to, for example a JSON-RPC method or endowment.\n   */\n  readonly parentCapability: Name;\n};\n\n/**\n * Internal utility for extracting the members types of an array. The type\n * evalutes to `never` if the specified type is the empty tuple or neither\n * an array nor a tuple.\n *\n * @template ArrayType - The array type whose members to extract.\n */\ntype ExtractArrayMembers<ArrayType> = ArrayType extends []\n  ? never\n  : ArrayType extends unknown[] | readonly unknown[]\n    ? ArrayType[number]\n    : never;\n\n/**\n * A utility type for extracting the allowed caveat types for a particular\n * permission from a permission specification type.\n *\n * @template PermissionSpecification - The permission specification type to\n * extract valid caveat types from.\n */\nexport type ExtractAllowedCaveatTypes<\n  PermissionSpecification extends PermissionSpecificationConstraint,\n> = ExtractArrayMembers<PermissionSpecification['allowedCaveats']>;\n\n/**\n * The options object of {@link constructPermission}.\n *\n * @template TargetPermission - The {@link Permission} that will be constructed.\n */\nexport type PermissionOptions<TargetPermission extends PermissionConstraint> = {\n  target: TargetPermission['parentCapability'];\n  /**\n   * The origin string of the subject that has the permission.\n   */\n  invoker: OriginString;\n\n  /**\n   * The caveats of the permission.\n   * See {@link Caveat}.\n   */\n  caveats?: NonEmptyArray<CaveatConstraint>;\n};\n\n/**\n * The default permission factory function. Naively constructs a permission from\n * the inputs. Sets a default, random `id` if none is provided.\n *\n * @see {@link Permission} For more details.\n * @template TargetPermission- - The {@link Permission} that will be constructed.\n * @param options - The options for the permission.\n * @returns The new permission object.\n */\nexport function constructPermission<\n  TargetPermission extends PermissionConstraint,\n>(options: PermissionOptions<TargetPermission>): TargetPermission {\n  const { caveats = null, invoker, target } = options;\n\n  return {\n    id: nanoid(),\n    parentCapability: target,\n    invoker,\n    caveats,\n    date: new Date().getTime(),\n  } as TargetPermission;\n}\n\n/**\n * Gets the caveat of the specified type belonging to the specified permission.\n *\n * @param permission - The permission whose caveat to retrieve.\n * @param caveatType - The type of the caveat to retrieve.\n * @returns The caveat, or undefined if no such caveat exists.\n */\nexport function findCaveat(\n  permission: PermissionConstraint,\n  caveatType: string,\n): CaveatConstraint | undefined {\n  return permission.caveats?.find((caveat) => caveat.type === caveatType);\n}\n\n/**\n * A requested permission object. Just an object with any of the properties\n * of a {@link PermissionConstraint} object.\n */\ntype RequestedPermission = Partial<PermissionConstraint>;\n\n/**\n * A record of target names and their {@link RequestedPermission} objects.\n */\nexport type RequestedPermissions = Record<TargetName, RequestedPermission>;\n\n/**\n * The restricted method context object. Essentially a way to pass internal\n * arguments to restricted methods and caveat functions, most importantly the\n * requesting origin.\n */\ntype RestrictedMethodContext = Readonly<{\n  origin: OriginString;\n  [key: string]: unknown;\n}>;\n\nexport type RestrictedMethodParameters = Json[] | Record<string, Json>;\n\n/**\n * The arguments passed to a restricted method implementation.\n *\n * @template Params - The JSON-RPC parameters of the restricted method.\n */\nexport type RestrictedMethodOptions<\n  Params extends RestrictedMethodParameters | null,\n> = {\n  method: TargetName;\n  params?: Params;\n  context: RestrictedMethodContext;\n};\n\n/**\n * A synchronous restricted method implementation.\n *\n * @template Params - The JSON-RPC parameters of the restricted method.\n * @template Result - The JSON-RPC result of the restricted method.\n */\nexport type SyncRestrictedMethod<\n  Params extends RestrictedMethodParameters,\n  Result extends Json,\n> = (args: RestrictedMethodOptions<Params>) => Result;\n\n/**\n * An asynchronous restricted method implementation.\n *\n * @template Params - The JSON-RPC parameters of the restricted method.\n * @template Result - The JSON-RPC result of the restricted method.\n */\nexport type AsyncRestrictedMethod<\n  Params extends RestrictedMethodParameters,\n  Result extends Json,\n> = (args: RestrictedMethodOptions<Params>) => Promise<Result>;\n\n/**\n * A synchronous or asynchronous restricted method implementation.\n *\n * @template Params - The JSON-RPC parameters of the restricted method.\n * @template Result - The JSON-RPC result of the restricted method.\n */\nexport type RestrictedMethod<\n  Params extends RestrictedMethodParameters,\n  Result extends Json,\n> =\n  | SyncRestrictedMethod<Params, Result>\n  | AsyncRestrictedMethod<Params, Result>;\n\nexport type ValidRestrictedMethod<\n  MethodImplementation extends RestrictedMethod<\n    RestrictedMethodParameters,\n    Json\n  >,\n> = MethodImplementation extends (args: infer Options) => Json | Promise<Json>\n  ? Options extends RestrictedMethodOptions<RestrictedMethodParameters>\n    ? MethodImplementation\n    : never\n  : never;\n\n/**\n * {@link EndowmentGetter} parameter object.\n */\nexport type EndowmentGetterParams = {\n  /**\n   * The origin of the requesting subject.\n   */\n  origin: string;\n\n  /**\n   * Any additional data associated with the request.\n   */\n  requestData?: unknown;\n\n  [key: string]: unknown;\n};\n\n/**\n * A synchronous or asynchronous function that gets the endowments for a\n * particular endowment permission. The getter receives the origin of the\n * requesting subject and, optionally, additional request metadata.\n */\nexport type EndowmentGetter<Endowments extends Json> = (\n  options: EndowmentGetterParams,\n) => Endowments | Promise<Endowments>;\n\nexport type PermissionFactory<\n  TargetPermission extends PermissionConstraint,\n  RequestData extends Record<string, unknown>,\n> = (\n  options: PermissionOptions<TargetPermission>,\n  requestData?: RequestData,\n) => TargetPermission;\n\nexport type PermissionValidatorConstraint = (\n  permission: PermissionConstraint,\n  origin?: OriginString,\n  target?: string,\n) => void;\n\n/**\n * The parameters passed to the side-effect function.\n */\nexport type SideEffectParams<\n  Actions extends ActionConstraint,\n  Events extends EventConstraint,\n> = {\n  requestData: PermissionsRequest;\n  messenger: SideEffectMessenger<Actions, Events>;\n};\n\n/**\n * A function that will execute actions as a permission side-effect.\n */\nexport type SideEffectHandler<\n  Actions extends ActionConstraint,\n  Events extends EventConstraint,\n> = (params: SideEffectParams<Actions, Events>) => Promise<unknown>;\n\n/**\n * The permissions side effects.\n */\nexport type PermissionSideEffect<\n  Actions extends ActionConstraint,\n  Events extends EventConstraint,\n> = {\n  /**\n   * A method triggered when the permission is accepted by the user\n   */\n  onPermitted: SideEffectHandler<Actions, Events>;\n  /**\n   * A method triggered if a `onPermitted` method rejected.\n   */\n  onFailure?: SideEffectHandler<Actions, Events>;\n};\n\n/**\n * The different possible types of permissions.\n */\nexport enum PermissionType {\n  /**\n   * A restricted JSON-RPC method. A subject must have the requisite permission\n   * to call a restricted JSON-RPC method.\n   */\n  RestrictedMethod = 'RestrictedMethod',\n\n  /**\n   * An \"endowment\" granted to subjects that possess the requisite permission,\n   * such as a global environment variable exposing a restricted API, etc.\n   */\n  Endowment = 'Endowment',\n}\n\n/**\n * The base constraint for permission specification objects. Every\n * {@link Permission} supported by a {@link PermissionController} must have an\n * associated specification, which is the source of truth for all permission-\n * related types. A permission specification includes the list of permitted\n * caveats, and any factory and validation functions specified by the consumer.\n * A concrete permission specification may specify further fields as necessary.\n *\n * See the README for more details.\n */\ntype PermissionSpecificationBase<Type extends PermissionType> = {\n  /**\n   * The type of the specified permission.\n   */\n  permissionType: Type;\n\n  /**\n   * The name of the target resource of the permission.\n   */\n  targetName: string;\n\n  /**\n   * An array of the caveat types that may be added to instances of this\n   * permission.\n   */\n  allowedCaveats: Readonly<NonEmptyArray<string>> | null;\n\n  /**\n   * The factory function used to get permission objects. Permissions returned\n   * by this function are presumed to valid, and they will not be passed to the\n   * validator function associated with this specification (if any). In other\n   * words, the factory function should validate the permissions it creates.\n   *\n   * If no factory is specified, the {@link Permission} constructor will be\n   * used, and the validator function (if specified) will be called on newly\n   * constructed permissions.\n   */\n  // TODO: Replace `any` with type\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  factory?: PermissionFactory<any, Record<string, unknown>>;\n\n  /**\n   * The validator function used to validate permissions of the associated type\n   * whenever they are granted or their caveat arrays are mutated.\n   *\n   * Permission validators are **not** invoked when a caveat is mutated, provided\n   * the caveat array has not changed. For this reason, permission validators\n   * **must not** be used to validate caveats. To validate caveats, use the\n   * corresponding caveat specification property.\n   *\n   * The validator should throw an appropriate JSON-RPC error if validation fails.\n   */\n  validator?: PermissionValidatorConstraint;\n\n  /**\n   * The side-effect triggered by the {@link PermissionController} once the user approved it.\n   * The side-effect can only be an action allowed to be called inside the {@link PermissionController}.\n   *\n   * If the side-effect action fails, the permission that triggered it is revoked.\n   */\n  sideEffect?: PermissionSideEffect<ActionConstraint, EventConstraint>;\n\n  /**\n   * The Permission may be available to only a subset of the subject types. If so, specify the subject types as an array.\n   * If a subject with a type not in this array tries to request the permission, the call will fail.\n   *\n   * Leaving this as undefined uses default behaviour where the permission is available to request for all subject types.\n   */\n  subjectTypes?: readonly SubjectType[];\n};\n\n/**\n * The constraint for restricted method permission specification objects.\n * Permissions that correspond to JSON-RPC methods are specified using objects\n * that conform to this type.\n *\n * See the README for more details.\n */\nexport type RestrictedMethodSpecificationConstraint =\n  PermissionSpecificationBase<PermissionType.RestrictedMethod> & {\n    /**\n     * The implementation of the restricted method that the permission\n     * corresponds to.\n     */\n    // TODO: Replace `any` with type\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    methodImplementation: RestrictedMethod<any, Json>;\n  };\n\n/**\n * The constraint for endowment permission specification objects. Permissions\n * that endow callers with some restricted resource are specified using objects\n * that conform to this type.\n *\n * See the README for more details.\n */\nexport type EndowmentSpecificationConstraint =\n  PermissionSpecificationBase<PermissionType.Endowment> & {\n    /**\n     * The {@link EndowmentGetter} function for the permission. This function\n     * will be called by the {@link PermissionController} whenever the\n     * permission is invoked, after which the host can apply the endowments to\n     * the requesting subject in the intended manner.\n     */\n    endowmentGetter: EndowmentGetter<Json>;\n  };\n\n/**\n * The constraint for permission specification objects. Every {@link Permission}\n * supported by a {@link PermissionController} must have an associated\n * specification, which is the source of truth for all permission-related types.\n * All specifications must adhere to the {@link PermissionSpecificationBase}\n * interface, but specifications may have different fields depending on the\n * {@link PermissionType}.\n *\n * See the README for more details.\n */\nexport type PermissionSpecificationConstraint =\n  | EndowmentSpecificationConstraint\n  | RestrictedMethodSpecificationConstraint;\n\n/**\n * Options for {@link PermissionSpecificationBuilder} functions.\n */\ntype PermissionSpecificationBuilderOptions<\n  MethodHooks extends Record<string, unknown>,\n  SpecMessenger = unknown,\n> = {\n  targetName?: string;\n  allowedCaveats?: Readonly<NonEmptyArray<string>> | null;\n  methodHooks?: MethodHooks;\n  /**\n   * A messenger scoped to this permission specification. The messenger is\n   * expected to have exactly the actions declared by the spec's `actionNames`\n   * delegated to it; {@link createRestrictedMethodMessenger} is the canonical\n   * way to construct it.\n   */\n  messenger?: SpecMessenger;\n};\n\n/**\n * A function that builds a permission specification. Modules that specify\n * permissions for external consumption should make this their primary /\n * default export so that host applications can use them to generate concrete\n * specifications tailored to their requirements.\n */\nexport type PermissionSpecificationBuilder<\n  Type extends PermissionType,\n  Options extends PermissionSpecificationBuilderOptions<\n    Record<string, unknown>\n  >,\n  Specification extends PermissionSpecificationConstraint & {\n    permissionType: Type;\n  },\n> = (options: Options) => Specification;\n\ntype ValidRestrictedMethodSpecification<\n  Specification extends RestrictedMethodSpecificationConstraint,\n> =\n  Specification['methodImplementation'] extends ValidRestrictedMethod<\n    Specification['methodImplementation']\n  >\n    ? Specification\n    : never;\n\n/**\n * Constraint for {@link PermissionSpecificationConstraint} objects that\n * evaluates to `never` if the specification contains any invalid fields.\n *\n * @template Specification - The permission specification to validate.\n */\nexport type ValidPermissionSpecification<\n  Specification extends PermissionSpecificationConstraint,\n> = Specification['targetName'] extends TargetName\n  ? Specification['permissionType'] extends PermissionType.Endowment\n    ? Specification\n    : Specification['permissionType'] extends PermissionType.RestrictedMethod\n      ? ValidRestrictedMethodSpecification<\n          Extract<Specification, RestrictedMethodSpecificationConstraint>\n        >\n      : never\n  : never;\n\n/**\n * Checks that the specification has the expected permission type.\n *\n * @param specification - The specification to check.\n * @param expectedType - The expected permission type.\n * @template Specification - The specification to check.\n * @template Type - The expected permission type.\n * @returns Whether or not the specification is of the expected type.\n */\nexport function hasSpecificationType<\n  Specification extends PermissionSpecificationConstraint,\n  Type extends PermissionType,\n>(\n  specification: Specification,\n  expectedType: Type,\n): specification is Specification & {\n  permissionType: Type;\n} {\n  return specification.permissionType === expectedType;\n}\n\n/**\n * The specifications for all permissions supported by a particular\n * {@link PermissionController}.\n *\n * @template Specifications - The union of all {@link PermissionSpecificationConstraint} types.\n */\nexport type PermissionSpecificationMap<\n  Specification extends PermissionSpecificationConstraint,\n> = {\n  [Name in Specification['targetName']]: Specification extends {\n    targetName: Name;\n  }\n    ? Specification\n    : never;\n};\n\n/**\n * Extracts a specific {@link PermissionSpecificationConstraint} from a union of\n * permission specifications.\n *\n * @template Specification - The specification union type to extract from.\n * @template Name - The `targetName` of the specification to extract.\n */\nexport type ExtractPermissionSpecification<\n  Specification extends PermissionSpecificationConstraint,\n  Name extends Specification['targetName'],\n> = Specification extends {\n  targetName: Name;\n}\n  ? Specification\n  : never;\n"]}