diff --git a/.gitignore b/.gitignore index 4be0d91..4ce03d7 100644 --- a/.gitignore +++ b/.gitignore @@ -141,3 +141,4 @@ __pycache__ /playwright-report/ /blob-report/ /playwright/.cache/ +dist_devel/ diff --git a/Makefile b/Makefile index af53f38..d0a1af8 100644 --- a/Makefile +++ b/Makefile @@ -48,10 +48,12 @@ clean: rm -rf src/ui/node_modules/ rm -rf dist/ rm -rf dist_ui/ + rm -rf dist_devel/ build: src/ cloudformation/ docs/ yarn -D VITE_BUILD_HASH=$(GIT_HASH) yarn build + cp -r src/api/resources/ dist/api/resources sam build --template-file cloudformation/main.yml local: diff --git a/cloudformation/iam.yml b/cloudformation/iam.yml index 756c970..c468b87 100644 --- a/cloudformation/iam.yml +++ b/cloudformation/iam.yml @@ -10,6 +10,8 @@ Parameters: LambdaFunctionName: Type: String AllowedPattern: ^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$ + SesEmailDomain: + Type: String Resources: ApiLambdaIAMRole: Type: AWS::IAM::Role @@ -24,6 +26,21 @@ Resources: Service: - lambda.amazonaws.com Policies: + - PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: + - ses:SendEmail + - ses:SendRawEmail + Effect: Allow + Resource: "*" + Condition: + StringEquals: + ses:FromAddress: !Sub "membership@${SesEmailDomain}" + ForAllValues:StringLike: + ses:Recipients: + - "*@illinois.edu" + PolicyName: ses-membership - PolicyDocument: Version: '2012-10-17' Statement: @@ -85,4 +102,4 @@ Outputs: Value: Fn::GetAtt: - ApiLambdaIAMRole - - Arn \ No newline at end of file + - Arn diff --git a/cloudformation/main.yml b/cloudformation/main.yml index 5edf7e3..09e6422 100644 --- a/cloudformation/main.yml +++ b/cloudformation/main.yml @@ -32,8 +32,10 @@ Mappings: General: dev: LogRetentionDays: 7 + SesDomain: "aws.qa.acmuiuc.org" prod: LogRetentionDays: 365 + SesDomain: "acm.illinois.edu" ApiGwConfig: dev: ApiCertificateArn: arn:aws:acm:us-east-1:427040638965:certificate/63ccdf0b-d2b5-44f0-b589-eceffb935c23 @@ -71,6 +73,7 @@ Resources: Parameters: RunEnvironment: !Ref RunEnvironment LambdaFunctionName: !Sub ${ApplicationPrefix}-lambda + SesEmailDomain: !FindInMap [General, !Ref RunEnvironment, SesDomain] AppLogGroups: Type: AWS::Serverless::Application @@ -120,29 +123,9 @@ Resources: Type: AWS::Serverless::Function DependsOn: - AppLogGroups - Metadata: - BuildMethod: esbuild - BuildProperties: - Format: esm - Minify: true - OutExtension: - - .js=.mjs - Target: "es2022" - Sourcemap: false - EntryPoints: - - api/lambda.js - External: - - aws-sdk - Banner: - - js=import path from 'path'; - import { fileURLToPath } from 'url'; - import { createRequire as topLevelCreateRequire } from 'module'; - const require = topLevelCreateRequire(import.meta.url); - const __filename = fileURLToPath(import.meta.url); - const __dirname = path.dirname(__filename); Properties: Architectures: [arm64] - CodeUri: ../dist + CodeUri: ../dist/lambda AutoPublishAlias: live Runtime: nodejs22.x Description: !Sub "${ApplicationFriendlyName} API Lambda" diff --git a/generate_jwt.js b/generate_jwt.js index 02f58a0..38776a9 100644 --- a/generate_jwt.js +++ b/generate_jwt.js @@ -18,7 +18,7 @@ const payload = { groups: ["0"], idp: "https://login.microsoftonline.com", ipaddr: "192.168.1.1", - name: "John Doe", + name: "Doe, John", oid: "00000000-0000-0000-0000-000000000000", rh: "rh-value", scp: "user_impersonation", diff --git a/package.json b/package.json index c1f86a4..16c772b 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "scripts": { "build": "yarn workspaces run build && yarn lockfile-manage", "dev": "concurrently --names 'api,ui' 'yarn workspace infra-core-api run dev' 'yarn workspace infra-core-ui run dev'", - "lockfile-manage": "synp --with-workspace --source-file yarn.lock && cp package-lock.json dist/ && cp src/api/package.json dist/ && rm package-lock.json", + "lockfile-manage": "synp --with-workspace --source-file yarn.lock && cp package-lock.json dist/lambda/ && cp src/api/package.lambda.json dist/lambda/package.json && rm package-lock.json", "prettier": "yarn workspaces run prettier && prettier --check tests/**/*.ts", "prettier:write": "yarn workspaces run prettier:write && prettier --write tests/**/*.ts", "lint": "yarn workspaces run lint", diff --git a/src/api/build.js b/src/api/build.js new file mode 100644 index 0000000..f24c810 --- /dev/null +++ b/src/api/build.js @@ -0,0 +1,39 @@ +import esbuild from "esbuild"; +import { resolve } from "path"; + +esbuild + .build({ + entryPoints: ["api/lambda.js"], // Entry file + bundle: true, + format: "esm", + minify: true, + outdir: "../../dist/lambda/", + outExtension: { ".js": ".mjs" }, + loader: { + ".png": "file", + ".pkpass": "file", + ".json": "file", + }, // File loaders + target: "es2022", // Target ES2022 + sourcemap: false, + platform: "node", + external: ["aws-sdk", "moment-timezone", "passkit-generator", "fastify"], + alias: { + 'moment-timezone': resolve(process.cwd(), '../../node_modules/moment-timezone/builds/moment-timezone-with-data-10-year-range.js') + }, + banner: { + js: ` + import path from 'path'; + import { fileURLToPath } from 'url'; + import { createRequire as topLevelCreateRequire } from 'module'; + const require = topLevelCreateRequire(import.meta.url); + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + `.trim(), + }, // Banner for compatibility with CommonJS + }) + .then(() => console.log("Build completed successfully!")) + .catch((error) => { + console.error("Build failed:", error); + process.exit(1); + }); diff --git a/src/api/esbuild.config.js b/src/api/esbuild.config.js new file mode 100644 index 0000000..c48615a --- /dev/null +++ b/src/api/esbuild.config.js @@ -0,0 +1,47 @@ +import { build, context } from 'esbuild'; +import { readFileSync } from 'fs'; +import { resolve } from 'path'; + +const isWatching = !!process.argv.includes('--watch') +const nodePackage = JSON.parse(readFileSync(resolve(process.cwd(), 'package.json'), 'utf8')); + +const buildOptions = { + entryPoints: [resolve(process.cwd(), 'index.ts')], + outfile: resolve(process.cwd(), '../', '../', 'dist_devel', 'index.js'), + bundle: true, + platform: 'node', + format: 'esm', + external: [ + Object.keys(nodePackage.dependencies ?? {}), + Object.keys(nodePackage.peerDependencies ?? {}), + Object.keys(nodePackage.devDependencies ?? {}), + ].flat(), + loader: { + '.png': 'file', // Add this line to specify a loader for .png files + }, + alias: { + 'moment-timezone': resolve(process.cwd(), '../../node_modules/moment-timezone/builds/moment-timezone-with-data-10-year-range.js') + }, + banner: { + js: ` + import path from 'path'; + import { fileURLToPath } from 'url'; + import { createRequire as topLevelCreateRequire } from 'module'; + const require = topLevelCreateRequire(import.meta.url); + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + `.trim(), + }, // Banner for compatibility with CommonJS +}; + +if (isWatching) { + context(buildOptions).then(ctx => { + if (isWatching) { + ctx.watch(); + } else { + ctx.rebuild(); + } + }); +} else { + build(buildOptions) +} diff --git a/src/api/functions/entraId.ts b/src/api/functions/entraId.ts index 30c0331..6524c53 100644 --- a/src/api/functions/entraId.ts +++ b/src/api/functions/entraId.ts @@ -7,6 +7,7 @@ import { } from "../../common/config.js"; import { BaseError, + EntraFetchError, EntraGroupError, EntraInvitationError, InternalServerError, @@ -19,6 +20,7 @@ import { EntraInvitationResponse, } from "../../common/types/iam.js"; import { FastifyInstance } from "fastify"; +import { UserProfileDataBase } from "common/types/msGraphApi.js"; function validateGroupId(groupId: string): boolean { const groupIdPattern = /^[a-zA-Z0-9-]+$/; // Adjust the pattern as needed @@ -351,3 +353,47 @@ export async function listGroupMembers( }); } } + +/** + * Retrieves the profile of a user from Entra ID. + * @param token - Entra ID token authorized to perform this action. + * @param userId - The user ID to fetch the profile for. + * @throws {EntraUserError} If fetching the user profile fails. + * @returns {Promise} The user's profile information. + */ +export async function getUserProfile( + token: string, + email: string, +): Promise { + const userId = await resolveEmailToOid(token, email); + try { + const url = `https://graph.microsoft.com/v1.0/users/${userId}?$select=userPrincipalName,givenName,surname,displayName,otherMails,mail`; + const response = await fetch(url, { + method: "GET", + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + const errorData = (await response.json()) as { + error?: { message?: string }; + }; + throw new EntraFetchError({ + message: errorData?.error?.message ?? response.statusText, + email, + }); + } + return (await response.json()) as UserProfileDataBase; + } catch (error) { + if (error instanceof EntraFetchError) { + throw error; + } + + throw new EntraFetchError({ + message: error instanceof Error ? error.message : String(error), + email, + }); + } +} diff --git a/src/api/functions/membership.ts b/src/api/functions/membership.ts new file mode 100644 index 0000000..1f309b3 --- /dev/null +++ b/src/api/functions/membership.ts @@ -0,0 +1,18 @@ +import { FastifyBaseLogger, FastifyInstance } from "fastify"; + +export async function checkPaidMembership( + endpoint: string, + log: FastifyBaseLogger, + netId: string, +) { + const membershipApiPayload = (await ( + await fetch(`${endpoint}?netId=${netId}`) + ).json()) as { netId: string; isPaidMember: boolean }; + log.trace(`Got Membership API Payload for ${netId}: ${membershipApiPayload}`); + try { + return membershipApiPayload["isPaidMember"]; + } catch (e: any) { + log.error(`Failed to get response from membership API: ${e.toString()}`); + throw e; + } +} diff --git a/src/api/functions/mobileWallet.ts b/src/api/functions/mobileWallet.ts new file mode 100644 index 0000000..b16f99b --- /dev/null +++ b/src/api/functions/mobileWallet.ts @@ -0,0 +1,117 @@ +import { getSecretValue } from "../plugins/auth.js"; +import { genericConfig, SecretConfig } from "../../common/config.js"; +import { + InternalServerError, + UnauthorizedError, +} from "../../common/errors/index.js"; +import { FastifyInstance, FastifyRequest } from "fastify"; +// these make sure that esbuild includes the files +import icon from "../resources/MembershipPass.pkpass/icon.png"; +import logo from "../resources/MembershipPass.pkpass/logo.png"; +import strip from "../resources/MembershipPass.pkpass/strip.png"; +import pass from "../resources/MembershipPass.pkpass/pass.js"; +import { PKPass } from "passkit-generator"; +import { promises as fs } from "fs"; + +function trim(s: string) { + return (s || "").replace(/^\s+|\s+$/g, ""); +} + +function convertName(name: string): string { + if (!name.includes(",")) { + return name; + } + return `${trim(name.split(",")[1])} ${name.split(",")[0]}`; +} + +export async function issueAppleWalletMembershipCard( + app: FastifyInstance, + request: FastifyRequest, + email: string, + name?: string, +) { + if (!email.endsWith("@illinois.edu")) { + throw new UnauthorizedError({ + message: + "Cannot issue membership pass for emails not on the illinois.edu domain.", + }); + } + const secretApiConfig = (await getSecretValue( + app.secretsManagerClient, + genericConfig.ConfigSecretName, + )) as SecretConfig; + if (!secretApiConfig) { + throw new InternalServerError({ + message: "Could not retrieve signing data", + }); + } + const signerCert = Buffer.from( + secretApiConfig.acm_passkit_signerCert_base64, + "base64", + ).toString("utf-8"); + const signerKey = Buffer.from( + secretApiConfig.acm_passkit_signerKey_base64, + "base64", + ).toString("utf-8"); + const wwdr = Buffer.from( + secretApiConfig.apple_signing_cert_base64, + "base64", + ).toString("utf-8"); + pass["passTypeIdentifier"] = app.environmentConfig["PasskitIdentifier"]; + + const pkpass = new PKPass( + { + "icon.png": await fs.readFile(icon), + "logo.png": await fs.readFile(logo), + "strip.png": await fs.readFile(strip), + "pass.json": Buffer.from(JSON.stringify(pass)), + }, + { + wwdr, + signerCert, + signerKey, + }, + { + // logoText: app.runEnvironment === "dev" ? "INVALID Membership Pass" : "Membership Pass", + serialNumber: app.environmentConfig["PasskitSerialNumber"], + }, + ); + pkpass.setBarcodes({ + altText: email.split("@")[0], + format: "PKBarcodeFormatPDF417", + message: app.runEnvironment === "dev" ? `INVALID${email}INVALID` : email, + }); + const iat = new Date().toLocaleDateString("en-US", { + day: "2-digit", + month: "2-digit", + year: "numeric", + }); + if (name && name !== "") { + pkpass.secondaryFields.push({ + label: "Member Name", + key: "name", + value: convertName(name), + }); + } + if (app.runEnvironment === "prod") { + pkpass.backFields.push({ + label: "Verification URL", + key: "iss", + value: `https://membership.acm.illinois.edu/verify/${email.split("@")[0]}`, + }); + } else { + pkpass.backFields.push({ + label: "TESTING ONLY Pass", + key: "iss", + value: `Do not honor!`, + }); + } + pkpass.backFields.push({ label: "Pass Created On", key: "iat", value: iat }); + pkpass.backFields.push({ label: "Membership ID", key: "id", value: email }); + const buffer = pkpass.getAsBuffer(); + request.log.info( + { type: "audit", actor: email, target: email }, + "Created membership verification pass", + ); + return buffer; +} diff --git a/src/api/functions/ses.ts b/src/api/functions/ses.ts new file mode 100644 index 0000000..0ce5ff2 --- /dev/null +++ b/src/api/functions/ses.ts @@ -0,0 +1,130 @@ +import { SendRawEmailCommand } from "@aws-sdk/client-ses"; +import { encode } from "base64-arraybuffer"; + +/** + * Generates a SendRawEmailCommand for SES to send an email with an attached membership pass. + * + * @param recipientEmail - The email address of the recipient. + * * @param recipientEmail - The email address of the sender with a verified identity in SES. + * @param attachmentBuffer - The membership pass in ArrayBufferLike format. + * @returns The command to send the email via SES. + */ +export function generateMembershipEmailCommand( + recipientEmail: string, + senderEmail: string, + attachmentBuffer: ArrayBufferLike, +): SendRawEmailCommand { + const encodedAttachment = encode(attachmentBuffer); + const boundary = "----BoundaryForEmail"; + + const emailTemplate = ` + + + + Your ACM @ UIUC Membership + + + + + + +
 
+ +
+
+

Welcome

+

+ Thank you for becoming a member of ACM @ UIUC! Attached is your membership pass. + You can add it to your Apple or Google Wallet for easy access. +

+

+ If you have any questions, feel free to contact us at + infra@acm.illinois.edu. +

+
+ Visit ACM @ UIUC +
+
+ + + + `; + + const rawEmail = ` +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="${boundary}" +From: ACM @ UIUC <${senderEmail}> +To: ${recipientEmail} +Subject: Your ACM @ UIUC Membership + +--${boundary} +Content-Type: text/html; charset="UTF-8" + +${emailTemplate} + +--${boundary} +Content-Type: application/vnd.apple.pkpass +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="membership.pkpass" + +${encodedAttachment} +--${boundary}--`.trim(); + return new SendRawEmailCommand({ + RawMessage: { + Data: new TextEncoder().encode(rawEmail), + }, + }); +} diff --git a/src/api/index.ts b/src/api/index.ts index ed7f349..ebe512b 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -21,6 +21,8 @@ import { STSClient, GetCallerIdentityCommand } from "@aws-sdk/client-sts"; import NodeCache from "node-cache"; import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; import { SecretsManagerClient } from "@aws-sdk/client-secrets-manager"; +import { SESClient } from "@aws-sdk/client-ses"; +import mobileWalletRoute from "./routes/mobileWallet.js"; dotenv.config(); @@ -35,6 +37,10 @@ async function init() { region: genericConfig.AwsRegion, }); + const sesClient = new SESClient({ + region: genericConfig.AwsRegion, + }); + const app: FastifyInstance = fastify({ logger: { level: process.env.LOG_LEVEL || "info", @@ -82,6 +88,7 @@ async function init() { app.nodeCache = new NodeCache({ checkperiod: 30 }); app.dynamoClient = dynamoClient; app.secretsManagerClient = secretsManagerClient; + app.sesClient = sesClient; app.addHook("onRequest", (req, _, done) => { req.startTime = now(); const hostname = req.hostname; @@ -111,6 +118,7 @@ async function init() { api.register(icalPlugin, { prefix: "/ical" }); api.register(iamRoutes, { prefix: "/iam" }); api.register(ticketsPlugin, { prefix: "/tickets" }); + api.register(mobileWalletRoute, { prefix: "/mobileWallet" }); if (app.runEnvironment === "dev") { api.register(vendingPlugin, { prefix: "/vending" }); } diff --git a/src/api/package.json b/src/api/package.json index 9f0467c..765b03b 100644 --- a/src/api/package.json +++ b/src/api/package.json @@ -7,8 +7,8 @@ "license": "BSD-3-Clause", "type": "module", "scripts": { - "build": "tsc", - "dev": "cross-env LOG_LEVEL=debug tsx watch index.ts", + "build": "tsc && node build.js", + "dev": "cross-env LOG_LEVEL=debug concurrently --names 'esbuild,server' 'node esbuild.config.js --watch' 'cd ../../dist_devel && nodemon index.js'", "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts --cache", "prettier": "prettier --check *.ts **/*.ts", @@ -17,6 +17,7 @@ "dependencies": { "@aws-sdk/client-dynamodb": "^3.624.0", "@aws-sdk/client-secrets-manager": "^3.624.0", + "@aws-sdk/client-ses": "^3.734.0", "@aws-sdk/client-sts": "^3.726.0", "@aws-sdk/util-dynamodb": "^3.624.0", "@azure/msal-node": "^2.16.1", @@ -25,6 +26,7 @@ "@fastify/caching": "^9.0.1", "@fastify/cors": "^10.0.1", "@touch4it/ical-timezones": "^1.9.0", + "base64-arraybuffer": "^1.0.2", "discord.js": "^14.15.3", "dotenv": "^16.4.5", "esbuild": "^0.24.2", @@ -36,12 +38,14 @@ "moment": "^2.30.1", "moment-timezone": "^0.5.45", "node-cache": "^5.1.2", + "passkit-generator": "^3.3.1", "pluralize": "^8.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.23.2", "zod-validation-error": "^3.3.1" }, "devDependencies": { - "@tsconfig/node22": "^22.0.0" + "@tsconfig/node22": "^22.0.0", + "nodemon": "^3.1.9" } -} \ No newline at end of file +} diff --git a/src/api/package.lambda.json b/src/api/package.lambda.json new file mode 100644 index 0000000..ae609ba --- /dev/null +++ b/src/api/package.lambda.json @@ -0,0 +1,15 @@ +{ + "name": "infra-core-api", + "version": "1.0.0", + "description": "ACM@UIUC Infra - Sample AWS Lambda in Node", + "main": "index.js", + "author": "ACM@UIUC", + "license": "BSD-3-Clause", + "type": "module", + "dependencies": { + "moment-timezone": "^0.5.45", + "passkit-generator": "^3.3.1", + "fastify": "^5.1.0" + }, + "devDependencies": {} +} diff --git a/src/api/resources/MembershipPass.pkpass/icon.png b/src/api/resources/MembershipPass.pkpass/icon.png new file mode 100644 index 0000000..3800ba0 Binary files /dev/null and b/src/api/resources/MembershipPass.pkpass/icon.png differ diff --git a/src/api/resources/MembershipPass.pkpass/logo.png b/src/api/resources/MembershipPass.pkpass/logo.png new file mode 100644 index 0000000..ae292cf Binary files /dev/null and b/src/api/resources/MembershipPass.pkpass/logo.png differ diff --git a/src/api/resources/MembershipPass.pkpass/pass.ts b/src/api/resources/MembershipPass.pkpass/pass.ts new file mode 100644 index 0000000..e0515a4 --- /dev/null +++ b/src/api/resources/MembershipPass.pkpass/pass.ts @@ -0,0 +1,18 @@ +export default { + sharingProhibited: true, + organizationName: "ACM @ UIUC", + description: "ACM Membership Pass", + teamIdentifier: "8VNQTQM2L6", + passTypeIdentifier: "REPLACE_ME", + foregroundColor: "rgb(242,253,255)", + labelColor: "rgb(243,155,109)", + backgroundColor: "rgb(0,83,179)", + logoText: "Membership Pass", + formatVersion: 1, + storeCard: { + headerFields: [], + secondaryFields: [], + auxiliaryFields: [], + backFields: [], + }, +}; diff --git a/src/api/resources/MembershipPass.pkpass/strip.png b/src/api/resources/MembershipPass.pkpass/strip.png new file mode 100644 index 0000000..b6be36f Binary files /dev/null and b/src/api/resources/MembershipPass.pkpass/strip.png differ diff --git a/src/api/resources/types.d.ts b/src/api/resources/types.d.ts new file mode 100644 index 0000000..358a27d --- /dev/null +++ b/src/api/resources/types.d.ts @@ -0,0 +1,9 @@ +declare module "*.png" { + const value: string; + export default value; +} + +declare module "*.json" { + const value: Record; + export default value; +} diff --git a/src/api/routes/mobileWallet.ts b/src/api/routes/mobileWallet.ts new file mode 100644 index 0000000..b4d7e88 --- /dev/null +++ b/src/api/routes/mobileWallet.ts @@ -0,0 +1,91 @@ +import { FastifyPluginAsync } from "fastify"; +import { issueAppleWalletMembershipCard } from "../functions/mobileWallet.js"; +import { + EntraFetchError, + UnauthenticatedError, + UnauthorizedError, + ValidationError, +} from "../../common/errors/index.js"; +import { generateMembershipEmailCommand } from "../functions/ses.js"; +import { z } from "zod"; +import { getEntraIdToken, getUserProfile } from "../functions/entraId.js"; +import { checkPaidMembership } from "../functions/membership.js"; + +const mobileWalletRoute: FastifyPluginAsync = async (fastify, _options) => { + fastify.get<{ Querystring: { email: string } }>( + "/membership", + { + schema: { + querystring: { + type: "object", + properties: { + email: { type: "string", format: "email" }, + }, + required: ["email"], + }, + }, + }, + async (request, reply) => { + if (!request.query.email) { + throw new UnauthenticatedError({ message: "Could not find user." }); + } + try { + await z + .string() + .email() + .refine( + (email) => email.endsWith("@illinois.edu"), + "Email must be on the illinois.edu domain.", + ) + .parseAsync(request.query.email); + } catch { + throw new ValidationError({ + message: "Email query parameter is not a valid email", + }); + } + const isPaidMember = await checkPaidMembership( + fastify.environmentConfig.MembershipApiEndpoint, + request.log, + request.query.email.replace("@illinois.edu", ""), + ); + if (!isPaidMember) { + throw new UnauthenticatedError({ + message: `${request.query.email} is not a paid member.`, + }); + } + const entraIdToken = await getEntraIdToken( + fastify, + fastify.environmentConfig.AadValidClientId, + ); + + const userProfile = await getUserProfile( + entraIdToken, + request.query.email, + ); + + const item = await issueAppleWalletMembershipCard( + fastify, + request, + request.query.email, + userProfile.displayName, + ); + const emailCommand = generateMembershipEmailCommand( + request.query.email, + `membership@${fastify.environmentConfig.EmailDomain}`, + item, + ); + if ( + fastify.runEnvironment === "dev" && + request.query.email === "testinguser@illinois.edu" + ) { + return reply + .status(202) + .send({ message: "OK (skipped sending email)" }); + } + await fastify.sesClient.send(emailCommand); + reply.status(202).send({ message: "OK" }); + }, + ); +}; + +export default mobileWalletRoute; diff --git a/src/api/types.d.ts b/src/api/types.d.ts index 7f0e498..252b40b 100644 --- a/src/api/types.d.ts +++ b/src/api/types.d.ts @@ -5,6 +5,7 @@ import { ConfigType } from "../common/config.js"; import NodeCache from "node-cache"; import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; import { SecretsManagerClient } from "@aws-sdk/client-secrets-manager"; +import { SESClient } from "@aws-sdk/client-ses"; declare module "fastify" { interface FastifyInstance { authenticate: ( @@ -25,6 +26,7 @@ declare module "fastify" { environmentConfig: ConfigType; nodeCache: NodeCache; dynamoClient: DynamoDBClient; + sesClient: SESClient; secretsManagerClient: SecretsManagerClient; } interface FastifyRequest { diff --git a/src/common/config.ts b/src/common/config.ts index b0609d6..3800c37 100644 --- a/src/common/config.ts +++ b/src/common/config.ts @@ -12,6 +12,10 @@ export type ConfigType = { AzureRoleMapping: AzureRoleMapping; ValidCorsOrigins: ValueOrArray | OriginFunction; AadValidClientId: string; + PasskitIdentifier: string; + PasskitSerialNumber: string; + MembershipApiEndpoint: string; + EmailDomain: string; }; type GenericConfigType = { @@ -66,6 +70,10 @@ const environmentConfig: EnvironmentConfigType = { /^https:\/\/(?:.*\.)?acmuiuc\.pages\.dev$/, ], AadValidClientId: "39c28870-94e4-47ee-b4fb-affe0bf96c9f", + PasskitIdentifier: "pass.org.acmuiuc.qa.membership", + PasskitSerialNumber: "0", + MembershipApiEndpoint: "https://infra-membership-api.aws.qa.acmuiuc.org/api/v1/checkMembership", + EmailDomain: "aws.qa.acmuiuc.org", }, prod: { AzureRoleMapping: { AutonomousWriters: [AppRoles.EVENTS_MANAGER] }, @@ -76,6 +84,10 @@ const environmentConfig: EnvironmentConfigType = { /^https:\/\/(?:.*\.)?acmuiuc\.pages\.dev$/, ], AadValidClientId: "5e08cf0f-53bb-4e09-9df2-e9bdc3467296", + PasskitIdentifier: "pass.edu.illinois.acm.membership", + PasskitSerialNumber: "0", + MembershipApiEndpoint: "https://infra-membership-api.aws.acmuiuc.org/api/v1/checkMembership", + EmailDomain: "acm.illinois.edu", } }; @@ -85,6 +97,9 @@ export type SecretConfig = { discord_bot_token: string; entra_id_private_key: string; entra_id_thumbprint: string; + acm_passkit_signerCert_base64: string; + acm_passkit_signerKey_base64: string; + apple_signing_cert_base64: string; }; export { genericConfig, environmentConfig }; diff --git a/src/common/errors/index.ts b/src/common/errors/index.ts index 632669f..b03d2a7 100644 --- a/src/common/errors/index.ts +++ b/src/common/errors/index.ts @@ -201,3 +201,16 @@ export class EntraGroupError extends BaseError<"EntraGroupError"> { this.group = group; } } + +export class EntraFetchError extends BaseError<"EntraFetchError"> { + email: string; + constructor({ message, email }: { message?: string; email: string }) { + super({ + name: "EntraFetchError", + id: 509, + message: message || "Could not get data from Entra ID.", + httpStatusCode: 500, + }); + this.email = email; + } +} diff --git a/tests/live/ical.test.ts b/tests/live/ical.test.ts index b6b87e3..5663a89 100644 --- a/tests/live/ical.test.ts +++ b/tests/live/ical.test.ts @@ -1,5 +1,4 @@ import { expect, test } from "vitest"; -import { InternalServerError } from "../../src/common/errors/index.js"; import { describe } from "node:test"; import { OrganizationList } from "../../src/common/orgs.js"; import ical from "node-ical"; diff --git a/tests/live/mobileWallet.test.ts b/tests/live/mobileWallet.test.ts new file mode 100644 index 0000000..c17aff3 --- /dev/null +++ b/tests/live/mobileWallet.test.ts @@ -0,0 +1,18 @@ +import { expect, test, describe } from "vitest"; + +const baseEndpoint = `https://infra-core-api.aws.qa.acmuiuc.org`; + +describe("Mobile pass issuance", async () => { + test("Test that passes will not be issued for non-members", async () => { + const response = await fetch( + `${baseEndpoint}/api/v1/mobileWallet/membership?email=notamemberatall@illinois.edu`, + ); + expect(response.status).toBe(403); + }); + test("Test that passes will be issued for members", async () => { + const response = await fetch( + `${baseEndpoint}/api/v1/mobileWallet/membership?email=testinguser@illinois.edu`, + ); + expect(response.status).toBe(202); + }); +}); diff --git a/tests/unit/mobileWallet.test.ts b/tests/unit/mobileWallet.test.ts new file mode 100644 index 0000000..937281d --- /dev/null +++ b/tests/unit/mobileWallet.test.ts @@ -0,0 +1,88 @@ +import { afterAll, expect, test, beforeEach, vi } from "vitest"; +import init from "../../src/api/index.js"; +import { describe } from "node:test"; +import { EntraFetchError } from "../../src/common/errors/index.js"; +import { mockClient } from "aws-sdk-client-mock"; +import { issueAppleWalletMembershipCard } from "../../src/api/functions/mobileWallet.js"; +import { SendRawEmailCommand, SESClient } from "@aws-sdk/client-ses"; + +const sesMock = mockClient(SESClient); + +vi.mock("../../src/api/functions/membership.js", () => { + return { + checkPaidMembership: vi.fn( + (_endpoint: string, _log: any, netId: string) => { + if (netId === "valid") { + return true; + } + return false; + }, + ), + }; +}); + +vi.mock("../../src/api/functions/entraId.js", () => { + return { + getEntraIdToken: vi.fn().mockImplementation(async () => { + return "atokenofalltime"; + }), + getUserProfile: vi + .fn() + .mockImplementation(async (_token: string, email: string) => { + if (email === "valid@illinois.edu") { + return { displayName: "John Doe" }; + } + throw new EntraFetchError({ + message: "User not found", + email, + }); + }), + resolveEmailToOid: vi.fn().mockImplementation(async () => { + return "12345"; + }), + }; +}); + +vi.mock("../../src/api/functions/mobileWallet.js", () => { + return { + issueAppleWalletMembershipCard: vi.fn().mockImplementation(async () => { + return new ArrayBuffer(); + }), + }; +}); + +const app = await init(); +describe("Mobile wallet pass issuance", async () => { + test("Test that passes will not be issued for non-emails", async () => { + const response = await app.inject({ + method: "GET", + url: "/api/v1/mobileWallet/membership?email=notanemail", + }); + expect(response.statusCode).toBe(400); + await response.json(); + }); + test("Test that passes will not be issued for non-members", async () => { + const response = await app.inject({ + method: "GET", + url: "/api/v1/mobileWallet/membership?email=notamember@illinois.edu", + }); + expect(response.statusCode).toBe(403); + await response.json(); + }); + test("Test that passes will be issued for members", async () => { + sesMock.on(SendRawEmailCommand).resolvesOnce({}).rejects(); + const response = await app.inject({ + method: "GET", + url: "/api/v1/mobileWallet/membership?email=valid@illinois.edu", + }); + expect(response.statusCode).toBe(202); + expect(issueAppleWalletMembershipCard).toHaveBeenCalledOnce(); + }); + afterAll(async () => { + await app.close(); + }); + beforeEach(() => { + (app as any).nodeCache.flushAll(); + vi.clearAllMocks(); + }); +}); diff --git a/tests/unit/secret.testdata.ts b/tests/unit/secret.testdata.ts index 33efb5c..978bc25 100644 --- a/tests/unit/secret.testdata.ts +++ b/tests/unit/secret.testdata.ts @@ -6,6 +6,9 @@ const secretObject = { discord_bot_token: "12345", entra_id_private_key: "", entra_id_thumbprint: "", + acm_passkit_signerCert_base64: "", + acm_passkit_signerKey_base64: "", + apple_signing_cert_base64: "", } as SecretConfig & { jwt_key: string }; const secretJson = JSON.stringify(secretObject); diff --git a/yarn.lock b/yarn.lock index 26a9a55..02fc88e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -153,6 +153,52 @@ tslib "^2.6.2" uuid "^9.0.1" +"@aws-sdk/client-ses@^3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ses/-/client-ses-3.734.0.tgz#4546c9a0c11d63ba390b52d30b942fcc8bcb83db" + integrity sha512-UivyDyjEriXtBin5KMjqFVUZiTJkibLT6Td62GgABKuAItJh19kQU3EcJ6nyYCAqEmpAapwTZWJzFLf27QyauQ== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.734.0" + "@aws-sdk/credential-provider-node" "3.734.0" + "@aws-sdk/middleware-host-header" "3.734.0" + "@aws-sdk/middleware-logger" "3.734.0" + "@aws-sdk/middleware-recursion-detection" "3.734.0" + "@aws-sdk/middleware-user-agent" "3.734.0" + "@aws-sdk/region-config-resolver" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@aws-sdk/util-endpoints" "3.734.0" + "@aws-sdk/util-user-agent-browser" "3.734.0" + "@aws-sdk/util-user-agent-node" "3.734.0" + "@smithy/config-resolver" "^4.0.1" + "@smithy/core" "^3.1.1" + "@smithy/fetch-http-handler" "^5.0.1" + "@smithy/hash-node" "^4.0.1" + "@smithy/invalid-dependency" "^4.0.1" + "@smithy/middleware-content-length" "^4.0.1" + "@smithy/middleware-endpoint" "^4.0.2" + "@smithy/middleware-retry" "^4.0.3" + "@smithy/middleware-serde" "^4.0.1" + "@smithy/middleware-stack" "^4.0.1" + "@smithy/node-config-provider" "^4.0.1" + "@smithy/node-http-handler" "^4.0.2" + "@smithy/protocol-http" "^5.0.1" + "@smithy/smithy-client" "^4.1.2" + "@smithy/types" "^4.1.0" + "@smithy/url-parser" "^4.0.1" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-body-length-node" "^4.0.0" + "@smithy/util-defaults-mode-browser" "^4.0.3" + "@smithy/util-defaults-mode-node" "^4.0.3" + "@smithy/util-endpoints" "^3.0.1" + "@smithy/util-middleware" "^4.0.1" + "@smithy/util-retry" "^4.0.1" + "@smithy/util-utf8" "^4.0.0" + "@smithy/util-waiter" "^4.0.2" + tslib "^2.6.2" + "@aws-sdk/client-sso-oidc@3.721.0": version "3.721.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.721.0.tgz#a53b954e5b0112cd253d82b0f68264827e7d36ca" @@ -331,6 +377,50 @@ "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/client-sso@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.734.0.tgz#789c98267f07aaa7155b404d0bfd4059c4b4deb9" + integrity sha512-oerepp0mut9VlgTwnG5Ds/lb0C0b2/rQ+hL/rF6q+HGKPfGsCuPvFx1GtwGKCXd49ase88/jVgrhcA9OQbz3kg== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.734.0" + "@aws-sdk/middleware-host-header" "3.734.0" + "@aws-sdk/middleware-logger" "3.734.0" + "@aws-sdk/middleware-recursion-detection" "3.734.0" + "@aws-sdk/middleware-user-agent" "3.734.0" + "@aws-sdk/region-config-resolver" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@aws-sdk/util-endpoints" "3.734.0" + "@aws-sdk/util-user-agent-browser" "3.734.0" + "@aws-sdk/util-user-agent-node" "3.734.0" + "@smithy/config-resolver" "^4.0.1" + "@smithy/core" "^3.1.1" + "@smithy/fetch-http-handler" "^5.0.1" + "@smithy/hash-node" "^4.0.1" + "@smithy/invalid-dependency" "^4.0.1" + "@smithy/middleware-content-length" "^4.0.1" + "@smithy/middleware-endpoint" "^4.0.2" + "@smithy/middleware-retry" "^4.0.3" + "@smithy/middleware-serde" "^4.0.1" + "@smithy/middleware-stack" "^4.0.1" + "@smithy/node-config-provider" "^4.0.1" + "@smithy/node-http-handler" "^4.0.2" + "@smithy/protocol-http" "^5.0.1" + "@smithy/smithy-client" "^4.1.2" + "@smithy/types" "^4.1.0" + "@smithy/url-parser" "^4.0.1" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-body-length-node" "^4.0.0" + "@smithy/util-defaults-mode-browser" "^4.0.3" + "@smithy/util-defaults-mode-node" "^4.0.3" + "@smithy/util-endpoints" "^3.0.1" + "@smithy/util-middleware" "^4.0.1" + "@smithy/util-retry" "^4.0.1" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + "@aws-sdk/client-sts@3.721.0": version "3.721.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.721.0.tgz#701de8e0877aec3974291e19cd1361feda742680" @@ -457,6 +547,23 @@ fast-xml-parser "4.4.1" tslib "^2.6.2" +"@aws-sdk/core@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.734.0.tgz#fa2289750efd75f4fb8c45719a4a4ea7e7755160" + integrity sha512-SxnDqf3vobdm50OLyAKfqZetv6zzwnSqwIwd3jrbopxxHKqNIM/I0xcYjD6Tn+mPig+u7iRKb9q3QnEooFTlmg== + dependencies: + "@aws-sdk/types" "3.734.0" + "@smithy/core" "^3.1.1" + "@smithy/node-config-provider" "^4.0.1" + "@smithy/property-provider" "^4.0.1" + "@smithy/protocol-http" "^5.0.1" + "@smithy/signature-v4" "^5.0.1" + "@smithy/smithy-client" "^4.1.2" + "@smithy/types" "^4.1.0" + "@smithy/util-middleware" "^4.0.1" + fast-xml-parser "4.4.1" + tslib "^2.6.2" + "@aws-sdk/credential-provider-env@3.716.0": version "3.716.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.716.0.tgz#10ab93c5806f5e1b29dde8dae38307c766b99197" @@ -479,6 +586,17 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-env@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.734.0.tgz#6c0b1734764a7fb1616455836b1c3dacd99e50a3" + integrity sha512-gtRkzYTGafnm1FPpiNO8VBmJrYMoxhDlGPYDVcijzx3DlF8dhWnowuSBCxLSi+MJMx5hvwrX2A+e/q0QAeHqmw== + dependencies: + "@aws-sdk/core" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@smithy/property-provider" "^4.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@aws-sdk/credential-provider-http@3.716.0": version "3.716.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.716.0.tgz#6d02e3c8b67069a30f51cd3fa761a1e939940da4" @@ -511,6 +629,22 @@ "@smithy/util-stream" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-http@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.734.0.tgz#21c5fbb380d1dd503491897b346e1e0b1d06ae41" + integrity sha512-JFSL6xhONsq+hKM8xroIPhM5/FOhiQ1cov0lZxhzZWj6Ai3UAjucy3zyIFDr9MgP1KfCYNdvyaUq9/o+HWvEDg== + dependencies: + "@aws-sdk/core" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@smithy/fetch-http-handler" "^5.0.1" + "@smithy/node-http-handler" "^4.0.2" + "@smithy/property-provider" "^4.0.1" + "@smithy/protocol-http" "^5.0.1" + "@smithy/smithy-client" "^4.1.2" + "@smithy/types" "^4.1.0" + "@smithy/util-stream" "^4.0.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-ini@3.721.0": version "3.721.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.721.0.tgz#6b28d36fb3409099eb2f8e6222a6b8064516ab32" @@ -547,6 +681,25 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-ini@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.734.0.tgz#5769ae28cd255d4fc946799c0273b4af6f2f12bb" + integrity sha512-HEyaM/hWI7dNmb4NhdlcDLcgJvrilk8G4DQX6qz0i4pBZGC2l4iffuqP8K6ZQjUfz5/6894PzeFuhTORAMd+cg== + dependencies: + "@aws-sdk/core" "3.734.0" + "@aws-sdk/credential-provider-env" "3.734.0" + "@aws-sdk/credential-provider-http" "3.734.0" + "@aws-sdk/credential-provider-process" "3.734.0" + "@aws-sdk/credential-provider-sso" "3.734.0" + "@aws-sdk/credential-provider-web-identity" "3.734.0" + "@aws-sdk/nested-clients" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@smithy/credential-provider-imds" "^4.0.1" + "@smithy/property-provider" "^4.0.1" + "@smithy/shared-ini-file-loader" "^4.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@aws-sdk/credential-provider-node@3.721.0": version "3.721.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.721.0.tgz#a52dc78efebfa566711e12b53e01a9e7216cba8a" @@ -583,6 +736,24 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-node@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.734.0.tgz#86d54171c11cab5b64bfa55ab0def5e807440ad2" + integrity sha512-9NOSNbkPVb91JwaXOhyfahkzAwWdMsbWHL6fh5/PHlXYpsDjfIfT23I++toepNF2nODAJNLnOEHGYIxgNgf6jQ== + dependencies: + "@aws-sdk/credential-provider-env" "3.734.0" + "@aws-sdk/credential-provider-http" "3.734.0" + "@aws-sdk/credential-provider-ini" "3.734.0" + "@aws-sdk/credential-provider-process" "3.734.0" + "@aws-sdk/credential-provider-sso" "3.734.0" + "@aws-sdk/credential-provider-web-identity" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@smithy/credential-provider-imds" "^4.0.1" + "@smithy/property-provider" "^4.0.1" + "@smithy/shared-ini-file-loader" "^4.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@aws-sdk/credential-provider-process@3.716.0": version "3.716.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.716.0.tgz#a8a7b9416cb28c0e2ef601a2713342533619ce4c" @@ -607,6 +778,18 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-process@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.734.0.tgz#eb1de678a9c3d2d7b382e74a670fa283327f9c45" + integrity sha512-zvjsUo+bkYn2vjT+EtLWu3eD6me+uun+Hws1IyWej/fKFAqiBPwyeyCgU7qjkiPQSXqk1U9+/HG9IQ6Iiz+eBw== + dependencies: + "@aws-sdk/core" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@smithy/property-provider" "^4.0.1" + "@smithy/shared-ini-file-loader" "^4.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@aws-sdk/credential-provider-sso@3.721.0": version "3.721.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.721.0.tgz#14350ec1ccdb612af36f35e4383067ecfb99f8e6" @@ -635,6 +818,20 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-sso@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.734.0.tgz#68a9d678319e9743d65cf59e2d29c0c440d8975c" + integrity sha512-cCwwcgUBJOsV/ddyh1OGb4gKYWEaTeTsqaAK19hiNINfYV/DO9r4RMlnWAo84sSBfJuj9shUNsxzyoe6K7R92Q== + dependencies: + "@aws-sdk/client-sso" "3.734.0" + "@aws-sdk/core" "3.734.0" + "@aws-sdk/token-providers" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@smithy/property-provider" "^4.0.1" + "@smithy/shared-ini-file-loader" "^4.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@aws-sdk/credential-provider-web-identity@3.716.0": version "3.716.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.716.0.tgz#dfde14b78a311c0d5ef974f42049c41bef604a83" @@ -657,6 +854,18 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/credential-provider-web-identity@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.734.0.tgz#666b61cc9f498a3aaecd8e38c9ae34aef37e2e64" + integrity sha512-t4OSOerc+ppK541/Iyn1AS40+2vT/qE+MFMotFkhCgCJbApeRF2ozEdnDN6tGmnl4ybcUuxnp9JWLjwDVlR/4g== + dependencies: + "@aws-sdk/core" "3.734.0" + "@aws-sdk/nested-clients" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@smithy/property-provider" "^4.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@aws-sdk/endpoint-cache@3.693.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/endpoint-cache/-/endpoint-cache-3.693.0.tgz#4b3f0bbc16dc2907e1b977e3d8ddfc7ba008fd12" @@ -697,6 +906,16 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/middleware-host-header@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.734.0.tgz#a9a02c055352f5c435cc925a4e1e79b7ba41b1b5" + integrity sha512-LW7RRgSOHHBzWZnigNsDIzu3AiwtjeI2X66v+Wn1P1u+eXssy1+up4ZY/h+t2sU4LU36UvEf+jrZti9c6vRnFw== + dependencies: + "@aws-sdk/types" "3.734.0" + "@smithy/protocol-http" "^5.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@aws-sdk/middleware-logger@3.714.0": version "3.714.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.714.0.tgz#c059e1aabf28fdfc647db6a3dba625a9813787cd" @@ -715,6 +934,15 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/middleware-logger@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.734.0.tgz#d31e141ae7a78667e372953a3b86905bc6124664" + integrity sha512-mUMFITpJUW3LcKvFok176eI5zXAUomVtahb9IQBwLzkqFYOrMJvWAvoV4yuxrJ8TlQBG8gyEnkb9SnhZvjg67w== + dependencies: + "@aws-sdk/types" "3.734.0" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@aws-sdk/middleware-recursion-detection@3.714.0": version "3.714.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.714.0.tgz#c2d20d335c035196ac1cd5cdf3f58c5f31b01bdb" @@ -735,6 +963,16 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/middleware-recursion-detection@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.734.0.tgz#4fa1deb9887455afbb39130f7d9bc89ccee17168" + integrity sha512-CUat2d9ITsFc2XsmeiRQO96iWpxSKYFjxvj27Hc7vo87YUHRnfMfnc8jw1EpxEwMcvBD7LsRa6vDNky6AjcrFA== + dependencies: + "@aws-sdk/types" "3.734.0" + "@smithy/protocol-http" "^5.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@aws-sdk/middleware-user-agent@3.721.0": version "3.721.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.721.0.tgz#2a5fbfb63d42a79b4f4b9d94e5aefa66b4e57ddd" @@ -761,6 +999,63 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/middleware-user-agent@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.734.0.tgz#12d400ccb98593f2b02e4fb08239cb9835d41d3a" + integrity sha512-MFVzLWRkfFz02GqGPjqSOteLe5kPfElUrXZft1eElnqulqs6RJfVSpOV7mO90gu293tNAeggMWAVSGRPKIYVMg== + dependencies: + "@aws-sdk/core" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@aws-sdk/util-endpoints" "3.734.0" + "@smithy/core" "^3.1.1" + "@smithy/protocol-http" "^5.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + +"@aws-sdk/nested-clients@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.734.0.tgz#10a116d141522341c446b11783551ef863aabd27" + integrity sha512-iph2XUy8UzIfdJFWo1r0Zng9uWj3253yvW9gljhtu+y/LNmNvSnJxQk1f3D2BC5WmcoPZqTS3UsycT3mLPSzWA== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.734.0" + "@aws-sdk/middleware-host-header" "3.734.0" + "@aws-sdk/middleware-logger" "3.734.0" + "@aws-sdk/middleware-recursion-detection" "3.734.0" + "@aws-sdk/middleware-user-agent" "3.734.0" + "@aws-sdk/region-config-resolver" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@aws-sdk/util-endpoints" "3.734.0" + "@aws-sdk/util-user-agent-browser" "3.734.0" + "@aws-sdk/util-user-agent-node" "3.734.0" + "@smithy/config-resolver" "^4.0.1" + "@smithy/core" "^3.1.1" + "@smithy/fetch-http-handler" "^5.0.1" + "@smithy/hash-node" "^4.0.1" + "@smithy/invalid-dependency" "^4.0.1" + "@smithy/middleware-content-length" "^4.0.1" + "@smithy/middleware-endpoint" "^4.0.2" + "@smithy/middleware-retry" "^4.0.3" + "@smithy/middleware-serde" "^4.0.1" + "@smithy/middleware-stack" "^4.0.1" + "@smithy/node-config-provider" "^4.0.1" + "@smithy/node-http-handler" "^4.0.2" + "@smithy/protocol-http" "^5.0.1" + "@smithy/smithy-client" "^4.1.2" + "@smithy/types" "^4.1.0" + "@smithy/url-parser" "^4.0.1" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-body-length-node" "^4.0.0" + "@smithy/util-defaults-mode-browser" "^4.0.3" + "@smithy/util-defaults-mode-node" "^4.0.3" + "@smithy/util-endpoints" "^3.0.1" + "@smithy/util-middleware" "^4.0.1" + "@smithy/util-retry" "^4.0.1" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + "@aws-sdk/region-config-resolver@3.714.0": version "3.714.0" resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.714.0.tgz#26449aeb67daa00560c69bb80cb6cd187ee18dc9" @@ -785,6 +1080,18 @@ "@smithy/util-middleware" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/region-config-resolver@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.734.0.tgz#45ffbc56a3e94cc5c9e0cd596b0fda60f100f70b" + integrity sha512-Lvj1kPRC5IuJBr9DyJ9T9/plkh+EfKLy+12s/mykOy1JaKHDpvj+XGy2YO6YgYVOb8JFtaqloid+5COtje4JTQ== + dependencies: + "@aws-sdk/types" "3.734.0" + "@smithy/node-config-provider" "^4.0.1" + "@smithy/types" "^4.1.0" + "@smithy/util-config-provider" "^4.0.0" + "@smithy/util-middleware" "^4.0.1" + tslib "^2.6.2" + "@aws-sdk/token-providers@3.721.0": version "3.721.0" resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.721.0.tgz#7956b8e88fd995b0fed3716a4d33f0e35f76a598" @@ -807,6 +1114,18 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/token-providers@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.734.0.tgz#8880e94f21457fe5dd7074ecc52fdd43180cbb2c" + integrity sha512-2U6yWKrjWjZO8Y5SHQxkFvMVWHQWbS0ufqfAIBROqmIZNubOL7jXCiVdEFekz6MZ9LF2tvYGnOW4jX8OKDGfIw== + dependencies: + "@aws-sdk/nested-clients" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@smithy/property-provider" "^4.0.1" + "@smithy/shared-ini-file-loader" "^4.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@aws-sdk/types@3.714.0", "@aws-sdk/types@^3.222.0": version "3.714.0" resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.714.0.tgz#de6afee1436d2d95364efa0663887f3bf0b1303a" @@ -823,6 +1142,14 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/types@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.734.0.tgz#af5e620b0e761918282aa1c8e53cac6091d169a2" + integrity sha512-o11tSPTT70nAkGV1fN9wm/hAIiLPyWX6SuGf+9JyTp7S/rC2cFWhR26MvA69nplcjNaXVzB0f+QFrLXXjOqCrg== + dependencies: + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@aws-sdk/util-dynamodb@^3.624.0": version "3.721.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-dynamodb/-/util-dynamodb-3.721.0.tgz#781723705f5a6c8dd8b3bd163acb5b0a78b7e33b" @@ -850,6 +1177,16 @@ "@smithy/util-endpoints" "^3.0.0" tslib "^2.6.2" +"@aws-sdk/util-endpoints@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.734.0.tgz#43bac42a21a45477a386ccf398028e7f793bc217" + integrity sha512-w2+/E88NUbqql6uCVAsmMxDQKu7vsKV0KqhlQb0lL+RCq4zy07yXYptVNs13qrnuTfyX7uPXkXrlugvK9R1Ucg== + dependencies: + "@aws-sdk/types" "3.734.0" + "@smithy/types" "^4.1.0" + "@smithy/util-endpoints" "^3.0.1" + tslib "^2.6.2" + "@aws-sdk/util-locate-window@^3.0.0": version "3.693.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.693.0.tgz#1160f6d055cf074ca198eb8ecf89b6311537ad6c" @@ -877,6 +1214,16 @@ bowser "^2.11.0" tslib "^2.6.2" +"@aws-sdk/util-user-agent-browser@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.734.0.tgz#bbf3348b14bd7783f60346e1ce86978999450fe7" + integrity sha512-xQTCus6Q9LwUuALW+S76OL0jcWtMOVu14q+GoLnWPUM7QeUw963oQcLhF7oq0CtaLLKyl4GOUfcwc773Zmwwng== + dependencies: + "@aws-sdk/types" "3.734.0" + "@smithy/types" "^4.1.0" + bowser "^2.11.0" + tslib "^2.6.2" + "@aws-sdk/util-user-agent-node@3.721.0": version "3.721.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.721.0.tgz#d5336167c753d1bbb749044155cb54aebdf3cf32" @@ -899,6 +1246,17 @@ "@smithy/types" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/util-user-agent-node@3.734.0": + version "3.734.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.734.0.tgz#d5c6ee192cea9d53a871178a2669b8b4dea39a68" + integrity sha512-c6Iinh+RVQKs6jYUFQ64htOU2HUXFQ3TVx+8Tu3EDF19+9vzWi9UukhIMH9rqyyEXIAkk9XL7avt8y2Uyw2dGA== + dependencies: + "@aws-sdk/middleware-user-agent" "3.734.0" + "@aws-sdk/types" "3.734.0" + "@smithy/node-config-provider" "^4.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@azure/msal-browser@^3.20.0": version "3.28.0" resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.28.0.tgz#faf955f1debe24ebf24cf8cbfb67246c658c3f11" @@ -1705,6 +2063,18 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429" integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== +"@hapi/hoek@^9.0.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@humanwhocodes/config-array@^0.13.0": version "0.13.0" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" @@ -2062,6 +2432,23 @@ resolved "https://registry.yarnpkg.com/@sapphire/snowflake/-/snowflake-3.5.5.tgz#33a60ab4231e3cab29e8a0077f342125f2c8d1bd" integrity sha512-xzvBr1Q1c4lCe7i6sRnrofxeO1QTP/LKQ6A6qy0iB4x5yfiSfARMEQEghojzTNALDTcv8En04qYNIco9/K9eZQ== +"@sideway/address@^4.1.0": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" + integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@sinonjs/commons@^3.0.0", "@sinonjs/commons@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" @@ -2163,6 +2550,20 @@ "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" +"@smithy/core@^3.1.1", "@smithy/core@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-3.1.2.tgz#f5b4c89bf054b717781d71c66b4fb594e06cbb62" + integrity sha512-htwQXkbdF13uwwDevz9BEzL5ABK+1sJpVQXywwGSH973AVOvisHNfpcB8A8761G6XgHoS2kHPqc9DqHJ2gp+/Q== + dependencies: + "@smithy/middleware-serde" "^4.0.2" + "@smithy/protocol-http" "^5.0.1" + "@smithy/types" "^4.1.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-middleware" "^4.0.1" + "@smithy/util-stream" "^4.0.2" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + "@smithy/credential-provider-imds@^3.2.8": version "3.2.8" resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.8.tgz#27ed2747074c86a7d627a98e56f324a65cba88de" @@ -2217,7 +2618,7 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@smithy/hash-node@^4.0.0": +"@smithy/hash-node@^4.0.0", "@smithy/hash-node@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-4.0.1.tgz#ce78fc11b848a4f47c2e1e7a07fb6b982d2f130c" integrity sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w== @@ -2235,7 +2636,7 @@ "@smithy/types" "^3.7.2" tslib "^2.6.2" -"@smithy/invalid-dependency@^4.0.0": +"@smithy/invalid-dependency@^4.0.0", "@smithy/invalid-dependency@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-4.0.1.tgz#704d1acb6fac105558c17d53f6d55da6b0d6b6fc" integrity sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ== @@ -2273,7 +2674,7 @@ "@smithy/types" "^3.7.2" tslib "^2.6.2" -"@smithy/middleware-content-length@^4.0.0": +"@smithy/middleware-content-length@^4.0.0", "@smithy/middleware-content-length@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-4.0.1.tgz#378bc94ae623f45e412fb4f164b5bb90b9de2ba3" integrity sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ== @@ -2310,6 +2711,20 @@ "@smithy/util-middleware" "^4.0.1" tslib "^2.6.2" +"@smithy/middleware-endpoint@^4.0.2", "@smithy/middleware-endpoint@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.3.tgz#74b64fb2473ae35649a8d22d41708bc5d8d99df2" + integrity sha512-YdbmWhQF5kIxZjWqPIgboVfi8i5XgiYMM7GGKFMTvBei4XjNQfNv8sukT50ITvgnWKKKpOtp0C0h7qixLgb77Q== + dependencies: + "@smithy/core" "^3.1.2" + "@smithy/middleware-serde" "^4.0.2" + "@smithy/node-config-provider" "^4.0.1" + "@smithy/shared-ini-file-loader" "^4.0.1" + "@smithy/types" "^4.1.0" + "@smithy/url-parser" "^4.0.1" + "@smithy/util-middleware" "^4.0.1" + tslib "^2.6.2" + "@smithy/middleware-retry@^3.0.31": version "3.0.34" resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.34.tgz#136c89fc22d70819fdefc51b0d24952cf98883f1" @@ -2340,6 +2755,21 @@ tslib "^2.6.2" uuid "^9.0.1" +"@smithy/middleware-retry@^4.0.3": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-4.0.4.tgz#95e55a1b163ff06264f20b4dbbcbd915c8028f60" + integrity sha512-wmxyUBGHaYUqul0wZiset4M39SMtDBOtUr2KpDuftKNN74Do9Y36Go6Eqzj9tL0mIPpr31ulB5UUtxcsCeGXsQ== + dependencies: + "@smithy/node-config-provider" "^4.0.1" + "@smithy/protocol-http" "^5.0.1" + "@smithy/service-error-classification" "^4.0.1" + "@smithy/smithy-client" "^4.1.3" + "@smithy/types" "^4.1.0" + "@smithy/util-middleware" "^4.0.1" + "@smithy/util-retry" "^4.0.1" + tslib "^2.6.2" + uuid "^9.0.1" + "@smithy/middleware-serde@^3.0.11": version "3.0.11" resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.11.tgz#c7d54e0add4f83e05c6878a011fc664e21022f12" @@ -2356,6 +2786,14 @@ "@smithy/types" "^4.1.0" tslib "^2.6.2" +"@smithy/middleware-serde@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-4.0.2.tgz#f792d72f6ad8fa6b172e3f19c6fe1932a856a56d" + integrity sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ== + dependencies: + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@smithy/middleware-stack@^3.0.11": version "3.0.11" resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.11.tgz#453af2096924e4064d9da4e053cfdf65d9a36acc" @@ -2414,6 +2852,17 @@ "@smithy/types" "^4.1.0" tslib "^2.6.2" +"@smithy/node-http-handler@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz#48d47a046cf900ab86bfbe7f5fd078b52c82fab6" + integrity sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw== + dependencies: + "@smithy/abort-controller" "^4.0.1" + "@smithy/protocol-http" "^5.0.1" + "@smithy/querystring-builder" "^4.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@smithy/property-provider@^3.1.11": version "3.1.11" resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.11.tgz#161cf1c2a2ada361e417382c57f5ba6fbca8acad" @@ -2524,7 +2973,7 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@smithy/signature-v4@^5.0.0": +"@smithy/signature-v4@^5.0.0", "@smithy/signature-v4@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-5.0.1.tgz#f93401b176150286ba246681031b0503ec359270" integrity sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA== @@ -2564,6 +3013,19 @@ "@smithy/util-stream" "^4.0.1" tslib "^2.6.2" +"@smithy/smithy-client@^4.1.2", "@smithy/smithy-client@^4.1.3": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-4.1.3.tgz#2c8f9aff3377e7655cebe84239da6be277ba8554" + integrity sha512-A2Hz85pu8BJJaYFdX8yb1yocqigyqBzn+OVaVgm+Kwi/DkN8vhN2kbDVEfADo6jXf5hPKquMLGA3UINA64UZ7A== + dependencies: + "@smithy/core" "^3.1.2" + "@smithy/middleware-endpoint" "^4.0.3" + "@smithy/middleware-stack" "^4.0.1" + "@smithy/protocol-http" "^5.0.1" + "@smithy/types" "^4.1.0" + "@smithy/util-stream" "^4.0.2" + tslib "^2.6.2" + "@smithy/types@^3.7.2": version "3.7.2" resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.7.2.tgz#05cb14840ada6f966de1bf9a9c7dd86027343e10" @@ -2702,6 +3164,17 @@ bowser "^2.11.0" tslib "^2.6.2" +"@smithy/util-defaults-mode-browser@^4.0.3": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.4.tgz#6fa7ba64a80a77f27b9b5c6972918904578b8d5b" + integrity sha512-Ej1bV5sbrIfH++KnWxjjzFNq9nyP3RIUq2c9Iqq7SmMO/idUR24sqvKH2LUQFTSPy/K7G4sB2m8n7YYlEAfZaw== + dependencies: + "@smithy/property-provider" "^4.0.1" + "@smithy/smithy-client" "^4.1.3" + "@smithy/types" "^4.1.0" + bowser "^2.11.0" + tslib "^2.6.2" + "@smithy/util-defaults-mode-node@^3.0.31": version "3.0.34" resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.34.tgz#5eb0d97231a34e137980abfb08ea5e3a8f2156f7" @@ -2728,6 +3201,19 @@ "@smithy/types" "^4.1.0" tslib "^2.6.2" +"@smithy/util-defaults-mode-node@^4.0.3": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.4.tgz#5470fdc96672cee5199620b576d7025de3b17333" + integrity sha512-HE1I7gxa6yP7ZgXPCFfZSDmVmMtY7SHqzFF55gM/GPegzZKaQWZZ+nYn9C2Cc3JltCMyWe63VPR3tSFDEvuGjw== + dependencies: + "@smithy/config-resolver" "^4.0.1" + "@smithy/credential-provider-imds" "^4.0.1" + "@smithy/node-config-provider" "^4.0.1" + "@smithy/property-provider" "^4.0.1" + "@smithy/smithy-client" "^4.1.3" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@smithy/util-endpoints@^2.1.7": version "2.1.7" resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.1.7.tgz#a088ebfab946a7219dd4763bfced82709894b82d" @@ -2737,7 +3223,7 @@ "@smithy/types" "^3.7.2" tslib "^2.6.2" -"@smithy/util-endpoints@^3.0.0": +"@smithy/util-endpoints@^3.0.0", "@smithy/util-endpoints@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-3.0.1.tgz#44ccbf1721447966f69496c9003b87daa8f61975" integrity sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA== @@ -2822,6 +3308,20 @@ "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" +"@smithy/util-stream@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-4.0.2.tgz#63495d3f7fba9d78748d540921136dc4a8d4c067" + integrity sha512-0eZ4G5fRzIoewtHtwaYyl8g2C+osYOT4KClXgfdNEDAgkbe2TYPqcnw4GAWabqkZCax2ihRGPe9LZnsPdIUIHA== + dependencies: + "@smithy/fetch-http-handler" "^5.0.1" + "@smithy/node-http-handler" "^4.0.2" + "@smithy/types" "^4.1.0" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-buffer-from" "^4.0.0" + "@smithy/util-hex-encoding" "^4.0.0" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + "@smithy/util-uri-escape@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz#e43358a78bf45d50bb736770077f0f09195b6f54" @@ -2869,6 +3369,15 @@ "@smithy/types" "^3.7.2" tslib "^2.6.2" +"@smithy/util-waiter@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-4.0.2.tgz#0a73a0fcd30ea7bbc3009cf98ad199f51b8eac51" + integrity sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ== + dependencies: + "@smithy/abort-controller" "^4.0.1" + "@smithy/types" "^4.1.0" + tslib "^2.6.2" + "@storybook/addon-actions@8.4.7": version "8.4.7" resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-8.4.7.tgz#210c6bb5a7e17c3664c300b4b69b6243ec34b9cd" @@ -3817,6 +4326,14 @@ ansi-styles@^6.1.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + arch@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" @@ -4080,6 +4597,11 @@ balanced-match@^2.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9" integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA== +base64-arraybuffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc" + integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ== + bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -4094,6 +4616,11 @@ better-opn@^3.0.2: dependencies: open "^8.0.4" +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + bowser@^2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" @@ -4128,7 +4655,7 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.3: +braces@^3.0.3, braces@~3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== @@ -4279,6 +4806,21 @@ check-error@^2.1.1: resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== +chokidar@^3.5.2: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + cli-boxes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145" @@ -4584,7 +5126,7 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7: +debug@4, debug@^4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7: version "4.4.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== @@ -4723,6 +5265,11 @@ discord.js@^14.15.3: tslib "^2.6.3" undici "6.19.8" +do-not-zip@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/do-not-zip/-/do-not-zip-1.0.0.tgz#cdced6c6352664ecb368f9fe7a15e1cb40c50c42" + integrity sha512-Pgd81ET43bhAGaN2Hq1zluSX1FmD7kl7KcV9ER/lawiLsRUB9pRA5y8r6us29Xk6BrINZETO8TjhYwtwafWUww== + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -5894,7 +6441,7 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob-parent@^5.0.0, glob-parent@^5.1.2: +glob-parent@^5.0.0, glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -6151,6 +6698,11 @@ identity-obj-proxy@^3.0.0: dependencies: harmony-reflect "^1.4.6" +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== + ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -6274,6 +6826,13 @@ is-bigint@^1.1.0: dependencies: has-bigints "^1.0.2" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-boolean-object@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.1.tgz#c20d0c654be05da4fbc23c562635c019e93daf89" @@ -6355,7 +6914,7 @@ is-generator-function@^1.0.10, is-generator-function@^1.0.7: has-tostringtag "^1.0.2" safe-regex-test "^1.1.0" -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -6515,6 +7074,17 @@ iterator.prototype@^1.1.4: has-symbols "^1.1.0" set-function-name "^2.0.2" +joi@17.4.2: + version "17.4.2" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.2.tgz#02f4eb5cf88e515e614830239379dcbbe28ce7f7" + integrity sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.0" + "@sideway/formula" "^3.0.0" + "@sideway/pinpoint" "^2.0.0" + jose@^4.14.6: version "4.15.9" resolved "https://registry.yarnpkg.com/jose/-/jose-4.15.9.tgz#9b68eda29e9a0614c042fa29387196c7dd800100" @@ -7158,6 +7728,11 @@ node-cache@^5.1.2: dependencies: clone "2.x" +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + node-ical@^0.20.1: version "0.20.1" resolved "https://registry.yarnpkg.com/node-ical/-/node-ical-0.20.1.tgz#3a67319af9be956b3cc81cdf6716d1352eaefaca" @@ -7173,7 +7748,23 @@ node-releases@^2.0.19: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== -normalize-path@^3.0.0: +nodemon@^3.1.9: + version "3.1.9" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.9.tgz#df502cdc3b120e1c3c0c6e4152349019efa7387b" + integrity sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg== + dependencies: + chokidar "^3.5.2" + debug "^4" + ignore-by-default "^1.0.1" + minimatch "^3.1.2" + pstree.remy "^1.1.8" + semver "^7.5.3" + simple-update-notifier "^2.0.0" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.5" + +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -7387,6 +7978,16 @@ parse5@^7.1.2: dependencies: entities "^4.5.0" +passkit-generator@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/passkit-generator/-/passkit-generator-3.3.1.tgz#8e711973b40ff09316367823030bd404731b3a7c" + integrity sha512-Kme0BjZTiBNSnCMMM0Vndjq1EzSIePU1Pne9jHY08WctmHlA8CEgbRRjzh1S9oBHO7qkDVOGek5OW4oJWTe8Ug== + dependencies: + do-not-zip "^1.0.0" + joi "17.4.2" + node-forge "^1.3.1" + tslib "^2.7.0" + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -7459,7 +8060,7 @@ picocolors@^1.0.0, picocolors@^1.1.0, picocolors@^1.1.1: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -7700,6 +8301,11 @@ psl@^1.1.28, psl@^1.1.33: dependencies: punycode "^2.3.1" +pstree.remy@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -7900,6 +8506,13 @@ react-transition-group@4.4.5: dependencies: loose-envify "^1.1.0" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + real-require@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" @@ -8243,7 +8856,7 @@ semver@^6.1.2, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.5.4, semver@^7.6.0, semver@^7.6.2, semver@^7.6.3: +semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2, semver@^7.6.3: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== @@ -8398,6 +9011,13 @@ signal-exit@^4.0.1: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +simple-update-notifier@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" + integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== + dependencies: + semver "^7.5.3" + sinon@^18.0.1: version "18.0.1" resolved "https://registry.yarnpkg.com/sinon/-/sinon-18.0.1.tgz#464334cdfea2cddc5eda9a4ea7e2e3f0c7a91c5e" @@ -8803,7 +9423,7 @@ supertest@^7.0.0: methods "^1.1.2" superagent "^9.0.1" -supports-color@^5.3.0: +supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -8980,6 +9600,11 @@ totalist@^3.0.0: resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== +touch@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694" + integrity sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA== + tough-cookie@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" @@ -9059,7 +9684,7 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.6.3: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.6.3, tslib@^2.7.0: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -9211,6 +9836,11 @@ unbox-primitive@^1.1.0: has-symbols "^1.1.0" which-boxed-primitive "^1.1.1" +undefsafe@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== + undici-types@~6.20.0: version "6.20.0" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"