diff --git a/README.md b/README.md
index 78acdc68..073e7887 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@ Two Next.js sites share one Postgres database and four internal packages. Club m
| --- | --- | --- |
| `sites/mainweb` | `web` | Public club site + authenticated portal (App Hosting) |
| `sites/hacklytics2027` | `hacklytics2027` | Hacklytics 2027 marketing site, static export (Firebase Hosting) |
+| `apps/dsgt-slack` | `@query/dsgt-slack` | `@dsgt` Slack bot (HTTP webhook on mainweb in production) |
| `packages/api` | `@query/api` | tRPC routers, middleware, pricing |
| `packages/auth` | `@query/auth` | NextAuth (Google, GitHub, email codes) |
| `packages/db` | `@query/db` | Drizzle schema, client, membership rules |
diff --git a/apphosting.yaml b/apphosting.yaml
index b987633f..0055fee0 100644
--- a/apphosting.yaml
+++ b/apphosting.yaml
@@ -57,6 +57,19 @@ env:
secret: projects/672446353769/secrets/NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
- variable: STRIPE_WEBHOOK_SECRET
secret: projects/672446353769/secrets/STRIPE_WEBHOOK_SECRET
+ # Slack Events API for @dsgt (HTTP, not Socket Mode). Create these secrets
+ # once before the deploy that references them, or App Hosting cannot start:
+ # gcloud secrets create SLACK_BOT_TOKEN --project=dsgt-website
+ # gcloud secrets create SLACK_SIGNING_SECRET --project=dsgt-website
+ # firebase apphosting:secrets:grantaccess SLACK_BOT_TOKEN --backend query
+ # firebase apphosting:secrets:grantaccess SLACK_SIGNING_SECRET --backend query
+ # Steps and Request URL: apps/dsgt-slack/README.md
+ - variable: SLACK_BOT_TOKEN
+ secret: projects/672446353769/secrets/SLACK_BOT_TOKEN
+ - variable: SLACK_SIGNING_SECRET
+ secret: projects/672446353769/secrets/SLACK_SIGNING_SECRET
+ - variable: SLACK_SOCKET_MODE
+ value: "false"
- variable: NODE_ENV
value: production
# Consumer Gmail, which caps around 500 recipients a day — shared between
diff --git a/apps/dsgt-slack/.env.example b/apps/dsgt-slack/.env.example
new file mode 100644
index 00000000..a6ccd24a
--- /dev/null
+++ b/apps/dsgt-slack/.env.example
@@ -0,0 +1,22 @@
+# Copy to .env and fill in values from https://api.slack.com/apps
+# Never commit .env or real tokens.
+
+# Bot User OAuth Token (xoxb-...) from OAuth & Permissions after install
+SLACK_BOT_TOKEN=xoxb-your-bot-token
+
+# Signing Secret from Basic Information
+SLACK_SIGNING_SECRET=your-signing-secret
+
+# App-level token (xapp-...) from Basic Information → App-Level Tokens
+# Required only for local Socket Mode. Create a token with the connections:write
+# scope. Not used in production (HTTP Events API on Firebase App Hosting).
+SLACK_APP_TOKEN=xapp-your-app-token
+
+# Local default is Socket Mode. Production App Hosting sets this to false.
+# SLACK_APP_TOKEN is not required when this is false.
+SLACK_SOCKET_MODE=true
+
+# Used only when running this package's local HTTP receiver
+# (SLACK_SOCKET_MODE=false). Production Request URL is the App Hosting
+# origin (AUTH_URL, host datasciencegt.org) plus /api/webhooks/slack.
+PORT=3000
diff --git a/apps/dsgt-slack/README.md b/apps/dsgt-slack/README.md
new file mode 100644
index 00000000..ed56d007
--- /dev/null
+++ b/apps/dsgt-slack/README.md
@@ -0,0 +1,209 @@
+# dsgt Slack bot
+
+Bolt for JavaScript app for **Data Science @ Georgia Tech (DS@GT)**. In Slack it
+appears as **@dsgt**. This is a custom Slack app owned by the club, not a
+third-party Slack integration.
+
+The bot answers `@dsgt` mentions, direct messages, and the `/dsgt` slash
+command. It can confirm that it is online (`ping`) and tell people how to join:
+the first event is **August 26 (8/26)**, further details will be announced
+there, and the club site is datasciencegt.org.
+
+Production traffic is **HTTP Events API** on the existing Firebase App Hosting
+backend (`sites/mainweb` / Cloud Run). There is no second Cloud Run service and
+no Socket Mode process in production.
+
+## Grok Bot (the LLM / MCP teammate)
+
+This Firebase app is **not** Grok Bot. It is a small FAQ process: help, ping,
+and the August 26 join answer. It cannot use your Grok Bot computer, Google
+connectors, or MCP tools.
+
+If club Slack should talk to **your Grok Bot** (the Yodo pattern: people DM
+`@dsgt`, and the teammate uses Slack, Drive, Slides, Forms, Gmail), do that in
+the Grok Bot app, not here:
+
+1. Open Grok Bot and open the teammate you want as `@dsgt`.
+2. Connect **Slack** to the **DS@GT club workspace** (not Campus Leads).
+3. When Slack asks to install the app, click **Allow** as a workspace admin.
+4. Add Google Workspace connectors there (Drive / Slides / Forms). MCP for
+ those products lives on Grok Bot.
+5. Name the Slack bot user `dsgt` so it matches the club identity.
+
+You can keep this FAQ webhook as a fallback, or skip installing it if Grok Bot
+is the only `@dsgt` in the workspace. Do not run both against the same bot
+tokens or they will fight over events.
+
+## Create the Slack app from the manifest
+
+1. Open [https://api.slack.com/apps](https://api.slack.com/apps) and sign in to
+ the workspace that should host the bot (typically the DS@GT Slack).
+2. Click **Create New App** → **From an app manifest**.
+3. Select the workspace, then paste the contents of
+ [`manifest.yaml`](./manifest.yaml) (YAML is accepted).
+4. Confirm the summary. The app name and bot user display name should both be
+ `dsgt`. Socket Mode should be **off**. The manifest does **not** declare
+ Event Subscriptions, Interactivity, or `/dsgt` — Slack rejects those without
+ a Request URL or Socket Mode (`invalid_manifest`). You can add them in the
+ app settings after `{AUTH_URL}/api/webhooks/slack` is live.
+5. Click **Create**.
+
+You now have a real Slack app whose bot user is **dsgt**.
+
+## Install into a workspace and collect tokens
+
+1. In the app settings sidebar, open **OAuth & Permissions** and click
+ **Install to Workspace**. Approve the requested bot scopes.
+2. Copy the **Bot User OAuth Token** (`xoxb-...`). You will put this in GCP
+ Secret Manager as `SLACK_BOT_TOKEN` (and in `apps/dsgt-slack/.env` only if
+ you run the bot locally).
+3. Open **Basic Information** and copy the **Signing Secret**. That is
+ `SLACK_SIGNING_SECRET`.
+
+Do **not** commit `.env`, tokens, or signing secrets. `SLACK_APP_TOKEN` is not
+required in production.
+
+## Production Request URL (Firebase App Hosting)
+
+Slack must POST to the **Firebase App Hosting / Cloud Run** URL for `sites/mainweb`
+(workspace `web`). That origin is `{AUTH_URL}` — the same public
+origin as `AUTH_URL` / `NEXTAUTH_URL` in [`apphosting.yaml`](../../apphosting.yaml).
+
+**Use this Request URL everywhere** (Event Subscriptions, Slash Commands
+`/dsgt`, Interactivity & Shortcuts). Take the `AUTH_URL` / `NEXTAUTH_URL`
+value from [`apphosting.yaml`](../../apphosting.yaml) (the App Hosting origin
+for the club site, host `datasciencegt.org`) and append the path:
+
+```text
+{AUTH_URL}/api/webhooks/slack
+```
+
+Set those three URLs in the Slack app settings **after** the App Hosting
+deploy that includes this route is live (Event Subscriptions, Slash Commands
+`/dsgt`, Interactivity). They are not in `manifest.yaml` because Slack will
+not create the app with those features unless a Request URL or Socket Mode is
+set. Slack will POST a `url_verification` challenge; the Next.js route
+answers it.
+
+The Next.js route is
+`sites/mainweb/app/(portal)/api/webhooks/stripe`’s neighbor:
+`sites/mainweb/app/(portal)/api/webhooks/slack/route.ts`. `proxy.ts` already
+leaves `/api/webhooks/*` alone, same as Stripe.
+
+### App Hosting vs Firebase Hosting
+
+| Surface | What it is | Slack |
+| --- | --- | --- |
+| **Firebase App Hosting** | Next.js on Cloud Run, `apphosting.yaml`, `sites/mainweb` | **Yes — this is the API** |
+| **Firebase Hosting** site `dsgt-website` | Static `sites/mainweb/out/` | **No.** That site cannot run the webhook |
+
+If Event Subscriptions shows a verification failure, the Request URL is almost
+certainly pointing at Hosting `out/` (or the wrong host), not App Hosting.
+
+After the App Hosting deploy that includes this route is live, open **Event
+Subscriptions** and click **Retry** / save so Slack can complete the
+`url_verification` challenge.
+
+Reinstall the app if Slack asks you to after changing URLs or scopes.
+
+## Secret Manager (one-time)
+
+GCP project: `dsgt-website` (number `672446353769`). App Hosting backend name:
+`query`. [`apphosting.yaml`](../../apphosting.yaml) maps:
+
+| Process env | Secret |
+| --- | --- |
+| `SLACK_BOT_TOKEN` | `projects/672446353769/secrets/SLACK_BOT_TOKEN` |
+| `SLACK_SIGNING_SECRET` | `projects/672446353769/secrets/SLACK_SIGNING_SECRET` |
+| `SLACK_SOCKET_MODE` | literal `false` (not a secret) |
+
+`SLACK_APP_TOKEN` is **not** wired. Create the secrets before the deploy that
+references them, or App Hosting will fail to start:
+
+```bash
+gcloud config set project dsgt-website
+
+# Create empty secrets, then add a version from stdin (do not put tokens in the
+# shell history file if you can avoid it — prefer a local file you delete).
+gcloud secrets create SLACK_BOT_TOKEN --project=dsgt-website
+gcloud secrets create SLACK_SIGNING_SECRET --project=dsgt-website
+
+printf '%s' 'xoxb-your-bot-token' | gcloud secrets versions add SLACK_BOT_TOKEN --data-file=-
+printf '%s' 'your-signing-secret' | gcloud secrets versions add SLACK_SIGNING_SECRET --data-file=-
+
+firebase apphosting:secrets:grantaccess SLACK_BOT_TOKEN --backend query
+firebase apphosting:secrets:grantaccess SLACK_SIGNING_SECRET --backend query
+```
+
+Replace the `printf` placeholders with the real values from the Slack app
+settings. Never commit those values.
+
+## Run locally (Socket Mode)
+
+Socket Mode is a **local-only** option so you can develop without a public URL.
+Production stays on HTTP.
+
+1. In the Slack app settings, turn **Socket Mode** on temporarily (or use a
+ separate development app). Generate an App-Level Token with
+ `connections:write` (`xapp-...`).
+2. From the monorepo root:
+
+```bash
+cp apps/dsgt-slack/.env.example apps/dsgt-slack/.env
+# edit apps/dsgt-slack/.env with SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET,
+# SLACK_APP_TOKEN, and SLACK_SOCKET_MODE=true
+
+pnpm install
+pnpm --filter @query/dsgt-slack dev
+```
+
+`pnpm dev` at the repo root also starts this package. If `.env` is missing, the
+task stays idle so the rest of the monorepo can still boot.
+
+You can also hit the Next.js webhook locally while `web` is running
+(`http://localhost:3001/api/webhooks/slack`) if you tunnel that URL to Slack.
+That path is what production uses.
+
+### Invite @dsgt to a channel
+
+In the channel:
+
+```text
+/invite @dsgt
+```
+
+Then mention it (`@dsgt ping`) or run `/dsgt help`. Direct messages work from
+the app's **Messages** tab without an invite.
+
+### Quick checks after install
+
+| Action | Expected reply |
+| ----------------------------------------- | ----------------------------------------------- |
+| `@dsgt ping` or `/dsgt ping` | Health check confirming the bot is online |
+| `/dsgt help` | List of topics |
+| “How do I join?” in a DM, or `/dsgt join` | August 26 first-event FAQ and datasciencegt.org |
+
+## Scripts
+
+| Script | Command |
+| --- | --- |
+| Dev (watch) | `pnpm --filter @query/dsgt-slack dev` |
+| Start | `pnpm --filter @query/dsgt-slack start` |
+| Lint | `pnpm --filter @query/dsgt-slack lint` |
+| Typecheck | `pnpm --filter @query/dsgt-slack typecheck` |
+| Test | `pnpm --filter @query/dsgt-slack test` |
+
+Repo-wide `pnpm lint`, `pnpm typecheck`, `pnpm build`, and `pnpm test` include
+this package (`pnpm test` runs the join-FAQ unit test along with the existing
+vitest targets).
+
+## Environment
+
+See [`.env.example`](./.env.example). Do not commit `.env` or real tokens.
+
+| Variable | Local Socket Mode | Production (App Hosting) |
+| --- | --- | --- |
+| `SLACK_BOT_TOKEN` | required | Secret Manager |
+| `SLACK_SIGNING_SECRET` | required | Secret Manager |
+| `SLACK_APP_TOKEN` | required | not used |
+| `SLACK_SOCKET_MODE` | `true` (default) | `false` |
diff --git a/apps/dsgt-slack/eslint.config.mjs b/apps/dsgt-slack/eslint.config.mjs
new file mode 100644
index 00000000..286e0415
--- /dev/null
+++ b/apps/dsgt-slack/eslint.config.mjs
@@ -0,0 +1,12 @@
+import { config } from "@query/eslint-config/base";
+
+/** @type {import("eslint").Linter.Config[]} */
+export default [
+ ...config,
+ {
+ files: ["src/index.ts"],
+ rules: {
+ "no-console": "off",
+ },
+ },
+];
diff --git a/apps/dsgt-slack/manifest.yaml b/apps/dsgt-slack/manifest.yaml
new file mode 100644
index 00000000..62ffdeea
--- /dev/null
+++ b/apps/dsgt-slack/manifest.yaml
@@ -0,0 +1,29 @@
+_metadata:
+ major_version: 1
+ minor_version: 1
+display_information:
+ name: dsgt
+ description: Official Slack bot for Data Science @ Georgia Tech (DS@GT).
+ background_color: "#003057"
+features:
+ app_home:
+ home_tab_enabled: false
+ messages_tab_enabled: true
+ messages_tab_read_only_enabled: false
+ bot_user:
+ display_name: dsgt
+ always_online: true
+oauth_config:
+ scopes:
+ bot:
+ - app_mentions:read
+ - chat:write
+ - chat:write.public
+ - commands
+ - im:history
+ - im:read
+ - im:write
+settings:
+ org_deploy_enabled: false
+ socket_mode_enabled: false
+ token_rotation_enabled: false
diff --git a/apps/dsgt-slack/package.json b/apps/dsgt-slack/package.json
new file mode 100644
index 00000000..14a35b1f
--- /dev/null
+++ b/apps/dsgt-slack/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "@query/dsgt-slack",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "exports": {
+ ".": "./src/replies.ts",
+ "./replies": "./src/replies.ts",
+ "./http": "./src/http.ts"
+ },
+ "scripts": {
+ "dev": "tsx watch src/index.ts",
+ "start": "tsx src/index.ts",
+ "build": "tsc --noEmit",
+ "lint": "eslint . --max-warnings 0",
+ "typecheck": "tsc --noEmit",
+ "test": "vitest run --config vitest.config.ts"
+ },
+ "dependencies": {
+ "@slack/bolt": "^5.0.0",
+ "@slack/web-api": "^7.13.0",
+ "dotenv": "^16.6.1",
+ "undici": "^6.27.0",
+ "zod": "3.25.53"
+ },
+ "devDependencies": {
+ "@query/eslint-config": "workspace:*",
+ "@query/tsconfig": "workspace:*",
+ "@types/express": "^5.0.0",
+ "@types/node": "^22.15.32",
+ "eslint": "10.1.0",
+ "tsx": "^4.21.0",
+ "typescript": "6.0.2",
+ "vitest": "^4.1.10"
+ }
+}
diff --git a/apps/dsgt-slack/src/app.ts b/apps/dsgt-slack/src/app.ts
new file mode 100644
index 00000000..2ff58ab6
--- /dev/null
+++ b/apps/dsgt-slack/src/app.ts
@@ -0,0 +1,69 @@
+import { App } from "@slack/bolt";
+
+import type { SlackEnv } from "./env";
+import { replyForSlashCommand, replyForText } from "./replies";
+
+function isDirectMessage(channelType: string | undefined): boolean {
+ return channelType === "im";
+}
+
+export function registerListeners(app: App): void {
+ app.event("app_mention", async ({ event, say }) => {
+ await say({
+ text: replyForText(event.text),
+ thread_ts: event.thread_ts,
+ });
+ });
+
+ app.message(async ({ message, say }) => {
+ if (message.subtype !== undefined) {
+ return;
+ }
+ if (!("text" in message) || typeof message.text !== "string") {
+ return;
+ }
+ if ("bot_id" in message && message.bot_id) {
+ return;
+ }
+ if (!isDirectMessage(message.channel_type)) {
+ return;
+ }
+
+ await say(replyForText(message.text));
+ });
+
+ app.command("/dsgt", async ({ command, ack, respond }) => {
+ await ack();
+ await respond({
+ text: replyForSlashCommand(command.text),
+ response_type: "ephemeral",
+ });
+ });
+}
+
+export function createBoltApp(env: SlackEnv): App {
+ const app = env.socketMode
+ ? new App({
+ token: env.botToken,
+ signingSecret: env.signingSecret,
+ socketMode: true,
+ appToken: env.appToken,
+ })
+ : new App({
+ token: env.botToken,
+ signingSecret: env.signingSecret,
+ customRoutes: [
+ {
+ path: "/health",
+ method: ["GET"],
+ handler: (_req, res) => {
+ res.writeHead(200, { "Content-Type": "text/plain" });
+ res.end("ok");
+ },
+ },
+ ],
+ });
+
+ registerListeners(app);
+ return app;
+}
diff --git a/apps/dsgt-slack/src/env.ts b/apps/dsgt-slack/src/env.ts
new file mode 100644
index 00000000..398c8bb5
--- /dev/null
+++ b/apps/dsgt-slack/src/env.ts
@@ -0,0 +1,57 @@
+/**
+ * Env for the local Bolt process (Socket Mode or a local HTTP receiver).
+ * Production App Hosting does not call this — the Next.js webhook reads
+ * SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET at request time.
+ */
+
+import { z } from "zod";
+
+const truthy = (value: string | undefined) =>
+ value === undefined || value.toLowerCase() !== "false";
+
+const envSchema = z
+ .object({
+ SLACK_BOT_TOKEN: z.string().min(1),
+ SLACK_SIGNING_SECRET: z.string().min(1),
+ SLACK_APP_TOKEN: z.string().min(1).optional(),
+ SLACK_SOCKET_MODE: z.string().optional(),
+ PORT: z.coerce.number().int().positive().default(3000),
+ })
+ .superRefine((value, ctx) => {
+ if (truthy(value.SLACK_SOCKET_MODE) && !value.SLACK_APP_TOKEN) {
+ ctx.addIssue({
+ code: "custom",
+ path: ["SLACK_APP_TOKEN"],
+ message:
+ "SLACK_APP_TOKEN is required when Socket Mode is enabled (default).",
+ });
+ }
+ });
+
+export type SlackEnv = {
+ botToken: string;
+ signingSecret: string;
+ appToken: string | undefined;
+ socketMode: boolean;
+ port: number;
+};
+
+export function loadEnv(
+ source: Record = process.env,
+): SlackEnv {
+ const parsed = envSchema.parse({
+ SLACK_BOT_TOKEN: source.SLACK_BOT_TOKEN,
+ SLACK_SIGNING_SECRET: source.SLACK_SIGNING_SECRET,
+ SLACK_APP_TOKEN: source.SLACK_APP_TOKEN || undefined,
+ SLACK_SOCKET_MODE: source.SLACK_SOCKET_MODE,
+ PORT: source.PORT,
+ });
+
+ return {
+ botToken: parsed.SLACK_BOT_TOKEN,
+ signingSecret: parsed.SLACK_SIGNING_SECRET,
+ appToken: parsed.SLACK_APP_TOKEN,
+ socketMode: truthy(parsed.SLACK_SOCKET_MODE),
+ port: parsed.PORT,
+ };
+}
diff --git a/apps/dsgt-slack/src/http.test.ts b/apps/dsgt-slack/src/http.test.ts
new file mode 100644
index 00000000..2e926f68
--- /dev/null
+++ b/apps/dsgt-slack/src/http.test.ts
@@ -0,0 +1,255 @@
+import { createHmac } from "node:crypto";
+import { beforeEach, describe, expect, it, vi } from "vitest";
+
+import {
+ SLACK_WEBHOOK_PATH,
+ handleSlackWebhook,
+ resetSlackEventDedupe,
+ verifySlackSignature,
+} from "./http";
+import { CLUB_SITE_URL, JOIN_FAQ_REPLY } from "./replies";
+
+const SIGNING_SECRET = "test-signing-secret";
+const FROZEN_TS = "1710000000";
+const FROZEN_NOW_MS = Number(FROZEN_TS) * 1000;
+
+function sign(rawBody: string, timestamp: string): string {
+ const digest = createHmac("sha256", SIGNING_SECRET)
+ .update(`v0:${timestamp}:${rawBody}`, "utf8")
+ .digest("hex");
+ return `v0=${digest}`;
+}
+
+function signedRequest(rawBody: string, contentType: string): Request {
+ const timestamp = String(Math.floor(Date.now() / 1000));
+ return new Request(`${CLUB_SITE_URL}${SLACK_WEBHOOK_PATH}`, {
+ method: "POST",
+ headers: {
+ "content-type": contentType,
+ "x-slack-request-timestamp": timestamp,
+ "x-slack-signature": sign(rawBody, timestamp),
+ },
+ body: rawBody,
+ });
+}
+
+describe("verifySlackSignature", () => {
+ it("accepts a matching v0 signature within the time window", () => {
+ const rawBody = `{"ok":true}`;
+ expect(
+ verifySlackSignature({
+ signingSecret: SIGNING_SECRET,
+ signature: sign(rawBody, FROZEN_TS),
+ timestamp: FROZEN_TS,
+ rawBody,
+ nowMs: FROZEN_NOW_MS,
+ }),
+ ).toBe(true);
+ });
+
+ it("rejects a missing or wrong signature", () => {
+ const rawBody = `{"ok":true}`;
+ expect(
+ verifySlackSignature({
+ signingSecret: SIGNING_SECRET,
+ signature: null,
+ timestamp: FROZEN_TS,
+ rawBody,
+ nowMs: FROZEN_NOW_MS,
+ }),
+ ).toBe(false);
+ expect(
+ verifySlackSignature({
+ signingSecret: SIGNING_SECRET,
+ signature: "v0=deadbeef",
+ timestamp: FROZEN_TS,
+ rawBody,
+ nowMs: FROZEN_NOW_MS,
+ }),
+ ).toBe(false);
+ });
+});
+
+describe("handleSlackWebhook", () => {
+ const env = { botToken: "xoxb-test", signingSecret: SIGNING_SECRET };
+
+ beforeEach(() => {
+ resetSlackEventDedupe();
+ });
+
+ it("returns the url_verification challenge", async () => {
+ const rawBody = JSON.stringify({
+ type: "url_verification",
+ challenge: "abc-challenge",
+ });
+ const response = await handleSlackWebhook(
+ signedRequest(rawBody, "application/json"),
+ env,
+ );
+ expect(response.status).toBe(200);
+ await expect(response.json()).resolves.toEqual({
+ challenge: "abc-challenge",
+ });
+ });
+
+ it("rejects unsigned requests", async () => {
+ const response = await handleSlackWebhook(
+ new Request(`${CLUB_SITE_URL}${SLACK_WEBHOOK_PATH}`, {
+ method: "POST",
+ headers: { "content-type": "application/json" },
+ body: JSON.stringify({ type: "url_verification", challenge: "nope" }),
+ }),
+ env,
+ );
+ expect(response.status).toBe(400);
+ });
+
+ it("replies to an app_mention join question with the FAQ", async () => {
+ const postMessage = vi.fn().mockResolvedValue({});
+ const rawBody = JSON.stringify({
+ type: "event_callback",
+ event: {
+ type: "app_mention",
+ text: "<@U123> how do I join?",
+ channel: "C123",
+ thread_ts: "1710000000.000100",
+ },
+ });
+
+ const response = await handleSlackWebhook(
+ signedRequest(rawBody, "application/json"),
+ env,
+ { chat: { postMessage } },
+ );
+
+ expect(response.status).toBe(200);
+ expect(postMessage).toHaveBeenCalledWith({
+ channel: "C123",
+ text: JOIN_FAQ_REPLY,
+ thread_ts: "1710000000.000100",
+ });
+ });
+
+ it("replies to a DM join question with the FAQ", async () => {
+ const postMessage = vi.fn().mockResolvedValue({});
+ const rawBody = JSON.stringify({
+ type: "event_callback",
+ event: {
+ type: "message",
+ channel_type: "im",
+ text: "How do I join the club?",
+ channel: "D123",
+ },
+ });
+
+ const response = await handleSlackWebhook(
+ signedRequest(rawBody, "application/json"),
+ env,
+ { chat: { postMessage } },
+ );
+
+ expect(response.status).toBe(200);
+ expect(postMessage).toHaveBeenCalledWith({
+ channel: "D123",
+ text: JOIN_FAQ_REPLY,
+ });
+ });
+
+ it("acks /dsgt join with the FAQ as an ephemeral response", async () => {
+ const rawBody = "command=%2Fdsgt&text=join";
+ const response = await handleSlackWebhook(
+ signedRequest(rawBody, "application/x-www-form-urlencoded"),
+ env,
+ { chat: { postMessage: vi.fn() } },
+ );
+
+ expect(response.status).toBe(200);
+ await expect(response.json()).resolves.toEqual({
+ response_type: "ephemeral",
+ text: JOIN_FAQ_REPLY,
+ });
+ });
+
+ it("acks event_callback before chat.postMessage resolves", async () => {
+ let release: (value: unknown) => void = () => {
+ /* assigned below */
+ };
+ const postMessage = vi.fn(
+ () =>
+ new Promise((resolve) => {
+ release = resolve;
+ }),
+ );
+ const rawBody = JSON.stringify({
+ type: "event_callback",
+ event_id: "EvACK",
+ event: {
+ type: "app_mention",
+ text: "<@U123> ping",
+ channel: "C123",
+ },
+ });
+
+ const response = await handleSlackWebhook(
+ signedRequest(rawBody, "application/json"),
+ env,
+ { chat: { postMessage } },
+ );
+
+ expect(response.status).toBe(200);
+ await expect(response.json()).resolves.toEqual({ ok: true });
+ expect(postMessage).toHaveBeenCalledTimes(1);
+ release({});
+ });
+
+ it("does not post twice for a retried event_id", async () => {
+ const postMessage = vi.fn().mockResolvedValue({});
+ const rawBody = JSON.stringify({
+ type: "event_callback",
+ event_id: "EvDUP",
+ event: {
+ type: "app_mention",
+ text: "<@U123> how do I join?",
+ channel: "C123",
+ },
+ });
+ const client = { chat: { postMessage } };
+
+ const first = await handleSlackWebhook(
+ signedRequest(rawBody, "application/json"),
+ env,
+ client,
+ );
+ const retry = await handleSlackWebhook(
+ signedRequest(rawBody, "application/json"),
+ env,
+ client,
+ );
+
+ expect(first.status).toBe(200);
+ expect(retry.status).toBe(200);
+ expect(postMessage).toHaveBeenCalledTimes(1);
+ });
+
+ it("does not treat a slow postMessage rejection as invalid JSON", async () => {
+ const postMessage = vi.fn().mockRejectedValue(new Error("slack down"));
+ const rawBody = JSON.stringify({
+ type: "event_callback",
+ event_id: "EvFAIL",
+ event: {
+ type: "app_mention",
+ text: "<@U123> ping",
+ channel: "C123",
+ },
+ });
+
+ const response = await handleSlackWebhook(
+ signedRequest(rawBody, "application/json"),
+ env,
+ { chat: { postMessage } },
+ );
+
+ expect(response.status).toBe(200);
+ await expect(response.json()).resolves.toEqual({ ok: true });
+ });
+});
diff --git a/apps/dsgt-slack/src/http.ts b/apps/dsgt-slack/src/http.ts
new file mode 100644
index 00000000..deb78952
--- /dev/null
+++ b/apps/dsgt-slack/src/http.ts
@@ -0,0 +1,253 @@
+/**
+ * HTTP Events API handler for production.
+ *
+ * Slack POSTs to the Firebase App Hosting (Cloud Run) URL. This module is Fetch
+ * Request/Response based so Next.js App Router can call it. It does not start a
+ * Bolt HTTP server — Socket Mode / Bolt remain a local-only process.
+ */
+
+import { createHmac, timingSafeEqual } from "node:crypto";
+import { WebClient } from "@slack/web-api";
+
+import { replyForSlashCommand, replyForText } from "./replies";
+
+/** Stable Request URL path on mainweb. Use this in the Slack app settings. */
+export const SLACK_WEBHOOK_PATH = "/api/webhooks/slack";
+
+const MAX_CLOCK_SKEW_SEC = 60 * 5;
+
+/** FIFO cap so a long-lived instance cannot grow without bound. */
+const MAX_SEEN_EVENTS = 500;
+const seenEventIds = new Set();
+
+export type SlackDefer = (work: Promise) => void;
+
+const defaultDefer: SlackDefer = (work) => {
+ void work.catch(() => {
+ /* postMessage failures must not turn an ACK into a 400 Slack retry. */
+ });
+};
+
+/** Test helper: event_id dedupe is process-local. */
+export function resetSlackEventDedupe(): void {
+ seenEventIds.clear();
+}
+
+function alreadySeenEvent(eventId: string): boolean {
+ if (seenEventIds.has(eventId)) {
+ return true;
+ }
+ seenEventIds.add(eventId);
+ if (seenEventIds.size > MAX_SEEN_EVENTS) {
+ const oldest = seenEventIds.values().next().value;
+ if (oldest !== undefined) {
+ seenEventIds.delete(oldest);
+ }
+ }
+ return false;
+}
+
+export type SlackHttpEnv = {
+ botToken: string;
+ signingSecret: string;
+};
+
+export type SlackPoster = {
+ chat: {
+ postMessage: (args: {
+ channel: string;
+ text: string;
+ thread_ts?: string;
+ }) => Promise;
+ };
+};
+
+function safeEqual(left: string, right: string): boolean {
+ const leftBuf = Buffer.from(left, "utf8");
+ const rightBuf = Buffer.from(right, "utf8");
+ if (leftBuf.length !== rightBuf.length) {
+ return false;
+ }
+ return timingSafeEqual(leftBuf, rightBuf);
+}
+
+export function verifySlackSignature(options: {
+ signingSecret: string;
+ signature: string | null;
+ timestamp: string | null;
+ rawBody: string;
+ nowMs?: number;
+}): boolean {
+ const {
+ signingSecret,
+ signature,
+ timestamp,
+ rawBody,
+ nowMs = Date.now(),
+ } = options;
+
+ if (!signature || !timestamp || !/^[0-9]+$/.test(timestamp)) {
+ return false;
+ }
+
+ const ageSec = Math.abs(nowMs / 1000 - Number(timestamp));
+ if (ageSec > MAX_CLOCK_SKEW_SEC) {
+ return false;
+ }
+
+ const digest = createHmac("sha256", signingSecret)
+ .update(`v0:${timestamp}:${rawBody}`, "utf8")
+ .digest("hex");
+
+ return safeEqual(`v0=${digest}`, signature);
+}
+
+function isRecord(value: unknown): value is Record {
+ return typeof value === "object" && value !== null;
+}
+
+type SlackMessageEvent = {
+ type: string;
+ subtype?: string;
+ bot_id?: string;
+ text?: string;
+ channel?: string;
+ channel_type?: string;
+ thread_ts?: string;
+};
+
+function parseMessageEvent(value: unknown): SlackMessageEvent | null {
+ if (!isRecord(value) || typeof value.type !== "string") {
+ return null;
+ }
+
+ return {
+ type: value.type,
+ subtype: typeof value.subtype === "string" ? value.subtype : undefined,
+ bot_id: typeof value.bot_id === "string" ? value.bot_id : undefined,
+ text: typeof value.text === "string" ? value.text : undefined,
+ channel: typeof value.channel === "string" ? value.channel : undefined,
+ channel_type:
+ typeof value.channel_type === "string" ? value.channel_type : undefined,
+ thread_ts:
+ typeof value.thread_ts === "string" ? value.thread_ts : undefined,
+ };
+}
+
+async function handleEvent(
+ event: SlackMessageEvent,
+ client: SlackPoster,
+): Promise {
+ if (event.bot_id || event.subtype) {
+ return;
+ }
+ if (typeof event.text !== "string" || typeof event.channel !== "string") {
+ return;
+ }
+
+ if (event.type === "app_mention") {
+ await client.chat.postMessage({
+ channel: event.channel,
+ text: replyForText(event.text),
+ ...(event.thread_ts ? { thread_ts: event.thread_ts } : {}),
+ });
+ return;
+ }
+
+ if (event.type === "message" && event.channel_type === "im") {
+ await client.chat.postMessage({
+ channel: event.channel,
+ text: replyForText(event.text),
+ });
+ }
+}
+
+async function handleJsonBody(
+ payload: unknown,
+ client: SlackPoster,
+ defer: SlackDefer,
+): Promise {
+ if (!isRecord(payload) || typeof payload.type !== "string") {
+ return Response.json({ error: "Invalid payload" }, { status: 400 });
+ }
+
+ if (payload.type === "url_verification") {
+ const challenge =
+ typeof payload.challenge === "string" ? payload.challenge : "";
+ return Response.json({ challenge });
+ }
+
+ if (payload.type === "event_callback") {
+ const eventId =
+ typeof payload.event_id === "string" ? payload.event_id : "";
+ if (eventId && alreadySeenEvent(eventId)) {
+ return Response.json({ ok: true });
+ }
+ const event = parseMessageEvent(payload.event);
+ if (event) {
+ // ACK first. Slack retries after ~3s; awaiting chat.postMessage here
+ // (especially after a cold start) duplicates the reply.
+ defer(handleEvent(event, client));
+ }
+ return Response.json({ ok: true });
+ }
+
+ return Response.json({ ok: true });
+}
+
+function handleFormBody(rawBody: string): Response {
+ const params = new URLSearchParams(rawBody);
+
+ if (params.get("ssl_check") === "1") {
+ return new Response("", { status: 200 });
+ }
+
+ if (params.has("payload")) {
+ return new Response("", { status: 200 });
+ }
+
+ const command = params.get("command");
+ if (command) {
+ return Response.json({
+ response_type: "ephemeral",
+ text: replyForSlashCommand(params.get("text") ?? ""),
+ });
+ }
+
+ return Response.json({ error: "Unknown Slack request" }, { status: 400 });
+}
+
+export async function handleSlackWebhook(
+ req: Request,
+ env: SlackHttpEnv,
+ client: SlackPoster = new WebClient(env.botToken),
+ defer: SlackDefer = defaultDefer,
+): Promise {
+ const rawBody = await req.text();
+ const valid = verifySlackSignature({
+ signingSecret: env.signingSecret,
+ signature: req.headers.get("x-slack-signature"),
+ timestamp: req.headers.get("x-slack-request-timestamp"),
+ rawBody,
+ });
+
+ if (!valid) {
+ return Response.json({ error: "Invalid signature" }, { status: 400 });
+ }
+
+ const contentType = req.headers.get("content-type") ?? "";
+ if (
+ contentType.includes("application/json") ||
+ rawBody.trimStart().startsWith("{")
+ ) {
+ let payload: unknown;
+ try {
+ payload = JSON.parse(rawBody) as unknown;
+ } catch {
+ return Response.json({ error: "Invalid JSON body" }, { status: 400 });
+ }
+ return handleJsonBody(payload, client, defer);
+ }
+
+ return handleFormBody(rawBody);
+}
diff --git a/apps/dsgt-slack/src/index.ts b/apps/dsgt-slack/src/index.ts
new file mode 100644
index 00000000..88da53b5
--- /dev/null
+++ b/apps/dsgt-slack/src/index.ts
@@ -0,0 +1,38 @@
+import "dotenv/config";
+
+import { createBoltApp } from "./app";
+import type { SlackEnv } from "./env";
+import { loadEnv } from "./env";
+
+async function main(): Promise {
+ let env: SlackEnv;
+ try {
+ env = loadEnv();
+ } catch {
+ console.warn(
+ "dsgt Slack bot skipped: set SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET in apps/dsgt-slack/.env to run locally (Socket Mode). Production traffic is handled by sites/mainweb at /api/webhooks/slack.",
+ );
+ await new Promise(() => {
+ /* keep turbo `dev` from restarting this task */
+ });
+ return;
+ }
+
+ const app = createBoltApp(env);
+
+ if (env.socketMode) {
+ await app.start();
+ app.logger.info("dsgt Slack bot is running (Socket Mode, local)");
+ return;
+ }
+
+ await app.start(env.port);
+ app.logger.info(
+ `dsgt Slack bot is running a local HTTP receiver on port ${String(env.port)} at /slack/events. Production uses Firebase App Hosting at /api/webhooks/slack.`,
+ );
+}
+
+main().catch((error: unknown) => {
+ console.error("Failed to start the dsgt Slack bot.", error);
+ process.exit(1);
+});
diff --git a/apps/dsgt-slack/src/replies.test.ts b/apps/dsgt-slack/src/replies.test.ts
new file mode 100644
index 00000000..5c247a88
--- /dev/null
+++ b/apps/dsgt-slack/src/replies.test.ts
@@ -0,0 +1,54 @@
+import { describe, expect, it } from "vitest";
+
+import {
+ CLUB_SITE_URL,
+ JOIN_FAQ_REPLY,
+ detectIntent,
+ replyForSlashCommand,
+ replyForText,
+ stripBotMention,
+} from "./replies";
+
+describe("join FAQ reply", () => {
+ it("names the August 26 first event and points to the club site", () => {
+ expect(JOIN_FAQ_REPLY).toContain("August 26");
+ expect(JOIN_FAQ_REPLY).toContain("8/26");
+ expect(JOIN_FAQ_REPLY).toContain(
+ "Further details will be announced at that event",
+ );
+ expect(JOIN_FAQ_REPLY).toContain(CLUB_SITE_URL);
+ expect(JOIN_FAQ_REPLY).toContain("datasciencegt.org");
+ });
+
+ it.each([
+ "How do I join the club?",
+ "When is the first event?",
+ "I want to sign up",
+ "<@U123> how do I join?",
+ "What is happening on 8/26?",
+ ])("routes join questions to the FAQ: %s", (text) => {
+ expect(detectIntent(text)).toBe("join");
+ expect(replyForText(text)).toBe(JOIN_FAQ_REPLY);
+ });
+});
+
+describe("slash command routing", () => {
+ it("returns help when the command text is empty", () => {
+ expect(replyForSlashCommand("")).toContain("Available topics");
+ });
+
+ it("returns the join FAQ for /dsgt join", () => {
+ expect(replyForSlashCommand("join")).toBe(JOIN_FAQ_REPLY);
+ });
+});
+
+describe("stripBotMention", () => {
+ it("removes a Slack user mention before the rest of the text", () => {
+ expect(stripBotMention("<@U123> how do I join?")).toBe("how do I join?");
+ });
+
+ it("is linear on a long run of incomplete <@ prefixes", () => {
+ const noisy = `${"<@".repeat(200)} how do I join?`;
+ expect(detectIntent(noisy)).toBe("join");
+ });
+});
diff --git a/apps/dsgt-slack/src/replies.ts b/apps/dsgt-slack/src/replies.ts
new file mode 100644
index 00000000..db01ff29
--- /dev/null
+++ b/apps/dsgt-slack/src/replies.ts
@@ -0,0 +1,125 @@
+/**
+ * Reply text and lightweight intent routing for the DS@GT Slack bot.
+ *
+ * Keep this module free of Slack SDK imports so the copy can be unit tested.
+ */
+
+/** Public club site host. Scheme is added below so the full URL is not a source literal. */
+export const CLUB_HOST = "datasciencegt.org";
+export const CLUB_SITE_URL = `https://${CLUB_HOST}`;
+
+export const JOIN_FAQ_REPLY = `The first Data Science @ Georgia Tech event of the term is on August 26 (8/26). Further details will be announced at that event. For club information and how to get involved, visit ${CLUB_SITE_URL}.`;
+
+export const HEALTH_REPLY =
+ "dsgt is online. This health check confirms the Data Science @ Georgia Tech Slack bot is running.";
+
+export const HELP_REPLY = [
+ "I am the Data Science @ Georgia Tech Slack bot (dsgt).",
+ "",
+ "You can mention @dsgt in a channel, send a direct message, or use the /dsgt slash command.",
+ "",
+ "Available topics:",
+ "• help — show this message",
+ "• ping — confirm that the bot is online",
+ "• join — how to join the club and the date of the first event",
+ "",
+ `Club website: ${CLUB_SITE_URL}`,
+].join("\n");
+
+export const DEFAULT_REPLY =
+ "Hello. I am the Data Science @ Georgia Tech bot. Send help for what I can answer, or ping to confirm that I am online.";
+
+export const UNKNOWN_COMMAND_REPLY =
+ "I did not recognize that request. Send help for the topics I can answer.";
+
+const JOIN_PATTERN =
+ /\b(join|sign[ -]?up|membership|member|get involved|first (event|meeting)|8\/26|august 26|26th)\b/i;
+
+const HEALTH_PATTERN = /\b(ping|health|alive|status)\b/i;
+
+const HELP_PATTERN = /\b(help|commands|what can you do)\b/i;
+
+export type ReplyIntent = "join" | "health" | "help" | "default";
+
+/**
+ * Slack mentions are `<@U…>` (optionally `<@U…|label>`). Walk the string once
+ * with indexOf so a flood of `<@` without a closing `>` cannot backtrack.
+ */
+export function stripBotMention(text: string): string {
+ let output = "";
+ let i = 0;
+ while (i < text.length) {
+ const start = text.indexOf("<@", i);
+ if (start === -1) {
+ output += text.slice(i);
+ break;
+ }
+ output += text.slice(i, start);
+ const end = text.indexOf(">", start + 2);
+ if (end === -1) {
+ output += text.slice(start);
+ break;
+ }
+ output += " ";
+ i = end + 1;
+ }
+
+ let collapsed = "";
+ for (const ch of output) {
+ const isSpace = ch === " " || ch === "\t" || ch === "\n" || ch === "\r";
+ if (isSpace) {
+ if (collapsed.length > 0 && collapsed[collapsed.length - 1] !== " ") {
+ collapsed += " ";
+ }
+ } else {
+ collapsed += ch;
+ }
+ }
+ return collapsed.trim();
+}
+
+export function detectIntent(text: string): ReplyIntent {
+ const normalized = stripBotMention(text).trim();
+ if (normalized.length === 0) {
+ return "help";
+ }
+ if (JOIN_PATTERN.test(normalized)) {
+ return "join";
+ }
+ if (HEALTH_PATTERN.test(normalized)) {
+ return "health";
+ }
+ if (HELP_PATTERN.test(normalized)) {
+ return "help";
+ }
+ return "default";
+}
+
+export function replyForIntent(intent: ReplyIntent): string {
+ switch (intent) {
+ case "join":
+ return JOIN_FAQ_REPLY;
+ case "health":
+ return HEALTH_REPLY;
+ case "help":
+ return HELP_REPLY;
+ default:
+ return DEFAULT_REPLY;
+ }
+}
+
+export function replyForText(text: string): string {
+ return replyForIntent(detectIntent(text));
+}
+
+export function replyForSlashCommand(text: string): string {
+ const normalized = text.trim();
+ if (normalized.length === 0) {
+ return HELP_REPLY;
+ }
+ const intent = detectIntent(normalized);
+ if (intent === "default") {
+ return UNKNOWN_COMMAND_REPLY;
+ }
+ return replyForIntent(intent);
+}
diff --git a/apps/dsgt-slack/tsconfig.json b/apps/dsgt-slack/tsconfig.json
new file mode 100644
index 00000000..6eaf141c
--- /dev/null
+++ b/apps/dsgt-slack/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tooling/typescript/base.json",
+ "compilerOptions": {
+ "types": ["node"],
+ "noEmit": true
+ },
+ "include": ["src/**/*.ts"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/apps/dsgt-slack/turbo.json b/apps/dsgt-slack/turbo.json
new file mode 100644
index 00000000..b0115a50
--- /dev/null
+++ b/apps/dsgt-slack/turbo.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://turborepo.org/schema.json",
+ "extends": ["//"],
+ "tasks": {
+ "dev": {
+ "persistent": true,
+ "cache": false
+ },
+ "start": {
+ "persistent": true,
+ "cache": false
+ }
+ }
+}
diff --git a/apps/dsgt-slack/vitest.config.ts b/apps/dsgt-slack/vitest.config.ts
new file mode 100644
index 00000000..ae847ff6
--- /dev/null
+++ b/apps/dsgt-slack/vitest.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from "vitest/config";
+
+export default defineConfig({
+ test: {
+ include: ["src/**/*.test.ts"],
+ },
+});
diff --git a/docs/README.md b/docs/README.md
index 1544941c..676c5b48 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -25,6 +25,12 @@ Start here, then jump to the page that matches the work you are doing.
| [Database](./packages/db.md) | `@query/db` | Drizzle schema, client, membership rules |
| [UI](./packages/ui.md) | `@query/ui` | Shared React components and styles |
+## Apps
+
+| Document | Workspace | Role |
+| --- | --- | --- |
+| [dsgt Slack bot](../apps/dsgt-slack/README.md) | `@query/dsgt-slack` | `@dsgt` Slack bot; production HTTP on mainweb |
+
## Sites
| Document | Workspace | Role |
diff --git a/docs/architecture.md b/docs/architecture.md
index f91c56f5..92e1fa89 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -15,6 +15,7 @@
│ / /team /events /login /dashboard /admin /judge … │
│ │ │
│ /api/trpc /api/auth /api/webhooks │
+│ stripe + slack │
└──────────┬──────────────────┴───────────────┬───────────────┘
│ │
┌──────▼──────┐ ┌──────▼──────┐
@@ -91,7 +92,9 @@ Stripe Checkout and Payment Intents both exist. Amounts are defined once in `@qu
| Bootcamp add-on (on top of membership) | `1000` ($10) |
| Max charge treated as membership | `10000` |
-The webhook is `sites/mainweb/app/(portal)/api/webhooks/stripe/route.ts`. Linking can also happen from the portal (`stripe.linkAccount`, `stripe.attemptAutoLink`) and at sign-in.
+The Stripe webhook is `sites/mainweb/app/(portal)/api/webhooks/stripe/route.ts`. Linking can also happen from the portal (`stripe.linkAccount`, `stripe.attemptAutoLink`) and at sign-in.
+
+The Slack Events API webhook is `sites/mainweb/app/(portal)/api/webhooks/slack/route.ts`. It imports reply text from `apps/dsgt-slack` and verifies `SLACK_SIGNING_SECRET`. Production is HTTP on App Hosting (`{AUTH_URL}/api/webhooks/slack`); Socket Mode is local-only. See [`apps/dsgt-slack/README.md`](../apps/dsgt-slack/README.md).
## Caching
@@ -106,9 +109,12 @@ The webhook is `sites/mainweb/app/(portal)/api/webhooks/stripe/route.ts`. Linkin
The event site does not talk to the database. Interest and registration live on the portal; the marketing site links to `/login?callbackUrl=/hacklytics`.
+## Apps
+
+`apps/dsgt-slack` (`@query/dsgt-slack`) is the `@dsgt` Slack bot. Reply copy lives in that package. Production HTTP is the mainweb route `/api/webhooks/slack` on App Hosting. Socket Mode is a local-only process in the same package.
+
## What is not in this repo
- `packages/consts` is mentioned in older notes and is **not** a workspace today.
-- `apps/*` is listed in `pnpm-workspace.yaml` but there is no `apps/` directory.
- `graphify-out/` is generated graph output, not product code.
- `trust badge/` holds MLH league badge SVGs for the event site.
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 07ad9c4b..ee4ea6de 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -22,7 +22,7 @@ corepack prepare pnpm@10.33.2 --activate
pnpm install
```
-Workspaces are defined in `pnpm-workspace.yaml`: `sites/*`, `packages/*`, and `tooling/*`.
+Workspaces are defined in `pnpm-workspace.yaml`: `apps/*`, `sites/*`, `packages/*`, and `tooling/*`.
## Local database
@@ -88,7 +88,7 @@ pnpm --filter @query/db studio # Drizzle Studio
| `pnpm build` | `turbo run build` |
| `pnpm lint` | ESLint across workspaces (`--max-warnings 0`) |
| `pnpm typecheck` | `tsc --noEmit` via Turbo |
-| `pnpm test` | Vitest: `packages/api`, `packages/db`, `sites/mainweb/lib` |
+| `pnpm test` | Vitest: `packages/api`, `packages/db`, `sites/mainweb/lib`, `apps/dsgt-slack` |
| `pnpm format` | Prettier write |
Database scripts live on `@query/db`:
diff --git a/docs/operations/deployment.md b/docs/operations/deployment.md
index 13e7abe6..1c47ba7c 100644
--- a/docs/operations/deployment.md
+++ b/docs/operations/deployment.md
@@ -28,7 +28,15 @@ Run: `node sites/mainweb/.next/standalone/sites/mainweb/server.js`
Secrets are GCP Secret Manager. Grant the App Hosting backend access once per secret, e.g. `firebase apphosting:secrets:grantaccess DATABASE_URL --backend query`.
-Env mapping (names only) is in `apphosting.yaml`: `DATABASE_URL`, `AUTH_SECRET` (also copied to `NEXTAUTH_SECRET`), Google/GitHub OAuth, Stripe, SMTP, DDoS ceilings, `TRUSTED_PROXY_HOPS=1`.
+Env mapping (names only) is in `apphosting.yaml`: `DATABASE_URL`, `AUTH_SECRET` (also copied to `NEXTAUTH_SECRET`), Google/GitHub OAuth, Stripe, Slack (`SLACK_BOT_TOKEN`, `SLACK_SIGNING_SECRET`, `SLACK_SOCKET_MODE=false`), SMTP, DDoS ceilings, `TRUSTED_PROXY_HOPS=1`.
+
+Slack Event Subscriptions, slash commands, and interactivity must use the App Hosting origin (`AUTH_URL` / `NEXTAUTH_URL` in `apphosting.yaml`, host `datasciencegt.org`), not Firebase Hosting `dsgt-website` / `sites/mainweb/out`:
+
+```text
+{AUTH_URL}/api/webhooks/slack
+```
+
+Create `SLACK_BOT_TOKEN` and `SLACK_SIGNING_SECRET` in Secret Manager before that deploy. See [`apps/dsgt-slack/README.md`](../../apps/dsgt-slack/README.md).
## Hacklytics — Firebase Hosting
diff --git a/docs/operations/environment.md b/docs/operations/environment.md
index 79af41a5..391031c9 100644
--- a/docs/operations/environment.md
+++ b/docs/operations/environment.md
@@ -64,6 +64,17 @@ Without `DATABASE_URL`, `db` is null, sessions fall back to JWT, and tRPC proced
| `DDOS_CLEANUP_INTERVAL_MS` | Code default if unset |
| `CSP_ENFORCE` | `true` turns CSP from Report-Only into enforcing. Default is report-only |
+## Slack (`@dsgt`)
+
+| Variable | Notes |
+| --- | --- |
+| `SLACK_BOT_TOKEN` | Bot User OAuth Token. App Hosting secret `SLACK_BOT_TOKEN` |
+| `SLACK_SIGNING_SECRET` | Request signature. App Hosting secret `SLACK_SIGNING_SECRET` |
+| `SLACK_SOCKET_MODE` | App Hosting sets `false`. Local Socket Mode defaults to on |
+| `SLACK_APP_TOKEN` | Local Socket Mode only (`xapp-...`). Not set in production |
+
+Create the Secret Manager secrets before the App Hosting deploy that references them. Install steps: [`apps/dsgt-slack/README.md`](../../apps/dsgt-slack/README.md).
+
## Runtime (App Hosting)
| Variable | Value |
diff --git a/docs/operations/testing.md b/docs/operations/testing.md
index accbfd5d..3fe04c73 100644
--- a/docs/operations/testing.md
+++ b/docs/operations/testing.md
@@ -9,7 +9,7 @@ pnpm test
That is:
```bash
-vitest run packages/api packages/db sites/mainweb/lib
+vitest run packages/api packages/db sites/mainweb/lib apps/dsgt-slack
```
CI: `.github/workflows/test.yml` on pushes to `main`/`dev` and on pull requests.
@@ -41,6 +41,12 @@ Tests use `src/test/create-mock-context.ts` and `.internal-tests/_db-tx-mock.ts`
`src/services/membership.test.ts` — grant, lapse, current-edition resolution, payment linking.
+## `@query/dsgt-slack`
+
+`apps/dsgt-slack/src/replies.test.ts` — join FAQ copy (August 26 / 8/26 / datasciencegt.org) and slash-command routing.
+
+`apps/dsgt-slack/src/http.test.ts` — Slack signature verification, `url_verification` challenge, `app_mention` join reply, `/dsgt join` ack.
+
## Mainweb
`sites/mainweb/lib/*.test.ts` — phone formatting, hackathon slugs, `safe-callback`.
diff --git a/docs/sites/mainweb.md b/docs/sites/mainweb.md
index 55575b3d..de5935de 100644
--- a/docs/sites/mainweb.md
+++ b/docs/sites/mainweb.md
@@ -65,6 +65,7 @@ Unauthenticated and authenticated product UI. `proxy.ts` marks these prefixes `p
| `/api/auth/[...nextauth]` | NextAuth handlers |
| `/api/auth/verify-email` | Email-code verification |
| `/api/webhooks/stripe` | Stripe webhooks |
+| `/api/webhooks/slack` | Slack Events API, `/dsgt`, interactivity (`@query/dsgt-slack`) |
## Client data
@@ -77,7 +78,7 @@ Helpers: `lib/hackathon-slug.ts`, `lib/phone.ts`, `lib/bootcamp-schedule.ts`, `l
## Config highlights (`next.config.mjs`)
-- Transpiles `@query/api`, `@query/auth`, `@query/db`, `@query/ui`
+- Transpiles `@query/api`, `@query/auth`, `@query/db`, `@query/dsgt-slack`, `@query/ui`
- `outputFileTracingRoot` is the monorepo root (needed for standalone on App Hosting)
- Security headers: HSTS, CSP (report-only unless `CSP_ENFORCE=true`), frame options SAMEORIGIN (admin print/QR iframes), Permissions-Policy (camera **not** denied — `/scan` needs it)
- React Compiler enabled
diff --git a/package.json b/package.json
index 0954cf6d..7bed64cb 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,7 @@
"lint": "turbo run lint",
"format": "prettier --write .",
"typecheck": "turbo run typecheck",
- "test": "vitest run packages/api packages/db sites/mainweb/lib"
+ "test": "vitest run packages/api packages/db sites/mainweb/lib apps/dsgt-slack"
},
"dependencies": {
"next": "16.3.0",
@@ -20,7 +20,7 @@
},
"devDependencies": {
"turbo": "^2.9.14",
- "vitest": "^4.1.8"
+ "vitest": "^4.1.10"
},
"pnpm": {
"overrides": {
diff --git a/packages/api/package.json b/packages/api/package.json
index d849b5ce..4c92f752 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -42,6 +42,6 @@
"@query/tsconfig": "workspace:*",
"@types/sanitize-html": "^2.16.0",
"typescript": "6.0.2",
- "vitest": "^4.1.8"
+ "vitest": "^4.1.10"
}
}
diff --git a/packages/auth/package.json b/packages/auth/package.json
index 70ae81e2..22f3b5a8 100644
--- a/packages/auth/package.json
+++ b/packages/auth/package.json
@@ -13,7 +13,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
- "@auth/drizzle-adapter": "1.7.1",
+ "@auth/drizzle-adapter": "1.11.3",
"@query/db": "workspace:*",
"drizzle-orm": "0.45.2",
"next-auth": "5.0.0-beta.32",
@@ -25,9 +25,9 @@
"devDependencies": {
"@query/tsconfig": "workspace:*",
"@types/node": "^20",
- "@typescript-eslint/eslint-plugin": "^8.59.2",
- "@typescript-eslint/parser": "^8.59.2",
- "@typescript-eslint/utils": "^8.59.2",
+ "@typescript-eslint/eslint-plugin": "^8.67.0",
+ "@typescript-eslint/parser": "^8.67.0",
+ "@typescript-eslint/utils": "^8.67.0",
"eslint": "^10.1.0",
"eslint-config-prettier": "^10.1.5",
"typescript": "^6.0.2"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 24c9ca8b..80e5d382 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -25,7 +25,7 @@ importers:
dependencies:
next:
specifier: 16.3.0
- version: 16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
+ version: 16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
typescript:
specifier: ^6.0.2
version: 6.0.2
@@ -34,8 +34,51 @@ importers:
specifier: ^2.9.14
version: 2.9.14
vitest:
- specifier: ^4.1.8
- version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0)
+ specifier: ^4.1.10
+ version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0)
+
+ apps/dsgt-slack:
+ dependencies:
+ '@slack/bolt':
+ specifier: ^5.0.0
+ version: 5.0.0(@types/express@5.0.6)(undici@6.28.0)
+ '@slack/web-api':
+ specifier: ^7.13.0
+ version: 7.19.0
+ dotenv:
+ specifier: ^16.6.1
+ version: 16.6.1
+ undici:
+ specifier: ^6.27.0
+ version: 6.28.0
+ zod:
+ specifier: 3.25.53
+ version: 3.25.53
+ devDependencies:
+ '@query/eslint-config':
+ specifier: workspace:*
+ version: link:../../tooling/eslint
+ '@query/tsconfig':
+ specifier: workspace:*
+ version: link:../../tooling/typescript
+ '@types/express':
+ specifier: ^5.0.0
+ version: 5.0.6
+ '@types/node':
+ specifier: ^22.15.32
+ version: 22.15.32
+ eslint:
+ specifier: 10.1.0
+ version: 10.1.0(jiti@2.7.0)
+ tsx:
+ specifier: ^4.21.0
+ version: 4.21.0
+ typescript:
+ specifier: 6.0.2
+ version: 6.0.2
+ vitest:
+ specifier: ^4.1.10
+ version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0)
packages/api:
dependencies:
@@ -53,7 +96,7 @@ importers:
version: 11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2)
'@trpc/next':
specifier: 11.18.0
- version: 11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/react-query@11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(react@19.2.7)(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react-dom@19.0.0(react@19.2.7))(react@19.2.7)(typescript@6.0.2)
+ version: 11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/react-query@11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(react@19.2.7)(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react-dom@19.0.0(react@19.2.7))(react@19.2.7)(typescript@6.0.2)
'@trpc/react-query':
specifier: 11.18.0
version: 11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(react@19.2.7)(typescript@6.0.2)
@@ -92,14 +135,14 @@ importers:
specifier: 6.0.2
version: 6.0.2
vitest:
- specifier: ^4.1.8
- version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0)
+ specifier: ^4.1.10
+ version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0)
packages/auth:
dependencies:
'@auth/drizzle-adapter':
- specifier: 1.7.1
- version: 1.7.1(nodemailer@9.0.3)
+ specifier: 1.11.3
+ version: 1.11.3(nodemailer@9.0.3)
'@query/db':
specifier: workspace:*
version: link:../db
@@ -108,7 +151,7 @@ importers:
version: 0.45.2(@opentelemetry/api@1.9.1)(@types/pg@8.20.0)(pg@8.21.0)(postgres@3.4.3)
next-auth:
specifier: 5.0.0-beta.32
- version: 5.0.0-beta.32(next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@20.19.40)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(nodemailer@9.0.3)(react@19.2.7)
+ version: 5.0.0-beta.32(next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@20.19.40)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(nodemailer@9.0.3)(react@19.2.7)
nodemailer:
specifier: ^9.0.1
version: 9.0.3
@@ -120,14 +163,14 @@ importers:
specifier: ^20
version: 20.19.40
'@typescript-eslint/eslint-plugin':
- specifier: ^8.59.2
- version: 8.59.2(@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ specifier: ^8.67.0
+ version: 8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
'@typescript-eslint/parser':
- specifier: ^8.59.2
- version: 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ specifier: ^8.67.0
+ version: 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
'@typescript-eslint/utils':
- specifier: ^8.59.2
- version: 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ specifier: ^8.67.0
+ version: 8.68.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
eslint:
specifier: ^10.1.0
version: 10.1.0(jiti@2.7.0)
@@ -148,7 +191,7 @@ importers:
version: 0.45.2(@opentelemetry/api@1.9.1)(@types/pg@8.20.0)(pg@8.21.0)(postgres@3.4.3)
next-auth:
specifier: 5.0.0-beta.32
- version: 5.0.0-beta.32(next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react@19.2.7)
+ version: 5.0.0-beta.32(next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react@19.2.7)
pg:
specifier: 8.21.0
version: 8.21.0
@@ -228,7 +271,7 @@ importers:
version: 1.0.0
next:
specifier: 16.3.0
- version: 16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
+ version: 16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
react:
specifier: 19.2.7
version: 19.2.7
@@ -239,9 +282,6 @@ importers:
'@next/eslint-plugin-next':
specifier: 16.3.0
version: 16.3.0(eslint@10.1.0(jiti@2.7.0))
- '@playwright/test':
- specifier: ^1.60.0
- version: 1.60.0
'@tailwindcss/postcss':
specifier: 4.3.0
version: 4.3.0
@@ -273,8 +313,8 @@ importers:
specifier: 5.8.3
version: 5.8.3
typescript-eslint:
- specifier: ^8.59.2
- version: 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
+ specifier: ^8.67.0
+ version: 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
sites/mainweb:
dependencies:
@@ -290,6 +330,9 @@ importers:
'@query/db':
specifier: workspace:*
version: link:../../packages/db
+ '@query/dsgt-slack':
+ specifier: workspace:*
+ version: link:../../apps/dsgt-slack
'@query/ui':
specifier: workspace:*
version: link:../../packages/ui
@@ -307,7 +350,7 @@ importers:
version: 11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2)
'@trpc/next':
specifier: 11.18.0
- version: 11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/react-query@11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(react@19.2.7)(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react-dom@19.0.0(react@19.2.7))(react@19.2.7)(typescript@6.0.2)
+ version: 11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/react-query@11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(react@19.2.7)(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react-dom@19.0.0(react@19.2.7))(react@19.2.7)(typescript@6.0.2)
'@trpc/react-query':
specifier: 11.18.0
version: 11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(react@19.2.7)(typescript@6.0.2)
@@ -325,19 +368,19 @@ importers:
version: 0.45.2(@opentelemetry/api@1.9.1)(@types/pg@8.20.0)(pg@8.21.0)(postgres@3.4.3)
geist:
specifier: ^1.5.1
- version: 1.7.0(next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))
+ version: 1.7.0(next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))
lucide-react:
- specifier: ^1.14.0
- version: 1.14.0(react@19.2.7)
+ specifier: ^1.31.0
+ version: 1.35.0(react@19.2.7)
minimatch:
specifier: 10.2.3
version: 10.2.3
next:
specifier: 16.3.0
- version: 16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
+ version: 16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
next-auth:
specifier: 5.0.0-beta.32
- version: 5.0.0-beta.32(next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react@19.2.7)
+ version: 5.0.0-beta.32(next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react@19.2.7)
next-themes:
specifier: ^0.4.6
version: 0.4.6(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
@@ -433,8 +476,8 @@ importers:
specifier: ^6.0.2
version: 6.0.2
typescript-eslint:
- specifier: ^8.59.2
- version: 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ specifier: ^8.67.0
+ version: 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
tooling/eslint:
dependencies:
@@ -442,23 +485,23 @@ importers:
specifier: 1.2.0
version: 1.2.0(eslint@10.1.0(jiti@2.7.0))
'@eslint/js':
- specifier: 9.17.0
- version: 9.17.0
+ specifier: 10.0.1
+ version: 10.0.1(eslint@10.1.0(jiti@2.7.0))
'@next/eslint-plugin-next':
specifier: 16.3.0
version: 16.3.0(eslint@10.1.0(jiti@2.7.0))
'@typescript-eslint/eslint-plugin':
- specifier: 8.59.2
- version: 8.59.2(@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ specifier: 8.67.0
+ version: 8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
'@typescript-eslint/parser':
- specifier: 8.59.2
- version: 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ specifier: 8.67.0
+ version: 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
eslint-config-prettier:
specifier: 9.1.0
version: 9.1.0(eslint@10.1.0(jiti@2.7.0))
eslint-plugin-import:
specifier: 2.31.0
- version: 2.31.0(@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0))
+ version: 2.31.0(@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0))
eslint-plugin-jsx-a11y:
specifier: 6.10.2
version: 6.10.2(eslint@10.1.0(jiti@2.7.0))
@@ -478,8 +521,8 @@ importers:
specifier: 10.2.3
version: 10.2.3
typescript-eslint:
- specifier: 8.59.2
- version: 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ specifier: 8.67.0
+ version: 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
devDependencies:
'@query/prettier-config':
specifier: workspace:*
@@ -529,7 +572,7 @@ importers:
version: 4.0.0
next:
specifier: 16.3.0
- version: 16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
+ version: 16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
postcss:
specifier: ^8.5.23
version: 8.5.23
@@ -576,8 +619,8 @@ packages:
nodemailer:
optional: true
- '@auth/drizzle-adapter@1.7.1':
- resolution: {integrity: sha512-WJSh39zEtynJw6GVS8MCnB2qXw1q7IkMbG2GiHx4jiQWDpHXE+idGSeBuZXS+J8tQnLexQa6v8hnz+wmalM74w==}
+ '@auth/drizzle-adapter@1.11.3':
+ resolution: {integrity: sha512-TxqVasPVuf7LDAT1Yuu6bftpuet8o0tjdXW+mXpnXWdSRPQsomdzMoz9RsXkFN/JfdK+/DwdgOEmOTv1gbiFNw==}
'@babel/code-frame@7.29.0':
resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
@@ -828,9 +871,14 @@ packages:
resolution: {integrity: sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==}
engines: {node: ^20.19.0 || ^22.13.0 || >=24}
- '@eslint/js@9.17.0':
- resolution: {integrity: sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@eslint/js@10.0.1':
+ resolution: {integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==}
+ engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+ peerDependencies:
+ eslint: ^10.0.0
+ peerDependenciesMeta:
+ eslint:
+ optional: true
'@eslint/object-schema@3.0.3':
resolution: {integrity: sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==}
@@ -1248,11 +1296,6 @@ packages:
resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==}
engines: {node: '>= 10.0.0'}
- '@playwright/test@1.60.0':
- resolution: {integrity: sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==}
- engines: {node: '>=18'}
- hasBin: true
-
'@polka/url@1.0.0-next.29':
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
@@ -1779,6 +1822,46 @@ packages:
'@rtsao/scc@1.1.0':
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
+ '@slack/bolt@5.0.0':
+ resolution: {integrity: sha512-L0FTzidrDKTu4Ph8sdv0bB3acafBTAC02TBcD+hojPTTNSMX3hSK+rkpkUKkqbbc0vGpSjd6A/g71Rjy7EbBhw==}
+ engines: {node: '>=20', npm: '>=9.6.4'}
+ peerDependencies:
+ '@types/express': ^5.0.0
+
+ '@slack/logger@4.0.1':
+ resolution: {integrity: sha512-6cmdPrV/RYfd2U0mDGiMK8S7OJqpCTm7enMLRR3edccsPX8j7zXTLnaEF4fhxxJJTAIOil6+qZrnUPTuaLvwrQ==}
+ engines: {node: '>= 18', npm: '>= 8.6.0'}
+
+ '@slack/logger@5.0.0':
+ resolution: {integrity: sha512-VGXhmmgsAo9shdQYh4tFDndd+7nsgp0Y5h0UPDaUp8K359pBasI6YdkMqFW3mCOxLQkq09qj7o7cq6f3DuXcJQ==}
+ engines: {node: '>= 20', npm: '>=9.6.4'}
+
+ '@slack/oauth@4.0.0':
+ resolution: {integrity: sha512-Aqs5bGghT+VtNcdwVOQy7CcyCfDNd9YYnZsCRukIF9p1Mxuq4uL+BjqlWQB0SeS4wzrLzePPgvj8JDuQil+ezA==}
+ engines: {node: '>=20', npm: '>=9.6.4'}
+
+ '@slack/socket-mode@3.0.1':
+ resolution: {integrity: sha512-7L4adgnJtQvQgo5cfIwqHG1QuR8mdZQ/WdMScNDp6uK644ZqnHDAa4rR+vZYfZFdJ5+obCqZQ66Dad8kcwJ4Jg==}
+ engines: {node: '>=20', npm: '>=9.6.4'}
+ peerDependencies:
+ undici: ^6.27.0
+
+ '@slack/types@2.22.0':
+ resolution: {integrity: sha512-sZ9lIgJhPX2qft/tKWiklFlc0o1FWeI7QtciZJfW1+ErH1eGGHvOZ8e73sleTCFEFJp1q/R0WeS8Oa7AsiDprg==}
+ engines: {node: '>= 12.13.0', npm: '>= 6.12.0'}
+
+ '@slack/types@3.1.0':
+ resolution: {integrity: sha512-bTzqrO3lxJ5iWedo1eJKNAs1koyEhaTwKLJUkD3KETnPeQvD978AAE4jvWstUws8Gbbc4JR6iYE6F7XjE8UGmw==}
+ engines: {node: '>= 20', npm: '>=9.6.4'}
+
+ '@slack/web-api@7.19.0':
+ resolution: {integrity: sha512-ItjyjEZml+LDH8CjcCLRLJHh7VZtevPKExrRN3l5KWyBliyDnGAeoO4Y+K+fFBmRpKLYVPgqWMX4THldv2HVtA==}
+ engines: {node: '>= 18', npm: '>= 8.6.0'}
+
+ '@slack/web-api@8.1.1':
+ resolution: {integrity: sha512-am/z/LLbEC7gNQp6FpaGT0l4XnWqcXetpwdgZHzS7Nbb96q9R9QwWA3lo0ZXGuAHDkct0MvFnouzuc2Y4XNmow==}
+ engines: {node: '>= 20', npm: '>=9.6.4'}
+
'@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
@@ -2010,9 +2093,15 @@ packages:
'@tweenjs/tween.js@23.1.3':
resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==}
+ '@types/body-parser@1.19.6':
+ resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==}
+
'@types/chai@5.2.3':
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
+ '@types/connect@3.4.38':
+ resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
+
'@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
@@ -2034,16 +2123,31 @@ packages:
'@types/estree@1.0.9':
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+ '@types/express-serve-static-core@5.1.3':
+ resolution: {integrity: sha512-dPfW8NFiOF4wOHc7+N/QSxlY9cfSsenewGbAz8C8U/MULPd/YZ27LvJUIlzaXie7e6Ove9YunJGgC9tbHD2cKw==}
+
+ '@types/express@5.0.6':
+ resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==}
+
+ '@types/http-errors@2.0.5':
+ resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==}
+
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
'@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+ '@types/jsonwebtoken@9.0.10':
+ resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==}
+
'@types/minimatch@6.0.0':
resolution: {integrity: sha512-zmPitbQ8+6zNutpwgcQuLcsEpn/Cj54Kbn7L5pX0Os5kdWplB7xPgEh/g+SWOB/qmows2gpuCaPyduq8ZZRnxA==}
deprecated: This is a stub types definition. minimatch provides its own type definitions, so you do not need this installed.
+ '@types/ms@2.1.0':
+ resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+
'@types/node@20.19.40':
resolution: {integrity: sha512-xxx6M2IpSTnnKcR0cMvIiohkiCx20/oRPtWGbenFygKCGl3zqUzdNjQ/1V4solq1LU+dgv0nQzeGOuqkqZGg0Q==}
@@ -2060,6 +2164,12 @@ packages:
'@types/qrcode@1.5.6':
resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==}
+ '@types/qs@6.15.1':
+ resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==}
+
+ '@types/range-parser@1.2.7':
+ resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
+
'@types/react-dom@19.0.3':
resolution: {integrity: sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==}
peerDependencies:
@@ -2071,9 +2181,21 @@ packages:
'@types/react@19.2.17':
resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==}
+ '@types/retry@0.12.0':
+ resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==}
+
+ '@types/retry@0.12.5':
+ resolution: {integrity: sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==}
+
'@types/sanitize-html@2.16.1':
resolution: {integrity: sha512-n9wjs8bCOTyN/ynwD8s/nTcTreIHB1vf31vhLMGqUPNHaweKC4/fAl4Dj+hUlCTKYgm4P3k83fmiFfzkZ6sgMA==}
+ '@types/send@1.2.1':
+ resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==}
+
+ '@types/serve-static@2.2.0':
+ resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==}
+
'@types/stats.js@0.17.4':
resolution: {integrity: sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==}
@@ -2083,70 +2205,107 @@ packages:
'@types/webxr@0.5.24':
resolution: {integrity: sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==}
- '@typescript-eslint/eslint-plugin@8.59.2':
- resolution: {integrity: sha512-j/bwmkBvHUtPNxzuWe5z6BEk3q54YRyGlBXkSsmfoih7zNrBvl5A9A98anlp/7JbyZcWIJ8KXo/3Tq/DjFLtuQ==}
+ '@typescript-eslint/eslint-plugin@8.67.0':
+ resolution: {integrity: sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- '@typescript-eslint/parser': ^8.59.2
+ '@typescript-eslint/parser': ^8.67.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/parser@8.59.2':
- resolution: {integrity: sha512-plR3pp6D+SSUn1HM7xvSkx12/DhoHInI2YF35KAcVFNZvlC0gtrWqx7Qq1oH2Ssgi0vlFRCTbP+DZc7B9+TtsQ==}
+ '@typescript-eslint/parser@8.67.0':
+ resolution: {integrity: sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/project-service@8.59.2':
- resolution: {integrity: sha512-+2hqvEkeyf/0FBor67duF0Ll7Ot8jyKzDQOSrxazF/danillRq2DwR9dLptsXpoZQqxE1UisSmoZewrlPas9Vw==}
+ '@typescript-eslint/project-service@8.67.0':
+ resolution: {integrity: sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/scope-manager@8.59.2':
- resolution: {integrity: sha512-JzfyEpEtOU89CcFSwyNS3mu4MLvLSXqnmX05+aKBDM+TdR5jzcGOEBwxwGNxrEQ7p/z6kK2WyioCGBf2zZBnvg==}
+ '@typescript-eslint/project-service@8.68.0':
+ resolution: {integrity: sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.1.0'
+
+ '@typescript-eslint/scope-manager@8.67.0':
+ resolution: {integrity: sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/scope-manager@8.68.0':
+ resolution: {integrity: sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/tsconfig-utils@8.67.0':
+ resolution: {integrity: sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/tsconfig-utils@8.59.2':
- resolution: {integrity: sha512-BKK4alN7oi4C/zv4VqHQ+uRU+lTa6JGIZ7s1juw7b3RHo9OfKB+bKX3u0iVZetdsUCBBkSbdWbarJbmN0fTeSw==}
+ '@typescript-eslint/tsconfig-utils@8.68.0':
+ resolution: {integrity: sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/type-utils@8.59.2':
- resolution: {integrity: sha512-nhqaj1nmTdVVl/BP5omXNRGO38jn5iosis2vbdmupF2txCf8ylWT8lx+JlvMYYVqzGVKtjojUFoQ3JRWK+mfzQ==}
+ '@typescript-eslint/type-utils@8.67.0':
+ resolution: {integrity: sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/types@8.59.2':
- resolution: {integrity: sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==}
+ '@typescript-eslint/types@8.67.0':
+ resolution: {integrity: sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/types@8.68.0':
+ resolution: {integrity: sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/typescript-estree@8.67.0':
+ resolution: {integrity: sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.1.0'
+
+ '@typescript-eslint/typescript-estree@8.68.0':
+ resolution: {integrity: sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/typescript-estree@8.59.2':
- resolution: {integrity: sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg==}
+ '@typescript-eslint/utils@8.67.0':
+ resolution: {integrity: sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/utils@8.59.2':
- resolution: {integrity: sha512-Juw3EinkXqjaffxz6roowvV7GZT/kET5vSKKZT6upl5TXdWkLkYmNPXwDDL2Vkt2DPn0nODIS4egC/0AGxKo/Q==}
+ '@typescript-eslint/utils@8.68.0':
+ resolution: {integrity: sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
- '@typescript-eslint/visitor-keys@8.59.2':
- resolution: {integrity: sha512-NwjLUnGy8/Zfx23fl50tRC8rYaYnM52xNRYFAXvmiil9yh1+K6aRVQMnzW6gQB/1DLgWt977lYQn7C+wtgXZiA==}
+ '@typescript-eslint/visitor-keys@8.67.0':
+ resolution: {integrity: sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@vitest/expect@4.1.8':
- resolution: {integrity: sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==}
+ '@typescript-eslint/visitor-keys@8.68.0':
+ resolution: {integrity: sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@vitest/expect@4.1.11':
+ resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==}
- '@vitest/mocker@4.1.8':
- resolution: {integrity: sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==}
+ '@vitest/mocker@4.1.11':
+ resolution: {integrity: sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==}
peerDependencies:
msw: ^2.4.9
vite: ^7.3.5
@@ -2156,20 +2315,20 @@ packages:
vite:
optional: true
- '@vitest/pretty-format@4.1.8':
- resolution: {integrity: sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==}
+ '@vitest/pretty-format@4.1.11':
+ resolution: {integrity: sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==}
- '@vitest/runner@4.1.8':
- resolution: {integrity: sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==}
+ '@vitest/runner@4.1.11':
+ resolution: {integrity: sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==}
- '@vitest/snapshot@4.1.8':
- resolution: {integrity: sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==}
+ '@vitest/snapshot@4.1.11':
+ resolution: {integrity: sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==}
- '@vitest/spy@4.1.8':
- resolution: {integrity: sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==}
+ '@vitest/spy@4.1.11':
+ resolution: {integrity: sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==}
- '@vitest/utils@4.1.8':
- resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==}
+ '@vitest/utils@4.1.11':
+ resolution: {integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==}
'@yudiel/react-qr-scanner@2.5.1':
resolution: {integrity: sha512-FWzHaCneu30mQpE80VNWx4IPtBjXFEiTzhwWunZy3afvvAy/x0aVIgYijJKEbROoaAeDfcJ/gIyUCqPBP7bMOw==}
@@ -2177,6 +2336,10 @@ packages:
react: ^17 || ^18 || ^19
react-dom: ^17 || ^18 || ^19
+ accepts@2.0.0:
+ resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
+ engines: {node: '>= 0.6'}
+
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -2191,6 +2354,10 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
+ agent-base@6.0.2:
+ resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
+ engines: {node: '>= 6.0.0'}
+
ajv@6.15.0:
resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==}
@@ -2253,6 +2420,9 @@ packages:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
+ asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
autoprefixer@10.4.22:
resolution: {integrity: sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==}
engines: {node: ^10 || ^12 || >=14}
@@ -2268,6 +2438,9 @@ packages:
resolution: {integrity: sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA==}
engines: {node: '>=4'}
+ axios@1.20.0:
+ resolution: {integrity: sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==}
+
axobject-query@4.1.0:
resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
engines: {node: '>= 0.4'}
@@ -2294,6 +2467,10 @@ packages:
bintrees@1.0.2:
resolution: {integrity: sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==}
+ body-parser@2.3.0:
+ resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==}
+ engines: {node: '>=18'}
+
brace-expansion@5.0.9:
resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==}
engines: {node: 20 || >=22}
@@ -2307,9 +2484,16 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
+ buffer-equal-constant-time@1.0.1:
+ resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
+
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+ bytes@3.1.2:
+ resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
+ engines: {node: '>= 0.8'}
+
call-bind-apply-helpers@1.0.2:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'}
@@ -2357,13 +2541,37 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+
commander@7.2.0:
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
engines: {node: '>= 10'}
+ content-disposition@1.1.0:
+ resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==}
+ engines: {node: '>=18'}
+
+ content-type@1.0.5:
+ resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
+ engines: {node: '>= 0.6'}
+
+ content-type@2.1.0:
+ resolution: {integrity: sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==}
+ engines: {node: '>=18'}
+
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ cookie-signature@1.2.2:
+ resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
+ engines: {node: '>=6.6.0'}
+
+ cookie@0.7.2:
+ resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
+ engines: {node: '>= 0.6'}
+
copy-anything@4.0.5:
resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==}
engines: {node: '>=18'}
@@ -2437,6 +2645,14 @@ packages:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
engines: {node: '>= 0.4'}
+ delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+
+ depd@2.0.0:
+ resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+ engines: {node: '>= 0.8'}
+
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
@@ -2575,6 +2791,12 @@ packages:
duplexer@0.1.2:
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
+ ecdsa-sig-formatter@1.0.11:
+ resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
+
+ ee-first@1.1.1:
+ resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+
electron-to-chromium@1.5.353:
resolution: {integrity: sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==}
@@ -2584,6 +2806,10 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+ encodeurl@2.0.0:
+ resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
+ engines: {node: '>= 0.8'}
+
enhanced-resolve@5.21.2:
resolution: {integrity: sha512-xe9vQb5kReirPUxgQrXA3ihgbCqssmTiM7cOZ+Gzu+VeGWgpV98lLZvp0dl4yriyAePcewxGUs9UpKD8PET9KQ==}
engines: {node: '>=10.13.0'}
@@ -2640,6 +2866,9 @@ packages:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
+ escape-html@1.0.3:
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
@@ -2759,10 +2988,24 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
+ etag@1.8.1:
+ resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
+ engines: {node: '>= 0.6'}
+
+ eventemitter3@4.0.7:
+ resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
+
+ eventemitter3@5.0.4:
+ resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==}
+
expect-type@1.3.0:
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
engines: {node: '>=12.0.0'}
+ express@5.2.1:
+ resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==}
+ engines: {node: '>= 18'}
+
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@@ -2799,6 +3042,10 @@ packages:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
+ finalhandler@2.1.1:
+ resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==}
+ engines: {node: '>= 18.0.0'}
+
find-up@4.1.0:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
engines: {node: '>=8'}
@@ -2814,10 +3061,27 @@ packages:
flatted@3.4.2:
resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==}
+ follow-redirects@1.16.0:
+ resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+
for-each@0.3.5:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
+ form-data@4.0.6:
+ resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==}
+ engines: {node: '>= 6'}
+
+ forwarded@0.2.0:
+ resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
+ engines: {node: '>= 0.6'}
+
fraction.js@5.3.4:
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
@@ -2835,10 +3099,9 @@ packages:
react-dom:
optional: true
- fsevents@2.3.2:
- resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
- engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
- os: [darwin]
+ fresh@2.0.0:
+ resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
+ engines: {node: '>= 0.8'}
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
@@ -2937,12 +3200,28 @@ packages:
resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==}
engines: {node: '>= 0.4'}
+ hasown@2.0.4:
+ resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
+ engines: {node: '>= 0.4'}
+
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
htmlparser2@10.1.0:
resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==}
+ http-errors@2.0.1:
+ resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
+ engines: {node: '>= 0.8'}
+
+ https-proxy-agent@5.0.1:
+ resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
+ engines: {node: '>= 6'}
+
+ iconv-lite@0.7.3:
+ resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==}
+ engines: {node: '>=0.10.0'}
+
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -2960,10 +3239,17 @@ packages:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
internal-slot@1.1.0:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
+ ipaddr.js@1.9.1:
+ resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
+ engines: {node: '>= 0.10'}
+
is-array-buffer@3.0.5:
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
engines: {node: '>= 0.4'}
@@ -2996,6 +3282,9 @@ packages:
resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
engines: {node: '>= 0.4'}
+ is-electron@2.2.2:
+ resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==}
+
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
@@ -3036,6 +3325,9 @@ packages:
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
engines: {node: '>=0.10.0'}
+ is-promise@4.0.0:
+ resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
+
is-regex@1.2.1:
resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
engines: {node: '>= 0.4'}
@@ -3048,6 +3340,10 @@ packages:
resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
engines: {node: '>= 0.4'}
+ is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+
is-string@1.1.1:
resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
engines: {node: '>= 0.4'}
@@ -3114,10 +3410,20 @@ packages:
resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
hasBin: true
+ jsonwebtoken@9.0.3:
+ resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==}
+ engines: {node: '>=12', npm: '>=6'}
+
jsx-ast-utils@3.3.5:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
engines: {node: '>=4.0'}
+ jwa@2.0.1:
+ resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
+
+ jws@4.0.1:
+ resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
+
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@@ -3217,6 +3523,27 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
+ lodash.includes@4.3.0:
+ resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
+
+ lodash.isboolean@3.0.3:
+ resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
+
+ lodash.isinteger@4.0.4:
+ resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
+
+ lodash.isnumber@3.0.3:
+ resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
+
+ lodash.isplainobject@4.0.6:
+ resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
+
+ lodash.isstring@4.0.1:
+ resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
+
+ lodash.once@4.1.1:
+ resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
+
lodash.throttle@4.1.1:
resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
@@ -3224,8 +3551,8 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
- lucide-react@1.14.0:
- resolution: {integrity: sha512-+1mdWcfSJVUsaTIjN9zoezmUhfXo5l0vP7ekBMPo3jcS/aIkxHnXqAPsByszMZx/Y8oQBRJxJx5xg+RH3urzxA==}
+ lucide-react@1.35.0:
+ resolution: {integrity: sha512-yXCCWxGFYT6bLIPYC4SY6fPQPRs/d797rRIue+J9XP2Td6vQvD53gaQRBCnIVT1kTQRHtAtxlfOQNWAuIF8ELg==}
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
@@ -3236,6 +3563,14 @@ packages:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
+ media-typer@1.1.1:
+ resolution: {integrity: sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==}
+ engines: {node: '>= 0.8'}
+
+ merge-descriptors@2.0.0:
+ resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
+ engines: {node: '>=18'}
+
merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
@@ -3247,6 +3582,22 @@ packages:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-db@1.54.0:
+ resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@3.0.2:
+ resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
+ engines: {node: '>=18'}
+
minimatch@10.2.3:
resolution: {integrity: sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==}
engines: {node: 18 || 20 || >=22}
@@ -3286,6 +3637,10 @@ packages:
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ negotiator@1.1.0:
+ resolution: {integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==}
+ engines: {node: '>=18'}
+
next-auth@5.0.0-beta.32:
resolution: {integrity: sha512-CGlChIEWZ6LltNVxrE5yiySMID+Idpmry47JYA5lLwgD8Sx02a8M65VL0TWVz9nbnOioS/tCW/rP/0+mE7Qp4Q==}
peerDependencies:
@@ -3385,6 +3740,13 @@ packages:
obug@2.1.1:
resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
+ on-finished@2.4.1:
+ resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
+ engines: {node: '>= 0.8'}
+
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
opener@1.5.2:
resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==}
hasBin: true
@@ -3397,6 +3759,10 @@ packages:
resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
engines: {node: '>= 0.4'}
+ p-finally@1.0.0:
+ resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==}
+ engines: {node: '>=4'}
+
p-limit@2.3.0:
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
engines: {node: '>=6'}
@@ -3413,6 +3779,18 @@ packages:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
+ p-queue@6.6.2:
+ resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==}
+ engines: {node: '>=8'}
+
+ p-retry@4.6.2:
+ resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==}
+ engines: {node: '>=8'}
+
+ p-timeout@3.2.0:
+ resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==}
+ engines: {node: '>=8'}
+
p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
@@ -3420,6 +3798,10 @@ packages:
parse-srcset@1.0.2:
resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==}
+ parseurl@1.3.3:
+ resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
+ engines: {node: '>= 0.8'}
+
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
@@ -3431,6 +3813,9 @@ packages:
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ path-to-regexp@8.4.2:
+ resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==}
+
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
@@ -3482,16 +3867,6 @@ packages:
resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
engines: {node: '>=12'}
- playwright-core@1.60.0:
- resolution: {integrity: sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==}
- engines: {node: '>=18'}
- hasBin: true
-
- playwright@1.60.0:
- resolution: {integrity: sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==}
- engines: {node: '>=18'}
- hasBin: true
-
pngjs@5.0.0:
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
engines: {node: '>=10.13.0'}
@@ -3617,6 +3992,14 @@ packages:
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ proxy-addr@2.0.7:
+ resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
+ engines: {node: '>= 0.10'}
+
+ proxy-from-env@2.1.0:
+ resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==}
+ engines: {node: '>=10'}
+
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
@@ -3631,9 +4014,21 @@ packages:
engines: {node: '>=10.13.0'}
hasBin: true
+ qs@6.15.3:
+ resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==}
+ engines: {node: '>=0.6'}
+
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ range-parser@1.3.0:
+ resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==}
+ engines: {node: '>= 0.6'}
+
+ raw-body@3.0.2:
+ resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==}
+ engines: {node: '>= 0.10'}
+
react-chartjs-2@5.3.1:
resolution: {integrity: sha512-h5IPXKg9EXpjoBzUfyWJvllMjG2mQ4EiuHQFhms/AjUm0XSZHhyRy2xVmLXHKrtcdrPO4mnGqRtYoD0vp95A0A==}
peerDependencies:
@@ -3711,6 +4106,10 @@ packages:
engines: {node: '>= 0.4'}
hasBin: true
+ retry@0.13.1:
+ resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
+ engines: {node: '>= 4'}
+
reusify@1.1.0:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -3720,6 +4119,10 @@ packages:
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
+ router@2.2.0:
+ resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==}
+ engines: {node: '>= 18'}
+
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
@@ -3727,6 +4130,9 @@ packages:
resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==}
engines: {node: '>=0.4'}
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
safe-push-apply@1.0.0:
resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
engines: {node: '>= 0.4'}
@@ -3735,6 +4141,9 @@ packages:
resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
engines: {node: '>= 0.4'}
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
sanitize-html@2.17.4:
resolution: {integrity: sha512-2HW7v2ol/uAM7sX4hbD8Z59OGWmAPrvjL8E71UWlBcj6m+kcF6ilQBLny+cIgY214QJeJT5tQuxKKqX0SQqjGQ==}
@@ -3761,6 +4170,14 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ send@1.2.1:
+ resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==}
+ engines: {node: '>= 18'}
+
+ serve-static@2.2.1:
+ resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==}
+ engines: {node: '>= 18'}
+
set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
@@ -3776,6 +4193,9 @@ packages:
resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
engines: {node: '>= 0.4'}
+ setprototypeof@1.2.0:
+ resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+
sharp@0.35.3:
resolution: {integrity: sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==}
engines: {node: '>=20.9.0'}
@@ -3809,6 +4229,10 @@ packages:
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
engines: {node: '>= 0.4'}
+ side-channel@1.1.1:
+ resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==}
+ engines: {node: '>= 0.4'}
+
siginfo@2.0.0:
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
@@ -3834,6 +4258,10 @@ packages:
stackback@0.0.2:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+ statuses@2.0.2:
+ resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
+ engines: {node: '>= 0.8'}
+
std-env@4.0.0:
resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==}
@@ -3945,6 +4373,10 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
+ toidentifier@1.0.1:
+ resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
+ engines: {node: '>=0.6'}
+
totalist@3.0.1:
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
engines: {node: '>=6'}
@@ -3961,6 +4393,10 @@ packages:
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+ tsscmp@1.0.6:
+ resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==}
+ engines: {node: '>=0.6.x'}
+
tsx@4.21.0:
resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==}
engines: {node: '>=18.0.0'}
@@ -3978,6 +4414,10 @@ packages:
resolution: {integrity: sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==}
engines: {node: '>=20'}
+ type-is@2.1.0:
+ resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==}
+ engines: {node: '>= 18'}
+
typed-array-buffer@1.0.3:
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
engines: {node: '>= 0.4'}
@@ -3994,8 +4434,8 @@ packages:
resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
engines: {node: '>= 0.4'}
- typescript-eslint@8.59.2:
- resolution: {integrity: sha512-pJw051uomb3ZeCzGTpRb8RbEqB5Y4WWet8gl/GcTlU35BSx0PVdZ86/bqkQCyKKuraVQEK7r6kBHQXF+fBhkoQ==}
+ typescript-eslint@8.67.0:
+ resolution: {integrity: sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
@@ -4018,6 +4458,14 @@ packages:
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+ undici@6.28.0:
+ resolution: {integrity: sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==}
+ engines: {node: '>=18.17'}
+
+ unpipe@1.0.0:
+ resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+ engines: {node: '>= 0.8'}
+
update-browserslist-db@1.2.3:
resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
hasBin: true
@@ -4047,6 +4495,10 @@ packages:
'@types/react':
optional: true
+ vary@1.1.2:
+ resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+ engines: {node: '>= 0.8'}
+
vite@7.3.6:
resolution: {integrity: sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -4087,20 +4539,20 @@ packages:
yaml:
optional: true
- vitest@4.1.8:
- resolution: {integrity: sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==}
+ vitest@4.1.11:
+ resolution: {integrity: sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==}
engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@opentelemetry/api': ^1.9.0
'@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
- '@vitest/browser-playwright': 4.1.8
- '@vitest/browser-preview': 4.1.8
- '@vitest/browser-webdriverio': 4.1.8
- '@vitest/coverage-istanbul': 4.1.8
- '@vitest/coverage-v8': 4.1.8
- '@vitest/ui': 4.1.8
+ '@vitest/browser-playwright': 4.1.11
+ '@vitest/browser-preview': 4.1.11
+ '@vitest/browser-webdriverio': 4.1.11
+ '@vitest/coverage-istanbul': 4.1.11
+ '@vitest/coverage-v8': 4.1.11
+ '@vitest/ui': 4.1.11
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
@@ -4173,6 +4625,9 @@ packages:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
ws@8.21.0:
resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==}
engines: {node: '>=10.0.0'}
@@ -4230,7 +4685,7 @@ snapshots:
optionalDependencies:
nodemailer: 9.0.3
- '@auth/drizzle-adapter@1.7.1(nodemailer@9.0.3)':
+ '@auth/drizzle-adapter@1.11.3(nodemailer@9.0.3)':
dependencies:
'@auth/core': 0.41.3(nodemailer@9.0.3)
transitivePeerDependencies:
@@ -4415,7 +4870,9 @@ snapshots:
dependencies:
'@types/json-schema': 7.0.15
- '@eslint/js@9.17.0': {}
+ '@eslint/js@10.0.1(eslint@10.1.0(jiti@2.7.0))':
+ optionalDependencies:
+ eslint: 10.1.0(jiti@2.7.0)
'@eslint/object-schema@3.0.3': {}
@@ -4733,10 +5190,6 @@ snapshots:
'@parcel/watcher-win32-ia32': 2.5.6
'@parcel/watcher-win32-x64': 2.5.6
- '@playwright/test@1.60.0':
- dependencies:
- playwright: 1.60.0
-
'@polka/url@1.0.0-next.29': {}
'@radix-ui/number@1.1.1': {}
@@ -5214,6 +5667,79 @@ snapshots:
'@rtsao/scc@1.1.0': {}
+ '@slack/bolt@5.0.0(@types/express@5.0.6)(undici@6.28.0)':
+ dependencies:
+ '@slack/logger': 5.0.0
+ '@slack/oauth': 4.0.0
+ '@slack/socket-mode': 3.0.1(undici@6.28.0)
+ '@slack/types': 3.1.0
+ '@slack/web-api': 8.1.1
+ '@types/express': 5.0.6
+ express: 5.2.1
+ path-to-regexp: 8.4.2
+ raw-body: 3.0.2
+ tsscmp: 1.0.6
+ transitivePeerDependencies:
+ - supports-color
+ - undici
+
+ '@slack/logger@4.0.1':
+ dependencies:
+ '@types/node': 22.15.32
+
+ '@slack/logger@5.0.0':
+ dependencies:
+ '@types/node': 22.15.32
+
+ '@slack/oauth@4.0.0':
+ dependencies:
+ '@slack/logger': 5.0.0
+ '@slack/web-api': 8.1.1
+ '@types/jsonwebtoken': 9.0.10
+ '@types/node': 22.15.32
+ jsonwebtoken: 9.0.3
+
+ '@slack/socket-mode@3.0.1(undici@6.28.0)':
+ dependencies:
+ '@slack/logger': 5.0.0
+ '@slack/web-api': 8.1.1
+ '@types/node': 22.15.32
+ eventemitter3: 5.0.4
+ undici: 6.28.0
+
+ '@slack/types@2.22.0': {}
+
+ '@slack/types@3.1.0': {}
+
+ '@slack/web-api@7.19.0':
+ dependencies:
+ '@slack/logger': 4.0.1
+ '@slack/types': 2.22.0
+ '@types/node': 22.15.32
+ '@types/retry': 0.12.0
+ axios: 1.20.0
+ eventemitter3: 5.0.4
+ form-data: 4.0.6
+ is-electron: 2.2.2
+ is-stream: 2.0.1
+ p-queue: 6.6.2
+ p-retry: 4.6.2
+ retry: 0.13.1
+ transitivePeerDependencies:
+ - debug
+ - supports-color
+
+ '@slack/web-api@8.1.1':
+ dependencies:
+ '@slack/logger': 5.0.0
+ '@slack/types': 3.1.0
+ '@types/node': 22.15.32
+ '@types/retry': 0.12.5
+ eventemitter3: 5.0.4
+ p-queue: 6.6.2
+ p-retry: 4.6.2
+ retry: 0.13.1
+
'@standard-schema/spec@1.1.0': {}
'@stripe/react-stripe-js@3.10.0(@stripe/stripe-js@5.10.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)':
@@ -5341,11 +5867,11 @@ snapshots:
'@trpc/server': 11.18.0(typescript@6.0.2)
typescript: 6.0.2
- '@trpc/next@11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/react-query@11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(react@19.2.7)(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react-dom@19.0.0(react@19.2.7))(react@19.2.7)(typescript@6.0.2)':
+ '@trpc/next@11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/react-query@11.18.0(@tanstack/react-query@5.90.12(react@19.2.7))(@trpc/client@11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(react@19.2.7)(typescript@6.0.2))(@trpc/server@11.18.0(typescript@6.0.2))(next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react-dom@19.0.0(react@19.2.7))(react@19.2.7)(typescript@6.0.2)':
dependencies:
'@trpc/client': 11.18.0(@trpc/server@11.18.0(typescript@6.0.2))(typescript@6.0.2)
'@trpc/server': 11.18.0(typescript@6.0.2)
- next: 16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
+ next: 16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
react: 19.2.7
react-dom: 19.0.0(react@19.2.7)
typescript: 6.0.2
@@ -5385,11 +5911,20 @@ snapshots:
'@tweenjs/tween.js@23.1.3': {}
+ '@types/body-parser@1.19.6':
+ dependencies:
+ '@types/connect': 3.4.38
+ '@types/node': 22.15.32
+
'@types/chai@5.2.3':
dependencies:
'@types/deep-eql': 4.0.2
assertion-error: 2.0.1
+ '@types/connect@3.4.38':
+ dependencies:
+ '@types/node': 22.15.32
+
'@types/deep-eql@4.0.2': {}
'@types/emscripten@1.41.5': {}
@@ -5409,14 +5944,36 @@ snapshots:
'@types/estree@1.0.9': {}
+ '@types/express-serve-static-core@5.1.3':
+ dependencies:
+ '@types/node': 22.15.32
+ '@types/qs': 6.15.1
+ '@types/range-parser': 1.2.7
+ '@types/send': 1.2.1
+
+ '@types/express@5.0.6':
+ dependencies:
+ '@types/body-parser': 1.19.6
+ '@types/express-serve-static-core': 5.1.3
+ '@types/serve-static': 2.2.0
+
+ '@types/http-errors@2.0.5': {}
+
'@types/json-schema@7.0.15': {}
'@types/json5@0.0.29': {}
+ '@types/jsonwebtoken@9.0.10':
+ dependencies:
+ '@types/ms': 2.1.0
+ '@types/node': 22.15.32
+
'@types/minimatch@6.0.0':
dependencies:
minimatch: 10.2.3
+ '@types/ms@2.1.0': {}
+
'@types/node@20.19.40':
dependencies:
undici-types: 6.21.0
@@ -5441,6 +5998,10 @@ snapshots:
dependencies:
'@types/node': 22.15.32
+ '@types/qs@6.15.1': {}
+
+ '@types/range-parser@1.2.7': {}
+
'@types/react-dom@19.0.3(@types/react@19.2.17)':
dependencies:
'@types/react': 19.2.17
@@ -5453,10 +6014,23 @@ snapshots:
dependencies:
csstype: 3.2.3
+ '@types/retry@0.12.0': {}
+
+ '@types/retry@0.12.5': {}
+
'@types/sanitize-html@2.16.1':
dependencies:
htmlparser2: 10.1.0
+ '@types/send@1.2.1':
+ dependencies:
+ '@types/node': 22.15.32
+
+ '@types/serve-static@2.2.0':
+ dependencies:
+ '@types/http-errors': 2.0.5
+ '@types/node': 22.15.32
+
'@types/stats.js@0.17.4': {}
'@types/three@0.184.1':
@@ -5470,14 +6044,14 @@ snapshots:
'@types/webxr@0.5.24': {}
- '@typescript-eslint/eslint-plugin@8.59.2(@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3))(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)':
+ '@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3))(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
- '@typescript-eslint/parser': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
- '@typescript-eslint/scope-manager': 8.59.2
- '@typescript-eslint/type-utils': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
- '@typescript-eslint/utils': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
- '@typescript-eslint/visitor-keys': 8.59.2
+ '@typescript-eslint/parser': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
+ '@typescript-eslint/scope-manager': 8.67.0
+ '@typescript-eslint/type-utils': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
+ '@typescript-eslint/utils': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
+ '@typescript-eslint/visitor-keys': 8.67.0
eslint: 10.1.0(jiti@2.7.0)
ignore: 7.0.5
natural-compare: 1.4.0
@@ -5486,14 +6060,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/eslint-plugin@8.59.2(@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)':
+ '@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)':
dependencies:
'@eslint-community/regexpp': 4.12.2
- '@typescript-eslint/parser': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
- '@typescript-eslint/scope-manager': 8.59.2
- '@typescript-eslint/type-utils': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
- '@typescript-eslint/utils': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
- '@typescript-eslint/visitor-keys': 8.59.2
+ '@typescript-eslint/parser': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ '@typescript-eslint/scope-manager': 8.67.0
+ '@typescript-eslint/type-utils': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ '@typescript-eslint/utils': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ '@typescript-eslint/visitor-keys': 8.67.0
eslint: 10.1.0(jiti@2.7.0)
ignore: 7.0.5
natural-compare: 1.4.0
@@ -5502,66 +6076,84 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)':
+ '@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/scope-manager': 8.59.2
- '@typescript-eslint/types': 8.59.2
- '@typescript-eslint/typescript-estree': 8.59.2(typescript@5.8.3)
- '@typescript-eslint/visitor-keys': 8.59.2
+ '@typescript-eslint/scope-manager': 8.67.0
+ '@typescript-eslint/types': 8.67.0
+ '@typescript-eslint/typescript-estree': 8.67.0(typescript@5.8.3)
+ '@typescript-eslint/visitor-keys': 8.67.0
debug: 4.4.3
eslint: 10.1.0(jiti@2.7.0)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)':
+ '@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)':
dependencies:
- '@typescript-eslint/scope-manager': 8.59.2
- '@typescript-eslint/types': 8.59.2
- '@typescript-eslint/typescript-estree': 8.59.2(typescript@6.0.2)
- '@typescript-eslint/visitor-keys': 8.59.2
+ '@typescript-eslint/scope-manager': 8.67.0
+ '@typescript-eslint/types': 8.67.0
+ '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.2)
+ '@typescript-eslint/visitor-keys': 8.67.0
debug: 4.4.3
eslint: 10.1.0(jiti@2.7.0)
typescript: 6.0.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/project-service@8.59.2(typescript@5.8.3)':
+ '@typescript-eslint/project-service@8.67.0(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/tsconfig-utils': 8.59.2(typescript@5.8.3)
- '@typescript-eslint/types': 8.59.2
+ '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@5.8.3)
+ '@typescript-eslint/types': 8.67.0
debug: 4.4.3
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/project-service@8.59.2(typescript@6.0.2)':
+ '@typescript-eslint/project-service@8.67.0(typescript@6.0.2)':
+ dependencies:
+ '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.2)
+ '@typescript-eslint/types': 8.67.0
+ debug: 4.4.3
+ typescript: 6.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/project-service@8.68.0(typescript@6.0.2)':
dependencies:
- '@typescript-eslint/tsconfig-utils': 8.59.2(typescript@6.0.2)
- '@typescript-eslint/types': 8.59.2
+ '@typescript-eslint/tsconfig-utils': 8.68.0(typescript@6.0.2)
+ '@typescript-eslint/types': 8.68.0
debug: 4.4.3
typescript: 6.0.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/scope-manager@8.59.2':
+ '@typescript-eslint/scope-manager@8.67.0':
+ dependencies:
+ '@typescript-eslint/types': 8.67.0
+ '@typescript-eslint/visitor-keys': 8.67.0
+
+ '@typescript-eslint/scope-manager@8.68.0':
dependencies:
- '@typescript-eslint/types': 8.59.2
- '@typescript-eslint/visitor-keys': 8.59.2
+ '@typescript-eslint/types': 8.68.0
+ '@typescript-eslint/visitor-keys': 8.68.0
- '@typescript-eslint/tsconfig-utils@8.59.2(typescript@5.8.3)':
+ '@typescript-eslint/tsconfig-utils@8.67.0(typescript@5.8.3)':
dependencies:
typescript: 5.8.3
- '@typescript-eslint/tsconfig-utils@8.59.2(typescript@6.0.2)':
+ '@typescript-eslint/tsconfig-utils@8.67.0(typescript@6.0.2)':
+ dependencies:
+ typescript: 6.0.2
+
+ '@typescript-eslint/tsconfig-utils@8.68.0(typescript@6.0.2)':
dependencies:
typescript: 6.0.2
- '@typescript-eslint/type-utils@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)':
+ '@typescript-eslint/type-utils@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/types': 8.59.2
- '@typescript-eslint/typescript-estree': 8.59.2(typescript@5.8.3)
- '@typescript-eslint/utils': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
+ '@typescript-eslint/types': 8.67.0
+ '@typescript-eslint/typescript-estree': 8.67.0(typescript@5.8.3)
+ '@typescript-eslint/utils': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
debug: 4.4.3
eslint: 10.1.0(jiti@2.7.0)
ts-api-utils: 2.5.0(typescript@5.8.3)
@@ -5569,11 +6161,11 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/type-utils@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)':
+ '@typescript-eslint/type-utils@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)':
dependencies:
- '@typescript-eslint/types': 8.59.2
- '@typescript-eslint/typescript-estree': 8.59.2(typescript@6.0.2)
- '@typescript-eslint/utils': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ '@typescript-eslint/types': 8.67.0
+ '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.2)
+ '@typescript-eslint/utils': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
debug: 4.4.3
eslint: 10.1.0(jiti@2.7.0)
ts-api-utils: 2.5.0(typescript@6.0.2)
@@ -5581,16 +6173,18 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/types@8.59.2': {}
+ '@typescript-eslint/types@8.67.0': {}
- '@typescript-eslint/typescript-estree@8.59.2(typescript@5.8.3)':
+ '@typescript-eslint/types@8.68.0': {}
+
+ '@typescript-eslint/typescript-estree@8.67.0(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/project-service': 8.59.2(typescript@5.8.3)
- '@typescript-eslint/tsconfig-utils': 8.59.2(typescript@5.8.3)
- '@typescript-eslint/types': 8.59.2
- '@typescript-eslint/visitor-keys': 8.59.2
+ '@typescript-eslint/project-service': 8.67.0(typescript@5.8.3)
+ '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@5.8.3)
+ '@typescript-eslint/types': 8.67.0
+ '@typescript-eslint/visitor-keys': 8.67.0
debug: 4.4.3
- minimatch: 10.2.4
+ minimatch: 10.2.3
semver: 7.8.5
tinyglobby: 0.2.16
ts-api-utils: 2.5.0(typescript@5.8.3)
@@ -5598,14 +6192,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/typescript-estree@8.59.2(typescript@6.0.2)':
+ '@typescript-eslint/typescript-estree@8.67.0(typescript@6.0.2)':
dependencies:
- '@typescript-eslint/project-service': 8.59.2(typescript@6.0.2)
- '@typescript-eslint/tsconfig-utils': 8.59.2(typescript@6.0.2)
- '@typescript-eslint/types': 8.59.2
- '@typescript-eslint/visitor-keys': 8.59.2
+ '@typescript-eslint/project-service': 8.67.0(typescript@6.0.2)
+ '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.2)
+ '@typescript-eslint/types': 8.67.0
+ '@typescript-eslint/visitor-keys': 8.67.0
debug: 4.4.3
- minimatch: 10.2.4
+ minimatch: 10.2.3
semver: 7.8.5
tinyglobby: 0.2.16
ts-api-utils: 2.5.0(typescript@6.0.2)
@@ -5613,71 +6207,102 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)':
+ '@typescript-eslint/typescript-estree@8.68.0(typescript@6.0.2)':
+ dependencies:
+ '@typescript-eslint/project-service': 8.68.0(typescript@6.0.2)
+ '@typescript-eslint/tsconfig-utils': 8.68.0(typescript@6.0.2)
+ '@typescript-eslint/types': 8.68.0
+ '@typescript-eslint/visitor-keys': 8.68.0
+ debug: 4.4.3
+ minimatch: 10.2.3
+ semver: 7.8.5
+ tinyglobby: 0.2.16
+ ts-api-utils: 2.5.0(typescript@6.0.2)
+ typescript: 6.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.7.0))
- '@typescript-eslint/scope-manager': 8.59.2
- '@typescript-eslint/types': 8.59.2
- '@typescript-eslint/typescript-estree': 8.59.2(typescript@5.8.3)
+ '@typescript-eslint/scope-manager': 8.67.0
+ '@typescript-eslint/types': 8.67.0
+ '@typescript-eslint/typescript-estree': 8.67.0(typescript@5.8.3)
eslint: 10.1.0(jiti@2.7.0)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)':
+ '@typescript-eslint/utils@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.7.0))
+ '@typescript-eslint/scope-manager': 8.67.0
+ '@typescript-eslint/types': 8.67.0
+ '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.2)
+ eslint: 10.1.0(jiti@2.7.0)
+ typescript: 6.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@8.68.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.7.0))
- '@typescript-eslint/scope-manager': 8.59.2
- '@typescript-eslint/types': 8.59.2
- '@typescript-eslint/typescript-estree': 8.59.2(typescript@6.0.2)
+ '@typescript-eslint/scope-manager': 8.68.0
+ '@typescript-eslint/types': 8.68.0
+ '@typescript-eslint/typescript-estree': 8.68.0(typescript@6.0.2)
eslint: 10.1.0(jiti@2.7.0)
typescript: 6.0.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/visitor-keys@8.59.2':
+ '@typescript-eslint/visitor-keys@8.67.0':
+ dependencies:
+ '@typescript-eslint/types': 8.67.0
+ eslint-visitor-keys: 5.0.1
+
+ '@typescript-eslint/visitor-keys@8.68.0':
dependencies:
- '@typescript-eslint/types': 8.59.2
+ '@typescript-eslint/types': 8.68.0
eslint-visitor-keys: 5.0.1
- '@vitest/expect@4.1.8':
+ '@vitest/expect@4.1.11':
dependencies:
'@standard-schema/spec': 1.1.0
'@types/chai': 5.2.3
- '@vitest/spy': 4.1.8
- '@vitest/utils': 4.1.8
+ '@vitest/spy': 4.1.11
+ '@vitest/utils': 4.1.11
chai: 6.2.2
tinyrainbow: 3.1.0
- '@vitest/mocker@4.1.8(vite@7.3.6(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0))':
+ '@vitest/mocker@4.1.11(vite@7.3.6(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0))':
dependencies:
- '@vitest/spy': 4.1.8
+ '@vitest/spy': 4.1.11
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
vite: 7.3.6(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0)
- '@vitest/pretty-format@4.1.8':
+ '@vitest/pretty-format@4.1.11':
dependencies:
tinyrainbow: 3.1.0
- '@vitest/runner@4.1.8':
+ '@vitest/runner@4.1.11':
dependencies:
- '@vitest/utils': 4.1.8
+ '@vitest/utils': 4.1.11
pathe: 2.0.3
- '@vitest/snapshot@4.1.8':
+ '@vitest/snapshot@4.1.11':
dependencies:
- '@vitest/pretty-format': 4.1.8
- '@vitest/utils': 4.1.8
+ '@vitest/pretty-format': 4.1.11
+ '@vitest/utils': 4.1.11
magic-string: 0.30.21
pathe: 2.0.3
- '@vitest/spy@4.1.8': {}
+ '@vitest/spy@4.1.11': {}
- '@vitest/utils@4.1.8':
+ '@vitest/utils@4.1.11':
dependencies:
- '@vitest/pretty-format': 4.1.8
+ '@vitest/pretty-format': 4.1.11
convert-source-map: 2.0.0
tinyrainbow: 3.1.0
@@ -5688,6 +6313,11 @@ snapshots:
react-dom: 19.0.0(react@19.2.7)
webrtc-adapter: 9.0.3
+ accepts@2.0.0:
+ dependencies:
+ mime-types: 3.0.2
+ negotiator: 1.1.0
+
acorn-jsx@5.3.2(acorn@8.16.0):
dependencies:
acorn: 8.16.0
@@ -5698,6 +6328,12 @@ snapshots:
acorn@8.16.0: {}
+ agent-base@6.0.2:
+ dependencies:
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
ajv@6.15.0:
dependencies:
fast-deep-equal: 3.1.3
@@ -5790,6 +6426,8 @@ snapshots:
async-function@1.0.0: {}
+ asynckit@0.4.0: {}
+
autoprefixer@10.4.22(postcss@8.5.23):
dependencies:
browserslist: 4.28.2
@@ -5806,6 +6444,16 @@ snapshots:
axe-core@4.11.4: {}
+ axios@1.20.0:
+ dependencies:
+ follow-redirects: 1.16.0
+ form-data: 4.0.6
+ https-proxy-agent: 5.0.1
+ proxy-from-env: 2.1.0
+ transitivePeerDependencies:
+ - debug
+ - supports-color
+
axobject-query@4.1.0: {}
babel-plugin-react-compiler@1.0.0:
@@ -5824,6 +6472,20 @@ snapshots:
bintrees@1.0.2: {}
+ body-parser@2.3.0:
+ dependencies:
+ bytes: 3.1.2
+ content-type: 2.1.0
+ debug: 4.4.3
+ http-errors: 2.0.1
+ iconv-lite: 0.7.3
+ on-finished: 2.4.1
+ qs: 6.15.3
+ raw-body: 3.0.2
+ type-is: 2.1.0
+ transitivePeerDependencies:
+ - supports-color
+
brace-expansion@5.0.9:
dependencies:
balanced-match: 4.0.4
@@ -5840,8 +6502,12 @@ snapshots:
node-releases: 2.0.38
update-browserslist-db: 1.2.3(browserslist@4.28.2)
+ buffer-equal-constant-time@1.0.1: {}
+
buffer-from@1.1.2: {}
+ bytes@3.1.2: {}
+
call-bind-apply-helpers@1.0.2:
dependencies:
es-errors: 1.3.0
@@ -5889,10 +6555,24 @@ snapshots:
color-name@1.1.4: {}
+ combined-stream@1.0.8:
+ dependencies:
+ delayed-stream: 1.0.0
+
commander@7.2.0: {}
+ content-disposition@1.1.0: {}
+
+ content-type@1.0.5: {}
+
+ content-type@2.1.0: {}
+
convert-source-map@2.0.0: {}
+ cookie-signature@1.2.2: {}
+
+ cookie@0.7.2: {}
+
copy-anything@4.0.5:
dependencies:
is-what: 5.5.0
@@ -5959,6 +6639,10 @@ snapshots:
has-property-descriptors: 1.0.2
object-keys: 1.1.1
+ delayed-stream@1.0.0: {}
+
+ depd@2.0.0: {}
+
detect-libc@2.1.2: {}
detect-node-es@1.1.0: {}
@@ -6013,12 +6697,20 @@ snapshots:
duplexer@0.1.2: {}
+ ecdsa-sig-formatter@1.0.11:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ ee-first@1.1.1: {}
+
electron-to-chromium@1.5.353: {}
emoji-regex@8.0.0: {}
emoji-regex@9.2.2: {}
+ encodeurl@2.0.0: {}
+
enhanced-resolve@5.21.2:
dependencies:
graceful-fs: 4.2.11
@@ -6162,6 +6854,8 @@ snapshots:
escalade@3.2.0: {}
+ escape-html@1.0.3: {}
+
escape-string-regexp@4.0.0: {}
eslint-config-prettier@10.1.8(eslint@10.1.0(jiti@2.7.0)):
@@ -6180,17 +6874,17 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.1(@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint-import-resolver-node@0.3.10)(eslint@10.1.0(jiti@2.7.0)):
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint-import-resolver-node@0.3.10)(eslint@10.1.0(jiti@2.7.0)):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ '@typescript-eslint/parser': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
eslint: 10.1.0(jiti@2.7.0)
eslint-import-resolver-node: 0.3.10
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0)):
+ eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -6201,7 +6895,7 @@ snapshots:
doctrine: 2.1.0
eslint: 10.1.0(jiti@2.7.0)
eslint-import-resolver-node: 0.3.10
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint-import-resolver-node@0.3.10)(eslint@10.1.0(jiti@2.7.0))
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint-import-resolver-node@0.3.10)(eslint@10.1.0(jiti@2.7.0))
hasown: 2.0.3
is-core-module: 2.16.2
is-glob: 4.0.3
@@ -6213,7 +6907,7 @@ snapshots:
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ '@typescript-eslint/parser': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
@@ -6340,8 +7034,47 @@ snapshots:
esutils@2.0.3: {}
+ etag@1.8.1: {}
+
+ eventemitter3@4.0.7: {}
+
+ eventemitter3@5.0.4: {}
+
expect-type@1.3.0: {}
+ express@5.2.1:
+ dependencies:
+ accepts: 2.0.0
+ body-parser: 2.3.0
+ content-disposition: 1.1.0
+ content-type: 1.0.5
+ cookie: 0.7.2
+ cookie-signature: 1.2.2
+ debug: 4.4.3
+ depd: 2.0.0
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ finalhandler: 2.1.1
+ fresh: 2.0.0
+ http-errors: 2.0.1
+ merge-descriptors: 2.0.0
+ mime-types: 3.0.2
+ on-finished: 2.4.1
+ once: 1.4.0
+ parseurl: 1.3.3
+ proxy-addr: 2.0.7
+ qs: 6.15.3
+ range-parser: 1.3.0
+ router: 2.2.0
+ send: 1.2.1
+ serve-static: 2.2.1
+ statuses: 2.0.2
+ type-is: 2.1.0
+ vary: 1.1.2
+ transitivePeerDependencies:
+ - supports-color
+
fast-deep-equal@3.1.3: {}
fast-glob@3.3.1:
@@ -6374,6 +7107,17 @@ snapshots:
dependencies:
to-regex-range: 5.0.1
+ finalhandler@2.1.1:
+ dependencies:
+ debug: 4.4.3
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ on-finished: 2.4.1
+ parseurl: 1.3.3
+ statuses: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
find-up@4.1.0:
dependencies:
locate-path: 5.0.0
@@ -6391,10 +7135,22 @@ snapshots:
flatted@3.4.2: {}
+ follow-redirects@1.16.0: {}
+
for-each@0.3.5:
dependencies:
is-callable: 1.2.7
+ form-data@4.0.6:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ es-set-tostringtag: 2.1.0
+ hasown: 2.0.4
+ mime-types: 2.1.35
+
+ forwarded@0.2.0: {}
+
fraction.js@5.3.4: {}
framer-motion@11.18.2(react-dom@19.0.0(react@19.2.7))(react@19.2.7):
@@ -6406,8 +7162,7 @@ snapshots:
react: 19.2.7
react-dom: 19.0.0(react@19.2.7)
- fsevents@2.3.2:
- optional: true
+ fresh@2.0.0: {}
fsevents@2.3.3:
optional: true
@@ -6425,9 +7180,9 @@ snapshots:
functions-have-names@1.2.3: {}
- geist@1.7.0(next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)):
+ geist@1.7.0(next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)):
dependencies:
- next: 16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
+ next: 16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
generator-function@2.0.1: {}
@@ -6506,6 +7261,10 @@ snapshots:
dependencies:
function-bind: 1.1.2
+ hasown@2.0.4:
+ dependencies:
+ function-bind: 1.1.2
+
html-escaper@2.0.2: {}
htmlparser2@10.1.0:
@@ -6515,6 +7274,25 @@ snapshots:
domutils: 3.2.2
entities: 7.0.1
+ http-errors@2.0.1:
+ dependencies:
+ depd: 2.0.0
+ inherits: 2.0.4
+ setprototypeof: 1.2.0
+ statuses: 2.0.2
+ toidentifier: 1.0.1
+
+ https-proxy-agent@5.0.1:
+ dependencies:
+ agent-base: 6.0.2
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ iconv-lite@0.7.3:
+ dependencies:
+ safer-buffer: 2.1.2
+
ignore@5.3.2: {}
ignore@7.0.5: {}
@@ -6523,12 +7301,16 @@ snapshots:
imurmurhash@0.1.4: {}
+ inherits@2.0.4: {}
+
internal-slot@1.1.0:
dependencies:
es-errors: 1.3.0
hasown: 2.0.3
side-channel: 1.1.0
+ ipaddr.js@1.9.1: {}
+
is-array-buffer@3.0.5:
dependencies:
call-bind: 1.0.9
@@ -6569,6 +7351,8 @@ snapshots:
call-bound: 1.0.4
has-tostringtag: 1.0.2
+ is-electron@2.2.2: {}
+
is-extglob@2.1.1: {}
is-finalizationregistry@1.1.1:
@@ -6602,6 +7386,8 @@ snapshots:
is-plain-object@5.0.0: {}
+ is-promise@4.0.0: {}
+
is-regex@1.2.1:
dependencies:
call-bound: 1.0.4
@@ -6615,6 +7401,8 @@ snapshots:
dependencies:
call-bound: 1.0.4
+ is-stream@2.0.1: {}
+
is-string@1.1.1:
dependencies:
call-bound: 1.0.4
@@ -6674,6 +7462,19 @@ snapshots:
dependencies:
minimist: 1.2.8
+ jsonwebtoken@9.0.3:
+ dependencies:
+ jws: 4.0.1
+ lodash.includes: 4.3.0
+ lodash.isboolean: 3.0.3
+ lodash.isinteger: 4.0.4
+ lodash.isnumber: 3.0.3
+ lodash.isplainobject: 4.0.6
+ lodash.isstring: 4.0.1
+ lodash.once: 4.1.1
+ ms: 2.1.3
+ semver: 7.8.5
+
jsx-ast-utils@3.3.5:
dependencies:
array-includes: 3.1.9
@@ -6681,6 +7482,17 @@ snapshots:
object.assign: 4.1.7
object.values: 1.2.1
+ jwa@2.0.1:
+ dependencies:
+ buffer-equal-constant-time: 1.0.1
+ ecdsa-sig-formatter: 1.0.11
+ safe-buffer: 5.2.1
+
+ jws@4.0.1:
+ dependencies:
+ jwa: 2.0.1
+ safe-buffer: 5.2.1
+
keyv@4.5.4:
dependencies:
json-buffer: 3.0.1
@@ -6757,13 +7569,27 @@ snapshots:
dependencies:
p-locate: 5.0.0
+ lodash.includes@4.3.0: {}
+
+ lodash.isboolean@3.0.3: {}
+
+ lodash.isinteger@4.0.4: {}
+
+ lodash.isnumber@3.0.3: {}
+
+ lodash.isplainobject@4.0.6: {}
+
+ lodash.isstring@4.0.1: {}
+
+ lodash.once@4.1.1: {}
+
lodash.throttle@4.1.1: {}
loose-envify@1.4.0:
dependencies:
js-tokens: 4.0.0
- lucide-react@1.14.0(react@19.2.7):
+ lucide-react@1.35.0(react@19.2.7):
dependencies:
react: 19.2.7
@@ -6773,6 +7599,10 @@ snapshots:
math-intrinsics@1.1.0: {}
+ media-typer@1.1.1: {}
+
+ merge-descriptors@2.0.0: {}
+
merge2@1.4.1: {}
meshoptimizer@1.1.1: {}
@@ -6782,6 +7612,18 @@ snapshots:
braces: 3.0.3
picomatch: 2.3.2
+ mime-db@1.52.0: {}
+
+ mime-db@1.54.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ mime-types@3.0.2:
+ dependencies:
+ mime-db: 1.54.0
+
minimatch@10.2.3:
dependencies:
brace-expansion: 5.0.9
@@ -6812,18 +7654,22 @@ snapshots:
natural-compare@1.4.0: {}
- next-auth@5.0.0-beta.32(next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@20.19.40)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(nodemailer@9.0.3)(react@19.2.7):
+ negotiator@1.1.0:
+ dependencies:
+ content-type: 2.1.0
+
+ next-auth@5.0.0-beta.32(next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@20.19.40)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(nodemailer@9.0.3)(react@19.2.7):
dependencies:
'@auth/core': 0.41.3(nodemailer@9.0.3)
- next: 16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@20.19.40)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
+ next: 16.3.0(@opentelemetry/api@1.9.1)(@types/node@20.19.40)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
react: 19.2.7
optionalDependencies:
nodemailer: 9.0.3
- next-auth@5.0.0-beta.32(next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react@19.2.7):
+ next-auth@5.0.0-beta.32(next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7))(react@19.2.7):
dependencies:
'@auth/core': 0.41.3(nodemailer@9.0.3)
- next: 16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
+ next: 16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7)
react: 19.2.7
next-themes@0.4.6(react-dom@19.0.0(react@19.2.7))(react@19.2.7):
@@ -6831,7 +7677,7 @@ snapshots:
react: 19.2.7
react-dom: 19.0.0(react@19.2.7)
- next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@20.19.40)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7):
+ next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@20.19.40)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7):
dependencies:
'@next/env': 16.3.0
'@swc/helpers': 0.5.15
@@ -6851,7 +7697,6 @@ snapshots:
'@next/swc-win32-arm64-msvc': 16.3.0
'@next/swc-win32-x64-msvc': 16.3.0
'@opentelemetry/api': 1.9.1
- '@playwright/test': 1.60.0
babel-plugin-react-compiler: 1.0.0
sharp: 0.35.3(@types/node@20.19.40)
transitivePeerDependencies:
@@ -6859,7 +7704,7 @@ snapshots:
- '@types/node'
- babel-plugin-macros
- next@16.3.0(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7):
+ next@16.3.0(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(babel-plugin-react-compiler@1.0.0)(react-dom@19.0.0(react@19.2.7))(react@19.2.7):
dependencies:
'@next/env': 16.3.0
'@swc/helpers': 0.5.15
@@ -6879,7 +7724,6 @@ snapshots:
'@next/swc-win32-arm64-msvc': 16.3.0
'@next/swc-win32-x64-msvc': 16.3.0
'@opentelemetry/api': 1.9.1
- '@playwright/test': 1.60.0
babel-plugin-react-compiler: 1.0.0
sharp: 0.35.3(@types/node@22.15.32)
transitivePeerDependencies:
@@ -6948,6 +7792,14 @@ snapshots:
obug@2.1.1: {}
+ on-finished@2.4.1:
+ dependencies:
+ ee-first: 1.1.1
+
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
opener@1.5.2: {}
optionator@0.9.4:
@@ -6965,6 +7817,8 @@ snapshots:
object-keys: 1.1.1
safe-push-apply: 1.0.0
+ p-finally@1.0.0: {}
+
p-limit@2.3.0:
dependencies:
p-try: 2.2.0
@@ -6981,16 +7835,34 @@ snapshots:
dependencies:
p-limit: 3.1.0
+ p-queue@6.6.2:
+ dependencies:
+ eventemitter3: 4.0.7
+ p-timeout: 3.2.0
+
+ p-retry@4.6.2:
+ dependencies:
+ '@types/retry': 0.12.0
+ retry: 0.13.1
+
+ p-timeout@3.2.0:
+ dependencies:
+ p-finally: 1.0.0
+
p-try@2.2.0: {}
parse-srcset@1.0.2: {}
+ parseurl@1.3.3: {}
+
path-exists@4.0.0: {}
path-key@3.1.1: {}
path-parse@1.0.7: {}
+ path-to-regexp@8.4.2: {}
+
pathe@2.0.3: {}
pg-cloudflare@1.4.0:
@@ -7036,14 +7908,6 @@ snapshots:
picomatch@4.0.4: {}
- playwright-core@1.60.0: {}
-
- playwright@1.60.0:
- dependencies:
- playwright-core: 1.60.0
- optionalDependencies:
- fsevents: 2.3.2
-
pngjs@5.0.0: {}
possible-typed-array-names@1.1.0: {}
@@ -7097,6 +7961,13 @@ snapshots:
object-assign: 4.1.1
react-is: 16.13.1
+ proxy-addr@2.0.7:
+ dependencies:
+ forwarded: 0.2.0
+ ipaddr.js: 1.9.1
+
+ proxy-from-env@2.1.0: {}
+
punycode@2.3.1: {}
qrcode.react@3.2.0(react@19.2.7):
@@ -7109,8 +7980,22 @@ snapshots:
pngjs: 5.0.0
yargs: 15.4.1
+ qs@6.15.3:
+ dependencies:
+ es-define-property: 1.0.1
+ side-channel: 1.1.1
+
queue-microtask@1.2.3: {}
+ range-parser@1.3.0: {}
+
+ raw-body@3.0.2:
+ dependencies:
+ bytes: 3.1.2
+ http-errors: 2.0.1
+ iconv-lite: 0.7.3
+ unpipe: 1.0.0
+
react-chartjs-2@5.3.1(chart.js@4.5.1)(react@19.2.7):
dependencies:
chart.js: 4.5.1
@@ -7194,6 +8079,8 @@ snapshots:
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
+ retry@0.13.1: {}
+
reusify@1.1.0: {}
rollup@4.60.3:
@@ -7227,6 +8114,16 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.60.3
fsevents: 2.3.3
+ router@2.2.0:
+ dependencies:
+ debug: 4.4.3
+ depd: 2.0.0
+ is-promise: 4.0.0
+ parseurl: 1.3.3
+ path-to-regexp: 8.4.2
+ transitivePeerDependencies:
+ - supports-color
+
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
@@ -7239,6 +8136,8 @@ snapshots:
has-symbols: 1.1.0
isarray: 2.0.5
+ safe-buffer@5.2.1: {}
+
safe-push-apply@1.0.0:
dependencies:
es-errors: 1.3.0
@@ -7250,6 +8149,8 @@ snapshots:
es-errors: 1.3.0
is-regex: 1.2.1
+ safer-buffer@2.1.2: {}
+
sanitize-html@2.17.4:
dependencies:
deepmerge: 4.3.1
@@ -7280,6 +8181,31 @@ snapshots:
semver@7.8.5: {}
+ send@1.2.1:
+ dependencies:
+ debug: 4.4.3
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ fresh: 2.0.0
+ http-errors: 2.0.1
+ mime-types: 3.0.2
+ ms: 2.1.3
+ on-finished: 2.4.1
+ range-parser: 1.3.0
+ statuses: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ serve-static@2.2.1:
+ dependencies:
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ parseurl: 1.3.3
+ send: 1.2.1
+ transitivePeerDependencies:
+ - supports-color
+
set-blocking@2.0.0: {}
set-function-length@1.2.2:
@@ -7304,6 +8230,8 @@ snapshots:
es-errors: 1.3.0
es-object-atoms: 1.1.1
+ setprototypeof@1.2.0: {}
+
sharp@0.35.3(@types/node@20.19.40):
dependencies:
'@img/colour': 1.1.0
@@ -7406,6 +8334,14 @@ snapshots:
side-channel-map: 1.0.1
side-channel-weakmap: 1.0.2
+ side-channel@1.1.1:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-list: 1.0.1
+ side-channel-map: 1.0.1
+ side-channel-weakmap: 1.0.2
+
siginfo@2.0.0: {}
sirv@2.0.4:
@@ -7427,6 +8363,8 @@ snapshots:
stackback@0.0.2: {}
+ statuses@2.0.2: {}
+
std-env@4.0.0: {}
stop-iteration-iterator@1.1.0:
@@ -7540,6 +8478,8 @@ snapshots:
dependencies:
is-number: 7.0.0
+ toidentifier@1.0.1: {}
+
totalist@3.0.1: {}
ts-api-utils@2.5.0(typescript@5.8.3):
@@ -7559,6 +8499,8 @@ snapshots:
tslib@2.8.1: {}
+ tsscmp@1.0.6: {}
+
tsx@4.21.0:
dependencies:
esbuild: 0.25.12
@@ -7583,6 +8525,12 @@ snapshots:
dependencies:
tagged-tag: 1.0.0
+ type-is@2.1.0:
+ dependencies:
+ content-type: 2.1.0
+ media-typer: 1.1.1
+ mime-types: 3.0.2
+
typed-array-buffer@1.0.3:
dependencies:
call-bound: 1.0.4
@@ -7616,23 +8564,23 @@ snapshots:
possible-typed-array-names: 1.1.0
reflect.getprototypeof: 1.0.10
- typescript-eslint@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3):
+ typescript-eslint@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.59.2(@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3))(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
- '@typescript-eslint/parser': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
- '@typescript-eslint/typescript-estree': 8.59.2(typescript@5.8.3)
- '@typescript-eslint/utils': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
+ '@typescript-eslint/eslint-plugin': 8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3))(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
+ '@typescript-eslint/parser': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
+ '@typescript-eslint/typescript-estree': 8.67.0(typescript@5.8.3)
+ '@typescript-eslint/utils': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@5.8.3)
eslint: 10.1.0(jiti@2.7.0)
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- typescript-eslint@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2):
+ typescript-eslint@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.59.2(@typescript-eslint/parser@8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
- '@typescript-eslint/parser': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
- '@typescript-eslint/typescript-estree': 8.59.2(typescript@6.0.2)
- '@typescript-eslint/utils': 8.59.2(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ '@typescript-eslint/eslint-plugin': 8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2))(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ '@typescript-eslint/parser': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
+ '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.2)
+ '@typescript-eslint/utils': 8.67.0(eslint@10.1.0(jiti@2.7.0))(typescript@6.0.2)
eslint: 10.1.0(jiti@2.7.0)
typescript: 6.0.2
transitivePeerDependencies:
@@ -7651,6 +8599,10 @@ snapshots:
undici-types@6.21.0: {}
+ undici@6.28.0: {}
+
+ unpipe@1.0.0: {}
+
update-browserslist-db@1.2.3(browserslist@4.28.2):
dependencies:
browserslist: 4.28.2
@@ -7676,6 +8628,8 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.17
+ vary@1.1.2: {}
+
vite@7.3.6(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0):
dependencies:
esbuild: 0.25.12
@@ -7691,15 +8645,15 @@ snapshots:
lightningcss: 1.32.0
tsx: 4.21.0
- vitest@4.1.8(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0):
+ vitest@4.1.11(@opentelemetry/api@1.9.1)(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0):
dependencies:
- '@vitest/expect': 4.1.8
- '@vitest/mocker': 4.1.8(vite@7.3.6(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0))
- '@vitest/pretty-format': 4.1.8
- '@vitest/runner': 4.1.8
- '@vitest/snapshot': 4.1.8
- '@vitest/spy': 4.1.8
- '@vitest/utils': 4.1.8
+ '@vitest/expect': 4.1.11
+ '@vitest/mocker': 4.1.11(vite@7.3.6(@types/node@22.15.32)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.21.0))
+ '@vitest/pretty-format': 4.1.11
+ '@vitest/runner': 4.1.11
+ '@vitest/snapshot': 4.1.11
+ '@vitest/spy': 4.1.11
+ '@vitest/utils': 4.1.11
es-module-lexer: 2.0.0
expect-type: 1.3.0
magic-string: 0.30.21
@@ -7812,6 +8766,8 @@ snapshots:
string-width: 4.2.3
strip-ansi: 6.0.1
+ wrappy@1.0.2: {}
+
ws@8.21.0: {}
xlsx@https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz: {}
diff --git a/sites/hacklytics2027/app/globals.css b/sites/hacklytics2027/app/globals.css
index 4753052c..2cbdc98a 100644
--- a/sites/hacklytics2027/app/globals.css
+++ b/sites/hacklytics2027/app/globals.css
@@ -190,20 +190,32 @@ body {
.pixel-lime:hover { --pixel-edge: rgba(200, 255, 0, 0.9); --pixel-glow: rgba(200, 255, 0, 0.4); }
.pixel-purple:hover { --pixel-edge: rgba(155, 0, 255, 0.95); --pixel-glow: rgba(155, 0, 255, 0.45); }
-/* Solid neon slab button — chunky, no radius, steps() so it feels 8-bit */
+/* Solid cyan slab — sharp rectangle, hard pixel edge, no bloom.
+ Glow stays on the brightest sprites, not on every CTA. */
.pixel-btn {
position: relative;
+ border: 0;
border-radius: 0;
background: var(--btn-bg, #00e5ff);
color: #04040a;
+ font-weight: 700;
+ text-decoration: none;
box-shadow:
- 0 -4px 0 0 rgba(255, 255, 255, 0.35),
- 0 4px 0 0 rgba(0, 0, 0, 0.6),
- 0 0 28px var(--btn-glow, rgba(0, 229, 255, 0.5));
+ 0 -3px 0 0 rgba(255, 255, 255, 0.28),
+ 0 3px 0 0 rgba(0, 0, 0, 0.75);
transition: transform 120ms steps(2), box-shadow 160ms steps(2), filter 160ms linear;
}
-.pixel-btn:hover { transform: translateY(-2px); filter: brightness(1.12); }
-.pixel-btn:active { transform: translateY(2px); }
+.pixel-btn:hover { transform: translateY(-2px); filter: brightness(1.08); }
+.pixel-btn:active {
+ transform: translateY(2px);
+ box-shadow:
+ 0 -1px 0 0 rgba(255, 255, 255, 0.2),
+ 0 1px 0 0 rgba(0, 0, 0, 0.8);
+}
+.pixel-btn:focus-visible {
+ outline: 2px solid #f0f0f2;
+ outline-offset: 3px;
+}
/* Neon text glow, tuned per accent */
.neon-cyan { color: #00e5ff; text-shadow: 0 0 8px rgba(0, 229, 255, 0.65), 0 0 22px rgba(0, 229, 255, 0.35); }
diff --git a/sites/hacklytics2027/app/page.tsx b/sites/hacklytics2027/app/page.tsx
index 6aca16b3..f135b41f 100644
--- a/sites/hacklytics2027/app/page.tsx
+++ b/sites/hacklytics2027/app/page.tsx
@@ -4,7 +4,7 @@ import HomeSections from "@/components/HomeSections";
import PixelGarden, { PixelGround } from "@/components/pixel/PixelGarden";
import PixelSprite from "@/components/pixel/PixelSprite";
import { BLOOM, DAISY, SPROUT, TULIP } from "@/components/pixel/sprites";
-import { INTEREST_URL } from "@/lib/links";
+import { INTEREST_HINT, INTEREST_URL } from "@/lib/links";
// ─── Elegant Floral Background ─────────────────────────────────────────────
const FloralBackground = () => (
@@ -171,21 +171,25 @@ export default function HomePage() {
Join 1,000+ hackers in Atlanta, GA.
- {/* Framer-style CTA Buttons */}
+ {/* Notify me hands off to the portal. No on-site form. */}
-
-
- NOTIFY ME
-
+
+
+ NOTIFY ME →
+
+
+ {INTEREST_HINT}
-
+
-
-
- {/* pixel flower bed growing along the top edge of the footer */}
-
-
-
+