diff --git a/.env.template b/.env.template index 9c32c6d06..f8a92aeb7 100644 --- a/.env.template +++ b/.env.template @@ -11,3 +11,4 @@ ENABLE_CLOUD= ENABLE_MOVE_DATABASE= SHOULD_REPORT_TRACE= TRACE_REPORT_ENDPOINT= +CAPTCHA_SITE_KEY= \ No newline at end of file diff --git a/.github/actions/deploy/deploy.mjs b/.github/actions/deploy/deploy.mjs index 093beae18..b38c117e3 100644 --- a/.github/actions/deploy/deploy.mjs +++ b/.github/actions/deploy/deploy.mjs @@ -13,6 +13,8 @@ const { R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET, + ENABLE_CAPTCHA, + CAPTCHA_TURNSTILE_SECRET, OAUTH_EMAIL_SENDER, OAUTH_EMAIL_LOGIN, OAUTH_EMAIL_PASSWORD, @@ -81,6 +83,8 @@ const createHelmCommand = ({ isDryRun }) => { `--set graphql.replicaCount=${graphqlReplicaCount}`, `--set-string graphql.image.tag="${imageTag}"`, `--set graphql.app.host=${host}`, + `--set graphql.app.captcha.enabled=${ENABLE_CAPTCHA}`, + `--set-string graphql.app.captcha.turnstile.secret="${CAPTCHA_TURNSTILE_SECRET}"`, `--set graphql.app.objectStorage.r2.enabled=true`, `--set-string graphql.app.objectStorage.r2.accountId="${R2_ACCOUNT_ID}"`, `--set-string graphql.app.objectStorage.r2.accessKeyId="${R2_ACCESS_KEY_ID}"`, diff --git a/.github/helm/affine/charts/graphql/templates/captcha-secret.yaml b/.github/helm/affine/charts/graphql/templates/captcha-secret.yaml new file mode 100644 index 000000000..009091c9c --- /dev/null +++ b/.github/helm/affine/charts/graphql/templates/captcha-secret.yaml @@ -0,0 +1,9 @@ +{{- if .Values.app.captcha.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: "{{ .Values.app.captcha.secretName }}" +type: Opaque +data: + turnstileSecret: {{ .Values.app.captcha.turnstile.secret | b64enc }} +{{- end }} diff --git a/.github/helm/affine/charts/graphql/templates/deployment.yaml b/.github/helm/affine/charts/graphql/templates/deployment.yaml index 41c68fa5f..efb679910 100644 --- a/.github/helm/affine/charts/graphql/templates/deployment.yaml +++ b/.github/helm/affine/charts/graphql/templates/deployment.yaml @@ -73,6 +73,8 @@ spec: value: "{{ .Values.app.host }}" - name: ENABLE_R2_OBJECT_STORAGE value: "{{ .Values.app.objectStorage.r2.enabled }}" + - name: ENABLE_CAPTCHA + value: "{{ .Values.app.captcha.enabled }}" - name: OAUTH_EMAIL_SENDER valueFrom: secretKeyRef: @@ -126,6 +128,13 @@ spec: name: "{{ .Values.app.objectStorage.r2.secretName }}" key: bucket {{ end }} + {{ if .Values.app.captcha.enabled }} + - name: CAPTCHA_TURNSTILE_SECRET + valueFrom: + secretKeyRef: + name: "{{ .Values.app.captcha.secretName }}" + key: turnstileSecret + {{ end }} {{ if .Values.app.oauth.google.enabled }} - name: OAUTH_GOOGLE_CLIENT_ID valueFrom: diff --git a/.github/helm/affine/charts/graphql/values.yaml b/.github/helm/affine/charts/graphql/values.yaml index bdb270b7e..41d544843 100644 --- a/.github/helm/affine/charts/graphql/values.yaml +++ b/.github/helm/affine/charts/graphql/values.yaml @@ -22,6 +22,11 @@ app: secretName: jwt-private-key # base64 encoded ecdsa private key privateKey: '' + captcha: + enable: false + secretName: captcha + turnstile: + secret: '' objectStorage: r2: enabled: false diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c04a2d498..9963899ec 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -57,6 +57,7 @@ jobs: BUILD_TYPE_OVERRIDE: ${{ github.event.inputs.flavor }} SHOULD_REPORT_TRACE: true TRACE_REPORT_ENDPOINT: ${{ secrets.TRACE_REPORT_ENDPOINT }} + CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }} - name: Upload core artifact uses: actions/upload-artifact@v3 with: @@ -197,6 +198,8 @@ jobs: R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} R2_BUCKET: ${{ secrets.R2_BUCKET }} + ENABLE_CAPTCHA: true + CAPTCHA_TURNSTILE_SECRET: ${{ secrets.CAPTCHA_TURNSTILE_SECRET }} OAUTH_EMAIL_SENDER: ${{ secrets.OAUTH_EMAIL_SENDER }} OAUTH_EMAIL_LOGIN: ${{ secrets.OAUTH_EMAIL_LOGIN }} OAUTH_EMAIL_PASSWORD: ${{ secrets.OAUTH_EMAIL_PASSWORD }} diff --git a/Cargo.lock b/Cargo.lock index dcdcdfabb..d9f49eb81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,8 +41,10 @@ dependencies = [ "notify", "once_cell", "parking_lot", + "rand", "serde", "serde_json", + "sha3", "sqlx", "tokio", "uuid", @@ -56,12 +58,16 @@ version = "0.0.0" name = "affine_storage" version = "1.0.0" dependencies = [ + "chrono", "jwst-codec", "jwst-core", "jwst-storage", "napi", "napi-build", "napi-derive", + "rand", + "sha3", + "tokio", ] [[package]] @@ -1188,6 +1194,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + [[package]] name = "kqueue" version = "1.0.8" @@ -2284,6 +2299,16 @@ dependencies = [ "digest", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.7" diff --git a/apps/core/.webpack/config.ts b/apps/core/.webpack/config.ts index c26572e28..9233c9cb4 100644 --- a/apps/core/.webpack/config.ts +++ b/apps/core/.webpack/config.ts @@ -359,6 +359,9 @@ export const createConfiguration: ( 'process.env.TRACE_REPORT_ENDPOINT': JSON.stringify( process.env.TRACE_REPORT_ENDPOINT ), + 'process.env.CAPTCHA_SITE_KEY': JSON.stringify( + process.env.CAPTCHA_SITE_KEY + ), runtimeConfig: JSON.stringify(runtimeConfig), }), new CopyPlugin({ diff --git a/apps/core/.webpack/runtime-config.ts b/apps/core/.webpack/runtime-config.ts index 31937b474..109e93c05 100644 --- a/apps/core/.webpack/runtime-config.ts +++ b/apps/core/.webpack/runtime-config.ts @@ -29,6 +29,7 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig { enableMoveDatabase: false, enableNotificationCenter: true, enableCloud: true, + enableCaptcha: true, enableEnhanceShareMode: false, serverUrlPrefix: 'https://app.affine.pro', editorFlags, @@ -62,6 +63,7 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig { enableMoveDatabase: false, enableNotificationCenter: true, enableCloud: true, + enableCaptcha: true, enableEnhanceShareMode: false, serverUrlPrefix: 'https://affine.fail', editorFlags, @@ -107,6 +109,11 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig { enableCloud: process.env.ENABLE_CLOUD ? process.env.ENABLE_CLOUD === 'true' : currentBuildPreset.enableCloud, + enableCaptcha: process.env.ENABLE_CAPTCHA + ? process.env.ENABLE_CAPTCHA === 'true' + : buildFlags.mode === 'development' + ? false + : currentBuildPreset.enableCaptcha, enableEnhanceShareMode: process.env.ENABLE_ENHANCE_SHARE_MODE ? process.env.ENABLE_ENHANCE_SHARE_MODE === 'true' : currentBuildPreset.enableEnhanceShareMode, diff --git a/apps/core/package.json b/apps/core/package.json index 24084049e..f0089898b 100644 --- a/apps/core/package.json +++ b/apps/core/package.json @@ -37,6 +37,7 @@ "@emotion/react": "^11.11.1", "@emotion/server": "^11.11.0", "@emotion/styled": "^11.11.0", + "@marsidev/react-turnstile": "^0.3.1", "@mui/material": "^5.14.13", "@radix-ui/react-select": "^2.0.0", "@react-hookz/web": "^23.1.0", @@ -61,7 +62,7 @@ "react-router-dom": "^6.16.0", "rxjs": "^7.8.1", "ses": "^0.18.8", - "swr": "2.2.0", + "swr": "2.2.4", "valtio": "^1.11.2", "y-protocols": "^1.0.6", "yjs": "^13.6.8", diff --git a/apps/core/src/components/affine/auth/after-sign-in-send-email.tsx b/apps/core/src/components/affine/auth/after-sign-in-send-email.tsx index a3344a98e..b2bc2b742 100644 --- a/apps/core/src/components/affine/auth/after-sign-in-send-email.tsx +++ b/apps/core/src/components/affine/auth/after-sign-in-send-email.tsx @@ -13,6 +13,7 @@ import { useCurrentLoginStatus } from '../../../hooks/affine/use-current-login-s import type { AuthPanelProps } from './index'; import * as style from './style.css'; import { useAuth } from './use-auth'; +import { Captcha, useCaptcha } from './use-captcha'; export const AfterSignInSendEmail = ({ setAuthState, @@ -21,6 +22,7 @@ export const AfterSignInSendEmail = ({ }: AuthPanelProps) => { const t = useAFFiNEI18N(); const loginStatus = useCurrentLoginStatus(); + const [verifyToken, challenge] = useCaptcha(); const { resendCountDown, allowSendEmail, signIn } = useAuth(); if (loginStatus === 'authenticated') { @@ -28,8 +30,10 @@ export const AfterSignInSendEmail = ({ } const onResendClick = useCallback(async () => { - await signIn(email); - }, [email, signIn]); + if (verifyToken) { + await signIn(email, verifyToken, challenge); + } + }, [challenge, email, signIn, verifyToken]); return ( <> @@ -37,7 +41,7 @@ export const AfterSignInSendEmail = ({ title={t['com.affine.auth.sign.in']()} subTitle={t['com.affine.auth.sign.in.sent.email.subtitle']()} /> - + {t['com.affine.auth.sign.sent.email.message.start']()} {email} {t['com.affine.auth.sign.sent.email.message.end']()} @@ -45,9 +49,18 @@ export const AfterSignInSendEmail = ({
{allowSendEmail ? ( - + <> + + + ) : ( <> diff --git a/apps/core/src/components/affine/auth/after-sign-up-send-email.tsx b/apps/core/src/components/affine/auth/after-sign-up-send-email.tsx index 71fa68a67..3a2d21ff1 100644 --- a/apps/core/src/components/affine/auth/after-sign-up-send-email.tsx +++ b/apps/core/src/components/affine/auth/after-sign-up-send-email.tsx @@ -12,6 +12,7 @@ import { useCurrentLoginStatus } from '../../../hooks/affine/use-current-login-s import type { AuthPanelProps } from './index'; import * as style from './style.css'; import { useAuth } from './use-auth'; +import { Captcha, useCaptcha } from './use-captcha'; export const AfterSignUpSendEmail: FC = ({ setAuthState, @@ -20,6 +21,7 @@ export const AfterSignUpSendEmail: FC = ({ }) => { const t = useAFFiNEI18N(); const loginStatus = useCurrentLoginStatus(); + const [verifyToken, challenge] = useCaptcha(); const { resendCountDown, allowSendEmail, signUp } = useAuth(); @@ -28,8 +30,10 @@ export const AfterSignUpSendEmail: FC = ({ } const onResendClick = useCallback(async () => { - await signUp(email); - }, [email, signUp]); + if (verifyToken) { + await signUp(email, verifyToken, challenge); + } + }, [challenge, email, signUp, verifyToken]); return ( <> @@ -37,7 +41,7 @@ export const AfterSignUpSendEmail: FC = ({ title={t['com.affine.auth.sign.up']()} subTitle={t['com.affine.auth.sign.up.sent.email.subtitle']()} /> - + {t['com.affine.auth.sign.sent.email.message.start']()} {email} {t['com.affine.auth.sign.sent.email.message.end']()} @@ -45,9 +49,18 @@ export const AfterSignUpSendEmail: FC = ({
{allowSendEmail ? ( - + <> + + + ) : ( <> diff --git a/apps/core/src/components/affine/auth/sign-in.tsx b/apps/core/src/components/affine/auth/sign-in.tsx index 87ee60404..fcc68f304 100644 --- a/apps/core/src/components/affine/auth/sign-in.tsx +++ b/apps/core/src/components/affine/auth/sign-in.tsx @@ -18,6 +18,7 @@ import { emailRegex } from '../../../utils/email-regex'; import type { AuthPanelProps } from './index'; import * as style from './style.css'; import { INTERNAL_BETA_URL, useAuth } from './use-auth'; +import { Captcha, useCaptcha } from './use-captcha'; function validateEmail(email: string) { return emailRegex.test(email); @@ -31,6 +32,7 @@ export const SignIn: FC = ({ }) => { const t = useAFFiNEI18N(); const loginStatus = useCurrentLoginStatus(); + const [verifyToken, challenge] = useCaptcha(); const { isMutating: isSigningIn, @@ -78,20 +80,33 @@ export const SignIn: FC = ({ } setAuthEmail(email); - if (user) { - const res = await signIn(email); - if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) { - return setAuthState('noAccess'); + if (verifyToken) { + if (user) { + const res = await signIn(email, verifyToken, challenge); + if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) { + return setAuthState('noAccess'); + } + setAuthState('afterSignInSendEmail'); + } else { + const res = await signUp(email, verifyToken, challenge); + if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) { + return setAuthState('noAccess'); + } else if (!res || res.status >= 400 || res.error) { + return; + } + setAuthState('afterSignUpSendEmail'); } - setAuthState('afterSignInSendEmail'); - } else { - const res = await signUp(email); - if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) { - return setAuthState('noAccess'); - } - setAuthState('afterSignUpSendEmail'); } - }, [email, setAuthEmail, setAuthState, signIn, signUp, verifyUser]); + }, [ + challenge, + email, + setAuthEmail, + setAuthState, + signIn, + signUp, + verifyToken, + verifyUser, + ]); return ( <> @@ -133,41 +148,45 @@ export const SignIn: FC = ({ onEnter={onContinue} /> - + {verifyToken ? null : } + + {verifyToken ? ( + + ) : null}
{/*prettier-ignore*/} By clicking "Continue with Google/Email" above, you acknowledge that you agree to AFFiNE's Terms of Conditions and Privacy Policy. - +
diff --git a/apps/core/src/components/affine/auth/style.css.ts b/apps/core/src/components/affine/auth/style.css.ts index ba6f5df03..23d814e1e 100644 --- a/apps/core/src/components/affine/auth/style.css.ts +++ b/apps/core/src/components/affine/auth/style.css.ts @@ -4,6 +4,12 @@ export const authModalContent = style({ marginTop: '30px', }); +export const captchaWrapper = style({ + margin: 'auto', + marginBottom: '4px', + textAlign: 'center', +}); + export const authMessage = style({ marginTop: '30px', color: 'var(--affine-text-secondary-color)', @@ -28,8 +34,9 @@ export const forgetPasswordButton = style({ }); export const resendWrapper = style({ - height: 32, + height: 77, display: 'flex', + flexDirection: 'column', justifyContent: 'center', alignItems: 'center', marginTop: 30, diff --git a/apps/core/src/components/affine/auth/use-auth.ts b/apps/core/src/components/affine/auth/use-auth.ts index 013571bb6..46f2dd96b 100644 --- a/apps/core/src/components/affine/auth/use-auth.ts +++ b/apps/core/src/components/affine/auth/use-auth.ts @@ -63,7 +63,7 @@ export const useAuth = () => { const startResendCountDown = useSetAtom(countDownAtom); const signIn = useCallback( - async (email: string) => { + async (email: string, verifyToken: string, challenge?: string) => { setAuthStore(prev => { return { ...prev, @@ -71,11 +71,20 @@ export const useAuth = () => { }; }); - const res = await signInCloud('email', { - email: email, - callbackUrl: '/auth/signIn', - redirect: false, - }).catch(console.error); + const res = await signInCloud( + 'email', + { + email: email, + callbackUrl: '/auth/signIn', + redirect: false, + }, + challenge + ? { + challenge, + token: verifyToken, + } + : { token: verifyToken } + ).catch(console.error); handleSendEmailError(res, pushNotification); @@ -93,7 +102,7 @@ export const useAuth = () => { ); const signUp = useCallback( - async (email: string) => { + async (email: string, verifyToken: string, challenge?: string) => { setAuthStore(prev => { return { ...prev, @@ -101,11 +110,20 @@ export const useAuth = () => { }; }); - const res = await signInCloud('email', { - email: email, - callbackUrl: '/auth/signUp', - redirect: false, - }).catch(console.error); + const res = await signInCloud( + 'email', + { + email: email, + callbackUrl: '/auth/signUp', + redirect: false, + }, + challenge + ? { + challenge, + token: verifyToken, + } + : { token: verifyToken } + ).catch(console.error); handleSendEmailError(res, pushNotification); diff --git a/apps/core/src/components/affine/auth/use-captcha.tsx b/apps/core/src/components/affine/auth/use-captcha.tsx new file mode 100644 index 000000000..e00ce5325 --- /dev/null +++ b/apps/core/src/components/affine/auth/use-captcha.tsx @@ -0,0 +1,105 @@ +import { fetchWithTraceReport } from '@affine/graphql'; +import { Turnstile } from '@marsidev/react-turnstile'; +import { atom, useAtom, useSetAtom } from 'jotai'; +import { useEffect, useRef } from 'react'; +import useSWR from 'swr'; + +import * as style from './style.css'; + +type Challenge = { + challenge: string; + resource: string; +}; + +const challengeFetcher = async (url: string) => { + if (!environment.isDesktop) { + return undefined; + } + + const res = await fetchWithTraceReport(url); + if (!res.ok) { + throw new Error('Failed to fetch challenge'); + } + const challenge = (await res.json()) as Challenge; + if (!challenge || !challenge.challenge || !challenge.resource) { + throw new Error('Invalid challenge'); + } + + return challenge; +}; +const generateChallengeResponse = async (challenge: string) => { + if (!environment.isDesktop) { + return undefined; + } + + return await window.apis?.ui?.getChallengeResponse(challenge); +}; + +const captchaAtom = atom(undefined); +const responseAtom = atom(undefined); + +export const Captcha = () => { + const setCaptcha = useSetAtom(captchaAtom); + const [response] = useAtom(responseAtom); + + if (!runtimeConfig.enableCaptcha) { + return <>; + } + + if (environment.isDesktop) { + if (response) { + return
Making Challenge
; + } else { + return
Verified Client
; + } + } + + return ( + + ); +}; + +export const useCaptcha = (): [string | undefined, string?] => { + const [verifyToken] = useAtom(captchaAtom); + const [response, setResponse] = useAtom(responseAtom); + + const { data: challenge } = useSWR('/api/auth/challenge', challengeFetcher, { + suspense: false, + revalidateOnFocus: false, + }); + const prevChallenge = useRef(''); + + useEffect(() => { + if ( + runtimeConfig.enableCaptcha && + environment.isDesktop && + challenge?.challenge && + prevChallenge.current !== challenge.challenge + ) { + prevChallenge.current = challenge.challenge; + generateChallengeResponse(challenge.resource) + .then(setResponse) + .catch(err => { + console.error('Error getting challenge response:', err); + }); + } + }, [challenge, setResponse]); + + if (!runtimeConfig.enableCaptcha) { + return ['XXXX.DUMMY.TOKEN.XXXX']; + } + + if (environment.isDesktop) { + if (response) { + return [response, challenge?.challenge]; + } else { + return [undefined, challenge?.challenge]; + } + } + + return [verifyToken]; +}; diff --git a/apps/electron/src/main/ui/challenge.ts b/apps/electron/src/main/ui/challenge.ts new file mode 100644 index 000000000..06a976066 --- /dev/null +++ b/apps/electron/src/main/ui/challenge.ts @@ -0,0 +1,7 @@ +import { mintChallengeResponse } from '@affine/native'; + +export const getChallengeResponse = async (resource: string) => { + // 20 bits challenge is a balance between security and user experience + // 20 bits challenge cost time is about 1-3s on m2 macbook air + return mintChallengeResponse(resource, 20); +}; diff --git a/apps/electron/src/main/ui/handlers.ts b/apps/electron/src/main/ui/handlers.ts index 271a13964..5e41a4625 100644 --- a/apps/electron/src/main/ui/handlers.ts +++ b/apps/electron/src/main/ui/handlers.ts @@ -4,6 +4,7 @@ import { getLinkPreview } from 'link-preview-js'; import { isMacOS } from '../../shared/utils'; import { logger } from '../logger'; import type { NamespaceHandlers } from '../type'; +import { getChallengeResponse } from './challenge'; import { getGoogleOauthCode } from './google-auth'; export const uiHandlers = { @@ -45,6 +46,9 @@ export const uiHandlers = { getGoogleOauthCode: async () => { return getGoogleOauthCode(); }, + getChallengeResponse: async (_, challenge: string) => { + return getChallengeResponse(challenge); + }, getBookmarkDataByLink: async (_, link: string) => { if ( (link.startsWith('https://x.com/') || diff --git a/apps/server/.env.example b/apps/server/.env.example index 01e76c182..55d11ef5f 100644 --- a/apps/server/.env.example +++ b/apps/server/.env.example @@ -3,4 +3,4 @@ NEXTAUTH_URL="http://localhost:8080" OAUTH_EMAIL_SENDER="noreply@toeverything.info" OAUTH_EMAIL_LOGIN="" OAUTH_EMAIL_PASSWORD="" -ENABLE_LOCAL_EMAIL="true" +ENABLE_LOCAL_EMAIL="true" \ No newline at end of file diff --git a/apps/server/src/config/def.ts b/apps/server/src/config/def.ts index c72c302d6..345b3942e 100644 --- a/apps/server/src/config/def.ts +++ b/apps/server/src/config/def.ts @@ -320,6 +320,27 @@ export interface AFFiNEConfig { sender: string; password: string; }; + captcha: { + /** + * whether to enable captcha + */ + enable: boolean; + turnstile: { + /** + * Cloudflare Turnstile CAPTCHA secret + * default value is demo api key, witch always return success + */ + secret: string; + }; + challenge: { + /** + * challenge bits length + * default value is 20, which can resolve in 0.5-3 second in M2 MacBook Air in single thread + * @default 20 + */ + bits: number; + }; + }; }; doc: { diff --git a/apps/server/src/config/default.ts b/apps/server/src/config/default.ts index eeea425d3..b23b915f7 100644 --- a/apps/server/src/config/default.ts +++ b/apps/server/src/config/default.ts @@ -62,6 +62,8 @@ export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => { R2_OBJECT_STORAGE_ACCESS_KEY_ID: 'objectStorage.r2.accessKeyId', R2_OBJECT_STORAGE_SECRET_ACCESS_KEY: 'objectStorage.r2.secretAccessKey', R2_OBJECT_STORAGE_BUCKET: 'objectStorage.r2.bucket', + ENABLE_CAPTCHA: ['auth.captcha.enable', 'boolean'], + CAPTCHA_TURNSTILE_SECRET: ['auth.captcha.turnstile.secret', 'string'], OAUTH_GOOGLE_ENABLED: ['auth.oauthProviders.google.enabled', 'boolean'], OAUTH_GOOGLE_CLIENT_ID: 'auth.oauthProviders.google.clientId', OAUTH_GOOGLE_CLIENT_SECRET: 'auth.oauthProviders.google.clientSecret', @@ -147,6 +149,15 @@ export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion refreshTokenExpiresIn: parse('7d')! / 1000, leeway: 60, + captcha: { + enable: false, + turnstile: { + secret: '1x0000000000000000000000000000000AA', + }, + challenge: { + bits: 20, + }, + }, privateKey: jwtKeyPair.privateKey, publicKey: jwtKeyPair.publicKey, enableSignup: true, diff --git a/apps/server/src/modules/auth/next-auth.controller.ts b/apps/server/src/modules/auth/next-auth.controller.ts index 25daf4153..8a1ee52b0 100644 --- a/apps/server/src/modules/auth/next-auth.controller.ts +++ b/apps/server/src/modules/auth/next-auth.controller.ts @@ -4,6 +4,7 @@ import { All, BadRequestException, Controller, + Get, Inject, Logger, Next, @@ -17,12 +18,14 @@ import { hash, verify } from '@node-rs/argon2'; import type { User } from '@prisma/client'; import type { NextFunction, Request, Response } from 'express'; import { pick } from 'lodash-es'; +import { nanoid } from 'nanoid'; import type { AuthAction, CookieOption, NextAuthOptions } from 'next-auth'; import { AuthHandler } from 'next-auth/core'; import { Config } from '../../config'; import { Metrics } from '../../metrics/metrics'; import { PrismaService } from '../../prisma/service'; +import { SessionService } from '../../session'; import { AuthThrottlerGuard, Throttle } from '../../throttler'; import { NextAuthOptionsProvide } from './next-auth-options'; import { AuthService } from './service'; @@ -43,12 +46,28 @@ export class NextAuthController { private readonly authService: AuthService, @Inject(NextAuthOptionsProvide) private readonly nextAuthOptions: NextAuthOptions, - private readonly metrics: Metrics + private readonly metrics: Metrics, + private readonly session: SessionService ) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.callbackSession = nextAuthOptions.callbacks!.session; } + @UseGuards(AuthThrottlerGuard) + @Throttle({ + default: { + limit: 60, + ttl: 60, + }, + }) + @Get('/challenge') + async getChallenge(@Res() res: Response) { + const challenge = nanoid(); + const resource = nanoid(); + await this.session.set(challenge, resource, 5 * 60 * 1000); + res.json({ challenge, resource }); + } + @UseGuards(AuthThrottlerGuard) @Throttle({ default: { @@ -128,6 +147,16 @@ export class NextAuthController { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion options.callbacks!.session = this.callbackSession; } + + if ( + this.config.auth.captcha.enable && + req.method === 'POST' && + action === 'signin' + ) { + const isVerified = await this.verifyChallenge(req, res); + if (!isVerified) return; + } + const { status, headers, body, redirect, cookies } = await AuthHandler({ req: { body: req.body, @@ -270,6 +299,44 @@ export class NextAuthController { } } + private async verifyChallenge(req: Request, res: Response): Promise { + const challenge = req.query?.challenge; + if (typeof challenge === 'string' && challenge) { + const resource = await this.session.get(challenge); + + if (!resource) { + this.rejectResponse(res, 'Invalid Challenge'); + return false; + } + + const isChallengeVerified = + await this.authService.verifyChallengeResponse( + req.query?.token, + resource + ); + + this.logger.debug( + `Challenge: ${challenge}, Resource: ${resource}, Response: ${req.query?.token}, isChallengeVerified: ${isChallengeVerified}` + ); + + if (!isChallengeVerified) { + this.rejectResponse(res, 'Invalid Challenge Response'); + return false; + } + } else { + const isTokenVerified = await this.authService.verifyCaptchaToken( + req.query?.token, + req.headers['CF-Connecting-IP'] as string + ); + + if (!isTokenVerified) { + this.rejectResponse(res, 'Invalid Captcha Response'); + return false; + } + } + return true; + } + private async verifyUserFromRequest(req: Request): Promise { const token = req.headers.authorization; if (!token) { @@ -311,6 +378,18 @@ export class NextAuthController { } throw new BadRequestException(`User not found`); } + + rejectResponse(res: Response, error: string, status = 400) { + res.status(status); + res.json({ + url: `https://${this.config.baseUrl}/api/auth/error?${new URLSearchParams( + { + error, + } + ).toString()}`, + error, + }); + } } const checkUrlOrigin = (url: string, origin: string) => { diff --git a/apps/server/src/modules/auth/service.ts b/apps/server/src/modules/auth/service.ts index d872cdfad..822d0e525 100644 --- a/apps/server/src/modules/auth/service.ts +++ b/apps/server/src/modules/auth/service.ts @@ -9,9 +9,11 @@ import { import { hash, verify } from '@node-rs/argon2'; import { Algorithm, sign, verify as jwtVerify } from '@node-rs/jsonwebtoken'; import type { User } from '@prisma/client'; +import { nanoid } from 'nanoid'; import { Config } from '../../config'; import { PrismaService } from '../../prisma'; +import { verifyChallengeResponse } from '../../storage'; import { MailService } from './mailer'; export type UserClaim = Pick< @@ -110,6 +112,38 @@ export class AuthService { } } + async verifyCaptchaToken(token: any, ip: string) { + if (typeof token !== 'string' || !token) return false; + + const formData = new FormData(); + formData.append('secret', this.config.auth.captcha.turnstile.secret); + formData.append('response', token); + formData.append('remoteip', ip); + // prevent replay attack + formData.append('idempotency_key', nanoid()); + + const url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'; + const result = await fetch(url, { + body: formData, + method: 'POST', + }); + const outcome = await result.json(); + + return ( + !!outcome.success && + // skip hostname check in dev mode + (this.config.affineEnv === 'dev' || outcome.hostname === this.config.host) + ); + } + + async verifyChallengeResponse(response: any, resource: string) { + return verifyChallengeResponse( + response, + this.config.auth.captcha.challenge.bits, + resource + ); + } + async signIn(email: string, password: string): Promise { const user = await this.prisma.user.findFirst({ where: { diff --git a/apps/server/src/storage/index.ts b/apps/server/src/storage/index.ts index c062662e0..5d7c0bc2a 100644 --- a/apps/server/src/storage/index.ts +++ b/apps/server/src/storage/index.ts @@ -34,3 +34,17 @@ export class StorageModule { } export const mergeUpdatesInApplyWay = storageModule.mergeUpdatesInApplyWay; + +export const verifyChallengeResponse = async ( + response: any, + bits: number, + resource: string +) => { + if (typeof response !== 'string' || !response || !resource) return false; + return storageModule.verifyChallengeResponse(response, bits, resource); +}; + +export const mintChallengeResponse = async (resource: string, bits: number) => { + if (!resource) return null; + return storageModule.mintChallengeResponse(resource, bits); +}; diff --git a/apps/server/tests/auth.spec.ts b/apps/server/tests/auth.spec.ts index 10a6a80d2..fa06c852a 100644 --- a/apps/server/tests/auth.spec.ts +++ b/apps/server/tests/auth.spec.ts @@ -10,6 +10,7 @@ import { AuthModule } from '../src/modules/auth'; import { AuthResolver } from '../src/modules/auth/resolver'; import { AuthService } from '../src/modules/auth/service'; import { PrismaModule } from '../src/prisma'; +import { mintChallengeResponse, verifyChallengeResponse } from '../src/storage'; import { RateLimiterModule } from '../src/throttler'; let authService: AuthService; @@ -176,3 +177,10 @@ test('should return valid sessionToken if request headers valid', async t => { ); t.is(result.sessionToken, '123456'); }); + +test('verify challenge', async t => { + const resource = 'xp8D3rcXV9bMhWrb6abxl'; + const response = await mintChallengeResponse(resource, 20); + const success = await verifyChallengeResponse(response, 20, resource); + t.true(success); +}); diff --git a/apps/storybook/.storybook/main.ts b/apps/storybook/.storybook/main.ts index e99794dec..ee6025fd1 100644 --- a/apps/storybook/.storybook/main.ts +++ b/apps/storybook/.storybook/main.ts @@ -57,6 +57,7 @@ export default { process.env.SHOULD_REPORT_TRACE === 'true' )}`, 'process.env.TRACE_REPORT_ENDPOINT': `"${process.env.TRACE_REPORT_ENDPOINT}"`, + 'process.env.CAPTCHA_SITE_KEY': `"${process.env.CAPTCHA_SITE_KEY}"`, runtimeConfig: getRuntimeConfig({ distribution: 'browser', mode: 'development', diff --git a/packages/env/src/global.ts b/packages/env/src/global.ts index da9364087..a1bf02061 100644 --- a/packages/env/src/global.ts +++ b/packages/env/src/global.ts @@ -28,6 +28,7 @@ export const runtimeFlagsSchema = z.object({ enableSQLiteProvider: z.boolean(), enableNotificationCenter: z.boolean(), enableCloud: z.boolean(), + enableCaptcha: z.boolean(), enableEnhanceShareMode: z.boolean(), // this is for the electron app serverUrlPrefix: z.string(), diff --git a/packages/hooks/package.json b/packages/hooks/package.json index c8f3c38c6..cc6fad19f 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -10,7 +10,7 @@ "jotai": "^2.4.3", "lodash.debounce": "^4.0.8", "react": "18.2.0", - "swr": "2.2.0" + "swr": "2.2.4" }, "devDependencies": { "@affine/env": "workspace:*", diff --git a/packages/infra/src/type.ts b/packages/infra/src/type.ts index d370670a3..f3ac43291 100644 --- a/packages/infra/src/type.ts +++ b/packages/infra/src/type.ts @@ -174,6 +174,7 @@ export type UIHandlers = { handleMaximizeApp: () => Promise; handleCloseApp: () => Promise; getGoogleOauthCode: () => Promise; + getChallengeResponse: (resource: string) => Promise; }; export type ClipboardHandlers = { diff --git a/packages/native/Cargo.toml b/packages/native/Cargo.toml index c0d573ea6..d0e93c329 100644 --- a/packages/native/Cargo.toml +++ b/packages/native/Cargo.toml @@ -21,8 +21,10 @@ napi-derive = "2" notify = { version = "6", features = ["serde"] } once_cell = "1" parking_lot = "0.12" +rand = "0.8" serde = "1" serde_json = "1" +sha3 = "0.10" sqlx = { version = "0.7.1", default-features = false, features = [ "sqlite", "migrate", diff --git a/packages/native/index.d.ts b/packages/native/index.d.ts index d5a71f667..a65cdbf8a 100644 --- a/packages/native/index.d.ts +++ b/packages/native/index.d.ts @@ -25,6 +25,15 @@ export enum ValidationResult { GeneralError = 3, Valid = 4, } +export function verifyChallengeResponse( + response: string, + bits: number, + resource: string +): Promise; +export function mintChallengeResponse( + resource: string, + bits?: number | undefined | null +): Promise; export class SqliteConnection { constructor(path: string); connect(): Promise; diff --git a/packages/native/index.js b/packages/native/index.js index a57f0002f..dabd08f1f 100644 --- a/packages/native/index.js +++ b/packages/native/index.js @@ -263,7 +263,14 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`); } -const { SqliteConnection, ValidationResult } = nativeBinding; +const { + SqliteConnection, + ValidationResult, + verifyChallengeResponse, + mintChallengeResponse, +} = nativeBinding; module.exports.SqliteConnection = SqliteConnection; module.exports.ValidationResult = ValidationResult; +module.exports.verifyChallengeResponse = verifyChallengeResponse; +module.exports.mintChallengeResponse = mintChallengeResponse; diff --git a/packages/native/src/hashcash.rs b/packages/native/src/hashcash.rs new file mode 100644 index 000000000..9ada59950 --- /dev/null +++ b/packages/native/src/hashcash.rs @@ -0,0 +1,225 @@ +use std::convert::TryFrom; + +use chrono::{DateTime, Duration, NaiveDateTime, Utc}; +use napi::{bindgen_prelude::AsyncTask, Env, JsBoolean, JsString, Result as NapiResult, Task}; +use napi_derive::napi; +use rand::{ + distributions::{Alphanumeric, Distribution}, + thread_rng, +}; +use sha3::{Digest, Sha3_256}; + +const SALT_LENGTH: usize = 16; + +#[derive(Debug)] +struct Stamp { + version: String, + claim: u32, + ts: String, + resource: String, + ext: String, + rand: String, + counter: String, +} + +impl Stamp { + fn check_expiration(&self) -> bool { + NaiveDateTime::parse_from_str(&self.ts, "%Y%m%d%H%M%S") + .ok() + .map(|ts| DateTime::::from_naive_utc_and_offset(ts, Utc)) + .and_then(|utc| { + utc + .checked_add_signed(Duration::minutes(5)) + .map(|utc| Utc::now() <= utc) + }) + .unwrap_or(false) + } + + pub fn check>(&self, bits: u32, resource: S) -> bool { + if self.version == "1" + && bits <= self.claim + && self.check_expiration() + && self.resource == resource.as_ref() + { + let hex_digits = ((self.claim as f32) / 4.).floor() as usize; + + // check challenge + let mut hasher = Sha3_256::new(); + hasher.update(&self.format().as_bytes()); + let result = format!("{:x}", hasher.finalize()); + result[..hex_digits] == String::from_utf8(vec![b'0'; hex_digits]).unwrap() + } else { + false + } + } + + fn format(&self) -> String { + format!( + "{}:{}:{}:{}:{}:{}:{}", + self.version, self.claim, self.ts, self.resource, self.ext, self.rand, self.counter + ) + } + + /// Mint a new hashcash stamp. + pub fn mint(resource: String, bits: Option) -> Self { + let version = "1"; + let now = Utc::now(); + let ts = now.format("%Y%m%d%H%M%S"); + let bits = bits.unwrap_or(20); + let rand = String::from_iter( + Alphanumeric + .sample_iter(thread_rng()) + .take(SALT_LENGTH) + .map(char::from), + ); + let challenge = format!("{}:{}:{}:{}:{}:{}", version, bits, ts, &resource, "", rand); + + Stamp { + version: version.to_string(), + claim: bits, + ts: ts.to_string(), + resource, + ext: "".to_string(), + rand, + counter: { + let mut hasher = Sha3_256::new(); + let mut counter = 0; + let hex_digits = ((bits as f32) / 4.).ceil() as usize; + let zeros = String::from_utf8(vec![b'0'; hex_digits]).unwrap(); + loop { + hasher.update(&format!("{}:{:x}", challenge, counter).as_bytes()); + let result = format!("{:x}", hasher.finalize_reset()); + if result[..hex_digits] == zeros { + break format!("{:x}", counter); + }; + counter += 1 + } + }, + } + } +} + +impl TryFrom<&str> for Stamp { + type Error = String; + + fn try_from(value: &str) -> Result { + let stamp_vec = value.split(':').collect::>(); + if stamp_vec.len() != 7 { + return Err(format!( + "Malformed stamp, expected 6 parts, got {}", + stamp_vec.len() + )); + } + Ok(Stamp { + version: stamp_vec[0].to_string(), + claim: stamp_vec[1] + .parse() + .map_err(|_| "Malformed stamp".to_string())?, + ts: stamp_vec[2].to_string(), + resource: stamp_vec[3].to_string(), + ext: stamp_vec[4].to_string(), + rand: stamp_vec[5].to_string(), + counter: stamp_vec[6].to_string(), + }) + } +} + +pub struct AsyncVerifyChallengeResponse { + response: String, + bits: u32, + resource: String, +} + +#[napi] +impl Task for AsyncVerifyChallengeResponse { + type Output = bool; + type JsValue = JsBoolean; + + fn compute(&mut self) -> NapiResult { + Ok(if let Ok(stamp) = Stamp::try_from(self.response.as_str()) { + stamp.check(self.bits, &self.resource) + } else { + false + }) + } + + fn resolve(&mut self, env: Env, output: bool) -> NapiResult { + env.get_boolean(output) + } +} + +#[napi] +pub fn verify_challenge_response( + response: String, + bits: u32, + resource: String, +) -> AsyncTask { + AsyncTask::new(AsyncVerifyChallengeResponse { + response, + bits, + resource, + }) +} + +pub struct AsyncMintChallengeResponse { + bits: Option, + resource: String, +} + +#[napi] +impl Task for AsyncMintChallengeResponse { + type Output = String; + type JsValue = JsString; + + fn compute(&mut self) -> NapiResult { + Ok(Stamp::mint(self.resource.clone(), self.bits).format()) + } + + fn resolve(&mut self, env: Env, output: String) -> NapiResult { + env.create_string(&output) + } +} + +#[napi] +pub fn mint_challenge_response( + resource: String, + bits: Option, +) -> AsyncTask { + AsyncTask::new(AsyncMintChallengeResponse { bits, resource }) +} + +#[cfg(test)] +mod tests { + use super::Stamp; + + #[test] + fn test_mint() { + let response = Stamp::mint("test".into(), Some(22)).format(); + assert!(Stamp::try_from(response.as_str()) + .unwrap() + .check(22, "test")); + } + + #[test] + fn test_check() { + assert!(Stamp::try_from("1:20:20202116:test::Z4p8WaiO:31c14") + .unwrap() + .check(20, "test")); + assert!(!Stamp::try_from("1:20:20202116:test1::Z4p8WaiO:31c14") + .unwrap() + .check(20, "test")); + assert!(!Stamp::try_from("1:20:20202116:test::z4p8WaiO:31c14") + .unwrap() + .check(20, "test")); + assert!(!Stamp::try_from("1:20:20202116:test::Z4p8WaiO:31C14") + .unwrap() + .check(20, "test")); + assert!(Stamp::try_from("0:20:20202116:test::Z4p8WaiO:31c14").is_err()); + assert!(!Stamp::try_from("1:19:20202116:test::Z4p8WaiO:31c14") + .unwrap() + .check(20, "test")); + assert!(!Stamp::try_from("1:20:20202115:test::Z4p8WaiO:31c14") + .unwrap() + .check(20, "test")); + } +} diff --git a/packages/native/src/lib.rs b/packages/native/src/lib.rs index 6b1c1083e..ef92a6727 100644 --- a/packages/native/src/lib.rs +++ b/packages/native/src/lib.rs @@ -1 +1,2 @@ pub mod sqlite; +pub mod hashcash; \ No newline at end of file diff --git a/packages/storage/Cargo.toml b/packages/storage/Cargo.toml index f660a8c61..6b5c685e3 100644 --- a/packages/storage/Cargo.toml +++ b/packages/storage/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] +chrono = "0.4" jwst-codec = { git = "https://github.com/toeverything/OctoBase.git", rev = "ad51b2c" } jwst-core = { git = "https://github.com/toeverything/OctoBase.git", rev = "ad51b2c" } jwst-storage = { git = "https://github.com/toeverything/OctoBase.git", rev = "ad51b2c" } @@ -15,6 +16,11 @@ napi = { version = "2", default-features = false, features = [ "async", ] } napi-derive = { version = "2", features = ["type-def"] } +rand = "0.8" +sha3 = "0.10" + +[dev-dependencies] +tokio = "1" [build-dependencies] napi-build = "2" diff --git a/packages/storage/index.d.ts b/packages/storage/index.d.ts index 636452036..a2c61f106 100644 --- a/packages/storage/index.d.ts +++ b/packages/storage/index.d.ts @@ -3,6 +3,15 @@ /* auto-generated by NAPI-RS */ +export function verifyChallengeResponse( + response: string, + bits: number, + resource: string +): Promise; +export function mintChallengeResponse( + resource: string, + bits?: number | undefined | null +): Promise; export interface Blob { contentType: string; lastModified: string; diff --git a/packages/storage/index.js b/packages/storage/index.js index 900771cb7..8dd0c023c 100644 --- a/packages/storage/index.js +++ b/packages/storage/index.js @@ -7,3 +7,5 @@ const binding = require('./storage.node'); export const Storage = binding.Storage; export const mergeUpdatesInApplyWay = binding.mergeUpdatesInApplyWay; +export const verifyChallengeResponse = binding.verifyChallengeResponse; +export const mintChallengeResponse = binding.mintChallengeResponse; diff --git a/packages/storage/src/hashcash.rs b/packages/storage/src/hashcash.rs new file mode 120000 index 000000000..c791528bb --- /dev/null +++ b/packages/storage/src/hashcash.rs @@ -0,0 +1 @@ +../../native/src/hashcash.rs \ No newline at end of file diff --git a/packages/storage/src/lib.rs b/packages/storage/src/lib.rs index 63965e78c..229cbde78 100644 --- a/packages/storage/src/lib.rs +++ b/packages/storage/src/lib.rs @@ -1,5 +1,7 @@ #![deny(clippy::all)] +pub mod hashcash; + use std::{ collections::HashMap, fmt::{Debug, Display}, diff --git a/packages/workspace/package.json b/packages/workspace/package.json index 7f0902b8d..dcc5eafe8 100644 --- a/packages/workspace/package.json +++ b/packages/workspace/package.json @@ -32,7 +32,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "socket.io-client": "^4.7.2", - "swr": "2.2.0", + "swr": "2.2.4", "valtio": "^1.11.2", "y-protocols": "^1.0.6", "y-provider": "workspace:*", diff --git a/plugins/image-preview/package.json b/plugins/image-preview/package.json index d3473f090..46107634f 100644 --- a/plugins/image-preview/package.json +++ b/plugins/image-preview/package.json @@ -22,7 +22,7 @@ "clsx": "^2.0.0", "foxact": "^0.2.20", "react-error-boundary": "^4.0.11", - "swr": "2.2.0" + "swr": "2.2.4" }, "devDependencies": { "@affine/plugin-cli": "workspace:*" diff --git a/yarn.lock b/yarn.lock index 80e696805..6f22e712e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -317,6 +317,7 @@ __metadata: "@emotion/react": ^11.11.1 "@emotion/server": ^11.11.0 "@emotion/styled": ^11.11.0 + "@marsidev/react-turnstile": ^0.3.1 "@mui/material": ^5.14.13 "@perfsee/webpack": ^1.8.4 "@pmmmwh/react-refresh-webpack-plugin": ^0.5.11 @@ -359,7 +360,7 @@ __metadata: style-loader: ^3.3.3 swc-loader: ^0.2.3 swc-plugin-coverage-instrument: ^0.0.20 - swr: 2.2.0 + swr: 2.2.4 thread-loader: ^4.0.2 valtio: ^1.11.2 webpack: ^5.89.0 @@ -515,7 +516,7 @@ __metadata: clsx: ^2.0.0 foxact: ^0.2.20 react-error-boundary: ^4.0.11 - swr: 2.2.0 + swr: 2.2.4 languageName: unknown linkType: soft @@ -857,7 +858,7 @@ __metadata: react: 18.2.0 react-dom: 18.2.0 socket.io-client: ^4.7.2 - swr: 2.2.0 + swr: 2.2.4 valtio: ^1.11.2 vitest: 0.34.6 ws: ^8.14.2 @@ -893,8 +894,8 @@ __metadata: linkType: hard "@anthropic-ai/sdk@npm:^0.6.2": - version: 0.6.2 - resolution: "@anthropic-ai/sdk@npm:0.6.2" + version: 0.6.7 + resolution: "@anthropic-ai/sdk@npm:0.6.7" dependencies: "@types/node": ^18.11.18 "@types/node-fetch": ^2.6.4 @@ -904,7 +905,8 @@ __metadata: form-data-encoder: 1.7.2 formdata-node: ^4.3.2 node-fetch: ^2.6.7 - checksum: a07dd0d42fe83b79bec506399755161cb12d26df756093df7f6189d062d01bd944a4d909d9d13b178567e7778b8966fe6f4b7051b9397cbd035c3fc184289c36 + web-streams-polyfill: ^3.2.1 + checksum: 68eaf8fca73c15f40e509bde28d3c617dac58219c323defe8217b9bdbdc846460d573d94699879399e37542663cab0e466c29e9dd9b529b457aadb76bc99f922 languageName: node linkType: hard @@ -1168,9 +1170,9 @@ __metadata: languageName: node linkType: hard -"@auth/core@npm:0.16.1": - version: 0.16.1 - resolution: "@auth/core@npm:0.16.1" +"@auth/core@npm:0.17.0": + version: 0.17.0 + resolution: "@auth/core@npm:0.17.0" dependencies: "@panva/hkdf": ^1.0.4 cookie: 0.5.0 @@ -1183,18 +1185,18 @@ __metadata: peerDependenciesMeta: nodemailer: optional: true - checksum: 1bb938fcafb921b511f47c966a94f86de70010be77a196d0db55c7af59c483b81628e29db6b6c6deaa711c7afeae77a56da2e9c640b95a85d959acbdbe7dbb8f + checksum: a0fdd3085df11f1d898260ded218605c1172fd8014cb7e837dbde4c7c6892a8015ac15ce04eac3f2e685bf35d97a4eae0a5aac367439b20c1a336b1a0c276e09 languageName: node linkType: hard "@auth/prisma-adapter@npm:^1.0.3": - version: 1.0.3 - resolution: "@auth/prisma-adapter@npm:1.0.3" + version: 1.0.4 + resolution: "@auth/prisma-adapter@npm:1.0.4" dependencies: - "@auth/core": 0.16.1 + "@auth/core": 0.17.0 peerDependencies: "@prisma/client": ">=2.26.0 || >=3 || >=4 || >=5" - checksum: a7629062752b1fc25dfef30721a93660c811739372056ffc526a6e5a040b83680a57f7678843351dde9c016b7066f750141381181b9fad728f71a5fd32c83746 + checksum: 40618d38ef9d396f15c794f804d6ad8bbc435604ddcdae9abe0d591e4e0b29f42d09ecf0e202621129c5878d94654d7e1c9fd81c8dcd2aa633b1b799ae18b272 languageName: node linkType: hard @@ -1302,7 +1304,7 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/client-s3@npm:3.428.0, @aws-sdk/client-s3@npm:^3.428.0": +"@aws-sdk/client-s3@npm:3.428.0": version: 3.428.0 resolution: "@aws-sdk/client-s3@npm:3.428.0" dependencies: @@ -1365,6 +1367,69 @@ __metadata: languageName: node linkType: hard +"@aws-sdk/client-s3@npm:^3.428.0": + version: 3.429.0 + resolution: "@aws-sdk/client-s3@npm:3.429.0" + dependencies: + "@aws-crypto/sha1-browser": 3.0.0 + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/client-sts": 3.429.0 + "@aws-sdk/credential-provider-node": 3.429.0 + "@aws-sdk/middleware-bucket-endpoint": 3.428.0 + "@aws-sdk/middleware-expect-continue": 3.428.0 + "@aws-sdk/middleware-flexible-checksums": 3.428.0 + "@aws-sdk/middleware-host-header": 3.429.0 + "@aws-sdk/middleware-location-constraint": 3.428.0 + "@aws-sdk/middleware-logger": 3.428.0 + "@aws-sdk/middleware-recursion-detection": 3.428.0 + "@aws-sdk/middleware-sdk-s3": 3.429.0 + "@aws-sdk/middleware-signing": 3.428.0 + "@aws-sdk/middleware-ssec": 3.428.0 + "@aws-sdk/middleware-user-agent": 3.428.0 + "@aws-sdk/region-config-resolver": 3.428.0 + "@aws-sdk/signature-v4-multi-region": 3.428.0 + "@aws-sdk/types": 3.428.0 + "@aws-sdk/util-endpoints": 3.428.0 + "@aws-sdk/util-user-agent-browser": 3.428.0 + "@aws-sdk/util-user-agent-node": 3.428.0 + "@aws-sdk/xml-builder": 3.310.0 + "@smithy/config-resolver": ^2.0.14 + "@smithy/eventstream-serde-browser": ^2.0.11 + "@smithy/eventstream-serde-config-resolver": ^2.0.11 + "@smithy/eventstream-serde-node": ^2.0.11 + "@smithy/fetch-http-handler": ^2.2.3 + "@smithy/hash-blob-browser": ^2.0.11 + "@smithy/hash-node": ^2.0.11 + "@smithy/hash-stream-node": ^2.0.11 + "@smithy/invalid-dependency": ^2.0.11 + "@smithy/md5-js": ^2.0.11 + "@smithy/middleware-content-length": ^2.0.13 + "@smithy/middleware-endpoint": ^2.1.1 + "@smithy/middleware-retry": ^2.0.16 + "@smithy/middleware-serde": ^2.0.11 + "@smithy/middleware-stack": ^2.0.5 + "@smithy/node-config-provider": ^2.1.1 + "@smithy/node-http-handler": ^2.1.7 + "@smithy/protocol-http": ^3.0.7 + "@smithy/smithy-client": ^2.1.11 + "@smithy/types": ^2.3.5 + "@smithy/url-parser": ^2.0.11 + "@smithy/util-base64": ^2.0.0 + "@smithy/util-body-length-browser": ^2.0.0 + "@smithy/util-body-length-node": ^2.1.0 + "@smithy/util-defaults-mode-browser": ^2.0.15 + "@smithy/util-defaults-mode-node": ^2.0.19 + "@smithy/util-retry": ^2.0.4 + "@smithy/util-stream": ^2.0.16 + "@smithy/util-utf8": ^2.0.0 + "@smithy/util-waiter": ^2.0.11 + fast-xml-parser: 4.2.5 + tslib: ^2.5.0 + checksum: d4f42cbb173a4a306167fb5aab623aef73489c98008482288f9e659bf902d84d04dac17938111bbc14a5918897d6868acfce39c5fc49074813c3e3329bfe765d + languageName: node + linkType: hard + "@aws-sdk/client-sso@npm:3.428.0": version: 3.428.0 resolution: "@aws-sdk/client-sso@npm:3.428.0" @@ -1407,6 +1472,48 @@ __metadata: languageName: node linkType: hard +"@aws-sdk/client-sso@npm:3.429.0": + version: 3.429.0 + resolution: "@aws-sdk/client-sso@npm:3.429.0" + dependencies: + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/middleware-host-header": 3.429.0 + "@aws-sdk/middleware-logger": 3.428.0 + "@aws-sdk/middleware-recursion-detection": 3.428.0 + "@aws-sdk/middleware-user-agent": 3.428.0 + "@aws-sdk/region-config-resolver": 3.428.0 + "@aws-sdk/types": 3.428.0 + "@aws-sdk/util-endpoints": 3.428.0 + "@aws-sdk/util-user-agent-browser": 3.428.0 + "@aws-sdk/util-user-agent-node": 3.428.0 + "@smithy/config-resolver": ^2.0.14 + "@smithy/fetch-http-handler": ^2.2.3 + "@smithy/hash-node": ^2.0.11 + "@smithy/invalid-dependency": ^2.0.11 + "@smithy/middleware-content-length": ^2.0.13 + "@smithy/middleware-endpoint": ^2.1.1 + "@smithy/middleware-retry": ^2.0.16 + "@smithy/middleware-serde": ^2.0.11 + "@smithy/middleware-stack": ^2.0.5 + "@smithy/node-config-provider": ^2.1.1 + "@smithy/node-http-handler": ^2.1.7 + "@smithy/protocol-http": ^3.0.7 + "@smithy/smithy-client": ^2.1.11 + "@smithy/types": ^2.3.5 + "@smithy/url-parser": ^2.0.11 + "@smithy/util-base64": ^2.0.0 + "@smithy/util-body-length-browser": ^2.0.0 + "@smithy/util-body-length-node": ^2.1.0 + "@smithy/util-defaults-mode-browser": ^2.0.15 + "@smithy/util-defaults-mode-node": ^2.0.19 + "@smithy/util-retry": ^2.0.4 + "@smithy/util-utf8": ^2.0.0 + tslib: ^2.5.0 + checksum: bcfd26dafb11cf4d513c72fe2bb86df3606692d912d663376c385ced2c171d60127b1b15fddb3b69b24df4bc052f4484be81f83a7545387fa7123681d6a4c443 + languageName: node + linkType: hard + "@aws-sdk/client-sts@npm:3.428.0": version: 3.428.0 resolution: "@aws-sdk/client-sts@npm:3.428.0" @@ -1453,6 +1560,52 @@ __metadata: languageName: node linkType: hard +"@aws-sdk/client-sts@npm:3.429.0": + version: 3.429.0 + resolution: "@aws-sdk/client-sts@npm:3.429.0" + dependencies: + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/credential-provider-node": 3.429.0 + "@aws-sdk/middleware-host-header": 3.429.0 + "@aws-sdk/middleware-logger": 3.428.0 + "@aws-sdk/middleware-recursion-detection": 3.428.0 + "@aws-sdk/middleware-sdk-sts": 3.428.0 + "@aws-sdk/middleware-signing": 3.428.0 + "@aws-sdk/middleware-user-agent": 3.428.0 + "@aws-sdk/region-config-resolver": 3.428.0 + "@aws-sdk/types": 3.428.0 + "@aws-sdk/util-endpoints": 3.428.0 + "@aws-sdk/util-user-agent-browser": 3.428.0 + "@aws-sdk/util-user-agent-node": 3.428.0 + "@smithy/config-resolver": ^2.0.14 + "@smithy/fetch-http-handler": ^2.2.3 + "@smithy/hash-node": ^2.0.11 + "@smithy/invalid-dependency": ^2.0.11 + "@smithy/middleware-content-length": ^2.0.13 + "@smithy/middleware-endpoint": ^2.1.1 + "@smithy/middleware-retry": ^2.0.16 + "@smithy/middleware-serde": ^2.0.11 + "@smithy/middleware-stack": ^2.0.5 + "@smithy/node-config-provider": ^2.1.1 + "@smithy/node-http-handler": ^2.1.7 + "@smithy/protocol-http": ^3.0.7 + "@smithy/smithy-client": ^2.1.11 + "@smithy/types": ^2.3.5 + "@smithy/url-parser": ^2.0.11 + "@smithy/util-base64": ^2.0.0 + "@smithy/util-body-length-browser": ^2.0.0 + "@smithy/util-body-length-node": ^2.1.0 + "@smithy/util-defaults-mode-browser": ^2.0.15 + "@smithy/util-defaults-mode-node": ^2.0.19 + "@smithy/util-retry": ^2.0.4 + "@smithy/util-utf8": ^2.0.0 + fast-xml-parser: 4.2.5 + tslib: ^2.5.0 + checksum: f9ef73f13a14a2ed8713226e70c013557f4c531bfbac3d92849f14a37690088997c0e47242ba39367183d0ef7caf2606c3e8adc6b2dfa4e1d9a3eecb5d6ce881 + languageName: node + linkType: hard + "@aws-sdk/credential-provider-env@npm:3.428.0": version: 3.428.0 resolution: "@aws-sdk/credential-provider-env@npm:3.428.0" @@ -1483,6 +1636,24 @@ __metadata: languageName: node linkType: hard +"@aws-sdk/credential-provider-ini@npm:3.429.0": + version: 3.429.0 + resolution: "@aws-sdk/credential-provider-ini@npm:3.429.0" + dependencies: + "@aws-sdk/credential-provider-env": 3.428.0 + "@aws-sdk/credential-provider-process": 3.428.0 + "@aws-sdk/credential-provider-sso": 3.429.0 + "@aws-sdk/credential-provider-web-identity": 3.428.0 + "@aws-sdk/types": 3.428.0 + "@smithy/credential-provider-imds": ^2.0.0 + "@smithy/property-provider": ^2.0.0 + "@smithy/shared-ini-file-loader": ^2.0.6 + "@smithy/types": ^2.3.5 + tslib: ^2.5.0 + checksum: febd40c428e969b843b70a5cf34ac4a92e1d4172aa47804b6ca1f1218a3298e7d8c2db1613a274fa3d6aaa400876bff55d62599a7b8bb52aa366bd9d9cbd1192 + languageName: node + linkType: hard + "@aws-sdk/credential-provider-node@npm:3.428.0": version: 3.428.0 resolution: "@aws-sdk/credential-provider-node@npm:3.428.0" @@ -1502,6 +1673,25 @@ __metadata: languageName: node linkType: hard +"@aws-sdk/credential-provider-node@npm:3.429.0": + version: 3.429.0 + resolution: "@aws-sdk/credential-provider-node@npm:3.429.0" + dependencies: + "@aws-sdk/credential-provider-env": 3.428.0 + "@aws-sdk/credential-provider-ini": 3.429.0 + "@aws-sdk/credential-provider-process": 3.428.0 + "@aws-sdk/credential-provider-sso": 3.429.0 + "@aws-sdk/credential-provider-web-identity": 3.428.0 + "@aws-sdk/types": 3.428.0 + "@smithy/credential-provider-imds": ^2.0.0 + "@smithy/property-provider": ^2.0.0 + "@smithy/shared-ini-file-loader": ^2.0.6 + "@smithy/types": ^2.3.5 + tslib: ^2.5.0 + checksum: 672a00b515238e78485a87b0ae383d264b634ae563d34d51a0a12d4976b5f450f5124b524d7f54bd8cb7739e55654dc10e4983fc98c2704bd5adf63a1ce7bfda + languageName: node + linkType: hard + "@aws-sdk/credential-provider-process@npm:3.428.0": version: 3.428.0 resolution: "@aws-sdk/credential-provider-process@npm:3.428.0" @@ -1530,6 +1720,21 @@ __metadata: languageName: node linkType: hard +"@aws-sdk/credential-provider-sso@npm:3.429.0": + version: 3.429.0 + resolution: "@aws-sdk/credential-provider-sso@npm:3.429.0" + dependencies: + "@aws-sdk/client-sso": 3.429.0 + "@aws-sdk/token-providers": 3.429.0 + "@aws-sdk/types": 3.428.0 + "@smithy/property-provider": ^2.0.0 + "@smithy/shared-ini-file-loader": ^2.0.6 + "@smithy/types": ^2.3.5 + tslib: ^2.5.0 + checksum: 3cdcc47ae0980e7d345d8303df390be79f06f90a69c596dbc01bf1a1d1a06b9a2b20f98ccedc757689a9a45b42bed262ed7132d141b0b43393554ef8e395d368 + languageName: node + linkType: hard + "@aws-sdk/credential-provider-web-identity@npm:3.428.0": version: 3.428.0 resolution: "@aws-sdk/credential-provider-web-identity@npm:3.428.0" @@ -1597,6 +1802,18 @@ __metadata: languageName: node linkType: hard +"@aws-sdk/middleware-host-header@npm:3.429.0": + version: 3.429.0 + resolution: "@aws-sdk/middleware-host-header@npm:3.429.0" + dependencies: + "@aws-sdk/types": 3.428.0 + "@smithy/protocol-http": ^3.0.7 + "@smithy/types": ^2.3.5 + tslib: ^2.5.0 + checksum: fbde219edd7ea73f6590f8c56aad9249c1c03b86fddcd8ff7d60ae574402810eae2abd56598b076fb5c1c3f95ea0606f658d3a47bc1d86940c5b8ae51dcefae2 + languageName: node + linkType: hard + "@aws-sdk/middleware-location-constraint@npm:3.428.0": version: 3.428.0 resolution: "@aws-sdk/middleware-location-constraint@npm:3.428.0" @@ -1645,6 +1862,20 @@ __metadata: languageName: node linkType: hard +"@aws-sdk/middleware-sdk-s3@npm:3.429.0": + version: 3.429.0 + resolution: "@aws-sdk/middleware-sdk-s3@npm:3.429.0" + dependencies: + "@aws-sdk/types": 3.428.0 + "@aws-sdk/util-arn-parser": 3.310.0 + "@smithy/protocol-http": ^3.0.7 + "@smithy/smithy-client": ^2.1.11 + "@smithy/types": ^2.3.5 + tslib: ^2.5.0 + checksum: 10dc36ee7ad34de1ba4f765d4fc0d16282c9a676fc632054f99091d79bc76ea1cb919df4e4304e897a3995d8f36a3ba743d0561a4d25894f7679c72bef3bc9f8 + languageName: node + linkType: hard + "@aws-sdk/middleware-sdk-sts@npm:3.428.0": version: 3.428.0 resolution: "@aws-sdk/middleware-sdk-sts@npm:3.428.0" @@ -1765,6 +1996,49 @@ __metadata: languageName: node linkType: hard +"@aws-sdk/token-providers@npm:3.429.0": + version: 3.429.0 + resolution: "@aws-sdk/token-providers@npm:3.429.0" + dependencies: + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/middleware-host-header": 3.429.0 + "@aws-sdk/middleware-logger": 3.428.0 + "@aws-sdk/middleware-recursion-detection": 3.428.0 + "@aws-sdk/middleware-user-agent": 3.428.0 + "@aws-sdk/types": 3.428.0 + "@aws-sdk/util-endpoints": 3.428.0 + "@aws-sdk/util-user-agent-browser": 3.428.0 + "@aws-sdk/util-user-agent-node": 3.428.0 + "@smithy/config-resolver": ^2.0.14 + "@smithy/fetch-http-handler": ^2.2.3 + "@smithy/hash-node": ^2.0.11 + "@smithy/invalid-dependency": ^2.0.11 + "@smithy/middleware-content-length": ^2.0.13 + "@smithy/middleware-endpoint": ^2.1.1 + "@smithy/middleware-retry": ^2.0.16 + "@smithy/middleware-serde": ^2.0.11 + "@smithy/middleware-stack": ^2.0.5 + "@smithy/node-config-provider": ^2.1.1 + "@smithy/node-http-handler": ^2.1.7 + "@smithy/property-provider": ^2.0.0 + "@smithy/protocol-http": ^3.0.7 + "@smithy/shared-ini-file-loader": ^2.0.6 + "@smithy/smithy-client": ^2.1.11 + "@smithy/types": ^2.3.5 + "@smithy/url-parser": ^2.0.11 + "@smithy/util-base64": ^2.0.0 + "@smithy/util-body-length-browser": ^2.0.0 + "@smithy/util-body-length-node": ^2.1.0 + "@smithy/util-defaults-mode-browser": ^2.0.15 + "@smithy/util-defaults-mode-node": ^2.0.19 + "@smithy/util-retry": ^2.0.4 + "@smithy/util-utf8": ^2.0.0 + tslib: ^2.5.0 + checksum: 3fd3c2f6e211b169d9d60076f1ad7c95e86ddd907be183c707c09be240254633821e38490fc74ff0832d9befeb37753e12da4a11e8d6dec39f5889b7afe02bd3 + languageName: node + linkType: hard + "@aws-sdk/types@npm:3.428.0, @aws-sdk/types@npm:^3.222.0": version: 3.428.0 resolution: "@aws-sdk/types@npm:3.428.0" @@ -4559,9 +4833,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/android-arm64@npm:0.19.4" +"@esbuild/android-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/android-arm64@npm:0.19.5" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -4587,9 +4861,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/android-arm@npm:0.19.4" +"@esbuild/android-arm@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/android-arm@npm:0.19.5" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -4615,9 +4889,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/android-x64@npm:0.19.4" +"@esbuild/android-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/android-x64@npm:0.19.5" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -4643,9 +4917,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/darwin-arm64@npm:0.19.4" +"@esbuild/darwin-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/darwin-arm64@npm:0.19.5" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -4671,9 +4945,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/darwin-x64@npm:0.19.4" +"@esbuild/darwin-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/darwin-x64@npm:0.19.5" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -4699,9 +4973,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/freebsd-arm64@npm:0.19.4" +"@esbuild/freebsd-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/freebsd-arm64@npm:0.19.5" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -4727,9 +5001,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/freebsd-x64@npm:0.19.4" +"@esbuild/freebsd-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/freebsd-x64@npm:0.19.5" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -4755,9 +5029,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/linux-arm64@npm:0.19.4" +"@esbuild/linux-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-arm64@npm:0.19.5" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -4783,9 +5057,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/linux-arm@npm:0.19.4" +"@esbuild/linux-arm@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-arm@npm:0.19.5" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -4811,9 +5085,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/linux-ia32@npm:0.19.4" +"@esbuild/linux-ia32@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-ia32@npm:0.19.5" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -4839,9 +5113,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/linux-loong64@npm:0.19.4" +"@esbuild/linux-loong64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-loong64@npm:0.19.5" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -4867,9 +5141,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/linux-mips64el@npm:0.19.4" +"@esbuild/linux-mips64el@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-mips64el@npm:0.19.5" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -4895,9 +5169,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/linux-ppc64@npm:0.19.4" +"@esbuild/linux-ppc64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-ppc64@npm:0.19.5" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -4923,9 +5197,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/linux-riscv64@npm:0.19.4" +"@esbuild/linux-riscv64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-riscv64@npm:0.19.5" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -4951,9 +5225,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/linux-s390x@npm:0.19.4" +"@esbuild/linux-s390x@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-s390x@npm:0.19.5" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -4979,9 +5253,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/linux-x64@npm:0.19.4" +"@esbuild/linux-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-x64@npm:0.19.5" conditions: os=linux & cpu=x64 languageName: node linkType: hard @@ -5007,9 +5281,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/netbsd-x64@npm:0.19.4" +"@esbuild/netbsd-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/netbsd-x64@npm:0.19.5" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard @@ -5035,9 +5309,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/openbsd-x64@npm:0.19.4" +"@esbuild/openbsd-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/openbsd-x64@npm:0.19.5" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -5063,9 +5337,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/sunos-x64@npm:0.19.4" +"@esbuild/sunos-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/sunos-x64@npm:0.19.5" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -5091,9 +5365,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/win32-arm64@npm:0.19.4" +"@esbuild/win32-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/win32-arm64@npm:0.19.5" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -5119,9 +5393,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/win32-ia32@npm:0.19.4" +"@esbuild/win32-ia32@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/win32-ia32@npm:0.19.5" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -5147,9 +5421,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.19.4": - version: 0.19.4 - resolution: "@esbuild/win32-x64@npm:0.19.4" +"@esbuild/win32-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/win32-x64@npm:0.19.5" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -6603,6 +6877,16 @@ __metadata: languageName: node linkType: hard +"@marsidev/react-turnstile@npm:^0.3.1": + version: 0.3.1 + resolution: "@marsidev/react-turnstile@npm:0.3.1" + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: 4dee0e16ea3fee42fc3e303b51f4afc539ec4decea561b07b6805b7d82738153cb7bf264ff5c991c10efec1acf9873d74947127722f8bcc3dfe2371b6b7764fb + languageName: node + linkType: hard + "@mdx-js/react@npm:^2.1.5": version: 2.3.0 resolution: "@mdx-js/react@npm:2.3.0" @@ -10096,10 +10380,10 @@ __metadata: languageName: node linkType: hard -"@remix-run/router@npm:1.9.0": - version: 1.9.0 - resolution: "@remix-run/router@npm:1.9.0" - checksum: 0537b0ff29879ac85077cb4c42eaca4a295b9efd71477848984c2f2dfa5741c9b83d3106a7bb72994a51a9adfeeab3b0f5a40f2dee8be3f0750feeeca2a6d513 +"@remix-run/router@npm:1.10.0": + version: 1.10.0 + resolution: "@remix-run/router@npm:1.10.0" + checksum: f8f9fcd5f08465a7e0a05378398ff6df2c5c5ef5766df3490a134d64260b3b16f1bd490bb0c3f5925c2671a0c1d8d1fa01dfbdc7ecc3b2447dc6eafe6b73bcc2 languageName: node linkType: hard @@ -10414,29 +10698,29 @@ __metadata: languageName: node linkType: hard -"@smithy/config-resolver@npm:^2.0.14": - version: 2.0.14 - resolution: "@smithy/config-resolver@npm:2.0.14" +"@smithy/config-resolver@npm:^2.0.14, @smithy/config-resolver@npm:^2.0.15": + version: 2.0.15 + resolution: "@smithy/config-resolver@npm:2.0.15" dependencies: - "@smithy/node-config-provider": ^2.1.1 + "@smithy/node-config-provider": ^2.1.2 "@smithy/types": ^2.3.5 "@smithy/util-config-provider": ^2.0.0 "@smithy/util-middleware": ^2.0.4 tslib: ^2.5.0 - checksum: 5fa08a715e20b49db178b22806d79cb43756b7f720007abb018ccf975270529869153ea25b98b99da3ffc80607c19a65ceb147fe908e80301eb51288802ea7b7 + checksum: f8ac61db1a388054fd859bc01e0276b5ba8f9291b4f99ff97e7d86bc276f35100fc76516af6e967fd3a002085f018f4c1167d83cecdd547cd9775ea52c69b08f languageName: node linkType: hard -"@smithy/credential-provider-imds@npm:^2.0.0, @smithy/credential-provider-imds@npm:^2.0.16": - version: 2.0.16 - resolution: "@smithy/credential-provider-imds@npm:2.0.16" +"@smithy/credential-provider-imds@npm:^2.0.0, @smithy/credential-provider-imds@npm:^2.0.17": + version: 2.0.17 + resolution: "@smithy/credential-provider-imds@npm:2.0.17" dependencies: - "@smithy/node-config-provider": ^2.1.1 + "@smithy/node-config-provider": ^2.1.2 "@smithy/property-provider": ^2.0.12 "@smithy/types": ^2.3.5 "@smithy/url-parser": ^2.0.11 tslib: ^2.5.0 - checksum: 1079f9b59d60f460bfbc95c722a740664733b5d6c219ff8ac04d85d8af78eccabc71ed08d39cf11ec1e80203e3b65e08eb06a99524c358b2a959e2baa4787fd4 + checksum: 726a2161cfe7c23491b778a1c62861838dc705f59b93a5feb0f414994fd15daf1fee9114618750e2cc6044d3223939eb16755c65c54efb99062729d2ded60d57 languageName: node linkType: hard @@ -10584,26 +10868,26 @@ __metadata: languageName: node linkType: hard -"@smithy/middleware-endpoint@npm:^2.1.0": - version: 2.1.1 - resolution: "@smithy/middleware-endpoint@npm:2.1.1" +"@smithy/middleware-endpoint@npm:^2.1.0, @smithy/middleware-endpoint@npm:^2.1.1": + version: 2.1.2 + resolution: "@smithy/middleware-endpoint@npm:2.1.2" dependencies: "@smithy/middleware-serde": ^2.0.11 - "@smithy/node-config-provider": ^2.1.1 - "@smithy/shared-ini-file-loader": ^2.2.0 + "@smithy/node-config-provider": ^2.1.2 + "@smithy/shared-ini-file-loader": ^2.2.1 "@smithy/types": ^2.3.5 "@smithy/url-parser": ^2.0.11 "@smithy/util-middleware": ^2.0.4 tslib: ^2.5.0 - checksum: 3f159f9cd9112fba16303eeb0c434e4d97e554bdb55f7b702564c92f3399c3c839617bbf5548b74f3a2526e8f321ee4f87231c2fff4dba465bfe2134fafe48fd + checksum: e55349f25feeb16f23ef5873c3d3ba9f062dbadf82ffdbc3ceb5b1bb19f9a6901a0ef665cae935fffd9f33b50d9c0f52f8a6a1a74eee6d3a131149a75faa492b languageName: node linkType: hard "@smithy/middleware-retry@npm:^2.0.16": - version: 2.0.16 - resolution: "@smithy/middleware-retry@npm:2.0.16" + version: 2.0.17 + resolution: "@smithy/middleware-retry@npm:2.0.17" dependencies: - "@smithy/node-config-provider": ^2.1.1 + "@smithy/node-config-provider": ^2.1.2 "@smithy/protocol-http": ^3.0.7 "@smithy/service-error-classification": ^2.0.4 "@smithy/types": ^2.3.5 @@ -10611,7 +10895,7 @@ __metadata: "@smithy/util-retry": ^2.0.4 tslib: ^2.5.0 uuid: ^8.3.2 - checksum: 9348bf7663ad85469614bda8a672bc8a5a104137caf1f3eb77553462f52044d27b933be177f850abe202fb9b4e060f39982e85565d8caf164de6377ffba82272 + checksum: 3035a9a3d6532d3aa3014671956e4896f2cc5888f88496f1a7907d3b050a403f1bfcaf25ed2a82d5c97fdfbb44bef549a05e5841156043d42ab952a9f12f6bdd languageName: node linkType: hard @@ -10635,15 +10919,15 @@ __metadata: languageName: node linkType: hard -"@smithy/node-config-provider@npm:^2.1.1": - version: 2.1.1 - resolution: "@smithy/node-config-provider@npm:2.1.1" +"@smithy/node-config-provider@npm:^2.1.1, @smithy/node-config-provider@npm:^2.1.2": + version: 2.1.2 + resolution: "@smithy/node-config-provider@npm:2.1.2" dependencies: "@smithy/property-provider": ^2.0.12 - "@smithy/shared-ini-file-loader": ^2.2.0 + "@smithy/shared-ini-file-loader": ^2.2.1 "@smithy/types": ^2.3.5 tslib: ^2.5.0 - checksum: b9bca5ba2b1ef60221f7bf24e876dabba46652ead428ec31a528ef57ee14af559752736317f870d55f1b90c6bb6c52886194475190a05339235ffe123217a9bd + checksum: 86e1eff810a3811e8263f268d42ab53df44225d67b2034449d7c8536b4e56b82a6326f41fe6bd0137703f5f73375e836a29774b1efe2a9158d3a7ed896f25bb9 languageName: node linkType: hard @@ -10710,13 +10994,13 @@ __metadata: languageName: node linkType: hard -"@smithy/shared-ini-file-loader@npm:^2.0.6, @smithy/shared-ini-file-loader@npm:^2.2.0": - version: 2.2.0 - resolution: "@smithy/shared-ini-file-loader@npm:2.2.0" +"@smithy/shared-ini-file-loader@npm:^2.0.6, @smithy/shared-ini-file-loader@npm:^2.2.1": + version: 2.2.1 + resolution: "@smithy/shared-ini-file-loader@npm:2.2.1" dependencies: "@smithy/types": ^2.3.5 tslib: ^2.5.0 - checksum: 77563b09f961c12d1afe3c5006074be3590fd3b44b096b5b7d5244b6924a5988731c4903d13f13cef4f6139e10735fb04d63e8c78bece1f6594dc3158033a7e2 + checksum: 9b06ffeb7cd1543b6be6af9cfa7e1f7b29047722c301cac30d336ecea7d97748892f23ab5c2985899c056c8ba960242730030a2439ffffd11641f954f76feda1 languageName: node linkType: hard @@ -10829,17 +11113,17 @@ __metadata: linkType: hard "@smithy/util-defaults-mode-node@npm:^2.0.19": - version: 2.0.19 - resolution: "@smithy/util-defaults-mode-node@npm:2.0.19" + version: 2.0.20 + resolution: "@smithy/util-defaults-mode-node@npm:2.0.20" dependencies: - "@smithy/config-resolver": ^2.0.14 - "@smithy/credential-provider-imds": ^2.0.16 - "@smithy/node-config-provider": ^2.1.1 + "@smithy/config-resolver": ^2.0.15 + "@smithy/credential-provider-imds": ^2.0.17 + "@smithy/node-config-provider": ^2.1.2 "@smithy/property-provider": ^2.0.12 "@smithy/smithy-client": ^2.1.11 "@smithy/types": ^2.3.5 tslib: ^2.5.0 - checksum: 86609e2ea7673b3e735e25ca4647dbd70a65fc335af860617936299443c2dd1e2d9481bc7d3b172cf589a4fbc8f12040cf219345ece80fe3dab331d6a52f8168 + checksum: 76055f1f759feecc9419242d30bbd94e0a2fee658c909b90bc7fb5cb19adc844221e21021ffc0aab5d98dc0070ce7f1d950c196d14c56d3c1ed2c5e4fcf7f0c2 languageName: node linkType: hard @@ -12418,7 +12702,7 @@ __metadata: jotai: ^2.4.3 lodash.debounce: ^4.0.8 react: 18.2.0 - swr: 2.2.0 + swr: 2.2.4 vitest: 0.34.6 y-provider: "workspace:*" peerDependencies: @@ -13653,14 +13937,14 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^6.7.5": - version: 6.7.5 - resolution: "@typescript-eslint/eslint-plugin@npm:6.7.5" + version: 6.8.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.8.0" dependencies: "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.7.5 - "@typescript-eslint/type-utils": 6.7.5 - "@typescript-eslint/utils": 6.7.5 - "@typescript-eslint/visitor-keys": 6.7.5 + "@typescript-eslint/scope-manager": 6.8.0 + "@typescript-eslint/type-utils": 6.8.0 + "@typescript-eslint/utils": 6.8.0 + "@typescript-eslint/visitor-keys": 6.8.0 debug: ^4.3.4 graphemer: ^1.4.0 ignore: ^5.2.4 @@ -13673,44 +13957,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: c37edf5a703db4ff9227d67c2d2cf817e65c9afc94cc0e650fa3d2b05ac55201ef887ce9dadb9ca13779f4025bf4367e132b013e3559e777006a2332079bb180 + checksum: c36ccf606ebcaff8263c4ffa3b4cda58c6f93474b9eea9906e51be2fef8596977a245cc13770b21c6bfd38ccf45a3cf3613d5f4499429f62ec80afe15ae345bd languageName: node linkType: hard "@typescript-eslint/parser@npm:^6.7.5": - version: 6.7.5 - resolution: "@typescript-eslint/parser@npm:6.7.5" + version: 6.8.0 + resolution: "@typescript-eslint/parser@npm:6.8.0" dependencies: - "@typescript-eslint/scope-manager": 6.7.5 - "@typescript-eslint/types": 6.7.5 - "@typescript-eslint/typescript-estree": 6.7.5 - "@typescript-eslint/visitor-keys": 6.7.5 + "@typescript-eslint/scope-manager": 6.8.0 + "@typescript-eslint/types": 6.8.0 + "@typescript-eslint/typescript-estree": 6.8.0 + "@typescript-eslint/visitor-keys": 6.8.0 debug: ^4.3.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 63f988c1c87697bd20487933be952b97f7a5f2a9977f505af671c7d49367fc01ca508817576646caa937c15cc0a0ef1e86adff9111eb19df8b489e7436d10620 + checksum: 10d7a3ae383fee5a5cba9541c72e23d6ab01cca6b414a62b44dacb5ebc15c80b80aa6c105b6469d3795f2f8514ae2499c069cd2d9dcac61f3db9ef6c7a75e080 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.7.5": - version: 6.7.5 - resolution: "@typescript-eslint/scope-manager@npm:6.7.5" +"@typescript-eslint/scope-manager@npm:6.8.0": + version: 6.8.0 + resolution: "@typescript-eslint/scope-manager@npm:6.8.0" dependencies: - "@typescript-eslint/types": 6.7.5 - "@typescript-eslint/visitor-keys": 6.7.5 - checksum: f21858ed78f81ab2d9879139f69657fda2a7b901078f79df64d1262d80f84ef66c56525ed0bb5e393fa5ca5474ad97f2225b7f713977c2d0f79cda31b2744af9 + "@typescript-eslint/types": 6.8.0 + "@typescript-eslint/visitor-keys": 6.8.0 + checksum: b6cf2803531d1c14b56c30fd3cd807b80e17fe48d0da8e5aa9ae50915407ed732c7e2a7ac8030b7cf8ed07b8e481a1138d76bf05b727837a0e016280c2f6873b languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.7.5": - version: 6.7.5 - resolution: "@typescript-eslint/type-utils@npm:6.7.5" +"@typescript-eslint/type-utils@npm:6.8.0": + version: 6.8.0 + resolution: "@typescript-eslint/type-utils@npm:6.8.0" dependencies: - "@typescript-eslint/typescript-estree": 6.7.5 - "@typescript-eslint/utils": 6.7.5 + "@typescript-eslint/typescript-estree": 6.8.0 + "@typescript-eslint/utils": 6.8.0 debug: ^4.3.4 ts-api-utils: ^1.0.1 peerDependencies: @@ -13718,7 +14002,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 8023d8ddcfbf4a0411b192016711068e9e6787c5811aee3a25ac40025ade0d063a1a3d7b38469e1a534bb31fa9dbeec08ab53b7a6d7b3128358294ac5b219d9a + checksum: 9b7d56904dc1a5719ef79eb1b7989d6fad10c71fb07ec3e66cf69b8c8dc5383d644ab122d4701bc4960fb7c99cc08aee4e645db3e4675d488d5779197e15dfda languageName: node linkType: hard @@ -13736,19 +14020,19 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:6.7.5": - version: 6.7.5 - resolution: "@typescript-eslint/types@npm:6.7.5" - checksum: f21e5726b60f13feb3a920c92515fbc1205ba0e9bba9959b2e42c02c282a0ab4fb0e5ae84f3807b9b1cf95036027e9033d92a911fa88e6c243a87621d8dd7a01 +"@typescript-eslint/types@npm:6.8.0": + version: 6.8.0 + resolution: "@typescript-eslint/types@npm:6.8.0" + checksum: 1fcd85f6d575116d51c6ee757ed37610ae5e7e4296a29f93c9c6949f6cd16d24550eb7fc5bae7a43119cc08e13836f69a7ae7c54ebba6c95aef96b34d3bfb7f7 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.7.5": - version: 6.7.5 - resolution: "@typescript-eslint/typescript-estree@npm:6.7.5" +"@typescript-eslint/typescript-estree@npm:6.8.0": + version: 6.8.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.8.0" dependencies: - "@typescript-eslint/types": 6.7.5 - "@typescript-eslint/visitor-keys": 6.7.5 + "@typescript-eslint/types": 6.8.0 + "@typescript-eslint/visitor-keys": 6.8.0 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -13757,7 +14041,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 17685e8321edce1d1ec4278d84e63c0f41ccb19e9308f21c37450943ad0c33328755ac52b966e7855af17e01d22bc83d1fcda79c279fabe7d3460c8f315a7265 + checksum: 388db7f33ef1bc0e7b960c0bce9c744c2e32c66c7ab8dfae73d8533958202ad6f31663b0010f79c45b5ff93159c67f45b00693d73b9da2472b17156dfd26b4a8 languageName: node linkType: hard @@ -13797,20 +14081,20 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.7.5": - version: 6.7.5 - resolution: "@typescript-eslint/utils@npm:6.7.5" +"@typescript-eslint/utils@npm:6.8.0": + version: 6.8.0 + resolution: "@typescript-eslint/utils@npm:6.8.0" dependencies: "@eslint-community/eslint-utils": ^4.4.0 "@types/json-schema": ^7.0.12 "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.7.5 - "@typescript-eslint/types": 6.7.5 - "@typescript-eslint/typescript-estree": 6.7.5 + "@typescript-eslint/scope-manager": 6.8.0 + "@typescript-eslint/types": 6.8.0 + "@typescript-eslint/typescript-estree": 6.8.0 semver: ^7.5.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: f365c654241f927e7784640079627d60a296aa3d575552b07594a69cfc419832eb5fa4adc87acb1988bea9741ae9cc4a5277dab168990310caef5de125255752 + checksum: 6d9f90db504502a9aa10e834830c3ffa25483757414670acc6141a3ebef9171a57688a3a179febf35a0e1e0b322f37228d9537bf1b279f1af7fc97888b873bc3 languageName: node linkType: hard @@ -13834,13 +14118,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.7.5": - version: 6.7.5 - resolution: "@typescript-eslint/visitor-keys@npm:6.7.5" +"@typescript-eslint/visitor-keys@npm:6.8.0": + version: 6.8.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.8.0" dependencies: - "@typescript-eslint/types": 6.7.5 + "@typescript-eslint/types": 6.8.0 eslint-visitor-keys: ^3.4.1 - checksum: 2df996742f63d89fa339b0e8ff3a3a289d36b3f584f7538a7626bed3869e9ae27f8f56ab31748519d25a63de2ae22a43dd8413610b00436ff342b0a17eb85289 + checksum: 710d9067b85d7715a400ae625c083c41733abb891d7b35108de083913980f9642e79d27689599fa39915f0fecae16dbfc30367007fccc838ccd917943660de22 languageName: node linkType: hard @@ -18836,9 +19120,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.4.535": - version: 1.4.554 - resolution: "electron-to-chromium@npm:1.4.554" - checksum: cbac43c50b43777327f4a7bf149ee3088c1da8b91bbcd80f78d2cc77bc52763f6d0941574499239d9caefd3430d3093f865e5f1093371418f7d6b70301eeae9b + version: 1.4.556 + resolution: "electron-to-chromium@npm:1.4.556" + checksum: 8c9aa48776d80c23d8709dcd4342f1b18ca5b63bdb233fb6913f0db7b382d69afa84d5f08ead84bde6378a6a7ab3d1127f7cb6f4d0642fa625e96de6559dc1d7 languageName: node linkType: hard @@ -19428,31 +19712,31 @@ __metadata: linkType: hard "esbuild@npm:^0.19.4": - version: 0.19.4 - resolution: "esbuild@npm:0.19.4" + version: 0.19.5 + resolution: "esbuild@npm:0.19.5" dependencies: - "@esbuild/android-arm": 0.19.4 - "@esbuild/android-arm64": 0.19.4 - "@esbuild/android-x64": 0.19.4 - "@esbuild/darwin-arm64": 0.19.4 - "@esbuild/darwin-x64": 0.19.4 - "@esbuild/freebsd-arm64": 0.19.4 - "@esbuild/freebsd-x64": 0.19.4 - "@esbuild/linux-arm": 0.19.4 - "@esbuild/linux-arm64": 0.19.4 - "@esbuild/linux-ia32": 0.19.4 - "@esbuild/linux-loong64": 0.19.4 - "@esbuild/linux-mips64el": 0.19.4 - "@esbuild/linux-ppc64": 0.19.4 - "@esbuild/linux-riscv64": 0.19.4 - "@esbuild/linux-s390x": 0.19.4 - "@esbuild/linux-x64": 0.19.4 - "@esbuild/netbsd-x64": 0.19.4 - "@esbuild/openbsd-x64": 0.19.4 - "@esbuild/sunos-x64": 0.19.4 - "@esbuild/win32-arm64": 0.19.4 - "@esbuild/win32-ia32": 0.19.4 - "@esbuild/win32-x64": 0.19.4 + "@esbuild/android-arm": 0.19.5 + "@esbuild/android-arm64": 0.19.5 + "@esbuild/android-x64": 0.19.5 + "@esbuild/darwin-arm64": 0.19.5 + "@esbuild/darwin-x64": 0.19.5 + "@esbuild/freebsd-arm64": 0.19.5 + "@esbuild/freebsd-x64": 0.19.5 + "@esbuild/linux-arm": 0.19.5 + "@esbuild/linux-arm64": 0.19.5 + "@esbuild/linux-ia32": 0.19.5 + "@esbuild/linux-loong64": 0.19.5 + "@esbuild/linux-mips64el": 0.19.5 + "@esbuild/linux-ppc64": 0.19.5 + "@esbuild/linux-riscv64": 0.19.5 + "@esbuild/linux-s390x": 0.19.5 + "@esbuild/linux-x64": 0.19.5 + "@esbuild/netbsd-x64": 0.19.5 + "@esbuild/openbsd-x64": 0.19.5 + "@esbuild/sunos-x64": 0.19.5 + "@esbuild/win32-arm64": 0.19.5 + "@esbuild/win32-ia32": 0.19.5 + "@esbuild/win32-x64": 0.19.5 dependenciesMeta: "@esbuild/android-arm": optional: true @@ -19500,7 +19784,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 024309a16365b020815a30e9a3a9354894a391cf1adbfad7f44a975cf161ab5e961619b30e1ec8ea02994631d71e6b38831119be69f8ccb610c32bbe21addc79 + checksum: 5a0227cf6ffffa3076714d88230af1dfdd2fc363d91bd712a81fb91230c315a395e2c9b7588eee62986aeebf4999804b9b1b59eeab8e2457184eb0056bfe20c8 languageName: node linkType: hard @@ -24718,8 +25002,8 @@ __metadata: linkType: hard "langsmith@npm:~0.0.31": - version: 0.0.42 - resolution: "langsmith@npm:0.0.42" + version: 0.0.43 + resolution: "langsmith@npm:0.0.43" dependencies: "@types/uuid": ^9.0.1 commander: ^10.0.1 @@ -24728,7 +25012,7 @@ __metadata: uuid: ^9.0.0 bin: langsmith: dist/cli/main.cjs - checksum: 16bcc2aab8be90dc509d3306a213ded8a5cd369771c389fd3ba067e161114175882920a796592509889e77e01c3e8787e8d0610770f41bc95fe344ee92e16e42 + checksum: 6f6b7d4164ba2796a250fb0f2e665e248d8148aafffe267c381173656becd59853498e835caf939d88396394bbafaabbd016d201ac845172b851b7d15d3cfee8 languageName: node linkType: hard @@ -24832,8 +25116,8 @@ __metadata: linkType: hard "lint-staged@npm:^15.0.0": - version: 15.0.0 - resolution: "lint-staged@npm:15.0.0" + version: 15.0.1 + resolution: "lint-staged@npm:15.0.1" dependencies: chalk: 5.3.0 commander: 11.1.0 @@ -24847,7 +25131,7 @@ __metadata: yaml: 2.3.2 bin: lint-staged: bin/lint-staged.js - checksum: 8d1a0621db9ea281c3cadacd0156edd45748f74ba9b9baeb734feacef96e52b23d801c76d24116b076e1489037f005cd12695458d82d060a69e2bb2cfd830713 + checksum: 4ef972b8fb246fa047e2f819833e675a816bfe1dd1fa4130d1b75cb6af2a51abc54eb7047a7b82403d9d4f8aefe1e71532a999161d180fb5ec019d360988b7bf languageName: node linkType: hard @@ -26414,11 +26698,11 @@ __metadata: linkType: hard "nanoid@npm:^5.0.1": - version: 5.0.1 - resolution: "nanoid@npm:5.0.1" + version: 5.0.2 + resolution: "nanoid@npm:5.0.2" bin: nanoid: bin/nanoid.js - checksum: fb5a57ec0563f12f101129b2f11fe50505e5f1219760c43e6ae30fc0a0d2aa269985f6d07ddea15e3bd4b24751c9ef14fa8117cbc80d410726429e2b37a4b13f + checksum: fa6908c2c6a7a9e91e02b98cb0b9b829454d390a63f83c1798f0c504d07b536d99cad3e975e5014b176534e67e234ff66bccd4610bf3ffb2cf0d6d932a73f3a8 languageName: node linkType: hard @@ -26548,11 +26832,11 @@ __metadata: linkType: hard "node-abi@npm:^3.45.0": - version: 3.50.0 - resolution: "node-abi@npm:3.50.0" + version: 3.51.0 + resolution: "node-abi@npm:3.51.0" dependencies: semver: ^7.3.5 - checksum: d86b659bdc0c1ce095613352c496de43d231eec863e8fe178fa90f831920c7fef7bcf6dca3affb3e963aa124f5a9363950d6d89f37f18aef48e0ffa2051e19da + checksum: 3fabc9d58f0478767157560249f79c4a9e95082b96700cd8cc470f517bd566dbab82a37c862db3f78d3187be9f19f5cd9822b6f1b7ac7a3254fa70c3e3b38a83 languageName: node linkType: hard @@ -29479,26 +29763,26 @@ __metadata: linkType: hard "react-router-dom@npm:^6.16.0": - version: 6.16.0 - resolution: "react-router-dom@npm:6.16.0" + version: 6.17.0 + resolution: "react-router-dom@npm:6.17.0" dependencies: - "@remix-run/router": 1.9.0 - react-router: 6.16.0 + "@remix-run/router": 1.10.0 + react-router: 6.17.0 peerDependencies: react: ">=16.8" react-dom: ">=16.8" - checksum: 18b398924bb0f0d97cf2f71dab71d860b960a7a267b2f77388990c662bb6d8738bdc3042d92f713fd63d269ae9ad90df39c8e97661b6ba758bbb7386b9f20ae0 + checksum: e0ba4f4c507681e2ffdecdf2e67edf7ec0e2bf4be35222e29d013afdb03866a5e6ecacc8b452bd55797b9672785d02f81bd6dbf6b05ac93a59e48e774b0060de languageName: node linkType: hard -"react-router@npm:6.16.0": - version: 6.16.0 - resolution: "react-router@npm:6.16.0" +"react-router@npm:6.17.0": + version: 6.17.0 + resolution: "react-router@npm:6.17.0" dependencies: - "@remix-run/router": 1.9.0 + "@remix-run/router": 1.10.0 peerDependencies: react: ">=16.8" - checksum: b31c187e3fdcdf7294ffdad6ff834e14d012840c94d8ee8c7fbe451062a8fcb6e31e8bc7827fb1ff45445dd40fad2b8c96a7e98f0ac1c3eb1d716c257a0821c9 + checksum: 99c30d94fbb34657e4c8c3ef1aaae33b143167d3869b442e06c83b4006f35200fde810029180e209654bef2f47f0b27a928f77cc2d859a358a2722cc9d494f03 languageName: node linkType: hard @@ -31886,14 +32170,15 @@ __metadata: languageName: node linkType: hard -"swr@npm:2.2.0": - version: 2.2.0 - resolution: "swr@npm:2.2.0" +"swr@npm:2.2.4": + version: 2.2.4 + resolution: "swr@npm:2.2.4" dependencies: + client-only: ^0.0.1 use-sync-external-store: ^1.2.0 peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 - checksum: 1f04795ff9dff54987cbf8a544afc9e42d1350a99e899be8a7cdc4885f561e3ee464f78245ee2ebc8ced262b04023d134f731e276227319dc2d6e1843389ddd8 + checksum: d1398f89fd68af0e0cb6100a5769b1e17c0dbe8a778898643ad28456acda64add43344754c7d919e3f2ca82854adf86ff7d465aba25a2d555bcb669e457138f8 languageName: node linkType: hard @@ -32098,8 +32383,8 @@ __metadata: linkType: hard "terser@npm:^5.10.0, terser@npm:^5.16.8": - version: 5.21.0 - resolution: "terser@npm:5.21.0" + version: 5.22.0 + resolution: "terser@npm:5.22.0" dependencies: "@jridgewell/source-map": ^0.3.3 acorn: ^8.8.2 @@ -32107,7 +32392,7 @@ __metadata: source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: 130f1567af1ffa4ddb067651bb284a01b45b5c83e82b3a072a5ff94b0b00ac35090f89c8714631a4a45972f65187bc149fc7144380611f437e1e3d9e174b136b + checksum: ee95981c54ebd381e0b7f5872c646e7a05543e53960f8e0c2f240863c368989d43a3ca80b7e9f691683c92ba199eb4b91d61785fef0b9ca4a887eb55866001f4 languageName: node linkType: hard @@ -33904,12 +34189,13 @@ __metadata: linkType: hard "webpack-merge@npm:^5.7.3, webpack-merge@npm:^5.9.0": - version: 5.9.0 - resolution: "webpack-merge@npm:5.9.0" + version: 5.10.0 + resolution: "webpack-merge@npm:5.10.0" dependencies: clone-deep: ^4.0.1 + flat: ^5.0.2 wildcard: ^2.0.0 - checksum: 64fe2c23aacc5f19684452a0e84ec02c46b990423aee6fcc5c18d7d471155bd14e9a6adb02bd3656eb3e0ac2532c8e97d69412ad14c97eeafe32fa6d10050872 + checksum: 1fe8bf5309add7298e1ac72fb3f2090e1dfa80c48c7e79fa48aa60b5961332c7d0d61efa8851acb805e6b91a4584537a347bc106e05e9aec87fa4f7088c62f2f languageName: node linkType: hard