Compare commits

..

14 Commits

Author SHA1 Message Date
73b6c85171 ow my formatting
All checks were successful
Test, Build, Deploy / Test, Build, and Deploy (push) Successful in 1m35s
Test, Build, Deploy / Create Sentry Release (push) Successful in 6s
2026-05-11 00:52:14 -04:00
037eb7fcac Possibly fix appeals? 2026-05-11 00:51:51 -04:00
abc1389dbb Bump dependencies 2026-05-11 00:51:40 -04:00
cd566248fd Bump node version 2026-05-11 00:51:09 -04:00
3d7e499ec1 Create data requests table 2026-05-06 03:18:57 -04:00
40dd0b5a5c Remove data transfer code
All checks were successful
Test, Build, Deploy / Test, Build, and Deploy (push) Successful in 1m25s
Test, Build, Deploy / Create Sentry Release (push) Successful in 7s
2026-04-29 02:05:08 -04:00
229398e401 Disable button while event is submitting
All checks were successful
Test, Build, Deploy / Test, Build, and Deploy (push) Successful in 58s
Test, Build, Deploy / Create Sentry Release (push) Successful in 6s
2026-04-17 01:47:42 -04:00
a9863f5680 Remove unneeded unix time param
All checks were successful
Test, Build, Deploy / Test, Build, and Deploy (push) Successful in 55s
Test, Build, Deploy / Create Sentry Release (push) Successful in 9s
2026-04-16 04:08:20 -04:00
2e76bd9f28 Make buttons hide again when performed_at is not null
All checks were successful
Test, Build, Deploy / Test, Build, and Deploy (push) Successful in 1m7s
Test, Build, Deploy / Create Sentry Release (push) Successful in 7s
2026-04-16 03:52:40 -04:00
171240bc7d Add db setup migration
All checks were successful
Test, Build, Deploy / Test, Build, and Deploy (push) Successful in 1m1s
Test, Build, Deploy / Create Sentry Release (push) Successful in 7s
2026-04-15 02:45:39 -04:00
ffce17d7aa Add more stuff to gitignore 2026-04-15 02:43:38 -04:00
06fdfe9d10 Log appeal denials
All checks were successful
Test, Build, Deploy / Test, Build, and Deploy (push) Successful in 1m8s
Test, Build, Deploy / Create Sentry Release (push) Successful in 7s
2026-04-14 22:09:43 -04:00
ba643bf986 Apparently these are causing problems
All checks were successful
Test, Build, Deploy / Test, Build, and Deploy (push) Successful in 1m1s
Test, Build, Deploy / Create Sentry Release (push) Successful in 6s
2026-04-14 04:16:45 -04:00
12f91dca7d Move input button styles hook to top level
All checks were successful
Test, Build, Deploy / Test, Build, and Deploy (push) Successful in 1m2s
Test, Build, Deploy / Create Sentry Release (push) Successful in 5s
2026-04-14 03:49:06 -04:00
22 changed files with 443 additions and 733 deletions

2
.gitignore vendored
View File

@@ -37,5 +37,7 @@ public/build
# Wrangler data
.wrangler
wrangler.jsonc
wrangler.toml
/generated/prisma

View File

@@ -1 +1 @@
v24.14.1
v24.15.0

View File

@@ -45,6 +45,7 @@ export async function loader({ context }: { context: RequestContext }) {
id: true,
},
where: {
approved: null,
user: {
path: "id",
equals: currentUser.id,

View File

@@ -44,6 +44,7 @@ export default function () {
const [eventType, setEventType] = useState("");
const [riddleAnswer, setRiddleAnswer] = useState("");
const [submitSuccess, setSubmitSuccess] = useState(false);
const [disableSubmit, setDisableSubmit] = useState(false);
useEffect(() => {
setDatePickerMin(`${new Date().toISOString().split("T").at(0)}`);
@@ -53,6 +54,7 @@ export default function () {
}, []);
async function submit() {
setDisableSubmit(true);
let eventResp: Response;
try {
@@ -69,6 +71,7 @@ export default function () {
method: "POST",
});
} catch {
setDisableSubmit(false);
toast({
description: "Please check your internet and try again",
isClosable: true,
@@ -86,6 +89,7 @@ export default function () {
errorMessage = ((await eventResp.json()) as { error: string }).error;
} catch {}
setDisableSubmit(false);
toast({
description: errorMessage,
isClosable: true,
@@ -150,7 +154,11 @@ export default function () {
onChange={(e) => setRiddleAnswer(e.target.value)}
placeholder="Riddle answer"
/>
<Button mt="16px" onClick={async () => await submit()}>
<Button
disabled={disableSubmit}
mt="16px"
onClick={async () => await submit()}
>
Book
</Button>
</Container>

View File

@@ -1,42 +0,0 @@
import { Button, Container, Heading, Text } from "@chakra-ui/react";
export default function () {
return (
<Container maxW="container.md">
<Heading size="lg">Transfer your Save Data</Heading>
<br />
<br />
<Text>Lost your account? Want to shake off a stalker?</Text>
<br />
<br />
<Text size="lg">We can help!</Text>
<br />
<br />
<Text>Some information you should know:</Text>
<br />
<Text>
We might require your .ROBLOSECURITY cookie, depending on your
circumstances. This is because Roblox does not allow terminated accounts
to utilize OAuth. Normally this would be a very bad idea, and we don't
like doing this either, but it may be the only option. Security is also
less of a concern for terminated accounts as they are blocked from
accessing almost all Roblox API endpoints (the exceptions being login,
logout, and creating support tickets - and only the logout endpoint
doesn't require completing a captcha). If you are concerned about your
account's security, we suggest logging in to your terminated account in
a private/incognito window, copying the .ROBLOSECURITY cookie from
there, and logging out once we have verified your old account (which
normally only takes a few seconds). The ultra paranoid may also consider
resetting their password. If you are not convinced or still have
questions, join our Discord server (link is on the about page) and open
a ticket with ModMail for us to verify you manually (no cookie
required).
</Text>
<br />
<br />
<Button as="a" href="/data-transfer/start" colorScheme="blue">
Start my Transfer
</Button>
</Container>
);
}

View File

@@ -1,10 +0,0 @@
import Success from "../../components/Success.js";
export default function () {
return (
<Success
heading="Data Transfer Submitted"
message="Your request is now being processed; this normally takes 1-2 weeks."
/>
);
}

View File

@@ -1,34 +0,0 @@
import { Button, Card, Container, Heading, VStack } from "@chakra-ui/react";
import { useLoaderData } from "@remix-run/react";
export async function loader({ context }: { context: RequestContext }) {
const { host, protocol } = new URL(context.request.url);
return { client_id: context.env.ROBLOX_OAUTH_CLIENT_ID, host, protocol };
}
export default function () {
const loaderData = useLoaderData<typeof loader>();
return (
<Container pt="16vh">
<Card borderRadius="32px" p="4vh">
<VStack alignContent="center" gap="2vh">
<Heading>Verify your new Roblox account</Heading>
<br />
<Button
as="a"
borderRadius="24px"
colorScheme="blue"
href={`https://apis.roblox.com/oauth/v1/authorize?client_id=${
loaderData.client_id
}&redirect_uri=${encodeURIComponent(
`${loaderData.protocol}//${loaderData.host}/api/data-transfers/verify`,
)}&response_type=code&scope=openid%20profile`}
>
Verify
</Button>
</VStack>
</Card>
</Container>
);
}

View File

@@ -1,81 +0,0 @@
import {
Button,
Container,
Heading,
HStack,
Radio,
RadioGroup,
Text,
Textarea,
useToast,
} from "@chakra-ui/react";
import { useState } from "react";
export default function () {
const [showCookieBox, setShowCookieBox] = useState(false);
const [loading, setLoading] = useState(false);
return (
<Container maxW="container.md">
<Heading pt="36px">Let's get started</Heading>
<Text pt="128px">Is your old Roblox account banned?</Text>
<RadioGroup onChange={(val) => setShowCookieBox(JSON.parse(val))}>
<HStack>
<Radio value="false">No</Radio>
<Radio value="true">Yes</Radio>
</HStack>
</RadioGroup>
<Textarea
id="cookie-box"
placeholder="Paste your .ROBLOSECURITY cookie here"
mt="16px"
style={{ display: showCookieBox ? "initial" : "none" }}
/>
<Button
colorScheme="blue"
isLoading={loading}
loadingText="Processing..."
mt="16px"
onClick={async () => {
setLoading(true);
const createTransferReq = await fetch("/api/data-transfers/create", {
body: JSON.stringify({
can_access: !showCookieBox,
cookie: (
document.getElementById("cookie-box") as HTMLInputElement
).value,
}),
headers: {
"content-type": "application/json",
},
method: "POST",
});
if (!createTransferReq.ok) {
setLoading(false);
useToast()({
description: (
(await createTransferReq.json()) as { error: string }
).error,
isClosable: true,
status: "error",
title: "Failed to create transfer request",
});
return;
}
location.assign(
((await createTransferReq.json()) as { url: string }).url,
);
}}
>
Continue
</Button>
<br />
<Text pt="16px">
If you cannot login at all, please visit the support page and join our
server.
</Text>
</Container>
);
}

View File

@@ -271,7 +271,7 @@ export default function () {
// Technically this won't be the same as the time in the db, but that doesn't matter since this is just to hide the button
newEventData[eventData.findIndex((e) => e.id === eventId)].performed_at =
Date.now();
new Date().toISOString();
setEventData([...newEventData]);
setSelectedEvent("");
@@ -313,7 +313,8 @@ export default function () {
const newEventData = eventData;
newEventData[eventData.findIndex((e) => e.id === eventId)].performed_at = 0;
newEventData[eventData.findIndex((e) => e.id === eventId)].performed_at =
new Date(0).toISOString();
setEventData([...newEventData]);
setSelectedEvent("");
setDisableClicks(false);
@@ -664,9 +665,7 @@ export default function () {
</Button>
</>
) : null}
{can_approve &&
!event.pending &&
typeof event.performed_at !== "number" ? (
{can_approve && !event.pending && !event.performed_at ? (
<>
<Button
colorScheme="blue"

View File

@@ -51,6 +51,9 @@ export default function () {
const toast = useToast();
const [uploading, setUploading] = useState(false);
const [loading, setLoading] = useState(false);
const inputSelectorProps = useMultiStyleConfig("Button", {
colorScheme: "blue",
});
const fileTypes: { [k: string]: string } = {
avif: "image/avif",
gif: "image/gif",
@@ -312,9 +315,7 @@ export default function () {
"::file-selector-button": {
border: "none",
outline: "none",
...useMultiStyleConfig("Button", {
colorScheme: "blue",
}),
...inputSelectorProps,
},
}}
multiple={true}

View File

@@ -173,7 +173,6 @@ export default function (props: {
)}
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
@@ -223,7 +222,6 @@ export default function (props: {
{data.id ? data.username : ""}
</Text>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"

View File

@@ -17,13 +17,7 @@ export default function ({
>
<Flex>
<Spacer />
<svg
xmlns="http://www.w3.org/2000/svg"
width="128"
height="128"
fill="currentColor"
viewBox="0 0 16 16"
>
<svg width="128" height="128" fill="currentColor" viewBox="0 0 16 16">
<path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0z" />
<path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l7-7z" />
</svg>

View File

@@ -1,19 +0,0 @@
export async function onRequest(context: RequestContext) {
const cookies = context.request.headers.get("cookie");
if (!cookies) return await context.next();
const cookieList = cookies.split("; ").map((cookie: string) => {
const [name, value] = cookie.split("=");
return { name, value };
});
const transferId = cookieList.find(
(cookie: { name: string; value: string }) => cookie.name === "__dtid",
);
if (transferId) context.data.data_transfer_id = transferId;
return await context.next();
}

View File

@@ -1,74 +0,0 @@
import { jsonError } from "../../common.js";
export async function onRequestPost(context: RequestContext) {
const { cookie, is_banned } = context.data.body;
if (
typeof is_banned !== "boolean" ||
(is_banned && typeof cookie !== "string") ||
(is_banned &&
!cookie.match(
/_\|WARNING:-DO-NOT-SHARE-THIS\.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items\.\|_[A-F\d]+/,
))
)
return jsonError("Invalid request", 400);
const id =
(context.request.headers.get("cf-ray")?.split("-")[0] as string) +
Date.now().toString() +
crypto.randomUUID().replaceAll("-", "");
if (!is_banned) {
await context.env.DATA.put(`datatransfer_${id}`, "{}", {
expirationTtl: 3600,
});
const host = context.request.headers.get("Host") as string;
return new Response(
`{"url":"https://apis.roblox.com/oauth/v1/authorize?client_id=${
context.env.ROBLOX_OAUTH_CLIENT_ID
}&redirect_uri=${encodeURIComponent(
`http${host.startsWith(
"localhost" ? "" : "s",
)}://${host}/api/data-transfers/verify`,
)}"}`,
{
headers: {
"set-cookie": `__dtid=${id}; HttpOnly; Max-Age=3600; Path=/; SameSite=Lax; Secure`,
},
},
);
}
const authedUserReq = await fetch(
"https://users.roblox.com/v1/users/authenticated",
{
headers: {
cookie: `.ROBLOSECURITY=${cookie}`,
},
},
);
if (!authedUserReq.ok) return jsonError("Cookie is invalid", 400);
const authedUser: { id: number; name: string } = await authedUserReq.json();
await context.env.DATA.put(
`datatransfer_${id}`,
JSON.stringify({
oldUser: authedUser,
}),
{
expirationTtl: 3600,
},
);
return new Response(null, {
headers: {
location: "/data-transfer/destination-account",
"set-cookie": `__dtid=${id}; HttpOnly; Max-Age=3600; Path=/; SameSite=Lax; Secure`,
},
status: 201,
});
}

View File

@@ -1,92 +0,0 @@
import { jsonError } from "../../common.js";
import { getBanList } from "../../roblox-open-cloud.js";
export async function onRequestGet(context: RequestContext) {
const code = new URL(context.request.url).searchParams.get("code");
if (!code) return jsonError("Missing code", 400);
const dataTransferData = (await context.env.DATA.get(
`datatransfer_${context.data.data_transfer_id}`,
{ type: "json" },
)) as { [k: string]: any } | null;
if (!dataTransferData)
return jsonError("No transfer exists with that ID", 404);
const exchangeReq = await fetch("https://apis.roblox.com/oauth/v1/token", {
body: `code=${code}&grant_type=authorization_code`,
headers: {
authorization: `Basic ${
btoa(context.env.ROBLOX_OAUTH_ID) +
":" +
context.env.ROBLOX_OAUTH_SECRET
}`,
"content-type": "application/x-www-form-urlencoded",
},
method: "POST",
});
if (!exchangeReq.ok) return jsonError("Failed to redeem code", 500);
const { id_token } = (await exchangeReq.json()) as { id_token: string };
const { name, preferred_username, sub } = JSON.parse(
atob(id_token.replaceAll("-", "+").replaceAll("_", "/")),
);
if (!preferred_username) return jsonError("Username missing", 500);
const userObj = {
displayName: name,
id: parseInt(sub),
name: preferred_username,
};
let redirectLocation = "/data-transfer/complete";
if (dataTransferData.oldUser) {
let banList;
try {
banList = (await getBanList(context)).value;
} catch {
return jsonError("Failed to create data transfer request", 500);
}
if (banList[userObj.id].BanType)
return new Response(null, {
headers: {
location: redirectLocation,
},
status: 302,
});
dataTransferData.newUser = userObj;
await fetch(
`https://api.trello.com/1/cards?key=${context.env.TRELLO_API_KEY}&token=${context.env.TRELLO_API_TOKEN}`,
{
body: JSON.stringify({
desc: `${dataTransferData.oldUser.name} -> ${userObj.name}\n${dataTransferData.oldUser.id} -> ${userObj.id}\nNO MODMAIL TICKET - WEBSITE FORM SUBMISSION`,
idList: context.env.TRELLO_LIST_ID,
name: `${dataTransferData.oldUser.name} | Data Transfer`,
}),
headers: {
"content-type": "application/json",
},
method: "POST",
},
);
} else {
dataTransferData.oldUser = userObj;
redirectLocation = "/data-transfer/destination-account";
}
return new Response(null, {
headers: {
location: redirectLocation,
},
status: 302,
});
}

View File

@@ -23,7 +23,7 @@ export async function onRequestPost(context: RequestContext) {
await D1.batch([
D1.prepare(
"UPDATE events SET performed_at = CURRENT_TIMESTAMP WHERE id = ?;",
).bind(Date.now(), event.id),
).bind(event.id),
D1.prepare(
"UPDATE et_members SET points = points + 10 WHERE id = ?;",
).bind(event.created_by),

View File

@@ -1,10 +1,12 @@
import { jsonError } from "../../../common.js";
import { getBanList } from "../../../roblox-open-cloud.js";
export async function onRequestPost(context: RequestContext) {
const appealId = context.params.id as string;
const appeal = await context.data.prisma.gameAppeal.findUnique({
select: {
roblox_id: true,
type: true,
},
where: {
id: appealId,
@@ -19,6 +21,18 @@ export async function onRequestPost(context: RequestContext) {
},
});
const { value: banList } = await getBanList(context);
await context.data.prisma.gameModLog.create({
data: {
action: `deny appeal | ${banList[appeal.roblox_id]?.BanType === 2 ? "ban" : appeal.type}`,
evidence: `https://carcrushers.cc/mod-queue?id=${context.params.id}&type=gma`,
executor: context.data.current_user.id,
id: crypto.randomUUID(),
target: appeal.roblox_id,
},
});
await context.env.DATA.put(
`gameappealblock_${appeal.roblox_id}`,
`${Date.now() + 2592000000}`,

View File

@@ -0,0 +1,186 @@
-- CreateTable
CREATE TABLE "appeals" (
"approved" BOOLEAN,
"ban_reason" TEXT NOT NULL,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"id" TEXT NOT NULL PRIMARY KEY,
"learned" TEXT NOT NULL,
"reason_for_unban" TEXT NOT NULL,
"user" JSONB NOT NULL
);
-- CreateTable
CREATE TABLE "appeal_bans" (
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" TEXT NOT NULL,
"user" TEXT NOT NULL PRIMARY KEY
);
-- CreateTable
CREATE TABLE "et_members" (
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" TEXT NOT NULL,
"id" TEXT NOT NULL PRIMARY KEY,
"is_management" BOOLEAN NOT NULL DEFAULT false,
"name" TEXT NOT NULL,
"points" INTEGER NOT NULL DEFAULT 0,
"roblox_id" INTEGER
);
-- CreateTable
CREATE TABLE "et_strikes" (
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" TEXT NOT NULL,
"id" TEXT NOT NULL PRIMARY KEY,
"reason" TEXT NOT NULL,
"user" TEXT NOT NULL
);
-- CreateTable
CREATE TABLE "events" (
"answer" TEXT,
"answered_at" DATETIME,
"approved" BOOLEAN NOT NULL DEFAULT false,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" TEXT NOT NULL,
"day" INTEGER NOT NULL,
"details" TEXT NOT NULL,
"id" TEXT NOT NULL PRIMARY KEY,
"month" INTEGER NOT NULL,
"pending" BOOLEAN NOT NULL DEFAULT true,
"performed_at" DATETIME,
"reached_minimum_player_count" BOOLEAN NOT NULL DEFAULT false,
"type" TEXT NOT NULL,
"year" INTEGER NOT NULL
);
-- CreateTable
CREATE TABLE "game_appeals" (
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"id" TEXT NOT NULL PRIMARY KEY,
"reason_for_unban" TEXT NOT NULL,
"roblox_id" INTEGER NOT NULL,
"roblox_username" TEXT NOT NULL,
"type" TEXT NOT NULL,
"what_happened" TEXT NOT NULL
);
-- CreateTable
CREATE TABLE "game_mod_logs" (
"action" TEXT NOT NULL,
"evidence" TEXT NOT NULL,
"executed_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"executor" TEXT NOT NULL,
"id" TEXT NOT NULL PRIMARY KEY,
"target" INTEGER NOT NULL
);
-- CreateTable
CREATE TABLE "game_mod_notes" (
"content" TEXT NOT NULL,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" TEXT NOT NULL,
"id" TEXT NOT NULL PRIMARY KEY,
"target" INTEGER NOT NULL
);
-- CreateTable
CREATE TABLE "inactivity_notices" (
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"decisions" JSONB NOT NULL,
"departments" JSONB NOT NULL DEFAULT [],
"end" TEXT NOT NULL,
"hiatus" BOOLEAN NOT NULL DEFAULT false,
"id" TEXT NOT NULL PRIMARY KEY,
"reason" TEXT NOT NULL,
"start" TEXT NOT NULL,
"user" JSONB NOT NULL
);
-- CreateTable
CREATE TABLE "push_notifications" (
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"event_id" TEXT NOT NULL,
"event_type" TEXT NOT NULL,
"token" TEXT NOT NULL
);
-- CreateTable
CREATE TABLE "reports" (
"attachments" JSONB NOT NULL DEFAULT [],
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"id" TEXT NOT NULL PRIMARY KEY,
"open" BOOLEAN NOT NULL DEFAULT true,
"target_ids" JSONB NOT NULL DEFAULT [],
"target_usernames" JSONB NOT NULL DEFAULT [],
"type" TEXT NOT NULL DEFAULT 'exploit',
"user" JSONB
);
-- CreateTable
CREATE TABLE "short_links" (
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"destination" TEXT NOT NULL,
"path" TEXT NOT NULL PRIMARY KEY,
"user" TEXT NOT NULL
);
-- CreateIndex
CREATE UNIQUE INDEX "appeals_id_key" ON "appeals"("id");
-- CreateIndex
CREATE INDEX "idx_appeals_approved_created_at" ON "appeals"("approved", "created_at");
-- CreateIndex
CREATE UNIQUE INDEX "appeal_bans_user_key" ON "appeal_bans"("user");
-- CreateIndex
CREATE UNIQUE INDEX "et_members_id_key" ON "et_members"("id");
-- CreateIndex
CREATE INDEX "idx_et_members_id_name" ON "et_members"("id", "name");
-- CreateIndex
CREATE UNIQUE INDEX "et_strikes_id_key" ON "et_strikes"("id");
-- CreateIndex
CREATE UNIQUE INDEX "events_id_key" ON "events"("id");
-- CreateIndex
CREATE INDEX "idx_events_month_year" ON "events"("month", "year");
-- CreateIndex
CREATE UNIQUE INDEX "game_appeals_id_key" ON "game_appeals"("id");
-- CreateIndex
CREATE INDEX "idx_game_appeals_created_at" ON "game_appeals"("created_at");
-- CreateIndex
CREATE UNIQUE INDEX "game_mod_logs_id_key" ON "game_mod_logs"("id");
-- CreateIndex
CREATE INDEX "idx_game_mod_logs_target" ON "game_mod_logs"("target");
-- CreateIndex
CREATE UNIQUE INDEX "game_mod_notes_id_key" ON "game_mod_notes"("id");
-- CreateIndex
CREATE INDEX "idx_game_mod_notes_target" ON "game_mod_notes"("target");
-- CreateIndex
CREATE UNIQUE INDEX "inactivity_notices_id_key" ON "inactivity_notices"("id");
-- CreateIndex
CREATE INDEX "idx_inactivity_notices_end_start" ON "inactivity_notices"("end", "start");
-- CreateIndex
CREATE UNIQUE INDEX "push_notifications_event_id_key" ON "push_notifications"("event_id");
-- CreateIndex
CREATE UNIQUE INDEX "reports_id_key" ON "reports"("id");
-- CreateIndex
CREATE INDEX "idx_reports_created_at_open" ON "reports"("created_at", "open");
-- CreateIndex
CREATE UNIQUE INDEX "short_links_path_key" ON "short_links"("path");

View File

@@ -0,0 +1,15 @@
-- CreateTable
CREATE TABLE "data_requests" (
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"id" TEXT NOT NULL PRIMARY KEY,
"originating_user" INTEGER,
"status" TEXT NOT NULL,
"target_user" INTEGER NOT NULL,
"type" TEXT NOT NULL
);
-- CreateIndex
CREATE UNIQUE INDEX "data_requests_id_key" ON "data_requests"("id");
-- CreateIndex
CREATE INDEX "idx_data_requests_created_at" ON "data_requests"("created_at");

538
package-lock.json generated
View File

@@ -12,13 +12,13 @@
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@fontsource-variable/plus-jakarta-sans": "^5.2.8",
"@prisma/adapter-d1": "^7.7.0",
"@prisma/client": "^7.7.0",
"@prisma/adapter-d1": "^7.8.0",
"@prisma/client": "^7.8.0",
"@remix-run/cloudflare": "^2.17.4",
"@remix-run/cloudflare-pages": "^2.17.4",
"@remix-run/react": "^2.17.4",
"@sentry/cloudflare": "^10.48.0",
"@sentry/remix": "^10.48.0",
"@sentry/cloudflare": "^10.52.0",
"@sentry/remix": "^10.52.0",
"aws4fetch": "^1.0.20",
"dayjs": "^1.11.20",
"framer-motion": "^12.38.0",
@@ -28,13 +28,13 @@
},
"devDependencies": {
"@remix-run/dev": "^2.17.4",
"@types/node": "^24.12.2",
"@types/node": "^24.12.3",
"@types/react": "^18.3.28",
"@types/react-big-calendar": "^1.16.3",
"@types/react-dom": "^18.3.7",
"dotenv": "^17.4.1",
"prettier": "^3.8.2",
"prisma": "^7.7.0",
"prettier": "^3.8.3",
"prisma": "^7.8.0",
"typescript": "^5.9.3"
}
},
@@ -569,9 +569,9 @@
}
},
"node_modules/@cloudflare/workers-types": {
"version": "4.20260329.1",
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260329.1.tgz",
"integrity": "sha512-LxBHrYYI/AZ6OCbUzRqRgg6Rt1qev2KxN2NNd3saye41AO2g52cYvHV+ohts5oPnrIUD7YRjbgN/J3NU7e7m5A==",
"version": "4.20260511.1",
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260511.1.tgz",
"integrity": "sha512-FA+si7cOq9i/gtCHhIc0XJL0l1F/ApF+m00752Aj7WZFJrj3ZulT2T8/+rT3BabMT0QEnqFEGIqCgrmqhgEfMg==",
"license": "MIT OR Apache-2.0"
},
"node_modules/@electric-sql/pglite": {
@@ -1177,9 +1177,9 @@
}
},
"node_modules/@fastify/otel/node_modules/brace-expansion": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
"integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
"version": "5.0.6",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
@@ -1413,22 +1413,10 @@
"node": ">=8.0.0"
}
},
"node_modules/@opentelemetry/context-async-hooks": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.6.1.tgz",
"integrity": "sha512-XHzhwRNkBpeP8Fs/qjGrAf9r9PRv67wkJQ/7ZPaBQQ68DYlTBBx5MF9LvPx7mhuXcDessKK2b+DcxqwpgkcivQ==",
"license": "Apache-2.0",
"engines": {
"node": "^18.19.0 || >=20.6.0"
},
"peerDependencies": {
"@opentelemetry/api": ">=1.0.0 <1.10.0"
}
},
"node_modules/@opentelemetry/core": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.6.1.tgz",
"integrity": "sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g==",
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.7.1.tgz",
"integrity": "sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==",
"license": "Apache-2.0",
"dependencies": {
"@opentelemetry/semantic-conventions": "^1.29.0"
@@ -1588,21 +1576,19 @@
"@opentelemetry/api": "^1.3.0"
}
},
"node_modules/@opentelemetry/instrumentation-ioredis": {
"version": "0.62.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.62.0.tgz",
"integrity": "sha512-ZYt//zcPve8qklaZX+5Z4MkU7UpEkFRrxsf2cnaKYBitqDnsCN69CPAuuMOX6NYdW2rG9sFy7V/QWtBlP5XiNQ==",
"node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/core": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.6.1.tgz",
"integrity": "sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g==",
"license": "Apache-2.0",
"dependencies": {
"@opentelemetry/instrumentation": "^0.214.0",
"@opentelemetry/redis-common": "^0.38.2",
"@opentelemetry/semantic-conventions": "^1.33.0"
"@opentelemetry/semantic-conventions": "^1.29.0"
},
"engines": {
"node": "^18.19.0 || >=20.6.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.3.0"
"@opentelemetry/api": ">=1.0.0 <1.10.0"
}
},
"node_modules/@opentelemetry/instrumentation-kafkajs": {
@@ -1756,23 +1742,6 @@
"@opentelemetry/api": "^1.3.0"
}
},
"node_modules/@opentelemetry/instrumentation-redis": {
"version": "0.62.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.62.0.tgz",
"integrity": "sha512-y3pPpot7WzR/8JtHcYlTYsyY8g+pbFhAqbwAuG5bLPnR6v6pt1rQc0DpH0OlGP/9CZbWBP+Zhwp9yFoygf/ZXQ==",
"license": "Apache-2.0",
"dependencies": {
"@opentelemetry/instrumentation": "^0.214.0",
"@opentelemetry/redis-common": "^0.38.2",
"@opentelemetry/semantic-conventions": "^1.27.0"
},
"engines": {
"node": "^18.19.0 || >=20.6.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.3.0"
}
},
"node_modules/@opentelemetry/instrumentation-tedious": {
"version": "0.33.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.33.0.tgz",
@@ -1790,39 +1759,13 @@
"@opentelemetry/api": "^1.3.0"
}
},
"node_modules/@opentelemetry/instrumentation-undici": {
"version": "0.24.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.24.0.tgz",
"integrity": "sha512-oKzZ3uvqP17sV0EsoQcJgjEfIp0kiZRbYu/eD8p13Cbahumf8lb/xpYeNr/hfAJ4owzEtIDcGIjprfLcYbIKBQ==",
"license": "Apache-2.0",
"dependencies": {
"@opentelemetry/core": "^2.0.0",
"@opentelemetry/instrumentation": "^0.214.0",
"@opentelemetry/semantic-conventions": "^1.24.0"
},
"engines": {
"node": "^18.19.0 || >=20.6.0"
},
"peerDependencies": {
"@opentelemetry/api": "^1.7.0"
}
},
"node_modules/@opentelemetry/redis-common": {
"version": "0.38.2",
"resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz",
"integrity": "sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==",
"license": "Apache-2.0",
"engines": {
"node": "^18.19.0 || >=20.6.0"
}
},
"node_modules/@opentelemetry/resources": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.6.1.tgz",
"integrity": "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA==",
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz",
"integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==",
"license": "Apache-2.0",
"dependencies": {
"@opentelemetry/core": "2.6.1",
"@opentelemetry/core": "2.7.1",
"@opentelemetry/semantic-conventions": "^1.29.0"
},
"engines": {
@@ -1833,13 +1776,13 @@
}
},
"node_modules/@opentelemetry/sdk-trace-base": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.6.1.tgz",
"integrity": "sha512-r86ut4T1e8vNwB35CqCcKd45yzqH6/6Wzvpk2/cZB8PsPLlZFTvrh8yfOS3CYZYcUmAx4hHTZJ8AO8Dj8nrdhw==",
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz",
"integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==",
"license": "Apache-2.0",
"dependencies": {
"@opentelemetry/core": "2.6.1",
"@opentelemetry/resources": "2.6.1",
"@opentelemetry/core": "2.7.1",
"@opentelemetry/resources": "2.7.1",
"@opentelemetry/semantic-conventions": "^1.29.0"
},
"engines": {
@@ -1891,23 +1834,23 @@
}
},
"node_modules/@prisma/adapter-d1": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@prisma/adapter-d1/-/adapter-d1-7.7.0.tgz",
"integrity": "sha512-0+lJsHqm+TXxXdGCCMFouNcJMVE029g6td/vRM7EhWoJYtvakwCzdzJqCQEaGPjCAPi6lzar4DAtEi7z04qjIA==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@prisma/adapter-d1/-/adapter-d1-7.8.0.tgz",
"integrity": "sha512-JLmmuDKnPltHicr8+W0xOt4ozbTlAiaPEDe8YGAJIEgHmflOF7sr4Dsd8d+saRBKOARnODz/yxx+y+QMRm/e/g==",
"license": "Apache-2.0",
"dependencies": {
"@cloudflare/workers-types": "^4.20251014.0",
"@prisma/driver-adapter-utils": "7.7.0",
"@prisma/driver-adapter-utils": "7.8.0",
"ky": "1.7.5"
}
},
"node_modules/@prisma/client": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-7.7.0.tgz",
"integrity": "sha512-5Ar4OsZpJ54s21sy5oDNNW9gQtd4NuxCaiM7+JDTOU07D6VvlpLjYzAVCMB1+JzokN+08dAVomlx+b7bhJd3ww==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-7.8.0.tgz",
"integrity": "sha512-HFp3Dawv/3sU3JtlPha90IB+48lS7zHiH4LKZPjmcE8YH5P9DOXGPvo8dqOtO7MqLDd1p2hOWMcFlRT1DMblHw==",
"license": "Apache-2.0",
"dependencies": {
"@prisma/client-runtime-utils": "7.7.0"
"@prisma/client-runtime-utils": "7.8.0"
},
"engines": {
"node": "^20.19 || ^22.12 || >=24.0"
@@ -1926,28 +1869,28 @@
}
},
"node_modules/@prisma/client-runtime-utils": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@prisma/client-runtime-utils/-/client-runtime-utils-7.7.0.tgz",
"integrity": "sha512-BLyd0UpFYOtyJFTHm7jS9vesHW7P83abibodQMiIofqjBKzDHQ1VAsQkdfvXyYDkPlONPfOTz7/rv3x/+CQqvQ==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@prisma/client-runtime-utils/-/client-runtime-utils-7.8.0.tgz",
"integrity": "sha512-5NQZztQ0oY/ADFkmd9gPuweH5A1/CCY8YQPorLLO0Mu6a87mY5gsnDkzmFmIHs9NFaLnZojzgddFVN4RpKYrdw==",
"license": "Apache-2.0"
},
"node_modules/@prisma/config": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.7.0.tgz",
"integrity": "sha512-hmPI3tKLO2aP0Y5vugbjcnA9qqlfJndiT6ds4tw28U5hNHLWg+mHJEWAhjsSPgxjtmxhJ/EDIeIlyh+3Us0OPg==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.8.0.tgz",
"integrity": "sha512-HFESzd9rx2ZQxlK+TL7tu1HPvCqrHiL6LCxYykI2c34mvaUuIVVl3lYuicJD/MNnzgPnyeBEMlK4WTomJCV5jw==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"c12": "3.1.0",
"c12": "3.3.4",
"deepmerge-ts": "7.1.5",
"effect": "3.20.0",
"empathic": "2.0.0"
}
},
"node_modules/@prisma/debug": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.7.0.tgz",
"integrity": "sha512-12J62XdqCmpiwJHhHdQxZeY3ckVCWIFmcJP8hg5dPTceeiQ0wiojXGFYTluKqFQfu46fRLgb/rLALZMAx3+dTA==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.8.0.tgz",
"integrity": "sha512-p+QZReysDUqXC+mk17q9a+Y/qzh4c2KYliDK30buYUyfrGeTGSyfmc0AIrJRhZJrLHhRiJa9Au/J72h3C+szvA==",
"license": "Apache-2.0"
},
"node_modules/@prisma/dev": {
@@ -1984,65 +1927,65 @@
"license": "MIT"
},
"node_modules/@prisma/driver-adapter-utils": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@prisma/driver-adapter-utils/-/driver-adapter-utils-7.7.0.tgz",
"integrity": "sha512-gZXREeu6mOk7zXfGFJgh86p7Vhj0sXNKp+4Cg1tWYo7V2dfncP2qxS2BiTmbIIha8xPqItkl0WSw38RuSq1HoQ==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@prisma/driver-adapter-utils/-/driver-adapter-utils-7.8.0.tgz",
"integrity": "sha512-/Q13o0ZT0rjc1Xk0Q9KhZYwuq2EW/vSbWUBKfgEKkaCuB/Sg6bqnjmTZqC5cD4d6y1vfFAEwBRzfzoSMIVJ55A==",
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "7.7.0"
"@prisma/debug": "7.8.0"
}
},
"node_modules/@prisma/engines": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.7.0.tgz",
"integrity": "sha512-7fmcbT7HHXBq/b+3h/dO1JI3fd8l8q7erf7xP7pRprh58hmSSnG8mg9K3yjW3h9WaHWUwngVFpSxxxivaitQ2w==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.8.0.tgz",
"integrity": "sha512-jx3rCnNNrt5uzbkKlegtQ2GZHxSlihMCzutgT/BP6UIDF1r9tDI39hV/0T/cHZgzJ3ELbuQPXlVZy+Y1n0pcgw==",
"devOptional": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "7.7.0",
"@prisma/engines-version": "7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711",
"@prisma/fetch-engine": "7.7.0",
"@prisma/get-platform": "7.7.0"
"@prisma/debug": "7.8.0",
"@prisma/engines-version": "7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a",
"@prisma/fetch-engine": "7.8.0",
"@prisma/get-platform": "7.8.0"
}
},
"node_modules/@prisma/engines-version": {
"version": "7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711.tgz",
"integrity": "sha512-r51DLcJ8bDRSrBEJF3J4cinoWyGA7rfP2mG6lD90VqIbGNOkbfcLcXalSVjq5Y6brQS3vcjrq4GbyUb1Cb7vkw==",
"version": "7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a.tgz",
"integrity": "sha512-fJPQxCkLgA5EayWaW8eArgCvjJ+N+Kz3VyeNKMEeYiQC4alNkxRKFVAGxv/ZUzuJISKqdw+zGeDbS6mn6RCPOA==",
"devOptional": true,
"license": "Apache-2.0"
},
"node_modules/@prisma/engines/node_modules/@prisma/get-platform": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.7.0.tgz",
"integrity": "sha512-MEUNzvKxvYnJ7kgvd6oNRnMmmiGNS9TYLB2weMeIXplnHdL/UWEGnvavYGnN7KLJ2n0iI4dDAyzSkHI3c7AscQ==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.8.0.tgz",
"integrity": "sha512-WlxgRGnolL8VH2EmkH1R/DkKNr/mVdS3G2h42IZFFZ3eUrH9OT6t73kIOSlkkrv50wG123Iq8d96ufv5LlZktw==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "7.7.0"
"@prisma/debug": "7.8.0"
}
},
"node_modules/@prisma/fetch-engine": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.7.0.tgz",
"integrity": "sha512-TfyzveBQoK4xALzsTpVhB/0KG1N8zOK0ap+RnBMkzGUu3f98fnQ4QtXa2wlKPhsO2X8a3N5ugFQgcKNoHGmDfw==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.8.0.tgz",
"integrity": "sha512-gwB0Euiz/DDRyxFRpLXYlK3RfaZUj1c5dAYMuhZYfApg7arknJlcb9bIsOHDppJmbqYaVA+yBIiFMDBfprsNPQ==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "7.7.0",
"@prisma/engines-version": "7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711",
"@prisma/get-platform": "7.7.0"
"@prisma/debug": "7.8.0",
"@prisma/engines-version": "7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a",
"@prisma/get-platform": "7.8.0"
}
},
"node_modules/@prisma/fetch-engine/node_modules/@prisma/get-platform": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.7.0.tgz",
"integrity": "sha512-MEUNzvKxvYnJ7kgvd6oNRnMmmiGNS9TYLB2weMeIXplnHdL/UWEGnvavYGnN7KLJ2n0iI4dDAyzSkHI3c7AscQ==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.8.0.tgz",
"integrity": "sha512-WlxgRGnolL8VH2EmkH1R/DkKNr/mVdS3G2h42IZFFZ3eUrH9OT6t73kIOSlkkrv50wG123Iq8d96ufv5LlZktw==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/debug": "7.7.0"
"@prisma/debug": "7.8.0"
}
},
"node_modules/@prisma/get-platform": {
@@ -2960,66 +2903,66 @@
]
},
"node_modules/@sentry-internal/browser-utils": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.48.0.tgz",
"integrity": "sha512-SCiTLBXzugFKxev6NoKYBIhQoDk0gUh0AVVVepCBqfCJiWBG01Zvv0R5tCVohr4cWRllkQ8mlBdNQd/I7s9tdA==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.52.0.tgz",
"integrity": "sha512-x/yEPZdpH6NGQeoeQnV9tj8reAH8twNttiltGZl2o8Rk7sQeUfe7E8yuYP2XbJ2RqyZK5qRS3COrNyMPzf6KFA==",
"license": "MIT",
"dependencies": {
"@sentry/core": "10.48.0"
"@sentry/core": "10.52.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/feedback": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.48.0.tgz",
"integrity": "sha512-tGkEyOM1HDS9qebDphUMEnyk3qq/50AnuTBiFmMJyjNzowylVGmRRk0sr3xkmbVHCDXQCiYnDmSVlJ2x4SDMrQ==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.52.0.tgz",
"integrity": "sha512-5kAn1W8ZvCuHtEHXpq6iRkUMdNCilwww+YxaN2yofVrCivAbB3Ha5JJUMqmWOPW0pC27zGYmoJMIDvG+PczUxA==",
"license": "MIT",
"dependencies": {
"@sentry/core": "10.48.0"
"@sentry/core": "10.52.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.48.0.tgz",
"integrity": "sha512-sevRTePfuk4PNuz9KAKpmTZEomAU0aLXyIhOwA0OnUDdxPhkY8kq5lwDbuxTHv6DQUjUX3YgFbY45VH1JEqHKA==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.52.0.tgz",
"integrity": "sha512-diywyuc/H7VTUR+W5ryVmLF+0X4UP1OskMqb6V8RSAvJHcj2JmIm7uP+Fc6ACTno+b6AUShwT/L4xVXzO6X9Cw==",
"license": "MIT",
"dependencies": {
"@sentry-internal/browser-utils": "10.48.0",
"@sentry/core": "10.48.0"
"@sentry-internal/browser-utils": "10.52.0",
"@sentry/core": "10.52.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay-canvas": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.48.0.tgz",
"integrity": "sha512-9nWuN2z4O+iwbTfuYV5ZmngBgJU/ZxfOo47A5RJP3Nu/kl59aJ1lUhILYOKyeNOIC/JyeERmpIcTxnlPXQzZ3Q==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.52.0.tgz",
"integrity": "sha512-BI5ie4dxPuUJ344CXVSnAxY1xZCbghglPSCIlTOYODpR9so9yo5IZh+Mwspt0oWsUMaxWJiQSNYlbPWi7WDavg==",
"license": "MIT",
"dependencies": {
"@sentry-internal/replay": "10.48.0",
"@sentry/core": "10.48.0"
"@sentry-internal/replay": "10.52.0",
"@sentry/core": "10.52.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/browser": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.48.0.tgz",
"integrity": "sha512-4jt2zX2ExgFcNe2x+W+/k81fmDUsOrquGtt028CiGuDuma6kEsWBI4JbooT1jhj2T+eeUxe3YGbM23Zhh7Ghhw==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.52.0.tgz",
"integrity": "sha512-ijL9jN86oXwXQWbwhPlEb70ODJSEmjxQEQdnZkC4gDWbjswcwvRsVJPYk+1xl2ir2iZixRIHipVxDcLwian35g==",
"license": "MIT",
"dependencies": {
"@sentry-internal/browser-utils": "10.48.0",
"@sentry-internal/feedback": "10.48.0",
"@sentry-internal/replay": "10.48.0",
"@sentry-internal/replay-canvas": "10.48.0",
"@sentry/core": "10.48.0"
"@sentry-internal/browser-utils": "10.52.0",
"@sentry-internal/feedback": "10.52.0",
"@sentry-internal/replay": "10.52.0",
"@sentry-internal/replay-canvas": "10.52.0",
"@sentry/core": "10.52.0"
},
"engines": {
"node": ">=18"
@@ -3206,13 +3149,13 @@
}
},
"node_modules/@sentry/cloudflare": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry/cloudflare/-/cloudflare-10.48.0.tgz",
"integrity": "sha512-i02Ps4/cJjFpbcHLMhNEFXTeVqLB9XpB3+/OFQ9aMFV3yDcxlvHwe0oo7WZf41iroArvpysotLG8Y8NBOU9omA==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry/cloudflare/-/cloudflare-10.52.0.tgz",
"integrity": "sha512-NhFpR0OKd7gZDuJWJd8C0jC6WhA+R+m1OGp0ul2ItwIASTzGMw6gGLo0XuQjC6GfuodNAGbCF1bQN3Zi3nV1Lg==",
"license": "MIT",
"dependencies": {
"@opentelemetry/api": "^1.9.1",
"@sentry/core": "10.48.0"
"@sentry/core": "10.52.0"
},
"engines": {
"node": ">=18"
@@ -3227,23 +3170,22 @@
}
},
"node_modules/@sentry/core": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.48.0.tgz",
"integrity": "sha512-h8F+fXVwYC9ro5ZaO8V+v3vqc0awlXHGblEAuVxSGgh4IV/oFX+QVzXeDTTrFOFS6v/Vn5vAyu240eJrJAS6/g==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.52.0.tgz",
"integrity": "sha512-VA/kAqLhkMnRWY2RXdBLyTemR9D4m7MVRy/gyapoq9yvllVPx9WXbvKgnMP2LQp7mFgT/oLFvw58aQKaYTGn3A==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/node": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.48.0.tgz",
"integrity": "sha512-MzyLJyYmr0Qg60K6NJ2EdwJUX1OuAYXs9tyYxnqVO3nJ8MyYwIcuN4FCYEnXkG6Jiy/4q7OuZgXWnfdQJVcaqw==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.52.0.tgz",
"integrity": "sha512-9+p3KJUk3rHO1HOEZuSknP2RgKCJZONDm4HWgkVDtVBtocb66KLtVlMjc59d2/bWP7tM3wc877tpG30quFfU9g==",
"license": "MIT",
"dependencies": {
"@fastify/otel": "0.18.0",
"@opentelemetry/api": "^1.9.1",
"@opentelemetry/context-async-hooks": "^2.6.1",
"@opentelemetry/core": "^2.6.1",
"@opentelemetry/instrumentation": "^0.214.0",
"@opentelemetry/instrumentation-amqplib": "0.61.0",
@@ -3254,7 +3196,6 @@
"@opentelemetry/instrumentation-graphql": "0.62.0",
"@opentelemetry/instrumentation-hapi": "0.60.0",
"@opentelemetry/instrumentation-http": "0.214.0",
"@opentelemetry/instrumentation-ioredis": "0.62.0",
"@opentelemetry/instrumentation-kafkajs": "0.23.0",
"@opentelemetry/instrumentation-knex": "0.58.0",
"@opentelemetry/instrumentation-koa": "0.62.0",
@@ -3264,16 +3205,13 @@
"@opentelemetry/instrumentation-mysql": "0.60.0",
"@opentelemetry/instrumentation-mysql2": "0.60.0",
"@opentelemetry/instrumentation-pg": "0.66.0",
"@opentelemetry/instrumentation-redis": "0.62.0",
"@opentelemetry/instrumentation-tedious": "0.33.0",
"@opentelemetry/instrumentation-undici": "0.24.0",
"@opentelemetry/resources": "^2.6.1",
"@opentelemetry/sdk-trace-base": "^2.6.1",
"@opentelemetry/semantic-conventions": "^1.40.0",
"@prisma/instrumentation": "7.6.0",
"@sentry/core": "10.48.0",
"@sentry/node-core": "10.48.0",
"@sentry/opentelemetry": "10.48.0",
"@sentry/core": "10.52.0",
"@sentry/node-core": "10.52.0",
"@sentry/opentelemetry": "10.52.0",
"import-in-the-middle": "^3.0.0"
},
"engines": {
@@ -3281,13 +3219,13 @@
}
},
"node_modules/@sentry/node-core": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.48.0.tgz",
"integrity": "sha512-D1TnPhN6vhrRqJ+bN+rdXDM+INibI6lNBm0eGx45zz7DBx9ouq2e9gm/DPx+y/hAkYYq0qTd6x84cGxtVZbKLw==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.52.0.tgz",
"integrity": "sha512-IG7MBtLRPQ2LuU+kbD14AFZroZgAeUmJQTP1FI/F8n56O31+p+9R703LuBTpvZr6sm+eRYDMWcGYYkfLHRVjwg==",
"license": "MIT",
"dependencies": {
"@sentry/core": "10.48.0",
"@sentry/opentelemetry": "10.48.0",
"@sentry/core": "10.52.0",
"@sentry/opentelemetry": "10.52.0",
"import-in-the-middle": "^3.0.0"
},
"engines": {
@@ -3295,11 +3233,9 @@
},
"peerDependencies": {
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0",
"@opentelemetry/core": "^1.30.1 || ^2.1.0",
"@opentelemetry/exporter-trace-otlp-http": ">=0.57.0 <1",
"@opentelemetry/instrumentation": ">=0.57.1 <1",
"@opentelemetry/resources": "^1.30.1 || ^2.1.0",
"@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0",
"@opentelemetry/semantic-conventions": "^1.39.0"
},
@@ -3307,9 +3243,6 @@
"@opentelemetry/api": {
"optional": true
},
"@opentelemetry/context-async-hooks": {
"optional": true
},
"@opentelemetry/core": {
"optional": true
},
@@ -3319,9 +3252,6 @@
"@opentelemetry/instrumentation": {
"optional": true
},
"@opentelemetry/resources": {
"optional": true
},
"@opentelemetry/sdk-trace-base": {
"optional": true
},
@@ -3331,32 +3261,31 @@
}
},
"node_modules/@sentry/opentelemetry": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.48.0.tgz",
"integrity": "sha512-Tn6Y0PZjRJ7OW8loK1ntK7wnJnIINnCfSpnwuqow0FMblaDmu5jDVOYq0U1SJBoBcMD5j9aSqrwyj6zqKwjc0A==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.52.0.tgz",
"integrity": "sha512-Sc7StsvC0bwhMcgDfTRWUIexO5cNzzKUurvUwtpgQUnxO7AzexU3lkY3yHYDsCbWYAEQMXAgQYQtbcqoh+Ie7g==",
"license": "MIT",
"dependencies": {
"@sentry/core": "10.48.0"
"@sentry/core": "10.52.0"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0",
"@opentelemetry/core": "^1.30.1 || ^2.1.0",
"@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0",
"@opentelemetry/semantic-conventions": "^1.39.0"
}
},
"node_modules/@sentry/react": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.48.0.tgz",
"integrity": "sha512-uc93vKjmu6gNns+JAX4qquuxWpAMit0uGPA1TYlMjct9NG1uX3TkDPJAr9Pgd1lOXx8mKqCmj5fK33QeExMpPw==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.52.0.tgz",
"integrity": "sha512-2m72QCsja2cJJHD0ALxRnVt0qMEC2FV4LSi6AAiEdEG4lTb6mgcxavx5pJrW90jE+6dMGPbUz4q8c9vi4jh1qQ==",
"license": "MIT",
"dependencies": {
"@sentry/browser": "10.48.0",
"@sentry/core": "10.48.0"
"@sentry/browser": "10.52.0",
"@sentry/core": "10.52.0"
},
"engines": {
"node": ">=18"
@@ -3366,9 +3295,9 @@
}
},
"node_modules/@sentry/remix": {
"version": "10.48.0",
"resolved": "https://registry.npmjs.org/@sentry/remix/-/remix-10.48.0.tgz",
"integrity": "sha512-ToJ1j9x0tHNM78UrdbjMDNL31nvbRUDdE2rTfeUEt7cQUo7vio68mmqrdnrIo0j6g5rwewWPXkNP+ENBeuzLOQ==",
"version": "10.52.0",
"resolved": "https://registry.npmjs.org/@sentry/remix/-/remix-10.52.0.tgz",
"integrity": "sha512-k6WguxtHupGKDlYW49kJAi7gWUt7uEWP3EpJ2hzdpIZwARcU4Mv5aCZm0tgtQs5O9c+Gq9EJsr+ASoDgM39Lng==",
"license": "MIT",
"dependencies": {
"@opentelemetry/api": "^1.9.1",
@@ -3376,9 +3305,9 @@
"@opentelemetry/semantic-conventions": "^1.40.0",
"@remix-run/router": "^1.23.2",
"@sentry/cli": "^2.58.5",
"@sentry/core": "10.48.0",
"@sentry/node": "10.48.0",
"@sentry/react": "10.48.0",
"@sentry/core": "10.52.0",
"@sentry/node": "10.52.0",
"@sentry/react": "10.52.0",
"yargs": "^17.6.0"
},
"bin": {
@@ -3495,9 +3424,9 @@
}
},
"node_modules/@types/node": {
"version": "24.12.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz",
"integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
"version": "24.12.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.3.tgz",
"integrity": "sha512-8oljBDGun9cIsZRJR6fkihn0TSXJI0UDOOhncYaERq6M0JMDoPLxyscwruJcb4GKS6dvK/d8xebYBg27h/duaQ==",
"license": "MIT",
"dependencies": {
"undici-types": "~7.16.0"
@@ -4082,27 +4011,27 @@
}
},
"node_modules/c12": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz",
"integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==",
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/c12/-/c12-3.3.4.tgz",
"integrity": "sha512-cM0ApFQSBXuourJejzwv/AuPRvAxordTyParRVcHjjtXirtkzM0uK2L9TTn9s0cXZbG7E55jCivRQzoxYmRAlA==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"chokidar": "^4.0.3",
"confbox": "^0.2.2",
"defu": "^6.1.4",
"dotenv": "^16.6.1",
"exsolve": "^1.0.7",
"giget": "^2.0.0",
"jiti": "^2.4.2",
"chokidar": "^5.0.0",
"confbox": "^0.2.4",
"defu": "^6.1.6",
"dotenv": "^17.3.1",
"exsolve": "^1.0.8",
"giget": "^3.2.0",
"jiti": "^2.6.1",
"ohash": "^2.0.11",
"pathe": "^2.0.3",
"perfect-debounce": "^1.0.0",
"pkg-types": "^2.2.0",
"rc9": "^2.1.2"
"perfect-debounce": "^2.1.0",
"pkg-types": "^2.3.0",
"rc9": "^3.0.1"
},
"peerDependencies": {
"magicast": "^0.3.5"
"magicast": "*"
},
"peerDependenciesMeta": {
"magicast": {
@@ -4111,34 +4040,21 @@
}
},
"node_modules/c12/node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz",
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
"readdirp": "^5.0.0"
},
"engines": {
"node": ">= 14.16.0"
"node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/c12/node_modules/dotenv": {
"version": "16.6.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
"devOptional": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/c12/node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
@@ -4147,13 +4063,13 @@
"license": "MIT"
},
"node_modules/c12/node_modules/readdirp": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz",
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">= 14.18.0"
"node": ">= 20.19.0"
},
"funding": {
"type": "individual",
@@ -4369,16 +4285,6 @@
"node": ">=10"
}
},
"node_modules/citty": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz",
"integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"consola": "^3.2.3"
}
},
"node_modules/cjs-module-lexer": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz",
@@ -4534,16 +4440,6 @@
"devOptional": true,
"license": "MIT"
},
"node_modules/consola": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz",
"integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
"devOptional": true,
"license": "MIT",
"engines": {
"node": "^14.18.0 || >=16.10.0"
}
},
"node_modules/content-disposition": {
"version": "0.5.4",
"dev": true,
@@ -4838,7 +4734,7 @@
"version": "17.4.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.1.tgz",
"integrity": "sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==",
"dev": true,
"devOptional": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
@@ -5701,30 +5597,15 @@
}
},
"node_modules/giget": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz",
"integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/giget/-/giget-3.2.0.tgz",
"integrity": "sha512-GvHTWcykIR/fP8cj8dMpuMMkvaeJfPvYnhq0oW+chSeIr+ldX21ifU2Ms6KBoyKZQZmVaUAAhQ2EZ68KJF8a7A==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"citty": "^0.1.6",
"consola": "^3.4.0",
"defu": "^6.1.4",
"node-fetch-native": "^1.6.6",
"nypm": "^0.6.0",
"pathe": "^2.0.3"
},
"bin": {
"giget": "dist/cli.mjs"
}
},
"node_modules/giget/node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
"devOptional": true,
"license": "MIT"
},
"node_modules/glob": {
"version": "10.5.0",
"dev": true,
@@ -6374,9 +6255,9 @@
"license": "MIT"
},
"node_modules/jiti": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
"integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
"devOptional": true,
"license": "MIT",
"bin": {
@@ -7819,13 +7700,6 @@
}
}
},
"node_modules/node-fetch-native": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz",
"integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==",
"devOptional": true,
"license": "MIT"
},
"node_modules/node-releases": {
"version": "2.0.27",
"dev": true,
@@ -7911,38 +7785,6 @@
"node": ">=8"
}
},
"node_modules/nypm": {
"version": "0.6.5",
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.5.tgz",
"integrity": "sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"citty": "^0.2.0",
"pathe": "^2.0.3",
"tinyexec": "^1.0.2"
},
"bin": {
"nypm": "dist/cli.mjs"
},
"engines": {
"node": ">=18"
}
},
"node_modules/nypm/node_modules/citty": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/citty/-/citty-0.2.2.tgz",
"integrity": "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==",
"devOptional": true,
"license": "MIT"
},
"node_modules/nypm/node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
"devOptional": true,
"license": "MIT"
},
"node_modules/object-assign": {
"version": "4.1.1",
"license": "MIT",
@@ -8231,9 +8073,9 @@
}
},
"node_modules/perfect-debounce": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz",
"integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==",
"devOptional": true,
"license": "MIT"
},
@@ -8556,9 +8398,9 @@
}
},
"node_modules/prettier": {
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.2.tgz",
"integrity": "sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==",
"version": "3.8.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
"integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
"dev": true,
"license": "MIT",
"bin": {
@@ -8586,16 +8428,16 @@
}
},
"node_modules/prisma": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-7.7.0.tgz",
"integrity": "sha512-HlgwRBt1uEFB9LStHL4HLYDvoi4BNu1rYA0hPG0zCAEyK9SaZBqp7E5Rjpc3Qh8Lex/ye/svoHZ0OWoFNhWxuQ==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-7.8.0.tgz",
"integrity": "sha512-yfN4yrw7HV9kEJhoy1+jgah0jafEIQsf7uWouSsM8MvJtlubsk+kM7AIBWZ8+GJl74Yj3c+nbYqBkMOxtsZ3Lw==",
"devOptional": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@prisma/config": "7.7.0",
"@prisma/config": "7.8.0",
"@prisma/dev": "0.24.3",
"@prisma/engines": "7.7.0",
"@prisma/engines": "7.8.0",
"@prisma/studio-core": "0.27.3",
"mysql2": "3.15.3",
"postgres": "3.4.7"
@@ -8794,14 +8636,14 @@
}
},
"node_modules/rc9": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz",
"integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/rc9/-/rc9-3.0.1.tgz",
"integrity": "sha512-gMDyleLWVE+i6Sgtc0QbbY6pEKqYs97NGi6isHQPqYlLemPoO8dxQ3uGi0f4NiP98c+jMW6cG1Kx9dDwfvqARQ==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"defu": "^6.1.4",
"destr": "^2.0.3"
"defu": "^6.1.6",
"destr": "^2.0.5"
}
},
"node_modules/react": {
@@ -9920,16 +9762,6 @@
"safe-buffer": "~5.1.0"
}
},
"node_modules/tinyexec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz",
"integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==",
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"dev": true,

View File

@@ -14,13 +14,13 @@
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@fontsource-variable/plus-jakarta-sans": "^5.2.8",
"@prisma/adapter-d1": "^7.7.0",
"@prisma/client": "^7.7.0",
"@prisma/adapter-d1": "^7.8.0",
"@prisma/client": "^7.8.0",
"@remix-run/cloudflare": "^2.17.4",
"@remix-run/cloudflare-pages": "^2.17.4",
"@remix-run/react": "^2.17.4",
"@sentry/cloudflare": "^10.48.0",
"@sentry/remix": "^10.48.0",
"@sentry/cloudflare": "^10.52.0",
"@sentry/remix": "^10.52.0",
"aws4fetch": "^1.0.20",
"dayjs": "^1.11.20",
"framer-motion": "^12.38.0",
@@ -30,17 +30,17 @@
},
"devDependencies": {
"@remix-run/dev": "^2.17.4",
"@types/node": "^24.12.2",
"@types/node": "^24.12.3",
"@types/react": "^18.3.28",
"@types/react-big-calendar": "^1.16.3",
"@types/react-dom": "^18.3.7",
"dotenv": "^17.4.1",
"prettier": "^3.8.2",
"prisma": "^7.7.0",
"prettier": "^3.8.3",
"prisma": "^7.8.0",
"typescript": "^5.9.3"
},
"overrides": {
"@cloudflare/workers-types": "^4.20260329.1"
"@cloudflare/workers-types": "^4.20260511.1"
},
"prettier": {
"endOfLine": "auto"

View File

@@ -29,6 +29,18 @@ model AppealBan {
@@map("appeal_bans")
}
model DataRequest {
created_at DateTime @default(now())
id String @id @unique
originating_user Int?
status String
target_user Int
type String
@@index([created_at], name: "idx_data_requests_created_at")
@@map("data_requests")
}
model EtMember {
created_at DateTime @default(now())
created_by String