import { createHash } from "node:crypto"; import type { PluginListItem } from "../services/.server/PluginLifecycleService"; import { getPluginConsentRequirements } from "./pluginConsentRequirements"; export function createCapabilityReviewDigest(item: Pick, capabilityNames: ReadonlyArray) { const selectedCapabilities = new Set(capabilityNames); const reviewPayload = { pluginId: item.pluginId, version: item.version, capabilities: getPluginConsentRequirements(item.manifest) .filter((requirement) => selectedCapabilities.has(requirement.name)) .map((requirement) => ({ name: requirement.name, scope: requirement.scope ?? null, kind: requirement.kind, })) .sort((left, right) => left.name.localeCompare(right.name)), }; return createHash("sha256").update(stableJsonStringify(reviewPayload)).digest("base64url"); } function stableJsonStringify(value: unknown): string { if (Array.isArray(value)) { return `[${value.map((item) => stableJsonStringify(item)).join(",")}]`; } if (value && typeof value === "object") { return `{${Object.entries(value as Record) .sort(([left], [right]) => left.localeCompare(right)) .map(([key, nestedValue]) => `${JSON.stringify(key)}:${stableJsonStringify(nestedValue)}`) .join(",")}}`; } return JSON.stringify(value); }