diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 2676745a..88ab7dc8 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -32,8 +32,11 @@ jobs:
filters: |
backend:
- 'backend/**'
+ # The rebuilt app in web/ is what ships. frontend/ is still in the
+ # tree for one release as a fallback but is no longer deployed, so
+ # a change to it must not trigger a build.
frontend:
- - 'frontend/**'
+ - 'web/**'
nginx:
- 'infra/nginx/**'
meilisearch:
@@ -59,6 +62,74 @@ jobs:
- 'infra/postgres/**'
- 'infra/backup/**'
+ # Validate the exact source contract before publishing an image or static
+ # artifact. The dummy env supplies import-time Config values only; FastAPI
+ # lifespan is not started by the exporter.
+ - name: Install PostgreSQL build tools
+ if: steps.changes.outputs.backend == 'true' || steps.changes.outputs.frontend == 'true'
+ run: sudo apt-get update && sudo apt-get install -y libpq-dev
+
+ - name: Set up Python for backend checks
+ if: steps.changes.outputs.backend == 'true' || steps.changes.outputs.frontend == 'true'
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+
+ - name: Set up uv
+ if: steps.changes.outputs.backend == 'true' || steps.changes.outputs.frontend == 'true'
+ uses: astral-sh/setup-uv@v6
+ with:
+ enable-cache: true
+ cache-dependency-glob: backend/uv.lock
+
+ - name: Install backend dependencies
+ if: steps.changes.outputs.backend == 'true' || steps.changes.outputs.frontend == 'true'
+ working-directory: backend
+ run: uv sync --frozen
+
+ - name: Test backend
+ if: steps.changes.outputs.backend == 'true'
+ working-directory: backend
+ run: uv run --env-file ../infra/.env.example pytest
+
+ - name: Export OpenAPI contract
+ if: steps.changes.outputs.backend == 'true' || steps.changes.outputs.frontend == 'true'
+ working-directory: backend
+ run: uv run python scripts/export_openapi.py --output "${{ runner.temp }}/openapi.json"
+
+ - name: Enable pnpm
+ if: steps.changes.outputs.backend == 'true' || steps.changes.outputs.frontend == 'true'
+ run: corepack enable
+
+ - name: Set up Node.js for checks
+ if: steps.changes.outputs.backend == 'true' || steps.changes.outputs.frontend == 'true'
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22'
+ cache: pnpm
+ cache-dependency-path: web/pnpm-lock.yaml
+
+ - name: Install web dependencies
+ if: steps.changes.outputs.backend == 'true' || steps.changes.outputs.frontend == 'true'
+ working-directory: web
+ run: pnpm install --frozen-lockfile
+
+ - name: Check generated API types
+ if: steps.changes.outputs.backend == 'true' || steps.changes.outputs.frontend == 'true'
+ working-directory: web
+ env:
+ OPENAPI_URL: ${{ runner.temp }}/openapi.json
+ run: pnpm api:check
+
+ - name: Validate frontend
+ if: steps.changes.outputs.frontend == 'true'
+ working-directory: web
+ run: |
+ pnpm format:check
+ pnpm lint
+ pnpm test
+ pnpm build
+
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
@@ -120,22 +191,9 @@ jobs:
cache-to: type=gha,mode=max,scope=nuspace-backup
# --- Frontend static export (Vite SPA) — built on the runner, not on the VM ---
- - name: Set up Node.js for frontend build
- if: steps.changes.outputs.frontend == 'true'
- uses: actions/setup-node@v4
- with:
- node-version: '20'
- cache: npm
- cache-dependency-path: frontend/package-lock.json
-
- - name: Build frontend static output
- if: steps.changes.outputs.frontend == 'true'
- working-directory: frontend
- run: npm ci && npm run build
-
- name: Pack frontend out/ for Ansible
if: steps.changes.outputs.frontend == 'true'
- run: tar czf "${{ runner.temp }}/frontend-static.tar.gz" -C frontend/out .
+ run: tar czf "${{ runner.temp }}/frontend-static.tar.gz" -C web/out .
- name: Frontend tarball path for Ansible
id: fe_artifact
diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml
new file mode 100644
index 00000000..17d6a0d0
--- /dev/null
+++ b/.github/workflows/quality.yml
@@ -0,0 +1,107 @@
+name: Quality
+
+on:
+ pull_request:
+ workflow_dispatch:
+
+jobs:
+ backend:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Install PostgreSQL build tools
+ run: sudo apt-get update && sudo apt-get install -y libpq-dev
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+
+ - name: Set up uv
+ uses: astral-sh/setup-uv@v6
+ with:
+ enable-cache: true
+ cache-dependency-glob: backend/uv.lock
+
+ - name: Install backend dependencies
+ working-directory: backend
+ run: uv sync --frozen
+
+ - name: Run backend tests
+ working-directory: backend
+ run: uv run --env-file ../infra/.env.example pytest
+
+ - name: Export OpenAPI
+ working-directory: backend
+ run: uv run python scripts/export_openapi.py --output "${{ runner.temp }}/openapi.json"
+
+ - name: Upload OpenAPI contract
+ uses: actions/upload-artifact@v4
+ with:
+ name: openapi-contract
+ path: ${{ runner.temp }}/openapi.json
+
+ web:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Enable pnpm
+ run: corepack enable
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: "22"
+ cache: pnpm
+ cache-dependency-path: web/pnpm-lock.yaml
+
+ - name: Install web dependencies
+ working-directory: web
+ run: pnpm install --frozen-lockfile
+
+ - name: Check formatting
+ working-directory: web
+ run: pnpm format:check
+
+ - name: Lint web
+ working-directory: web
+ run: pnpm lint
+
+ - name: Test web
+ working-directory: web
+ run: pnpm test
+
+ - name: Build web
+ working-directory: web
+ run: pnpm build
+
+ contract:
+ needs: [backend, web]
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Download OpenAPI contract
+ uses: actions/download-artifact@v4
+ with:
+ name: openapi-contract
+ path: openapi
+
+ - name: Enable pnpm
+ run: corepack enable
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: "22"
+
+ - name: Check generated API types
+ working-directory: web
+ env:
+ OPENAPI_URL: ${{ github.workspace }}/openapi/openapi.json
+ run: pnpm api:check
diff --git a/AGENTS.md b/AGENTS.md
index ee051abd..e81992ae 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -4,7 +4,9 @@
```
backend/ Python 3.12 / FastAPI app (package name: nuros)
-frontend/ React 19 / Vite 7 / TypeScript SPA
+web/ React 19 / Vite 8 / TypeScript SPA — the app that ships
+frontend/ The previous SPA. Kept one release as a fallback; not built,
+ not routed to, not deployed. Work in web/.
infra/ Docker Compose, Nginx, monitoring, service configs
terraform/ GCP infrastructure-as-code
ansible/ Deployment playbooks (runs from CI, not locally)
@@ -39,15 +41,27 @@ uv run pytest # tests
Pre-commit hooks run `ruff --fix` then `black` automatically.
-### Frontend (`frontend/`)
+### Frontend (`web/`)
+
+pnpm, not npm. The lockfile is `web/pnpm-lock.yaml` and CI installs with
+`--frozen-lockfile`, so a dependency added with npm will fail the build.
```sh
-npm ci && npm run build # production build → out/
-npm run dev # dev server on :5173
-npm run test:url-validation # run a single test file via tsx
+pnpm install # deps
+pnpm build # typecheck + production build → out/
+pnpm dev # dev server on :5173
+pnpm typecheck # tsc -b --noEmit
+pnpm lint # oxlint, including type-aware rules
+pnpm format # prettier, sorts Tailwind classes
+pnpm test # node --test over src/**/*.test.ts
+pnpm api:check # fail if src/api/schema.d.ts is stale
```
-TypeScript strict mode. `@` alias maps to `src/`.
+`out/`, not Vite's default `dist/` — the deployment path expects it (see
+`web/vite.config.ts`).
+
+TypeScript strict mode. `@` alias maps to `src/`. Read `web/README.md` before
+changing anything there; several of its conventions are load-bearing.
## Backend Architecture
diff --git a/ansible/roles/frontend/tasks/main.yml b/ansible/roles/frontend/tasks/main.yml
index 1d3f71b1..476600ea 100644
--- a/ansible/roles/frontend/tasks/main.yml
+++ b/ansible/roles/frontend/tasks/main.yml
@@ -1,10 +1,14 @@
---
# Static files are built in GitHub Actions and shipped as a tarball on the controller.
# `frontend_tarball_path` is set by CI when frontend paths changed; empty skips deploy.
+#
+# The path is web/out, not frontend/out: the app that ships is the rebuild in
+# web/. The frontend/ tree is still in the repository for one release, but
+# nothing unpacks into it and nginx no longer serves it.
- name: Ensure frontend out directory exists with proper permissions
ansible.builtin.file:
- path: "/home/{{ ansible_user }}/nuspace/frontend/out"
+ path: "/home/{{ ansible_user }}/nuspace/web/out"
state: directory
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
@@ -14,7 +18,7 @@
- name: Clear previous static export
ansible.builtin.shell: |
set -e
- rm -rf /home/{{ ansible_user }}/nuspace/frontend/out/*
+ rm -rf /home/{{ ansible_user }}/nuspace/web/out/*
args:
executable: /bin/bash
when: frontend_tarball_path | default('') | length > 0
@@ -22,7 +26,7 @@
- name: Unpack frontend build from CI runner to VM
ansible.builtin.unarchive:
src: "{{ frontend_tarball_path }}"
- dest: "/home/{{ ansible_user }}/nuspace/frontend/out"
+ dest: "/home/{{ ansible_user }}/nuspace/web/out"
remote_src: false
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
@@ -30,7 +34,7 @@
- name: Verify out files were created
ansible.builtin.stat:
- path: "/home/{{ ansible_user }}/nuspace/frontend/out/index.html"
+ path: "/home/{{ ansible_user }}/nuspace/web/out/index.html"
register: dist_check
when: frontend_tarball_path | default('') | length > 0
@@ -43,7 +47,7 @@
- name: Show frontend deploy success message
ansible.builtin.debug:
- msg: "Frontend static files from CI are deployed under frontend/out."
+ msg: "Frontend static files from CI are deployed under web/out."
when: frontend_tarball_path | default('') | length > 0
- name: Recreate nginx service to pick up new out files
diff --git a/backend/common/utils/meilisearch.py b/backend/common/utils/meilisearch.py
index 0e41b489..0a1e6fe9 100644
--- a/backend/common/utils/meilisearch.py
+++ b/backend/common/utils/meilisearch.py
@@ -2,6 +2,7 @@
from typing import Type
from backend.core.database.manager import AsyncDatabaseManager
+from fastapi import HTTPException
from httpx import AsyncClient
from sqlalchemy import select
from sqlalchemy.orm import DeclarativeBase
@@ -81,6 +82,24 @@ async def get(
payload["filter"] = filters
response = await client.post(f"/indexes/{storage_name}/search", json=payload)
+
+ # An error response has no "hits", and every caller reads result["hits"]
+ # directly -- so without this the failure surfaces as an opaque
+ # `KeyError: 'hits'` and a 500 with no indication of what went wrong.
+ #
+ # This is not a rare edge: index setup deletes and recreates every index on
+ # startup, so there is a window after each deploy where searching an index
+ # that does not exist yet 500s.
+ if response.status_code >= 400:
+ body = response.json()
+ raise HTTPException(
+ status_code=503,
+ detail=(
+ f"Search index '{storage_name}' is unavailable "
+ f"({body.get('code', response.status_code)})."
+ ),
+ )
+
return response.json()
diff --git a/backend/core/configs/config.py b/backend/core/configs/config.py
index 83087e80..cc140a8d 100644
--- a/backend/core/configs/config.py
+++ b/backend/core/configs/config.py
@@ -44,6 +44,15 @@ class Config(BaseSettings):
GCP_SIGNING_SERVICE_ACCOUNT_KEY_JSON: str | None = None
ORIGINS: List[str] = ["*"]
MOCK_KEYCLOAK: bool # always set True in local dev
+ # Your own registrar username, for testing the registrar sync locally.
+ #
+ # Mock users have no real NU email, so the username cannot be derived from
+ # the session the way it is in production. This used to be a colleague's
+ # username written into the source, which meant every developer's local sync
+ # attempt was a login attempt against that person's real registrar account --
+ # and enough wrong passwords locks them out. Set your own here, or leave it
+ # unset and the sync will simply fail to authenticate.
+ REGISTRAR_DEBUG_USERNAME: str | None = None
USE_GCS_EMULATOR: bool # keep True for local dev; For staging/prod .env will have it False
GCS_EMULATOR_HOST: str
INTEGRATION_SECRET: str
diff --git a/backend/fixtures/dev/seed_campus.sql b/backend/fixtures/dev/seed_campus.sql
new file mode 100644
index 00000000..7038164d
--- /dev/null
+++ b/backend/fixtures/dev/seed_campus.sql
@@ -0,0 +1,435 @@
+-- Realistic Campus Current and SGotinish data for local dev.
+--
+-- Without this, a fresh database has one event, one community and two users, so
+-- most screens render an empty state and the ones that do not are exercised
+-- against a single row. Every filter, every grouping and every permission
+-- branch then looks like it works because there is nothing for it to get wrong.
+--
+-- What this covers, and why each case is here:
+--
+-- * events — past, in progress, today and weeks out, so the time
+-- filters and the "Happening now" badge have something to
+-- separate; open and registration policies; a featured tag.
+-- * communities — every type and several categories, one verified, one
+-- headed by a non-admin so `can_edit` differs by viewer.
+-- * opportunities — expired and open, year-round (`deadline IS NULL`), one
+-- restricted by major, and eligibilities covering the
+-- three level shapes: specific years, a whole level, PhD.
+-- * SG membership — Heads, Executives and Members across regular and special
+-- departments, so the roster grouping is non-trivial and
+-- the capo permission rules can actually be violated.
+-- * tickets — one per status, one anonymous with a known key, and one
+-- with a delegated access list.
+--
+-- Announcements need no seeding of their own: `/announcements/bundle` is built
+-- from upcoming events and recruiting communities, both of which are below.
+--
+-- Run against the local stack:
+-- docker compose exec -T postgres psql -U postgres -d postgres \
+-- < backend/fixtures/dev/seed_campus.sql
+--
+-- Then restart the API — Meilisearch indexes from the database at startup, so
+-- anything inserted afterwards is invisible to search until it does:
+-- docker compose restart fastapi
+--
+-- Signing in as each of these people (MOCK_KEYCLOAK=true):
+-- http://localhost/api/login?mock_user=alice admin
+-- http://localhost/api/login?mock_user=bob ordinary student
+-- http://localhost/api/login?mock_user=charlie Head (boss)
+-- http://localhost/api/login?mock_user=dana Executive (capo)
+-- http://localhost/api/login?mock_user=erik Member (soldier)
+--
+-- Re-runnable. Rows are matched on the natural key a person would recognise —
+-- a community's name, an event's name, a ticket's title — because none of these
+-- tables has a unique constraint to hang `ON CONFLICT` on. A bare
+-- `ON CONFLICT DO NOTHING` looks like it deduplicates and does nothing at all
+-- without a constraint to conflict against; the second run of an earlier draft
+-- of this file produced a clean duplicate of every event, ticket, community and
+-- opportunity. Nothing here deletes anything you created by hand.
+
+BEGIN;
+
+-- ---------------------------------------------------------------------------
+-- People
+-- ---------------------------------------------------------------------------
+-- alice and bob already exist from the mock provider; charlie is defined there
+-- too but only appears once he has signed in. Inserting all five means the
+-- roster is populated before anyone logs in, and the FK targets for the
+-- communities and tickets below exist.
+
+INSERT INTO users (sub, email, role, scope, name, surname, picture, created_at, updated_at) VALUES
+ ('mock-sub-alice', 'alice@example.com', 'admin', 'allowed', 'Alice', 'Anderson', 'https://i.pravatar.cc/150?img=3', now(), now()),
+ ('mock-sub-bob', 'bob@example.com', 'default', 'allowed', 'Bob', 'Brown', 'https://i.pravatar.cc/150?img=4', now(), now()),
+ ('mock-sub-charlie', 'charlie@example.com', 'boss', 'allowed', 'Charlie', 'Clark', 'https://i.pravatar.cc/150?img=5', now(), now()),
+ ('mock-sub-dana', 'dana@example.com', 'capo', 'allowed', 'Dana', 'Dosanova', 'https://i.pravatar.cc/150?img=6', now(), now()),
+ ('mock-sub-erik', 'erik@example.com', 'soldier', 'allowed', 'Erik', 'Ermekov', 'https://i.pravatar.cc/150?img=7', now(), now()),
+ ('mock-sub-fatima', 'fatima@example.com', 'soldier', 'allowed', 'Fatima', 'Fazylova', 'https://i.pravatar.cc/150?img=8', now(), now()),
+ ('mock-sub-gulnar', 'gulnar@example.com', 'capo', 'allowed', 'Gulnar', 'Galieva', 'https://i.pravatar.cc/150?img=9', now(), now()),
+ ('mock-sub-hassan', 'hassan@example.com', 'default', 'allowed', 'Hassan', 'Hakim', 'https://i.pravatar.cc/150?img=10', now(), now())
+ON CONFLICT (sub) DO UPDATE SET
+ role = EXCLUDED.role,
+ name = EXCLUDED.name,
+ surname = EXCLUDED.surname,
+ updated_at = now();
+
+-- ---------------------------------------------------------------------------
+-- Departments
+-- ---------------------------------------------------------------------------
+-- Id 9 is the root Student Government department. The backend hardcodes it —
+-- `DelegationPolicy.check_department_deletable` refuses to delete id 9 by
+-- number — so a local database has to reproduce that id for the protected-row
+-- behaviour to be testable at all. Explicit ids here, not a sequence.
+
+INSERT INTO departments (id, name, is_special) VALUES
+ (9, 'Student Government', false),
+ (10, 'Ministry of Academics', false),
+ (11, 'Ministry of Sport', false),
+ (12, 'Ministry of Media', false),
+ (13, 'Ethics Commission', true),
+ (14, 'Election Committee', true)
+ON CONFLICT (id) DO UPDATE SET
+ name = EXCLUDED.name,
+ is_special = EXCLUDED.is_special;
+
+-- Keep the sequence ahead of the explicit ids, or the first department created
+-- through the UI collides with one of them.
+SELECT setval(
+ pg_get_serial_sequence('departments', 'id'),
+ GREATEST((SELECT MAX(id) FROM departments), 1)
+);
+
+UPDATE users SET department_id = 9, sg_assigned_at = now() - interval '200 days' WHERE sub = 'mock-sub-charlie';
+UPDATE users SET department_id = 10, sg_assigned_at = now() - interval '150 days', sg_assigned_by_sub = 'mock-sub-charlie' WHERE sub = 'mock-sub-dana';
+UPDATE users SET department_id = 10, sg_assigned_at = now() - interval '100 days', sg_assigned_by_sub = 'mock-sub-dana' WHERE sub = 'mock-sub-erik';
+-- Fatima sits in a different department from Dana on purpose: a capo must not
+-- be able to remove or delegate to her, and that is only visible with someone
+-- outside their own department in the roster.
+UPDATE users SET department_id = 11, sg_assigned_at = now() - interval '90 days', sg_assigned_by_sub = 'mock-sub-charlie' WHERE sub = 'mock-sub-fatima';
+UPDATE users SET department_id = 13, sg_assigned_at = now() - interval '80 days', sg_assigned_by_sub = 'mock-sub-charlie' WHERE sub = 'mock-sub-gulnar';
+
+-- ---------------------------------------------------------------------------
+-- Communities
+-- ---------------------------------------------------------------------------
+
+INSERT INTO communities (name, type, category, email, verified, description, established, head, telegram_url, instagram_url, created_at, updated_at)
+SELECT * FROM (VALUES
+ ('NU Fencing Club', 'club', 'sports', 'fencing@nu.edu.kz', true,
+ E'Foil, épée and sabre, three evenings a week in the Sports Complex.\n\nBeginners welcome — we lend kit for the first term. **No experience needed.**',
+ '2019-09-01', 'mock-sub-bob', 'https://t.me/nufencing', 'https://instagram.com/nufencing', now(), now()),
+
+ ('Debate Society', 'club', 'academic', 'debate@nu.edu.kz', true,
+ 'British Parliamentary format, weekly rounds, and the training squad for regional tournaments.',
+ '2015-02-15', 'mock-sub-charlie', 'https://t.me/nudebate', NULL, now(), now()),
+
+ ('Robotics and Mechatronics Association', 'organization', 'professional', 'rma@nu.edu.kz', false,
+ 'Builds the university competition robots. Recruiting mechanical, electronics and software people every September.',
+ '2021-09-10', 'mock-sub-dana', 'https://t.me/nurobotics', 'https://instagram.com/nurobotics', now(), now()),
+
+ ('Student Theatre', 'club', 'art', NULL, false,
+ 'Two productions a year, in English and Kazakh. No audition required to join the crew.',
+ '2017-10-05', 'mock-sub-erik', NULL, 'https://instagram.com/nutheatre', now(), now()),
+
+ ('Office of Student Affairs', 'university', 'social', 'osa@nu.edu.kz', true,
+ 'Official university office. Runs orientation, student support and the campus events calendar.',
+ '2010-01-01', 'mock-sub-alice', NULL, NULL, now(), now()),
+
+ ('Kazakh Culture Club', 'club', 'cultural', 'kcc@nu.edu.kz', false,
+ 'Language evenings, Nauryz, and dombra lessons for anyone who wants them.',
+ '2018-03-21', 'mock-sub-fatima', 'https://t.me/nukcc', NULL, now(), now()),
+
+ ('Hiking and Outdoors', 'club', 'recreational', NULL, false,
+ 'Weekend trips to Burabay and the Ile-Alatau. Transport shared, no membership fee.',
+ '2022-04-12', 'mock-sub-gulnar', 'https://t.me/nuhiking', NULL, now(), now())
+) AS seed(name, type, category, email, verified, description, established, head, telegram_url, instagram_url, created_at, updated_at)
+WHERE NOT EXISTS (SELECT 1 FROM communities c WHERE c.name = seed.name);
+
+-- ---------------------------------------------------------------------------
+-- Events
+-- ---------------------------------------------------------------------------
+-- Times are relative to now() so the time filters keep working next month —
+-- fixed dates in a seed script quietly become "all past" and the upcoming list
+-- reads as empty.
+
+INSERT INTO events (creator_sub, policy, registration_link, name, place, start_datetime, end_datetime, description, type, status, tag, created_at, updated_at)
+SELECT * FROM (VALUES
+ ('mock-sub-charlie', 'open', NULL,
+ 'Open Mic Night', 'Block 8, Atrium',
+ now() + interval '2 hours', now() + interval '5 hours',
+ E'Bring an instrument, a poem or nothing at all.\n\n- Sign-up sheet at the door\n- Free tea',
+ 'art', 'approved', 'regular', now(), now()),
+
+ ('mock-sub-bob', 'registration', 'https://forms.gle/example-fencing',
+ 'Fencing Taster Session', 'Sports Complex, Hall 2',
+ now() + interval '3 days', now() + interval '3 days 2 hours',
+ 'Kit provided. Wear trainers and something you can move in. Places are limited to 24.',
+ 'sports', 'approved', 'regular', now(), now()),
+
+ ('mock-sub-alice', 'open', NULL,
+ 'Career Fair 2026', 'Block 7, Main Hall',
+ now() + interval '11 days', now() + interval '11 days 8 hours',
+ E'Forty employers across engineering, data and life sciences.\n\n## What to bring\n\n1. Printed CV\n2. Student ID',
+ 'recruitment', 'approved', 'featured', now(), now()),
+
+ ('mock-sub-dana', 'registration', 'https://forms.gle/example-hackathon',
+ 'NU Hackathon: 36 Hours', 'SCAI, Floor 3',
+ now() + interval '25 days', now() + interval '26 days 12 hours',
+ 'Teams of up to four. Hardware track and a software track, with mentors from the Robotics Association.',
+ 'academic', 'approved', 'promotional', now(), now()),
+
+ ('mock-sub-erik', 'open', NULL,
+ 'Winter Charity Bazaar', 'Block 1, Foyer',
+ now() + interval '40 days', now() + interval '40 days 6 hours',
+ 'All proceeds to the Astana children''s hospital. Stalls are free for student societies.',
+ 'social', 'approved', 'charity', now(), now()),
+
+ -- Already finished: the detail page should show "Finished" and hide the
+ -- registration button even though a link is set.
+ ('mock-sub-charlie', 'registration', 'https://forms.gle/example-past',
+ 'Autumn Debate Open', 'Block 6, Room 6.201',
+ now() - interval '14 days', now() - interval '14 days' + interval '9 hours',
+ 'Eight rounds, British Parliamentary. Results are on the Debate Society channel.',
+ 'academic', 'approved', 'regular', now(), now()),
+
+ ('mock-sub-gulnar', 'open', NULL,
+ 'Sunrise Hike: Burabay', 'Meet at Block 22 car park',
+ now() + interval '6 days', now() + interval '6 days 14 hours',
+ 'Leaving at 05:00. Bring water, layers and boots — this is not a stroll.',
+ 'recreational', 'approved', 'regular', now(), now()),
+
+ -- Not approved: must not appear in the student-facing list at all.
+ ('mock-sub-hassan', 'open', NULL,
+ 'Unapproved Test Event', 'Nowhere',
+ now() + interval '9 days', now() + interval '9 days 1 hour',
+ 'Exists so the status filter has something it is supposed to be hiding.',
+ 'social', 'pending', 'regular', now(), now())
+) AS seed(creator_sub, policy, registration_link, name, place, start_datetime, end_datetime, description, type, status, tag, created_at, updated_at)
+WHERE NOT EXISTS (SELECT 1 FROM events e WHERE e.name = seed.name);
+
+-- ---------------------------------------------------------------------------
+-- Opportunities
+-- ---------------------------------------------------------------------------
+-- The enum labels here are the Python member *names* (RESEARCH, GRM), not the
+-- values the API speaks (research, GrM) — SQLAlchemy stores names by default,
+-- and using the API spelling fails with an invalid-enum error.
+
+INSERT INTO opportunities (name, description, deadline, host, type, link, location, funding, created_at, updated_at)
+SELECT * FROM (VALUES
+ ('Nazarbayev University Research Assistantship',
+ E'Paid research assistant positions across all schools for the spring semester.\n\nSupervisors post projects in February; applications go through your school office.',
+ CURRENT_DATE + 21, 'NU Office of the Provost', 'RESEARCH',
+ 'https://nu.edu.kz/research', 'Astana', 'Stipend, 120,000 KZT/month', now(), now()),
+
+ ('DAAD Summer School in Germany',
+ 'Four weeks at a German university, language course included. Covers travel, accommodation and a monthly allowance.',
+ CURRENT_DATE + 45, 'DAAD', 'SUMMER_SCHOOL',
+ 'https://daad.de', 'Germany', 'Fully funded', now(), now()),
+
+ ('Google Summer of Code',
+ 'Work on an open-source project with a mentoring organisation over the summer. Open to any student who can write code.',
+ CURRENT_DATE + 60, 'Google', 'INTERNSHIP',
+ 'https://summerofcode.withgoogle.com', 'Remote', 'Stipend by country tier', now(), now()),
+
+ -- Year-round: `deadline IS NULL` is the shape the "year-round" toggle
+ -- produces, and the card must not render a closing date for it.
+ ('NU Alumni Mentorship Programme',
+ 'Matched with an alumnus in your field for a semester. Applications are read as they arrive.',
+ NULL, 'NU Alumni Association', 'FORUM',
+ 'https://nu.edu.kz/alumni', 'Astana / Remote', NULL, now(), now()),
+
+ -- Already closed: `hide_expired=true` is the default on the list, so this one
+ -- proves the filter is doing something.
+ ('Bolashak Scholarship — 2025 intake',
+ 'Graduate study abroad, fully funded, with a return-service commitment.',
+ CURRENT_DATE - 30, 'Centre for International Programmes', 'SCHOLARSHIP',
+ 'https://bolashak.gov.kz', 'Abroad', 'Fully funded', now(), now()),
+
+ ('Astana Hub Startup Grant',
+ 'Seed funding for student teams with a working prototype. Two rounds a year.',
+ CURRENT_DATE + 90, 'Astana Hub', 'GRANT',
+ 'https://astanahub.com', 'Astana', 'Up to 20,000 USD', now(), now())
+) AS seed(name, description, deadline, host, type, link, location, funding, created_at, updated_at)
+WHERE NOT EXISTS (SELECT 1 FROM opportunities o WHERE o.name = seed.name);
+
+-- Eligibility, covering the three shapes the form can produce.
+INSERT INTO opportunity_eligibility (opportunity_id, education_level, year)
+SELECT o.id, level, year FROM opportunities o
+CROSS JOIN LATERAL (VALUES ('UG'::education_level, 3), ('UG', 4), ('GRM', NULL))
+ AS e(level, year)
+WHERE o.name = 'Nazarbayev University Research Assistantship'
+ON CONFLICT DO NOTHING;
+
+-- A whole level with no years: one row with year NULL, which is what "the
+-- entire level is eligible" means. Zero rows would mean nobody is.
+INSERT INTO opportunity_eligibility (opportunity_id, education_level, year)
+SELECT id, 'UG', NULL FROM opportunities WHERE name = 'DAAD Summer School in Germany'
+ON CONFLICT DO NOTHING;
+
+INSERT INTO opportunity_eligibility (opportunity_id, education_level, year)
+SELECT o.id, level, year FROM opportunities o
+CROSS JOIN LATERAL (VALUES ('UG'::education_level, 2), ('UG', 3), ('UG', 4), ('GRM', 1))
+ AS e(level, year)
+WHERE o.name = 'Google Summer of Code'
+ON CONFLICT DO NOTHING;
+
+-- PhD always carries year NULL — there is no year to pick.
+INSERT INTO opportunity_eligibility (opportunity_id, education_level, year)
+SELECT o.id, level, NULL FROM opportunities o
+CROSS JOIN LATERAL (VALUES ('GRM'::education_level), ('PHD')) AS e(level)
+WHERE o.name = 'NU Alumni Mentorship Programme'
+ON CONFLICT DO NOTHING;
+
+INSERT INTO opportunity_eligibility (opportunity_id, education_level, year)
+SELECT id, 'PHD', NULL FROM opportunities WHERE name = 'Bolashak Scholarship — 2025 intake'
+ON CONFLICT DO NOTHING;
+
+INSERT INTO opportunity_eligibility (opportunity_id, education_level, year)
+SELECT id, 'UG', NULL FROM opportunities WHERE name = 'Astana Hub Startup Grant'
+ON CONFLICT DO NOTHING;
+
+-- Majors: one restricted opportunity, one left open to everybody. As with the
+-- types above, these are Python member names — `COMPUTER_SCIENCE`, not the
+-- "Computer Science" the API sends.
+INSERT INTO opportunity_majors (opportunity_id, major)
+SELECT o.id, major FROM opportunities o
+CROSS JOIN LATERAL (VALUES
+ ('COMPUTER_SCIENCE'::opportunity_major),
+ ('DATA_SCIENCE'),
+ ('ELECTRICAL_AND_COMPUTER_ENGINEERING'),
+ ('ROBOTICS_AND_MECHATRONICS_ENGINEERING')
+) AS m(major)
+WHERE o.name = 'Google Summer of Code'
+ON CONFLICT DO NOTHING;
+
+INSERT INTO opportunity_majors (opportunity_id, major)
+SELECT o.id, major FROM opportunities o
+CROSS JOIN LATERAL (VALUES ('PHYSICS'::opportunity_major), ('CHEMISTRY'), ('BIOLOGICAL_SCIENCES'))
+ AS m(major)
+WHERE o.name = 'Nazarbayev University Research Assistantship'
+ON CONFLICT DO NOTHING;
+
+-- ---------------------------------------------------------------------------
+-- SGotinish
+-- ---------------------------------------------------------------------------
+
+INSERT INTO tickets (author_sub, category, title, body, status, is_anonymous, owner_hash, created_at, updated_at)
+SELECT * FROM (VALUES
+ ('mock-sub-bob', 'academic',
+ 'Library closes too early during finals',
+ 'The 24-hour reading room stops being 24-hour in week 14, which is exactly when it is needed. Could the hours be extended through the exam period?',
+ 'open', false, NULL, now() - interval '3 days', now() - interval '3 days'),
+
+ ('mock-sub-hassan', 'technical',
+ 'Wi-fi drops in Block 22 every evening',
+ 'Between roughly 21:00 and midnight the connection in the west wing becomes unusable. It has been like this since September.',
+ 'in_progress', false, NULL, now() - interval '9 days', now() - interval '2 days'),
+
+ ('mock-sub-bob', 'suggestion',
+ 'Add a bike rack outside Block 7',
+ 'There is nowhere to lock a bike near the main entrance, so people chain them to the railings.',
+ 'resolved', false, NULL, now() - interval '30 days', now() - interval '20 days'),
+
+ ('mock-sub-hassan', 'administrative',
+ 'Transcript request took five weeks',
+ 'Requested on 12 March, received on 16 April, with no way to check progress in between.',
+ 'closed', false, NULL, now() - interval '60 days', now() - interval '35 days'),
+
+ -- Anonymous. `author_sub` is NULL by design: the owner hash is the only thing
+ -- that identifies the author, and the key that produces it is
+ -- demo-anonymous-warpkey-for-local-dev
+ -- so this ticket is reachable at
+ -- http://localhost:6767/t#key=demo-anonymous-warpkey-for-local-dev
+ -- Do not put a real key in a fixture; this one exists to be public.
+ (NULL, 'complaint',
+ 'Grading in a core course feels inconsistent',
+ 'Two students submitted near-identical work and received grades a full letter apart. Raising it with the instructor did not help.',
+ 'in_progress', true, 'b7e8ba0e5b9ebf78ea3c78426a9b419a2e42e00698f4ee8b364cf27bd87dd07e',
+ now() - interval '5 days', now() - interval '1 day')
+) AS seed(author_sub, category, title, body, status, is_anonymous, owner_hash, created_at, updated_at)
+WHERE NOT EXISTS (SELECT 1 FROM tickets t WHERE t.title = seed.title);
+
+INSERT INTO conversations (ticket_id, sg_member_sub, status, created_at)
+SELECT t.id, 'mock-sub-dana', 'active', t.created_at + interval '4 hours'
+FROM tickets t
+WHERE t.title = 'Wi-fi drops in Block 22 every evening'
+ AND NOT EXISTS (SELECT 1 FROM conversations c WHERE c.ticket_id = t.id);
+
+INSERT INTO conversations (ticket_id, sg_member_sub, status, created_at)
+SELECT t.id, 'mock-sub-charlie', 'active', t.created_at + interval '2 hours'
+FROM tickets t
+WHERE t.title = 'Grading in a core course feels inconsistent'
+ AND NOT EXISTS (SELECT 1 FROM conversations c WHERE c.ticket_id = t.id);
+
+INSERT INTO messages (conversation_id, sender_sub, body, is_from_sg_member, sent_at)
+SELECT c.id, 'mock-sub-dana',
+ 'Thanks for reporting this — we have passed it to IT and asked for the access point logs for the west wing.',
+ true, c.created_at + interval '20 minutes'
+FROM conversations c JOIN tickets t ON t.id = c.ticket_id
+WHERE t.title = 'Wi-fi drops in Block 22 every evening'
+ AND NOT EXISTS (
+ SELECT 1 FROM messages m WHERE m.conversation_id = c.id AND m.body = 'Thanks for reporting this — we have passed it to IT and asked for the access point logs for the west wing.'
+ );
+
+INSERT INTO messages (conversation_id, sender_sub, body, is_from_sg_member, sent_at)
+SELECT c.id, 'mock-sub-hassan',
+ 'It happened again last night, around 22:30. Two other people on my floor see the same thing.',
+ false, c.created_at + interval '1 day'
+FROM conversations c JOIN tickets t ON t.id = c.ticket_id
+WHERE t.title = 'Wi-fi drops in Block 22 every evening'
+ AND NOT EXISTS (
+ SELECT 1 FROM messages m WHERE m.conversation_id = c.id AND m.body = 'It happened again last night, around 22:30. Two other people on my floor see the same thing.'
+ );
+
+-- The anonymous author's own message carries no sender_sub. That is the whole
+-- point of the anonymous flow, and it is why the conversation view has to cope
+-- with a message that has no sender.
+INSERT INTO messages (conversation_id, sender_sub, body, is_from_sg_member, sent_at)
+SELECT c.id, NULL,
+ 'I would rather not name the course here. Is there a way to raise it without the instructor knowing who asked?',
+ false, c.created_at + interval '10 minutes'
+FROM conversations c JOIN tickets t ON t.id = c.ticket_id
+WHERE t.title = 'Grading in a core course feels inconsistent'
+ AND NOT EXISTS (
+ SELECT 1 FROM messages m WHERE m.conversation_id = c.id AND m.body = 'I would rather not name the course here. Is there a way to raise it without the instructor knowing who asked?'
+ );
+
+INSERT INTO messages (conversation_id, sender_sub, body, is_from_sg_member, sent_at)
+SELECT c.id, 'mock-sub-charlie',
+ 'Yes. We can raise it through the Ethics Commission without attributing it to you. Nothing you have written here is linked to your account.',
+ true, c.created_at + interval '3 hours'
+FROM conversations c JOIN tickets t ON t.id = c.ticket_id
+WHERE t.title = 'Grading in a core course feels inconsistent'
+ AND NOT EXISTS (
+ SELECT 1 FROM messages m WHERE m.conversation_id = c.id AND m.body = 'Yes. We can raise it through the Ethics Commission without attributing it to you. Nothing you have written here is linked to your account.'
+ );
+
+-- Every Head gets DELEGATE on every ticket, which is what
+-- `TicketService.create_ticket` does for real tickets: it grants access to all
+-- bosses and notifies them. Inserting rows directly skips that, and without
+-- these the SG inbox is empty for a Head — the list is filtered to tickets you
+-- authored or have explicit access to, so a boss with no access rows sees
+-- nothing and it looks like the inbox is broken.
+INSERT INTO ticket_access (ticket_id, user_sub, permission, granted_by_sub, granted_at)
+SELECT t.id, u.sub, 'DELEGATE', NULL, t.created_at
+FROM tickets t CROSS JOIN users u
+WHERE u.role = 'boss'
+ON CONFLICT DO NOTHING;
+
+-- A delegated access list, so the ticket page has something to show and the
+-- "who can see this" question has a non-empty answer. Enum labels again are
+-- Python member names: VIEW / ASSIGN / DELEGATE.
+INSERT INTO ticket_access (ticket_id, user_sub, permission, granted_by_sub, granted_at)
+SELECT t.id, 'mock-sub-dana', 'ASSIGN', 'mock-sub-charlie', now() - interval '4 days'
+FROM tickets t WHERE t.title = 'Grading in a core course feels inconsistent'
+ON CONFLICT DO NOTHING;
+
+INSERT INTO ticket_access (ticket_id, user_sub, permission, granted_by_sub, granted_at)
+SELECT t.id, 'mock-sub-erik', 'VIEW', 'mock-sub-dana', now() - interval '3 days'
+FROM tickets t WHERE t.title = 'Grading in a core course feels inconsistent'
+ON CONFLICT DO NOTHING;
+
+INSERT INTO ticket_access (ticket_id, user_sub, permission, granted_by_sub, granted_at)
+SELECT t.id, 'mock-sub-dana', 'DELEGATE', 'mock-sub-charlie', now() - interval '8 days'
+FROM tickets t WHERE t.title = 'Wi-fi drops in Block 22 every evening'
+ON CONFLICT DO NOTHING;
+
+COMMIT;
diff --git a/backend/fixtures/dev/seed_registered_courses.sql b/backend/fixtures/dev/seed_registered_courses.sql
new file mode 100644
index 00000000..2cc72aa4
--- /dev/null
+++ b/backend/fixtures/dev/seed_registered_courses.sql
@@ -0,0 +1,85 @@
+-- Synthetic registered courses for local dev.
+--
+-- Real ones are pulled from the registrar per student, which needs credentials
+-- no local environment has — so without this every Courses screen renders its
+-- empty state and the live GPA calculator can't be exercised at all.
+--
+-- Shaped like week 8 of a term, deliberately covering the cases the GPA
+-- arithmetic distinguishes: a course doing well with most of the term still
+-- ahead, one where banked and so-far diverge hard, one with nothing graded yet
+-- (must be skipped, not counted as zero), one fully graded, and one with no
+-- items at all.
+--
+-- Run against the local stack:
+-- docker compose exec -T postgres psql -U postgres -d postgres \
+-- < backend/fixtures/dev/seed_registered_courses.sql
+--
+-- Assumes the mock user `mock-sub-alice` exists (MOCK_KEYCLOAK=true, then
+-- hit /api/login?mock_user=1).
+BEGIN;
+
+INSERT INTO courses (registrar_id, course_code, level, school, title, credits, term, created_at, updated_at) VALUES
+ (100151, 'CSCI 151', 'UG', 'SCAI', 'Programming for Scientists and Engineers', 4, 'Fall 2026', now(), now()),
+ (100231, 'CSCI 231', 'UG', 'SCAI', 'Computer Systems and Organization', 3, 'Fall 2026', now(), now()),
+ (100241, 'MATH 241', 'UG', 'SSH', 'Linear Algebra with Applications', 3, 'Fall 2026', now(), now()),
+ (100161, 'PHYS 161', 'UG', 'SSH', 'Physics I', 4, 'Fall 2026', now(), now()),
+ (100101, 'WCS 101', 'UG', 'SSH', 'Writing and Communication I', 3, 'Fall 2026', now(), now());
+
+INSERT INTO student_courses (student_sub, course_id, created_at, updated_at)
+SELECT 'mock-sub-alice', id, now(), now() FROM courses;
+
+-- CSCI 151: doing well, most of the term still ahead.
+INSERT INTO course_items (student_course_id, item_name, total_weight_pct, max_score, obtained_score, created_at, updated_at)
+SELECT sc.id, v.name, v.w, v.max, v.got, now(), now()
+FROM student_courses sc
+JOIN courses c ON c.id = sc.course_id AND c.course_code = 'CSCI 151'
+CROSS JOIN (VALUES
+ ('Lab 1', 5.0, 100.0, 98.0),
+ ('Lab 2', 5.0, 100.0, 92.0),
+ ('Lab 3', 5.0, 100.0, 88.0),
+ ('Homework 1', 10.0, 50.0, 47.5),
+ ('Homework 2', 10.0, 50.0, 41.0),
+ ('Midterm', 25.0, 100.0, 84.0),
+ ('Project', 15.0, 100.0, NULL),
+ ('Final', 25.0, 100.0, NULL)
+) AS v(name, w, max, got);
+
+-- CSCI 231: a rough midterm — the case where "banked" and "so far" diverge.
+INSERT INTO course_items (student_course_id, item_name, total_weight_pct, max_score, obtained_score, created_at, updated_at)
+SELECT sc.id, v.name, v.w, v.max, v.got, now(), now()
+FROM student_courses sc
+JOIN courses c ON c.id = sc.course_id AND c.course_code = 'CSCI 231'
+CROSS JOIN (VALUES
+ ('Quiz 1', 10.0, 20.0, 13.0),
+ ('Quiz 2', 10.0, 20.0, 16.0),
+ ('Midterm', 30.0, 100.0, 61.0),
+ ('Lab work', 20.0, 100.0, NULL),
+ ('Final', 30.0, 100.0, NULL)
+) AS v(name, w, max, got);
+
+-- MATH 241: nothing graded yet — must be skipped by the GPA, not read as 0.
+INSERT INTO course_items (student_course_id, item_name, total_weight_pct, max_score, obtained_score, created_at, updated_at)
+SELECT sc.id, v.name, v.w, v.max, v.got, now(), now()
+FROM student_courses sc
+JOIN courses c ON c.id = sc.course_id AND c.course_code = 'MATH 241'
+CROSS JOIN (VALUES
+ ('Midterm 1', 25.0, 100.0, NULL::numeric),
+ ('Midterm 2', 25.0, 100.0, NULL),
+ ('Final', 50.0, 100.0, NULL)
+) AS v(name, w, max, got);
+
+-- PHYS 161: borderline, and weights sum to 100 with everything graded.
+INSERT INTO course_items (student_course_id, item_name, total_weight_pct, max_score, obtained_score, created_at, updated_at)
+SELECT sc.id, v.name, v.w, v.max, v.got, now(), now()
+FROM student_courses sc
+JOIN courses c ON c.id = sc.course_id AND c.course_code = 'PHYS 161'
+CROSS JOIN (VALUES
+ ('Problem set 1', 20.0, 40.0, 31.0),
+ ('Problem set 2', 20.0, 40.0, 29.0),
+ ('Midterm', 30.0, 100.0, 74.0),
+ ('Final', 30.0, 100.0, 71.0)
+) AS v(name, w, max, got);
+
+-- WCS 101: no items at all — the empty-course case.
+
+COMMIT;
diff --git a/backend/lifespan.py b/backend/lifespan.py
index 0f5b574a..ed87cc27 100644
--- a/backend/lifespan.py
+++ b/backend/lifespan.py
@@ -3,13 +3,15 @@
from fastapi import FastAPI
from google.auth.credentials import Credentials
+# Register Rabbit subscribers before the broker starts.
+import backend.modules.notification.tasks # noqa: F401
+import backend.modules.notion.tasks # noqa: F401
from backend.bootstrap.db import cleanup_db, setup_db
from backend.bootstrap.gcp import setup_gcp
from backend.bootstrap.meilisearch import cleanup_meilisearch, setup_meilisearch
from backend.bootstrap.rbq import cleanup_rbq, setup_rbq
from backend.bootstrap.redis import cleanup_redis, setup_redis
from backend.core.configs.config import Config
-from backend.modules.routers import routers
from backend.modules.auth.app_token import AppTokenManager
from backend.modules.auth.keycloak_manager import KeyCloakManager
from backend.modules.bot.startup import cleanup_bot, setup_bot
@@ -27,10 +29,6 @@
MEILISEARCH_INDEXES as OPPORTUNITIES_MEILI_INDEXES,
)
-# Register Rabbit subscribers before the broker starts.
-import backend.modules.notification.tasks # noqa: F401
-import backend.modules.notion.tasks # noqa: F401
-
@asynccontextmanager
async def lifespan(app: FastAPI):
@@ -56,8 +54,6 @@ async def lifespan(app: FastAPI):
await setup_bot(app)
- for router in routers:
- app.include_router(router)
yield
finally:
diff --git a/backend/main.py b/backend/main.py
index b1646584..edc213de 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -7,6 +7,7 @@
# Import both the instrumentor and the metrics_app
from backend.middlewares.prometheus_metrics import instrument_app, metrics_app
+from backend.modules.routers import routers
app = FastAPI(
debug=True if config.IS_DEBUG else False,
@@ -18,9 +19,15 @@
title="nuspace API",
description=" Nuspace.kz is a SuperApp for NU students that streamlines communication and "
"replaces disorganized Telegram chats with a more reliable solution. "
- "[Project Github](https://github.com/ulanpy/nuspace). "
+ "[Project Github](https://github.com/ulanpy/nuspace). ",
)
+# Routes describe the application and must exist before lifespan starts.
+# Keeping them out of startup lets tooling export OpenAPI without connecting to
+# Postgres, Redis, Meilisearch, RabbitMQ, GCS, or Telegram.
+for router in routers:
+ app.include_router(router)
+
app.mount("/metrics", metrics_app)
app.add_middleware(
diff --git a/backend/modules/auth/api.py b/backend/modules/auth/api.py
index dfe3316d..33111ee2 100644
--- a/backend/modules/auth/api.py
+++ b/backend/modules/auth/api.py
@@ -1,3 +1,4 @@
+import logging
from typing import Annotated
from aiogram import Bot
@@ -7,7 +8,6 @@
from jose import JWTError
from redis.asyncio import Redis
-from backend.modules.auth.dependencies import get_creds_or_401
from backend.common.request_url import request_app_base_url
from backend.core.configs.config import config
from backend.modules.auth import dependencies as deps
@@ -16,10 +16,12 @@
set_kc_auth_cookies,
unset_kc_auth_cookies,
)
+from backend.modules.auth.dependencies import get_creds_or_401
from backend.modules.auth.schemas import CurrentUserResponse, Sub
from backend.modules.auth.service import AuthService
router = APIRouter(tags=["Auth Routes"])
+logger = logging.getLogger(__name__)
@router.get("/login")
@@ -41,12 +43,11 @@ async def login(
status_code=303,
)
+ response = await auth_service.get_authorize_redirect(request, state, app_base_url, reauth)
if reauth:
refresh_token = request.cookies.get(config.COOKIE_REFRESH_NAME)
- response = RedirectResponse(url="/", status_code=303)
await auth_service.prepare_reauth(request, response, refresh_token)
-
- return await auth_service.get_authorize_redirect(request, state, app_base_url, reauth)
+ return response
@router.get("/auth/callback")
@@ -66,10 +67,31 @@ async def auth_callback(
async def bind_tg(
request: Request,
sub_param: Sub,
+ user: Annotated[tuple[dict, dict], Depends(get_creds_or_401)],
auth_service: AuthService = Depends(deps.get_auth_service),
):
+ """Issue a Telegram deeplink binding the caller's own account to a chat."""
+ # The sub is taken from the session, never from the request body, and the
+ # endpoint requires a session at all. Both used to be untrue: it had no auth
+ # dependency and trusted the body, while returning `correct_number` — the
+ # answer to the emoji confirmation — in the same response. Subs are public
+ # (every event and community response carries `creator.sub`), so anyone
+ # could request a link for any account and bind their own Telegram to it,
+ # quietly redirecting that user's notifications, SGotinish ticket updates
+ # included.
+ #
+ # The body is still accepted so existing clients keep working, but a sub
+ # that is not the caller's is refused rather than ignored: a client sending
+ # someone else's is either stale or hostile, and both are worth surfacing.
+ session_sub = user[0].get("sub")
+ if sub_param.sub != session_sub:
+ raise HTTPException(
+ status_code=status.HTTP_403_FORBIDDEN,
+ detail="Cannot bind Telegram for another user",
+ )
+
bot: Bot = request.app.state.bot
- payload = auth_service.build_telegram_bind_payload(sub_param.sub)
+ payload = auth_service.build_telegram_bind_payload(session_sub)
link = await create_start_link(bot, payload["start_payload"], encode=True)
return {
"link": link,
@@ -125,26 +147,23 @@ async def get_current_user(
return await auth_service.get_current_user(kc_principal, app_principal)
-@router.get("/logout")
+# 204 with no body: the only thing this endpoint produces is Set-Cookie headers.
+# It used to return the integer 200 as a JSON body, which said nothing and
+# invited callers to read a result that was never meaningful.
+@router.get("/logout", status_code=status.HTTP_204_NO_CONTENT, response_class=Response)
async def logout(
response: Response,
auth_service: AuthService = Depends(deps.get_auth_service),
refresh_token: Annotated[str | None, Cookie(alias=config.COOKIE_REFRESH_NAME)] = None,
):
- if not refresh_token:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="No refresh token found in cookies",
- )
-
- try:
- await auth_service.logout(refresh_token)
- except Exception as exc:
- raise HTTPException(
- status_code=status.HTTP_403_FORBIDDEN,
- detail=f"Error revoking token: {exc}",
- ) from exc
+ if refresh_token:
+ try:
+ await auth_service.logout(refresh_token)
+ except Exception:
+ # Remote revocation is desirable, but an unavailable identity
+ # provider must not prevent the browser from ending its local
+ # session. The short-lived access token will expire independently.
+ logger.warning("Failed to revoke refresh token during logout", exc_info=True)
unset_kc_auth_cookies(response)
response.delete_cookie(key=config.COOKIE_APP_NAME)
- return status.HTTP_200_OK
diff --git a/backend/modules/auth/mock.py b/backend/modules/auth/mock.py
index 537a8adf..4c0ac001 100644
--- a/backend/modules/auth/mock.py
+++ b/backend/modules/auth/mock.py
@@ -20,6 +20,33 @@
"picture": "https://i.pravatar.cc/150?img=5",
"sub": "mock-sub-charlie",
},
+ # Added so every Student Government role can be signed into rather than
+ # role-swapped in SQL between passes. backend/fixtures/dev/seed_campus.sql
+ # gives these three their roles and departments: Dana is an Executive and
+ # Erik a Member of the same department, which is the pair the capo rules
+ # are about, and Gulnar sits in a special department so "not your
+ # department" has something to refuse.
+ {
+ "email": "dana@example.com",
+ "given_name": "Dana",
+ "family_name": "Dosanova",
+ "picture": "https://i.pravatar.cc/150?img=6",
+ "sub": "mock-sub-dana",
+ },
+ {
+ "email": "erik@example.com",
+ "given_name": "Erik",
+ "family_name": "Ermekov",
+ "picture": "https://i.pravatar.cc/150?img=7",
+ "sub": "mock-sub-erik",
+ },
+ {
+ "email": "hassan@example.com",
+ "given_name": "Hassan",
+ "family_name": "Hakim",
+ "picture": "https://i.pravatar.cc/150?img=10",
+ "sub": "mock-sub-hassan",
+ },
]
diff --git a/backend/modules/auth/tests/test_auth_api.py b/backend/modules/auth/tests/test_auth_api.py
new file mode 100644
index 00000000..23e49128
--- /dev/null
+++ b/backend/modules/auth/tests/test_auth_api.py
@@ -0,0 +1,88 @@
+from unittest.mock import AsyncMock
+
+import pytest
+from backend.core.configs.config import config
+from backend.modules.auth.api import login, logout
+from fastapi import Response
+from fastapi.responses import RedirectResponse
+from starlette.requests import Request
+
+
+def request_with_cookies(cookies: dict[str, str] | None = None) -> Request:
+ cookie_header = "; ".join(f"{name}={value}" for name, value in (cookies or {}).items())
+ headers = [(b"host", b"localhost")]
+ if cookie_header:
+ headers.append((b"cookie", cookie_header.encode()))
+ return Request(
+ {
+ "type": "http",
+ "scheme": "http",
+ "method": "GET",
+ "path": "/api/login",
+ "query_string": b"",
+ "headers": headers,
+ "server": ("localhost", 80),
+ "client": ("127.0.0.1", 1234),
+ }
+ )
+
+
+@pytest.mark.asyncio
+async def test_reauthentication_clears_cookies_on_authorize_response(monkeypatch):
+ from backend.modules.auth import api
+
+ monkeypatch.setattr(api.config, "MOCK_KEYCLOAK", False)
+ auth_service = AsyncMock()
+ auth_service.ensure_login_state.return_value = "state"
+ authorize_response = RedirectResponse("https://identity.example/login")
+ auth_service.get_authorize_redirect.return_value = authorize_response
+ redis = AsyncMock()
+ request = request_with_cookies({config.COOKIE_REFRESH_NAME: "refresh-token"})
+
+ result = await login(
+ request=request,
+ auth_service=auth_service,
+ redis=redis,
+ reauth=True,
+ )
+
+ assert result is authorize_response
+ auth_service.prepare_reauth.assert_awaited_once_with(
+ request, authorize_response, "refresh-token"
+ )
+
+
+@pytest.mark.asyncio
+async def test_logout_without_refresh_token_still_clears_local_cookies():
+ response = Response()
+ auth_service = AsyncMock()
+
+ result = await logout(
+ response=response,
+ auth_service=auth_service,
+ refresh_token=None,
+ )
+
+ assert result is None
+ auth_service.logout.assert_not_awaited()
+ deleted_cookies = response.headers.getlist("set-cookie")
+ assert any(cookie.startswith(f"{config.COOKIE_ACCESS_NAME}=") for cookie in deleted_cookies)
+ assert any(cookie.startswith(f"{config.COOKIE_REFRESH_NAME}=") for cookie in deleted_cookies)
+ assert any(cookie.startswith(f"{config.COOKIE_APP_NAME}=") for cookie in deleted_cookies)
+
+
+@pytest.mark.asyncio
+async def test_logout_clears_local_cookies_when_remote_revocation_fails():
+ response = Response()
+ auth_service = AsyncMock()
+ auth_service.logout.side_effect = RuntimeError("identity provider unavailable")
+
+ result = await logout(
+ response=response,
+ auth_service=auth_service,
+ refresh_token="refresh-token",
+ )
+
+ assert result is None
+ auth_service.logout.assert_awaited_once_with("refresh-token")
+ assert len(response.headers.getlist("set-cookie")) == 3
diff --git a/backend/modules/campuscurrent/communities/og.py b/backend/modules/campuscurrent/communities/og.py
index 8f39519b..15addb9f 100644
--- a/backend/modules/campuscurrent/communities/og.py
+++ b/backend/modules/campuscurrent/communities/og.py
@@ -112,3 +112,25 @@ async def get_community_og_by_query(
html = _build_community_html(community_response, request)
return HTMLResponse(content=html, status_code=status.HTTP_200_OK)
+
+
+@router.get("/og/communities/{id}", response_class=HTMLResponse, include_in_schema=False)
+async def get_community_og_by_path(
+ request: Request,
+ id: int,
+ user=Depends(get_creds_or_guest),
+ infra: Infra = Depends(get_infra),
+ community_service: CommunityService = Depends(get_community_service),
+) -> HTMLResponse:
+ """Path-param variant for /communities/{id} URLs.
+
+ Nginx rewrites crawler requests to /api/og$request_uri, so the shape of this
+ route has to mirror the frontend's URLs. The query-param route above is kept
+ so links already shared as /communities?id=123 keep their previews.
+ """
+ community_response = await community_service.get_community_response(
+ infra=infra, community_id=id, user=user
+ )
+
+ html = _build_community_html(community_response, request)
+ return HTMLResponse(content=html, status_code=status.HTTP_200_OK)
diff --git a/backend/modules/campuscurrent/events/og.py b/backend/modules/campuscurrent/events/og.py
index ea3db7d2..71621c34 100644
--- a/backend/modules/campuscurrent/events/og.py
+++ b/backend/modules/campuscurrent/events/og.py
@@ -32,13 +32,13 @@ def _truncate(text: str, max_len: int) -> str:
def _select_og_image(event_response) -> str | None:
+ # Events no longer carry a community (see "detached communities from
+ # events"), so there is no community banner to fall back to. Reading it
+ # here raised AttributeError and turned every preview for an event without
+ # its own media into a 500.
for media in event_response.media:
if getattr(media, "url", ""):
return media.url
- if event_response.community:
- for media in event_response.community.media:
- if getattr(media, "url", ""):
- return media.url
return None
@@ -104,3 +104,25 @@ async def get_event_og_by_query(
html = _build_event_html(event_response, request)
return HTMLResponse(content=html, status_code=status.HTTP_200_OK)
+
+
+@router.get("/og/events/{id}", response_class=HTMLResponse, include_in_schema=False)
+async def get_event_og_by_path(
+ request: Request,
+ id: int,
+ user=Depends(get_creds_or_guest),
+ infra: Infra = Depends(get_infra),
+ event_service: EventService = Depends(get_event_service),
+) -> HTMLResponse:
+ """Path-param variant for /events/{id} URLs.
+
+ Nginx rewrites crawler requests to /api/og$request_uri, so the shape of this
+ route has to mirror the frontend's URLs. The query-param route above is kept
+ so links already shared as /events?id=123 keep their previews.
+ """
+ event_response = await event_service.get_event_by_id(
+ infra=infra, event_id=id, user=user
+ )
+
+ html = _build_event_html(event_response, request)
+ return HTMLResponse(content=html, status_code=status.HTTP_200_OK)
diff --git a/backend/modules/courses/courses/api.py b/backend/modules/courses/courses/api.py
index 18ab8a12..e82922d7 100644
--- a/backend/modules/courses/courses/api.py
+++ b/backend/modules/courses/courses/api.py
@@ -1,23 +1,28 @@
"""
-This module is as a tribute to the creator
+This module is as a tribute to the creator
of crashed.nu — @superhooman.
GitHub: https://github.com/superhooman/crashed.nu
"""
-
-
from typing import Annotated, List
import httpx
from backend.common.dependencies import get_infra
-from backend.modules.auth.dependencies import get_creds_or_401
from backend.common.schemas import Infra
from backend.core.configs.config import config
+from backend.modules.auth.dependencies import get_creds_or_401
from backend.modules.courses.courses import schemas
from backend.modules.courses.courses.dependencies import get_student_course_service
from backend.modules.courses.courses.errors import CourseLookupError, SemesterResolutionError
from backend.modules.courses.courses.policy import StudentCoursePolicy
from backend.modules.courses.courses.service import StudentCourseService
+from backend.modules.courses.registrar.clients.registrar_client import (
+ RegistrarLoginUnconfirmed,
+)
+from backend.modules.courses.registrar.username import (
+ RegistrarDebugUsernameMissing,
+ resolve_registrar_username,
+)
from fastapi import APIRouter, Cookie, Depends, HTTPException, Query, status
from fastapi.responses import Response
@@ -52,8 +57,10 @@ async def sync_courses_from_registrar(
"""
try:
student_sub = user[0].get("sub")
- student_username = (
- user[0].get("email").split("@")[0] if not config.IS_DEBUG else "ulan.sharipov"
+ student_username = resolve_registrar_username(
+ user[0].get("email"),
+ is_debug=config.IS_DEBUG,
+ debug_username=config.REGISTRAR_DEBUG_USERNAME,
)
sync_result = await service.sync_courses_from_registrar(
student_sub=student_sub,
@@ -62,17 +69,30 @@ async def sync_courses_from_registrar(
)
return sync_result
+ except RegistrarDebugUsernameMissing as e:
+ raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail=str(e))
+
except CourseLookupError as e:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
except SemesterResolutionError as e:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
+ except RegistrarLoginUnconfirmed as e:
+ # Not a credentials problem, so not a 401 -- telling the student to
+ # check a password that works wastes their time and hides a real fault.
+ raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=str(e))
+
except ValueError as e:
# Registrar login failures bubble up as ValueError
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))
-
+ except httpx.RequestError as e:
+ # DNS, TLS or connectivity failure reaching the registrar.
+ raise HTTPException(
+ status_code=status.HTTP_502_BAD_GATEWAY,
+ detail=f"Could not reach the registrar: {e.__class__.__name__}",
+ )
@router.post("/registered_courses/sync/pdf", response_model=schemas.RegistrarSyncResponse)
@@ -240,9 +260,7 @@ async def update_course_item(
- Updated course item with all details
"""
- return await service.update_course_item(
- item_id=item_id, item_update=item_update, user=user
- )
+ return await service.update_course_item(item_id=item_id, item_update=item_update, user=user)
@router.delete("/course_items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
@@ -295,6 +313,4 @@ async def get_courses(
**Returns:**
- Paginated list of courses with total pages information
"""
- return await service.get_courses(
- infra=infra, page=page, size=size, term=term, keyword=keyword
- )
+ return await service.get_courses(infra=infra, page=page, size=size, term=term, keyword=keyword)
diff --git a/backend/modules/courses/courses/tests/test_course_code_normalization.py b/backend/modules/courses/courses/tests/test_course_code_normalization.py
index 5f7fcc19..d48532c3 100644
--- a/backend/modules/courses/courses/tests/test_course_code_normalization.py
+++ b/backend/modules/courses/courses/tests/test_course_code_normalization.py
@@ -1,20 +1,14 @@
+import pytest
from backend.modules.courses.courses.service import StudentCourseService
from backend.modules.courses.registrar.schemas import CourseSearchResponse, CourseSummary
-import pytest
def test_normalize_course_code_spaces_cross_list_wcs_wll() -> None:
- assert (
- StudentCourseService._normalize_course_code("WCS260/WLL235")
- == "WCS 260/WLL 235"
- )
+ assert StudentCourseService._normalize_course_code("WCS260/WLL235") == "WCS 260/WLL 235"
def test_normalize_course_code_spaces_cross_list_wll_ant() -> None:
- assert (
- StudentCourseService._normalize_course_code(" WLL171 / ANT175 ")
- == "WLL 171/ANT 175"
- )
+ assert StudentCourseService._normalize_course_code(" WLL171 / ANT175 ") == "WLL 171/ANT 175"
@pytest.mark.asyncio
@@ -62,11 +56,10 @@ async def find_course_by_registrar_id(self, registrar_id: int):
async def create_course(self, data):
return {"created": True, "registrar_id": data.registrar_id}
- service = StudentCourseService(repository=FakeRepo(), registrar_service=FakeRegistrar())
+ service = StudentCourseService(repository=FakeRepo(), registrar=FakeRegistrar())
result = await service._get_or_create_course(
course_code="WLL 235/WCS 260",
term_value="822",
)
assert result == {"created": True, "registrar_id": 9999}
-
diff --git a/backend/modules/courses/courses/tests/test_registrar_sync_api.py b/backend/modules/courses/courses/tests/test_registrar_sync_api.py
new file mode 100644
index 00000000..752dd029
--- /dev/null
+++ b/backend/modules/courses/courses/tests/test_registrar_sync_api.py
@@ -0,0 +1,25 @@
+from unittest.mock import AsyncMock
+
+import pytest
+from backend.modules.courses.courses.api import sync_courses_from_registrar
+from backend.modules.courses.courses.schemas import RegistrarSyncRequest
+from fastapi import HTTPException
+
+
+@pytest.mark.asyncio
+async def test_debug_sync_without_username_returns_503_before_service_call(monkeypatch):
+ from backend.modules.courses.courses import api
+
+ monkeypatch.setattr(api.config, "IS_DEBUG", True)
+ monkeypatch.setattr(api.config, "REGISTRAR_DEBUG_USERNAME", " ")
+ service = AsyncMock()
+
+ with pytest.raises(HTTPException) as raised:
+ await sync_courses_from_registrar(
+ data=RegistrarSyncRequest(password="real-password"),
+ user=({"sub": "mock-user"}, {}),
+ service=service,
+ )
+
+ assert raised.value.status_code == 503
+ service.sync_courses_from_registrar.assert_not_awaited()
diff --git a/backend/modules/courses/degree_audit/api.py b/backend/modules/courses/degree_audit/api.py
index a730284f..3ddcd45a 100644
--- a/backend/modules/courses/degree_audit/api.py
+++ b/backend/modules/courses/degree_audit/api.py
@@ -14,7 +14,12 @@
DegreeRequirement,
)
from backend.modules.courses.degree_audit.service import DegreeAuditService
-from fastapi import APIRouter, Depends, status
+from backend.modules.courses.registrar.clients.registrar_client import (
+ InvalidRegistrarCredentials,
+ RegistrarLoginUnconfirmed,
+)
+from fastapi import APIRouter, Depends, HTTPException, status
+import httpx
from sqlalchemy.ext.asyncio import AsyncSession
router = APIRouter(prefix="/degree-audit", tags=["Degree Audit"])
@@ -44,16 +49,38 @@ async def audit_from_registrar(
db_session: AsyncSession = Depends(get_db_session),
service: DegreeAuditService = Depends(get_degree_audit_service),
) -> AuditResponse:
- return await service.audit_with_registrar(
- year=payload.year,
- majors=payload.majors,
- minors=payload.minors,
- username=payload.username if not config.IS_DEBUG else "bauyrzhan.kizatov",
- password=payload.password,
- student_sub=_creds[1]["sub"],
- session=db_session,
- tc_mappings=payload.tc_mappings,
- )
+ # Locally, override with your own registrar username via
+ # REGISTRAR_DEBUG_USERNAME rather than sending someone else's.
+ username = payload.username
+ if config.IS_DEBUG and config.REGISTRAR_DEBUG_USERNAME:
+ username = config.REGISTRAR_DEBUG_USERNAME
+
+ try:
+ return await service.audit_with_registrar(
+ year=payload.year,
+ majors=payload.majors,
+ minors=payload.minors,
+ username=username,
+ password=payload.password,
+ student_sub=_creds[1]["sub"],
+ session=db_session,
+ tc_mappings=payload.tc_mappings,
+ )
+
+ # Without these the registrar's own failures escape as unhandled exceptions
+ # and become a 500, which tells the caller nothing and (with debug on) sends
+ # a full traceback back in the response body.
+ except InvalidRegistrarCredentials as exc:
+ raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(exc))
+
+ except RegistrarLoginUnconfirmed as exc:
+ raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=str(exc))
+
+ except httpx.RequestError as exc:
+ raise HTTPException(
+ status_code=status.HTTP_502_BAD_GATEWAY,
+ detail=f"Could not reach the registrar: {exc.__class__.__name__}",
+ )
@router.post(
diff --git a/backend/modules/courses/degree_audit/service.py b/backend/modules/courses/degree_audit/service.py
index 2b6723f2..680db3b6 100644
--- a/backend/modules/courses/degree_audit/service.py
+++ b/backend/modules/courses/degree_audit/service.py
@@ -339,21 +339,32 @@ async def get_cached_result(
stmt = select(DegreeAuditResult).where(DegreeAuditResult.student_sub == student_sub)
if year:
stmt = stmt.where(DegreeAuditResult.admission_year == year)
- if major:
- stmt = stmt.where(DegreeAuditResult.major == major)
stmt = stmt.order_by(DegreeAuditResult.updated_at.desc())
result = await session.execute(stmt)
- row: DegreeAuditResult | None = result.scalars().first()
+ rows: list[DegreeAuditResult] = list(result.scalars().all())
+
+ def programmes(row: DegreeAuditResult) -> tuple[list[str], list[str]]:
+ # `major` holds a JSON blob -- {"majors": [...], "minors": [...]} --
+ # not a programme name. Older rows may still hold a bare name, hence
+ # the fallback.
+ try:
+ parsed = json.loads(row.major)
+ return parsed.get("majors", []), parsed.get("minors", [])
+ except Exception:
+ return [row.major], []
+
+ # Filtering by major has to look inside that blob. It used to compare the
+ # column to the name directly, which could never match, so passing
+ # `?major=` always returned null -- the caller could not tell "no audit
+ # for this programme" from "the filter is broken".
+ if major:
+ rows = [row for row in rows if major in programmes(row)[0]]
+
+ row = rows[0] if rows else None
if not row:
return None
-
- try:
- parsed = json.loads(row.major)
- majors = parsed.get("majors", [])
- minors = parsed.get("minors", [])
- except Exception:
- majors = [row.major]
- minors = []
+
+ majors, minors = programmes(row)
from backend.modules.courses.degree_audit.schemas import AuditProgramResult
diff --git a/backend/modules/courses/registrar/clients/registrar_client.py b/backend/modules/courses/registrar/clients/registrar_client.py
index 03dd4c79..0b9a5303 100644
--- a/backend/modules/courses/registrar/clients/registrar_client.py
+++ b/backend/modules/courses/registrar/clients/registrar_client.py
@@ -1,31 +1,72 @@
import json
-from typing import Any
-import time
import re
+import ssl
+import time
+from pathlib import Path
+from typing import Any
import httpx
-from httpx import Cookies
-
HOST = "https://registrar.nu.edu.kz"
LOGIN_PATH = "/index.php"
SCHEDULE_HTML_PATH = "/my-registrar/personal-schedule"
SCHEDULE_JSON_PATH = "/my-registrar/personal-schedule/json"
+# registrar.nu.edu.kz serves a valid, publicly-trusted Sectigo certificate for
+# *.nu.edu.kz, but sends only the leaf -- it omits the intermediate CA. Clients
+# therefore cannot build a chain to the Sectigo root and verification fails with
+# "unable to get local issuer certificate".
+#
+# Supplying the missing intermediate ourselves is the actual fix. The
+# alternative that was in place -- disabling verification entirely -- also
+# disables every guarantee TLS provides on this connection, and this is the
+# connection that carries a student's registrar password. Anyone able to
+# intercept traffic between the backend and the registrar could present any
+# certificate at all and harvest those credentials in plaintext.
+_INTERMEDIATE_CA = Path(__file__).with_name("sectigo_intermediate.pem")
+
+
+# Session cookies a successful login may set. AUTHSSL is what the registrar
+# used; Drupal's own are SESS*/SSESS*. Accepting any of them means a rename on
+# their side degrades to "could not confirm" rather than "wrong password".
+_SESSION_COOKIE_NAMES = {"AUTHSSL", "AUTHSESS"}
+
+
+class InvalidRegistrarCredentials(ValueError):
+ """The registrar explicitly rejected the username or password."""
+
+
+class RegistrarLoginUnconfirmed(RuntimeError):
+ """Login neither clearly succeeded nor was clearly rejected."""
+
+
+def _build_ssl_context() -> ssl.SSLContext:
+ # Default trust store for the roots, plus the one intermediate the registrar
+ # omits. Loading it as an additional anchor is only a path-building aid --
+ # its own root is already trusted, so this grants no new trust.
+ context = ssl.create_default_context()
+ context.load_verify_locations(cafile=str(_INTERMEDIATE_CA))
+ return context
+
class RegistrarClient:
"""
HTTP client for interacting with NU registrar system.
-
+
Provides async context manager interface for authenticated requests to fetch
student schedule data. Handles login authentication and session management
automatically.
-
+
Args:
- verify_ssl: Whether to verify SSL certificates (default: False for registrar)
+ verify_ssl: Whether to verify the registrar's TLS certificate. Defaults
+ to True and should stay that way; the missing intermediate that made
+ verification fail is bundled, so there is no longer a reason to
+ disable it. Kept only as an escape hatch if the registrar's
+ certificate chain changes again.
timeout: Request timeout in seconds (default: 30.0)
"""
- def __init__(self, *, verify_ssl: bool = False, timeout: float = 30.0) -> None:
+
+ def __init__(self, *, verify_ssl: bool = True, timeout: float = 30.0) -> None:
self.verify_ssl = verify_ssl
self.timeout = timeout
self._client: httpx.AsyncClient | None = None
@@ -44,7 +85,7 @@ async def _ensure_client(self) -> httpx.AsyncClient:
self._client = httpx.AsyncClient(
base_url=HOST,
timeout=self.timeout,
- verify=self.verify_ssl,
+ verify=_build_ssl_context() if self.verify_ssl else False,
)
self._client.cookies.set("has_js", "1", domain="registrar.nu.edu.kz")
return self._client
@@ -68,9 +109,29 @@ async def login(self, username: str, password: str) -> None:
if response.status_code >= 400:
response.raise_for_status()
- cookies: Cookies = client.cookies
- if not any(cookie for cookie in cookies.jar if cookie.name == "AUTHSSL"):
- raise ValueError("Invalid registrar credentials")
+ # Drupal answers a rejected login with 200 and an error message, so the
+ # status code says nothing. Read the outcome from three signals rather
+ # than one: previously this checked only for an AUTHSSL cookie and
+ # reported "invalid credentials" whenever it was absent, which means a
+ # rename of that cookie would tell every student their password was
+ # wrong while it was in fact fine.
+ body = response.text
+ rejected = "unrecognized username or password" in body.lower()
+ has_session = any(
+ cookie.name in _SESSION_COOKIE_NAMES or cookie.name.startswith("SSESS")
+ for cookie in client.cookies.jar
+ )
+ looks_logged_in = has_session or "user/logout" in body
+
+ if rejected:
+ raise InvalidRegistrarCredentials("The registrar rejected the username or password.")
+ if not looks_logged_in:
+ # Neither signal present: the login page changed, or the registrar
+ # answered with something unexpected. Saying "wrong password" here
+ # would send the student to reset a password that works.
+ raise RegistrarLoginUnconfirmed(
+ "Could not confirm the registrar login; the sign-in page may have changed."
+ )
async def _get_schedule_access(self) -> dict[str, Any]:
"""
@@ -143,7 +204,9 @@ async def fetch_schedule(self, username: str, password: str) -> dict[str, Any]:
return primary
- async def fetch_unofficial_transcript_raw(self, username: str, password: str) -> tuple[str, Any]:
+ async def fetch_unofficial_transcript_raw(
+ self, username: str, password: str
+ ) -> tuple[str, Any]:
"""
Fetch unofficial transcript payload directly from registrar.
Returns tuple of (content_type, payload) where payload is JSON (dict)
@@ -186,7 +249,11 @@ async def fetch_unofficial_transcript_pdf(self, username: str, password: str) ->
pass
if text:
- m = re.search(r'(?:href|src)="([^"]*transcriptRenderDocumentPDF[^"]+)"', text, re.IGNORECASE)
+ m = re.search(
+ r'(?:href|src)="([^"]*transcriptRenderDocumentPDF[^"]+)"',
+ text,
+ re.IGNORECASE,
+ )
if m:
url = m.group(1)
# Support both absolute and relative links.
diff --git a/backend/modules/courses/registrar/clients/sectigo_intermediate.pem b/backend/modules/courses/registrar/clients/sectigo_intermediate.pem
new file mode 100644
index 00000000..af4a9d66
--- /dev/null
+++ b/backend/modules/courses/registrar/clients/sectigo_intermediate.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGTDCCBDSgAwIBAgIQOXpmzCdWNi4NqofKbqvjsTANBgkqhkiG9w0BAQwFADBf
+MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
+Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
+HhcNMjEwMzIyMDAwMDAwWhcNMzYwMzIxMjM1OTU5WjBgMQswCQYDVQQGEwJHQjEY
+MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIFB1Ymxp
+YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gQ0EgRFYgUjM2MIIBojANBgkqhkiG9w0B
+AQEFAAOCAY8AMIIBigKCAYEAljZf2HIz7+SPUPQCQObZYcrxLTHYdf1ZtMRe7Yeq
+RPSwygz16qJ9cAWtWNTcuICc++p8Dct7zNGxCpqmEtqifO7NvuB5dEVexXn9RFFH
+12Hm+NtPRQgXIFjx6MSJcNWuVO3XGE57L1mHlcQYj+g4hny90aFh2SCZCDEVkAja
+EMMfYPKuCjHuuF+bzHFb/9gV8P9+ekcHENF2nR1efGWSKwnfG5RawlkaQDpRtZTm
+M64TIsv/r7cyFO4nSjs1jLdXYdz5q3a4L0NoabZfbdxVb+CUEHfB0bpulZQtH1Rv
+38e/lIdP7OTTIlZh6OYL6NhxP8So0/sht/4J9mqIGxRFc0/pC8suja+wcIUna0HB
+pXKfXTKpzgis+zmXDL06ASJf5E4A2/m+Hp6b84sfPAwQ766rI65mh50S0Di9E3Pn
+2WcaJc+PILsBmYpgtmgWTR9eV9otfKRUBfzHUHcVgarub/XluEpRlTtZudU5xbFN
+xx/DgMrXLUAPaI60fZ6wA+PTAgMBAAGjggGBMIIBfTAfBgNVHSMEGDAWgBRWc1hk
+lfmSGrASKgRieaFAFYghSTAdBgNVHQ4EFgQUaMASFhgOr872h6YyV6NGUV3LBycw
+DgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYI
+KwYBBQUHAwEGCCsGAQUFBwMCMBsGA1UdIAQUMBIwBgYEVR0gADAIBgZngQwBAgEw
+VAYDVR0fBE0wSzBJoEegRYZDaHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdv
+UHVibGljU2VydmVyQXV0aGVudGljYXRpb25Sb290UjQ2LmNybDCBhAYIKwYBBQUH
+AQEEeDB2ME8GCCsGAQUFBzAChkNodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3Rp
+Z29QdWJsaWNTZXJ2ZXJBdXRoZW50aWNhdGlvblJvb3RSNDYucDdjMCMGCCsGAQUF
+BzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEA
+YtOC9Fy+TqECFw40IospI92kLGgoSZGPOSQXMBqmsGWZUQ7rux7cj1du6d9rD6C8
+ze1B2eQjkrGkIL/OF1s7vSmgYVafsRoZd/IHUrkoQvX8FZwUsmPu7amgBfaY3g+d
+q1x0jNGKb6I6Bzdl6LgMD9qxp+3i7GQOnd9J8LFSietY6Z4jUBzVoOoz8iAU84OF
+h2HhAuiPw1ai0VnY38RTI+8kepGWVfGxfBWzwH9uIjeooIeaosVFvE8cmYUB4TSH
+5dUyD0jHct2+8ceKEtIoFU/FfHq/mDaVnvcDCZXtIgitdMFQdMZaVehmObyhRdDD
+4NQCs0gaI9AAgFj4L9QtkARzhQLNyRf87Kln+YU0lgCGr9HLg3rGO8q+Y4ppLsOd
+unQZ6ZxPNGIfOApbPVf5hCe58EZwiWdHIMn9lPP6+F404y8NNugbQixBber+x536
+WrZhFZLjEkhp7fFXf9r32rNPfb74X/U90Bdy4lzp3+X1ukh1BuMxA/EEhDoTOS3l
+7ABvc7BYSQubQ2490OcdkIzUh3ZwDrakMVrbaTxUM2p24N6dB+ns2zptWCva6jzW
+r8IWKIMxzxLPv5Kt3ePKcUdvkBU/smqujSczTzzSjIoR5QqQA6lN1ZRSnuHIWCvh
+JEltkYnTAH41QJ6SAWO66GrrUESwN/cgZzL4JLEqz1Y=
+-----END CERTIFICATE-----
diff --git a/backend/modules/courses/registrar/tests/test_registrar_client.py b/backend/modules/courses/registrar/tests/test_registrar_client.py
index d8b5406e..1587404b 100644
--- a/backend/modules/courses/registrar/tests/test_registrar_client.py
+++ b/backend/modules/courses/registrar/tests/test_registrar_client.py
@@ -1,16 +1,84 @@
import importlib.util
from pathlib import Path
+from types import SimpleNamespace
import pytest
-CLIENT_PATH = (
- Path(__file__).resolve().parents[1] / "clients" / "registrar_client.py"
-)
+CLIENT_PATH = Path(__file__).resolve().parents[1] / "clients" / "registrar_client.py"
spec = importlib.util.spec_from_file_location("registrar_client", CLIENT_PATH)
registrar_client = importlib.util.module_from_spec(spec)
assert spec and spec.loader
spec.loader.exec_module(registrar_client)
RegistrarClient = registrar_client.RegistrarClient
+InvalidRegistrarCredentials = registrar_client.InvalidRegistrarCredentials
+RegistrarLoginUnconfirmed = registrar_client.RegistrarLoginUnconfirmed
+
+
+class LoginResponse:
+ status_code = 200
+
+ def __init__(self, text: str):
+ self.text = text
+
+ def raise_for_status(self) -> None:
+ raise AssertionError("raise_for_status should not be called")
+
+
+class LoginHttpClient:
+ def __init__(self, text: str, cookie_names: tuple[str, ...] = ()):
+ self.response = LoginResponse(text)
+ self.cookies = SimpleNamespace(jar=[SimpleNamespace(name=name) for name in cookie_names])
+
+ async def post(self, *args, **kwargs):
+ return self.response
+
+
+def install_login_client(monkeypatch, registrar, fake_http_client):
+ async def fake_ensure_client():
+ return fake_http_client
+
+ monkeypatch.setattr(registrar, "_ensure_client", fake_ensure_client)
+
+
+@pytest.mark.asyncio
+async def test_login_recognizes_explicitly_rejected_credentials(monkeypatch):
+ client = RegistrarClient()
+ install_login_client(
+ monkeypatch,
+ client,
+ LoginHttpClient("Unrecognized username or password."),
+ )
+
+ with pytest.raises(InvalidRegistrarCredentials):
+ await client.login("student", "wrong")
+
+
+@pytest.mark.asyncio
+@pytest.mark.parametrize(
+ ("body", "cookies"),
+ [
+ ("Welcome", ("AUTHSSL",)),
+ ('Log out ', ()),
+ ],
+)
+async def test_login_accepts_session_or_logout_success_signals(monkeypatch, body, cookies):
+ client = RegistrarClient()
+ install_login_client(monkeypatch, client, LoginHttpClient(body, cookies))
+
+ await client.login("student", "correct")
+
+
+@pytest.mark.asyncio
+async def test_login_reports_an_unconfirmed_page_change(monkeypatch):
+ client = RegistrarClient()
+ install_login_client(
+ monkeypatch,
+ client,
+ LoginHttpClient("Unexpected login response"),
+ )
+
+ with pytest.raises(RegistrarLoginUnconfirmed):
+ await client.login("student", "correct")
@pytest.mark.asyncio
diff --git a/backend/modules/courses/registrar/tests/test_registrar_service.py b/backend/modules/courses/registrar/tests/test_registrar_service.py
index eb065bae..350b1e71 100644
--- a/backend/modules/courses/registrar/tests/test_registrar_service.py
+++ b/backend/modules/courses/registrar/tests/test_registrar_service.py
@@ -1,5 +1,4 @@
import pytest
-
from backend.modules.courses.registrar import service as registrar_service
from backend.modules.courses.registrar.service import RegistrarService
@@ -12,7 +11,7 @@ async def fake_get(*args, **kwargs):
return {
"hits": [
{
- "abbr": "MATH 263",
+ "course_code": "MATH 263",
"prerequisite": "Wrong prereq",
"corequisite": "",
"antirequisite": "",
@@ -22,7 +21,7 @@ async def fake_get(*args, **kwargs):
"priority_4": "",
},
{
- "abbr": "MATH 162",
+ "course_code": "MATH 162",
"prerequisite": "Correct prereq",
"corequisite": "",
"antirequisite": "",
@@ -50,7 +49,7 @@ async def fake_get(*args, **kwargs):
return {
"hits": [
{
- "abbr": "MATH 263",
+ "course_code": "MATH 263",
"prerequisite": "Wrong prereq",
}
]
@@ -61,4 +60,3 @@ async def fake_get(*args, **kwargs):
result = await service.fetch_course_priorities(["MATH 162"])
assert result == {}
-
diff --git a/backend/modules/courses/registrar/tests/test_registrar_username.py b/backend/modules/courses/registrar/tests/test_registrar_username.py
new file mode 100644
index 00000000..e444da03
--- /dev/null
+++ b/backend/modules/courses/registrar/tests/test_registrar_username.py
@@ -0,0 +1,47 @@
+import pytest
+from backend.modules.courses.registrar.username import (
+ RegistrarDebugUsernameMissing,
+ resolve_registrar_username,
+)
+
+
+def test_debug_requires_an_explicit_nonblank_username():
+ for configured in (None, "", " "):
+ with pytest.raises(RegistrarDebugUsernameMissing):
+ resolve_registrar_username(
+ None,
+ is_debug=True,
+ debug_username=configured,
+ )
+
+
+def test_debug_uses_only_the_configured_username():
+ assert (
+ resolve_registrar_username(
+ "mock-user@example.com",
+ is_debug=True,
+ debug_username=" developer ",
+ )
+ == "developer"
+ )
+
+
+def test_production_derives_the_email_local_part():
+ assert (
+ resolve_registrar_username(
+ "student@nu.edu.kz",
+ is_debug=False,
+ debug_username="ignored",
+ )
+ == "student"
+ )
+
+
+@pytest.mark.parametrize("email", [None, "", "not-an-email", "@nu.edu.kz"])
+def test_production_rejects_an_invalid_email(email):
+ with pytest.raises(ValueError):
+ resolve_registrar_username(
+ email,
+ is_debug=False,
+ debug_username=None,
+ )
diff --git a/backend/modules/courses/registrar/username.py b/backend/modules/courses/registrar/username.py
new file mode 100644
index 00000000..911c8859
--- /dev/null
+++ b/backend/modules/courses/registrar/username.py
@@ -0,0 +1,31 @@
+class RegistrarDebugUsernameMissing(RuntimeError):
+ """Debug registrar access was attempted without an explicit safe username."""
+
+
+def resolve_registrar_username(
+ email: object,
+ *,
+ is_debug: bool,
+ debug_username: str | None,
+) -> str:
+ """
+ Resolve credentials without ever falling back to a mock identity in debug.
+
+ Production keeps using the local part of the authenticated NU email. Debug
+ mode must opt in with a nonblank username before any registrar call occurs.
+ """
+ if is_debug:
+ username = (debug_username or "").strip()
+ if not username:
+ raise RegistrarDebugUsernameMissing(
+ "Registrar sync is unavailable until REGISTRAR_DEBUG_USERNAME is configured."
+ )
+ return username
+
+ if not isinstance(email, str) or "@" not in email:
+ raise ValueError("The signed-in account does not have a valid email address.")
+
+ username = email.split("@", 1)[0].strip()
+ if not username:
+ raise ValueError("The signed-in account does not have a valid email address.")
+ return username
diff --git a/backend/modules/courses/statistics/service.py b/backend/modules/courses/statistics/service.py
index 147e327f..fef827d6 100644
--- a/backend/modules/courses/statistics/service.py
+++ b/backend/modules/courses/statistics/service.py
@@ -23,6 +23,14 @@ async def list_grade_reports(
meili_filters = [f"term = {term}"] if term else None
meili_result = None
+ # The term filter has to be applied in SQL as well as in Meilisearch.
+ # Meilisearch is only consulted when there is a keyword, so without this the
+ # filter silently did nothing while browsing a term -- `?term=FA2025` and
+ # even `?term=NONSENSE` both returned every row, which reads as "this term
+ # has 1308 courses" rather than as a broken filter.
+ if term:
+ conditions.append(GradeReport.term == term)
+
if keyword:
meili_result = await meilisearch.get(
client=meilisearch_client,
diff --git a/backend/modules/sgotinish/conversations/dependencies.py b/backend/modules/sgotinish/conversations/dependencies.py
index e860ca0a..ac147b5a 100644
--- a/backend/modules/sgotinish/conversations/dependencies.py
+++ b/backend/modules/sgotinish/conversations/dependencies.py
@@ -1,10 +1,19 @@
+from backend.common.dependencies import get_db_session
from backend.modules.sgotinish.conversations.service import ConversationService
from backend.modules.sgotinish.tickets.dependencies import get_ticket_service
from backend.modules.sgotinish.tickets.service import TicketService
from fastapi import Depends
+from sqlalchemy.ext.asyncio import AsyncSession
def get_conversation_service(
+ db_session: AsyncSession = Depends(get_db_session),
ticket_service: TicketService = Depends(get_ticket_service),
) -> ConversationService:
- return ticket_service.conversation_service
+ # Built the same way the message service is: TicketService satisfies the
+ # TicketAccessChecker protocol the conversation service needs.
+ #
+ # This previously returned `ticket_service.conversation_service`, an
+ # attribute TicketService does not define, so every conversation endpoint
+ # raised AttributeError and answered 500.
+ return ConversationService(db_session, ticket_service)
diff --git a/backend/modules/sgotinish/messages/api.py b/backend/modules/sgotinish/messages/api.py
index a0b3e92f..74f26c88 100644
--- a/backend/modules/sgotinish/messages/api.py
+++ b/backend/modules/sgotinish/messages/api.py
@@ -7,6 +7,7 @@
from backend.modules.sgotinish.messages import dependencies as deps
from backend.modules.sgotinish.messages import schemas
from backend.modules.sgotinish.messages.service import MessageService
+from backend.modules.sgotinish.owner_hash import get_owner_hash
from fastapi import APIRouter, Depends, Query
router = APIRouter(tags=["SGotinish Messages Routes"])
@@ -22,7 +23,7 @@ async def create_message(
message_data: schemas.MessageCreateDTO,
user_tuple: Annotated[tuple[dict, dict], Depends(get_creds_or_guest)],
service: MessageService = Depends(deps.get_message_service),
- owner_hash: str | None = Query(default=None),
+ owner_hash: str | None = Depends(get_owner_hash),
) -> schemas.MessageResponseDTO:
"""
Creates a new message in a conversation.
@@ -52,7 +53,7 @@ async def get_messages(
service: MessageService = Depends(deps.get_message_service),
size: int = Query(20, ge=1, le=100),
page: int = 1,
- owner_hash: str | None = Query(default=None),
+ owner_hash: str | None = Depends(get_owner_hash),
) -> schemas.ListMessageDTO:
"""
Retrieves a paginated list of messages with flexible filtering.
@@ -83,7 +84,7 @@ async def get_message(
message_id: int,
user_tuple: Annotated[tuple[dict, dict], Depends(get_creds_or_guest)],
service: MessageService = Depends(deps.get_message_service),
- owner_hash: str | None = Query(default=None),
+ owner_hash: str | None = Depends(get_owner_hash),
) -> schemas.MessageResponseDTO:
"""
Retrieves a single message by its unique ID.
@@ -115,7 +116,7 @@ async def mark_message_as_read(
message_id: int,
user_tuple: Annotated[tuple[dict, dict], Depends(get_creds_or_guest)],
service: MessageService = Depends(deps.get_message_service),
- owner_hash: str | None = Query(default=None),
+ owner_hash: str | None = Depends(get_owner_hash),
) -> schemas.MessageResponseDTO:
"""
Marks a message as read by the current user.
diff --git a/backend/modules/sgotinish/owner_hash.py b/backend/modules/sgotinish/owner_hash.py
new file mode 100644
index 00000000..74354aa8
--- /dev/null
+++ b/backend/modules/sgotinish/owner_hash.py
@@ -0,0 +1,31 @@
+"""Where an anonymous ticket's owner hash is read from.
+
+`owner_hash` is the *only* credential guarding an anonymous ticket: whoever
+holds it can read and post messages on that ticket. It was accepted solely as a
+query parameter, which writes it into every access log that records a request
+line -- nginx's default format does, verbatim -- along with any proxy, CDN or
+backup that touches those logs.
+
+That undoes what the anonymity design is for. Ticket rows deliberately store no
+`author_sub`, and then the key to the ticket was being copied into plaintext
+logs on every poll for new messages.
+
+Reading it from a header instead keeps it out of request lines and out of
+`Referer`. The query parameter still works so the existing frontend and any
+anonymous link already in circulation keep functioning; the header takes
+precedence, and new clients should send only the header.
+"""
+
+from typing import Annotated
+
+from fastapi import Header, Query
+
+OWNER_HASH_HEADER = "X-Owner-Hash"
+
+
+async def get_owner_hash(
+ x_owner_hash: Annotated[str | None, Header(alias=OWNER_HASH_HEADER)] = None,
+ owner_hash: Annotated[str | None, Query()] = None,
+) -> str | None:
+ """The anonymous owner hash, preferring the header over the query string."""
+ return x_owner_hash or owner_hash
diff --git a/backend/scripts/__init__.py b/backend/scripts/__init__.py
new file mode 100644
index 00000000..663a0e6c
--- /dev/null
+++ b/backend/scripts/__init__.py
@@ -0,0 +1 @@
+"""Developer and CI entry points."""
diff --git a/backend/scripts/export_openapi.py b/backend/scripts/export_openapi.py
new file mode 100644
index 00000000..00f6ff23
--- /dev/null
+++ b/backend/scripts/export_openapi.py
@@ -0,0 +1,55 @@
+import argparse
+import json
+import sys
+from pathlib import Path
+
+from dotenv import load_dotenv
+
+REPOSITORY_ROOT = Path(__file__).resolve().parents[2]
+DEFAULT_ENV_FILE = REPOSITORY_ROOT / "infra" / ".env.example"
+
+
+def parse_args() -> argparse.Namespace:
+ parser = argparse.ArgumentParser(
+ description="Export the FastAPI contract without starting external services."
+ )
+ parser.add_argument(
+ "--env-file",
+ type=Path,
+ default=DEFAULT_ENV_FILE,
+ help="Dummy configuration fixture loaded before importing the app.",
+ )
+ parser.add_argument(
+ "--output",
+ type=Path,
+ help="Write JSON here instead of stdout.",
+ )
+ return parser.parse_args()
+
+
+def main() -> None:
+ args = parse_args()
+ load_dotenv(args.env_file, override=False)
+ sys.path.insert(0, str(REPOSITORY_ROOT))
+
+ # Config is instantiated while importing the app, so the fixture must be
+ # loaded first. Importing does not run FastAPI lifespan.
+ from backend.main import app
+
+ schema = app.openapi()
+ if not schema.get("paths"):
+ raise RuntimeError("OpenAPI export has no paths; routers were not registered.")
+
+ # FastAPI's insertion order follows router registration and is stable.
+ # Preserve it so codegen diffs reflect contract changes instead of sorting
+ # thousands of generated declarations alphabetically.
+ document = json.dumps(schema, ensure_ascii=False, indent=2) + "\n"
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(document, encoding="utf-8")
+ return
+ sys.stdout.write(document)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/docs/web-parity-uat.md b/docs/web-parity-uat.md
new file mode 100644
index 00000000..1a1f05f7
--- /dev/null
+++ b/docs/web-parity-uat.md
@@ -0,0 +1,176 @@
+# `web/` parity release checklist
+
+This is the required human acceptance gate for the first production release of
+`web/`. Automated checks protect the implementation; they do not prove that a
+real user can complete every legacy workflow. Every required checkbox below
+must be checked against the release candidate before merge.
+
+Do not delete `frontend/` as part of this release. It remains the rollback
+fallback for one production release. Capacitor is intentionally outside the
+`web/` parity scope.
+
+## Release candidate
+
+- Commit SHA:
+- Environment and URL:
+- Tester:
+- Date:
+- Browser and version:
+- Desktop viewport:
+- Mobile device or viewport:
+- CI run:
+- Failed checks/issues (write `none`, or link each issue):
+
+## Automated gate
+
+- [ ] `pnpm format:check`
+- [ ] `pnpm lint`
+- [ ] `pnpm test`
+- [ ] `pnpm typecheck`
+- [ ] `pnpm build`
+- [ ] `pnpm api:check`
+- [ ] Backend tests and OpenAPI export passed in CI
+- [ ] No required UAT item below is blocked, skipped, or failing
+
+## Discovery and profile
+
+Use `alice` for administration, `bob` for opportunity authoring, and `hassan`
+for an ordinary student.
+
+- [ ] Events can be searched and filtered by type and time period; clearing
+ filters restores the unfiltered list and a copied filtered URL reloads
+ with the same controls.
+- [ ] Communities can be searched and filtered by type and category; clearing
+ and URL reload behave as above.
+- [ ] Opportunities can be searched and filtered by type, education level,
+ year, major, and active-only; eligibility labels match the selected
+ levels/years.
+- [ ] `bob` can create and edit an opportunity, and adding it to Google
+ Calendar either succeeds or shows the expected reauthentication path.
+- [ ] An event detail can be shared, copied, and opened in Google Calendar with
+ the correct title, time, location, and description.
+- [ ] Event and community create/edit flows work with no image, one valid
+ image, invalid/oversized selection, all uploads failing, and a partially
+ failing upload batch; retry never creates a duplicate entity.
+- [ ] A Telegram-linked user does not see the connection prompt; an unlinked
+ user can follow it; dismissing it persists for that browser.
+- [ ] In Telegram, the community form's native main button submits exactly
+ once and is removed when the form/dialog unmounts.
+- [ ] A profile with no managed communities offers the create-community action.
+
+## Courses
+
+Use a student with registered courses and at least two published grade reports.
+
+- [ ] Registrar-password sync and PDF sync both refresh registered courses and
+ show actionable failures.
+- [ ] The weekly timetable orders classes, does not duplicate merged meetings,
+ and Google/ICS exports contain the visible schedule.
+- [ ] Excluding a course updates current, projected, and ceiling GPA for the
+ session; re-including it restores the figures; reload resets exclusions.
+- [ ] Sharing an assignment template exposes names and weights only—never
+ obtained/max scores—and updates the student's previous template instead
+ of duplicating it.
+- [ ] Importing a classmate's template requires confirmation and produces the
+ expected assignment rows without overwriting silently.
+- [ ] Between two and eight grade reports can be compared on desktop and
+ mobile; removal works and a ninth report is not added.
+
+## Planner
+
+- [ ] Create, rename, duplicate, switch, and delete plans; switching or
+ reloading a copied plan URL preserves the selected plan and term.
+- [ ] Add courses, load their sections, and independently select lecture/lab
+ section types; genuine clashes are visible.
+- [ ] Auto-build produces a schedule, and its Undo action restores every
+ course's exact prior section selection, including courses with none.
+- [ ] Reset names the destructive effect, can be cancelled without changes,
+ and removes the current plan's courses only after confirmation.
+- [ ] Catalog, course cards, and selected-section details show a syllabus link
+ when the shipped CSV contains that course, and omit it otherwise.
+- [ ] Term-query and plan-list failures show retryable errors; a successful
+ empty plan list does not leave permanent skeletons.
+
+## Degree audit
+
+- [ ] Registrar-password and transcript-PDF audits both run against selected
+ year/major/minor combinations and show cached results on return.
+- [ ] Each programme's “View requirements” dialog shows the published
+ requirement fields and retries a failed request.
+- [ ] Unmatched transfer courses open the mapping step; blank rows remain
+ unmatched, invalid credits are rejected, and valid NU mappings rerun the
+ same audit.
+- [ ] A rerun that still has unmatched courses can be mapped again.
+- [ ] Password/PDF audit input is cleared after success without unmatched
+ courses, skip, dialog close, mode switch, request failure, and route
+ unmount; it never appears in browser storage or logs.
+
+## SGotinish
+
+Use `hassan` as a student, `charlie` as Head, `dana` as Executive, and `erik`
+as Member.
+
+- [ ] Student tickets filter by category and status and retain those filters in
+ a copied URL.
+- [ ] Normal and anonymous ticket creation both work; an anonymous WarpKey is
+ kept in the URL fragment and is not stored by the browser application.
+- [ ] Head, Executive, and Member cabinets expose only their permitted actions;
+ category/status filtering works without changing authorization.
+- [ ] Assignment, delegation, withdrawal, conversation, and completion flows
+ work for their allowed roles, including confirmation and error states.
+- [ ] Telegram-linked/unlinked prompt behavior matches the discovery pages.
+
+## Sign-off and rollback
+
+- Product sign-off:
+- Engineering sign-off:
+- Known non-blocking differences:
+ - `web/` remains the only shipped application. `frontend/` is retained
+ unchanged for the soak-release rollback described below.
+ - The landing page does not repeat the unverified “3100+ students” claim or
+ the legacy joke footer. It keeps the public Nuspace header, legal links,
+ and student-project attribution.
+ - The desktop sidebar returns as a collapsible navigation rail, while mobile
+ keeps the sticky header and sheet. The unused legacy bottom navigation is
+ intentionally not restored.
+ - Discovery pages retain compact, URL-filtered lists and the current
+ permission-aware authoring flows; legacy infinite-list and state-only tab
+ implementations are not carried over.
+ - Course comparison supports up to eight reports, not the legacy limit of
+ four. Planner scheduling retains overlap lanes, demand calculations,
+ section-type grouping, exact undo state, and retryable failures.
+ - Degree Audit keeps the current credential lifecycle, transfer mapping, and
+ cached-result behavior. About keeps team and help content directly visible
+ instead of putting static information in legacy modals.
+ - Disabled elections, Dorm Eats, animation wrappers, raw palette styling,
+ injected style tags, and obsolete API hooks remain outside parity scope.
+
+### Rollback procedure
+
+Rolling back to `frontend/` is a revert-and-rebuild, not a traffic switch, and
+it costs a full deploy cycle. Two things make it slower than it sounds:
+
+- The VM keeps no previous build. `ansible/roles/frontend/tasks/main.yml` wipes
+ `web/out/*` before unpacking, so there is no known-good artifact sitting on
+ the host to re-serve.
+- Nothing routes between the two apps. Prod nginx bind-mounts `../web/out`
+ directly, so serving `frontend/` again requires changing that mount, not a
+ config flag.
+
+If a required item fails after deployment, stop the rollout and open a revert PR
+touching these three files together — reverting any subset leaves the deploy
+inconsistent:
+
+1. `infra/prod.docker-compose.yml` — point the nginx `/var/www/my-app/out`
+ mount back at `../frontend/out`.
+2. `ansible/roles/frontend/tasks/main.yml` — unpack into `frontend/out` instead
+ of `web/out`.
+3. `.github/workflows/deploy.yml` — build `frontend/` and pack its export as
+ the Ansible tarball.
+
+Then deploy from that branch; CI rebuilds the legacy export from source. Keep
+`frontend/`, its Compose service, and the fallback comments intact for this
+entire soak release — the revert above assumes that code is still present.
+
+Record the failure, the revert PR, and the rollback deployment in the release
+issue before resuming.
diff --git a/infra/.env.example b/infra/.env.example
index 7b8d9e7c..e03ffb47 100644
--- a/infra/.env.example
+++ b/infra/.env.example
@@ -15,9 +15,9 @@ REDIS_HOST=redis
REDIS_PORT=6379
-# Meeilisearch connection
-MEILISEARCH_URL = "http://meilisearch:7700"
-MEILISEARCH_MASTER_KEY = "secret"
+# Meilisearch connection
+MEILISEARCH_URL=http://meilisearch:7700
+MEILISEARCH_MASTER_KEY=secret
# Keycloak Client information
@@ -41,11 +41,21 @@ SESSION_MIDDLEWARE_KEY=secret
TG_WEBHOOK_SECRET_TOKEN=secret
APP_JWT_SECRET_256=secret
APP_TOKEN_EXPIRY_MINUTES=5
-GCS_EMULATOR_HOST="http://gcs:4443" # this is a container adress
-DEV_APP_URL=http://localhost # browser/OAuth origin in debug (not used for webhooks)
-MOCK_KEYCLOAK=True # true unless you are have necessary keys for services
-USE_GCS_EMULATOR=True # true unless you are have necessary keys for services
-IS_DEBUG=True # local: uvicorn --reload; prod compose sets IS_DEBUG=false (no reload, single process)
+# Browser/OAuth origin in debug (not used for webhooks)
+DEV_APP_URL=http://localhost
+# Keep these true unless you have the necessary local service credentials.
+MOCK_KEYCLOAK=True
+
+# Your own registrar username (the part of your NU email before the @), used
+# only when IS_DEBUG. Mock users have no NU email, so registrar sync and degree
+# audit cannot derive it from the session locally.
+# Leave blank to make those calls fail authentication instead of reaching a real
+# account -- never point it at someone else's username.
+REGISTRAR_DEBUG_USERNAME=
+GCS_EMULATOR_HOST=http://gcs:4443
+USE_GCS_EMULATOR=True
+# Local: uvicorn --reload; prod compose sets false (no reload, single process).
+IS_DEBUG=True
INTEGRATION_SECRET=secret
# Gemini (/post event extraction)
@@ -85,4 +95,4 @@ VM_SERVICE_ACCOUNT_EMAIL=admin@admin
#Qualtrics credentials
QUALTRICS_API_TOKEN=secret
QUALTRICS_DATA_CENTER_ID=secret
-QUALTRICS_SURVEY_ID=secret
\ No newline at end of file
+QUALTRICS_SURVEY_ID=secret
diff --git a/infra/docker-compose.yml b/infra/docker-compose.yml
index 6427b503..fbc75dd0 100644
--- a/infra/docker-compose.yml
+++ b/infra/docker-compose.yml
@@ -41,7 +41,9 @@ services:
- nuros
restart: always
ports:
- - "80:80" # Expose Nginx on port 80 of localhost
+ # :80 now serves web/. The old frontend/ service is still defined below
+ # for one release, but nothing routes to it — see infra/nginx/nginx.dev.conf.
+ - "80:80"
volumes:
- ./nginx/nginx.dev.conf:/etc/nginx/nginx.conf
- ../frontend/dist:/var/www/my-app/dist # Make sure this folder exists in production builds
@@ -157,6 +159,23 @@ services:
depends_on:
- cloudflared
+ # The app. Served at http://localhost since the cutover; `frontend` below is
+ # the previous one, kept for one release as a fallback and not routed to.
+ web:
+ build:
+ context: ..
+ dockerfile: web/Dockerfile.dev
+ restart: always
+ volumes:
+ - ../web:/app # Mount source for HMR
+ - /app/node_modules # Anonymous volume keeps the image's deps
+ environment:
+ # The bind mount makes pnpm's deps-status check want to purge
+ # node_modules, which it refuses to do without a TTY.
+ - CI=true
+ networks:
+ - nuros
+
loki:
container_name: loki
image: grafana/loki:latest
diff --git a/infra/nginx/nginx.dev.conf b/infra/nginx/nginx.dev.conf
index 45560bb8..a27c4765 100644
--- a/infra/nginx/nginx.dev.conf
+++ b/infra/nginx/nginx.dev.conf
@@ -27,9 +27,13 @@ http {
"~*discordbot" 1;
}
- # Route bots to OG endpoint while preserving the request path
+ # Route bots to the OG endpoint while preserving the request path, and
+ # everyone else to the app. `web` is the rebuilt frontend: at the cutover
+ # it took over :80, and the old `frontend` service is still defined in the
+ # compose file but no longer routed to. Point this back at frontend:5173 to
+ # fall back to it without redeploying anything.
map $is_bot $proxy_upstream {
- 0 http://frontend:5173;
+ 0 http://web:5173;
1 http://fastapi:8000;
}
@@ -102,4 +106,5 @@ http {
}
+
}
diff --git a/infra/prod.docker-compose.yml b/infra/prod.docker-compose.yml
index 30f9ce59..16382de3 100644
--- a/infra/prod.docker-compose.yml
+++ b/infra/prod.docker-compose.yml
@@ -113,7 +113,7 @@ services:
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- - ../frontend/out:/var/www/my-app/out
+ - ../web/out:/var/www/my-app/out
- ../ssl/cloudflare.crt:/etc/ssl/cloudflare/origin.crt
- ../ssl/cloudflare.key:/etc/ssl/cloudflare/origin.key
- ./nginx/vpn-index.html:/etc/nginx/vpn-index.html:ro
diff --git a/web/.gitignore b/web/.gitignore
new file mode 100644
index 00000000..4bd514db
--- /dev/null
+++ b/web/.gitignore
@@ -0,0 +1,30 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+# Generated from the backend OpenAPI schema
+openapi.json
+
+# pnpm store, created when the dev container installs into the bind mount
+.pnpm-store/
diff --git a/web/.oxlintrc.json b/web/.oxlintrc.json
new file mode 100644
index 00000000..f348808d
--- /dev/null
+++ b/web/.oxlintrc.json
@@ -0,0 +1,34 @@
+{
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
+ "ignorePatterns": ["dist", "src/api/schema.d.ts", "src/routeTree.gen.ts"],
+ "plugins": ["react", "typescript", "jsx-a11y", "import"],
+ "categories": {
+ "correctness": "error",
+ "suspicious": "warn"
+ },
+ "rules": {
+ "react/react-in-jsx-scope": "off",
+ "import/no-unassigned-import": "off"
+ },
+ "overrides": [
+ {
+ "files": ["src/components/ui/**"],
+ "rules": {
+ "jsx-a11y/label-has-associated-control": "off"
+ }
+ },
+ {
+ "files": ["src/**/*.test.ts"],
+ "rules": {
+ "typescript/no-floating-promises": "off"
+ }
+ },
+ {
+ "files": ["src/components/markdown.tsx"],
+ "rules": {
+ "jsx-a11y/anchor-has-content": "off",
+ "jsx-a11y/heading-has-content": "off"
+ }
+ }
+ ]
+}
diff --git a/web/.prettierignore b/web/.prettierignore
new file mode 100644
index 00000000..81207d82
--- /dev/null
+++ b/web/.prettierignore
@@ -0,0 +1,10 @@
+node_modules/
+coverage/
+.pnpm-store/
+pnpm-lock.yaml
+package-lock.json
+pnpm-lock.yaml
+yarn.lock
+src/routeTree.gen.ts
+src/api/schema.d.ts
+out/
diff --git a/web/.prettierrc b/web/.prettierrc
new file mode 100644
index 00000000..9000bfaa
--- /dev/null
+++ b/web/.prettierrc
@@ -0,0 +1,11 @@
+{
+ "endOfLine": "lf",
+ "semi": false,
+ "singleQuote": false,
+ "tabWidth": 2,
+ "trailingComma": "es5",
+ "printWidth": 80,
+ "plugins": ["prettier-plugin-tailwindcss"],
+ "tailwindStylesheet": "src/index.css",
+ "tailwindFunctions": ["cn", "cva"]
+}
diff --git a/web/Dockerfile.dev b/web/Dockerfile.dev
new file mode 100644
index 00000000..b0c18080
--- /dev/null
+++ b/web/Dockerfile.dev
@@ -0,0 +1,26 @@
+# Dev container for the new frontend (web/). Mirrors frontend/Dockerfile_next
+# but uses pnpm via corepack instead of npm.
+FROM node:24-alpine
+
+RUN apk add --no-cache bash curl git
+RUN corepack enable
+
+# Keep the content-addressable store outside /app. The source directory is
+# bind-mounted from the host, so a store under it would write ~300MB of package
+# files straight into the working tree.
+ENV npm_config_store_dir=/pnpm-store
+
+WORKDIR /app
+
+# Cache the dependency layer separately from source.
+COPY web/package.json web/pnpm-lock.yaml web/pnpm-workspace.yaml ./
+RUN pnpm install --frozen-lockfile
+
+COPY web .
+
+# Reach the backend by its compose service name rather than through nginx.
+ENV VITE_API_PROXY_TARGET=http://fastapi:8000
+
+EXPOSE 5173
+
+CMD ["pnpm", "dev"]
diff --git a/web/README.md b/web/README.md
new file mode 100644
index 00000000..3f25cd63
--- /dev/null
+++ b/web/README.md
@@ -0,0 +1,181 @@
+# web
+
+The Nuspace frontend. Serves `http://localhost` in development and everything
+CI deploys to production.
+
+The previous app in `frontend/` is still in the repository for one release as a
+fallback and is no longer routed to or built. Deleting it is a follow-up.
+
+**Stack:** Vite 8 · React 19 · TypeScript 7 · TanStack Router (file-based) ·
+TanStack Query · Tailwind v4 · shadcn/ui on Base UI.
+
+## Running it
+
+The app needs the backend, so bring up the stack rather than running `pnpm dev`
+standalone:
+
+```sh
+cd ../infra
+cp .env.example .env # fill TELEGRAM_BOT_TOKEN
+docker compose up --build
+```
+
+| | |
+| ----------------------- | -------- |
+| `http://localhost` | this app |
+| `http://localhost:8080` | pgAdmin |
+
+To compare against the old app, point `$proxy_upstream` in
+`infra/nginx/nginx.dev.conf` back at `frontend:5173` and reload nginx.
+
+To run outside Docker, `pnpm dev` serves on 5173 and proxies `/api` to
+`http://localhost` (override with `VITE_API_PROXY_TARGET`).
+
+### HMR can go stale — check before you trust what you see
+
+This repo runs under **Docker Desktop on Linux**, which shares the host
+filesystem into a VM. That layer desynchronizes: new files appear, but files
+edited **in place** can keep serving old content to the container for hours.
+Vite never fires, because from inside the container nothing changed.
+
+The failure is quiet and it will waste your time — the page looks fine, it is
+just not your code. A route returning 200 proves nothing either, since the dev
+server serves the same `index.html` for every path.
+
+Confirm the container actually sees an edit:
+
+```sh
+docker compose exec web grep -c somethingYouJustTyped /app/src/path/to/file.tsx
+```
+
+`docker compose restart web` resyncs the mount. The permanent fix is to run the
+stack on the native Docker daemon (`docker context use default`) instead of the
+Docker Desktop VM, which uses real bind mounts and has no such layer.
+
+### Signing in locally
+
+`MOCK_KEYCLOAK=true` is the default, so no real credentials are needed:
+
+```
+http://localhost/api/login?mock_user=alice
+```
+
+`mock_user` accepts a number, an email, a sub or a first name. The people
+`backend/fixtures/dev/seed_campus.sql` sets up cover every role worth testing:
+
+| `mock_user` | role |
+| ----------- | ------------------------------------------- |
+| `alice` | admin |
+| `bob` | student, and on the opportunities allowlist |
+| `charlie` | Head (`boss`) |
+| `dana` | Executive (`capo`) |
+| `erik` | Member (`soldier`) |
+| `hassan` | student, no special access |
+
+## Commands
+
+```sh
+pnpm dev # dev server
+pnpm build # typecheck + production build
+pnpm typecheck # tsc -b --noEmit over the project references
+pnpm lint # oxlint, including type-aware rules
+pnpm format # prettier, sorts Tailwind classes
+pnpm test # node --test over src/**/*.test.ts
+pnpm api:generate # regenerate src/api/schema.d.ts from the backend
+pnpm api:check # fail if the committed schema is stale
+```
+
+## API types are generated, not written
+
+`src/api/schema.d.ts` is generated from the backend's OpenAPI document and
+committed. Nothing about a request or response is typed by hand, so a backend
+change that breaks the contract fails `tsc` instead of surfacing at runtime.
+
+Regenerate from an offline backend export:
+
+```sh
+cd ../backend
+uv run python scripts/export_openapi.py --output /tmp/nuspace-openapi.json
+cd ../web
+OPENAPI_URL=/tmp/nuspace-openapi.json pnpm api:generate
+```
+
+`pnpm api:check` runs the same generation and fails on any diff, so drift is
+caught in CI. The exporter loads `infra/.env.example` as a dummy configuration
+fixture and constructs the schema without starting Postgres, Redis,
+Meilisearch, RabbitMQ, GCS, or the bot.
+
+The generator runs in an isolated environment pinned to TypeScript 6.
+`openapi-typescript` emits through the compiler's `ts.factory` AST API, which
+TypeScript 7 does not expose. Its output is plain text, so the version that
+produced it does not matter.
+
+**The one exception is `/me`.** The backend declares it `user: Dict[str, Any]`,
+so OpenAPI reports an opaque index signature and codegen cannot describe it.
+`src/features/auth/schema.ts` parses it with zod, reusing the generated
+`UserRole` union so a backend role change still breaks the build. That file is
+the only place a payload shape is written by hand — everywhere else, use the
+generated types.
+
+## Media uploads
+
+Bytes never pass through our API. `useMediaUpload()` (in `src/features/media/`)
+runs the three-step presigned flow: ask the backend to sign one PUT per file,
+send the bytes straight at the returned URL, and let the bucket tell the backend
+what landed. The `x-goog-meta-*` headers are part of the signature and are
+replayed exactly as issued — re-deriving `Content-Type` from the `File` is
+enough for GCS to answer 403.
+
+Two things about step three are easy to get wrong:
+
+- **Locally the Media row already exists before the bytes do.** With
+ `USE_GCS_EMULATOR=true` there is no Pub/Sub, so the backend creates the row
+ while signing, and the upload URL points at its own `/bucket/local-upload`
+ proxy. In production the row appears only after GCS notifies
+ `POST /bucket/gcs-hook`, which happens _after_ the PUT resolves. A refetch
+ immediately on success can legitimately come back without the new image, and
+ only production will show you that.
+- **Formats are not interchangeable, and the backend filters on them.** Events
+ return `carousel` only; communities return `profile` and `banner`. Asking an
+ entity for a format it never carries renders nothing, with no error — the
+ generated types cannot catch it, because the value is valid either way. Go
+ through `selectMedia()` in `src/features/media/select.ts`, where that mapping
+ is written down.
+
+## Conventions
+
+- **One QueryClient**, exported from `src/app/query-client.ts` and passed to
+ both `QueryClientProvider` and the router context. Never construct another.
+- **Auth is a route concern.** `routes/_app.tsx` guards everything beneath it in
+ `beforeLoad`. Pages assume a signed-in user via `useCurrentUser()`.
+- **Permissions go through `usePermissions()`**, not inline role checks.
+- **Datetimes cross the boundary in `lib/datetime.ts`.** The backend reads a
+ naive datetime as Almaty local time; that conversion lives in one file.
+- **Query keys come from `src/api/query-keys.ts`**, so invalidation can target a
+ whole subtree.
+- **Loading, error and empty states** go through `components/query-boundary.tsx`.
+- **Use the design tokens** (`bg-muted`, `text-foreground`, `border-border`),
+ not raw palette classes like `bg-gray-100`. The tokens already handle dark
+ mode; palette classes need a hand-written `dark:` variant for every use and
+ drift out of sync.
+- **Never build a Tailwind class by interpolation** (`` `grid-cols-${n}` ``).
+ The scanner cannot see it and the class is silently dropped from the
+ stylesheet.
+
+## Tests
+
+`node --test`, no test framework. Node 22+ strips TypeScript natively, so a
+`.test.ts` file next to the module it covers runs with no build step and no
+dependency. `tsconfig.test.json` gives those files Node's types; the app project
+excludes them so app code cannot reach for `node:` builtins by accident.
+
+There is one suite, on `features/communities/url-validation.ts`, ported from the
+old app along with the module. It is the interesting kind of test: `new URL`
+accepts `https://wtf://t.me/x` and reports `wtf:` as the host, so a naive
+protocol check passes something that goes nowhere near Telegram.
+
+## Linting
+
+Oxlint, not ESLint. typescript-eslint refuses to load under TypeScript 7 and
+has no supporting release yet, while oxlint parses with its own Rust parser and
+its type-aware mode tracks TS 7 via `oxlint-tsgolint`.
diff --git a/web/components.json b/web/components.json
new file mode 100644
index 00000000..15addee8
--- /dev/null
+++ b/web/components.json
@@ -0,0 +1,25 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "base-nova",
+ "rsc": false,
+ "tsx": true,
+ "tailwind": {
+ "config": "",
+ "css": "src/index.css",
+ "baseColor": "neutral",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "iconLibrary": "lucide",
+ "rtl": false,
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ },
+ "menuColor": "default",
+ "menuAccent": "subtle",
+ "registries": {}
+}
diff --git a/web/index.html b/web/index.html
new file mode 100644
index 00000000..b3435a9c
--- /dev/null
+++ b/web/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ Nuspace
+
+
+
+
+
+
diff --git a/web/package.json b/web/package.json
new file mode 100644
index 00000000..e07d9e23
--- /dev/null
+++ b/web/package.json
@@ -0,0 +1,58 @@
+{
+ "name": "web",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "packageManager": "pnpm@11.15.0",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "lint": "oxlint --type-aware",
+ "format": "prettier --write \"**/*.{ts,tsx,css,json,md}\"",
+ "format:check": "prettier --check \"**/*.{ts,tsx,css,json,md}\"",
+ "typecheck": "tsc -b --noEmit",
+ "test": "node --test \"src/**/*.test.ts\"",
+ "preview": "vite preview",
+ "api:generate": "node scripts/generate-api-types.mjs",
+ "api:check": "node scripts/generate-api-types.mjs --check",
+ "lint:fix": "oxlint --type-aware --fix"
+ },
+ "dependencies": {
+ "@base-ui/react": "^1.6.0",
+ "@fontsource-variable/onest": "^5.3.0",
+ "@hookform/resolvers": "^5.4.0",
+ "@tailwindcss/vite": "^4",
+ "@tanstack/react-query": "^5.101.4",
+ "@tanstack/react-router": "^1.170.18",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "lucide-react": "^1.26.0",
+ "openapi-fetch": "^0.17.0",
+ "react": "^19.2.6",
+ "react-dom": "^19.2.6",
+ "react-hook-form": "^7.82.0",
+ "react-markdown": "^10.1.0",
+ "remark-gfm": "^4.0.1",
+ "shadcn": "^4.14.1",
+ "sonner": "^2.0.7",
+ "tailwind-merge": "^3.6.0",
+ "tailwindcss": "^4",
+ "tw-animate-css": "^1.4.0",
+ "zod": "^4.4.3"
+ },
+ "devDependencies": {
+ "@tanstack/react-query-devtools": "^5.101.4",
+ "@tanstack/react-router-devtools": "^1.167.0",
+ "@tanstack/router-plugin": "^1.168.23",
+ "@types/node": "^24",
+ "@types/react": "^19",
+ "@types/react-dom": "^19",
+ "@vitejs/plugin-react": "^6",
+ "oxlint": "^1.75.0",
+ "oxlint-tsgolint": "^7.0.2001",
+ "prettier": "^3.8.3",
+ "prettier-plugin-tailwindcss": "^0.8.0",
+ "typescript": "~7.0.2",
+ "vite": "^8"
+ }
+}
diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml
new file mode 100644
index 00000000..b9000e0a
--- /dev/null
+++ b/web/pnpm-lock.yaml
@@ -0,0 +1,5374 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@base-ui/react':
+ specifier: ^1.6.0
+ version: 1.6.0(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ '@fontsource-variable/onest':
+ specifier: ^5.3.0
+ version: 5.3.0
+ '@hookform/resolvers':
+ specifier: ^5.4.0
+ version: 5.4.0(react-hook-form@7.82.0(react@19.2.8))
+ '@tailwindcss/vite':
+ specifier: ^4
+ version: 4.3.3(vite@8.1.5(@types/node@24.13.3)(jiti@2.7.0))
+ '@tanstack/react-query':
+ specifier: ^5.101.4
+ version: 5.101.4(react@19.2.8)
+ '@tanstack/react-router':
+ specifier: ^1.170.18
+ version: 1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ class-variance-authority:
+ specifier: ^0.7.1
+ version: 0.7.1
+ clsx:
+ specifier: ^2.1.1
+ version: 2.1.1
+ lucide-react:
+ specifier: ^1.26.0
+ version: 1.26.0(react@19.2.8)
+ openapi-fetch:
+ specifier: ^0.17.0
+ version: 0.17.0
+ react:
+ specifier: ^19.2.6
+ version: 19.2.8
+ react-dom:
+ specifier: ^19.2.6
+ version: 19.2.8(react@19.2.8)
+ react-hook-form:
+ specifier: ^7.82.0
+ version: 7.82.0(react@19.2.8)
+ react-markdown:
+ specifier: ^10.1.0
+ version: 10.1.0(@types/react@19.2.17)(react@19.2.8)(supports-color@10.2.2)
+ remark-gfm:
+ specifier: ^4.0.1
+ version: 4.0.1(supports-color@10.2.2)
+ shadcn:
+ specifier: ^4.14.1
+ version: 4.14.1(supports-color@10.2.2)(typescript@7.0.2)
+ sonner:
+ specifier: ^2.0.7
+ version: 2.0.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ tailwind-merge:
+ specifier: ^3.6.0
+ version: 3.6.0
+ tailwindcss:
+ specifier: ^4
+ version: 4.3.3
+ tw-animate-css:
+ specifier: ^1.4.0
+ version: 1.4.0
+ zod:
+ specifier: ^4.4.3
+ version: 4.4.3
+ devDependencies:
+ '@tanstack/react-query-devtools':
+ specifier: ^5.101.4
+ version: 5.101.4(@tanstack/react-query@5.101.4(react@19.2.8))(react@19.2.8)
+ '@tanstack/react-router-devtools':
+ specifier: ^1.167.0
+ version: 1.167.0(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@tanstack/router-core@1.171.15)(csstype@3.2.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ '@tanstack/router-plugin':
+ specifier: ^1.168.23
+ version: 1.168.23(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(rolldown@1.1.5)(supports-color@10.2.2)(vite@8.1.5(@types/node@24.13.3)(jiti@2.7.0))
+ '@types/node':
+ specifier: ^24
+ version: 24.13.3
+ '@types/react':
+ specifier: ^19
+ version: 19.2.17
+ '@types/react-dom':
+ specifier: ^19
+ version: 19.2.3(@types/react@19.2.17)
+ '@vitejs/plugin-react':
+ specifier: ^6
+ version: 6.0.4(vite@8.1.5(@types/node@24.13.3)(jiti@2.7.0))
+ oxlint:
+ specifier: ^1.75.0
+ version: 1.75.0(oxlint-tsgolint@7.0.2001)
+ oxlint-tsgolint:
+ specifier: ^7.0.2001
+ version: 7.0.2001
+ prettier:
+ specifier: ^3.8.3
+ version: 3.9.6
+ prettier-plugin-tailwindcss:
+ specifier: ^0.8.0
+ version: 0.8.1(prettier@3.9.6)
+ typescript:
+ specifier: ~7.0.2
+ version: 7.0.2
+ vite:
+ specifier: ^8
+ version: 8.1.5(@types/node@24.13.3)(jiti@2.7.0)
+
+packages:
+
+ '@babel/code-frame@7.29.7':
+ resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.29.7':
+ resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.29.7':
+ resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.29.7':
+ resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-annotate-as-pure@7.29.7':
+ resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.29.7':
+ resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-create-class-features-plugin@7.29.7':
+ resolution: {integrity: sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-globals@7.29.7':
+ resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-member-expression-to-functions@7.29.7':
+ resolution: {integrity: sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.29.7':
+ resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.29.7':
+ resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-optimise-call-expression@7.29.7':
+ resolution: {integrity: sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-plugin-utils@7.29.7':
+ resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-replace-supers@7.29.7':
+ resolution: {integrity: sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-skip-transparent-expression-wrappers@7.29.7':
+ resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-string-parser@7.29.7':
+ resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.29.7':
+ resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.29.7':
+ resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.29.7':
+ resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.29.7':
+ resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/plugin-syntax-jsx@7.29.7':
+ resolution: {integrity: sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-typescript@7.29.7':
+ resolution: {integrity: sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-modules-commonjs@7.29.7':
+ resolution: {integrity: sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-typescript@7.29.7':
+ resolution: {integrity: sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/preset-typescript@7.29.7':
+ resolution: {integrity: sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/runtime@7.29.7':
+ resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/template@7.29.7':
+ resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.29.7':
+ resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.29.7':
+ resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==}
+ engines: {node: '>=6.9.0'}
+
+ '@base-ui/react@1.6.0':
+ resolution: {integrity: sha512-/jzjTWJYXhRFO45Bev9lc3cHbmjzCMpUqbMZ2AgKy/z25mY9B6shGSNcXcjQar9n5doM0KYW1W8fcFv2jZBuMw==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ '@date-fns/tz': ^1.2.0
+ '@types/react': ^17 || ^18 || ^19
+ date-fns: ^4.0.0
+ react: ^17 || ^18 || ^19
+ react-dom: ^17 || ^18 || ^19
+ peerDependenciesMeta:
+ '@date-fns/tz':
+ optional: true
+ '@types/react':
+ optional: true
+ date-fns:
+ optional: true
+
+ '@base-ui/utils@0.3.1':
+ resolution: {integrity: sha512-gFFiltORVmW/N6IILTGxizP3PBpVpysqML1ALY5Vk0mH+7faVkCknOU31goYHN5Aoek2dkjxva1XOD2Ce9WuIg==}
+ peerDependencies:
+ '@types/react': ^17 || ^18 || ^19
+ react: ^17 || ^18 || ^19
+ react-dom: ^17 || ^18 || ^19
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@dotenvx/dotenvx@1.75.1':
+ resolution: {integrity: sha512-/BITOC9dmS/edY2zQwZNicQ059O6RKabtQfyEafV0nGtfYRNHYy1DIPiYVcov40+tob9hfmBnbR963dS+EQ1DQ==}
+ hasBin: true
+
+ '@dotenvx/primitives@0.8.0':
+ resolution: {integrity: sha512-VYJy0uhFm9zTJ1TxBaW/pA8bjbOM/OttaNMwZ1RHG4JKyRG7DhSdiqD1ipQoAyoD22olUtxbP78W9xY3Wd11bg==}
+
+ '@emnapi/core@1.11.1':
+ resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==}
+
+ '@emnapi/runtime@1.11.1':
+ resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==}
+
+ '@emnapi/wasi-threads@1.2.2':
+ resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==}
+
+ '@floating-ui/core@1.8.0':
+ resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==}
+
+ '@floating-ui/dom@1.8.0':
+ resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==}
+
+ '@floating-ui/react-dom@2.1.9':
+ resolution: {integrity: sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==}
+ peerDependencies:
+ react: '>=16.8.0'
+ react-dom: '>=16.8.0'
+
+ '@floating-ui/utils@0.2.12':
+ resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==}
+
+ '@fontsource-variable/onest@5.3.0':
+ resolution: {integrity: sha512-K4Es0F3M+iFnVY5mfunimhPSk1Uvl3eyovQVWjtf8oS00a7WSrSg2BD5Bh/pAcAZUe4ocV4M08dg5tvCULBJ7Q==}
+
+ '@hono/node-server@1.19.15':
+ resolution: {integrity: sha512-Za2ai6TLdKjUvnur+eenO6nuYYipVAEhyCAdaV8IRvmU9kK8crOZUSYvIXn72E4f8fJqyAbpcJuTsYYmZp9Deg==}
+ engines: {node: '>=18.14.1'}
+ peerDependencies:
+ hono: ^4
+
+ '@hookform/resolvers@5.4.0':
+ resolution: {integrity: sha512-EIsqr/t/qbinPIhGjMdtvutIN1Kk4uwbROE9/UQ93CAVGR7GkA7Y92+fX80OzXi/OB67jVFYwKGO1WzkxmkFZw==}
+ peerDependencies:
+ react-hook-form: ^7.55.0
+
+ '@jridgewell/gen-mapping@0.3.13':
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+ '@modelcontextprotocol/sdk@1.29.0':
+ resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@cfworker/json-schema': ^4.1.1
+ zod: ^3.25 || ^4.0
+ peerDependenciesMeta:
+ '@cfworker/json-schema':
+ optional: true
+
+ '@napi-rs/wasm-runtime@1.1.6':
+ resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==}
+ peerDependencies:
+ '@emnapi/core': ^1.7.1
+ '@emnapi/runtime': ^1.7.1
+
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
+ '@oxc-project/types@0.139.0':
+ resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==}
+
+ '@oxlint-tsgolint/darwin-arm64@7.0.2001':
+ resolution: {integrity: sha512-CUJEdbSZ54+Xy9OXqOhWLTKZKV0BBiV7C2i/ygyVmXtkUNXx5YCzN8DpSSshTAKktoL7S+tnQ/ftFG/i7X896w==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@oxlint-tsgolint/darwin-x64@7.0.2001':
+ resolution: {integrity: sha512-pXfBb5BqONCcgrXQNUZWXgiYmRSWJzd97S8i41VVOh6ut0tyo+cJ5FKFpczDHxiVNfj/3e7c9B4MtztNdpIVCw==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@oxlint-tsgolint/linux-arm64@7.0.2001':
+ resolution: {integrity: sha512-roP7zujb/QDPzDwEKsFFpzNHHy91/Y7oX9vQXk78ekyZtcQj1QXDIMH33gjDdHBfRl4K9pZ36xhRgrP4Zr+R8A==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@oxlint-tsgolint/linux-x64@7.0.2001':
+ resolution: {integrity: sha512-UDezNqdECVmngu2TPnjaS1YoAmcTaBoI5lV9vk3VahBxoi+I5r9k3iJTT7qZoYWOXTD/7T7bNcwRgrocR6BscQ==}
+ cpu: [x64]
+ os: [linux]
+
+ '@oxlint-tsgolint/win32-arm64@7.0.2001':
+ resolution: {integrity: sha512-uJZhqB6pdXLuN+AD1F5082byyQti/NPmJA77GtcFlmT2HzRelqbNls3SaIqxpjdFgvSBF9g0yOKGBkGFg7kX8Q==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@oxlint-tsgolint/win32-x64@7.0.2001':
+ resolution: {integrity: sha512-FkDRm8hx9OwzGQqyWG1tO5QrTLRApff9DzSgpz9QZau37BR8d1VYKOxMLGf6shPZntJFoTwIIJYT68VndYDCog==}
+ cpu: [x64]
+ os: [win32]
+
+ '@oxlint/binding-android-arm-eabi@1.75.0':
+ resolution: {integrity: sha512-lutovtFzJqlRaqpZrCqSSGaHZzl9nIxxpjLzhSRLunN6dCLylj0uzlCyQGaQDIys7rrv8kVXiFO+R4Zpn0bX7g==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [android]
+
+ '@oxlint/binding-android-arm64@1.75.0':
+ resolution: {integrity: sha512-hXI0hDgHkw4w5nfru72aG7y+2iQJmC4waH/KV6H/hbgA6yAP5jYNx0P9yug15Hs0tWl/+mda3Jjn/2gmDT48tw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [android]
+
+ '@oxlint/binding-darwin-arm64@1.75.0':
+ resolution: {integrity: sha512-D91BWbK/dMYfCcrghspPIuKs2D9LF4Z/OabVSQjw1AO6PWxArD7teDA48bm0ySFqWDaPVqmQRl5GMWNglTXyrQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@oxlint/binding-darwin-x64@1.75.0':
+ resolution: {integrity: sha512-02mpwzf12BonZ6PT0TuQoomvEh2kVl2WGBIKWezCyToIS+rYkQZ6GXnARBAl9A4Ovm2V+Xe7M4KretyqmmcnJQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [darwin]
+
+ '@oxlint/binding-freebsd-x64@1.75.0':
+ resolution: {integrity: sha512-qZJgLnDaBsiL5YESx2t/TZ8eXkL9fEkKoXEdzegROhlz9A0lgyGnZ0dAzJrh7LJAHQl2K9RdRueN2s/9N7+odg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@oxlint/binding-linux-arm-gnueabihf@1.75.0':
+ resolution: {integrity: sha512-7XlaWA5BJD3XpCfrEqjEe6Zseeb14S7QGa304XfwKignRaKQ+eIj775BQ7nIslggWickl4IsPUFqJ+/gAyNHVg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@oxlint/binding-linux-arm-musleabihf@1.75.0':
+ resolution: {integrity: sha512-av6Tpv8yrcMMMOadOqENBhlsLRcGFXXwoQ0hzHhsmS9FJ4Wioy8we427GbcMe2XTxmL2e60T67H1Dyr3up+tAA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@oxlint/binding-linux-arm64-gnu@1.75.0':
+ resolution: {integrity: sha512-WcUhd8fHT5plrA14lANevl+hOl815mVI5t2hU21oFWrZKFXIVV/Sr4rWQV0NzSvzBupbMLNc5ErEA6Ehxh5jMg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxlint/binding-linux-arm64-musl@1.75.0':
+ resolution: {integrity: sha512-UWzp5wRHFe/ESO3+eEaxXsTkYTGLYjnTsi/I5neEacXSItQ6WNleapfOAeA4x2b8nyhJ4uQxqvtv9pHv8kWJtQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@oxlint/binding-linux-ppc64-gnu@1.75.0':
+ resolution: {integrity: sha512-XEVRwGMLKCUKrvhLAz4F6AIh8MJrQVdSZtAmPpRZt9tGPsUnamPOcl3dS/ZQzJnar/Ymgc//+xho0L60Emzuxg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxlint/binding-linux-riscv64-gnu@1.75.0':
+ resolution: {integrity: sha512-mAG4DUXqfLC8cTjMD2kt3jDmVzFREYtDyeLNdLdsCcBc4Zbl2EMuiFektGBilQwkNjYnMvCqJs55U+Hyb+b+jw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxlint/binding-linux-riscv64-musl@1.75.0':
+ resolution: {integrity: sha512-95hrAvriAlI+pekSomTFIn0+bawMDlDwTNVmdjsFusTHyL2JWh7TWvRNG/Lkim72uN8OiCcO9wcaC6omLP5E3w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [musl]
+
+ '@oxlint/binding-linux-s390x-gnu@1.75.0':
+ resolution: {integrity: sha512-4b6f2+FrtruAESrCqIKcrarzfrSx+wk2QNcp+RT91/Prc+pMQMAfyZ1rG1c3tFQNl8Bc616tx40uNXyxNBRPbQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxlint/binding-linux-x64-gnu@1.75.0':
+ resolution: {integrity: sha512-nshAhrUvXFUWOvqQ2soIw7HFNWvpvEV4o0cYSqPtzLiPF5gKyYTDOOTJ6Rn8g8K/iGvPIrbDA4v8+5MvnjJrrg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxlint/binding-linux-x64-musl@1.75.0':
+ resolution: {integrity: sha512-e4jNxLKnxLC6sYBQRxrI2pgIIxnmMtF8U/VwNYcjTT/CLS+spH624cYVnj07bTKwaEWT37/e025isOs6j/0xqA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@oxlint/binding-openharmony-arm64@1.75.0':
+ resolution: {integrity: sha512-hZ2lH+1qLf/DiEP9UWuQTK2JWj/BgvMB4jhIV4SmNU1wfEiYYX4TynQyAZXx0j9X4qRYizAL042SKaV+8ynh4w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@oxlint/binding-win32-arm64-msvc@1.75.0':
+ resolution: {integrity: sha512-Ilj6PNzGDS3bCU0MSJH7Msh0NhH+T/mRp2shwg+q+GHeVlPwP5LEboW96aW+3kVKFk6zYZy1Xi5pZkqZh6X8KQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@oxlint/binding-win32-ia32-msvc@1.75.0':
+ resolution: {integrity: sha512-QVit2nOEOiPhkmsrksPSkoGCdnZRNkspt8fwoYyP09te1VEbnSj4LAxua4rc8FKTmWkySVe05j8iz9GXYfF1AQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [ia32]
+ os: [win32]
+
+ '@oxlint/binding-win32-x64-msvc@1.75.0':
+ resolution: {integrity: sha512-DSxnNkBUAYARPwJtR12Ig3deWr8w0H997xP6jy33i+e0SyYJw8FKuz4+cZtpmPEhQmvlPJE3X/2vNxDmLkd/rA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [win32]
+
+ '@rolldown/binding-android-arm64@1.1.5':
+ resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [android]
+
+ '@rolldown/binding-darwin-arm64@1.1.5':
+ resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rolldown/binding-darwin-x64@1.1.5':
+ resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rolldown/binding-freebsd-x64@1.1.5':
+ resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rolldown/binding-linux-arm-gnueabihf@1.1.5':
+ resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@rolldown/binding-linux-arm64-gnu@1.1.5':
+ resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rolldown/binding-linux-arm64-musl@1.1.5':
+ resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@rolldown/binding-linux-ppc64-gnu@1.1.5':
+ resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rolldown/binding-linux-s390x-gnu@1.1.5':
+ resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@rolldown/binding-linux-x64-gnu@1.1.5':
+ resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rolldown/binding-linux-x64-musl@1.1.5':
+ resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@rolldown/binding-openharmony-arm64@1.1.5':
+ resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rolldown/binding-wasm32-wasi@1.1.5':
+ resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [wasm32]
+
+ '@rolldown/binding-win32-arm64-msvc@1.1.5':
+ resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rolldown/binding-win32-x64-msvc@1.1.5':
+ resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [win32]
+
+ '@rolldown/pluginutils@1.0.1':
+ resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
+
+ '@sec-ant/readable-stream@0.4.1':
+ resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
+
+ '@sindresorhus/merge-streams@4.0.0':
+ resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
+ engines: {node: '>=18'}
+
+ '@standard-schema/utils@0.3.0':
+ resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==}
+
+ '@tailwindcss/node@4.3.3':
+ resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==}
+
+ '@tailwindcss/oxide-android-arm64@4.3.3':
+ resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [android]
+
+ '@tailwindcss/oxide-darwin-arm64@4.3.3':
+ resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-darwin-x64@4.3.3':
+ resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-freebsd-x64@4.3.3':
+ resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
+ resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==}
+ engines: {node: '>= 20'}
+ cpu: [arm]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
+ resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.3.3':
+ resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.3.3':
+ resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@tailwindcss/oxide-linux-x64-musl@4.3.3':
+ resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@tailwindcss/oxide-wasm32-wasi@4.3.3':
+ resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+ bundledDependencies:
+ - '@napi-rs/wasm-runtime'
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ - '@tybys/wasm-util'
+ - '@emnapi/wasi-threads'
+ - tslib
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
+ resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.3.3':
+ resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [win32]
+
+ '@tailwindcss/oxide@4.3.3':
+ resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==}
+ engines: {node: '>= 20'}
+
+ '@tailwindcss/vite@4.3.3':
+ resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==}
+ peerDependencies:
+ vite: ^5.2.0 || ^6 || ^7 || ^8
+
+ '@tanstack/history@1.162.0':
+ resolution: {integrity: sha512-79pf/RkhteYZTRgcR4F9kbk84P2N8rugQJswxfIqovlbRiT3yI7eBE+5QorIrZaOKktsgzRlXh1l/du/xpl4iA==}
+ engines: {node: '>=20.19'}
+
+ '@tanstack/query-core@5.101.4':
+ resolution: {integrity: sha512-gNwcvOJcRbLWPOLG/2OBm+zM+Yv+MKsXKEOWC57USuZDEsI71hEErQsiEGx5wX9rzWWkfwM0fVSPoiIFSsxfiw==}
+
+ '@tanstack/query-devtools@5.101.4':
+ resolution: {integrity: sha512-z5IPHnDX3aUWeTWlRKLyooBQekaCAw4xRpZqPQ390RiWTDBcTynjpPT221BArw0u2+pnQMdGvPQI9YNNubBcmA==}
+
+ '@tanstack/react-query-devtools@5.101.4':
+ resolution: {integrity: sha512-VeK2gtmfj7kvRBjtxS7TKxt/6qKhn8VzabY4UiYMr7NV9CddjSRYRgeYyld+NpjAkgMV9dd+2Qdr8ah5I03NeA==}
+ peerDependencies:
+ '@tanstack/react-query': ^5.101.4
+ react: ^18 || ^19
+
+ '@tanstack/react-query@5.101.4':
+ resolution: {integrity: sha512-yRg2pfOCxIs4ZJW3XYYHU/WgtD04FHSnfHlpRT7h7pR77hwkdRG4wxbKe4aq6P0RvXUTBSQpQeadS1SUYUe+KA==}
+ peerDependencies:
+ react: ^18 || ^19
+
+ '@tanstack/react-router-devtools@1.167.0':
+ resolution: {integrity: sha512-nGw095EG7IHx0h5NtlEmzf6vcCTaFNPWdTSuDKazajhN0ct/v/TkekJ9J6KYUCeV1a8/2ZmToc58M+0rrOyn7w==}
+ engines: {node: '>=20.19'}
+ peerDependencies:
+ '@tanstack/react-router': ^1.170.0
+ '@tanstack/router-core': ^1.170.0
+ react: '>=18.0.0 || >=19.0.0'
+ react-dom: '>=18.0.0 || >=19.0.0'
+ peerDependenciesMeta:
+ '@tanstack/router-core':
+ optional: true
+
+ '@tanstack/react-router@1.170.18':
+ resolution: {integrity: sha512-wpbGYZEp/fmz1q4bn7BD8VZ+/VZ7GBqSJv5V969pU+chP8y7dquWDmKTFMohvUegb9lg12m1uPVvD6kB2wORvQ==}
+ engines: {node: '>=20.19'}
+ peerDependencies:
+ react: '>=18.0.0 || >=19.0.0'
+ react-dom: '>=18.0.0 || >=19.0.0'
+
+ '@tanstack/react-store@0.9.3':
+ resolution: {integrity: sha512-y2iHd/N9OkoQbFJLUX1T9vbc2O9tjH0pQRgTcx1/Nz4IlwLvkgpuglXUx+mXt0g5ZDFrEeDnONPqkbfxXJKwRg==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
+ '@tanstack/router-core@1.171.15':
+ resolution: {integrity: sha512-IILCDcLaItMZQ2jEmCABHY1Nhjjn5XUvwpQp3e4Nmu+vfg0BgYFuu/QASz2SwE2ZNbVMrvt8X/wxa+Gg5aErxA==}
+ engines: {node: '>=20.19'}
+
+ '@tanstack/router-devtools-core@1.168.0':
+ resolution: {integrity: sha512-wQoQhlBK7nlZgqzaqdYXKWNTpdHdsaREdaPhFZVH0/Ador+F+eM3/NF2i3f2LPeS0GgKraZUQXe1Q/1+KHyEYg==}
+ engines: {node: '>=20.19'}
+ peerDependencies:
+ '@tanstack/router-core': ^1.170.0
+ csstype: ^3.0.10
+ peerDependenciesMeta:
+ csstype:
+ optional: true
+
+ '@tanstack/router-generator@1.167.21':
+ resolution: {integrity: sha512-m3oXZyienj8owialdyoZ0txHQrnEx/Ra+D9kWtar5fC2cWZr5Pvxl86VY2mX5RRLC5QLKLeRGT1x4HV95wHVDQ==}
+ engines: {node: '>=20.19'}
+
+ '@tanstack/router-plugin@1.168.23':
+ resolution: {integrity: sha512-0+PIcvnaAimFwjoEIeV3h7LKjzC8zNnp7pH2UamdKwQ9QlY99WU9V0Xl0zbM0i9hrUa/mKgWPDAzELmPUu5fMA==}
+ engines: {node: '>=20.19'}
+ peerDependencies:
+ '@rsbuild/core': '>=1.0.2 || ^2.0.0'
+ '@tanstack/react-router': ^1.170.18
+ vite: '>=5.0.0 || >=6.0.0 || >=7.0.0 || >=8.0.0'
+ vite-plugin-solid: ^2.11.10 || ^3.0.0-0
+ webpack: '>=5.92.0'
+ peerDependenciesMeta:
+ '@rsbuild/core':
+ optional: true
+ '@tanstack/react-router':
+ optional: true
+ vite:
+ optional: true
+ vite-plugin-solid:
+ optional: true
+ webpack:
+ optional: true
+
+ '@tanstack/router-utils@1.162.2':
+ resolution: {integrity: sha512-hTWqJtqIFFdvuCl8WXNyrodp2L9zo2G37xKRrcVmVRWpAB2h+U1LuRAfS4tsFTiWOIoE/B+WDVFB8JpoEdw6jQ==}
+ engines: {node: '>=20.19'}
+
+ '@tanstack/store@0.9.3':
+ resolution: {integrity: sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw==}
+
+ '@tanstack/virtual-file-routes@1.162.0':
+ resolution: {integrity: sha512-uhOeFyxLcU41HzvrxsGpiWdcMbScY1EDgbZ5K7DVRMYInbLYWAC0EA/kx9wXAoSM8q82bUG2hRl8+EAjE6XAbA==}
+ engines: {node: '>=20.19'}
+
+ '@ts-morph/common@0.27.0':
+ resolution: {integrity: sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==}
+
+ '@tybys/wasm-util@0.10.3':
+ resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==}
+
+ '@types/debug@4.1.13':
+ resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==}
+
+ '@types/estree-jsx@1.0.5':
+ resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
+
+ '@types/estree@1.0.9':
+ resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+
+ '@types/hast@3.0.5':
+ resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==}
+
+ '@types/mdast@4.0.4':
+ resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+
+ '@types/ms@2.1.0':
+ resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+
+ '@types/node@24.13.3':
+ resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==}
+
+ '@types/react-dom@19.2.3':
+ resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
+ peerDependencies:
+ '@types/react': ^19.2.0
+
+ '@types/react@19.2.17':
+ resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==}
+
+ '@types/unist@2.0.11':
+ resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
+
+ '@types/unist@3.0.3':
+ resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+
+ '@types/validate-npm-package-name@4.0.2':
+ resolution: {integrity: sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==}
+
+ '@typescript/typescript-aix-ppc64@7.0.2':
+ resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@typescript/typescript-darwin-arm64@7.0.2':
+ resolution: {integrity: sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@typescript/typescript-darwin-x64@7.0.2':
+ resolution: {integrity: sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@typescript/typescript-freebsd-arm64@7.0.2':
+ resolution: {integrity: sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@typescript/typescript-freebsd-x64@7.0.2':
+ resolution: {integrity: sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@typescript/typescript-linux-arm64@7.0.2':
+ resolution: {integrity: sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@typescript/typescript-linux-arm@7.0.2':
+ resolution: {integrity: sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm]
+ os: [linux]
+
+ '@typescript/typescript-linux-loong64@7.0.2':
+ resolution: {integrity: sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@typescript/typescript-linux-mips64el@7.0.2':
+ resolution: {integrity: sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@typescript/typescript-linux-ppc64@7.0.2':
+ resolution: {integrity: sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@typescript/typescript-linux-riscv64@7.0.2':
+ resolution: {integrity: sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@typescript/typescript-linux-s390x@7.0.2':
+ resolution: {integrity: sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==}
+ engines: {node: '>=16.20.0'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@typescript/typescript-linux-x64@7.0.2':
+ resolution: {integrity: sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [linux]
+
+ '@typescript/typescript-netbsd-arm64@7.0.2':
+ resolution: {integrity: sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@typescript/typescript-netbsd-x64@7.0.2':
+ resolution: {integrity: sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@typescript/typescript-openbsd-arm64@7.0.2':
+ resolution: {integrity: sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@typescript/typescript-openbsd-x64@7.0.2':
+ resolution: {integrity: sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@typescript/typescript-sunos-x64@7.0.2':
+ resolution: {integrity: sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@typescript/typescript-win32-arm64@7.0.2':
+ resolution: {integrity: sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@typescript/typescript-win32-x64@7.0.2':
+ resolution: {integrity: sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [win32]
+
+ '@ungap/structured-clone@1.3.3':
+ resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==}
+
+ '@vitejs/plugin-react@6.0.4':
+ resolution: {integrity: sha512-XcCQz0TBpBgljhj0gMuuDj49i6Ytqh5q1osT/Gp5uAVJUCTWxyskk/l1jwYYiu2xcNHHipdMz40EGfM1VdamVg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ peerDependencies:
+ '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0
+ babel-plugin-react-compiler: ^1.0.0
+ vite: ^8.0.0
+ peerDependenciesMeta:
+ '@rolldown/plugin-babel':
+ optional: true
+ babel-plugin-react-compiler:
+ optional: true
+
+ accepts@2.0.0:
+ resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
+ engines: {node: '>= 0.6'}
+
+ ajv-formats@2.1.1:
+ resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
+ peerDependencies:
+ ajv: ^8.0.0
+ peerDependenciesMeta:
+ ajv:
+ optional: true
+
+ ajv-formats@3.0.1:
+ resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==}
+ peerDependencies:
+ ajv: ^8.0.0
+ peerDependenciesMeta:
+ ajv:
+ optional: true
+
+ ajv@8.20.0:
+ resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==}
+
+ ansi-colors@4.1.3:
+ resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
+ engines: {node: '>=6'}
+
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-regex@6.2.2:
+ resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
+ engines: {node: '>=12'}
+
+ ansis@4.3.1:
+ resolution: {integrity: sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==}
+ engines: {node: '>=14'}
+
+ argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+ ast-types@0.16.1:
+ resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
+ engines: {node: '>=4'}
+
+ atomically@1.7.0:
+ resolution: {integrity: sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==}
+ engines: {node: '>=10.12.0'}
+
+ babel-dead-code-elimination@1.0.12:
+ resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==}
+
+ bail@2.0.2:
+ resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
+
+ balanced-match@4.0.4:
+ resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
+ engines: {node: 18 || 20 || >=22}
+
+ baseline-browser-mapping@2.11.1:
+ resolution: {integrity: sha512-HYXq73DDpCtNzOmrFsm9eSwCvWCql0RzqjpDzXN9EadiLJ4DNat0nsZ/Bzmy+Ud12mb4/zKDY0cQ805ZzN+i0A==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ body-parser@2.3.0:
+ resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==}
+ engines: {node: '>=18'}
+
+ brace-expansion@5.0.8:
+ resolution: {integrity: sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==}
+ engines: {node: 20 || >=22}
+
+ braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+
+ browserslist@4.28.7:
+ resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
+ bundle-name@4.1.0:
+ resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
+ engines: {node: '>=18'}
+
+ 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'}
+
+ call-bound@1.0.4:
+ resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
+ engines: {node: '>= 0.4'}
+
+ callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+
+ caniuse-lite@1.0.30001806:
+ resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==}
+
+ ccount@2.0.1:
+ resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
+
+ chalk@5.6.2:
+ resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+
+ character-entities-html4@2.1.0:
+ resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+
+ character-entities-legacy@3.0.0:
+ resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+
+ character-entities@2.0.2:
+ resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+
+ character-reference-invalid@2.0.1:
+ resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
+
+ chokidar@5.0.0:
+ resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
+ engines: {node: '>= 20.19.0'}
+
+ class-variance-authority@0.7.1:
+ resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
+
+ cli-cursor@5.0.0:
+ resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==}
+ engines: {node: '>=18'}
+
+ cli-spinners@2.9.2:
+ resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
+ engines: {node: '>=6'}
+
+ clsx@2.1.1:
+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
+ engines: {node: '>=6'}
+
+ code-block-writer@13.0.3:
+ resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==}
+
+ comma-separated-tokens@2.0.3:
+ resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+
+ commander@11.1.0:
+ resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
+ engines: {node: '>=16'}
+
+ commander@14.0.3:
+ resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==}
+ engines: {node: '>=20'}
+
+ conf@10.2.0:
+ resolution: {integrity: sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==}
+ engines: {node: '>=12'}
+
+ 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.0.0:
+ resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==}
+ engines: {node: '>=18'}
+
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+ cookie-es@3.1.1:
+ resolution: {integrity: sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==}
+
+ 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'}
+
+ cors@2.8.6:
+ resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==}
+ engines: {node: '>= 0.10'}
+
+ cosmiconfig@9.0.2:
+ resolution: {integrity: sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==}
+ engines: {node: '>=14'}
+ peerDependencies:
+ typescript: '>=4.9.5'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
+
+ cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
+ debounce-fn@4.0.0:
+ resolution: {integrity: sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==}
+ engines: {node: '>=10'}
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ decode-named-character-reference@1.3.0:
+ resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==}
+
+ dedent@1.7.2:
+ resolution: {integrity: sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==}
+ peerDependencies:
+ babel-plugin-macros: ^3.1.0
+ peerDependenciesMeta:
+ babel-plugin-macros:
+ optional: true
+
+ deepmerge@4.3.1:
+ resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
+ engines: {node: '>=0.10.0'}
+
+ default-browser-id@5.0.1:
+ resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==}
+ engines: {node: '>=18'}
+
+ default-browser@5.5.0:
+ resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==}
+ engines: {node: '>=18'}
+
+ define-lazy-prop@2.0.0:
+ resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
+ engines: {node: '>=8'}
+
+ define-lazy-prop@3.0.0:
+ resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
+ engines: {node: '>=12'}
+
+ depd@2.0.0:
+ resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+ engines: {node: '>= 0.8'}
+
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+ engines: {node: '>=8'}
+
+ devlop@1.1.0:
+ resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+
+ diff@8.0.4:
+ resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==}
+ engines: {node: '>=0.3.1'}
+
+ dot-prop@6.0.1:
+ resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==}
+ engines: {node: '>=10'}
+
+ dotenv@17.4.2:
+ resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==}
+ engines: {node: '>=12'}
+
+ dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+
+ ee-first@1.1.1:
+ resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+
+ electron-to-chromium@1.5.396:
+ resolution: {integrity: sha512-yHiw2Y3C3H9U6TMbOfoWK/BPreiOPXRfTWPBwQBoZG6/8TB6eOPnsy5oaRYuatR7Fw2SJ4kKforgufeo7fq0EQ==}
+
+ emoji-regex@10.6.0:
+ resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
+
+ encodeurl@2.0.0:
+ resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
+ engines: {node: '>= 0.8'}
+
+ enhanced-resolve@5.24.3:
+ resolution: {integrity: sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ==}
+ engines: {node: '>=10.13.0'}
+
+ enquirer@2.4.1:
+ resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==}
+ engines: {node: '>=8.6'}
+
+ env-paths@2.2.1:
+ resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
+ engines: {node: '>=6'}
+
+ error-ex@1.3.4:
+ resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==}
+
+ es-define-property@1.0.1:
+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+ engines: {node: '>= 0.4'}
+
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
+ es-object-atoms@1.1.2:
+ resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==}
+ engines: {node: '>= 0.4'}
+
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ escape-html@1.0.3:
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
+ escape-string-regexp@5.0.0:
+ resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
+ engines: {node: '>=12'}
+
+ esprima@4.0.1:
+ resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ estree-util-is-identifier-name@3.0.0:
+ resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
+
+ etag@1.8.1:
+ resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
+ engines: {node: '>= 0.6'}
+
+ eventsource-parser@3.1.0:
+ resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==}
+ engines: {node: '>=18.0.0'}
+
+ eventsource@3.0.7:
+ resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==}
+ engines: {node: '>=18.0.0'}
+
+ execa@5.1.1:
+ resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+ engines: {node: '>=10'}
+
+ execa@9.6.1:
+ resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==}
+ engines: {node: ^18.19.0 || >=20.5.0}
+
+ express-rate-limit@8.6.0:
+ resolution: {integrity: sha512-XKJXDsASUOo0LLtFwW5hCcQGH0N4WQc/Rn8/Pvoia+TJFOkkFPvrtW9lZOeeNcxQJspvOIERMwiRLsVFlhHEkA==}
+ engines: {node: '>= 16'}
+ peerDependencies:
+ express: '>= 4.11'
+
+ express@5.2.1:
+ resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==}
+ engines: {node: '>= 18'}
+
+ extend@3.0.2:
+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+ fast-glob@3.3.3:
+ resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
+ engines: {node: '>=8.6.0'}
+
+ fast-uri@3.1.4:
+ resolution: {integrity: sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==}
+
+ fastq@1.20.1:
+ resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
+
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ figures@6.1.0:
+ resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
+ engines: {node: '>=18'}
+
+ fill-range@7.1.1:
+ 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@3.0.0:
+ resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==}
+ engines: {node: '>=6'}
+
+ forwarded@0.2.0:
+ resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
+ engines: {node: '>= 0.6'}
+
+ fresh@2.0.0:
+ resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
+ engines: {node: '>= 0.8'}
+
+ fs-extra@11.4.0:
+ resolution: {integrity: sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==}
+ engines: {node: '>=14.14'}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ fuzzysort@3.1.0:
+ resolution: {integrity: sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==}
+
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
+ get-east-asian-width@1.6.0:
+ resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==}
+ engines: {node: '>=18'}
+
+ get-intrinsic@1.3.0:
+ resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+ engines: {node: '>= 0.4'}
+
+ get-own-enumerable-keys@1.0.0:
+ resolution: {integrity: sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==}
+ engines: {node: '>=14.16'}
+
+ get-proto@1.0.1:
+ resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+ engines: {node: '>= 0.4'}
+
+ get-stream@6.0.1:
+ resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+ engines: {node: '>=10'}
+
+ get-stream@9.0.1:
+ resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
+ engines: {node: '>=18'}
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ goober@2.1.19:
+ resolution: {integrity: sha512-U7veizMqxyKlM58+Z5j2ngJBH/r9siDmxpvNxSw0PylF6WQvrASJEZrxh1hidRBJc2jqoBVSyOban5u8m+6Rxg==}
+ peerDependencies:
+ csstype: ^3.0.10
+
+ gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ has-symbols@1.1.0:
+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+ engines: {node: '>= 0.4'}
+
+ hasown@2.0.4:
+ resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
+ engines: {node: '>= 0.4'}
+
+ hast-util-to-jsx-runtime@2.3.6:
+ resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
+
+ hast-util-whitespace@3.0.0:
+ resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+
+ hono@4.12.32:
+ resolution: {integrity: sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==}
+ engines: {node: '>=16.9.0'}
+
+ html-url-attributes@3.0.1:
+ resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
+
+ http-errors@2.0.1:
+ resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
+ engines: {node: '>= 0.8'}
+
+ human-signals@2.1.0:
+ resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+ engines: {node: '>=10.17.0'}
+
+ human-signals@8.0.1:
+ resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
+ engines: {node: '>=18.18.0'}
+
+ 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'}
+
+ import-fresh@3.3.1:
+ resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
+ engines: {node: '>=6'}
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ inline-style-parser@0.2.7:
+ resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
+
+ ip-address@10.2.0:
+ resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==}
+ engines: {node: '>= 12'}
+
+ ipaddr.js@1.9.1:
+ resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
+ engines: {node: '>= 0.10'}
+
+ is-alphabetical@2.0.1:
+ resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
+
+ is-alphanumerical@2.0.1:
+ resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
+
+ is-arrayish@0.2.1:
+ resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
+
+ is-decimal@2.0.1:
+ resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
+
+ is-docker@2.2.1:
+ resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
+ engines: {node: '>=8'}
+ hasBin: true
+
+ is-docker@3.0.0:
+ resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ hasBin: true
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-hexadecimal@2.0.1:
+ resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
+
+ is-in-ssh@1.0.0:
+ resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==}
+ engines: {node: '>=20'}
+
+ is-inside-container@1.0.0:
+ resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
+ engines: {node: '>=14.16'}
+ hasBin: true
+
+ is-interactive@2.0.0:
+ resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==}
+ engines: {node: '>=12'}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ is-obj@2.0.0:
+ resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
+ engines: {node: '>=8'}
+
+ is-obj@3.0.0:
+ resolution: {integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==}
+ engines: {node: '>=12'}
+
+ is-plain-obj@4.1.0:
+ resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
+ engines: {node: '>=12'}
+
+ is-promise@4.0.0:
+ resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
+
+ is-regexp@3.1.0:
+ resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==}
+ engines: {node: '>=12'}
+
+ is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+
+ is-stream@4.0.1:
+ resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
+ engines: {node: '>=18'}
+
+ is-unicode-supported@1.3.0:
+ resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==}
+ engines: {node: '>=12'}
+
+ is-unicode-supported@2.1.0:
+ resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==}
+ engines: {node: '>=18'}
+
+ is-wsl@2.2.0:
+ resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
+ engines: {node: '>=8'}
+
+ is-wsl@3.1.1:
+ resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==}
+ engines: {node: '>=16'}
+
+ isbot@5.2.1:
+ resolution: {integrity: sha512-dJ+LpKyClQZ7NG+j3OensC/mAZkGpukE9YUrgPYvAZj2doVL0edfDgywTUh5CXa0o+nW9a1V9e5+CJTX8+SxRw==}
+ engines: {node: '>=18'}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ isexe@3.1.5:
+ resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==}
+ engines: {node: '>=18'}
+
+ jiti@2.7.0:
+ resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
+ hasBin: true
+
+ jose@6.2.4:
+ resolution: {integrity: sha512-N8acGzVsQy6M/fjFcxtysNc4Q379TcM5dM/qKkNtsHFji88yANnXTr7BLeP75iPnFwBfQzM/jg2BZ9+HZrHCZA==}
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ js-yaml@4.3.0:
+ resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==}
+ hasBin: true
+
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ json-parse-even-better-errors@2.3.1:
+ resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
+
+ json-schema-traverse@1.0.0:
+ resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
+
+ json-schema-typed@7.0.3:
+ resolution: {integrity: sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==}
+
+ json-schema-typed@8.0.2:
+ resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==}
+
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ jsonfile@6.2.1:
+ resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==}
+
+ kleur@3.0.3:
+ resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
+ engines: {node: '>=6'}
+
+ kleur@4.1.5:
+ resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+ engines: {node: '>=6'}
+
+ lightningcss-android-arm64@1.32.0:
+ resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [android]
+
+ lightningcss-android-arm64@1.33.0:
+ resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [android]
+
+ lightningcss-darwin-arm64@1.32.0:
+ resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ lightningcss-darwin-arm64@1.33.0:
+ resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ lightningcss-darwin-x64@1.32.0:
+ resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ lightningcss-darwin-x64@1.33.0:
+ resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ lightningcss-freebsd-x64@1.32.0:
+ resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ lightningcss-freebsd-x64@1.33.0:
+ resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ lightningcss-linux-arm-gnueabihf@1.32.0:
+ resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ lightningcss-linux-arm-gnueabihf@1.33.0:
+ resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ lightningcss-linux-arm64-gnu@1.32.0:
+ resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ lightningcss-linux-arm64-gnu@1.33.0:
+ resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ lightningcss-linux-arm64-musl@1.32.0:
+ resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ lightningcss-linux-arm64-musl@1.33.0:
+ resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ lightningcss-linux-x64-gnu@1.32.0:
+ resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ lightningcss-linux-x64-gnu@1.33.0:
+ resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ lightningcss-linux-x64-musl@1.32.0:
+ resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ lightningcss-linux-x64-musl@1.33.0:
+ resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ lightningcss-win32-arm64-msvc@1.32.0:
+ resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ lightningcss-win32-arm64-msvc@1.33.0:
+ resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ lightningcss-win32-x64-msvc@1.32.0:
+ resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ lightningcss-win32-x64-msvc@1.33.0:
+ resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ lightningcss@1.32.0:
+ resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
+ engines: {node: '>= 12.0.0'}
+
+ lightningcss@1.33.0:
+ resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==}
+ engines: {node: '>= 12.0.0'}
+
+ lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
+ locate-path@3.0.0:
+ resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
+ engines: {node: '>=6'}
+
+ log-symbols@6.0.0:
+ resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==}
+ engines: {node: '>=18'}
+
+ longest-streak@3.1.0:
+ resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
+
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+ lucide-react@1.26.0:
+ resolution: {integrity: sha512-raglYVR2+VkMfJL158krjVmE+rV5ST2lzA/KQm1FRSjMHT4MnWaegHxoVEpmc2So3nOEhp9oGejJwAPX8MoAjg==}
+ peerDependencies:
+ react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+ markdown-table@3.0.4:
+ resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
+
+ math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+
+ mdast-util-find-and-replace@3.0.2:
+ resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
+
+ mdast-util-from-markdown@2.0.3:
+ resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==}
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
+
+ mdast-util-gfm-footnote@2.1.0:
+ resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==}
+
+ mdast-util-gfm-strikethrough@2.0.0:
+ resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
+
+ mdast-util-gfm-table@2.0.0:
+ resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
+
+ mdast-util-gfm-task-list-item@2.0.0:
+ resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
+
+ mdast-util-gfm@3.1.0:
+ resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==}
+
+ mdast-util-mdx-expression@2.0.1:
+ resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
+
+ mdast-util-mdx-jsx@3.2.0:
+ resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
+
+ mdast-util-mdxjs-esm@2.0.1:
+ resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
+
+ mdast-util-phrasing@4.1.0:
+ resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
+
+ mdast-util-to-hast@13.2.1:
+ resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
+
+ mdast-util-to-markdown@2.1.2:
+ resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
+
+ mdast-util-to-string@4.0.0:
+ resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
+
+ 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'}
+
+ merge-stream@2.0.0:
+ resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micromark-core-commonmark@2.0.3:
+ resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
+
+ micromark-extension-gfm-autolink-literal@2.1.0:
+ resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}
+
+ micromark-extension-gfm-footnote@2.1.0:
+ resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==}
+
+ micromark-extension-gfm-strikethrough@2.1.0:
+ resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==}
+
+ micromark-extension-gfm-table@2.1.1:
+ resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==}
+
+ micromark-extension-gfm-tagfilter@2.0.0:
+ resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==}
+
+ micromark-extension-gfm@3.0.0:
+ resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
+
+ micromark-factory-destination@2.0.1:
+ resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
+
+ micromark-factory-label@2.0.1:
+ resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
+
+ micromark-factory-space@2.0.1:
+ resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
+
+ micromark-factory-title@2.0.1:
+ resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==}
+
+ micromark-factory-whitespace@2.0.1:
+ resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==}
+
+ micromark-util-character@2.1.1:
+ resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
+
+ micromark-util-chunked@2.0.1:
+ resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==}
+
+ micromark-util-classify-character@2.0.1:
+ resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==}
+
+ micromark-util-combine-extensions@2.0.1:
+ resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==}
+
+ micromark-util-decode-numeric-character-reference@2.0.2:
+ resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}
+
+ micromark-util-decode-string@2.0.1:
+ resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}
+
+ micromark-util-encode@2.0.1:
+ resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
+
+ micromark-util-html-tag-name@2.0.1:
+ resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
+
+ micromark-util-normalize-identifier@2.0.1:
+ resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==}
+
+ micromark-util-resolve-all@2.0.1:
+ resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==}
+
+ micromark-util-sanitize-uri@2.0.1:
+ resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
+
+ micromark-util-subtokenize@2.1.0:
+ resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==}
+
+ micromark-util-symbol@2.0.1:
+ resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
+
+ micromark-util-types@2.0.2:
+ resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
+
+ micromark@4.0.2:
+ resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
+
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+
+ mime-db@1.54.0:
+ resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@3.0.2:
+ resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
+ engines: {node: '>=18'}
+
+ mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+
+ mimic-fn@3.1.0:
+ resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==}
+ engines: {node: '>=8'}
+
+ mimic-function@5.0.1:
+ resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
+ engines: {node: '>=18'}
+
+ minimatch@10.2.5:
+ resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==}
+ engines: {node: 18 || 20 || >=22}
+
+ minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ nanoid@3.3.16:
+ resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ negotiator@1.0.0:
+ resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
+ engines: {node: '>= 0.6'}
+
+ node-releases@2.0.51:
+ resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==}
+ engines: {node: '>=18'}
+
+ npm-run-path@4.0.1:
+ resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+ engines: {node: '>=8'}
+
+ npm-run-path@6.0.0:
+ resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==}
+ engines: {node: '>=18'}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ object-inspect@1.13.4:
+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
+ engines: {node: '>= 0.4'}
+
+ object-treeify@1.1.33:
+ resolution: {integrity: sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==}
+ engines: {node: '>= 10'}
+
+ 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==}
+
+ onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+
+ onetime@7.0.0:
+ resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
+ engines: {node: '>=18'}
+
+ open@11.0.0:
+ resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==}
+ engines: {node: '>=20'}
+
+ open@8.4.2:
+ resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
+ engines: {node: '>=12'}
+
+ openapi-fetch@0.17.0:
+ resolution: {integrity: sha512-PsbZR1wAPcG91eEthKhN+Zn92FMHxv+/faECIwjXdxfTODGSGegYv0sc1Olz+HYPvKOuoXfp+0pA2XVt2cI0Ig==}
+
+ openapi-typescript-helpers@0.1.0:
+ resolution: {integrity: sha512-OKTGPthhivLw/fHz6c3OPtg72vi86qaMlqbJuVJ23qOvQ+53uw1n7HdmkJFibloF7QEjDrDkzJiOJuockM/ljw==}
+
+ ora@8.2.0:
+ resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==}
+ engines: {node: '>=18'}
+
+ oxlint-tsgolint@7.0.2001:
+ resolution: {integrity: sha512-KjK/XLcXr1DSyonKhsuFqJRiuKqcyG9j3LJ8nkOsrLzGvodBPqzHOKauy10asLMDI0sUpvb+1sxlzff3udZvfg==}
+ hasBin: true
+
+ oxlint@1.75.0:
+ resolution: {integrity: sha512-m9WzjRcRYA/uqIZDa9tclrieoPJ/ln1QYTKdFx6NUOs8uY5DiHlIwRQoCrHT6OM6O3ww3l2skY5gO7G7ZphE7g==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+ peerDependencies:
+ oxlint-tsgolint: '>=7.0.2001'
+ vite-plus: '*'
+ peerDependenciesMeta:
+ oxlint-tsgolint:
+ optional: true
+ vite-plus:
+ optional: true
+
+ p-limit@2.3.0:
+ resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+ engines: {node: '>=6'}
+
+ p-locate@3.0.0:
+ resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==}
+ engines: {node: '>=6'}
+
+ p-try@2.2.0:
+ resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+ engines: {node: '>=6'}
+
+ parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+
+ parse-entities@4.0.2:
+ resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
+
+ parse-json@5.2.0:
+ resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
+ engines: {node: '>=8'}
+
+ parse-ms@4.0.0:
+ resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
+ engines: {node: '>=18'}
+
+ parseurl@1.3.3:
+ resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
+ engines: {node: '>= 0.8'}
+
+ path-browserify@1.0.1:
+ resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+
+ path-exists@3.0.0:
+ resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==}
+ engines: {node: '>=4'}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-key@4.0.0:
+ resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
+ engines: {node: '>=12'}
+
+ path-to-regexp@8.4.2:
+ resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==}
+
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@2.3.2:
+ resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==}
+ engines: {node: '>=8.6'}
+
+ picomatch@4.0.5:
+ resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==}
+ engines: {node: '>=12'}
+
+ pkce-challenge@5.0.1:
+ resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==}
+ engines: {node: '>=16.20.0'}
+
+ pkg-up@3.1.0:
+ resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==}
+ engines: {node: '>=8'}
+
+ postcss-selector-parser@7.1.4:
+ resolution: {integrity: sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==}
+ engines: {node: '>=4'}
+
+ postcss@8.5.23:
+ resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ powershell-utils@0.1.0:
+ resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==}
+ engines: {node: '>=20'}
+
+ prettier-plugin-tailwindcss@0.8.1:
+ resolution: {integrity: sha512-iaFMYqDsE4ffdDkn5qup0j5f2aCEBFZrdrZnvu9QKTlWx/iGPeQ4HHu7b7fCPMxeo9nwQBiOAh2nSypdFYWJkw==}
+ engines: {node: '>=20.19'}
+ peerDependencies:
+ '@ianvs/prettier-plugin-sort-imports': '*'
+ '@prettier/plugin-hermes': '*'
+ '@prettier/plugin-oxc': '*'
+ '@prettier/plugin-pug': '*'
+ '@shopify/prettier-plugin-liquid': '*'
+ '@trivago/prettier-plugin-sort-imports': '*'
+ '@zackad/prettier-plugin-twig': '*'
+ prettier: ^3.0
+ prettier-plugin-astro: '*'
+ prettier-plugin-css-order: '*'
+ prettier-plugin-jsdoc: '*'
+ prettier-plugin-marko: '*'
+ prettier-plugin-multiline-arrays: '*'
+ prettier-plugin-organize-attributes: '*'
+ prettier-plugin-organize-imports: '*'
+ prettier-plugin-sort-imports: '*'
+ prettier-plugin-svelte: '*'
+ peerDependenciesMeta:
+ '@ianvs/prettier-plugin-sort-imports':
+ optional: true
+ '@prettier/plugin-hermes':
+ optional: true
+ '@prettier/plugin-oxc':
+ optional: true
+ '@prettier/plugin-pug':
+ optional: true
+ '@shopify/prettier-plugin-liquid':
+ optional: true
+ '@trivago/prettier-plugin-sort-imports':
+ optional: true
+ '@zackad/prettier-plugin-twig':
+ optional: true
+ prettier-plugin-astro:
+ optional: true
+ prettier-plugin-css-order:
+ optional: true
+ prettier-plugin-jsdoc:
+ optional: true
+ prettier-plugin-marko:
+ optional: true
+ prettier-plugin-multiline-arrays:
+ optional: true
+ prettier-plugin-organize-attributes:
+ optional: true
+ prettier-plugin-organize-imports:
+ optional: true
+ prettier-plugin-sort-imports:
+ optional: true
+ prettier-plugin-svelte:
+ optional: true
+
+ prettier@3.9.6:
+ resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==}
+ engines: {node: '>=14'}
+ hasBin: true
+
+ pretty-ms@9.3.0:
+ resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==}
+ engines: {node: '>=18'}
+
+ prompts@2.4.2:
+ resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
+ engines: {node: '>= 6'}
+
+ property-information@7.2.0:
+ resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==}
+
+ proxy-addr@2.0.7:
+ resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
+ engines: {node: '>= 0.10'}
+
+ 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-dom@19.2.8:
+ resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==}
+ peerDependencies:
+ react: ^19.2.8
+
+ react-hook-form@7.82.0:
+ resolution: {integrity: sha512-Zw/uFZ2dO+02GHlBn7JFGn8kZJ7LdM33B/0BXOovzFay+CMhf94JMw5BVu+F1tVkUKjNvBuaE3fz5BJhga10Tg==}
+ engines: {node: '>=18.0.0'}
+ peerDependencies:
+ react: ^16.8.0 || ^17 || ^18 || ^19
+
+ react-markdown@10.1.0:
+ resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==}
+ peerDependencies:
+ '@types/react': '>=18'
+ react: '>=18'
+
+ react@19.2.8:
+ resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==}
+ engines: {node: '>=0.10.0'}
+
+ readdirp@5.0.0:
+ resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
+ engines: {node: '>= 20.19.0'}
+
+ recast@0.23.12:
+ resolution: {integrity: sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA==}
+ engines: {node: '>= 4'}
+
+ remark-gfm@4.0.1:
+ resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
+
+ remark-parse@11.0.0:
+ resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
+
+ remark-rehype@11.1.2:
+ resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
+
+ remark-stringify@11.0.0:
+ resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
+
+ require-from-string@2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
+
+ reselect@5.2.0:
+ resolution: {integrity: sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==}
+
+ resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+
+ restore-cursor@5.1.0:
+ resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==}
+ engines: {node: '>=18'}
+
+ reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rolldown@1.1.5:
+ resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+
+ router@2.2.0:
+ resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==}
+ engines: {node: '>= 18'}
+
+ run-applescript@7.1.0:
+ resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==}
+ engines: {node: '>=18'}
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+ scheduler@0.27.0:
+ resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+
+ semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+
+ semver@7.8.5:
+ resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ send@1.2.1:
+ resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==}
+ engines: {node: '>= 18'}
+
+ seroval-plugins@1.5.6:
+ resolution: {integrity: sha512-HXuLAX2pu/UByPpaeo/TaMfvMIi+1QqIoPJYCcAtU8QkVNwgR6MPlGuCQTErV1JwraaMbYaWVIBX7mppzGLATQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ seroval: ^1.0
+
+ seroval@1.5.6:
+ resolution: {integrity: sha512-rVQVWjjSvlINzaQPZH5JFqsqEsIWdTxY3iJZCnTL/5gQbXIRooVZKI60tVCkOVfzcRPejboxO2t0P89dg5mQaA==}
+ engines: {node: '>=10'}
+
+ serve-static@2.2.1:
+ resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==}
+ engines: {node: '>= 18'}
+
+ setprototypeof@1.2.0:
+ resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+
+ shadcn@4.14.1:
+ resolution: {integrity: sha512-Xb4r150oGNexMBxUnWPG1emcaUlFbhzMOJubdA+k0NTkmhgBBycFZjTz9Aw2yQbpDR6QnIZbk234N20s/s7s9A==}
+ engines: {node: '>=20.18.1'}
+ hasBin: true
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ side-channel-list@1.0.1:
+ resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-map@1.0.1:
+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-weakmap@1.0.2:
+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
+ engines: {node: '>= 0.4'}
+
+ side-channel@1.1.1:
+ resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==}
+ engines: {node: '>= 0.4'}
+
+ signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+
+ signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+
+ sisteransi@1.0.5:
+ resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
+
+ sonner@2.0.7:
+ resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==}
+ peerDependencies:
+ react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
+ space-separated-tokens@2.0.2:
+ resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+
+ statuses@2.0.2:
+ resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
+ engines: {node: '>= 0.8'}
+
+ stdin-discarder@0.2.2:
+ resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
+ engines: {node: '>=18'}
+
+ string-width@7.2.0:
+ resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
+ engines: {node: '>=18'}
+
+ stringify-entities@4.0.4:
+ resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+
+ stringify-object@5.0.0:
+ resolution: {integrity: sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg==}
+ engines: {node: '>=14.16'}
+
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+
+ strip-ansi@7.2.0:
+ resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
+ engines: {node: '>=12'}
+
+ strip-bom@3.0.0:
+ resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+ engines: {node: '>=4'}
+
+ strip-final-newline@2.0.0:
+ resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+ engines: {node: '>=6'}
+
+ strip-final-newline@4.0.0:
+ resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
+ engines: {node: '>=18'}
+
+ style-to-js@1.1.21:
+ resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==}
+
+ style-to-object@1.0.14:
+ resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
+
+ supports-color@10.2.2:
+ resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==}
+ engines: {node: '>=18'}
+
+ systeminformation@5.33.1:
+ resolution: {integrity: sha512-DEN6ICHk3Tk0Uf/hrAHh7xlt7iL5CJFBtPZinA0H62DrGG/KPKqq/Nzj6lCXPS4Ay/sf/14zNnk9LpqKzBIc+w==}
+ engines: {node: '>=10.0.0'}
+ os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android]
+ hasBin: true
+
+ tailwind-merge@3.6.0:
+ resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==}
+
+ tailwindcss@4.3.3:
+ resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==}
+
+ tapable@2.3.3:
+ resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==}
+ engines: {node: '>=6'}
+
+ tiny-invariant@1.3.3:
+ resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
+
+ tinyglobby@0.2.17:
+ resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
+ engines: {node: '>=12.0.0'}
+
+ to-regex-range@5.0.1:
+ 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'}
+
+ trim-lines@3.0.1:
+ resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+
+ trough@2.2.0:
+ resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
+
+ ts-morph@26.0.0:
+ resolution: {integrity: sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug==}
+
+ tsconfig-paths@4.2.0:
+ resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==}
+ engines: {node: '>=6'}
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ tw-animate-css@1.4.0:
+ resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==}
+
+ type-is@2.1.0:
+ resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==}
+ engines: {node: '>= 18'}
+
+ typescript@7.0.2:
+ resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==}
+ engines: {node: '>=16.20.0'}
+ hasBin: true
+
+ undici-types@7.18.2:
+ resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
+
+ undici@7.29.0:
+ resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==}
+ engines: {node: '>=20.18.1'}
+
+ unicorn-magic@0.3.0:
+ resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
+ engines: {node: '>=18'}
+
+ unified@11.0.5:
+ resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
+
+ unist-util-is@6.0.1:
+ resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
+
+ unist-util-position@5.0.0:
+ resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+
+ unist-util-stringify-position@4.0.0:
+ resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+
+ unist-util-visit-parents@6.0.2:
+ resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
+
+ unist-util-visit@5.1.0:
+ resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==}
+
+ universalify@2.0.1:
+ resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+ engines: {node: '>= 10.0.0'}
+
+ unpipe@1.0.0:
+ resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+ engines: {node: '>= 0.8'}
+
+ unplugin@3.3.0:
+ resolution: {integrity: sha512-qa66K+crbfyE6JK10GjvbJeRrOsuC/JpbnHctfyp/i4oBTxWOzJfRZyDiOk1PtErMFRu8JhsU/wPvOdBNWe5Rg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ peerDependencies:
+ '@farmfe/core': '*'
+ '@rspack/core': '*'
+ bun-types-no-globals: '*'
+ esbuild: '*'
+ rolldown: '*'
+ rollup: '*'
+ unloader: '*'
+ vite: '*'
+ webpack: '*'
+ peerDependenciesMeta:
+ '@farmfe/core':
+ optional: true
+ '@rspack/core':
+ optional: true
+ bun-types-no-globals:
+ optional: true
+ esbuild:
+ optional: true
+ rolldown:
+ optional: true
+ rollup:
+ optional: true
+ unloader:
+ optional: true
+ vite:
+ optional: true
+ webpack:
+ optional: true
+
+ update-browserslist-db@1.2.3:
+ resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
+ use-sync-external-store@1.6.0:
+ resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
+ util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ validate-npm-package-name@7.0.2:
+ resolution: {integrity: sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==}
+ engines: {node: ^20.17.0 || >=22.9.0}
+
+ vary@1.1.2:
+ resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+ engines: {node: '>= 0.8'}
+
+ vfile-message@4.0.3:
+ resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
+
+ vfile@6.0.3:
+ resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+
+ vite@8.1.5:
+ resolution: {integrity: sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^20.19.0 || >=22.12.0
+ '@vitejs/devtools': ^0.3.0
+ esbuild: ^0.27.0 || ^0.28.0
+ jiti: '>=1.21.0'
+ less: ^4.0.0
+ sass: ^1.70.0
+ sass-embedded: ^1.70.0
+ stylus: '>=0.54.8'
+ sugarss: ^5.0.0
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ '@vitejs/devtools':
+ optional: true
+ esbuild:
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ webpack-virtual-modules@0.6.2:
+ resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ which@4.0.0:
+ resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==}
+ engines: {node: ^16.13.0 || >=18.0.0}
+ hasBin: true
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ wsl-utils@0.3.1:
+ resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==}
+ engines: {node: '>=20'}
+
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
+ yocto-spinner@1.2.2:
+ resolution: {integrity: sha512-DODGl1wJjA/s5pnJFKau9lIYHT81lnhob1i3e1TjxZRxEhWRKl74nTbWE6H5KlkViQQTo/Z29YFdxzTZAMY3ng==}
+ engines: {node: '>=18.19'}
+
+ yoctocolors@2.1.2:
+ resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==}
+ engines: {node: '>=18'}
+
+ zod-to-json-schema@3.25.2:
+ resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==}
+ peerDependencies:
+ zod: ^3.25.28 || ^4
+
+ zod@3.25.76:
+ resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
+
+ zod@4.4.3:
+ resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==}
+
+ zwitch@2.0.4:
+ resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
+
+snapshots:
+
+ '@babel/code-frame@7.29.7':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.29.7
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.29.7': {}
+
+ '@babel/core@7.29.7(supports-color@10.2.2)':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@babel/helpers': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/template': 7.29.7
+ '@babel/traverse': 7.29.7(supports-color@10.2.2)
+ '@babel/types': 7.29.7
+ '@jridgewell/remapping': 2.3.5
+ convert-source-map: 2.0.0
+ debug: 4.4.3(supports-color@10.2.2)
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/generator@7.29.7':
+ dependencies:
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
+
+ '@babel/helper-annotate-as-pure@7.29.7':
+ dependencies:
+ '@babel/types': 7.29.7
+
+ '@babel/helper-compilation-targets@7.29.7':
+ dependencies:
+ '@babel/compat-data': 7.29.7
+ '@babel/helper-validator-option': 7.29.7
+ browserslist: 4.28.7
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
+ '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-annotate-as-pure': 7.29.7
+ '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-optimise-call-expression': 7.29.7
+ '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@10.2.2)
+ '@babel/traverse': 7.29.7(supports-color@10.2.2)
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-globals@7.29.7': {}
+
+ '@babel/helper-member-expression-to-functions@7.29.7(supports-color@10.2.2)':
+ dependencies:
+ '@babel/traverse': 7.29.7(supports-color@10.2.2)
+ '@babel/types': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-imports@7.29.7(supports-color@10.2.2)':
+ dependencies:
+ '@babel/traverse': 7.29.7(supports-color@10.2.2)
+ '@babel/types': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-module-imports': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-validator-identifier': 7.29.7
+ '@babel/traverse': 7.29.7(supports-color@10.2.2)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-optimise-call-expression@7.29.7':
+ dependencies:
+ '@babel/types': 7.29.7
+
+ '@babel/helper-plugin-utils@7.29.7': {}
+
+ '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-optimise-call-expression': 7.29.7
+ '@babel/traverse': 7.29.7(supports-color@10.2.2)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-skip-transparent-expression-wrappers@7.29.7(supports-color@10.2.2)':
+ dependencies:
+ '@babel/traverse': 7.29.7(supports-color@10.2.2)
+ '@babel/types': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-string-parser@7.29.7': {}
+
+ '@babel/helper-validator-identifier@7.29.7': {}
+
+ '@babel/helper-validator-option@7.29.7': {}
+
+ '@babel/helpers@7.29.7':
+ dependencies:
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
+
+ '@babel/parser@7.29.7':
+ dependencies:
+ '@babel/types': 7.29.7
+
+ '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))':
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))':
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@babel/helper-plugin-utils': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-annotate-as-pure': 7.29.7
+ '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@10.2.2)
+ '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/preset-typescript@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/helper-validator-option': 7.29.7
+ '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))
+ '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/runtime@7.29.7': {}
+
+ '@babel/template@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+
+ '@babel/traverse@7.29.7(supports-color@10.2.2)':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.7
+ '@babel/helper-globals': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
+ debug: 4.4.3(supports-color@10.2.2)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/types@7.29.7':
+ dependencies:
+ '@babel/helper-string-parser': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+
+ '@base-ui/react@1.6.0(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
+ dependencies:
+ '@babel/runtime': 7.29.7
+ '@base-ui/utils': 0.3.1(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ '@floating-ui/react-dom': 2.1.9(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ '@floating-ui/utils': 0.2.12
+ react: 19.2.8
+ react-dom: 19.2.8(react@19.2.8)
+ use-sync-external-store: 1.6.0(react@19.2.8)
+ optionalDependencies:
+ '@types/react': 19.2.17
+
+ '@base-ui/utils@0.3.1(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
+ dependencies:
+ '@babel/runtime': 7.29.7
+ '@floating-ui/utils': 0.2.12
+ react: 19.2.8
+ react-dom: 19.2.8(react@19.2.8)
+ reselect: 5.2.0
+ use-sync-external-store: 1.6.0(react@19.2.8)
+ optionalDependencies:
+ '@types/react': 19.2.17
+
+ '@dotenvx/dotenvx@1.75.1':
+ dependencies:
+ '@dotenvx/primitives': 0.8.0
+ commander: 11.1.0
+ conf: 10.2.0
+ dotenv: 17.4.2
+ enquirer: 2.4.1
+ env-paths: 2.2.1
+ execa: 5.1.1
+ fdir: 6.5.0(picomatch@4.0.5)
+ ignore: 5.3.2
+ object-treeify: 1.1.33
+ open: 8.4.2
+ picomatch: 4.0.5
+ systeminformation: 5.33.1
+ undici: 7.29.0
+ which: 4.0.0
+ yocto-spinner: 1.2.2
+
+ '@dotenvx/primitives@0.8.0': {}
+
+ '@emnapi/core@1.11.1':
+ dependencies:
+ '@emnapi/wasi-threads': 1.2.2
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/runtime@1.11.1':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/wasi-threads@1.2.2':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@floating-ui/core@1.8.0':
+ dependencies:
+ '@floating-ui/utils': 0.2.12
+
+ '@floating-ui/dom@1.8.0':
+ dependencies:
+ '@floating-ui/core': 1.8.0
+ '@floating-ui/utils': 0.2.12
+
+ '@floating-ui/react-dom@2.1.9(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
+ dependencies:
+ '@floating-ui/dom': 1.8.0
+ react: 19.2.8
+ react-dom: 19.2.8(react@19.2.8)
+
+ '@floating-ui/utils@0.2.12': {}
+
+ '@fontsource-variable/onest@5.3.0': {}
+
+ '@hono/node-server@1.19.15(hono@4.12.32)':
+ dependencies:
+ hono: 4.12.32
+
+ '@hookform/resolvers@5.4.0(react-hook-form@7.82.0(react@19.2.8))':
+ dependencies:
+ '@standard-schema/utils': 0.3.0
+ react-hook-form: 7.82.0(react@19.2.8)
+
+ '@jridgewell/gen-mapping@0.3.13':
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/sourcemap-codec@1.5.5': {}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ '@modelcontextprotocol/sdk@1.29.0(supports-color@10.2.2)(zod@3.25.76)':
+ dependencies:
+ '@hono/node-server': 1.19.15(hono@4.12.32)
+ ajv: 8.20.0
+ ajv-formats: 3.0.1(ajv@8.20.0)
+ content-type: 1.0.5
+ cors: 2.8.6
+ cross-spawn: 7.0.6
+ eventsource: 3.0.7
+ eventsource-parser: 3.1.0
+ express: 5.2.1(supports-color@10.2.2)
+ express-rate-limit: 8.6.0(express@5.2.1(supports-color@10.2.2))(supports-color@10.2.2)
+ hono: 4.12.32
+ jose: 6.2.4
+ json-schema-typed: 8.0.2
+ pkce-challenge: 5.0.1
+ raw-body: 3.0.2
+ zod: 3.25.76
+ zod-to-json-schema: 3.25.2(zod@3.25.76)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)':
+ dependencies:
+ '@emnapi/core': 1.11.1
+ '@emnapi/runtime': 1.11.1
+ '@tybys/wasm-util': 0.10.3
+ optional: true
+
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.20.1
+
+ '@oxc-project/types@0.139.0': {}
+
+ '@oxlint-tsgolint/darwin-arm64@7.0.2001':
+ optional: true
+
+ '@oxlint-tsgolint/darwin-x64@7.0.2001':
+ optional: true
+
+ '@oxlint-tsgolint/linux-arm64@7.0.2001':
+ optional: true
+
+ '@oxlint-tsgolint/linux-x64@7.0.2001':
+ optional: true
+
+ '@oxlint-tsgolint/win32-arm64@7.0.2001':
+ optional: true
+
+ '@oxlint-tsgolint/win32-x64@7.0.2001':
+ optional: true
+
+ '@oxlint/binding-android-arm-eabi@1.75.0':
+ optional: true
+
+ '@oxlint/binding-android-arm64@1.75.0':
+ optional: true
+
+ '@oxlint/binding-darwin-arm64@1.75.0':
+ optional: true
+
+ '@oxlint/binding-darwin-x64@1.75.0':
+ optional: true
+
+ '@oxlint/binding-freebsd-x64@1.75.0':
+ optional: true
+
+ '@oxlint/binding-linux-arm-gnueabihf@1.75.0':
+ optional: true
+
+ '@oxlint/binding-linux-arm-musleabihf@1.75.0':
+ optional: true
+
+ '@oxlint/binding-linux-arm64-gnu@1.75.0':
+ optional: true
+
+ '@oxlint/binding-linux-arm64-musl@1.75.0':
+ optional: true
+
+ '@oxlint/binding-linux-ppc64-gnu@1.75.0':
+ optional: true
+
+ '@oxlint/binding-linux-riscv64-gnu@1.75.0':
+ optional: true
+
+ '@oxlint/binding-linux-riscv64-musl@1.75.0':
+ optional: true
+
+ '@oxlint/binding-linux-s390x-gnu@1.75.0':
+ optional: true
+
+ '@oxlint/binding-linux-x64-gnu@1.75.0':
+ optional: true
+
+ '@oxlint/binding-linux-x64-musl@1.75.0':
+ optional: true
+
+ '@oxlint/binding-openharmony-arm64@1.75.0':
+ optional: true
+
+ '@oxlint/binding-win32-arm64-msvc@1.75.0':
+ optional: true
+
+ '@oxlint/binding-win32-ia32-msvc@1.75.0':
+ optional: true
+
+ '@oxlint/binding-win32-x64-msvc@1.75.0':
+ optional: true
+
+ '@rolldown/binding-android-arm64@1.1.5':
+ optional: true
+
+ '@rolldown/binding-darwin-arm64@1.1.5':
+ optional: true
+
+ '@rolldown/binding-darwin-x64@1.1.5':
+ optional: true
+
+ '@rolldown/binding-freebsd-x64@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-arm-gnueabihf@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-arm64-gnu@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-arm64-musl@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-ppc64-gnu@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-s390x-gnu@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-x64-gnu@1.1.5':
+ optional: true
+
+ '@rolldown/binding-linux-x64-musl@1.1.5':
+ optional: true
+
+ '@rolldown/binding-openharmony-arm64@1.1.5':
+ optional: true
+
+ '@rolldown/binding-wasm32-wasi@1.1.5':
+ dependencies:
+ '@emnapi/core': 1.11.1
+ '@emnapi/runtime': 1.11.1
+ '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)
+ optional: true
+
+ '@rolldown/binding-win32-arm64-msvc@1.1.5':
+ optional: true
+
+ '@rolldown/binding-win32-x64-msvc@1.1.5':
+ optional: true
+
+ '@rolldown/pluginutils@1.0.1': {}
+
+ '@sec-ant/readable-stream@0.4.1': {}
+
+ '@sindresorhus/merge-streams@4.0.0': {}
+
+ '@standard-schema/utils@0.3.0': {}
+
+ '@tailwindcss/node@4.3.3':
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ enhanced-resolve: 5.24.3
+ jiti: 2.7.0
+ lightningcss: 1.32.0
+ magic-string: 0.30.21
+ source-map-js: 1.2.1
+ tailwindcss: 4.3.3
+
+ '@tailwindcss/oxide-android-arm64@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-arm64@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-x64@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-freebsd-x64@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-musl@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-wasm32-wasi@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide@4.3.3':
+ optionalDependencies:
+ '@tailwindcss/oxide-android-arm64': 4.3.3
+ '@tailwindcss/oxide-darwin-arm64': 4.3.3
+ '@tailwindcss/oxide-darwin-x64': 4.3.3
+ '@tailwindcss/oxide-freebsd-x64': 4.3.3
+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3
+ '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3
+ '@tailwindcss/oxide-linux-arm64-musl': 4.3.3
+ '@tailwindcss/oxide-linux-x64-gnu': 4.3.3
+ '@tailwindcss/oxide-linux-x64-musl': 4.3.3
+ '@tailwindcss/oxide-wasm32-wasi': 4.3.3
+ '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3
+ '@tailwindcss/oxide-win32-x64-msvc': 4.3.3
+
+ '@tailwindcss/vite@4.3.3(vite@8.1.5(@types/node@24.13.3)(jiti@2.7.0))':
+ dependencies:
+ '@tailwindcss/node': 4.3.3
+ '@tailwindcss/oxide': 4.3.3
+ tailwindcss: 4.3.3
+ vite: 8.1.5(@types/node@24.13.3)(jiti@2.7.0)
+
+ '@tanstack/history@1.162.0': {}
+
+ '@tanstack/query-core@5.101.4': {}
+
+ '@tanstack/query-devtools@5.101.4': {}
+
+ '@tanstack/react-query-devtools@5.101.4(@tanstack/react-query@5.101.4(react@19.2.8))(react@19.2.8)':
+ dependencies:
+ '@tanstack/query-devtools': 5.101.4
+ '@tanstack/react-query': 5.101.4(react@19.2.8)
+ react: 19.2.8
+
+ '@tanstack/react-query@5.101.4(react@19.2.8)':
+ dependencies:
+ '@tanstack/query-core': 5.101.4
+ react: 19.2.8
+
+ '@tanstack/react-router-devtools@1.167.0(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@tanstack/router-core@1.171.15)(csstype@3.2.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
+ dependencies:
+ '@tanstack/react-router': 1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ '@tanstack/router-devtools-core': 1.168.0(@tanstack/router-core@1.171.15)(csstype@3.2.3)
+ react: 19.2.8
+ react-dom: 19.2.8(react@19.2.8)
+ optionalDependencies:
+ '@tanstack/router-core': 1.171.15
+ transitivePeerDependencies:
+ - csstype
+
+ '@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
+ dependencies:
+ '@tanstack/history': 1.162.0
+ '@tanstack/react-store': 0.9.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ '@tanstack/router-core': 1.171.15
+ isbot: 5.2.1
+ react: 19.2.8
+ react-dom: 19.2.8(react@19.2.8)
+
+ '@tanstack/react-store@0.9.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
+ dependencies:
+ '@tanstack/store': 0.9.3
+ react: 19.2.8
+ react-dom: 19.2.8(react@19.2.8)
+ use-sync-external-store: 1.6.0(react@19.2.8)
+
+ '@tanstack/router-core@1.171.15':
+ dependencies:
+ '@tanstack/history': 1.162.0
+ cookie-es: 3.1.1
+ seroval: 1.5.6
+ seroval-plugins: 1.5.6(seroval@1.5.6)
+
+ '@tanstack/router-devtools-core@1.168.0(@tanstack/router-core@1.171.15)(csstype@3.2.3)':
+ dependencies:
+ '@tanstack/router-core': 1.171.15
+ clsx: 2.1.1
+ goober: 2.1.19(csstype@3.2.3)
+ optionalDependencies:
+ csstype: 3.2.3
+
+ '@tanstack/router-generator@1.167.21(supports-color@10.2.2)':
+ dependencies:
+ '@babel/types': 7.29.7
+ '@tanstack/router-core': 1.171.15
+ '@tanstack/router-utils': 1.162.2(supports-color@10.2.2)
+ '@tanstack/virtual-file-routes': 1.162.0
+ jiti: 2.7.0
+ magic-string: 0.30.21
+ prettier: 3.9.6
+ zod: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@tanstack/router-plugin@1.168.23(@tanstack/react-router@1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(rolldown@1.1.5)(supports-color@10.2.2)(vite@8.1.5(@types/node@24.13.3)(jiti@2.7.0))':
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
+ '@tanstack/router-core': 1.171.15
+ '@tanstack/router-generator': 1.167.21(supports-color@10.2.2)
+ '@tanstack/router-utils': 1.162.2(supports-color@10.2.2)
+ chokidar: 5.0.0
+ unplugin: 3.3.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(jiti@2.7.0))
+ zod: 4.4.3
+ optionalDependencies:
+ '@tanstack/react-router': 1.170.18(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ vite: 8.1.5(@types/node@24.13.3)(jiti@2.7.0)
+ transitivePeerDependencies:
+ - '@farmfe/core'
+ - '@rspack/core'
+ - bun-types-no-globals
+ - esbuild
+ - rolldown
+ - rollup
+ - supports-color
+ - unloader
+
+ '@tanstack/router-utils@1.162.2(supports-color@10.2.2)':
+ dependencies:
+ '@babel/generator': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+ ansis: 4.3.1
+ babel-dead-code-elimination: 1.0.12(supports-color@10.2.2)
+ diff: 8.0.4
+ pathe: 2.0.3
+ tinyglobby: 0.2.17
+ transitivePeerDependencies:
+ - supports-color
+
+ '@tanstack/store@0.9.3': {}
+
+ '@tanstack/virtual-file-routes@1.162.0': {}
+
+ '@ts-morph/common@0.27.0':
+ dependencies:
+ fast-glob: 3.3.3
+ minimatch: 10.2.5
+ path-browserify: 1.0.1
+
+ '@tybys/wasm-util@0.10.3':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@types/debug@4.1.13':
+ dependencies:
+ '@types/ms': 2.1.0
+
+ '@types/estree-jsx@1.0.5':
+ dependencies:
+ '@types/estree': 1.0.9
+
+ '@types/estree@1.0.9': {}
+
+ '@types/hast@3.0.5':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/mdast@4.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/ms@2.1.0': {}
+
+ '@types/node@24.13.3':
+ dependencies:
+ undici-types: 7.18.2
+
+ '@types/react-dom@19.2.3(@types/react@19.2.17)':
+ dependencies:
+ '@types/react': 19.2.17
+
+ '@types/react@19.2.17':
+ dependencies:
+ csstype: 3.2.3
+
+ '@types/unist@2.0.11': {}
+
+ '@types/unist@3.0.3': {}
+
+ '@types/validate-npm-package-name@4.0.2': {}
+
+ '@typescript/typescript-aix-ppc64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-darwin-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-darwin-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-freebsd-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-freebsd-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-arm@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-loong64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-mips64el@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-ppc64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-riscv64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-s390x@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-netbsd-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-netbsd-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-openbsd-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-openbsd-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-sunos-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-win32-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-win32-x64@7.0.2':
+ optional: true
+
+ '@ungap/structured-clone@1.3.3': {}
+
+ '@vitejs/plugin-react@6.0.4(vite@8.1.5(@types/node@24.13.3)(jiti@2.7.0))':
+ dependencies:
+ '@rolldown/pluginutils': 1.0.1
+ vite: 8.1.5(@types/node@24.13.3)(jiti@2.7.0)
+
+ accepts@2.0.0:
+ dependencies:
+ mime-types: 3.0.2
+ negotiator: 1.0.0
+
+ ajv-formats@2.1.1(ajv@8.20.0):
+ optionalDependencies:
+ ajv: 8.20.0
+
+ ajv-formats@3.0.1(ajv@8.20.0):
+ optionalDependencies:
+ ajv: 8.20.0
+
+ ajv@8.20.0:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-uri: 3.1.4
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+
+ ansi-colors@4.1.3: {}
+
+ ansi-regex@5.0.1: {}
+
+ ansi-regex@6.2.2: {}
+
+ ansis@4.3.1: {}
+
+ argparse@2.0.1: {}
+
+ ast-types@0.16.1:
+ dependencies:
+ tslib: 2.8.1
+
+ atomically@1.7.0: {}
+
+ babel-dead-code-elimination@1.0.12(supports-color@10.2.2):
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/parser': 7.29.7
+ '@babel/traverse': 7.29.7(supports-color@10.2.2)
+ '@babel/types': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
+ bail@2.0.2: {}
+
+ balanced-match@4.0.4: {}
+
+ baseline-browser-mapping@2.11.1: {}
+
+ body-parser@2.3.0(supports-color@10.2.2):
+ dependencies:
+ bytes: 3.1.2
+ content-type: 2.0.0
+ debug: 4.4.3(supports-color@10.2.2)
+ 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.8:
+ dependencies:
+ balanced-match: 4.0.4
+
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
+ browserslist@4.28.7:
+ dependencies:
+ baseline-browser-mapping: 2.11.1
+ caniuse-lite: 1.0.30001806
+ electron-to-chromium: 1.5.396
+ node-releases: 2.0.51
+ update-browserslist-db: 1.2.3(browserslist@4.28.7)
+
+ bundle-name@4.1.0:
+ dependencies:
+ run-applescript: 7.1.0
+
+ bytes@3.1.2: {}
+
+ call-bind-apply-helpers@1.0.2:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+
+ call-bound@1.0.4:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ get-intrinsic: 1.3.0
+
+ callsites@3.1.0: {}
+
+ caniuse-lite@1.0.30001806: {}
+
+ ccount@2.0.1: {}
+
+ chalk@5.6.2: {}
+
+ character-entities-html4@2.1.0: {}
+
+ character-entities-legacy@3.0.0: {}
+
+ character-entities@2.0.2: {}
+
+ character-reference-invalid@2.0.1: {}
+
+ chokidar@5.0.0:
+ dependencies:
+ readdirp: 5.0.0
+
+ class-variance-authority@0.7.1:
+ dependencies:
+ clsx: 2.1.1
+
+ cli-cursor@5.0.0:
+ dependencies:
+ restore-cursor: 5.1.0
+
+ cli-spinners@2.9.2: {}
+
+ clsx@2.1.1: {}
+
+ code-block-writer@13.0.3: {}
+
+ comma-separated-tokens@2.0.3: {}
+
+ commander@11.1.0: {}
+
+ commander@14.0.3: {}
+
+ conf@10.2.0:
+ dependencies:
+ ajv: 8.20.0
+ ajv-formats: 2.1.1(ajv@8.20.0)
+ atomically: 1.7.0
+ debounce-fn: 4.0.0
+ dot-prop: 6.0.1
+ env-paths: 2.2.1
+ json-schema-typed: 7.0.3
+ onetime: 5.1.2
+ pkg-up: 3.1.0
+ semver: 7.8.5
+
+ content-disposition@1.1.0: {}
+
+ content-type@1.0.5: {}
+
+ content-type@2.0.0: {}
+
+ convert-source-map@2.0.0: {}
+
+ cookie-es@3.1.1: {}
+
+ cookie-signature@1.2.2: {}
+
+ cookie@0.7.2: {}
+
+ cors@2.8.6:
+ dependencies:
+ object-assign: 4.1.1
+ vary: 1.1.2
+
+ cosmiconfig@9.0.2(typescript@7.0.2):
+ dependencies:
+ env-paths: 2.2.1
+ import-fresh: 3.3.1
+ js-yaml: 4.3.0
+ parse-json: 5.2.0
+ optionalDependencies:
+ typescript: 7.0.2
+
+ cross-spawn@7.0.6:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ cssesc@3.0.0: {}
+
+ csstype@3.2.3: {}
+
+ debounce-fn@4.0.0:
+ dependencies:
+ mimic-fn: 3.1.0
+
+ debug@4.4.3(supports-color@10.2.2):
+ dependencies:
+ ms: 2.1.3
+ optionalDependencies:
+ supports-color: 10.2.2
+
+ decode-named-character-reference@1.3.0:
+ dependencies:
+ character-entities: 2.0.2
+
+ dedent@1.7.2: {}
+
+ deepmerge@4.3.1: {}
+
+ default-browser-id@5.0.1: {}
+
+ default-browser@5.5.0:
+ dependencies:
+ bundle-name: 4.1.0
+ default-browser-id: 5.0.1
+
+ define-lazy-prop@2.0.0: {}
+
+ define-lazy-prop@3.0.0: {}
+
+ depd@2.0.0: {}
+
+ dequal@2.0.3: {}
+
+ detect-libc@2.1.2: {}
+
+ devlop@1.1.0:
+ dependencies:
+ dequal: 2.0.3
+
+ diff@8.0.4: {}
+
+ dot-prop@6.0.1:
+ dependencies:
+ is-obj: 2.0.0
+
+ dotenv@17.4.2: {}
+
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ ee-first@1.1.1: {}
+
+ electron-to-chromium@1.5.396: {}
+
+ emoji-regex@10.6.0: {}
+
+ encodeurl@2.0.0: {}
+
+ enhanced-resolve@5.24.3:
+ dependencies:
+ graceful-fs: 4.2.11
+ tapable: 2.3.3
+
+ enquirer@2.4.1:
+ dependencies:
+ ansi-colors: 4.1.3
+ strip-ansi: 6.0.1
+
+ env-paths@2.2.1: {}
+
+ error-ex@1.3.4:
+ dependencies:
+ is-arrayish: 0.2.1
+
+ es-define-property@1.0.1: {}
+
+ es-errors@1.3.0: {}
+
+ es-object-atoms@1.1.2:
+ dependencies:
+ es-errors: 1.3.0
+
+ escalade@3.2.0: {}
+
+ escape-html@1.0.3: {}
+
+ escape-string-regexp@5.0.0: {}
+
+ esprima@4.0.1: {}
+
+ estree-util-is-identifier-name@3.0.0: {}
+
+ etag@1.8.1: {}
+
+ eventsource-parser@3.1.0: {}
+
+ eventsource@3.0.7:
+ dependencies:
+ eventsource-parser: 3.1.0
+
+ execa@5.1.1:
+ dependencies:
+ cross-spawn: 7.0.6
+ get-stream: 6.0.1
+ human-signals: 2.1.0
+ is-stream: 2.0.1
+ merge-stream: 2.0.0
+ npm-run-path: 4.0.1
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ strip-final-newline: 2.0.0
+
+ execa@9.6.1:
+ dependencies:
+ '@sindresorhus/merge-streams': 4.0.0
+ cross-spawn: 7.0.6
+ figures: 6.1.0
+ get-stream: 9.0.1
+ human-signals: 8.0.1
+ is-plain-obj: 4.1.0
+ is-stream: 4.0.1
+ npm-run-path: 6.0.0
+ pretty-ms: 9.3.0
+ signal-exit: 4.1.0
+ strip-final-newline: 4.0.0
+ yoctocolors: 2.1.2
+
+ express-rate-limit@8.6.0(express@5.2.1(supports-color@10.2.2))(supports-color@10.2.2):
+ dependencies:
+ debug: 4.4.3(supports-color@10.2.2)
+ express: 5.2.1(supports-color@10.2.2)
+ ip-address: 10.2.0
+ transitivePeerDependencies:
+ - supports-color
+
+ express@5.2.1(supports-color@10.2.2):
+ dependencies:
+ accepts: 2.0.0
+ body-parser: 2.3.0(supports-color@10.2.2)
+ content-disposition: 1.1.0
+ content-type: 1.0.5
+ cookie: 0.7.2
+ cookie-signature: 1.2.2
+ debug: 4.4.3(supports-color@10.2.2)
+ depd: 2.0.0
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ finalhandler: 2.1.1(supports-color@10.2.2)
+ 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(supports-color@10.2.2)
+ send: 1.2.1(supports-color@10.2.2)
+ serve-static: 2.2.1(supports-color@10.2.2)
+ statuses: 2.0.2
+ type-is: 2.1.0
+ vary: 1.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ extend@3.0.2: {}
+
+ fast-deep-equal@3.1.3: {}
+
+ fast-glob@3.3.3:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
+ fast-uri@3.1.4: {}
+
+ fastq@1.20.1:
+ dependencies:
+ reusify: 1.1.0
+
+ fdir@6.5.0(picomatch@4.0.5):
+ optionalDependencies:
+ picomatch: 4.0.5
+
+ figures@6.1.0:
+ dependencies:
+ is-unicode-supported: 2.1.0
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ finalhandler@2.1.1(supports-color@10.2.2):
+ dependencies:
+ debug: 4.4.3(supports-color@10.2.2)
+ 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@3.0.0:
+ dependencies:
+ locate-path: 3.0.0
+
+ forwarded@0.2.0: {}
+
+ fresh@2.0.0: {}
+
+ fs-extra@11.4.0:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 6.2.1
+ universalify: 2.0.1
+
+ fsevents@2.3.3:
+ optional: true
+
+ function-bind@1.1.2: {}
+
+ fuzzysort@3.1.0: {}
+
+ gensync@1.0.0-beta.2: {}
+
+ get-east-asian-width@1.6.0: {}
+
+ get-intrinsic@1.3.0:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.2
+ function-bind: 1.1.2
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.4
+ math-intrinsics: 1.1.0
+
+ get-own-enumerable-keys@1.0.0: {}
+
+ get-proto@1.0.1:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.2
+
+ get-stream@6.0.1: {}
+
+ get-stream@9.0.1:
+ dependencies:
+ '@sec-ant/readable-stream': 0.4.1
+ is-stream: 4.0.1
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ goober@2.1.19(csstype@3.2.3):
+ dependencies:
+ csstype: 3.2.3
+
+ gopd@1.2.0: {}
+
+ graceful-fs@4.2.11: {}
+
+ has-symbols@1.1.0: {}
+
+ hasown@2.0.4:
+ dependencies:
+ function-bind: 1.1.2
+
+ hast-util-to-jsx-runtime@2.3.6(supports-color@10.2.2):
+ dependencies:
+ '@types/estree': 1.0.9
+ '@types/hast': 3.0.5
+ '@types/unist': 3.0.3
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ hast-util-whitespace: 3.0.0
+ mdast-util-mdx-expression: 2.0.1(supports-color@10.2.2)
+ mdast-util-mdx-jsx: 3.2.0(supports-color@10.2.2)
+ mdast-util-mdxjs-esm: 2.0.1(supports-color@10.2.2)
+ property-information: 7.2.0
+ space-separated-tokens: 2.0.2
+ style-to-js: 1.1.21
+ unist-util-position: 5.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ hast-util-whitespace@3.0.0:
+ dependencies:
+ '@types/hast': 3.0.5
+
+ hono@4.12.32: {}
+
+ html-url-attributes@3.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
+
+ human-signals@2.1.0: {}
+
+ human-signals@8.0.1: {}
+
+ iconv-lite@0.7.3:
+ dependencies:
+ safer-buffer: 2.1.2
+
+ ignore@5.3.2: {}
+
+ import-fresh@3.3.1:
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+
+ inherits@2.0.4: {}
+
+ inline-style-parser@0.2.7: {}
+
+ ip-address@10.2.0: {}
+
+ ipaddr.js@1.9.1: {}
+
+ is-alphabetical@2.0.1: {}
+
+ is-alphanumerical@2.0.1:
+ dependencies:
+ is-alphabetical: 2.0.1
+ is-decimal: 2.0.1
+
+ is-arrayish@0.2.1: {}
+
+ is-decimal@2.0.1: {}
+
+ is-docker@2.2.1: {}
+
+ is-docker@3.0.0: {}
+
+ is-extglob@2.1.1: {}
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-hexadecimal@2.0.1: {}
+
+ is-in-ssh@1.0.0: {}
+
+ is-inside-container@1.0.0:
+ dependencies:
+ is-docker: 3.0.0
+
+ is-interactive@2.0.0: {}
+
+ is-number@7.0.0: {}
+
+ is-obj@2.0.0: {}
+
+ is-obj@3.0.0: {}
+
+ is-plain-obj@4.1.0: {}
+
+ is-promise@4.0.0: {}
+
+ is-regexp@3.1.0: {}
+
+ is-stream@2.0.1: {}
+
+ is-stream@4.0.1: {}
+
+ is-unicode-supported@1.3.0: {}
+
+ is-unicode-supported@2.1.0: {}
+
+ is-wsl@2.2.0:
+ dependencies:
+ is-docker: 2.2.1
+
+ is-wsl@3.1.1:
+ dependencies:
+ is-inside-container: 1.0.0
+
+ isbot@5.2.1: {}
+
+ isexe@2.0.0: {}
+
+ isexe@3.1.5: {}
+
+ jiti@2.7.0: {}
+
+ jose@6.2.4: {}
+
+ js-tokens@4.0.0: {}
+
+ js-yaml@4.3.0:
+ dependencies:
+ argparse: 2.0.1
+
+ jsesc@3.1.0: {}
+
+ json-parse-even-better-errors@2.3.1: {}
+
+ json-schema-traverse@1.0.0: {}
+
+ json-schema-typed@7.0.3: {}
+
+ json-schema-typed@8.0.2: {}
+
+ json5@2.2.3: {}
+
+ jsonfile@6.2.1:
+ dependencies:
+ universalify: 2.0.1
+ optionalDependencies:
+ graceful-fs: 4.2.11
+
+ kleur@3.0.3: {}
+
+ kleur@4.1.5: {}
+
+ lightningcss-android-arm64@1.32.0:
+ optional: true
+
+ lightningcss-android-arm64@1.33.0:
+ optional: true
+
+ lightningcss-darwin-arm64@1.32.0:
+ optional: true
+
+ lightningcss-darwin-arm64@1.33.0:
+ optional: true
+
+ lightningcss-darwin-x64@1.32.0:
+ optional: true
+
+ lightningcss-darwin-x64@1.33.0:
+ optional: true
+
+ lightningcss-freebsd-x64@1.32.0:
+ optional: true
+
+ lightningcss-freebsd-x64@1.33.0:
+ optional: true
+
+ lightningcss-linux-arm-gnueabihf@1.32.0:
+ optional: true
+
+ lightningcss-linux-arm-gnueabihf@1.33.0:
+ optional: true
+
+ lightningcss-linux-arm64-gnu@1.32.0:
+ optional: true
+
+ lightningcss-linux-arm64-gnu@1.33.0:
+ optional: true
+
+ lightningcss-linux-arm64-musl@1.32.0:
+ optional: true
+
+ lightningcss-linux-arm64-musl@1.33.0:
+ optional: true
+
+ lightningcss-linux-x64-gnu@1.32.0:
+ optional: true
+
+ lightningcss-linux-x64-gnu@1.33.0:
+ optional: true
+
+ lightningcss-linux-x64-musl@1.32.0:
+ optional: true
+
+ lightningcss-linux-x64-musl@1.33.0:
+ optional: true
+
+ lightningcss-win32-arm64-msvc@1.32.0:
+ optional: true
+
+ lightningcss-win32-arm64-msvc@1.33.0:
+ optional: true
+
+ lightningcss-win32-x64-msvc@1.32.0:
+ optional: true
+
+ lightningcss-win32-x64-msvc@1.33.0:
+ optional: true
+
+ lightningcss@1.32.0:
+ dependencies:
+ detect-libc: 2.1.2
+ optionalDependencies:
+ lightningcss-android-arm64: 1.32.0
+ lightningcss-darwin-arm64: 1.32.0
+ lightningcss-darwin-x64: 1.32.0
+ lightningcss-freebsd-x64: 1.32.0
+ lightningcss-linux-arm-gnueabihf: 1.32.0
+ lightningcss-linux-arm64-gnu: 1.32.0
+ lightningcss-linux-arm64-musl: 1.32.0
+ lightningcss-linux-x64-gnu: 1.32.0
+ lightningcss-linux-x64-musl: 1.32.0
+ lightningcss-win32-arm64-msvc: 1.32.0
+ lightningcss-win32-x64-msvc: 1.32.0
+
+ lightningcss@1.33.0:
+ dependencies:
+ detect-libc: 2.1.2
+ optionalDependencies:
+ lightningcss-android-arm64: 1.33.0
+ lightningcss-darwin-arm64: 1.33.0
+ lightningcss-darwin-x64: 1.33.0
+ lightningcss-freebsd-x64: 1.33.0
+ lightningcss-linux-arm-gnueabihf: 1.33.0
+ lightningcss-linux-arm64-gnu: 1.33.0
+ lightningcss-linux-arm64-musl: 1.33.0
+ lightningcss-linux-x64-gnu: 1.33.0
+ lightningcss-linux-x64-musl: 1.33.0
+ lightningcss-win32-arm64-msvc: 1.33.0
+ lightningcss-win32-x64-msvc: 1.33.0
+
+ lines-and-columns@1.2.4: {}
+
+ locate-path@3.0.0:
+ dependencies:
+ p-locate: 3.0.0
+ path-exists: 3.0.0
+
+ log-symbols@6.0.0:
+ dependencies:
+ chalk: 5.6.2
+ is-unicode-supported: 1.3.0
+
+ longest-streak@3.1.0: {}
+
+ lru-cache@5.1.1:
+ dependencies:
+ yallist: 3.1.1
+
+ lucide-react@1.26.0(react@19.2.8):
+ dependencies:
+ react: 19.2.8
+
+ magic-string@0.30.21:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ markdown-table@3.0.4: {}
+
+ math-intrinsics@1.1.0: {}
+
+ mdast-util-find-and-replace@3.0.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ escape-string-regexp: 5.0.0
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
+ mdast-util-from-markdown@2.0.3(supports-color@10.2.2):
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ mdast-util-to-string: 4.0.0
+ micromark: 4.0.2(supports-color@10.2.2)
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-decode-string: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-stringify-position: 4.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-find-and-replace: 3.0.2
+ micromark-util-character: 2.1.1
+
+ mdast-util-gfm-footnote@2.1.0(supports-color@10.2.2):
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
+ mdast-util-to-markdown: 2.1.2
+ micromark-util-normalize-identifier: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-strikethrough@2.0.0(supports-color@10.2.2):
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-table@2.0.0(supports-color@10.2.2):
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ markdown-table: 3.0.4
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-task-list-item@2.0.0(supports-color@10.2.2):
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm@3.1.0(supports-color@10.2.2):
+ dependencies:
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
+ mdast-util-gfm-autolink-literal: 2.0.1
+ mdast-util-gfm-footnote: 2.1.0(supports-color@10.2.2)
+ mdast-util-gfm-strikethrough: 2.0.0(supports-color@10.2.2)
+ mdast-util-gfm-table: 2.0.0(supports-color@10.2.2)
+ mdast-util-gfm-task-list-item: 2.0.0(supports-color@10.2.2)
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-expression@2.0.1(supports-color@10.2.2):
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.5
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-jsx@3.2.0(supports-color@10.2.2):
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.5
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
+ mdast-util-to-markdown: 2.1.2
+ parse-entities: 4.0.2
+ stringify-entities: 4.0.4
+ unist-util-stringify-position: 4.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdxjs-esm@2.0.1(supports-color@10.2.2):
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.5
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-phrasing@4.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ unist-util-is: 6.0.1
+
+ mdast-util-to-hast@13.2.1:
+ dependencies:
+ '@types/hast': 3.0.5
+ '@types/mdast': 4.0.4
+ '@ungap/structured-clone': 1.3.3
+ devlop: 1.1.0
+ micromark-util-sanitize-uri: 2.0.1
+ trim-lines: 3.0.1
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+
+ mdast-util-to-markdown@2.1.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ longest-streak: 3.1.0
+ mdast-util-phrasing: 4.1.0
+ mdast-util-to-string: 4.0.0
+ micromark-util-classify-character: 2.0.1
+ micromark-util-decode-string: 2.0.1
+ unist-util-visit: 5.1.0
+ zwitch: 2.0.4
+
+ mdast-util-to-string@4.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+
+ media-typer@1.1.1: {}
+
+ merge-descriptors@2.0.0: {}
+
+ merge-stream@2.0.0: {}
+
+ merge2@1.4.1: {}
+
+ micromark-core-commonmark@2.0.3:
+ dependencies:
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ micromark-factory-destination: 2.0.1
+ micromark-factory-label: 2.0.1
+ micromark-factory-space: 2.0.1
+ micromark-factory-title: 2.0.1
+ micromark-factory-whitespace: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-chunked: 2.0.1
+ micromark-util-classify-character: 2.0.1
+ micromark-util-html-tag-name: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-subtokenize: 2.1.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-autolink-literal@2.1.0:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-footnote@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-strikethrough@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-chunked: 2.0.1
+ micromark-util-classify-character: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-table@2.1.1:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-tagfilter@2.0.0:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm@3.0.0:
+ dependencies:
+ micromark-extension-gfm-autolink-literal: 2.1.0
+ micromark-extension-gfm-footnote: 2.1.0
+ micromark-extension-gfm-strikethrough: 2.1.0
+ micromark-extension-gfm-table: 2.1.1
+ micromark-extension-gfm-tagfilter: 2.0.0
+ micromark-extension-gfm-task-list-item: 2.1.0
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-destination@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-label@2.0.1:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-space@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-title@2.0.1:
+ dependencies:
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-whitespace@2.0.1:
+ dependencies:
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-character@2.1.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-chunked@2.0.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-classify-character@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-combine-extensions@2.0.1:
+ dependencies:
+ micromark-util-chunked: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-decode-numeric-character-reference@2.0.2:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-decode-string@2.0.1:
+ dependencies:
+ decode-named-character-reference: 1.3.0
+ micromark-util-character: 2.1.1
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-encode@2.0.1: {}
+
+ micromark-util-html-tag-name@2.0.1: {}
+
+ micromark-util-normalize-identifier@2.0.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-resolve-all@2.0.1:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-util-sanitize-uri@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-encode: 2.0.1
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-subtokenize@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-chunked: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-symbol@2.0.1: {}
+
+ micromark-util-types@2.0.2: {}
+
+ micromark@4.0.2(supports-color@10.2.2):
+ dependencies:
+ '@types/debug': 4.1.13
+ debug: 4.4.3(supports-color@10.2.2)
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-chunked: 2.0.1
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-encode: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-subtokenize: 2.1.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ micromatch@4.0.8:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.2
+
+ mime-db@1.54.0: {}
+
+ mime-types@3.0.2:
+ dependencies:
+ mime-db: 1.54.0
+
+ mimic-fn@2.1.0: {}
+
+ mimic-fn@3.1.0: {}
+
+ mimic-function@5.0.1: {}
+
+ minimatch@10.2.5:
+ dependencies:
+ brace-expansion: 5.0.8
+
+ minimist@1.2.8: {}
+
+ ms@2.1.3: {}
+
+ nanoid@3.3.16: {}
+
+ negotiator@1.0.0: {}
+
+ node-releases@2.0.51: {}
+
+ npm-run-path@4.0.1:
+ dependencies:
+ path-key: 3.1.1
+
+ npm-run-path@6.0.0:
+ dependencies:
+ path-key: 4.0.0
+ unicorn-magic: 0.3.0
+
+ object-assign@4.1.1: {}
+
+ object-inspect@1.13.4: {}
+
+ object-treeify@1.1.33: {}
+
+ on-finished@2.4.1:
+ dependencies:
+ ee-first: 1.1.1
+
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ onetime@5.1.2:
+ dependencies:
+ mimic-fn: 2.1.0
+
+ onetime@7.0.0:
+ dependencies:
+ mimic-function: 5.0.1
+
+ open@11.0.0:
+ dependencies:
+ default-browser: 5.5.0
+ define-lazy-prop: 3.0.0
+ is-in-ssh: 1.0.0
+ is-inside-container: 1.0.0
+ powershell-utils: 0.1.0
+ wsl-utils: 0.3.1
+
+ open@8.4.2:
+ dependencies:
+ define-lazy-prop: 2.0.0
+ is-docker: 2.2.1
+ is-wsl: 2.2.0
+
+ openapi-fetch@0.17.0:
+ dependencies:
+ openapi-typescript-helpers: 0.1.0
+
+ openapi-typescript-helpers@0.1.0: {}
+
+ ora@8.2.0:
+ dependencies:
+ chalk: 5.6.2
+ cli-cursor: 5.0.0
+ cli-spinners: 2.9.2
+ is-interactive: 2.0.0
+ is-unicode-supported: 2.1.0
+ log-symbols: 6.0.0
+ stdin-discarder: 0.2.2
+ string-width: 7.2.0
+ strip-ansi: 7.2.0
+
+ oxlint-tsgolint@7.0.2001:
+ optionalDependencies:
+ '@oxlint-tsgolint/darwin-arm64': 7.0.2001
+ '@oxlint-tsgolint/darwin-x64': 7.0.2001
+ '@oxlint-tsgolint/linux-arm64': 7.0.2001
+ '@oxlint-tsgolint/linux-x64': 7.0.2001
+ '@oxlint-tsgolint/win32-arm64': 7.0.2001
+ '@oxlint-tsgolint/win32-x64': 7.0.2001
+
+ oxlint@1.75.0(oxlint-tsgolint@7.0.2001):
+ optionalDependencies:
+ '@oxlint/binding-android-arm-eabi': 1.75.0
+ '@oxlint/binding-android-arm64': 1.75.0
+ '@oxlint/binding-darwin-arm64': 1.75.0
+ '@oxlint/binding-darwin-x64': 1.75.0
+ '@oxlint/binding-freebsd-x64': 1.75.0
+ '@oxlint/binding-linux-arm-gnueabihf': 1.75.0
+ '@oxlint/binding-linux-arm-musleabihf': 1.75.0
+ '@oxlint/binding-linux-arm64-gnu': 1.75.0
+ '@oxlint/binding-linux-arm64-musl': 1.75.0
+ '@oxlint/binding-linux-ppc64-gnu': 1.75.0
+ '@oxlint/binding-linux-riscv64-gnu': 1.75.0
+ '@oxlint/binding-linux-riscv64-musl': 1.75.0
+ '@oxlint/binding-linux-s390x-gnu': 1.75.0
+ '@oxlint/binding-linux-x64-gnu': 1.75.0
+ '@oxlint/binding-linux-x64-musl': 1.75.0
+ '@oxlint/binding-openharmony-arm64': 1.75.0
+ '@oxlint/binding-win32-arm64-msvc': 1.75.0
+ '@oxlint/binding-win32-ia32-msvc': 1.75.0
+ '@oxlint/binding-win32-x64-msvc': 1.75.0
+ oxlint-tsgolint: 7.0.2001
+
+ p-limit@2.3.0:
+ dependencies:
+ p-try: 2.2.0
+
+ p-locate@3.0.0:
+ dependencies:
+ p-limit: 2.3.0
+
+ p-try@2.2.0: {}
+
+ parent-module@1.0.1:
+ dependencies:
+ callsites: 3.1.0
+
+ parse-entities@4.0.2:
+ dependencies:
+ '@types/unist': 2.0.11
+ character-entities-legacy: 3.0.0
+ character-reference-invalid: 2.0.1
+ decode-named-character-reference: 1.3.0
+ is-alphanumerical: 2.0.1
+ is-decimal: 2.0.1
+ is-hexadecimal: 2.0.1
+
+ parse-json@5.2.0:
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ error-ex: 1.3.4
+ json-parse-even-better-errors: 2.3.1
+ lines-and-columns: 1.2.4
+
+ parse-ms@4.0.0: {}
+
+ parseurl@1.3.3: {}
+
+ path-browserify@1.0.1: {}
+
+ path-exists@3.0.0: {}
+
+ path-key@3.1.1: {}
+
+ path-key@4.0.0: {}
+
+ path-to-regexp@8.4.2: {}
+
+ pathe@2.0.3: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@2.3.2: {}
+
+ picomatch@4.0.5: {}
+
+ pkce-challenge@5.0.1: {}
+
+ pkg-up@3.1.0:
+ dependencies:
+ find-up: 3.0.0
+
+ postcss-selector-parser@7.1.4:
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
+ postcss@8.5.23:
+ dependencies:
+ nanoid: 3.3.16
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ powershell-utils@0.1.0: {}
+
+ prettier-plugin-tailwindcss@0.8.1(prettier@3.9.6):
+ dependencies:
+ prettier: 3.9.6
+
+ prettier@3.9.6: {}
+
+ pretty-ms@9.3.0:
+ dependencies:
+ parse-ms: 4.0.0
+
+ prompts@2.4.2:
+ dependencies:
+ kleur: 3.0.3
+ sisteransi: 1.0.5
+
+ property-information@7.2.0: {}
+
+ proxy-addr@2.0.7:
+ dependencies:
+ forwarded: 0.2.0
+ ipaddr.js: 1.9.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-dom@19.2.8(react@19.2.8):
+ dependencies:
+ react: 19.2.8
+ scheduler: 0.27.0
+
+ react-hook-form@7.82.0(react@19.2.8):
+ dependencies:
+ react: 19.2.8
+
+ react-markdown@10.1.0(@types/react@19.2.17)(react@19.2.8)(supports-color@10.2.2):
+ dependencies:
+ '@types/hast': 3.0.5
+ '@types/mdast': 4.0.4
+ '@types/react': 19.2.17
+ devlop: 1.1.0
+ hast-util-to-jsx-runtime: 2.3.6(supports-color@10.2.2)
+ html-url-attributes: 3.0.1
+ mdast-util-to-hast: 13.2.1
+ react: 19.2.8
+ remark-parse: 11.0.0(supports-color@10.2.2)
+ remark-rehype: 11.1.2
+ unified: 11.0.5
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ react@19.2.8: {}
+
+ readdirp@5.0.0: {}
+
+ recast@0.23.12:
+ dependencies:
+ ast-types: 0.16.1
+ esprima: 4.0.1
+ source-map: 0.6.1
+ tiny-invariant: 1.3.3
+ tslib: 2.8.1
+
+ remark-gfm@4.0.1(supports-color@10.2.2):
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-gfm: 3.1.0(supports-color@10.2.2)
+ micromark-extension-gfm: 3.0.0
+ remark-parse: 11.0.0(supports-color@10.2.2)
+ remark-stringify: 11.0.0
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-parse@11.0.0(supports-color@10.2.2):
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
+ micromark-util-types: 2.0.2
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-rehype@11.1.2:
+ dependencies:
+ '@types/hast': 3.0.5
+ '@types/mdast': 4.0.4
+ mdast-util-to-hast: 13.2.1
+ unified: 11.0.5
+ vfile: 6.0.3
+
+ remark-stringify@11.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-to-markdown: 2.1.2
+ unified: 11.0.5
+
+ require-from-string@2.0.2: {}
+
+ reselect@5.2.0: {}
+
+ resolve-from@4.0.0: {}
+
+ restore-cursor@5.1.0:
+ dependencies:
+ onetime: 7.0.0
+ signal-exit: 4.1.0
+
+ reusify@1.1.0: {}
+
+ rolldown@1.1.5:
+ dependencies:
+ '@oxc-project/types': 0.139.0
+ '@rolldown/pluginutils': 1.0.1
+ optionalDependencies:
+ '@rolldown/binding-android-arm64': 1.1.5
+ '@rolldown/binding-darwin-arm64': 1.1.5
+ '@rolldown/binding-darwin-x64': 1.1.5
+ '@rolldown/binding-freebsd-x64': 1.1.5
+ '@rolldown/binding-linux-arm-gnueabihf': 1.1.5
+ '@rolldown/binding-linux-arm64-gnu': 1.1.5
+ '@rolldown/binding-linux-arm64-musl': 1.1.5
+ '@rolldown/binding-linux-ppc64-gnu': 1.1.5
+ '@rolldown/binding-linux-s390x-gnu': 1.1.5
+ '@rolldown/binding-linux-x64-gnu': 1.1.5
+ '@rolldown/binding-linux-x64-musl': 1.1.5
+ '@rolldown/binding-openharmony-arm64': 1.1.5
+ '@rolldown/binding-wasm32-wasi': 1.1.5
+ '@rolldown/binding-win32-arm64-msvc': 1.1.5
+ '@rolldown/binding-win32-x64-msvc': 1.1.5
+
+ router@2.2.0(supports-color@10.2.2):
+ dependencies:
+ debug: 4.4.3(supports-color@10.2.2)
+ depd: 2.0.0
+ is-promise: 4.0.0
+ parseurl: 1.3.3
+ path-to-regexp: 8.4.2
+ transitivePeerDependencies:
+ - supports-color
+
+ run-applescript@7.1.0: {}
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ safer-buffer@2.1.2: {}
+
+ scheduler@0.27.0: {}
+
+ semver@6.3.1: {}
+
+ semver@7.8.5: {}
+
+ send@1.2.1(supports-color@10.2.2):
+ dependencies:
+ debug: 4.4.3(supports-color@10.2.2)
+ 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
+
+ seroval-plugins@1.5.6(seroval@1.5.6):
+ dependencies:
+ seroval: 1.5.6
+
+ seroval@1.5.6: {}
+
+ serve-static@2.2.1(supports-color@10.2.2):
+ dependencies:
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ parseurl: 1.3.3
+ send: 1.2.1(supports-color@10.2.2)
+ transitivePeerDependencies:
+ - supports-color
+
+ setprototypeof@1.2.0: {}
+
+ shadcn@4.14.1(supports-color@10.2.2)(typescript@7.0.2):
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/parser': 7.29.7
+ '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@dotenvx/dotenvx': 1.75.1
+ '@modelcontextprotocol/sdk': 1.29.0(supports-color@10.2.2)(zod@3.25.76)
+ '@types/validate-npm-package-name': 4.0.2
+ browserslist: 4.28.7
+ commander: 14.0.3
+ cosmiconfig: 9.0.2(typescript@7.0.2)
+ dedent: 1.7.2
+ deepmerge: 4.3.1
+ diff: 8.0.4
+ execa: 9.6.1
+ fast-glob: 3.3.3
+ fs-extra: 11.4.0
+ fuzzysort: 3.1.0
+ kleur: 4.1.5
+ open: 11.0.0
+ ora: 8.2.0
+ postcss: 8.5.23
+ postcss-selector-parser: 7.1.4
+ prompts: 2.4.2
+ recast: 0.23.12
+ stringify-object: 5.0.0
+ tailwind-merge: 3.6.0
+ ts-morph: 26.0.0
+ tsconfig-paths: 4.2.0
+ undici: 7.29.0
+ validate-npm-package-name: 7.0.2
+ zod: 3.25.76
+ zod-to-json-schema: 3.25.2(zod@3.25.76)
+ transitivePeerDependencies:
+ - '@cfworker/json-schema'
+ - babel-plugin-macros
+ - supports-color
+ - typescript
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ side-channel-list@1.0.1:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-map@1.0.1:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-weakmap@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-map: 1.0.1
+
+ 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
+
+ signal-exit@3.0.7: {}
+
+ signal-exit@4.1.0: {}
+
+ sisteransi@1.0.5: {}
+
+ sonner@2.0.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
+ dependencies:
+ react: 19.2.8
+ react-dom: 19.2.8(react@19.2.8)
+
+ source-map-js@1.2.1: {}
+
+ source-map@0.6.1: {}
+
+ space-separated-tokens@2.0.2: {}
+
+ statuses@2.0.2: {}
+
+ stdin-discarder@0.2.2: {}
+
+ string-width@7.2.0:
+ dependencies:
+ emoji-regex: 10.6.0
+ get-east-asian-width: 1.6.0
+ strip-ansi: 7.2.0
+
+ stringify-entities@4.0.4:
+ dependencies:
+ character-entities-html4: 2.1.0
+ character-entities-legacy: 3.0.0
+
+ stringify-object@5.0.0:
+ dependencies:
+ get-own-enumerable-keys: 1.0.0
+ is-obj: 3.0.0
+ is-regexp: 3.1.0
+
+ strip-ansi@6.0.1:
+ dependencies:
+ ansi-regex: 5.0.1
+
+ strip-ansi@7.2.0:
+ dependencies:
+ ansi-regex: 6.2.2
+
+ strip-bom@3.0.0: {}
+
+ strip-final-newline@2.0.0: {}
+
+ strip-final-newline@4.0.0: {}
+
+ style-to-js@1.1.21:
+ dependencies:
+ style-to-object: 1.0.14
+
+ style-to-object@1.0.14:
+ dependencies:
+ inline-style-parser: 0.2.7
+
+ supports-color@10.2.2:
+ optional: true
+
+ systeminformation@5.33.1: {}
+
+ tailwind-merge@3.6.0: {}
+
+ tailwindcss@4.3.3: {}
+
+ tapable@2.3.3: {}
+
+ tiny-invariant@1.3.3: {}
+
+ tinyglobby@0.2.17:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.5)
+ picomatch: 4.0.5
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ toidentifier@1.0.1: {}
+
+ trim-lines@3.0.1: {}
+
+ trough@2.2.0: {}
+
+ ts-morph@26.0.0:
+ dependencies:
+ '@ts-morph/common': 0.27.0
+ code-block-writer: 13.0.3
+
+ tsconfig-paths@4.2.0:
+ dependencies:
+ json5: 2.2.3
+ minimist: 1.2.8
+ strip-bom: 3.0.0
+
+ tslib@2.8.1: {}
+
+ tw-animate-css@1.4.0: {}
+
+ type-is@2.1.0:
+ dependencies:
+ content-type: 2.0.0
+ media-typer: 1.1.1
+ mime-types: 3.0.2
+
+ typescript@7.0.2:
+ optionalDependencies:
+ '@typescript/typescript-aix-ppc64': 7.0.2
+ '@typescript/typescript-darwin-arm64': 7.0.2
+ '@typescript/typescript-darwin-x64': 7.0.2
+ '@typescript/typescript-freebsd-arm64': 7.0.2
+ '@typescript/typescript-freebsd-x64': 7.0.2
+ '@typescript/typescript-linux-arm': 7.0.2
+ '@typescript/typescript-linux-arm64': 7.0.2
+ '@typescript/typescript-linux-loong64': 7.0.2
+ '@typescript/typescript-linux-mips64el': 7.0.2
+ '@typescript/typescript-linux-ppc64': 7.0.2
+ '@typescript/typescript-linux-riscv64': 7.0.2
+ '@typescript/typescript-linux-s390x': 7.0.2
+ '@typescript/typescript-linux-x64': 7.0.2
+ '@typescript/typescript-netbsd-arm64': 7.0.2
+ '@typescript/typescript-netbsd-x64': 7.0.2
+ '@typescript/typescript-openbsd-arm64': 7.0.2
+ '@typescript/typescript-openbsd-x64': 7.0.2
+ '@typescript/typescript-sunos-x64': 7.0.2
+ '@typescript/typescript-win32-arm64': 7.0.2
+ '@typescript/typescript-win32-x64': 7.0.2
+
+ undici-types@7.18.2: {}
+
+ undici@7.29.0: {}
+
+ unicorn-magic@0.3.0: {}
+
+ unified@11.0.5:
+ dependencies:
+ '@types/unist': 3.0.3
+ bail: 2.0.2
+ devlop: 1.1.0
+ extend: 3.0.2
+ is-plain-obj: 4.1.0
+ trough: 2.2.0
+ vfile: 6.0.3
+
+ unist-util-is@6.0.1:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-stringify-position@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-visit-parents@6.0.2:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+
+ unist-util-visit@5.1.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
+ universalify@2.0.1: {}
+
+ unpipe@1.0.0: {}
+
+ unplugin@3.3.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(jiti@2.7.0)):
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ picomatch: 4.0.5
+ webpack-virtual-modules: 0.6.2
+ optionalDependencies:
+ rolldown: 1.1.5
+ vite: 8.1.5(@types/node@24.13.3)(jiti@2.7.0)
+
+ update-browserslist-db@1.2.3(browserslist@4.28.7):
+ dependencies:
+ browserslist: 4.28.7
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
+ use-sync-external-store@1.6.0(react@19.2.8):
+ dependencies:
+ react: 19.2.8
+
+ util-deprecate@1.0.2: {}
+
+ validate-npm-package-name@7.0.2: {}
+
+ vary@1.1.2: {}
+
+ vfile-message@4.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-stringify-position: 4.0.0
+
+ vfile@6.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ vfile-message: 4.0.3
+
+ vite@8.1.5(@types/node@24.13.3)(jiti@2.7.0):
+ dependencies:
+ lightningcss: 1.33.0
+ picomatch: 4.0.5
+ postcss: 8.5.23
+ rolldown: 1.1.5
+ tinyglobby: 0.2.17
+ optionalDependencies:
+ '@types/node': 24.13.3
+ fsevents: 2.3.3
+ jiti: 2.7.0
+
+ webpack-virtual-modules@0.6.2: {}
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ which@4.0.0:
+ dependencies:
+ isexe: 3.1.5
+
+ wrappy@1.0.2: {}
+
+ wsl-utils@0.3.1:
+ dependencies:
+ is-wsl: 3.1.1
+ powershell-utils: 0.1.0
+
+ yallist@3.1.1: {}
+
+ yocto-spinner@1.2.2:
+ dependencies:
+ yoctocolors: 2.1.2
+
+ yoctocolors@2.1.2: {}
+
+ zod-to-json-schema@3.25.2(zod@3.25.76):
+ dependencies:
+ zod: 3.25.76
+
+ zod@3.25.76: {}
+
+ zod@4.4.3: {}
+
+ zwitch@2.0.4: {}
diff --git a/web/pnpm-workspace.yaml b/web/pnpm-workspace.yaml
new file mode 100644
index 00000000..6afd1d41
--- /dev/null
+++ b/web/pnpm-workspace.yaml
@@ -0,0 +1,5 @@
+packages: []
+
+allowBuilds:
+ esbuild: true
+ msw: false
diff --git a/web/public/data/course_links.csv b/web/public/data/course_links.csv
new file mode 100644
index 00000000..610a76b1
--- /dev/null
+++ b/web/public/data/course_links.csv
@@ -0,0 +1,2023 @@
+course_code,course_name,link
+ACCT 201,Introduction to Accounting,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/351?entityType=Course&reportId=422
+ANT 101,Being Human: An Introduction to Four Field Anthropology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2880?entityType=Course&reportId=422
+ANT 110,Introduction to Sociocultural Anthropology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2403?entityType=Course&reportId=422
+ANT 140,World Prehistory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3021?entityType=Course&reportId=422
+ANT 160,Introduction to Biological Anthropology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3050?entityType=Course&reportId=422
+ANT 175,Introduction to Linguistic Anthropology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3181?entityType=Course&reportId=422
+ANT 204,Capitalism in Crisis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2404?entityType=Course&reportId=422
+ANT 214,Qualitative Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3022?entityType=Course&reportId=422
+ANT 215,What is Islam? Anthropological Perspectives,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3095?entityType=Course&reportId=422
+ANT 231,Frauds and Fallacies in Archaeology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2879?entityType=Course&reportId=422
+ANT 232,"Life, Death and Economy: Archaeology of Central Asia",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3016?entityType=Course&reportId=422
+ANT 233,"Cavemen, Mammoths, and Sabertooths: Stone Age Archaeology in Eurasia",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2346?entityType=Course&reportId=422
+ANT 240,Laboratory Methods in Archaeology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3020?entityType=Course&reportId=422
+ANT 262,Monkey Business: Primate Society and Behavior,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3051?entityType=Course&reportId=422
+ANT 270,Anthropology of Warfare,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3195?entityType=Course&reportId=422
+ANT 275,Language and Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3178?entityType=Course&reportId=422
+ANT 285,Food and Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2881?entityType=Course&reportId=422
+ANT 286,Nomads: Around the World and Through Time,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3019?entityType=Course&reportId=422
+ANT 306,Anthropology of Performance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3136?entityType=Course&reportId=422
+ANT 312,The Anthropology of Conflict,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3192?entityType=Course&reportId=422
+ANT 313,Islam and Politics in Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3193?entityType=Course&reportId=422
+ANT 314,Politics of Identity in Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3194?entityType=Course&reportId=422
+ANT 316,Bazaars and Museums: Material and Cultural Heritage in Central Asia and Beyond,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3137?entityType=Course&reportId=422
+ANT 331,Archaeology of Power and Inequality,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3015?entityType=Course&reportId=422
+ANT 333,Anthropology of Space,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3053?entityType=Course&reportId=422
+ANT 340,Method and Theory in Archaeology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3017?entityType=Course&reportId=422
+ANT 345,Archaeology Field School,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3018?entityType=Course&reportId=422
+ANT 361,"Human Evolution: Bones, Stones and Genomes",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3052?entityType=Course&reportId=422
+ANT 375,Inner Asian Frontiers of China: A Cultural Perspective,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3179?entityType=Course&reportId=422
+ANT 380,Linguistic and Cultural Diversity in Contemporary China: From Beijing to Xinjiang,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3180?entityType=Course&reportId=422
+ANT 385,Postcolonial Theory and its Applications in Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2405?entityType=Course&reportId=422
+ANT 386,Social Challenges of Climate Change,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2942?entityType=Course&reportId=422
+ANT 399,Special Topics in Anthropology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3094?entityType=Course&reportId=422
+ANT 400,Research Assistance in Anthropology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3054?entityType=Course&reportId=422
+ANT 401,Research Assistance in Anthropology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3055?entityType=Course&reportId=422
+ANT 402,Research Assistance in Anthropology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3056?entityType=Course&reportId=422
+ANT 403,Research Assistance in Anthropology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3057?entityType=Course&reportId=422
+ANT 404,Research Assistance in Anthropology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3058?entityType=Course&reportId=422
+ANT 412,Approaches to Global Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3023?entityType=Course&reportId=422
+ANT 420,Materiality and Eurasian Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3014?entityType=Course&reportId=422
+ANT 421,Sport and Construction of Identity,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3197?entityType=Course&reportId=422
+ANT 435,The Archaeology of Ritual,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2877?entityType=Course&reportId=422
+ANT 440,Skeletal Materials for Archaeologists,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3049?entityType=Course&reportId=422
+ANT 475,Digital Ethnographies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3024?entityType=Course&reportId=422
+ANT 481,Anthropology of Entrepreneurship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3025?entityType=Course&reportId=422
+ANT 482,"Climate Change, Future Energy, and Sustainability",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3026?entityType=Course&reportId=422
+ANT 483,Applied Public Heritage,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2878?entityType=Course&reportId=422
+ANT 498,Capstone Seminar I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2581?entityType=Course&reportId=422
+ANT 499,Capstone Seminar II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2401?entityType=Course&reportId=422
+ANT 506,Anthropology of Performance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3138?entityType=Course&reportId=422
+ANT 520,Materiality and Eurasian Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3013?entityType=Course&reportId=422
+ANT 521,Sport and Construction of Identity,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3196?entityType=Course&reportId=422
+ANT 535,The Archaeology of Ritual,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2876?entityType=Course&reportId=422
+ANT 585,Postcolonial Theory and Its Application in Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2402?entityType=Course&reportId=422
+BBA 201,Management and Organizations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/356?entityType=Course&reportId=422
+BBA 202,Business Communication,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/352?entityType=Course&reportId=422
+BBA 203,Responsible Leadership (Ethics),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/353?entityType=Course&reportId=422
+BBA 208,Data Analytics for Business,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1358?entityType=Course&reportId=422
+BBA 209,"Environmental, Social and Governance Factors (ESG) for Business",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/359?entityType=Course&reportId=422
+BBA 210,Fundamentals of Marketing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1329?entityType=Course&reportId=422
+BBA 230,Entrepreneurship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1330?entityType=Course&reportId=422
+BBA 240,Strategy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/357?entityType=Course&reportId=422
+BBA 260,Operations Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/361?entityType=Course&reportId=422
+BBA 310,BBA Elective I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/362?entityType=Course&reportId=422
+BBA 320,BBA Elective IV,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/363?entityType=Course&reportId=422
+BBA 321,BBA Elective II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/364?entityType=Course&reportId=422
+BBA 361,BBA Elective III,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/365?entityType=Course&reportId=422
+BBA 399,Internship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/366?entityType=Course&reportId=422
+BBA 499,Capstone,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/355?entityType=Course&reportId=422
+BIOL 101,Introductory Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2500?entityType=Course&reportId=422
+BIOL 105,General Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3003?entityType=Course&reportId=422
+BIOL 110,Modern Biology I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3004?entityType=Course&reportId=422
+BIOL 110L,Modern Biology I Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2501?entityType=Course&reportId=422
+BIOL 120,Modern Biology II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3281?entityType=Course&reportId=422
+BIOL 120L,Modern Biology II Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2368?entityType=Course&reportId=422
+BIOL 230,Human Anatomy and Physiology I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3177?entityType=Course&reportId=422
+BIOL 301,Molecular Cell Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2806?entityType=Course&reportId=422
+BIOL 301L,Molecular Cell Biology Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3040?entityType=Course&reportId=422
+BIOL 305,Introduction to Microbiology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2566?entityType=Course&reportId=422
+BIOL 305L,Introduction to Microbiology Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2567?entityType=Course&reportId=422
+BIOL 310,Immunology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3151?entityType=Course&reportId=422
+BIOL 320,Developmental Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3280?entityType=Course&reportId=422
+BIOL 321,Bioethics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3008?entityType=Course&reportId=422
+BIOL 331,Human Anatomy and Physiology II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3175?entityType=Course&reportId=422
+BIOL 331L,Human Anatomy and Physiology II Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3176?entityType=Course&reportId=422
+BIOL 333,Environmental Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2971?entityType=Course&reportId=422
+BIOL 340,Introduction to Bioinformatics with Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3229?entityType=Course&reportId=422
+BIOL 341,Biochemistry I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3155?entityType=Course&reportId=422
+BIOL 341L,Biochemistry I Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3156?entityType=Course&reportId=422
+BIOL 355,Critical Research Reasoning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3009?entityType=Course&reportId=422
+BIOL 363,Structural Bioinformatics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2702?entityType=Course&reportId=422
+BIOL 370,Genetics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3277?entityType=Course&reportId=422
+BIOL 370L,Genetics Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3168?entityType=Course&reportId=422
+BIOL 380,Biology of Behavior,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3171?entityType=Course&reportId=422
+BIOL 385,Cell Signaling: Principles and Mechanisms,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3276?entityType=Course&reportId=422
+BIOL 392,Directed Study in Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3172?entityType=Course&reportId=422
+BIOL 399,Biology Internship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2681?entityType=Course&reportId=422
+BIOL 425,Biomedical Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2656?entityType=Course&reportId=422
+BIOL 430,Histology with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3278?entityType=Course&reportId=422
+BIOL 440,Neuroscience,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3002?entityType=Course&reportId=422
+BIOL 444,Stem Cell Biology and Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2759?entityType=Course&reportId=422
+BIOL 445,Medical Microbiology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3275?entityType=Course&reportId=422
+BIOL 450,Food Microbiology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2568?entityType=Course&reportId=422
+BIOL 450L,Food Microbiology Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2569?entityType=Course&reportId=422
+BIOL 452,Biology of Cancer,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2682?entityType=Course&reportId=422
+BIOL 456,Biology Research Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2683?entityType=Course&reportId=422
+BIOL 460,Human Parasitology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3279?entityType=Course&reportId=422
+BIOL 468,Integrated Cell Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2760?entityType=Course&reportId=422
+BIOL 470,Advanced Cell Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2803?entityType=Course&reportId=422
+BIOL 471,Light and Electron Microscopy Concepts and Techniques,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2804?entityType=Course&reportId=422
+BIOL 471L,Light and Electron Microscopy Concepts and Techniques-Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3042?entityType=Course&reportId=422
+BIOL 480,Molecular Immunology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3154?entityType=Course&reportId=422
+BIOL 481,Neuroimmunology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2685?entityType=Course&reportId=422
+BIOL 490,Honors Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3000?entityType=Course&reportId=422
+BIOL 491,Honors Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3001?entityType=Course&reportId=422
+BIOL 492,Research Experience in Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2684?entityType=Course&reportId=422
+BIOL 502,Research Methods and Bioethics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3169?entityType=Course&reportId=422
+BIOL 520,Statistical Methods in Life Sciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3170?entityType=Course&reportId=422
+BIOL 550,Structural and Molecular Biology in Health and Disease,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2975?entityType=Course&reportId=422
+BIOL 560,Molecular Biology of Prokaryotic Cells,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2570?entityType=Course&reportId=422
+BIOL 570,Advanced Biotechnology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2805?entityType=Course&reportId=422
+BIOL 580,Applied Bioinformatics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3231?entityType=Course&reportId=422
+BIOL 590,Research Design and Project Planning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2700?entityType=Course&reportId=422
+BIOL 591,Cellular Biophysics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2976?entityType=Course&reportId=422
+BIOL 592,Graduate Research Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2977?entityType=Course&reportId=422
+BIOL 599,Master’s Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2701?entityType=Course&reportId=422
+BIOL 605,Radiation Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3010?entityType=Course&reportId=422
+BIOL 606,Advanced Environmental Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2974?entityType=Course&reportId=422
+BIOL 623,Advanced Immunology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3152?entityType=Course&reportId=422
+BIOL 630,Advanced Neuroscience,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3174?entityType=Course&reportId=422
+BIOL 631,Synthetic Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2703?entityType=Course&reportId=422
+BIOL 632,Drug Discovery and Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2704?entityType=Course&reportId=422
+BIOL 634,Advanced Cancer Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2655?entityType=Course&reportId=422
+BIOL 637,Fundamentals of Advanced Microscopy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2802?entityType=Course&reportId=422
+BIOL 637L,Fundamentals of Advanced Microscopy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3041?entityType=Course&reportId=422
+BIOL 670,Gene Therapy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2756?entityType=Course&reportId=422
+BIOL 675,Regenerative Medicine,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2757?entityType=Course&reportId=422
+BIOL 691,Master’s Thesis Research Proposal,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3256?entityType=Course&reportId=422
+BIOL 692,Master's Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3011?entityType=Course&reportId=422
+BIOL 800,Doctoral Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2705?entityType=Course&reportId=422
+BIOL 800,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3153?entityType=Course&reportId=422
+BIOL 805,Radiation Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3012?entityType=Course&reportId=422
+BIOL 820,Statistical Methods in Life Sciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3167?entityType=Course&reportId=422
+BIOL 830,Advanced Neuroscience,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3173?entityType=Course&reportId=422
+BIOL 831,Synthetic Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2706?entityType=Course&reportId=422
+BIOL 832,Drug Discovery and Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2707?entityType=Course&reportId=422
+BIOL 834,Advanced Cancer Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2654?entityType=Course&reportId=422
+BIOL 837,Advanced Optical and Electron Microscopy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2800?entityType=Course&reportId=422
+BIOL 850,Structural and Molecular Biology in Health and Disease,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2972?entityType=Course&reportId=422
+BIOL 860,Molecular Biology of Prokaryotic Cells,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2571?entityType=Course&reportId=422
+BIOL 870,Advanced Biotechnology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2801?entityType=Course&reportId=422
+BIOL 875,Gene Therapy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2758?entityType=Course&reportId=422
+BIOL 880,Applied Bioinformatics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3230?entityType=Course&reportId=422
+BIOL 891,Cellular Biophysics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2973?entityType=Course&reportId=422
+BUS 101,Core Course in Business,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/368?entityType=Course&reportId=422
+BUS 420,Business Law,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/724?entityType=Course&reportId=422
+CEE 200,Structural Mechanics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/946?entityType=Course&reportId=422
+CEE 201,Environmental Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1172?entityType=Course&reportId=422
+CEE 202,Environmental Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1304?entityType=Course&reportId=422
+CEE 203,Structural Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1047?entityType=Course&reportId=422
+CEE 204,Civil Engineering CAD and Surveying,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/953?entityType=Course&reportId=422
+CEE 300,Structural Design - Concrete,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1242?entityType=Course&reportId=422
+CEE 301,Structural Design - Steel,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1028?entityType=Course&reportId=422
+CEE 302,Geotechnical Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1278?entityType=Course&reportId=422
+CEE 303,Geotechnical Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1279?entityType=Course&reportId=422
+CEE 304,Fluid Mechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1060?entityType=Course&reportId=422
+CEE 305,Hydraulics and Hydrology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1061?entityType=Course&reportId=422
+CEE 306,Civil Engineering Materials,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/995?entityType=Course&reportId=422
+CEE 350,Water and Wastewater Treatment Processes,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1295?entityType=Course&reportId=422
+CEE 351,Application of Geomatics in Civil Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/998?entityType=Course&reportId=422
+CEE 352,Engineering Geology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1171?entityType=Course&reportId=422
+CEE 400,Transportation Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/996?entityType=Course&reportId=422
+CEE 401,Construction Technology and Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/861?entityType=Course&reportId=422
+CEE 450,Behavior and Design of Structural System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1026?entityType=Course&reportId=422
+CEE 454,Foundation Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3429?entityType=Course&reportId=422
+CEE 455,Solid & Hazardous Waste Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1170?entityType=Course&reportId=422
+CEE 457,Air Quality Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1062?entityType=Course&reportId=422
+CEE 458,Modern Information Technology in Construction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/903?entityType=Course&reportId=422
+CEE 460,Water Supply and Distribution Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1063?entityType=Course&reportId=422
+CEE 462,Pavement Design and Performance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/997?entityType=Course&reportId=422
+CEE 463,Individual Research Project in Civil & Environmental Engineering 1,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1087?entityType=Course&reportId=422
+CEE 464,Individual Research Project in Civil and Environmental Engineering II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1088?entityType=Course&reportId=422
+CEE 465,Structure and Properties of Concrete Materials,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1243?entityType=Course&reportId=422
+CEE 466,Introduction to Finite Element Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3446?entityType=Course&reportId=422
+CEE 467,Building Information Modelling for Geotechnical Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/904?entityType=Course&reportId=422
+CEE 468,Structural Design – Concrete II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1244?entityType=Course&reportId=422
+CHEM 090,Chemistry for Non-Science Majors,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3122?entityType=Course&reportId=422
+CHEM 091,Survey of Physical Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3157?entityType=Course&reportId=422
+CHEM 092,Survey of Environmental Sciences for Non-Science Majors,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3121?entityType=Course&reportId=422
+CHEM 101,General Chemistry I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2892?entityType=Course&reportId=422
+CHEM 101L,General Chemistry I Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3080?entityType=Course&reportId=422
+CHEM 102,General Chemistry II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2921?entityType=Course&reportId=422
+CHEM 189C,Independent Study,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2922?entityType=Course&reportId=422
+CHEM 211,Organic Chemistry I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2632?entityType=Course&reportId=422
+CHEM 211L,Organic Chemistry I Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2633?entityType=Course&reportId=422
+CHEM 212,Organic Chemistry II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2792?entityType=Course&reportId=422
+CHEM 212L,Organic Chemistry II Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2793?entityType=Course&reportId=422
+CHEM 220,Quantitative Chemical Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3075?entityType=Course&reportId=422
+CHEM 220L,Quantitative Chemical Analysis Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2408?entityType=Course&reportId=422
+CHEM 250,Descriptive Inorganic Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3158?entityType=Course&reportId=422
+CHEM 320,Instrumental Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3076?entityType=Course&reportId=422
+CHEM 320L,Instrumental Analysis Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3077?entityType=Course&reportId=422
+CHEM 331,Physical Chemistry I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2764?entityType=Course&reportId=422
+CHEM 331L,Physical Chemistry Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2765?entityType=Course&reportId=422
+CHEM 332,Physical Chemistry II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2766?entityType=Course&reportId=422
+CHEM 332L,Physical Chemistry II Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2767?entityType=Course&reportId=422
+CHEM 341,Biochemistry I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2672?entityType=Course&reportId=422
+CHEM 341L,Biochemistry I Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2673?entityType=Course&reportId=422
+CHEM 350,Advanced Inorganic Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2425?entityType=Course&reportId=422
+CHEM 350L,Advanced Inorganic Chemistry Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2370?entityType=Course&reportId=422
+CHEM 380,Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2426?entityType=Course&reportId=422
+CHEM 400,Chemistry Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3162?entityType=Course&reportId=422
+CHEM 410,Structural Spectroscopy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3109?entityType=Course&reportId=422
+CHEM 411,Advanced Organic Chemistry I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2631?entityType=Course&reportId=422
+CHEM 431,Computational Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2919?entityType=Course&reportId=422
+CHEM 432,Introduction to Cheminformatics and Computer Aided Drug Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2920?entityType=Course&reportId=422
+CHEM 433,Surfactants and Colloids,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3247?entityType=Course&reportId=422
+CHEM 442,Biochemistry II with Lab-Metabolic Biochemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2354?entityType=Course&reportId=422
+CHEM 451,Applied Homogenous Catalysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2427?entityType=Course&reportId=422
+CHEM 471,Environmental Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2918?entityType=Course&reportId=422
+CHEM 488,Directed Research I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3159?entityType=Course&reportId=422
+CHEM 489,Directed Research II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3160?entityType=Course&reportId=422
+CHEM 490,Nanochemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3161?entityType=Course&reportId=422
+CHEM 510,Principles of Physical Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2763?entityType=Course&reportId=422
+CHEM 511,Theoretical Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2913?entityType=Course&reportId=422
+CHEM 515,Applied Colloid and Surfactant Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3238?entityType=Course&reportId=422
+CHEM 518,Applied Polymer Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3239?entityType=Course&reportId=422
+CHEM 520,Applied Analytical Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3079?entityType=Course&reportId=422
+CHEM 522,Analytical Environmental Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2912?entityType=Course&reportId=422
+CHEM 530,Inorganic Structures and Reaction Mechanisms,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2434?entityType=Course&reportId=422
+CHEM 531,Nanochemistry and Functional Nanomaterials,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3164?entityType=Course&reportId=422
+CHEM 532,Organometallic Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2431?entityType=Course&reportId=422
+CHEM 540,Organic Reactions and Mechanisms,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2628?entityType=Course&reportId=422
+CHEM 541,Medicinal Chemistry and Drug Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2629?entityType=Course&reportId=422
+CHEM 543,Structural Identification of Organic Compounds,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3108?entityType=Course&reportId=422
+CHEM 550,Selected Topics in Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2432?entityType=Course&reportId=422
+CHEM 560,Directed Research in Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2433?entityType=Course&reportId=422
+CHEM 591,Scientific Methods in Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3240?entityType=Course&reportId=422
+CHEM 592,Chemistry Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3241?entityType=Course&reportId=422
+CHEM 691,Thesis Proposal,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3242?entityType=Course&reportId=422
+CHEM 692,MSc Thesis in Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3243?entityType=Course&reportId=422
+CHEM 700,Hot Topics in Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3245?entityType=Course&reportId=422
+CHEM 710,Mechanistic Principles of Organic Reactions,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2630?entityType=Course&reportId=422
+CHEM 711,Polymer Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3244?entityType=Course&reportId=422
+CHEM 720,Spectrochemical Methods of Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3078?entityType=Course&reportId=422
+CHEM 722,Advanced Environmental Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2914?entityType=Course&reportId=422
+CHEM 730,Chemical Thermodynamics and Kinetics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2768?entityType=Course&reportId=422
+CHEM 731,Design of Functional Materials,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2915?entityType=Course&reportId=422
+CHEM 733,Colloid and Surfactant Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3246?entityType=Course&reportId=422
+CHEM 740,Advanced Medicinal Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2355?entityType=Course&reportId=422
+CHEM 750,Modern Inorganic Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2430?entityType=Course&reportId=422
+CHEM 752,Materials Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3163?entityType=Course&reportId=422
+CHEM 753,Organometallic Catalysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2428?entityType=Course&reportId=422
+CHEM 780,Research Methods and Ethics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2429?entityType=Course&reportId=422
+CHEM 798,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2916?entityType=Course&reportId=422
+CHEM 800,Doctoral Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2917?entityType=Course&reportId=422
+CHME 200,Basic Principles and Calculations in Chemical Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/993?entityType=Course&reportId=422
+CHME 201,Chemical Engineering Thermodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1209?entityType=Course&reportId=422
+CHME 202,Fluid Mechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1301?entityType=Course&reportId=422
+CHME 203,Organic and Polymer Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/884?entityType=Course&reportId=422
+CHME 222,Inorganic and Analytical Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/905?entityType=Course&reportId=422
+CHME 300,Heat and Mass Transfer,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1232?entityType=Course&reportId=422
+CHME 301,Applied Mathematics for Process Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/982?entityType=Course&reportId=422
+CHME 302,Instrumental Methods of Analysis for Engineers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1008?entityType=Course&reportId=422
+CHME 303,Separation Processes,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1263?entityType=Course&reportId=422
+CHME 304,Chemical Reaction Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1264?entityType=Course&reportId=422
+CHME 305,Chemical Engineering Laboratory I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/883?entityType=Course&reportId=422
+CHME 351,Environment and Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1266?entityType=Course&reportId=422
+CHME 352,Research Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1324?entityType=Course&reportId=422
+CHME 353,Electrochemical Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/886?entityType=Course&reportId=422
+CHME 400,Process Design and Simulation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1025?entityType=Course&reportId=422
+CHME 401,Chemical Engineering Laboratory II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/885?entityType=Course&reportId=422
+CHME 402,Materials Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/889?entityType=Course&reportId=422
+CHME 403,Chemical Process Control and Safety,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1023?entityType=Course&reportId=422
+CHME 421,Tissue Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/994?entityType=Course&reportId=422
+CHME 453,Multiphase Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1233?entityType=Course&reportId=422
+CHME 454,Transport Phenomena and Operations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1234?entityType=Course&reportId=422
+CHME 459,Biomechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/992?entityType=Course&reportId=422
+CHME 461,Powder Technology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/981?entityType=Course&reportId=422
+CHME 464,Directed Study,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1024?entityType=Course&reportId=422
+CHME 485,Introduction to Biochemical Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1265?entityType=Course&reportId=422
+CHN 101,Beginning Mandarin I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2896?entityType=Course&reportId=422
+CHN 102,Beginning Mandarin II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2897?entityType=Course&reportId=422
+CHN 201,Intermediate Mandarin I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2898?entityType=Course&reportId=422
+CHN 202,Intermediate Mandarin II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2899?entityType=Course&reportId=422
+CHN 301,Upper Intermediate Chinese I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2900?entityType=Course&reportId=422
+CSCI 101,Introduction to Computational Sciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1167?entityType=Course&reportId=422
+CSCI 111,Web Programming and Problem Solving,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1129?entityType=Course&reportId=422
+CSCI 115,Programming Fundamentals,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1252?entityType=Course&reportId=422
+CSCI 151,Programming for Scientists and Engineers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/938?entityType=Course&reportId=422
+CSCI 152,Performance and Data Structures,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/970?entityType=Course&reportId=422
+CSCI 231,Computer Systems and Organization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1076?entityType=Course&reportId=422
+CSCI 235,Programming Languages,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/968?entityType=Course&reportId=422
+CSCI 245,System Analysis and Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/942?entityType=Course&reportId=422
+CSCI 262,Software Project Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/943?entityType=Course&reportId=422
+CSCI 270,Algorithms,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1168?entityType=Course&reportId=422
+CSCI 272,Formal Languages,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1084?entityType=Course&reportId=422
+CSCI 281,Human-Computer Interaction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/939?entityType=Course&reportId=422
+CSCI 299,Internship I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/969?entityType=Course&reportId=422
+CSCI 307,Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1176?entityType=Course&reportId=422
+CSCI 325,Introduction to Parallel Systems and GPU Programming,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1100?entityType=Course&reportId=422
+CSCI 330,Mobile Computing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1127?entityType=Course&reportId=422
+CSCI 332,Operating Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1041?entityType=Course&reportId=422
+CSCI 333,Computer Networks,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1251?entityType=Course&reportId=422
+CSCI 336,Ubiquity and Sensing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1226?entityType=Course&reportId=422
+CSCI 341,Database Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1314?entityType=Course&reportId=422
+CSCI 344,Data Mining and Decision Support,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1099?entityType=Course&reportId=422
+CSCI 355,Compiler Construction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1085?entityType=Course&reportId=422
+CSCI 361,Software Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1136?entityType=Course&reportId=422
+CSCI 363,Software Testing and Quality Assurance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/870?entityType=Course&reportId=422
+CSCI 371,Algorithmic Problem Solving,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1166?entityType=Course&reportId=422
+CSCI 390,Artificial Intelligence,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1186?entityType=Course&reportId=422
+CSCI 393,Introduction to Natural Language Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1212?entityType=Course&reportId=422
+CSCI 399,Internship II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/971?entityType=Course&reportId=422
+CSCI 399F,Internship II-F,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/972?entityType=Course&reportId=422
+CSCI 408,Senior Project I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/928?entityType=Course&reportId=422
+CSCI 409,Senior Project II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/929?entityType=Course&reportId=422
+CSCI 434,Information Security,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1177?entityType=Course&reportId=422
+CSCI 437,Internet of Things: Technologies and Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1040?entityType=Course&reportId=422
+CSCI 445,Bioinformatics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1255?entityType=Course&reportId=422
+CSCI 447,Machine Learning: Theory and Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1256?entityType=Course&reportId=422
+CSCI 455,Scripting Languages,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1124?entityType=Course&reportId=422
+CSCI 462,Open Source Software,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/940?entityType=Course&reportId=422
+CSCI 471,Complexity and Computability,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1165?entityType=Course&reportId=422
+CSCI 490,Brain Computer Interface,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1259?entityType=Course&reportId=422
+CSCI 494,Deep Learning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1137?entityType=Course&reportId=422
+CSCI 496,Generative Artificial Intelligence,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/926?entityType=Course&reportId=422
+CSCI 501,Software Principles and Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/974?entityType=Course&reportId=422
+CSCI 502,Hardware / Software Co-Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/914?entityType=Course&reportId=422
+CSCI 511,CS Track Core Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1083?entityType=Course&reportId=422
+CSCI 512,Information Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1039?entityType=Course&reportId=422
+CSCI 515,Modeling and Simulation for Computer Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/927?entityType=Course&reportId=422
+CSCI 531,Distributed Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1125?entityType=Course&reportId=422
+CSCI 535,Wireless Communication and Networks,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1227?entityType=Course&reportId=422
+CSCI 537,Software Defined Networking,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1126?entityType=Course&reportId=422
+CSCI 545,Big Data Analytics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1258?entityType=Course&reportId=422
+CSCI 547,Algorithmic Trading,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/871?entityType=Course&reportId=422
+CSCI 563,Software Testing and Quality Assurance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/975?entityType=Course&reportId=422
+CSCI 572,Cognitive Modelling for Human-Computer Interaction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/941?entityType=Course&reportId=422
+CSCI 575,Formal Methods and Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/973?entityType=Course&reportId=422
+CSCI 581,Acquisition and Analysis of Biomedical Data,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1257?entityType=Course&reportId=422
+CSCI 585,Computer Vision,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1102?entityType=Course&reportId=422
+CSCI 591,Advanced Artificial Intelligence,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1077?entityType=Course&reportId=422
+CSCI 592,Intelligent Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1078?entityType=Course&reportId=422
+CSCI 594,Deep Learning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/872?entityType=Course&reportId=422
+CSCI 595,Generative Artificial Intelligence,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1188?entityType=Course&reportId=422
+CSCI 693,Thesis Proposal,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1122?entityType=Course&reportId=422
+CSCI 694,Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1123?entityType=Course&reportId=422
+CSCI 700,Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1260?entityType=Course&reportId=422
+CSCI 700,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1261?entityType=Course&reportId=422
+CSCI 701,Advanced Software Principles and Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/967?entityType=Course&reportId=422
+CSCI 702,Advanced Hardware / Software Co-Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/913?entityType=Course&reportId=422
+CSCI 711,Advanced Theory of Computation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1086?entityType=Course&reportId=422
+CSCI 722,Current Research Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1075?entityType=Course&reportId=422
+CSCI 725,Advanced Quantum Computing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/867?entityType=Course&reportId=422
+CSCI 735,Advanced Wireless Communication and Networks,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1228?entityType=Course&reportId=422
+CSCI 737,Advanced Software Defined Networking,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1128?entityType=Course&reportId=422
+CSCI 745,Advanced Big Data Analytics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1101?entityType=Course&reportId=422
+CSCI 747,Advanced Algorithmic Trading,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/868?entityType=Course&reportId=422
+CSCI 772,Advanced Cognitive Modelling for Human-Computer Interaction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/937?entityType=Course&reportId=422
+CSCI 775,Advanced Formal Methods and Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/966?entityType=Course&reportId=422
+CSCI 781,Advanced Acquisition and Analysis of Biomedical Data,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1262?entityType=Course&reportId=422
+CSCI 785,Advanced Computer Vision,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/930?entityType=Course&reportId=422
+CSCI 791,Advanced Artificial Reasoning and Problem Solving,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1073?entityType=Course&reportId=422
+CSCI 792,Advanced Intelligent Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1074?entityType=Course&reportId=422
+CSCI 794,Advanced Deep Learning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/869?entityType=Course&reportId=422
+CSCI 795,Advanced Generative Artificial Intelligence,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1187?entityType=Course&reportId=422
+DCEE 700,Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1089?entityType=Course&reportId=422
+DCEE 700,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1090?entityType=Course&reportId=422
+DCEE 701,Current Research Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1091?entityType=Course&reportId=422
+DCEE 750,Finite Element Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1029?entityType=Course&reportId=422
+DCEE 751,Structural Dynamics and Earthquake Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3435?entityType=Course&reportId=422
+DCEE 752,Advanced Concrete Technology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/999?entityType=Course&reportId=422
+DCEE 753,Structural Evaluation and Rehabilitation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1245?entityType=Course&reportId=422
+DCEE 754,Theory of Physio-chemical Treatment Processes,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1296?entityType=Course&reportId=422
+DCEE 755,Contaminated Site Management and Soil Treatment Technologies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1169?entityType=Course&reportId=422
+DCEE 756,Environmental Modeling Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1059?entityType=Course&reportId=422
+DCEE 757,Advanced Environmental Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1298?entityType=Course&reportId=422
+DCEE 758,Computational Geomechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1275?entityType=Course&reportId=422
+DCEE 759,Geotechnical Earthquake Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1276?entityType=Course&reportId=422
+DCEE 760,Advanced Foundation Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/901?entityType=Course&reportId=422
+DCEE 761,Advanced Soil Mechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1274?entityType=Course&reportId=422
+DCEE 762,Advanced Project Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/862?entityType=Course&reportId=422
+DCEE 763,Building Information Modeling in Construction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1092?entityType=Course&reportId=422
+DCEE 765,Concrete Repair and Maintenance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1246?entityType=Course&reportId=422
+DCEE 766,"Advanced Pavement Design, Analysis, and Rehabilitation",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1000?entityType=Course&reportId=422
+DCEE 767,Advanced Concrete Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1031?entityType=Course&reportId=422
+DCEE 768,Advanced Wastewater Treatment,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1297?entityType=Course&reportId=422
+DCEE 769,Sustainable Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1057?entityType=Course&reportId=422
+DCEE 770,"Green Building - Concept, Design, Construction, and Operation",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1058?entityType=Course&reportId=422
+DCEE 771,Soil Improvement and Stabilization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1277?entityType=Course&reportId=422
+DCEE 772,Engineering Management and Engineering Economy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/863?entityType=Course&reportId=422
+DCEE 773,Unsaturated Soil Mechanics for Engineering Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/899?entityType=Course&reportId=422
+DCEE 774,Computational Modeling and Instrumentation in Geotechnical Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/900?entityType=Course&reportId=422
+DCHME 700,Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1207?entityType=Course&reportId=422
+DCHME 700,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1208?entityType=Course&reportId=422
+DCHME 701,Current Research Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/906?entityType=Course&reportId=422
+DCHME 752,Polymer Melt Fluid Mechanics and Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1299?entityType=Course&reportId=422
+DCHME 755,Integrated Computational Materials Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1300?entityType=Course&reportId=422
+DCHME 757,Advanced Chemical Engineering Thermodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1206?entityType=Course&reportId=422
+DCHME 761,Advanced Chemical Reaction Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1267?entityType=Course&reportId=422
+DCHME 762,Advanced Materials Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/907?entityType=Course&reportId=422
+DCHME 763,Advanced Heat and Mass Transfer,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1231?entityType=Course&reportId=422
+DCHME 766,Advanced Energy Materials and Their Application,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/908?entityType=Course&reportId=422
+DELCE 700,Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1149?entityType=Course&reportId=422
+DELCE 700,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1150?entityType=Course&reportId=422
+DELCE 701,Current Research Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1014?entityType=Course&reportId=422
+DELCE 753,Stochastic Processes,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/963?entityType=Course&reportId=422
+DELCE 758,Advanced Industrial and Commercial Energy Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1148?entityType=Course&reportId=422
+DELCE 759,Advanced Pattern Recognition and Machine Learning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/921?entityType=Course&reportId=422
+DELCE 760,Advanced System Modelling and Control,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1218?entityType=Course&reportId=422
+DELCE 761,Advanced Data Structures and Algorithms,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1270?entityType=Course&reportId=422
+DELCE 762,Fundamentals of Signal Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1204?entityType=Course&reportId=422
+DELCE 763,Advanced Electronic Circuits,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1189?entityType=Course&reportId=422
+DELCE 764,Advanced Semiconductor Process Engineering for VLSI,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/934?entityType=Course&reportId=422
+DENG 700,Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1107?entityType=Course&reportId=422
+DENG 700,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1108?entityType=Course&reportId=422
+DENG 701,Current Research Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1109?entityType=Course&reportId=422
+DENG 782,Research Methods and Ethics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/950?entityType=Course&reportId=422
+DENG 789,Doctoral Seminar I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1110?entityType=Course&reportId=422
+DENG 790,Doctoral Seminar II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1111?entityType=Course&reportId=422
+DENG 791,Doctoral Seminar III,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1112?entityType=Course&reportId=422
+DENG 792,Doctoral Seminar IV,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1113?entityType=Course&reportId=422
+DENG 793,Doctoral Seminar V,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1114?entityType=Course&reportId=422
+DMAE 700,Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1105?entityType=Course&reportId=422
+DMAE 700,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1106?entityType=Course&reportId=422
+DMAE 701,Advanced Applied Mathematics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1043?entityType=Course&reportId=422
+DMAE 702,Current Research Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/915?entityType=Course&reportId=422
+DMAE 703,Numerical Techniques for Engineers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1042?entityType=Course&reportId=422
+DMAE 704,Rocket Propulsion Fundamentals,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1016?entityType=Course&reportId=422
+DMAE 705,Sustainable Vehicle Transportation Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1017?entityType=Course&reportId=422
+DMAE 750,Advanced Statistics and Probability,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1312?entityType=Course&reportId=422
+DMAE 751,Modern Control Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1147?entityType=Course&reportId=422
+DMAE 753,Computational and Unsteady Aerodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/954?entityType=Course&reportId=422
+DMAE 756,Design and Manufacturing with Environmental Concern,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1103?entityType=Course&reportId=422
+DMAE 757,Design Optimization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1104?entityType=Course&reportId=422
+DMAE 759,Space Structures Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1049?entityType=Course&reportId=422
+DMAE 763,"Computational Fluid-Structure Interaction: Methods, Models and Applications",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1315?entityType=Course&reportId=422
+DMAE 765,Advanced Manufacturing Processes and Strategies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/945?entityType=Course&reportId=422
+DMAE 769,Advanced Computational Fluid Dynamics (CFD) and Heat Transfer in Mechanical Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1316?entityType=Course&reportId=422
+DMAE 770,Digital Transformation Concepts,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1048?entityType=Course&reportId=422
+DMAE 771,Space Flight Dynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1044?entityType=Course&reportId=422
+DMAE 772,Advanced Materials and Composites,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1247?entityType=Course&reportId=422
+DPE 608,Strategic Management and Leadership,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2341?entityType=Course&reportId=422
+DPE 609,Organizational Behavior in the Public Sector,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/472?entityType=Course&reportId=422
+DPE 612,Policy Tools for Addressing Inequality and Demographic Change,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2343?entityType=Course&reportId=422
+DPE 615,Scientific Reasoning for Policy Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1379?entityType=Course&reportId=422
+DPE 620,Circular Economy Strategy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1382?entityType=Course&reportId=422
+DPE 628,Good Governance and Corruption,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/122?entityType=Course&reportId=422
+DPE 632,Artificial Intelligence and Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1374?entityType=Course&reportId=422
+DPE 646,Communications for Public Leadership,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/124?entityType=Course&reportId=422
+DPE 651,Agricultural Policy Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3307?entityType=Course&reportId=422
+DPE 660,Health System and Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3308?entityType=Course&reportId=422
+DPE 671,Game Theory and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/127?entityType=Course&reportId=422
+DPE 673,Development Assistance and Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/123?entityType=Course&reportId=422
+DPE 682,Sustainable Development and Environmental Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/128?entityType=Course&reportId=422
+DPE 683,Energy Systems and Climate Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/692?entityType=Course&reportId=422
+DPE 684,Global Energy Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/693?entityType=Course&reportId=422
+DPE 685,Water Resources Policy and Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2338?entityType=Course&reportId=422
+DPM 604,Economic Applications for Public Managers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/675?entityType=Course&reportId=422
+DPM 610,Program Evaluation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/674?entityType=Course&reportId=422
+DPP 600,Developing Dissertation Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/108?entityType=Course&reportId=422
+DPP 601,Microeconomics in the Public Sector,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/118?entityType=Course&reportId=422
+DPP 602,Macroeconomics in Public Sector,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/120?entityType=Course&reportId=422
+DPP 603,Public Administration and Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3396?entityType=Course&reportId=422
+DPP 611,Statistics in Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/121?entityType=Course&reportId=422
+DPP 613,Research Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/114?entityType=Course&reportId=422
+DPP 614,Advanced Quantitative Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/116?entityType=Course&reportId=422
+DPP 615,"Law, Governance and Public Policy",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3302?entityType=Course&reportId=422
+DPP 616,Advanced Qualitative Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/115?entityType=Course&reportId=422
+DPP 621,Public Policy and Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/113?entityType=Course&reportId=422
+DPP 631,Politics of Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/112?entityType=Course&reportId=422
+DPP 690,Thesis Preparation and Writing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/109?entityType=Course&reportId=422
+DPP 690,0 Thesis Preparation and Writing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/110?entityType=Course&reportId=422
+DPP 699,Thesis Design and Written Proposal,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/111?entityType=Course&reportId=422
+DS 501,Fundamentals of Data Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1178?entityType=Course&reportId=422
+DS 502,Probability and Statistics for Data Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1254?entityType=Course&reportId=422
+DS 504,Data Mining and Decision Support,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1097?entityType=Course&reportId=422
+DS 507,Database Management Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1313?entityType=Course&reportId=422
+DS 509,Information Retrieval,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1213?entityType=Course&reportId=422
+DS 551,Process and Project Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/944?entityType=Course&reportId=422
+DS 552,Data-Driven Innovation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1096?entityType=Course&reportId=422
+DS 693,Thesis Proposal,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1120?entityType=Course&reportId=422
+DS 694,Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1121?entityType=Course&reportId=422
+DS 704,Advanced Data Mining and Decision Support,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1098?entityType=Course&reportId=422
+DUT 101,Beginning Dutch I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2725?entityType=Course&reportId=422
+DUT 102,Beginning Dutch II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2726?entityType=Course&reportId=422
+DUT 201,Intermediate Dutch I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2727?entityType=Course&reportId=422
+EAS 500,Introduction to Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2614?entityType=Course&reportId=422
+EAS 501,General Methodology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2724?entityType=Course&reportId=422
+EAS 502,Disciplinary Methodologies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2697?entityType=Course&reportId=422
+EAS 503,Thesis I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2615?entityType=Course&reportId=422
+EAS 504,Thesis II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2616?entityType=Course&reportId=422
+EAS 505,Research and Fieldwork Practicum,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2617?entityType=Course&reportId=422
+EAS 506,Qualitative Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2696?entityType=Course&reportId=422
+EAS 511,Independent Study in Eurasian Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2609?entityType=Course&reportId=422
+EAS 512,Topics in Eurasian Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2610?entityType=Course&reportId=422
+EAS 513,Critical Issues in Eurasian Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2611?entityType=Course&reportId=422
+EAS 514,Topics in Eurasian Social Sciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2612?entityType=Course&reportId=422
+EAS 700,Introduction to Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2613?entityType=Course&reportId=422
+EAS 701,Critical Issues in Eurasian Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3198?entityType=Course&reportId=422
+EAS 702,Elective in Eurasian Humanities,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3199?entityType=Course&reportId=422
+EAS 703,Elective in Eurasian Social Sciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3200?entityType=Course&reportId=422
+EAS 704,Elective II in Eurasian Humanities,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3201?entityType=Course&reportId=422
+EAS 705,Elective II in Eurasian Social Sciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3202?entityType=Course&reportId=422
+EAS 708,Proseminar in Eurasian Humanities,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3203?entityType=Course&reportId=422
+EAS 709,Proseminar in Eurasian Social Sciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3204?entityType=Course&reportId=422
+EAS 710,Independent Study in Eurasian Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3205?entityType=Course&reportId=422
+EAS 711,Doctoral Seminar in Eurasian Studies I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3207?entityType=Course&reportId=422
+EAS 712,Doctoral Seminar in Eurasian Studies II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3208?entityType=Course&reportId=422
+EAS 713,Qualifying Examination,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3206?entityType=Course&reportId=422
+EAS 800,Doctoral Thesis in Eurasian Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3210?entityType=Course&reportId=422
+EAS 800,0 Dissertation Research in Eurasian Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3209?entityType=Course&reportId=422
+ECON 101,Introduction to Microeconomics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2374?entityType=Course&reportId=422
+ECON 102,Introduction to Macroeconomics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2577?entityType=Course&reportId=422
+ECON 120,Managerial Economics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2366?entityType=Course&reportId=422
+ECON 201,Intermediate Microeconomics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2999?entityType=Course&reportId=422
+ECON 202,Intermediate Macroeconomics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3291?entityType=Course&reportId=422
+ECON 211,Economic Statistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3248?entityType=Course&reportId=422
+ECON 300,Research Assistance in Economics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2578?entityType=Course&reportId=422
+ECON 301,Econometrics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2995?entityType=Course&reportId=422
+ECON 302,Game Theory and Economic Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2997?entityType=Course&reportId=422
+ECON 305,Advanced Microeconomics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2998?entityType=Course&reportId=422
+ECON 318,Applied Econometrics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3043?entityType=Course&reportId=422
+ECON 319,Matching Theory and Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2356?entityType=Course&reportId=422
+ECON 320,Money and Banking,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2755?entityType=Course&reportId=422
+ECON 322,Natural Resources and Environmental Economics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3290?entityType=Course&reportId=422
+ECON 325,International Trade,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2443?entityType=Course&reportId=422
+ECON 326,The Economics of Financial Markets,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2754?entityType=Course&reportId=422
+ECON 328,Labor Economics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2576?entityType=Course&reportId=422
+ECON 333,Political Economy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2357?entityType=Course&reportId=422
+ECON 335,Economics of Information,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2895?entityType=Course&reportId=422
+ECON 336,Programming for Economists,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2985?entityType=Course&reportId=422
+ECON 337,Empirical Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2367?entityType=Course&reportId=422
+ECON 341,Economic Simulation Modeling,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3289?entityType=Course&reportId=422
+ECON 345,The Economics of Family,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2579?entityType=Course&reportId=422
+ECON 400,Research Assistance in Economics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2440?entityType=Course&reportId=422
+ECON 403,Introduction to Contract Theory and Auctions,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2371?entityType=Course&reportId=422
+ECON 413,Econometrics II Time Series,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2854?entityType=Course&reportId=422
+ECON 414,Advanced Monetary Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2400?entityType=Course&reportId=422
+ECON 415,Industrial Organization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2438?entityType=Course&reportId=422
+ECON 416,Empirical Industrial Organization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2439?entityType=Course&reportId=422
+ECON 418,Corporate Finance and Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2948?entityType=Course&reportId=422
+ECON 428,Wages and the Labor Market,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2580?entityType=Course&reportId=422
+ECON 433,Econometrics II Panel Data,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3044?entityType=Course&reportId=422
+ECON 434,Introduction to Big Data Analytics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2984?entityType=Course&reportId=422
+ECON 443,Topics in Macroeconomic Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2863?entityType=Course&reportId=422
+ECON 449,Quantitative Macroeconomics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2399?entityType=Course&reportId=422
+ECON 501,Microeconomics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2862?entityType=Course&reportId=422
+ECON 502,Macroeconomics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2996?entityType=Course&reportId=422
+ECON 503,Introduction to Contract Theory and Auctions,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2372?entityType=Course&reportId=422
+ECON 511,Statistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2855?entityType=Course&reportId=422
+ECON 512,Mathematical Economics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2860?entityType=Course&reportId=422
+ECON 513,Econometrics II Times Series,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2856?entityType=Course&reportId=422
+ECON 514,Advanced Monetary Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2398?entityType=Course&reportId=422
+ECON 515,Industrial Organization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2441?entityType=Course&reportId=422
+ECON 516,Empirical Industrial Organization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2442?entityType=Course&reportId=422
+ECON 518,Corporate Finance and Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2949?entityType=Course&reportId=422
+ECON 521,Microeconomic Theory II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3249?entityType=Course&reportId=422
+ECON 522,Macroeconomics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2397?entityType=Course&reportId=422
+ECON 528,Wages and the Labor Market,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2861?entityType=Course&reportId=422
+ECON 531,Econometrics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2857?entityType=Course&reportId=422
+ECON 532,Applied Econometrics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2858?entityType=Course&reportId=422
+ECON 533,Econometrics II Panel Data,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3045?entityType=Course&reportId=422
+ECON 534,Introduction to Big Data Analytics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2982?entityType=Course&reportId=422
+ECON 536,Programming for Economists,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2983?entityType=Course&reportId=422
+ECON 543,Topics in Macroeconomic Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2859?entityType=Course&reportId=422
+ECON 547,Advanced Game Theory: Mechanism Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2373?entityType=Course&reportId=422
+ECON 548,Structural Methods in Market Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3046?entityType=Course&reportId=422
+ECON 549,Quantitative Macroeconomics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2396?entityType=Course&reportId=422
+ECON 580,Research and Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2864?entityType=Course&reportId=422
+ECON 589,Thesis I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2865?entityType=Course&reportId=422
+ECON 590,Thesis II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2866?entityType=Course&reportId=422
+EDHE 601,Thesis Seminar I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/193?entityType=Course&reportId=422
+EDHE 602,Thesis Seminar II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/194?entityType=Course&reportId=422
+EDHE 603,Thesis Seminar III,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/195?entityType=Course&reportId=422
+EDHE 604,Thesis Seminar IV,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/196?entityType=Course&reportId=422
+EDHE 605,Thesis Submission and Defense,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/197?entityType=Course&reportId=422
+EDHE 625,Fundamentals of Higher Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/198?entityType=Course&reportId=422
+EDHE 626,Organization and Governance in Higher Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/199?entityType=Course&reportId=422
+EDHE 627,"Student Experience, Learning and Success in Higher Education",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/200?entityType=Course&reportId=422
+EDHE 628,Higher Education Policy Analysis and Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/201?entityType=Course&reportId=422
+EDHE 629,Globalization and International Higher Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/202?entityType=Course&reportId=422
+EDHE 631,Sociology of Higher Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/203?entityType=Course&reportId=422
+EDIE 601,Thesis Seminar I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/183?entityType=Course&reportId=422
+EDIE 602,Thesis Seminar II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/184?entityType=Course&reportId=422
+EDIE 603,Thesis Seminar III,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/185?entityType=Course&reportId=422
+EDIE 604,Thesis Seminar IV,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/186?entityType=Course&reportId=422
+EDIE 605,Thesis Submission and Defense,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/187?entityType=Course&reportId=422
+EDIE 625,Fundamentals of Inclusive Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/188?entityType=Course&reportId=422
+EDIE 626,Global Perspectives on Inclusive Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/189?entityType=Course&reportId=422
+EDIE 628,Inclusive Curriculum and Assessment,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/190?entityType=Course&reportId=422
+EDIE 629,Gifted and Talented Learners,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/191?entityType=Course&reportId=422
+EDIE 631,Developing Inclusive Schools for an Inclusive Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/192?entityType=Course&reportId=422
+EDML 601,Introduction to Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/204?entityType=Course&reportId=422
+EDML 602,Academic Literacies for Multilingual Education Professionals I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/850?entityType=Course&reportId=422
+EDML 603,Academic Literacies for Multilingual Education Professionals II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/860?entityType=Course&reportId=422
+EDML 610,Foundations of Multilingual Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/205?entityType=Course&reportId=422
+EDML 612,Multilingual Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/206?entityType=Course&reportId=422
+EDML 613,The Multilingual School,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/207?entityType=Course&reportId=422
+EDML 614,Multilingual Curriculum Development and Assessment,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/208?entityType=Course&reportId=422
+EDML 620,Language and Literacy Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/209?entityType=Course&reportId=422
+EDML 622,First and Second Langauge Acquisition,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/210?entityType=Course&reportId=422
+EDML 627,Application of CLIL in Teaching,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/211?entityType=Course&reportId=422
+EDML 629,Multiliteracies: Teaching Language and Literacy for a Multilingual Context,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/212?entityType=Course&reportId=422
+EDML 630,Language Policy and Education Reform Across Contexts,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/213?entityType=Course&reportId=422
+EDML 680,Developing the Thesis Research Topic,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/214?entityType=Course&reportId=422
+EDML 690,Thesis Research I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1326?entityType=Course&reportId=422
+EDML 691,Thesis Research II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/216?entityType=Course&reportId=422
+EDML 692,Thesis Research III,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1327?entityType=Course&reportId=422
+EDSE 601,Thesis Seminar I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/173?entityType=Course&reportId=422
+EDSE 602,Thesis Seminar II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/174?entityType=Course&reportId=422
+EDSE 603,Thesis Seminar III,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/175?entityType=Course&reportId=422
+EDSE 604,Thesis Seminar IV,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/176?entityType=Course&reportId=422
+EDSE 605,Thesis Submission and Defense,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/177?entityType=Course&reportId=422
+EDSE 621,Education Policy Analysis and Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/178?entityType=Course&reportId=422
+EDSE 625,Fundamentals of School Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/179?entityType=Course&reportId=422
+EDSE 626,Curriculum Development and Implementation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/180?entityType=Course&reportId=422
+EDSE 629,Teacher Development and Identity,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/181?entityType=Course&reportId=422
+EDSE 632,School Improvement and Effectiveness,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/182?entityType=Course&reportId=422
+EDUC 510,Advanced English for Education Professionals I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/135?entityType=Course&reportId=422
+EDUC 511,Advanced English for Education Professionals II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/136?entityType=Course&reportId=422
+EDUC 512,English for Thesis Writing I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/137?entityType=Course&reportId=422
+EDUC 513,English for Thesis Writing II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/138?entityType=Course&reportId=422
+EDUC 531,Academic English II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/140?entityType=Course&reportId=422
+EDUC 535,Academic English I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/141?entityType=Course&reportId=422
+EDUC 571,Basic Kazakh,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/129?entityType=Course&reportId=422
+EDUC 572,Kazakh for Professional Purposes,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/130?entityType=Course&reportId=422
+EDUC 573,Academic Writing in Kazakh,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/131?entityType=Course&reportId=422
+EDUC 581,Basic Kazakh (MSc),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/142?entityType=Course&reportId=422
+EDUC 582,Kazakh for Professional Purposes (MSc),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/143?entityType=Course&reportId=422
+EDUC 583,Academic Writing in Kazakh (MSc),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/144?entityType=Course&reportId=422
+EDUC 585,Education in Kazakhstan for International Students,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/132?entityType=Course&reportId=422
+EDUC 590,Academic English Writing for Doctoral Students I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/151?entityType=Course&reportId=422
+EDUC 591,Academic English Writing for Doctoral Students II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/152?entityType=Course&reportId=422
+EDUC 592,Academic English Writing for Doctoral Students III,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/153?entityType=Course&reportId=422
+EDUC 602,Educational Context and Reform in Kazakhstan,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/139?entityType=Course&reportId=422
+EDUC 606,Introduction to Education Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/145?entityType=Course&reportId=422
+EDUC 607,Research Methods I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/133?entityType=Course&reportId=422
+EDUC 608,Research Methods II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/134?entityType=Course&reportId=422
+EDUC 610,Management in Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/146?entityType=Course&reportId=422
+EDUC 617,Contextualizing Education Reform in Kazakhstan and Beyond,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/147?entityType=Course&reportId=422
+EDUC 618,Educational Leadership,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/148?entityType=Course&reportId=422
+EDUC 627,Psychology of Learning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/149?entityType=Course&reportId=422
+EDUC 630,Economics and Finance in Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/150?entityType=Course&reportId=422
+EDUC 701,Education Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/154?entityType=Course&reportId=422
+EDUC 704,Advanced Methods of Education Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/155?entityType=Course&reportId=422
+EDUC 705,Advanced Methods of Education Research: Qualitative Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/156?entityType=Course&reportId=422
+EDUC 709,Introduction to Scholarship in Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/157?entityType=Course&reportId=422
+EDUC 711,Globalization and Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/158?entityType=Course&reportId=422
+EDUC 712,Educational Policy and Reform,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/159?entityType=Course&reportId=422
+EDUC 720,Philosophy of Education,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/160?entityType=Course&reportId=422
+EDUC 727,Exploring the Research Topic I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/161?entityType=Course&reportId=422
+EDUC 728,Exploring the Research Topic II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/162?entityType=Course&reportId=422
+EDUC 729,Developing the Research Topic,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/163?entityType=Course&reportId=422
+EDUC 730,Preparation for Proposal Defence,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/164?entityType=Course&reportId=422
+EDUC 733,Thesis Proposal Defense,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/165?entityType=Course&reportId=422
+EDUC 740,Doctoral Seminar I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/166?entityType=Course&reportId=422
+EDUC 741,Doctoral Seminar II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/167?entityType=Course&reportId=422
+EDUC 751,Dissertation Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/168?entityType=Course&reportId=422
+EDUC 752,Dissertation Research: Independent Study,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/169?entityType=Course&reportId=422
+EDUC 753,Thesis Defense,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/851?entityType=Course&reportId=422
+EDUC 760,"Teaching and Learning in the University Context: Curriculum, Pedagogy and Assessment",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/171?entityType=Course&reportId=422
+EDUC 800,International Study,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/172?entityType=Course&reportId=422
+ELCE 200,Circuits Theory I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1065?entityType=Course&reportId=422
+ELCE 201,Circuits Theory II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1066?entityType=Course&reportId=422
+ELCE 201L,Circuits Theory Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1253?entityType=Course&reportId=422
+ELCE 202,Digital Logic Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/891?entityType=Course&reportId=422
+ELCE 202L,Digital Logic Design Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/892?entityType=Course&reportId=422
+ELCE 203,Signals and Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1198?entityType=Course&reportId=422
+ELCE 203L,Signals and Systems Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1199?entityType=Course&reportId=422
+ELCE 204,Solid State Devices,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/932?entityType=Course&reportId=422
+ELCE 204L,Solid State Devices Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/933?entityType=Course&reportId=422
+ELCE 205,Discrete Mathematics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/893?entityType=Course&reportId=422
+ELCE 300,Microprocessor Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1220?entityType=Course&reportId=422
+ELCE 300L,Microprocessor Systems Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1221?entityType=Course&reportId=422
+ELCE 301,Electronic Circuits,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1192?entityType=Course&reportId=422
+ELCE 301L,Electronic Circuits Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1193?entityType=Course&reportId=422
+ELCE 302,Electrical Machines,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1214?entityType=Course&reportId=422
+ELCE 302L,Electrical Machines Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1215?entityType=Course&reportId=422
+ELCE 303,Power System Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1154?entityType=Course&reportId=422
+ELCE 303L,Power System Analysis Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1155?entityType=Course&reportId=422
+ELCE 304,Computer Networks,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1224?entityType=Course&reportId=422
+ELCE 304L,Computer Networks Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1225?entityType=Course&reportId=422
+ELCE 305,Data Structures and Algorithms,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/881?entityType=Course&reportId=422
+ELCE 305L,Data Structures and Algorithms Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/882?entityType=Course&reportId=422
+ELCE 306,Linear Control Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1161?entityType=Course&reportId=422
+ELCE 306L,Linear Control Theory Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1162?entityType=Course&reportId=422
+ELCE 307,Digital Signal Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1200?entityType=Course&reportId=422
+ELCE 307L,Digital Signal Processing Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1201?entityType=Course&reportId=422
+ELCE 308,Communication Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1222?entityType=Course&reportId=422
+ELCE 308L,Communication Systems Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1223?entityType=Course&reportId=422
+ELCE 309,Individual Study,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1071?entityType=Course&reportId=422
+ELCE 310L,Electronic Instrumentation and Measurement Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/890?entityType=Course&reportId=422
+ELCE 311,Interdisciplinary Design Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1271?entityType=Course&reportId=422
+ELCE 350,Electromagnetics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/984?entityType=Course&reportId=422
+ELCE 352,Applied Simulation Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1343?entityType=Course&reportId=422
+ELCE 399,Internship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1202?entityType=Course&reportId=422
+ELCE 403,Introduction to Adaptive Signal Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1203?entityType=Course&reportId=422
+ELCE 450,Modern Characterizations for Semiconductor Industry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/931?entityType=Course&reportId=422
+ELCE 451,Electric Drives and Motion Control Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1216?entityType=Course&reportId=422
+ELCE 452,Renewable Energy and Electric Vehicles,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1151?entityType=Course&reportId=422
+ELCE 453,"High Voltage, AC/DC, FACTS Devices",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1152?entityType=Course&reportId=422
+ELCE 454,Power Transmission and Distribution Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1153?entityType=Course&reportId=422
+ELCE 455,Machine Learning with Python,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/922?entityType=Course&reportId=422
+ELCE 456,Internet of Things,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/964?entityType=Course&reportId=422
+ELCE 457,Introduction to Computer Vision,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/894?entityType=Course&reportId=422
+ELCE 458,Numerical Optimization Techniques and Computer Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/879?entityType=Course&reportId=422
+ELCE 459,Design of Application Specific Electronic Circuits,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1190?entityType=Course&reportId=422
+ELCE 460,Introduction to Computer Architecture,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1205?entityType=Course&reportId=422
+ELCE 461,Industrial Automation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1163?entityType=Course&reportId=422
+ELCE 461L,Industrial Automation Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1164?entityType=Course&reportId=422
+ELCE 462,Wireless Networks,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/965?entityType=Course&reportId=422
+ELCE 463,Network Science: Methods and Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/880?entityType=Course&reportId=422
+ELCE 465,PCB Design and Manufacturing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1273?entityType=Course&reportId=422
+ELCE 466,RF and Microwave Circuits,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1191?entityType=Course&reportId=422
+ELCE 467,Modern Wireless Communications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1272?entityType=Course&reportId=422
+ELCE 468,Robots for Rehabilitation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1217?entityType=Course&reportId=422
+ELCE 469,Microfluidics Fundamentals and Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1072?entityType=Course&reportId=422
+ELCE 470,Optical Communications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/983?entityType=Course&reportId=422
+ELCE 486,Photonics for Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1015?entityType=Course&reportId=422
+EMBAE 704,Project Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/370?entityType=Course&reportId=422
+EMBAE 707,Project Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/369?entityType=Course&reportId=422
+EMBAE 709,Consumer Behaviour,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/371?entityType=Course&reportId=422
+EMEM 509,Systems Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1050?entityType=Course&reportId=422
+EMEM 527,Globalization and Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1130?entityType=Course&reportId=422
+EMEM 533,Engineering Management and Engineering Economy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/864?entityType=Course&reportId=422
+EMEM 535,Managing Product and Service Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1051?entityType=Course&reportId=422
+EMEM 537,Engineering Decision Tools,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1230?entityType=Course&reportId=422
+EMEM 538,Knowledge and Innovation Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1131?entityType=Course&reportId=422
+EMEM 539,Big Data and Information Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/923?entityType=Course&reportId=422
+EMEM 543,Quality and Lean Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1132?entityType=Course&reportId=422
+EMEM 551,Digital Transformation and Disruption,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1133?entityType=Course&reportId=422
+EMEM 552,Capstone Project Planning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1134?entityType=Course&reportId=422
+EMEM 553,Capstone Project Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1135?entityType=Course&reportId=422
+EMEM 554,Operations and Supply Chain Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1229?entityType=Course&reportId=422
+ENG 100,Introduction to Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1069?entityType=Course&reportId=422
+ENG 101,Programming for Engineers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1269?entityType=Course&reportId=422
+ENG 102,Engineering Materials I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/949?entityType=Course&reportId=422
+ENG 103,Engineering Materials II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1211?entityType=Course&reportId=422
+ENG 200,Engineering Mathematics III (Differential Equations & Linear Algebra),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1011?entityType=Course&reportId=422
+ENG 201,Applied Probability and Statistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/961?entityType=Course&reportId=422
+ENG 202,Numerical Methods in Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/980?entityType=Course&reportId=422
+ENG 300,Interdisciplinary Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1115?entityType=Course&reportId=422
+ENG 400,CHME Capstone Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1022?entityType=Course&reportId=422
+ENG 400,ELCE Capstone Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1064?entityType=Course&reportId=422
+ENG 400,MAE Capstone Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/917?entityType=Course&reportId=422
+ENG 400,СEE Capstone Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3440?entityType=Course&reportId=422
+FEAP 010,English for Academic Purposes I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/723?entityType=Course&reportId=422
+FEAP 020,English for Academic Purposes II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/725?entityType=Course&reportId=422
+FIN 201,Principles of Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/372?entityType=Course&reportId=422
+FLDP 090,Foundations of Leadership I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/727?entityType=Course&reportId=422
+FLDP 095,Foundations of Leadership II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/728?entityType=Course&reportId=422
+FMAT 010,Foundation Mathematics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/729?entityType=Course&reportId=422
+FMAT 041,Foundation Mathematics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/730?entityType=Course&reportId=422
+FRE 101,Beginning French I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3116?entityType=Course&reportId=422
+FRE 102,Beginning French II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3117?entityType=Course&reportId=422
+FRE 201,Intermediate French I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3118?entityType=Course&reportId=422
+FRE 202,Intermediate French II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3119?entityType=Course&reportId=422
+FRE 312,Advanced Expression,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3120?entityType=Course&reportId=422
+GEOL 101,Fundamentals of Geology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/222?entityType=Course&reportId=422
+GEOL 201,Mineralogy and Petrology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1365?entityType=Course&reportId=422
+GEOL 202,Geologic Maps and Cross-Sections,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1368?entityType=Course&reportId=422
+GEOL 203,Sedimentary Petrology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1369?entityType=Course&reportId=422
+GEOL 204,Sedimentology and Stratigraphy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/236?entityType=Course&reportId=422
+GEOL 205,Paleontology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/218?entityType=Course&reportId=422
+GEOL 206,Field Geology I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/237?entityType=Course&reportId=422
+GEOL 207,Geomorphology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/233?entityType=Course&reportId=422
+GEOL 301,Igneous and Metamorphic Petrology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/714?entityType=Course&reportId=422
+GEOL 302,Thermodynamics and Geochemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1366?entityType=Course&reportId=422
+GEOL 303,Structural Geology and Tectonics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/245?entityType=Course&reportId=422
+GEOL 304,Geophysics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/246?entityType=Course&reportId=422
+GEOL 305,Geology of Ore Deposits,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/223?entityType=Course&reportId=422
+GEOL 306,Geodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/247?entityType=Course&reportId=422
+GEOL 307,Geographic Information Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/219?entityType=Course&reportId=422
+GEOL 308,Environmental Geochemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/248?entityType=Course&reportId=422
+GEOL 309,Hydrogeology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/230?entityType=Course&reportId=422
+GEOL 310,Field Geology II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/249?entityType=Course&reportId=422
+GEOL 401,Petroleum Geology and Geochemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/238?entityType=Course&reportId=422
+GEOL 402,Water Resource Management and Environmental Geosciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/231?entityType=Course&reportId=422
+GEOL 403,Geostatistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/220?entityType=Course&reportId=422
+GEOL 404,Research Project I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/250?entityType=Course&reportId=422
+GEOL 405,Research Project II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/251?entityType=Course&reportId=422
+GEOL 407,Exploration Geology and Geophysics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/234?entityType=Course&reportId=422
+GEOL 408,Remote Sensing of the Earth,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3424?entityType=Course&reportId=422
+GEOL 410,"Carbonate Systems, Processes and Deposits",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/239?entityType=Course&reportId=422
+GEOL 411,Photography for Geosciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/721?entityType=Course&reportId=422
+GEOL 501,Advanced Economic Geology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/224?entityType=Course&reportId=422
+GEOL 502,Advanced Petroleum Geology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/240?entityType=Course&reportId=422
+GEOL 503,Advanced Sedimentology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/241?entityType=Course&reportId=422
+GEOL 504,Advanced Geochemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/253?entityType=Course&reportId=422
+GEOL 505,Advanced Geophysics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/254?entityType=Course&reportId=422
+GEOL 506,Advanced Petrology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/717?entityType=Course&reportId=422
+GEOL 507,Exploration Geosciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/235?entityType=Course&reportId=422
+GEOL 508,Advanced Structural Geology and Microtectonics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/709?entityType=Course&reportId=422
+GEOL 509,Advanced Field Geology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/256?entityType=Course&reportId=422
+GEOL 601,Advanced Tectonics and Geodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/257?entityType=Course&reportId=422
+GEOL 602,Advanced GIS,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/221?entityType=Course&reportId=422
+GEOL 603,Advanced Hydrogeology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/232?entityType=Course&reportId=422
+GEOL 604,Engineering Geology and Geotechnics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/242?entityType=Course&reportId=422
+GEOL 605,Geology of Central Asia and Metallogenesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/225?entityType=Course&reportId=422
+GEOL 690,Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/258?entityType=Course&reportId=422
+GER 101,Beginning German,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2733?entityType=Course&reportId=422
+GER 102,Beginning German II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2734?entityType=Course&reportId=422
+GER 201,Intermediate German I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2735?entityType=Course&reportId=422
+GER 202,Intermediate German II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2736?entityType=Course&reportId=422
+GSBA 620,Financial Accounting,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/374?entityType=Course&reportId=422
+GSBA 622,Managerial Accounting,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/373?entityType=Course&reportId=422
+GSBE 630,Managerial Economics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/375?entityType=Course&reportId=422
+GSBF 501,Orientation Week (Team Building),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/386?entityType=Course&reportId=422
+GSBF 511,Financial Data Analytics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/376?entityType=Course&reportId=422
+GSBF 512,Principles of Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/662?entityType=Course&reportId=422
+GSBF 513,Financial Data Analytics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/387?entityType=Course&reportId=422
+GSBF 514,Corporate Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/379?entityType=Course&reportId=422
+GSBF 515A,Investments I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/382?entityType=Course&reportId=422
+GSBF 517,Macroeconomics for Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/377?entityType=Course&reportId=422
+GSBF 520,Empirical Asset Pricing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/383?entityType=Course&reportId=422
+GSBF 523,Special Topics for Coporate Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/380?entityType=Course&reportId=422
+GSBF 541,Residency I: Almaty/NBK,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/389?entityType=Course&reportId=422
+GSBF 542,Residency II: International Financial Center,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/390?entityType=Course&reportId=422
+GSBF 550A,Master's Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/385?entityType=Course&reportId=422
+GSBF 660,Foundations of Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/378?entityType=Course&reportId=422
+GSBF 661,Corporate Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/381?entityType=Course&reportId=422
+GSBM 640,Management and Organizations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/393?entityType=Course&reportId=422
+GSBM 641,Quantitative Tools for Managers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/392?entityType=Course&reportId=422
+GSBM 642,Strategy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/394?entityType=Course&reportId=422
+GSBM 644,Entrepreneurship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/399?entityType=Course&reportId=422
+GSBM 646,Advanced Leadership,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/391?entityType=Course&reportId=422
+GSBM 647,Operations Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/395?entityType=Course&reportId=422
+GSBM 648,Negotiations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/396?entityType=Course&reportId=422
+GSBM 649,Raising Capital,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/397?entityType=Course&reportId=422
+GSBM 653,Emerging Markets Strategy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/400?entityType=Course&reportId=422
+GSBM 654,Capstone Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/398?entityType=Course&reportId=422
+GSBMK 650,Marketing Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/402?entityType=Course&reportId=422
+GSBMK 652,Marketing Strategy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/401?entityType=Course&reportId=422
+GSBO 6,Orientation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/403?entityType=Course&reportId=422
+GSBPHD 01,Foundations of Social Science Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/417?entityType=Course&reportId=422
+GSBPHD 02,Qualitative Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/418?entityType=Course&reportId=422
+GSBPHD 03,Quantitative Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/405?entityType=Course&reportId=422
+GSBPHD 04,Core Research Skills I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/415?entityType=Course&reportId=422
+GSBPHD 05,Subject Specific Course I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/406?entityType=Course&reportId=422
+GSBPHD 06,Subject Specific Course II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/407?entityType=Course&reportId=422
+GSBPHD 07,Subject Specific Course III,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/408?entityType=Course&reportId=422
+GSBPHD 08,Core Research Skills II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/416?entityType=Course&reportId=422
+GSBPHD 09,GSBPHD Elective 1,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/404?entityType=Course&reportId=422
+GSBPHD 10,GSBPHD Elective 2,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/414?entityType=Course&reportId=422
+GSBPHD 11,GSBPHD Elective 3,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/419?entityType=Course&reportId=422
+GSBPHD 12,GSBPHD Elective 4,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/413?entityType=Course&reportId=422
+GSBPHD 13,PhD Qualifying Exam,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/409?entityType=Course&reportId=422
+GSBPHD 14,Thesis Research Progress,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/410?entityType=Course&reportId=422
+GSBPHD 15,Thesis Proposal Presentation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/411?entityType=Course&reportId=422
+GSBPHD 16,Final Thesis Defence,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/412?entityType=Course&reportId=422
+GSBPHD 17,Mathematical Economics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/648?entityType=Course&reportId=422
+GSBPHD 18,Microeconomic Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/650?entityType=Course&reportId=422
+HST 100,History of Kazakhstan,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2603?entityType=Course&reportId=422
+HST 104,Central Asian History II (1700 - 1991),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2604?entityType=Course&reportId=422
+HST 110,Introduction to World Religions,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2989?entityType=Course&reportId=422
+HST 121,World History I (to 1500),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2554?entityType=Course&reportId=422
+HST 123,Introduction to the History of Science and Technology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2635?entityType=Course&reportId=422
+HST 124,Introduction to the History of Medicine,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2636?entityType=Course&reportId=422
+HST 131,European History I (to 1700),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2555?entityType=Course&reportId=422
+HST 132,European History II (from 1700),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2556?entityType=Course&reportId=422
+HST 172,Middle Eastern History II (from 1800),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2769?entityType=Course&reportId=422
+HST 205,The Mongol Empire,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2600?entityType=Course&reportId=422
+HST 206,The Age of the Dragon Throne: Chinese Civilizations from the Mongols through the Qing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2601?entityType=Course&reportId=422
+HST 224,"WWI and the World: Causes, Conduct and the Consequences of WWI",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2770?entityType=Course&reportId=422
+HST 226,Soviet Central Asia in WWII,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2602?entityType=Course&reportId=422
+HST 232,Russian History from Riurik to Catherine the Great,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2605?entityType=Course&reportId=422
+HST 233,The Russian Empire from Catherine the Great to the Bolshevik Revolution,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2606?entityType=Course&reportId=422
+HST 236,"Eurasian Revolutions, 1905-1949",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2962?entityType=Course&reportId=422
+HST 238,"Clash of Civilizations: Communities, Confessions and Empires in Central Europe, 1000-1890",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2557?entityType=Course&reportId=422
+HST 239,"Modernizing the Periphery: Nationalism, Communism, and Empire in Central Europe, 1890-Present",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2558?entityType=Course&reportId=422
+HST 242,"History of the Soviet Union: Politics, Society, Culture",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2961?entityType=Course&reportId=422
+HST 245,Global History of Travel and Travel Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2559?entityType=Course&reportId=422
+HST 261,History of Islam (570s to 1258),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2599?entityType=Course&reportId=422
+HST 263,The History of Islam II: Islam in the Modern World,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3081?entityType=Course&reportId=422
+HST 268,Women and Islam in Central Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3082?entityType=Course&reportId=422
+HST 271,History of the Ottoman Empire,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2771?entityType=Course&reportId=422
+HST 272,Modern Turkey: from the Ottoman Empire to the Turkish Republic,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2772?entityType=Course&reportId=422
+HST 273,History of Sufism in the Middle East and Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2597?entityType=Course&reportId=422
+HST 274,Texts and Contexts,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2560?entityType=Course&reportId=422
+HST 320,The Crusades,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2598?entityType=Course&reportId=422
+HST 329,Women in Islamic History,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3083?entityType=Course&reportId=422
+HST 331,The Eurasian Enlightenment,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2561?entityType=Course&reportId=422
+HST 336,The Totalitarian Phenomenon,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2963?entityType=Course&reportId=422
+HST 341,Eastern Christianity,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2607?entityType=Course&reportId=422
+HST 342,Russian Intellectual History (1762 - 1905),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2608?entityType=Course&reportId=422
+HST 375,Inner Asian Frontiers of China: A Cultural Perspective,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3182?entityType=Course&reportId=422
+HST 380,Linguistic and Cultural Diversity in Contemporary China: From Beijing to Xinjiang,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3183?entityType=Course&reportId=422
+HST 399,Independent Study,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2595?entityType=Course&reportId=422
+HST 424,Global Histories,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2634?entityType=Course&reportId=422
+HST 433,"Empire, Nation and Identity in Nineteenth-Century Eurasia",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2562?entityType=Course&reportId=422
+HST 434,"Neither Red, Nor White: 1917 Revolution as a National Moment",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2964?entityType=Course&reportId=422
+HST 435,Stalinist Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2596?entityType=Course&reportId=422
+HST 440,Religions in the Soviet and Post-Soviet Eras,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2988?entityType=Course&reportId=422
+HST 441,Utopias in Russian and Soviet Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2409?entityType=Course&reportId=422
+HST 443,Imperial Apocalypse: 1917 and 1991 in Comparative Perspective,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2965?entityType=Course&reportId=422
+HST 451,Conversion to Islam in Medieval and Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2594?entityType=Course&reportId=422
+HST 454,Turkestan in the Nineteenth Century,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3211?entityType=Course&reportId=422
+HST 462,History of Islam Under Russian Rule,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3084?entityType=Course&reportId=422
+HST 498,Directed Reading,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3085?entityType=Course&reportId=422
+HST 499,History Capstone: Undergraduate Dissertation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3086?entityType=Course&reportId=422
+HST 533,"Empire, Nation and Identity in Nineteenth-Century Eurasia",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2563?entityType=Course&reportId=422
+HST 534,"Neither Red, Nor White: 1917 Revolution as a National Moment",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2966?entityType=Course&reportId=422
+HST 535,Stalinist Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2593?entityType=Course&reportId=422
+HST 540,Religions in the Soviet and Post-Soviet Eras,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2987?entityType=Course&reportId=422
+HST 541,Utopias in Russian and Soviet Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2410?entityType=Course&reportId=422
+HST 543,Imperial Apocalypse: 1917 and 1991 in Comparative Perspective,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2967?entityType=Course&reportId=422
+HST 551,Conversion to Islam in Medieval and Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2592?entityType=Course&reportId=422
+HST 552,"Proseminar in Eurasian History, 552-1917",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3217?entityType=Course&reportId=422
+HST 554,Turkestan in the Nineteenth Century,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3212?entityType=Course&reportId=422
+HST 562,History of Islam Under Russian Rule,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3087?entityType=Course&reportId=422
+HST 733,"Empire, Nation and Identity in Nineteenth-Century Eurasia",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2564?entityType=Course&reportId=422
+HST 734,"Neither Red, Nor White: 1917 Revolution as a National Moment",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2968?entityType=Course&reportId=422
+HST 740,Religions in the Soviet and Post-Soviet Eras,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2986?entityType=Course&reportId=422
+HST 741,Utopias in Russian and Soviet Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2411?entityType=Course&reportId=422
+HST 743,Imperial Apocalypse: 1917 and 1991 in Comparative Perspective,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2960?entityType=Course&reportId=422
+HST 751,Conversion to Islam in Medieval and Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2591?entityType=Course&reportId=422
+HST 752,"Proseminar in Eurasian History, 552-1917",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3218?entityType=Course&reportId=422
+KAZ 150,Basic Kazakh,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3273?entityType=Course&reportId=422
+KAZ 201,Academic Kazakh I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2358?entityType=Course&reportId=422
+KAZ 202,Academic Kazakh II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3048?entityType=Course&reportId=422
+KAZ 211,Academic Speaking in Kazakh,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3113?entityType=Course&reportId=422
+KAZ 212,Academic Writing in Kazakh,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3047?entityType=Course&reportId=422
+KAZ 226,Kazakh for Medical School,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2893?entityType=Course&reportId=422
+KAZ 311,Professional Academic Communication,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3271?entityType=Course&reportId=422
+KAZ 313,Kazakh for Business,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2762?entityType=Course&reportId=422
+KAZ 349,Kazakh Mythology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3272?entityType=Course&reportId=422
+KAZ 351,Kazakh Short Stories,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3269?entityType=Course&reportId=422
+KAZ 353,Kazakh Poetry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3270?entityType=Course&reportId=422
+KAZ 354,Kazakh Drama,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3215?entityType=Course&reportId=422
+KAZ 356,Kazakh Music History,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2950?entityType=Course&reportId=422
+KAZ 357,Literature of Alash,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3268?entityType=Course&reportId=422
+KAZ 359,Professional Kazakh for Medicine,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2894?entityType=Course&reportId=422
+KAZ 362,Creative Writing in Kazakh Language,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3254?entityType=Course&reportId=422
+KAZ 363,Language and Globalization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2761?entityType=Course&reportId=422
+KAZ 364,Kazakh for Civil Service,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3213?entityType=Course&reportId=422
+KAZ 365,Abai’s World,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3214?entityType=Course&reportId=422
+KAZ 366,Kazakh Language for Engineers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3292?entityType=Course&reportId=422
+KAZ 368,Onomastics: History and Function of Names,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3293?entityType=Course&reportId=422
+KAZ 371,Contemporary Kazakh Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3255?entityType=Course&reportId=422
+KAZ 372,Language and Ethnicity,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3274?entityType=Course&reportId=422
+KAZ 373,Kazakh Terminology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3114?entityType=Course&reportId=422
+KAZ 374,Kazakh Diplomacy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3265?entityType=Course&reportId=422
+KAZ 375,Cultural Studies and Kazakh Culture,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3266?entityType=Course&reportId=422
+KAZ 376,Language and Culture,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3115?entityType=Course&reportId=422
+KAZ 377,Intercultural Communication through Film,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3267?entityType=Course&reportId=422
+KAZ 410,Kazakh Literature of the XV-XIX Centuries,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2369?entityType=Course&reportId=422
+KFL 101,Elementary Kazakh as a Foreign Language I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2359?entityType=Course&reportId=422
+KFL 102,Elementary Kazakh as a Foreign Language II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2360?entityType=Course&reportId=422
+KFL 201,Intermediate Kazakh as a Foreign Language I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2361?entityType=Course&reportId=422
+KFL 202,Intermediate Kazakh as a Foreign Language II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2362?entityType=Course&reportId=422
+KFL 301,Advanced Kazakh as a Foreign Language I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2363?entityType=Course&reportId=422
+KFL 302,Advanced Kazakh as a Foreign Language II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2364?entityType=Course&reportId=422
+KOR 101,Beginning Korean I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2728?entityType=Course&reportId=422
+KOR 102,Beginning Korean II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2729?entityType=Course&reportId=422
+KOR 201,Intermediate Korean I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2730?entityType=Course&reportId=422
+KOR 202,Intermediate Korean II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2731?entityType=Course&reportId=422
+KOR 301,Advanced Korean I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2732?entityType=Course&reportId=422
+LING 130,Introduction to Language and Communication,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3237?entityType=Course&reportId=422
+LING 131,Introduction to Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3006?entityType=Course&reportId=422
+LING 140,Language Variation and Change: the Story of English,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3007?entityType=Course&reportId=422
+LING 240,Introduction to Sociolinguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2694?entityType=Course&reportId=422
+LING 270,Languages of Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2423?entityType=Course&reportId=422
+LING 271,Introduction to Cognitive Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3232?entityType=Course&reportId=422
+LING 272,Language and the Mind,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3233?entityType=Course&reportId=422
+LING 273,Survey of Research Methods in Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2424?entityType=Course&reportId=422
+LING 277,Language Diversity and Language Universals,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3005?entityType=Course&reportId=422
+LING 278,Sounds of the World’s Languages,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2469?entityType=Course&reportId=422
+LING 280,Introduction to Turkic Historical and Comparative Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3216?entityType=Course&reportId=422
+LING 372,Discourse Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2695?entityType=Course&reportId=422
+LING 374,Language Contact in Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2471?entityType=Course&reportId=422
+LING 375,The Art and Science of Analyzing Languages: Morphosyntax of the World's Languages,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2553?entityType=Course&reportId=422
+LING 376,Psycholinguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3235?entityType=Course&reportId=422
+LING 377,Historical Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2470?entityType=Course&reportId=422
+LING 389,Discourse and Grammar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2752?entityType=Course&reportId=422
+LING 431,Statistics and Computational Methods in Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2753?entityType=Course&reportId=422
+LING 461,Experimental Semantics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3234?entityType=Course&reportId=422
+LING 470,Multilingualism and Language Contact,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2472?entityType=Course&reportId=422
+LING 472,Language Ideologies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2690?entityType=Course&reportId=422
+LING 473,Advanced Empirical Methods in Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2751?entityType=Course&reportId=422
+LING 482,Language and Worldview,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2693?entityType=Course&reportId=422
+LING 491,Advanced Independent Study,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3236?entityType=Course&reportId=422
+LING 531,Statistics and Computational Methods in Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2748?entityType=Course&reportId=422
+LING 570,Multilingualism and Language Contact,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2473?entityType=Course&reportId=422
+LING 572,Language Ideologies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2692?entityType=Course&reportId=422
+LING 573,Advanced Empirical Methods in Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2747?entityType=Course&reportId=422
+LING 574,Language Contact in Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2474?entityType=Course&reportId=422
+LING 589,Discourse and Grammar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2749?entityType=Course&reportId=422
+LING 731,Statistics and Computational Methods in Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2750?entityType=Course&reportId=422
+LING 772,Language Ideologies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2691?entityType=Course&reportId=422
+LING 773,Advanced Empirical Methods in Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2552?entityType=Course&reportId=422
+LING 774,Language Contact in Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2468?entityType=Course&reportId=422
+LING 782,Language and Worldview,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2689?entityType=Course&reportId=422
+LING 789,Discourse and Grammar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2746?entityType=Course&reportId=422
+MAC 960,Acting Internship in Obstetrics and Gynecology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/485?entityType=Course&reportId=422
+MAC 961,Acting Internship in General Pediatrics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/483?entityType=Course&reportId=422
+MAC 962,Acting Internship in General Surgery,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/486?entityType=Course&reportId=422
+MAC 963,Acting Internship in Internal Medicine,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/484?entityType=Course&reportId=422
+MAE 201,Computer Aided Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1117?entityType=Course&reportId=422
+MAE 205,Materials and Manufacturing I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1038?entityType=Course&reportId=422
+MAE 206,Engineering Dynamics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1146?entityType=Course&reportId=422
+MAE 300,Fluid Mechanics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1236?entityType=Course&reportId=422
+MAE 301,Engineering Thermodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1021?entityType=Course&reportId=422
+MAE 302,Machine Elements Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1250?entityType=Course&reportId=422
+MAE 303,Control Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1145?entityType=Course&reportId=422
+MAE 305,Fluid Mechanics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1237?entityType=Course&reportId=422
+MAE 306,Computer Aided Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3448?entityType=Course&reportId=422
+MAE 307,Engineering Dynamics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1249?entityType=Course&reportId=422
+MAE 350,Structural Mechanics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1036?entityType=Course&reportId=422
+MAE 351,Vehicle Propulsion Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1020?entityType=Course&reportId=422
+MAE 400,Heat Transfer,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1308?entityType=Course&reportId=422
+MAE 401,Mechanical Systems Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1037?entityType=Course&reportId=422
+MAE 450,Additive Manufacturing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1035?entityType=Course&reportId=422
+MAE 451,Unmanned Aerial Vehicle Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/958?entityType=Course&reportId=422
+MAE 452,Computer Aided Geometric Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1116?entityType=Course&reportId=422
+MAE 453,Fire Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1320?entityType=Course&reportId=422
+MAE 454,Aerodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/960?entityType=Course&reportId=422
+MAE 455,Flight Performance and Mechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/959?entityType=Course&reportId=422
+MAE 456,Materials and Manufacturing II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/948?entityType=Course&reportId=422
+MAE 457,Feasibility Analysis of Clean Energy Technologies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1309?entityType=Course&reportId=422
+MAE 460,Advanced Topics in Computational Fluid Dynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1319?entityType=Course&reportId=422
+MAE 462,Multiphase Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1238?entityType=Course&reportId=422
+MAE 463,Micro-Electro-Mechanical Systems (MEMS) and Microsystems Technology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1067?entityType=Course&reportId=422
+MAE 464,Mechanics of Soft Materials,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1068?entityType=Course&reportId=422
+MAE 465,Introduction to Maintenance Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/918?entityType=Course&reportId=422
+MAE 466,Application of Optimization in Mechanical and Aerospace Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/919?entityType=Course&reportId=422
+MAE 500,Unmanned Aerial Vehicle Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/957?entityType=Course&reportId=422
+MANS 811,Anesthesiology Clerkship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/487?entityType=Course&reportId=422
+MATH 109,Mathematical Discovery,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2535?entityType=Course&reportId=422
+MATH 161,Calculus I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2536?entityType=Course&reportId=422
+MATH 162,Calculus II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3282?entityType=Course&reportId=422
+MATH 251,Discrete Mathematics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2910?entityType=Course&reportId=422
+MATH 263,Calculus III,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2421?entityType=Course&reportId=422
+MATH 273,Linear Algebra with Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2648?entityType=Course&reportId=422
+MATH 274,Introduction to Differential Equations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3165?entityType=Course&reportId=422
+MATH 301,Introduction to Number Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2661?entityType=Course&reportId=422
+MATH 302,Abstract Algebra I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3295?entityType=Course&reportId=422
+MATH 310,Applied Statistical Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2680?entityType=Course&reportId=422
+MATH 321,Probability,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2365?entityType=Course&reportId=422
+MATH 322,Mathematical Statistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2679?entityType=Course&reportId=422
+MATH 323,Actuarial Mathematics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2649?entityType=Course&reportId=422
+MATH 350,Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2658?entityType=Course&reportId=422
+MATH 351,Numerical Methods with Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2659?entityType=Course&reportId=422
+MATH 361,Real Analysis I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2660?entityType=Course&reportId=422
+MATH 371,Introduction to Mathematical Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2452?entityType=Course&reportId=422
+MATH 403,Abstract Algebra II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3297?entityType=Course&reportId=422
+MATH 407,Graph Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2907?entityType=Course&reportId=422
+MATH 411,Linear Programming,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2351?entityType=Course&reportId=422
+MATH 412,Nonlinear Optimization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2886?entityType=Course&reportId=422
+MATH 417,Cryptography,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2908?entityType=Course&reportId=422
+MATH 423,Actuarial Mathematics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2650?entityType=Course&reportId=422
+MATH 424,Mathematical Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2651?entityType=Course&reportId=422
+MATH 425,Stochastic Processes,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2888?entityType=Course&reportId=422
+MATH 440,Regression Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3030?entityType=Course&reportId=422
+MATH 441,Design of Experiments,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3098?entityType=Course&reportId=422
+MATH 446,Time Series Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2887?entityType=Course&reportId=422
+MATH 449,Statistical Programming,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3099?entityType=Course&reportId=422
+MATH 455,Stochastic Calculus,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2347?entityType=Course&reportId=422
+MATH 456,Introduction to Lie Groups and Representations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3296?entityType=Course&reportId=422
+MATH 460,Topology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2686?entityType=Course&reportId=422
+MATH 461,Real Analysis II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2687?entityType=Course&reportId=422
+MATH 462,Advanced Linear Algebra,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2909?entityType=Course&reportId=422
+MATH 471,Nonlinear Differential Equations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2453?entityType=Course&reportId=422
+MATH 476,Numerical Methods for Partial Differential Equations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2379?entityType=Course&reportId=422
+MATH 477,Applied Finite Element Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3252?entityType=Course&reportId=422
+MATH 480,Complex Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2380?entityType=Course&reportId=422
+MATH 481,Partial Differential Equations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2348?entityType=Course&reportId=422
+MATH 482,Fourier Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3033?entityType=Course&reportId=422
+MATH 490,Special Topics in Mathematics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2381?entityType=Course&reportId=422
+MATH 491,Special Topics in Mathematics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2382?entityType=Course&reportId=422
+MATH 497,Directed Study in Mathematics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3034?entityType=Course&reportId=422
+MATH 498,Directed Study in Mathematics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3035?entityType=Course&reportId=422
+MATH 499,Capstone Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3166?entityType=Course&reportId=422
+MATH 510,Measure Theory and Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2420?entityType=Course&reportId=422
+MATH 512,Optimization Methods and Techniques,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2889?entityType=Course&reportId=422
+MATH 514,Operations Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2890?entityType=Course&reportId=422
+MATH 515,Theory of Probability,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2891?entityType=Course&reportId=422
+MATH 517,Scientific Modeling and Simulation with Mathematics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2653?entityType=Course&reportId=422
+MATH 518,Applied Finite Element Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3031?entityType=Course&reportId=422
+MATH 519,Scientific Computing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3032?entityType=Course&reportId=422
+MATH 540,Statistical Learning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2350?entityType=Course&reportId=422
+MATH 541,Data Analysis and Statistical Learning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3096?entityType=Course&reportId=422
+MATH 542,Statistical Programming,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3097?entityType=Course&reportId=422
+MATH 551,Advanced Numerical Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3253?entityType=Course&reportId=422
+MATH 555,Stochastic Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2688?entityType=Course&reportId=422
+MATH 571,Advanced Nonlinear Differential Equations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2455?entityType=Course&reportId=422
+MATH 576,Numerical Methods for Partial Differential Equations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2652?entityType=Course&reportId=422
+MATH 577,Modeling and Numerical Analysis for Incompressible Fluids,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3038?entityType=Course&reportId=422
+MATH 580,Advanced Complex Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3039?entityType=Course&reportId=422
+MATH 582,Mathematical Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2454?entityType=Course&reportId=422
+MATH 592,Research Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2377?entityType=Course&reportId=422
+MATH 599,Thesis Research Preparation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2378?entityType=Course&reportId=422
+MATH 601,Analytic Number Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2657?entityType=Course&reportId=422
+MATH 620,Asymptotic Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2375?entityType=Course&reportId=422
+MATH 676,Advanced Partial Differential Equations with Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2376?entityType=Course&reportId=422
+MATH 677,Introduction to Nonlinear Dispersive and Wave Equations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2349?entityType=Course&reportId=422
+MATH 680,Potential Theory and Polynomial Approximation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3036?entityType=Course&reportId=422
+MATH 682,Applied Functional Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3037?entityType=Course&reportId=422
+MATH 691,Thesis Proposal,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2383?entityType=Course&reportId=422
+MATH 692,Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2384?entityType=Course&reportId=422
+MATH 700,Doctoral Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2664?entityType=Course&reportId=422
+MATH 700,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2665?entityType=Course&reportId=422
+MATH 701,Real Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2385?entityType=Course&reportId=422
+MATH 702,Functional Analysis with Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2663?entityType=Course&reportId=422
+MATH 711,Abstract Algebra,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3294?entityType=Course&reportId=422
+MATH 714,Advanced Operations Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2885?entityType=Course&reportId=422
+MATH 721,Nonlinear Differential Equations with Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2451?entityType=Course&reportId=422
+MATH 722,Advanced Partial Differential Equations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2419?entityType=Course&reportId=422
+MATH 740,Advanced Statistical Learning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3100?entityType=Course&reportId=422
+MATH 742,Advanced Statistical Programming,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3101?entityType=Course&reportId=422
+MATH 751,Probability Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2882?entityType=Course&reportId=422
+MATH 761,Mathematical Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2883?entityType=Course&reportId=422
+MATH 771,Operations Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2884?entityType=Course&reportId=422
+MATH 776,Advanced Numerical Methods for Partial Differential Equations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2647?entityType=Course&reportId=422
+MATH 780,Research Methods and Ethics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2662?entityType=Course&reportId=422
+MATH 791,Topics in Mathematics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2911?entityType=Course&reportId=422
+MBA 01,Introduction to General Management Principles,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/420?entityType=Course&reportId=422
+MBA 02,Foundations of Financial and Managerial Accounting,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/426?entityType=Course&reportId=422
+MBA 03,Leadership & Communication,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/421?entityType=Course&reportId=422
+MBA 04,Data Anatytics for Managers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/423?entityType=Course&reportId=422
+MBA 05,Principles of Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/427?entityType=Course&reportId=422
+MBA 06,Economics for Managers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/422?entityType=Course&reportId=422
+MBA 07,Management and Organizations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/424?entityType=Course&reportId=422
+MBA 08,Marketing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/429?entityType=Course&reportId=422
+MBA 09,Entrepreneurship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/428?entityType=Course&reportId=422
+MBA 10,Foundations of Strategy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/425?entityType=Course&reportId=422
+MBA 11,Operations Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/430?entityType=Course&reportId=422
+MBA 12,"Environmental, Social and Governance Factors (ESG) for Business",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/432?entityType=Course&reportId=422
+MBA 13,Practicum Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/431?entityType=Course&reportId=422
+MBAE 01,Corporate Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/433?entityType=Course&reportId=422
+MBAE 02,Negotiations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/434?entityType=Course&reportId=422
+MBAE 03,Investments,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/435?entityType=Course&reportId=422
+MBAE 04,Supply Chain Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/436?entityType=Course&reportId=422
+MBAE 05,International Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/437?entityType=Course&reportId=422
+MBAE 06,Strategic Marketing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/438?entityType=Course&reportId=422
+MBME 600,Research Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1009?entityType=Course&reportId=422
+MBME 601,Master Thesis I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/987?entityType=Course&reportId=422
+MBME 602,Master Thesis II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/988?entityType=Course&reportId=422
+MBME 603,Biomaterials Science and Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/989?entityType=Course&reportId=422
+MBME 604,Biosensors,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1010?entityType=Course&reportId=422
+MBME 607,Advanced Tissue Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/991?entityType=Course&reportId=422
+MBME 610,Anatomy and Physiology for Biomedical Engineers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/887?entityType=Course&reportId=422
+MBME 700,Strategies for Controlled Topical Delivery of Drugs,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/888?entityType=Course&reportId=422
+MBME 708,Biomedical Imaging,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1007?entityType=Course&reportId=422
+MBME 709,Mechanics of Living Tissues,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/990?entityType=Course&reportId=422
+MBME 710,Biophotonics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1006?entityType=Course&reportId=422
+MBSB 611,Medical Anatomy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/490?entityType=Course&reportId=422
+MBSB 612,Human Genetics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/494?entityType=Course&reportId=422
+MBSB 613,Cellular Pathologic Basis of Disease,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/493?entityType=Course&reportId=422
+MBSB 614,Fuel Metabolism,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/489?entityType=Course&reportId=422
+MBSB 615,Immunology in Health and Disease,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/488?entityType=Course&reportId=422
+MBSB 616,Medical Microbiology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/491?entityType=Course&reportId=422
+MBSB 617,Pharmacology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/492?entityType=Course&reportId=422
+MCEE 600,Research Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1093?entityType=Course&reportId=422
+MCEE 601,Master Thesis I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1094?entityType=Course&reportId=422
+MCEE 602,Master Thesis II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1095?entityType=Course&reportId=422
+MCEE 603,Finite Element Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1033?entityType=Course&reportId=422
+MCEE 604,Advanced Soil Mechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1282?entityType=Course&reportId=422
+MCEE 605,Advanced Environmental Chemistry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1292?entityType=Course&reportId=422
+MCEE 606,Advanced Project Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/865?entityType=Course&reportId=422
+MCEE 700,Structural Dynamics and Earthquake Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3436?entityType=Course&reportId=422
+MCEE 701,Advanced Concrete Technology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1001?entityType=Course&reportId=422
+MCEE 702,Structural Evaluation and Rehabilitation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1239?entityType=Course&reportId=422
+MCEE 703,Theory of Physio-chemical Treatment Processes,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1293?entityType=Course&reportId=422
+MCEE 704,Contaminated Site Management and Soil Treatment Technologies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1174?entityType=Course&reportId=422
+MCEE 705,Environmental Modeling Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1056?entityType=Course&reportId=422
+MCEE 706,Concrete Repair and Maintenance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1240?entityType=Course&reportId=422
+MCEE 707,Geotechnical Earthquake Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1280?entityType=Course&reportId=422
+MCEE 708,Advanced Foundation Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/896?entityType=Course&reportId=422
+MCEE 709,Building Information Modeling in Construction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/866?entityType=Course&reportId=422
+MCEE 710,"Green Building - Concept, Design, Construction, and Operation",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1055?entityType=Course&reportId=422
+MCEE 711,Soil Improvement and Stabilization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1281?entityType=Course&reportId=422
+MCEE 712,"Advanced Pavement Design, Analysis, and Rehabilitation",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1002?entityType=Course&reportId=422
+MCEE 713,Advanced Concrete Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1034?entityType=Course&reportId=422
+MCEE 714,Advanced Wastewater Treatment,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1294?entityType=Course&reportId=422
+MCEE 715,Sustainable Construction and Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1054?entityType=Course&reportId=422
+MCEE 716,Unsaturated Soil Mechanics for Engineering Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/897?entityType=Course&reportId=422
+MCEE 717,Computational Modeling and Instrumentation in Geotechnical Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/898?entityType=Course&reportId=422
+MCHME 600,Research Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1003?entityType=Course&reportId=422
+MCHME 601,Master Thesis I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1004?entityType=Course&reportId=422
+MCHME 602,MSc Thesis II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1005?entityType=Course&reportId=422
+MCHME 603,Advanced Materials Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/909?entityType=Course&reportId=422
+MCHME 604,Advanced Materials Characterization Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1323?entityType=Course&reportId=422
+MCHME 605,Advanced Chemical Reaction Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1268?entityType=Course&reportId=422
+MCHME 606,Advanced Heat and Mass Transfer,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1235?entityType=Course&reportId=422
+MCHME 701,Advanced Chemical Thermodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1210?entityType=Course&reportId=422
+MCHME 707,Polymer Melt Fluid Mechanics and Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1302?entityType=Course&reportId=422
+MCHME 713,Advanced Energy Materials and Their Application,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/910?entityType=Course&reportId=422
+MCHME 714,Computational Materials Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1303?entityType=Course&reportId=422
+MCPC 933,Cardiac Pathologies Clerkship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/495?entityType=Course&reportId=422
+MECE 600,Research Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1013?entityType=Course&reportId=422
+MECE 601,MSc Thesis I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1157?entityType=Course&reportId=422
+MECE 602,MSc Thesis II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1158?entityType=Course&reportId=422
+MECE 603,Advanced Data Structures and Algorithms,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/876?entityType=Course&reportId=422
+MECE 605,Probability and Statistics for Electrical and Computer Engineers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/962?entityType=Course&reportId=422
+MECE 606,Embedded Systems and Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/895?entityType=Course&reportId=422
+MECE 608,Energy Systems Operations and Planning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1159?entityType=Course&reportId=422
+MECE 700,Industrial and Commercial Power Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1160?entityType=Course&reportId=422
+MECE 704,Fundamentals of Signal Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1197?entityType=Course&reportId=422
+MECE 707,Advanced Electronic Circuits,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1195?entityType=Course&reportId=422
+MECE 716,Adaptive Signal Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1196?entityType=Course&reportId=422
+MECE 717,Pattern Recognition and Machine Learning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/920?entityType=Course&reportId=422
+MECE 724,System Modelling and Control,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1219?entityType=Course&reportId=422
+MECE 726,Modern Semiconductor Devices and Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/935?entityType=Course&reportId=422
+MECE 727,Biosensors,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1012?entityType=Course&reportId=422
+MECE 728,Renewable and Sustainable Energy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1156?entityType=Course&reportId=422
+MECE 729,Convex Optimization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/877?entityType=Course&reportId=422
+MECE 730,Microfluidic Devices,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1070?entityType=Course&reportId=422
+MECE 731,RF and Microwave Circuits,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1194?entityType=Course&reportId=422
+MECE 732,Optical Communications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/986?entityType=Course&reportId=422
+MECE 733,Semiconductor Process Engineering for VLSI,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/936?entityType=Course&reportId=422
+MEL 967,Gastroenterology and Hepatology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/496?entityType=Course&reportId=422
+MFAM 860,Family Medicine Clerkship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/497?entityType=Course&reportId=422
+MICE 932,Intensive Care and Emergency Medicine Clerkship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/498?entityType=Course&reportId=422
+MILS 401,Integrated Life Sciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/499?entityType=Course&reportId=422
+MINE 201,Mineral Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/270?entityType=Course&reportId=422
+MINE 301,Mine Surveying and GIS,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/272?entityType=Course&reportId=422
+MINE 302,Fundamentals of Geomechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/273?entityType=Course&reportId=422
+MINE 303,Mine Services and Materials Handling,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/264?entityType=Course&reportId=422
+MINE 304,Resource Estimation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/286?entityType=Course&reportId=422
+MINE 305,Rock Breakage,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/291?entityType=Course&reportId=422
+MINE 306,Underground Mining Systems and Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/274?entityType=Course&reportId=422
+MINE 307,Surface Mining System and Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/259?entityType=Course&reportId=422
+MINE 401,Mining Geotechnical Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/260?entityType=Course&reportId=422
+MINE 402,Mine Planning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/287?entityType=Course&reportId=422
+MINE 403,Coal Mining,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/275?entityType=Course&reportId=422
+MINE 404,"Health, Safety and Sustainability in Mining",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/296?entityType=Course&reportId=422
+MINE 405,Mine Ventilation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/297?entityType=Course&reportId=422
+MINE 407,Mining and Environment,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/271?entityType=Course&reportId=422
+MINE 408,Mine Risk Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/298?entityType=Course&reportId=422
+MINE 489,Mine Design Project I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/265?entityType=Course&reportId=422
+MINE 490,Mine Design Project II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/266?entityType=Course&reportId=422
+MINE 501,Foundations of Mining,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/261?entityType=Course&reportId=422
+MINE 502,Geology for Mining Engineers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/292?entityType=Course&reportId=422
+MINE 503,Applied Geostatistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/288?entityType=Course&reportId=422
+MINE 504,Mine Geomechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/267?entityType=Course&reportId=422
+MINE 505,Advanced Mine Ventilation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/299?entityType=Course&reportId=422
+MINE 507,Rock Excavation Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/293?entityType=Course&reportId=422
+MINE 508,Advanced Rock Mechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/268?entityType=Course&reportId=422
+MINE 509,Advanced Surface Mine Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/262?entityType=Course&reportId=422
+MINE 510,Advanced Underground Mine Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/276?entityType=Course&reportId=422
+MINE 601,Mine Management and Sustainability,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/301?entityType=Course&reportId=422
+MINE 602,Mine Automation and Maintenance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/300?entityType=Course&reportId=422
+MINE 603,Multivariate Geostatistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/289?entityType=Course&reportId=422
+MINE 604,Geology of Ore Deposits,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/285?entityType=Course&reportId=422
+MINE 605,Mechanized Excavation and Tunnelling,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/294?entityType=Course&reportId=422
+MINE 606,Underground Hard Rock Geotechnical Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/277?entityType=Course&reportId=422
+MINE 690,Thesis I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/278?entityType=Course&reportId=422
+MINE 691,Thesis II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/279?entityType=Course&reportId=422
+MINE 701,Advanced Mine Geomechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/269?entityType=Course&reportId=422
+MINE 702,Current Research Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/302?entityType=Course&reportId=422
+MINE 703,Advanced Mining Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/280?entityType=Course&reportId=422
+MINE 801,Advanced Mechanized Excavation and Tunnelling,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/295?entityType=Course&reportId=422
+MINE 803,Advanced Geometallurgy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/290?entityType=Course&reportId=422
+MINE 804,Unconventional Mining Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/281?entityType=Course&reportId=422
+MINE 805,Mine Robotics and Automation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/282?entityType=Course&reportId=422
+MINE 806,Advanced Numerical Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/263?entityType=Course&reportId=422
+MINE 890,Doctoral Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/283?entityType=Course&reportId=422
+MINE 890,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/284?entityType=Course&reportId=422
+MINF 821,Infectious Diseases Clerkship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/500?entityType=Course&reportId=422
+MMAE 600,Research Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1305?entityType=Course&reportId=422
+MMAE 601,Master Thesis I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1306?entityType=Course&reportId=422
+MMAE 602,Master Thesis II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/916?entityType=Course&reportId=422
+MMAE 603,Modern Control Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1144?entityType=Course&reportId=422
+MMAE 604,Advanced Computational Fluid Dynamics (CFD) and Heat Transfer in Mechanical Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1318?entityType=Course&reportId=422
+MMAE 605,Advanced Manufacturing Processes and Strategies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/947?entityType=Course&reportId=422
+MMAE 606,Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1307?entityType=Course&reportId=422
+MMAE 700,Advanced Statistics and Probability,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1310?entityType=Course&reportId=422
+MMAE 701,Numerical Techniques for Engineers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1046?entityType=Course&reportId=422
+MMAE 702,Sustainable Vehicle Transportation Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1018?entityType=Course&reportId=422
+MMAE 705,Design Optimization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1119?entityType=Course&reportId=422
+MMAE 706,Computational and Unsteady Aerodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/955?entityType=Course&reportId=422
+MMAE 710,Space Structures Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/956?entityType=Course&reportId=422
+MMAE 713,"Computational Fluid-Structure Interaction: Methods, Models and Applications",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1317?entityType=Course&reportId=422
+MMAE 714,Space Flight Dynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1045?entityType=Course&reportId=422
+MMAE 716,Digital Transformation Concepts,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1052?entityType=Course&reportId=422
+MMAE 717,Advanced Materials and Composites,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1248?entityType=Course&reportId=422
+MMAE 718,Advanced Systems Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1053?entityType=Course&reportId=422
+MMAE 719,Rocket Propulsion Fundamentals,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1019?entityType=Course&reportId=422
+MMED 820,Medicine Inpatient I Clerkship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/501?entityType=Course&reportId=422
+MMMM 501,Molecular Basis of Infection,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/513?entityType=Course&reportId=422
+MMMM 502,Molecular Basis of Cancer,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/502?entityType=Course&reportId=422
+MMMM 503,Bioethics in Research: Principles and Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/504?entityType=Course&reportId=422
+MMMM 504,Molecular Basis of Genetic Disease,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/509?entityType=Course&reportId=422
+MMMM 507,Critical Analysis of the Contemporary Concepts in Molecular Medicine,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/514?entityType=Course&reportId=422
+MMMM 508,Molecular Immunology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/505?entityType=Course&reportId=422
+MMMM 509,From the Bench to the Bedside: Drug Development and Clinical Trials,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/506?entityType=Course&reportId=422
+MMMM 511,Research Methods in Molecular Biomedicine,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/510?entityType=Course&reportId=422
+MMMM 513,Molecular Basis of Neurological Disorders,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/512?entityType=Course&reportId=422
+MMMM 603,Recombinant Drugs,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/507?entityType=Course&reportId=422
+MMMM 605,Developmental Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/511?entityType=Course&reportId=422
+MMMM 610,Natural Drugs,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/503?entityType=Course&reportId=422
+MMMM 690,Master Research Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/508?entityType=Course&reportId=422
+MOBG 830,Obstetrics and Gynecology Clerkship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/515?entityType=Course&reportId=422
+MOSP 641,Neuroscience,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/518?entityType=Course&reportId=422
+MOSP 642,Introduction to Psychiatry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/526?entityType=Course&reportId=422
+MOSP 731,Endocrine System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/520?entityType=Course&reportId=422
+MOSP 732,Digestion and Nutrition,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/521?entityType=Course&reportId=422
+MOSP 733,Hematology and Oncology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/522?entityType=Course&reportId=422
+MOSP 734,Skin and Musculoskeletal System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/524?entityType=Course&reportId=422
+MOSP 735,Reproductive and Developmental Biology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/523?entityType=Course&reportId=422
+MOSP 736,Clinical Problem Solving,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/517?entityType=Course&reportId=422
+MOSP 743,Cardiovascular System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/516?entityType=Course&reportId=422
+MOSP 744,Pulmonary System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/519?entityType=Course&reportId=422
+MOSP 745,Renal System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/525?entityType=Course&reportId=422
+MPA 602,Public Administration in Theory and Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/77?entityType=Course&reportId=422
+MPA 603,Economic Applications for Public Managers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/81?entityType=Course&reportId=422
+MPA 605,Research Methods for Public Managers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/78?entityType=Course&reportId=422
+MPA 607,Fiscal Management and Budgeting,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3298?entityType=Course&reportId=422
+MPA 609,Human Resource Policy and Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/76?entityType=Course&reportId=422
+MPA 610,Program Evaluation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3411?entityType=Course&reportId=422
+MPA 699,Master’s Project with Overseas Component,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/79?entityType=Course&reportId=422
+MPA-O 602I,Public Administration in Theory and Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/738?entityType=Course&reportId=422
+MPA-O 602II, Public Administration in Theory and Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/739?entityType=Course&reportId=422
+MPA-O 603I,Economic Applications for Public Managers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/848?entityType=Course&reportId=422
+MPA-O 603II,Economic Applications for Public Managers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/849?entityType=Course&reportId=422
+MPA-O 607I,Fiscal Management and Budgeting,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/740?entityType=Course&reportId=422
+MPA-O 607II,Fiscal Management and Budgeting,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/741?entityType=Course&reportId=422
+MPA-O 609I,Human Resource Policy and Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/781?entityType=Course&reportId=422
+MPA-O 609II,Human Resource Policy and Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/782?entityType=Course&reportId=422
+MPA-O 610I,Program Evaluation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/784?entityType=Course&reportId=422
+MPA-O 610II,Program Evaluation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/785?entityType=Course&reportId=422
+MPCB 601,Introduction to Being a Physician,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/527?entityType=Course&reportId=422
+MPCB 602,Basics of Medical Interviewing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/528?entityType=Course&reportId=422
+MPCB 603,Basics of Physical Examination,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/531?entityType=Course&reportId=422
+MPCB 605,Clinical Experiences I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/532?entityType=Course&reportId=422
+MPCB 701,Advanced Physical Examination II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/530?entityType=Course&reportId=422
+MPCB 703,Advanced Medical Interviewing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/529?entityType=Course&reportId=422
+MPCB 704,Clinical Procedures,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/533?entityType=Course&reportId=422
+MPCL 800,Pre-clerkship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/534?entityType=Course&reportId=422
+MPE 600,Internship in Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/736?entityType=Course&reportId=422
+MPE 608,Strategic Management and Leadership,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2339?entityType=Course&reportId=422
+MPE 609,Organizational Behavior in the Public Sector,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/473?entityType=Course&reportId=422
+MPE 610,National Identity and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/96?entityType=Course&reportId=422
+MPE 611,Benefit Cost Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/105?entityType=Course&reportId=422
+MPE 612,Policy Tools for Addressing Inequality and Demographic Change,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2342?entityType=Course&reportId=422
+MPE 615,Scientific Reasoning for Policy Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1378?entityType=Course&reportId=422
+MPE 616,Collaborative Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/691?entityType=Course&reportId=422
+MPE 619,Quantitative Analysis for Managers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/676?entityType=Course&reportId=422
+MPE 620,Circular Economy Strategy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1381?entityType=Course&reportId=422
+MPE 622,Case Study Research Method,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/678?entityType=Course&reportId=422
+MPE 628,Good Governance and Corruption,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/94?entityType=Course&reportId=422
+MPE 632,Artificial Intelligence and Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1372?entityType=Course&reportId=422
+MPE 633,Big Data Applications in Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3457?entityType=Course&reportId=422
+MPE 635,Innovation Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3458?entityType=Course&reportId=422
+MPE 636,Social Entrepreneurship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3459?entityType=Course&reportId=422
+MPE 637,Policy Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3433?entityType=Course&reportId=422
+MPE 638,Contemporary Security Challenges in Central Asia and Beyond,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/98?entityType=Course&reportId=422
+MPE 641,Globalisation and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/107?entityType=Course&reportId=422
+MPE 646,Communications for Public Leadership,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/99?entityType=Course&reportId=422
+MPE 649,Public Sector Innovation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/471?entityType=Course&reportId=422
+MPE 651,Agricultural Policy Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3304?entityType=Course&reportId=422
+MPE 660,Health System and Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3305?entityType=Course&reportId=422
+MPE 670,Behavioural Insights and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/103?entityType=Course&reportId=422
+MPE 671,Game Theory and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/104?entityType=Course&reportId=422
+MPE 672,"The Third Sector: civil society, nonprofit organizations, and voluntary action",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/97?entityType=Course&reportId=422
+MPE 673,Development Assistance and Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/95?entityType=Course&reportId=422
+MPE 681,Natural Resources Policy and Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/697?entityType=Course&reportId=422
+MPE 682,Sustainable Development and Environmental Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/106?entityType=Course&reportId=422
+MPE 683,Energy Systems and Climate Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/695?entityType=Course&reportId=422
+MPE 684,Global Energy Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/696?entityType=Course&reportId=422
+MPE 685,Water Resources Policy and Management,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/699?entityType=Course&reportId=422
+MPE 688,New Technologies and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3399?entityType=Course&reportId=422
+MPED 832,Pediatric Clerkship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/535?entityType=Course&reportId=422
+MPE-O 611I,Benefit Cost Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/787?entityType=Course&reportId=422
+MPE-O 611II,Benefit Cost Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/789?entityType=Course&reportId=422
+MPP 601,Microeconomics and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/89?entityType=Course&reportId=422
+MPP 602,Macroeconomics and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/88?entityType=Course&reportId=422
+MPP 603,Data Analytics in Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3407?entityType=Course&reportId=422
+MPP 611,Statistics for Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/91?entityType=Course&reportId=422
+MPP 613,Policy Research Design and Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2344?entityType=Course&reportId=422
+MPP 621,Public Policy and Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2345?entityType=Course&reportId=422
+MPP 631,Politics and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/84?entityType=Course&reportId=422
+MPP 641,Public Management and Leadership,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/83?entityType=Course&reportId=422
+MPP 699,Policy Analysis Exercise with Overseas Component,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/86?entityType=Course&reportId=422
+MPP 699,0 Policy Analysis Exercise with Overseas Component,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/87?entityType=Course&reportId=422
+MPPS 631,Medical Ethics and Professionalism,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/536?entityType=Course&reportId=422
+MPPS 632,Behavioral Medicine,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/538?entityType=Course&reportId=422
+MPPS 633,English-Russian-Kazakh Medical Terminology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/539?entityType=Course&reportId=422
+MPPS 733,Health System and Administration,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/537?entityType=Course&reportId=422
+MPSY 850,Psychiatry Clerkship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/540?entityType=Course&reportId=422
+MPTX 501,Organ System and Common Diseases,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/541?entityType=Course&reportId=422
+MPTX 502,Cellular Communications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/544?entityType=Course&reportId=422
+MPTX 503,Principles of Pharmacology and Toxicology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/545?entityType=Course&reportId=422
+MPTX 504,Systemic Pharmacology I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/554?entityType=Course&reportId=422
+MPTX 505,Drug Discovery I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/549?entityType=Course&reportId=422
+MPTX 506,Systemic Pharmacology II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/555?entityType=Course&reportId=422
+MPTX 507,Applied Toxicology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/546?entityType=Course&reportId=422
+MPTX 508,Research Methods in Pharmacology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/547?entityType=Course&reportId=422
+MPTX 509,Drug Discovery and Development II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/550?entityType=Course&reportId=422
+MPTX 511E,Environmental Toxicology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/542?entityType=Course&reportId=422
+MPTX 601,Biostatistics and Critical Appraisal,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/543?entityType=Course&reportId=422
+MPTX 602,Current Topics in Pharmacology and Toxicology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/551?entityType=Course&reportId=422
+MPTX 603,Introduction to Research Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/552?entityType=Course&reportId=422
+MPTX 604E,Scientific Writing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/548?entityType=Course&reportId=422
+MPTX 701,Research Project and Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/553?entityType=Course&reportId=422
+MSC 600,Research Methods and Ethics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1241?entityType=Course&reportId=422
+MSC 601,Technical Communication,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/952?entityType=Course&reportId=422
+MSC 602,Advanced Applied Mathematics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/985?entityType=Course&reportId=422
+MSC 615,Advanced Statistics and Probability,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1311?entityType=Course&reportId=422
+MSCP 720,Scholarly Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/556?entityType=Course&reportId=422
+MSF 01,Financial Modeling,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/480?entityType=Course&reportId=422
+MSF 05,Internship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/444?entityType=Course&reportId=422
+MSF 06,Banking and Credit,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/481?entityType=Course&reportId=422
+MSF 07,Economic Policy in Global Markets,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/441?entityType=Course&reportId=422
+MSF 08,Microeconomics for Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/442?entityType=Course&reportId=422
+MSF 10,Independent Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/446?entityType=Course&reportId=422
+MSF 11,Fintech,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/439?entityType=Course&reportId=422
+MSF 12,Financial Accounting,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/440?entityType=Course&reportId=422
+MSF 13,Industry Insights Initiative,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/698?entityType=Course&reportId=422
+MSMR 501,Musculoskeletal System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/569?entityType=Course&reportId=422
+MSMR 502,Nutrition in Sports and Exercise,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/566?entityType=Course&reportId=422
+MSMR 503,"Exercise Genetics, Physiology and Endocrinology",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/557?entityType=Course&reportId=422
+MSMR 504,Pharmacology in Sports and Rehabilitation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/570?entityType=Course&reportId=422
+MSMR 505,Exercise and Biomechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/572?entityType=Course&reportId=422
+MSMR 506,Seminar in Sports Medicine,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/558?entityType=Course&reportId=422
+MSMR 507,Management and Rehabilitation of Injuries,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/573?entityType=Course&reportId=422
+MSMR 508,Health Fitness and Wellbeing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/559?entityType=Course&reportId=422
+MSMR 509,Robots for Rehabilitation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/571?entityType=Course&reportId=422
+MSMR 510,Biostatistics and Epidemiology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/564?entityType=Course&reportId=422
+MSMR 511,Introduction to Research Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/560?entityType=Course&reportId=422
+MSMR 513,Internship in Sports Medicine and Rehabilitation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/574?entityType=Course&reportId=422
+MSMR 514,Adaptive Physical Activity,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/575?entityType=Course&reportId=422
+MSMR 515,Nutrition for Life,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/567?entityType=Course&reportId=422
+MSMR 516,Clinical and Motivational Interviewing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3299?entityType=Course&reportId=422
+MSMR 601,Psychology of Sports and Rehabilitation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/565?entityType=Course&reportId=422
+MSMR 602,Advances in Sports and Rehabilitation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/561?entityType=Course&reportId=422
+MSMR 603,Master Research Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/562?entityType=Course&reportId=422
+MSMR 701,Ethics and Professionalism,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/568?entityType=Course&reportId=422
+MSMR 702,Master Research Project Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2340?entityType=Course&reportId=422
+MSN 501,Theoretical Foundations of Advanced Nursing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3383?entityType=Course&reportId=422
+MSN 502,Advanced Physical and Health Assessment,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3373?entityType=Course&reportId=422
+MSN 503,"Statistics for Nursing Research, Evidence-Based Practice, and Quality Improvement",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3384?entityType=Course&reportId=422
+MSN 504,Informatics and Healthcare Technologies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3385?entityType=Course&reportId=422
+MSN 505,Health Policy and Advocacy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3386?entityType=Course&reportId=422
+MSN 506,"Nursing Research, Evidence-Based Practice, and Quality Improvement",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/829?entityType=Course&reportId=422
+MSN 507,Advanced Pathophysiology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/830?entityType=Course&reportId=422
+MSN 508,Advanced Pharmacology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/831?entityType=Course&reportId=422
+MSN 509,Learning and Teaching Strategies and Innovation in Nursing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/832?entityType=Course&reportId=422
+MSN 510,Population-Based Health Promotion and Clinical Prevention,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/833?entityType=Course&reportId=422
+MSRB 621,Evidence-Based Medicine I and Biostatistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/578?entityType=Course&reportId=422
+MSRB 622,Evidence-Based Medicine II and Biostatistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/579?entityType=Course&reportId=422
+MSRB 711,Population Health,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/576?entityType=Course&reportId=422
+MSRB 712,Applied Evidence-Based Medicine,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/577?entityType=Course&reportId=422
+MSRG 810,Surgery I Clerkship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/580?entityType=Course&reportId=422
+NUSM 101,Introduction to Medicine,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/581?entityType=Course&reportId=422
+NUSM 102,Biology for Medical Students I with Lab,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1346?entityType=Course&reportId=422
+NUSM 301,"Introduction to Immunology, Microbiology and Genetics",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/582?entityType=Course&reportId=422
+NUSM 302,Introduction to Statistics for Evidence-Based Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/593?entityType=Course&reportId=422
+NUSM 303,Introduction to Anatomy and Histology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/590?entityType=Course&reportId=422
+NUSM 310,Capstone Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/583?entityType=Course&reportId=422
+NUSM 401,Introduction to Being a Physician,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/584?entityType=Course&reportId=422
+NUSM 402,Medical Anatomy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/587?entityType=Course&reportId=422
+NUSM 403,Human Genetics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/592?entityType=Course&reportId=422
+NUSM 404,Cellular and Pathologic Basis of Disease,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/591?entityType=Course&reportId=422
+NUSM 405,Fuel Metabolism,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/586?entityType=Course&reportId=422
+NUSM 406,Immunology in Health and Disease,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/585?entityType=Course&reportId=422
+NUSM 407,Medical Microbiology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/588?entityType=Course&reportId=422
+NUSM 408,Pharmacology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/589?entityType=Course&reportId=422
+PER 101,Beginning Persian I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2737?entityType=Course&reportId=422
+PER 102,Beginning Persian II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2738?entityType=Course&reportId=422
+PER 201,Intermediate Persian I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2739?entityType=Course&reportId=422
+PER 202,Intermediate Persian II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2740?entityType=Course&reportId=422
+PETE 201,Fluid Mechanics and Thermodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/322?entityType=Course&reportId=422
+PETE 202,Transport Phenomena,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/303?entityType=Course&reportId=422
+PETE 203,Drilling Engineering with Laboratories,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/333?entityType=Course&reportId=422
+PETE 204,Reservoir Rock and Fluid Properties with Laboratories,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/318?entityType=Course&reportId=422
+PETE 301,Numerical Methods for Petroleum Engineers,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/323?entityType=Course&reportId=422
+PETE 302,Reservoir Engineering I with Laboratories,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/324?entityType=Course&reportId=422
+PETE 303,Well Logging and Formation Evaluation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/319?entityType=Course&reportId=422
+PETE 304,Well Completion and Stimulation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/334?entityType=Course&reportId=422
+PETE 305,Well Test Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/325?entityType=Course&reportId=422
+PETE 306,Reservoir Engineering II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/316?entityType=Course&reportId=422
+PETE 307,Production Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/326?entityType=Course&reportId=422
+PETE 311,Reservoir Simulation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/338?entityType=Course&reportId=422
+PETE 400,Capstone Design Project I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/327?entityType=Course&reportId=422
+PETE 404,Petroleum Geomechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/320?entityType=Course&reportId=422
+PETE 405,Enhanced Oil Recovery,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/304?entityType=Course&reportId=422
+PETE 407,Capstone Design Project II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/328?entityType=Course&reportId=422
+PETE 408,Gas Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/344?entityType=Course&reportId=422
+PETE 409,Surface Facilities,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3344?entityType=Course&reportId=422
+PETE 501,Foundations of Petroleum Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/317?entityType=Course&reportId=422
+PETE 502,Petroleum Geology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/343?entityType=Course&reportId=422
+PETE 503,Fluid Flow Through Porous Media,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/305?entityType=Course&reportId=422
+PETE 504,Advanced Formation Evaluation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/321?entityType=Course&reportId=422
+PETE 505,Advanced Drilling Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/335?entityType=Course&reportId=422
+PETE 506,Advanced Reservoir Simulation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/339?entityType=Course&reportId=422
+PETE 507,Advanced Reservoir Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/329?entityType=Course&reportId=422
+PETE 508,Advanced Production Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/306?entityType=Course&reportId=422
+PETE 509,Advanced Well Testing and Evaluation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/330?entityType=Course&reportId=422
+PETE 600,Thesis I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/307?entityType=Course&reportId=422
+PETE 601,Petroleum Data Analytics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/340?entityType=Course&reportId=422
+PETE 602,Research Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/336?entityType=Course&reportId=422
+PETE 606,Advanced Enhanced Oil Recovery,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/308?entityType=Course&reportId=422
+PETE 613,Unconventional Resources Drilling,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/337?entityType=Course&reportId=422
+PETE 614,"Introduction to Geospatial, Earth Observation and Surveying Technologies for Onshore and Marine Petroleum and Mining Industry",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/332?entityType=Course&reportId=422
+PETE 620,Thesis II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/309?entityType=Course&reportId=422
+PETE 701,Advanced Well Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/310?entityType=Course&reportId=422
+PETE 702,Current Research Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/311?entityType=Course&reportId=422
+PETE 703,Advanced Reservoir Engineering,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/331?entityType=Course&reportId=422
+PETE 801,Advanced Reservoir Simulation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/341?entityType=Course&reportId=422
+PETE 802,Fluid Flow Through Porous Media,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/312?entityType=Course&reportId=422
+PETE 803,Advanced Enhanced Oil Recovery,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/313?entityType=Course&reportId=422
+PETE 805,Special Topics in Petroleum Engineering : Data Analytics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/342?entityType=Course&reportId=422
+PETE 890,Doctoral Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/314?entityType=Course&reportId=422
+PETE 890,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/315?entityType=Course&reportId=422
+PHDBS 701,Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/598?entityType=Course&reportId=422
+PHDBS 701,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/599?entityType=Course&reportId=422
+PHDBS 702,Molecular Basis of Health and Disease,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/600?entityType=Course&reportId=422
+PHDBS 703,Biomedical Research Analysis and Design of Experimentation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/601?entityType=Course&reportId=422
+PHDBS 704,NUSOM Seminar (Final Semester),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/595?entityType=Course&reportId=422
+PHDBS 704,0 NUSOM Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/596?entityType=Course&reportId=422
+PHDBS 705,"Biosafety, Animal Welfare and Ethics",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/602?entityType=Course&reportId=422
+PHDBS 706,Advanced Biomedical Research Analysis and Design of Experimentation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/603?entityType=Course&reportId=422
+PHDBS 707,Publication Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/604?entityType=Course&reportId=422
+PHDBS 708,Writing for Biomedical Sciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/610?entityType=Course&reportId=422
+PHDBS 709,Molecular Basis of Infection,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/606?entityType=Course&reportId=422
+PHDBS 710,Molecular Pathology of Cancer,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/597?entityType=Course&reportId=422
+PHDBS 711,Molecular Basis of Genetic Disease,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/608?entityType=Course&reportId=422
+PHDBS 712,Molecular Immunology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/607?entityType=Course&reportId=422
+PHDBS 713,From the Bench to the Bedside: Drug Development and Clinical Trials,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/605?entityType=Course&reportId=422
+PHDBS 715,Molecular Basis of Neurological Disorders,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/609?entityType=Course&reportId=422
+PHDBS 717,Organ System and Common Diseases,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/594?entityType=Course&reportId=422
+PHDBS 718,Principles of Pharmacology and Toxicology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/611?entityType=Course&reportId=422
+PHDBS 719,Systemic Pharmacology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/612?entityType=Course&reportId=422
+PHDBS 721,Drug Discovery I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/613?entityType=Course&reportId=422
+PHDBS 722,Systemic Pharmacology II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/614?entityType=Course&reportId=422
+PHDBS 723,Drug Addiction and Toxicology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/615?entityType=Course&reportId=422
+PHDGH 701,Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/618?entityType=Course&reportId=422
+PHDGH 701,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/619?entityType=Course&reportId=422
+PHDGH 702,Foundations of Global Health,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/620?entityType=Course&reportId=422
+PHDGH 703,Health Policy and Systems in Global Health,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/621?entityType=Course&reportId=422
+PHDGH 704,NUSOM Seminar in Global Health,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/616?entityType=Course&reportId=422
+PHDGH 704,0 NUSOM Seminar in Global Health,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/617?entityType=Course&reportId=422
+PHDGH 705,Global Health into Action,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/622?entityType=Course&reportId=422
+PHDGH 706,Methods in Global Health Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/626?entityType=Course&reportId=422
+PHDGH 707,Implementation Science in Global Health,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/624?entityType=Course&reportId=422
+PHDGH 708,Advanced Methods in Global Health Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/627?entityType=Course&reportId=422
+PHDGH 709,Critical Appraisal in Global Health,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/625?entityType=Course&reportId=422
+PHDGH 710,Writing for Health Sciences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/623?entityType=Course&reportId=422
+PHIL 101,Introduction to Philosophy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2940?entityType=Course&reportId=422
+PHIL 141,Critical Thinking,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3140?entityType=Course&reportId=422
+PHIL 160,Philosophy of Religion,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3141?entityType=Course&reportId=422
+PHIL 210,Ethics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2807?entityType=Course&reportId=422
+PHIL 223,Philosophy of Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2957?entityType=Course&reportId=422
+PHIL 225,Truth and Reality,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2808?entityType=Course&reportId=422
+PHIL 231,Global Justice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3133?entityType=Course&reportId=422
+PHIL 232,Philosophy of Law,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3135?entityType=Course&reportId=422
+PHIL 240,Formal Logic,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3139?entityType=Course&reportId=422
+PHIL 314,Free Will and Moral Responsibility,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2938?entityType=Course&reportId=422
+PHIL 315,Philosophy of Agency,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2939?entityType=Course&reportId=422
+PHIL 320,"Truth, Knowledge and Belief",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2809?entityType=Course&reportId=422
+PHIL 361,Philosophy of Language,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2958?entityType=Course&reportId=422
+PHIL 362,Philosophy of Mind,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2959?entityType=Course&reportId=422
+PHIL 431,Human Rights and Cultural Differences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3134?entityType=Course&reportId=422
+PHIL 575,Philosophy of Art,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2941?entityType=Course&reportId=422
+PHYS 161,Physics I for Scientists and Engineers with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2572?entityType=Course&reportId=422
+PHYS 162,Physics II for Scientists and Engineers with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2573?entityType=Course&reportId=422
+PHYS 201,Introductory Astronomy I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2574?entityType=Course&reportId=422
+PHYS 202,Introductory Astrophysics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2575?entityType=Course&reportId=422
+PHYS 221,Classical Mechanics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2623?entityType=Course&reportId=422
+PHYS 222,Classical Mechanics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2624?entityType=Course&reportId=422
+PHYS 261,Modern Physics with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2461?entityType=Course&reportId=422
+PHYS 270,Computational Physics with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2677?entityType=Course&reportId=422
+PHYS 280,Thermodynamics and Statistical Physics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3283?entityType=Course&reportId=422
+PHYS 291,Introduction to Quantum Technologies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2448?entityType=Course&reportId=422
+PHYS 299,Research Project and Internship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2449?entityType=Course&reportId=422
+PHYS 315,Mathematical Methods of Physics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2465?entityType=Course&reportId=422
+PHYS 361,Classical Electrodynamics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2952?entityType=Course&reportId=422
+PHYS 362,Classical Electrodynamics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2953?entityType=Course&reportId=422
+PHYS 370,Optics with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2386?entityType=Course&reportId=422
+PHYS 395,Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2445?entityType=Course&reportId=422
+PHYS 399,Physics Research Project,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2446?entityType=Course&reportId=422
+PHYS 451,Quantum Mechanics I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3127?entityType=Course&reportId=422
+PHYS 452,Quantum Mechanics II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3128?entityType=Course&reportId=422
+PHYS 462,Field Theories in Physics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2627?entityType=Course&reportId=422
+PHYS 463,Astrophysics and General Relativity,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2954?entityType=Course&reportId=422
+PHYS 465,Advanced Experimental Physics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2387?entityType=Course&reportId=422
+PHYS 470,Introduction to Optoelectronics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2462?entityType=Course&reportId=422
+PHYS 473,Introduction to Solid State Physics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3286?entityType=Course&reportId=422
+PHYS 483,Statistical Mechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2951?entityType=Course&reportId=422
+PHYS 491,Directed Study of Advanced Physics Topics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2447?entityType=Course&reportId=422
+PHYS 498,Honors Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3125?entityType=Course&reportId=422
+PHYS 499,Honors Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3126?entityType=Course&reportId=422
+PHYS 505,Classical Mechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2626?entityType=Course&reportId=422
+PHYS 510,Quantum Mechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3123?entityType=Course&reportId=422
+PHYS 511,Computational Modeling and Simulation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2463?entityType=Course&reportId=422
+PHYS 515,Classical Electrodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2955?entityType=Course&reportId=422
+PHYS 520,Statistical Physics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3284?entityType=Course&reportId=422
+PHYS 530,Solid State Physics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3285?entityType=Course&reportId=422
+PHYS 550,Advanced Mathematical Physics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2464?entityType=Course&reportId=422
+PHYS 563,General Relativity,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2625?entityType=Course&reportId=422
+PHYS 565,Advanced Physics Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2388?entityType=Course&reportId=422
+PHYS 570,Introduction to Optoelectronics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2460?entityType=Course&reportId=422
+PHYS 591,Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2444?entityType=Course&reportId=422
+PHYS 600,Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2674?entityType=Course&reportId=422
+PHYS 692,Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2675?entityType=Course&reportId=422
+PHYS 700,Doctoral Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2678?entityType=Course&reportId=422
+PHYS 700,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2676?entityType=Course&reportId=422
+PHYS 701,Current Research Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2389?entityType=Course&reportId=422
+PHYS 705,Classical Mechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2622?entityType=Course&reportId=422
+PHYS 710,Quantum Mechanics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3124?entityType=Course&reportId=422
+PHYS 711,Computational Modeling and Simulation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2466?entityType=Course&reportId=422
+PHYS 715,Classical Electrodynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2956?entityType=Course&reportId=422
+PHYS 720,Statistical Physics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3287?entityType=Course&reportId=422
+PHYS 730,Solid State Physics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3288?entityType=Course&reportId=422
+PHYS 750,Advanced Mathematical Physics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2467?entityType=Course&reportId=422
+PHYS 763,General Relativity,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2621?entityType=Course&reportId=422
+PHYS 765,Advanced Physics Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2390?entityType=Course&reportId=422
+PHYS 770,Introduction to Optoelectronics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2459?entityType=Course&reportId=422
+PHYS 791,Research Methods and Ethics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2450?entityType=Course&reportId=422
+PLS 100,Introduction to the Politics of Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3105?entityType=Course&reportId=422
+PLS 101,Introduction to Political Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2980?entityType=Course&reportId=422
+PLS 102,The Political Challenges of Technologies and Science: An Introduction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2810?entityType=Course&reportId=422
+PLS 120,Introduction to Political Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2496?entityType=Course&reportId=422
+PLS 140,Introduction to Comparative Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2638?entityType=Course&reportId=422
+PLS 150,Introduction to International Relations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2476?entityType=Course&reportId=422
+PLS 210,Political Science Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2637?entityType=Course&reportId=422
+PLS 211,Quantitative Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2790?entityType=Course&reportId=422
+PLS 222,Global Justice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3131?entityType=Course&reportId=422
+PLS 312,Public Opinion and Elections,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2436?entityType=Course&reportId=422
+PLS 315,Political Game Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2547?entityType=Course&reportId=422
+PLS 321,Major Political Thinkers: Machiavelli,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2813?entityType=Course&reportId=422
+PLS 322,Russian Intellectual History (1762 - 1905),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2618?entityType=Course&reportId=422
+PLS 324,The Philosophies of Multiculturalism,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2814?entityType=Course&reportId=422
+PLS 326,Modern Political Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2498?entityType=Course&reportId=422
+PLS 327,Contemporary Political Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2499?entityType=Course&reportId=422
+PLS 328,Confucianism and the Development of Chinese Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2590?entityType=Course&reportId=422
+PLS 329,Anarchy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2497?entityType=Course&reportId=422
+PLS 330,Politics and Governance of Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2437?entityType=Course&reportId=422
+PLS 332,Islam and Politics in Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3190?entityType=Course&reportId=422
+PLS 338,U.S. Government and Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2979?entityType=Course&reportId=422
+PLS 340,Politics of East Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2844?entityType=Course&reportId=422
+PLS 341,Politics of Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2475?entityType=Course&reportId=422
+PLS 342,Political Corruption,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2978?entityType=Course&reportId=422
+PLS 343,Politics of Sub-Saharan Africa,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2869?entityType=Course&reportId=422
+PLS 345,"Revolutions, Social Movements, and Contentious Politics",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2506?entityType=Course&reportId=422
+PLS 351,International Political Economy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2904?entityType=Course&reportId=422
+PLS 352,International Relations Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2641?entityType=Course&reportId=422
+PLS 354,Introduction to International Law,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2391?entityType=Course&reportId=422
+PLS 355,European Union: Institutions and Policies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2906?entityType=Course&reportId=422
+PLS 356,International Politics of the Korean Peninsula,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2789?entityType=Course&reportId=422
+PLS 360,Foreign Policy Analysis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2477?entityType=Course&reportId=422
+PLS 361,Memory Politics in East Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2788?entityType=Course&reportId=422
+PLS 362,"Science, Technology and International Affairs",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3103?entityType=Course&reportId=422
+PLS 363,Visual Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3104?entityType=Course&reportId=422
+PLS 365,Civil-Military Relations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2507?entityType=Course&reportId=422
+PLS 370,"Law, Politics and Society",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2392?entityType=Course&reportId=422
+PLS 371,Comparative Welfare States,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2905?entityType=Course&reportId=422
+PLS 372,Post-Soviet Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2393?entityType=Course&reportId=422
+PLS 373,Comparative Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2843?entityType=Course&reportId=422
+PLS 391,Intermediate Special Topics in Comparative Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2781?entityType=Course&reportId=422
+PLS 392,Politics of China,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2981?entityType=Course&reportId=422
+PLS 395,Independent Study,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2842?entityType=Course&reportId=422
+PLS 415,Maximum Likelihood Models,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2502?entityType=Course&reportId=422
+PLS 416,Experimental Political Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2787?entityType=Course&reportId=422
+PLS 417,Scientific Research in Political Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2546?entityType=Course&reportId=422
+PLS 420,Human Rights and Cultural Differences,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3132?entityType=Course&reportId=422
+PLS 422,Just War Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2811?entityType=Course&reportId=422
+PLS 423,Immigration Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2495?entityType=Course&reportId=422
+PLS 424,Issues in the Philosophy of Social Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2639?entityType=Course&reportId=422
+PLS 425,Feminist Political Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2503?entityType=Course&reportId=422
+PLS 426,"Hannah Arendt on Power, Violence, and Revolution",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2485?entityType=Course&reportId=422
+PLS 431,Politics and Governance of the Russian Federation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2435?entityType=Course&reportId=422
+PLS 432,Comparative Democratization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2640?entityType=Course&reportId=422
+PLS 433,Homeland Security,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2504?entityType=Course&reportId=422
+PLS 434,Text Analysis and Political Communication in the Information Age,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2841?entityType=Course&reportId=422
+PLS 436,State Capacity and State-Building,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2870?entityType=Course&reportId=422
+PLS 437,Nationalism and Multi-Ethnic Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2505?entityType=Course&reportId=422
+PLS 441,Advanced Topics in Comparative Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2780?entityType=Course&reportId=422
+PLS 445,Political Violence,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2642?entityType=Course&reportId=422
+PLS 446,The Politics of Immigration Control,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2520?entityType=Course&reportId=422
+PLS 447,Comparative Political Parties,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2521?entityType=Course&reportId=422
+PLS 448,Comparative Electoral System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2550?entityType=Course&reportId=422
+PLS 449,Politics and Governance of the Gulf,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2523?entityType=Course&reportId=422
+PLS 451,Advanced Topics in International Relations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2524?entityType=Course&reportId=422
+PLS 452,The United Nations System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2480?entityType=Course&reportId=422
+PLS 455,The Politics of Arms in International Relations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2522?entityType=Course&reportId=422
+PLS 457,International Security and Conflict,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2541?entityType=Course&reportId=422
+PLS 458,International Organization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2481?entityType=Course&reportId=422
+PLS 459,International Conflict Processes,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2540?entityType=Course&reportId=422
+PLS 460,Environmental Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2832?entityType=Course&reportId=422
+PLS 465,Politics of International Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2902?entityType=Course&reportId=422
+PLS 468,International Relations of Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2835?entityType=Course&reportId=422
+PLS 469,International Relations of Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3107?entityType=Course&reportId=422
+PLS 472,"Negotiation, Cooperation and Strategy",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2525?entityType=Course&reportId=422
+PLS 474,Public Choice and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2833?entityType=Course&reportId=422
+PLS 495,Research Practicum in PSIR,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2834?entityType=Course&reportId=422
+PLS 510,Quantitative Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2549?entityType=Course&reportId=422
+PLS 511,Qualitative Methods in Political Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2394?entityType=Course&reportId=422
+PLS 514,Qualitative Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3191?entityType=Course&reportId=422
+PLS 515,Maximum Likelihood Models,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2516?entityType=Course&reportId=422
+PLS 516,Experimental Political Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2784?entityType=Course&reportId=422
+PLS 517,Scientific Research in Political Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2542?entityType=Course&reportId=422
+PLS 522,Just War Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2815?entityType=Course&reportId=422
+PLS 523,Immigration Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2486?entityType=Course&reportId=422
+PLS 526,"Hannah Arendt on Power, Violence, and Revolution",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2487?entityType=Course&reportId=422
+PLS 531,Politics and Governance of the Russian Federation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2515?entityType=Course&reportId=422
+PLS 532,Comparative Democratization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2644?entityType=Course&reportId=422
+PLS 533,Homeland Security,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2517?entityType=Course&reportId=422
+PLS 534,Text Analysis and Political Communication in the Information Age,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2518?entityType=Course&reportId=422
+PLS 536,State Capacity and State-building,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2871?entityType=Course&reportId=422
+PLS 537,Nationalism and Multi-Ethnic Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2519?entityType=Course&reportId=422
+PLS 540,Core Seminar in Comparative Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2782?entityType=Course&reportId=422
+PLS 541,Advanced Topics in Comparative Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2783?entityType=Course&reportId=422
+PLS 545,Political Violence,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2643?entityType=Course&reportId=422
+PLS 546,The Politics of Immigration Control,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2512?entityType=Course&reportId=422
+PLS 547,Comparative Political Parties,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2513?entityType=Course&reportId=422
+PLS 548,Comparative Electoral System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2548?entityType=Course&reportId=422
+PLS 549,Politics and Governance of the Gulf,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2514?entityType=Course&reportId=422
+PLS 550,Core Seminar in IR,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2786?entityType=Course&reportId=422
+PLS 551,Advanced Topics in International Relations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2839?entityType=Course&reportId=422
+PLS 552,The United Nations System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2478?entityType=Course&reportId=422
+PLS 555,The Politics of Arms in International Relations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2510?entityType=Course&reportId=422
+PLS 557,International Security and Conflict,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2544?entityType=Course&reportId=422
+PLS 558,International Organization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2479?entityType=Course&reportId=422
+PLS 559,International Conflict Processes,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2543?entityType=Course&reportId=422
+PLS 560,Environmental Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2840?entityType=Course&reportId=422
+PLS 565,Politics of International Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2903?entityType=Course&reportId=422
+PLS 568,International Relations of Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2838?entityType=Course&reportId=422
+PLS 569,International Relations of Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3106?entityType=Course&reportId=422
+PLS 572,"Negotiation, Cooperation and Strategy",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2511?entityType=Course&reportId=422
+PLS 574,Public Choice and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2837?entityType=Course&reportId=422
+PLS 581,Independent Study in Political Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2488?entityType=Course&reportId=422
+PLS 596,Thesis Preparation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2489?entityType=Course&reportId=422
+PLS 597,Research for Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2490?entityType=Course&reportId=422
+PLS 598,MA Thesis I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2491?entityType=Course&reportId=422
+PLS 599,MA Thesis II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2492?entityType=Course&reportId=422
+PLS 710,Quantitative Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2836?entityType=Course&reportId=422
+PLS 711,Qualitative Methods in Political Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2395?entityType=Course&reportId=422
+PLS 715,Maximum Likelihood Models,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2509?entityType=Course&reportId=422
+PLS 716,Experimental Political Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2785?entityType=Course&reportId=422
+PLS 717,Scientific Research in Political Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2545?entityType=Course&reportId=422
+PLS 722,Just War Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2812?entityType=Course&reportId=422
+PLS 723,Immigration Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2493?entityType=Course&reportId=422
+PLS 726,"Hannah Arendt on Power, Violence, and Revolution",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2494?entityType=Course&reportId=422
+PLS 731,Politics and Governance of the Russian Federation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2508?entityType=Course&reportId=422
+PLS 732,Comparative Democratization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2645?entityType=Course&reportId=422
+PLS 733,Homeland Security,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2527?entityType=Course&reportId=422
+PLS 734,Text Analysis and Political Communication in the Information Age,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2528?entityType=Course&reportId=422
+PLS 737,Nationalism and Multi-Ethnic Governance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2529?entityType=Course&reportId=422
+PLS 740,Core Seminar in Comparative Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2778?entityType=Course&reportId=422
+PLS 741,Advanced Topics in Comparative Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2779?entityType=Course&reportId=422
+PLS 745,Political Violence,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2646?entityType=Course&reportId=422
+PLS 746,The Politics of Immigration Control,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2530?entityType=Course&reportId=422
+PLS 747,Comparative Political Parties,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2531?entityType=Course&reportId=422
+PLS 748,Comparative Electoral System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2551?entityType=Course&reportId=422
+PLS 749,Politics and Governance of the Gulf,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2532?entityType=Course&reportId=422
+PLS 750,Core Seminar in IR,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2791?entityType=Course&reportId=422
+PLS 751,Advanced Topics in International Relations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2828?entityType=Course&reportId=422
+PLS 752,The United Nations System,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2483?entityType=Course&reportId=422
+PLS 755,The Politics of Arms in International Relations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2526?entityType=Course&reportId=422
+PLS 757,International Security and Conflict,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2538?entityType=Course&reportId=422
+PLS 758,International Organization,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2482?entityType=Course&reportId=422
+PLS 759,International Conflict Processes,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2539?entityType=Course&reportId=422
+PLS 760,Environmental Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2829?entityType=Course&reportId=422
+PLS 765,Politics of International Finance,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2901?entityType=Course&reportId=422
+PLS 768,Internation Relations of Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2830?entityType=Course&reportId=422
+PLS 769,International Relations of Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3102?entityType=Course&reportId=422
+PLS 774,Public Choice and Public Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2831?entityType=Course&reportId=422
+PLS 781,Independent Study in Political Science,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2777?entityType=Course&reportId=422
+POL 101,Beginning Polish,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2714?entityType=Course&reportId=422
+POL 102,Beginning Polish II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2715?entityType=Course&reportId=422
+PUBH 501,Principles of Public Health Problem Solving,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/641?entityType=Course&reportId=422
+PUBH 511,Inferential Biostatistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/632?entityType=Course&reportId=422
+PUBH 512,Biostatistical Modeling and Sampling,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/633?entityType=Course&reportId=422
+PUBH 521,Principles of Analytical Epidemiology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/644?entityType=Course&reportId=422
+PUBH 522,Advanced Analytical Epidemiology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/645?entityType=Course&reportId=422
+PUBH 528,Qualitative Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/637?entityType=Course&reportId=422
+PUBH 551,"Health Services Management, Health Economics and Health Policy",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/638?entityType=Course&reportId=422
+PUBH 552,Principles of Heath Economics and Policy,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/639?entityType=Course&reportId=422
+PUBH 561,Graduate Research Seminar I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/634?entityType=Course&reportId=422
+PUBH 599,Global Nutrition and Sustainability,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/628?entityType=Course&reportId=422
+PUBH 601,Health Education and Promotion,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/642?entityType=Course&reportId=422
+PUBH 631,Social and Behavioral Sciences in Public Health,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/643?entityType=Course&reportId=422
+PUBH 633,Methods in Public Health,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/635?entityType=Course&reportId=422
+PUBH 641,Problem Investigations in Environmental Health,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/636?entityType=Course&reportId=422
+PUBH 651,Risk Management in Health Care,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/640?entityType=Course&reportId=422
+PUBH 652,Applied Methods in Health Services Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/631?entityType=Course&reportId=422
+PUBH 681,Master's Project Planning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/629?entityType=Course&reportId=422
+PUBH 682,Master's Project Implementation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/630?entityType=Course&reportId=422
+REL 110,Introduction to World Religions,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2991?entityType=Course&reportId=422
+REL 212,Buddhist Religious Traditions,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2992?entityType=Course&reportId=422
+REL 215,What is Islam? Anthropological Perspectives,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3093?entityType=Course&reportId=422
+REL 261,History of Islam (570s to 1258),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2586?entityType=Course&reportId=422
+REL 263,The History of Islam II: Islam in the Modern World,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3091?entityType=Course&reportId=422
+REL 268,Women and Islam in Central Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3092?entityType=Course&reportId=422
+REL 273,History of Sufism in the Middle East and Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2587?entityType=Course&reportId=422
+REL 320,The Crusades,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2588?entityType=Course&reportId=422
+REL 329,Women in Islamic History,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3089?entityType=Course&reportId=422
+REL 332,Islam and Politics in Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3189?entityType=Course&reportId=422
+REL 341,Eastern Christianity,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2619?entityType=Course&reportId=422
+REL 435,The Archaeology of Ritual,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2873?entityType=Course&reportId=422
+REL 440,Religions in the Soviet and Post-Soviet Eras,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2994?entityType=Course&reportId=422
+REL 451,Conversion to Islam in Medieval and Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2589?entityType=Course&reportId=422
+REL 462,History of Islam Under Russian Rule,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3090?entityType=Course&reportId=422
+REL 535,The Archaeology of Ritual,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2874?entityType=Course&reportId=422
+REL 540,Religions in the Soviet and Post-Soviet Eras,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2993?entityType=Course&reportId=422
+REL 551,Conversion to Islam in Medieval and Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2584?entityType=Course&reportId=422
+REL 562,History of Islam Under Russian Rule,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3088?entityType=Course&reportId=422
+REL 740,Religions in the Soviet and Post-Soviet Eras,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2990?entityType=Course&reportId=422
+REL 751,Conversion to Islam in Medieval and Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2585?entityType=Course&reportId=422
+ROBT 201,Mechanics: Statics and Dynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/873?entityType=Course&reportId=422
+ROBT 202,System Dynamics and Modeling,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1139?entityType=Course&reportId=422
+ROBT 203,Electrical and Electronic Circuits I with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1290?entityType=Course&reportId=422
+ROBT 204,Electrical and Electronic Circuits II with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1291?entityType=Course&reportId=422
+ROBT 205,Signals and Sensing with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1138?entityType=Course&reportId=422
+ROBT 206,Microcontrollers with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/978?entityType=Course&reportId=422
+ROBT 301,Mechanical Design I with CAD and Machining Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/874?entityType=Course&reportId=422
+ROBT 303,Linear Control Theory with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1285?entityType=Course&reportId=422
+ROBT 304,Electromechanical Systems with Laboratory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/875?entityType=Course&reportId=422
+ROBT 305,Embedded Systems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/912?entityType=Course&reportId=422
+ROBT 307,Power Electronics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1288?entityType=Course&reportId=422
+ROBT 308,Industrial Automation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1286?entityType=Course&reportId=422
+ROBT 310,Image Processing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1322?entityType=Course&reportId=422
+ROBT 312,Robotics I: Kinematics and Dynamics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1184?entityType=Course&reportId=422
+ROBT 391,Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1142?entityType=Course&reportId=422
+ROBT 399,Internship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1143?entityType=Course&reportId=422
+ROBT 402,Robotic/Mechatronic System Design,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/951?entityType=Course&reportId=422
+ROBT 403,"Robotics II: Control, Modeling and Learning with Laboratory",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1183?entityType=Course&reportId=422
+ROBT 407,Machine Learning with Applications,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/977?entityType=Course&reportId=422
+ROBT 414,Human-Robot Interaction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/924?entityType=Course&reportId=422
+ROBT 491,Capstone Project I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1140?entityType=Course&reportId=422
+ROBT 492,Capstone Project II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1141?entityType=Course&reportId=422
+ROBT 501,Robot Manipulation and Mobility,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1185?entityType=Course&reportId=422
+ROBT 502,Robot Perception and Vision,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1081?entityType=Course&reportId=422
+ROBT 503,Dynamic Systems and Control,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1082?entityType=Course&reportId=422
+ROBT 611,Industrial Robotics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/911?entityType=Course&reportId=422
+ROBT 613,Brain-Machine Interfaces,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/979?entityType=Course&reportId=422
+ROBT 615,Optimal Control and Planning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1289?entityType=Course&reportId=422
+ROBT 691,Thesis Proposal,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1283?entityType=Course&reportId=422
+ROBT 692,Thesis,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1284?entityType=Course&reportId=422
+ROBT 700,Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1180?entityType=Course&reportId=422
+ROBT 700,0 Thesis Research,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1181?entityType=Course&reportId=422
+ROBT 701,Advanced Robot Manipulation and Mobility,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1182?entityType=Course&reportId=422
+ROBT 702,Advanced Robot Perception and Vision,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1321?entityType=Course&reportId=422
+ROBT 703,Advanced Optimal Control and Planning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1287?entityType=Course&reportId=422
+ROBT 709,Advanced Robot Dynamics and Control,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1080?entityType=Course&reportId=422
+ROBT 722,Current Research Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1179?entityType=Course&reportId=422
+SEDS 502,Teaching Practicum,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1175?entityType=Course&reportId=422
+SEDS 503,Laboratory Practicum,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/976?entityType=Course&reportId=422
+SEDS 591,Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/925?entityType=Course&reportId=422
+SEDS 592,Research Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/1079?entityType=Course&reportId=422
+SMG 100,Introduction to Natural Resource Extraction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/346?entityType=Course&reportId=422
+SMG 200,Resource Economics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3455?entityType=Course&reportId=422
+SMG 210,Strength of Materials,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/347?entityType=Course&reportId=422
+SMG 400,Engineering Economics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/350?entityType=Course&reportId=422
+SMG 710,Advanced Statistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/348?entityType=Course&reportId=422
+SOC 101,Introduction to Sociology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2868?entityType=Course&reportId=422
+SOC 115,Global Social Problems,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3059?entityType=Course&reportId=422
+SOC 201,Social Science Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2872?entityType=Course&reportId=422
+SOC 203,Quantitative Methods in Sociology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3060?entityType=Course&reportId=422
+SOC 210,Gender and Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2422?entityType=Course&reportId=422
+SOC 212,Food and Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2875?entityType=Course&reportId=422
+SOC 213,Work and Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2867?entityType=Course&reportId=422
+SOC 214,Qualitative Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3029?entityType=Course&reportId=422
+SOC 215,Sociology of Race and Ethnicity,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3110?entityType=Course&reportId=422
+SOC 217,Sociology of the Family,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3061?entityType=Course&reportId=422
+SOC 220,"Science, Technology, and Society",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3062?entityType=Course&reportId=422
+SOC 221,International Migration,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3112?entityType=Course&reportId=422
+SOC 223,Social Movements: How People Make Change,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2946?entityType=Course&reportId=422
+SOC 301,Classical Sociological Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2743?entityType=Course&reportId=422
+SOC 310,Social Inequality,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2969?entityType=Course&reportId=422
+SOC 317,Economy and Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2945?entityType=Course&reportId=422
+SOC 318,Sexuality and Gender in a Transnational World,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3063?entityType=Course&reportId=422
+SOC 320,Organized Crime and Corruption,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2741?entityType=Course&reportId=422
+SOC 322,Digital Media Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2583?entityType=Course&reportId=422
+SOC 375,Inner Asian Frontiers of China: A Cultural Perspective,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3186?entityType=Course&reportId=422
+SOC 386,Social Challenges of Climate Change,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2944?entityType=Course&reportId=422
+SOC 400,Research Assistance in Sociology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3065?entityType=Course&reportId=422
+SOC 401,Research Assistance in Sociology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3066?entityType=Course&reportId=422
+SOC 402,Research Assistance in Sociology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3067?entityType=Course&reportId=422
+SOC 403,Research Assistance in Sociology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3068?entityType=Course&reportId=422
+SOC 404,Research Assistance in Sociology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3069?entityType=Course&reportId=422
+SOC 410,Violence Against Women: An Intersectional Approach,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3111?entityType=Course&reportId=422
+SOC 411,Citizenship in Eurasia: Political Sociology of Civic Belonging,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2947?entityType=Course&reportId=422
+SOC 412,Approaches to Global Development,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3027?entityType=Course&reportId=422
+SOC 415,Social Problems and Issues in Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3064?entityType=Course&reportId=422
+SOC 416,Sociology of Punishment,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2742?entityType=Course&reportId=422
+SOC 420,Applied Policy Analysis: Tools and Perspectives,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2534?entityType=Course&reportId=422
+SOC 421,Informal Practices and Social Order in Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2744?entityType=Course&reportId=422
+SOC 425,Modern Sociological Theory,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2970?entityType=Course&reportId=422
+SOC 482,"Climate Change, Future Energy, and Sustainability",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3028?entityType=Course&reportId=422
+SOC 498,Capstone Seminar Part I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2582?entityType=Course&reportId=422
+SOC 499,Capstone Seminar II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2406?entityType=Course&reportId=422
+SOC 510,Social Inequality,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3070?entityType=Course&reportId=422
+SOC 511,Citizenship in Eurasia: Political Sociology of Civic Belonging,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2943?entityType=Course&reportId=422
+SOC 514,Qualitative Research Methods,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3071?entityType=Course&reportId=422
+SOC 515,Social Problems and Issues in Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3072?entityType=Course&reportId=422
+SOC 521,Informal Practices and Social Order in Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2745?entityType=Course&reportId=422
+SOC 710,Social Inequality,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3073?entityType=Course&reportId=422
+SOC 725,COVID-19: The Sociocultural Aspects of a Pandemic,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3074?entityType=Course&reportId=422
+SPA 101,Beginning Spanish I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2668?entityType=Course&reportId=422
+SPA 102,Beginning Spanish II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2669?entityType=Course&reportId=422
+SPA 201,Intermediate Spanish I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2670?entityType=Course&reportId=422
+SPA 202,Intermediate Spanish II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2671?entityType=Course&reportId=422
+SPA 254,"Superstition, Magical Realism, and Horror in Hispanic Culture",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2818?entityType=Course&reportId=422
+SPA 311,Colloquial Spanish,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2666?entityType=Course&reportId=422
+SPA 314,Advanced Spanish Grammar and Composition,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2667?entityType=Course&reportId=422
+SPA 351,Literature and Film of the Postcolonial World,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2819?entityType=Course&reportId=422
+TUR 100,"Languages, Cultures, and Communities of the Turkic World",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3227?entityType=Course&reportId=422
+TUR 224,"WWI and the World: Causes, Conduct and the Consequences of WWI",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2773?entityType=Course&reportId=422
+TUR 230,Literatures of Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3228?entityType=Course&reportId=422
+TUR 231,Istanbul in Literature and Culture,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2708?entityType=Course&reportId=422
+TUR 235,Turkish Poetry in Translation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2709?entityType=Course&reportId=422
+TUR 271,History of the Ottoman Empire,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2774?entityType=Course&reportId=422
+TUR 272,Modern Turkey: from the Ottoman Empire to the Turkish Republic,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2775?entityType=Course&reportId=422
+TUR 280,Introduction to Turkic Historical and Comparative Linguistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3250?entityType=Course&reportId=422
+TUR 301,Introduction to Old Turkic,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3219?entityType=Course&reportId=422
+TUR 305,Introduction to Chagatay and Ottoman Turkish,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3220?entityType=Course&reportId=422
+TUR 375,Inner Asian Frontiers of China: A Cultural Perspective,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3184?entityType=Course&reportId=422
+TUR 380,Linguistic and Cultural Diversity in Contemporary China: From Beijing to Xinjiang,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3185?entityType=Course&reportId=422
+TUR 411,Advanced Readings in Turkish Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2710?entityType=Course&reportId=422
+TUR 412,Advanced Turkish in Media and Politics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2711?entityType=Course&reportId=422
+TUR 451,The Turkish Novel,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2712?entityType=Course&reportId=422
+TUR 454,Turkestan in the Nineteenth Century,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3221?entityType=Course&reportId=422
+TUR 455,Eurasian Environments,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3222?entityType=Course&reportId=422
+TUR 552,"Proseminar in Eurasian History, 552-1917",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3225?entityType=Course&reportId=422
+TUR 554,Turkestan in the Nineteenth Century,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3223?entityType=Course&reportId=422
+TUR 752,"Proseminar in Eurasian History, 552-1917",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3226?entityType=Course&reportId=422
+TUR 775,Doctoral Topic in Turkic Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3224?entityType=Course&reportId=422
+WCS 101,Communication and Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3148?entityType=Course&reportId=422
+WCS 135,Introduction to Visual Communication,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2537?entityType=Course&reportId=422
+WCS 150,Rhetoric and Composition,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3149?entityType=Course&reportId=422
+WCS 200,Introduction to Public Speaking,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3150?entityType=Course&reportId=422
+WCS 201,Introduction to Journalism,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3129?entityType=Course&reportId=422
+WCS 203,Interpersonal Communication,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3142?entityType=Course&reportId=422
+WCS 204,Gender and Communication,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3143?entityType=Course&reportId=422
+WCS 205,Intercultural Communication,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3346?entityType=Course&reportId=422
+WCS 210,Technical and Professional Writing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3130?entityType=Course&reportId=422
+WCS 220,Science Writing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3251?entityType=Course&reportId=422
+WCS 230,"Say What you Mean: Clarity, Precision, and Style in Academic Writing",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2816?entityType=Course&reportId=422
+WCS 240,Writing for Digital Media,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2484?entityType=Course&reportId=422
+WCS 250,Advanced Rhetoric and Composition,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2457?entityType=Course&reportId=422
+WCS 260,Creative Writing: Introduction to Fiction Writing I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2847?entityType=Course&reportId=422
+WCS 270,Academic and Professional Presentations,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3144?entityType=Course&reportId=422
+WCS 300,Internship: Undergraduate Speaker Consultant I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3145?entityType=Course&reportId=422
+WCS 301,Internship: Undergraduate Speaker Consultant II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3146?entityType=Course&reportId=422
+WCS 302,Argumentation and Debate,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3147?entityType=Course&reportId=422
+WCS 360,Poetry Writing Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2456?entityType=Course&reportId=422
+WCS 361,Advanced Fiction Writing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2848?entityType=Course&reportId=422
+WCS 363,Writing Speculative Fiction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2849?entityType=Course&reportId=422
+WCS 390,Writing Fellows I – Composition and Collaboration in Theory and Practice,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2935?entityType=Course&reportId=422
+WCS 391,Writing Fellows II – Practicum in Composition and Collaboration,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2533?entityType=Course&reportId=422
+WCS 392,Writing Fellows III - Research and Practice in Writing and Peer Mentorship,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2352?entityType=Course&reportId=422
+WCS 462,Creative Nonfiction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2850?entityType=Course&reportId=422
+WCS 465,Creative Writing: Autofiction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2851?entityType=Course&reportId=422
+WCS 469,Independent Study in Creative Writing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2852?entityType=Course&reportId=422
+WCS 501,Science Communication,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2776?entityType=Course&reportId=422
+WCS 562,Creative Nonfiction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2846?entityType=Course&reportId=422
+WCS 730,From Genre to Style and Back: Writing for PhD Students,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2353?entityType=Course&reportId=422
+WLL 102,"Language, Experience, Culture",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2713?entityType=Course&reportId=422
+WLL 110,Introduction to Literary Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2418?entityType=Course&reportId=422
+WLL 121,Introduction to Cultural Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2817?entityType=Course&reportId=422
+WLL 171,Introduction to Linguistic Anthropology,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3187?entityType=Course&reportId=422
+WLL 201,World Literature I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2923?entityType=Course&reportId=422
+WLL 209,Introduction to Translation Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2417?entityType=Course&reportId=422
+WLL 211,World Literature II: from the 18th to the 20th century,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2794?entityType=Course&reportId=422
+WLL 212,Introduction to Poetry,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2924?entityType=Course&reportId=422
+WLL 218,Renaissance in Italy and Beyond,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2925?entityType=Course&reportId=422
+WLL 235,Creative Writing: Introduction to Fiction Writing I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2845?entityType=Course&reportId=422
+WLL 240,Introduction to the Novel,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2795?entityType=Course&reportId=422
+WLL 241,Survey of Folk Tales,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2720?entityType=Course&reportId=422
+WLL 244,Survey of Nineteenth-Century Russian Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3262?entityType=Course&reportId=422
+WLL 245,Global History of Travel and Travel Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2565?entityType=Course&reportId=422
+WLL 246,Survey of Contemporary Russian Literature and Culture,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3263?entityType=Course&reportId=422
+WLL 248,Survey of Soviet Literature and Culture,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3264?entityType=Course&reportId=422
+WLL 250,From Page to Screen,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2821?entityType=Course&reportId=422
+WLL 254,"Superstition, Magical Realism, and Horror in Hispanic Culture",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2822?entityType=Course&reportId=422
+WLL 257,Fan Culture in the Age of Convergence,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2823?entityType=Course&reportId=422
+WLL 261,Survey of American Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2796?entityType=Course&reportId=422
+WLL 271,Language and Society,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3188?entityType=Course&reportId=422
+WLL 274,Texts and Contexts,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2414?entityType=Course&reportId=422
+WLL 313,Dante's Inferno,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2932?entityType=Course&reportId=422
+WLL 315,Shakespeare,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2797?entityType=Course&reportId=422
+WLL 333,Literary Modernism: Tradition and Innovation,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2798?entityType=Course&reportId=422
+WLL 334,Postmodern Fiction: Forms and Messages,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2799?entityType=Course&reportId=422
+WLL 340,The Image of the East in Russophone Literature and Culture: Genesis and Meaning,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3260?entityType=Course&reportId=422
+WLL 341,Soviet Literature as Multinational Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3261?entityType=Course&reportId=422
+WLL 342,Russian Intellectual History (1762 - 1905),https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2620?entityType=Course&reportId=422
+WLL 349,Terrible Perfection: Women in 19th-Century Russian Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2415?entityType=Course&reportId=422
+WLL 351,Literature and Film of the Postcolonial World,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2820?entityType=Course&reportId=422
+WLL 359,Terror and Perfection: Soviet Female Writers and Poets,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3259?entityType=Course&reportId=422
+WLL 360,Poetry Writing Seminar,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2458?entityType=Course&reportId=422
+WLL 363,Writing Speculative Fiction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2931?entityType=Course&reportId=422
+WLL 375,Philosophy of Art,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2937?entityType=Course&reportId=422
+WLL 385,Postcolonial Theory and its Applications in Eurasia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2407?entityType=Course&reportId=422
+WLL 399,Independent Study,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2718?entityType=Course&reportId=422
+WLL 400,Research Assistance in Linguistics and Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2698?entityType=Course&reportId=422
+WLL 401,Advanced Topics in World Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2929?entityType=Course&reportId=422
+WLL 412,Poetic Personae,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2930?entityType=Course&reportId=422
+WLL 440,Oral Epic in Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2719?entityType=Course&reportId=422
+WLL 441,Utopias in Russian and Soviet Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2416?entityType=Course&reportId=422
+WLL 442,Contemporary Russian and Russophone Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3258?entityType=Course&reportId=422
+WLL 450,Laughter,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2716?entityType=Course&reportId=422
+WLL 451,The Call of the Evil: Unmasking the Villain(ness) in Popular Culture and Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2824?entityType=Course&reportId=422
+WLL 462,Creative Nonfiction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2926?entityType=Course&reportId=422
+WLL 465,Creative Writing: Autofiction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2853?entityType=Course&reportId=422
+WLL 469,Independent Study in Creative Writing,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2717?entityType=Course&reportId=422
+WLL 498,"Languages, Linguistics, and Literatures Capstone I",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2699?entityType=Course&reportId=422
+WLL 499,"Languages, Linguistics, and Literatures Capstone II",https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2825?entityType=Course&reportId=422
+WLL 501,Advanced Topics in World Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2927?entityType=Course&reportId=422
+WLL 512,Poetic Personae,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2928?entityType=Course&reportId=422
+WLL 540,Oral Epic in Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2721?entityType=Course&reportId=422
+WLL 541,Utopias in Russian and Soviet Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2413?entityType=Course&reportId=422
+WLL 542,Contemporary Russian and Russophone Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/3257?entityType=Course&reportId=422
+WLL 550,Laughter,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2723?entityType=Course&reportId=422
+WLL 551,The Call of the Evil: Unmasking the Villain(ness) in Popular Culture and Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2826?entityType=Course&reportId=422
+WLL 562,Creative Nonfiction,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2933?entityType=Course&reportId=422
+WLL 712,Poetic Personae,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2934?entityType=Course&reportId=422
+WLL 740,Oral Epic in Central Asia,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2722?entityType=Course&reportId=422
+WLL 741,Utopias in Russian and Soviet Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2412?entityType=Course&reportId=422
+WLL 751,The Call of the Evil: Unmasking the Villain(ness) in Popular Culture and Literature,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/2827?entityType=Course&reportId=422
+ZCOM 040,Academic Communications for Graduate Studies I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/7?entityType=Course&reportId=422
+ZCOM 041,Academic Communications for Graduate Studies II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/8?entityType=Course&reportId=422
+ZLIN 062,Linear Algebra for Graduate Studies,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/14?entityType=Course&reportId=422
+ZRDG 030,Academic Reading for Graduate Studies I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/9?entityType=Course&reportId=422
+ZRDG 031,Academic Reading for Graduate Studies II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/10?entityType=Course&reportId=422
+ZSTA 060,Foundational Statistics,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/13?entityType=Course&reportId=422
+ZWRT 020,Academic Writing for Graduate Studies I,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/11?entityType=Course&reportId=422
+ZWRT 021,Academic Writing for Graduate Studies II,https://nukz.curriqunet.com/DynamicReports/AllFieldsReportByEntity/12?entityType=Course&reportId=422
diff --git a/web/public/favicon.svg b/web/public/favicon.svg
new file mode 100644
index 00000000..0c279bdd
--- /dev/null
+++ b/web/public/favicon.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/scripts/generate-api-types.mjs b/web/scripts/generate-api-types.mjs
new file mode 100644
index 00000000..6e4f7736
--- /dev/null
+++ b/web/scripts/generate-api-types.mjs
@@ -0,0 +1,99 @@
+#!/usr/bin/env node
+/**
+ * Generates src/api/schema.d.ts from the backend's OpenAPI document.
+ *
+ * The backend only serves /api/openapi.json when IS_DEBUG=true (the local
+ * Docker default) — see backend/main.py. There is no schema endpoint in
+ * production, which is fine: this is a build-time artifact and the generated
+ * file is committed.
+ *
+ * pnpm api:generate write src/api/schema.d.ts
+ * pnpm api:check fail if the committed file is out of date
+ *
+ * openapi-typescript builds its output through the TypeScript compiler's
+ * ts.factory AST API, which TypeScript 7 does not expose — importing it under
+ * TS 7 throws immediately. Since its output is plain text, the generator runs
+ * in an isolated environment pinned to TS 6 rather than the project compiler.
+ * Nothing about the emitted .d.ts depends on which version produced it.
+ */
+import { execFile } from "node:child_process"
+import { readFile, writeFile, mkdir } from "node:fs/promises"
+import { dirname, resolve } from "node:path"
+import { fileURLToPath } from "node:url"
+import { promisify } from "node:util"
+
+const execFileAsync = promisify(execFile)
+
+const here = dirname(fileURLToPath(import.meta.url))
+const OUT = resolve(here, "../src/api/schema.d.ts")
+const SOURCE = process.env.OPENAPI_URL ?? "http://localhost/api/openapi.json"
+const check = process.argv.includes("--check")
+
+// Pinned so regeneration is reproducible across machines and CI.
+const GENERATOR = "openapi-typescript@7.13.0"
+const GENERATOR_COMPILER = "typescript@6.0.3"
+
+const BANNER = `/**
+ * GENERATED FILE — DO NOT EDIT.
+ * Regenerate with \`pnpm api:generate\` from an offline backend OpenAPI export.
+ */
+
+`
+
+async function generate() {
+ const { stdout } = await execFileAsync(
+ "pnpm",
+ [
+ "dlx",
+ "--package",
+ GENERATOR_COMPILER,
+ "--package",
+ GENERATOR,
+ "openapi-typescript",
+ SOURCE,
+ ],
+ { maxBuffer: 64 * 1024 * 1024 }
+ )
+
+ // pnpm dlx prefixes resolution progress on stdout in some versions; keep
+ // everything from the generated banner onward.
+ const start = stdout.indexOf("/**")
+ if (start === -1) {
+ throw new Error(
+ `Generator produced no schema output:\n${stdout.slice(0, 500)}`
+ )
+ }
+ return BANNER + stdout.slice(start)
+}
+
+async function main() {
+ let next
+ try {
+ next = await generate()
+ } catch (cause) {
+ throw new Error(
+ `Could not generate types from ${SOURCE}.\n` +
+ `Export the backend schema and set OPENAPI_URL to its path.`,
+ { cause }
+ )
+ }
+
+ if (check) {
+ const current = await readFile(OUT, "utf8").catch(() => null)
+ if (current !== next) {
+ console.error(
+ "src/api/schema.d.ts is out of date with the backend schema.\n" +
+ "Run `pnpm api:generate` and commit the result."
+ )
+ process.exit(1)
+ }
+ console.log("src/api/schema.d.ts is up to date.")
+ return
+ }
+
+ await mkdir(dirname(OUT), { recursive: true })
+ await writeFile(OUT, next)
+ console.log(`Wrote ${OUT}`)
+}
+
+await main()
diff --git a/web/src/api/client.ts b/web/src/api/client.ts
new file mode 100644
index 00000000..63b720c5
--- /dev/null
+++ b/web/src/api/client.ts
@@ -0,0 +1,93 @@
+import createClient, { type Middleware } from "openapi-fetch"
+
+import type { paths } from "@/api/schema"
+
+/**
+ * Auth is cookie-based and same-origin: nginx proxies /api to FastAPI, and the
+ * access/refresh/app tokens are httpOnly cookies the browser sends on its own.
+ * There is no Authorization header to attach and no token for the client to
+ * hold. `credentials: "include"` keeps that working when the dev server and the
+ * API are not literally the same origin.
+ */
+export const api = createClient({
+ baseUrl: "/api",
+ credentials: "include",
+})
+
+/** A non-2xx response from the API. */
+export class ApiError extends Error {
+ readonly status: number
+ /** FastAPI's error body: `{"detail": "..."}` or a 422 validation array. */
+ readonly detail: unknown
+
+ constructor(status: number, detail: unknown) {
+ super(`API request failed with ${status}: ${describe(detail)}`)
+ this.name = "ApiError"
+ this.status = status
+ this.detail = detail
+ }
+
+ /** True when the session is missing or expired. */
+ get isUnauthorized() {
+ return this.status === 401
+ }
+
+ /** True when the user is known but not allowed to do this. */
+ get isForbidden() {
+ return this.status === 403
+ }
+}
+
+function isRecord(value: unknown): value is Record {
+ return typeof value === "object" && value !== null
+}
+
+function describe(detail: unknown): string {
+ if (typeof detail === "string") return detail
+
+ if (isRecord(detail) && "detail" in detail) {
+ const inner = detail.detail
+ if (typeof inner === "string") return inner
+
+ // FastAPI validation errors are [{loc, msg, type}, ...].
+ if (Array.isArray(inner)) {
+ const messages: unknown[] = inner
+ return messages
+ .map((issue) =>
+ isRecord(issue) && typeof issue.msg === "string"
+ ? issue.msg
+ : JSON.stringify(issue)
+ )
+ .join("; ")
+ }
+ }
+
+ return JSON.stringify(detail)
+}
+
+/**
+ * openapi-fetch returns `{ data, error }` rather than throwing. React Query
+ * needs a rejected promise to drive its error states, so unwrap at the seam:
+ * every hook calls this and gets a value or an ApiError.
+ */
+export async function unwrap(
+ promise: Promise<{ data?: T; error?: unknown; response: Response }>
+): Promise {
+ const { data, error, response } = await promise
+ if (error !== undefined || !response.ok) {
+ throw new ApiError(response.status, error)
+ }
+ // 204/205 carry no body by design, and callers of those endpoints type the
+ // result as void — so widening undefined to T here is intentional.
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion
+ return data as T
+}
+
+/** Adds credentials to every request, including ones openapi-fetch retries. */
+const credentialsMiddleware: Middleware = {
+ onRequest({ request }) {
+ return new Request(request, { credentials: "include" })
+ },
+}
+
+api.use(credentialsMiddleware)
diff --git a/web/src/api/errors.ts b/web/src/api/errors.ts
new file mode 100644
index 00000000..64fc8bb2
--- /dev/null
+++ b/web/src/api/errors.ts
@@ -0,0 +1,77 @@
+import { ApiError } from "@/api/client"
+
+/**
+ * A message safe to put in front of a user for a failed API call.
+ *
+ * The old app open-coded this twice — once in `opportunity-form.tsx` and once
+ * in `sg-members-management.tsx` — as ~70 lines apiece of re-reading the
+ * `Response` body and re-parsing JSON that the fetch layer had already parsed.
+ * Both copies rendered whatever `detail` came back, whatever the status.
+ *
+ * This one follows the rule established in
+ * `features/courses/registrar-errors.ts`: **never render a 5xx `detail`.**
+ * FastAPI runs with `debug=True` locally, so a 500 body is a Python traceback;
+ * in production it is still an internal description written for developers.
+ * A 4xx detail is the opposite — deliberate, addressed to the caller, and
+ * usually the only thing that explains what to fix.
+ */
+export function apiErrorMessage(error: unknown, fallback: string): string {
+ if (!(error instanceof ApiError)) {
+ // Network failures, aborted requests and thrown strings all land here.
+ return error instanceof Error && error.message.trim()
+ ? error.message
+ : fallback
+ }
+
+ if (error.status >= 500) return fallback
+
+ return extractDetail(error.detail) ?? fallback
+}
+
+/** True when the failure is the session having gone away. */
+export function isUnauthorized(error: unknown): boolean {
+ return error instanceof ApiError && error.isUnauthorized
+}
+
+function isRecord(value: unknown): value is Record {
+ return typeof value === "object" && value !== null
+}
+
+/**
+ * FastAPI answers with `{"detail": "..."}` for a raised HTTPException and with
+ * `{"detail": [{loc, msg, type}, ...]}` for a request that failed validation.
+ * Pydantic's `msg` is short and readable ("String should have at most 75
+ * characters"); `loc` names the field, which the form has already labelled, so
+ * only `msg` is worth showing.
+ */
+function extractDetail(body: unknown): string | null {
+ const detail = isRecord(body) && "detail" in body ? body.detail : body
+
+ if (typeof detail === "string") {
+ const trimmed = detail.trim()
+ return trimmed === "" ? null : trimmed
+ }
+
+ if (Array.isArray(detail)) {
+ const issues: unknown[] = detail
+ const messages = issues
+ .map((issue) =>
+ isRecord(issue) && typeof issue.msg === "string" ? issue.msg : null
+ )
+ .filter((message) => message !== null)
+ return messages.length > 0 ? messages.join(". ") : null
+ }
+
+ /**
+ * `{"code": "...", "message": "..."}`, which the planner raises on its 409s
+ * so the caller can branch on `code` while still having something to show.
+ * Only `message` is for a person; `code` is for a machine and must not reach
+ * the screen.
+ */
+ if (isRecord(detail) && typeof detail.message === "string") {
+ const trimmed = detail.message.trim()
+ return trimmed === "" ? null : trimmed
+ }
+
+ return null
+}
diff --git a/web/src/api/query-keys.ts b/web/src/api/query-keys.ts
new file mode 100644
index 00000000..7f18bc83
--- /dev/null
+++ b/web/src/api/query-keys.ts
@@ -0,0 +1,89 @@
+/**
+ * Every query key in the app is built here.
+ *
+ * The previous app had 88 inline `queryKey:` literals with no shared
+ * convention — ["campusCurrent","communities"] next to ["grade-terms"] next to
+ * ["sg-members","list"] — which made targeted invalidation guesswork. Keys are
+ * hierarchical: invalidating `qk.events.all()` clears every events query,
+ * including lists and details.
+ */
+export const qk = {
+ session: () => ["session"] as const,
+
+ events: {
+ all: () => ["events"] as const,
+ list: (filters: Record) =>
+ ["events", "list", filters] as const,
+ detail: (id: number) => ["events", "detail", id] as const,
+ },
+
+ communities: {
+ all: () => ["communities"] as const,
+ list: (filters: Record) =>
+ ["communities", "list", filters] as const,
+ detail: (id: number) => ["communities", "detail", id] as const,
+ mine: () => ["communities", "mine"] as const,
+ },
+
+ announcements: {
+ all: () => ["announcements"] as const,
+ bundle: () => ["announcements", "bundle"] as const,
+ telegram: () => ["announcements", "telegram"] as const,
+ },
+
+ opportunities: {
+ all: () => ["opportunities"] as const,
+ list: (filters: Record) =>
+ ["opportunities", "list", filters] as const,
+ detail: (id: number) => ["opportunities", "detail", id] as const,
+ },
+
+ courses: {
+ all: () => ["courses"] as const,
+ catalog: (filters: Record) =>
+ ["courses", "catalog", filters] as const,
+ registered: () => ["courses", "registered"] as const,
+ schedule: () => ["courses", "schedule"] as const,
+ templates: (courseId: number) =>
+ ["courses", "templates", courseId] as const,
+ requirements: (year: string, name: string, type: string) =>
+ ["courses", "degree-requirements", year, name, type] as const,
+ semesters: () => ["courses", "semesters"] as const,
+ gradeTerms: () => ["courses", "grade-terms"] as const,
+ grades: (filters: Record) =>
+ ["courses", "grades", filters] as const,
+ degreeAudit: () => ["courses", "degree-audit"] as const,
+ /**
+ * One key per plan. A student can keep several schedule variants, and
+ * caching them under a single key would show the previous plan's courses
+ * for a frame after switching — the plans differ in exactly the data the
+ * grid draws.
+ */
+ planner: (scheduleId?: number | null) =>
+ ["courses", "planner", scheduleId ?? "default"] as const,
+ /** The list of plans, without their courses. */
+ plannerPlans: () => ["courses", "planner-plans"] as const,
+ },
+
+ sgotinish: {
+ all: () => ["sgotinish"] as const,
+ tickets: (filters: Record) =>
+ ["sgotinish", "tickets", filters] as const,
+ ticket: (id: number) => ["sgotinish", "tickets", id] as const,
+ messages: (conversationId: number) =>
+ ["sgotinish", "messages", conversationId] as const,
+ members: () => ["sgotinish", "members"] as const,
+ list: (filters: Record) =>
+ ["sgotinish", "tickets", "list", filters] as const,
+ departments: () => ["sgotinish", "departments"] as const,
+ },
+
+ notifications: {
+ all: () => ["notifications"] as const,
+ list: (filters: Record) =>
+ ["notifications", "list", filters] as const,
+ },
+
+ search: (keyword: string, storageName: string) =>
+ ["search", storageName, keyword] as const,
+} as const
diff --git a/web/src/api/schema.d.ts b/web/src/api/schema.d.ts
new file mode 100644
index 00000000..b8cdc73b
--- /dev/null
+++ b/web/src/api/schema.d.ts
@@ -0,0 +1,6970 @@
+/**
+ * GENERATED FILE — DO NOT EDIT.
+ * Regenerate with `pnpm api:generate` from an offline backend OpenAPI export.
+ */
+
+/**
+ * This file was auto-generated by openapi-typescript.
+ * Do not make direct changes to the file.
+ */
+
+export interface paths {
+ "/login": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Login */
+ get: operations["login_login_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/auth/callback": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Auth Callback */
+ get: operations["auth_callback_auth_callback_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/connect-tg": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Bind Tg
+ * @description Issue a Telegram deeplink binding the caller's own account to a chat.
+ */
+ post: operations["bind_tg_connect_tg_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/refresh-token": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Refresh Token */
+ post: operations["refresh_token_refresh_token_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/me": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Get Current User */
+ get: operations["get_current_user_me_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/logout": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Logout */
+ get: operations["logout_logout_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/communities": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Communities
+ * @description Retrieves a paginated list of communities with flexible filtering.
+ */
+ get: operations["get_communities_communities_get"];
+ put?: never;
+ /**
+ * Add Community
+ * @description Create a new community. Any registered user can create communities.
+ *
+ * **Access Policy:**
+ * - Any registered user can create communities
+ * - Users can only create communities for themselves (head must be "me" or their own sub)
+ */
+ post: operations["add_community_communities_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/communities/{community_id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Community
+ * @description Retrieves a specific community by ID.
+ */
+ get: operations["get_community_communities__community_id__get"];
+ put?: never;
+ post?: never;
+ /**
+ * Delete Community
+ * @description Deletes a community. Admin only.
+ */
+ delete: operations["delete_community_communities__community_id__delete"];
+ options?: never;
+ head?: never;
+ /**
+ * Update Community
+ * @description Updates fields of an existing community. Head or admin only.
+ */
+ patch: operations["update_community_communities__community_id__patch"];
+ trace?: never;
+ };
+ "/events": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Events
+ * @description Retrieves a paginated list of events with flexible filtering.
+ *
+ * **Access Policy:**
+ * - Anyone (including guests) can view: Approved, Cancelled
+ * - Event creator or admin can view all statuses for their own events
+ * - For users viewing events they don't own:
+ * - Must explicitly specify status in {approved, cancelled}
+ */
+ get: operations["get_events_events_get"];
+ put?: never;
+ /**
+ * Add Event
+ * @description Creates a new event.
+ *
+ * **Access Policy:**
+ * - Any authenticated user can create events for themselves
+ * - Admin can create events with any configuration
+ *
+ * **Data Enrichment:**
+ * - `status`: approved
+ * - `tag`: regular (admins can change later)
+ */
+ post: operations["add_event_events_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/events/{event_id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Event
+ * @description Retrieves a specific event by ID.
+ */
+ get: operations["get_event_events__event_id__get"];
+ put?: never;
+ post?: never;
+ /**
+ * Delete Event
+ * @description Deletes a specific event.
+ *
+ * **Access Policy:**
+ * - Event creator or admin
+ */
+ delete: operations["delete_event_events__event_id__delete"];
+ options?: never;
+ head?: never;
+ /**
+ * Update Event
+ * @description Updates fields of an existing event.
+ *
+ * **Access Policy:**
+ * - Admin can update any field
+ * - Event creator can update most fields except tag
+ */
+ patch: operations["update_event_events__event_id__patch"];
+ trace?: never;
+ };
+ "/profile": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Get Profile */
+ get: operations["get_profile_profile_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/search/": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Full Search
+ * @description Full search implementation returning complete entity details
+ */
+ get: operations["full_search_search__get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/bucket/upload-url": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Generate Upload Url
+ * @description Generates pre-signed URLs for direct upload to Google Cloud Storage bucket.
+ */
+ post: operations["generate_upload_url_bucket_upload_url_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/bucket/gcs-hook": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Gcs Webhook
+ * @description Processes GCS notifications from Pub/Sub and upserts media records.
+ */
+ post: operations["gcs_webhook_bucket_gcs_hook_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/bucket/local-upload/{bucket}/{full_path}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ /**
+ * Local Upload Proxy
+ * @description Dev-only upload proxy: accepts PUT body and uploads to the emulator via storage client.
+ */
+ put: operations["local_upload_proxy_bucket_local_upload__bucket___full_path__put"];
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/bucket/local-download/{bucket}/{full_path}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Local Download Proxy
+ * @description Dev-only download proxy: reads from emulator via storage client and returns bytes.
+ */
+ get: operations["local_download_proxy_bucket_local_download__bucket___full_path__get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/webhook": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Webhook
+ * @description Webhook for the bot. Receives updates from Telegram and processes them.
+ */
+ post: operations["webhook_webhook_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/registered_courses/sync": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Sync Courses From Registrar
+ * @description Syncs courses from the university registrar for the authenticated student.
+ *
+ * **Access Policy:**
+ * - Students can only sync their own courses
+ *
+ * **Parameters:**
+ * - `data`: Registrar credentials (password)
+ *
+ * **Returns:**
+ * - List of synced courses with total count
+ *
+ * **Process:**
+ * 1. Fetches student's schedule from registrar
+ * 2. Determines current semester based on current date
+ * 3. For each course in the schedule:
+ * - Checks if course exists in local database
+ * - If not, fetches course details from registrar and creates it
+ * - Creates StudentCourse registration if not already registered
+ */
+ post: operations["sync_courses_from_registrar_registered_courses_sync_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/registered_courses/sync/pdf": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Sync Courses From Schedule Pdf
+ * @description Sync registered courses from an uploaded registrar personal schedule PDF.
+ */
+ post: operations["sync_courses_from_schedule_pdf_registered_courses_sync_pdf_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/registered_courses": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Registered Courses
+ * @description Retrieves all courses registered by the authenticated student.
+ *
+ * **Access Policy:**
+ * - Students can only view their own registered courses
+ * - Admin can view any student's registered courses
+ *
+ * **Returns:**
+ * - List of registered courses with course details, items, and class averages
+ */
+ get: operations["get_registered_courses_registered_courses_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/registered_courses/schedule": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Registered Courses Schedule
+ * @description Return the most recently synced registrar schedule for the authenticated user.
+ */
+ get: operations["get_registered_courses_schedule_registered_courses_schedule_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/registered_courses/schedule/google": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Export Registered Schedule To Google Calendar
+ * @description Export the student's latest registrar schedule to Google Calendar.
+ */
+ post: operations["export_registered_schedule_to_google_calendar_registered_courses_schedule_google_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/registered_courses/schedule/ics": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Export Registered Schedule To Ics
+ * @description Download the student's latest registrar schedule as an iCalendar (.ics) file.
+ * Works with Apple Calendar, Outlook, and other apps that import .ics.
+ */
+ get: operations["export_registered_schedule_to_ics_registered_courses_schedule_ics_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/course_items": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Add Course Item
+ * @description Adds a new course item (assignment, exam, etc.) to a registered course.
+ *
+ * **Access Policy:**
+ * - Students can only add items to their own registered courses
+ * - Admin can add items to any course
+ *
+ * **Parameters:**
+ * - `course_item_data`: Course item data including student_course_id, name, scores, etc.
+ *
+ * **Returns:**
+ * - Created course item with all details
+ */
+ post: operations["add_course_item_course_items_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/course_items/{item_id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ post?: never;
+ /**
+ * Delete Course Item
+ * @description Deletes a specific course item.
+ *
+ * **Access Policy:**
+ * - Students can only delete items from their own registered courses
+ * - Admin can delete any course item
+ *
+ * **Parameters:**
+ * - `item_id`: ID of the course item to delete
+ *
+ * **Returns:**
+ * - HTTP 204 No Content on successful deletion
+ */
+ delete: operations["delete_course_item_course_items__item_id__delete"];
+ options?: never;
+ head?: never;
+ /**
+ * Update Course Item
+ * @description Updates an existing course item.
+ *
+ * **Access Policy:**
+ * - Students can only update items in their own registered courses
+ * - Admin can update any course item
+ *
+ * **Parameters:**
+ * - `item_id`: ID of the course item to update
+ * - `item_update`: Updated course item data (partial update)
+ *
+ * **Returns:**
+ * - Updated course item with all details
+ */
+ patch: operations["update_course_item_course_items__item_id__patch"];
+ trace?: never;
+ };
+ "/courses": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Courses
+ * @description Retrieves a paginated list of all courses with optional filtering and search.
+ *
+ * **Access Policy:**
+ * - Anyone can view courses (no authentication required)
+ *
+ * **Parameters:**
+ * - `page`: Page number to retrieve (default: 1, minimum: 1)
+ * - `size`: Number of courses per page (default: 20, max: 100, minimum: 1)
+ * - `term`: Filter courses by specific academic term (optional)
+ * - `keyword`: Search keyword for course code or course title (optional)
+ *
+ * **Returns:**
+ * - Paginated list of courses with total pages information
+ */
+ get: operations["get_courses_courses_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner/semesters": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** List registrar semesters for planner dropdowns */
+ get: operations["list_semesters_planner_semesters_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner/schedules": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** List planner schedule variants for the authenticated student */
+ get: operations["list_planner_schedules_planner_schedules_get"];
+ put?: never;
+ /** Create a new planner schedule variant */
+ post: operations["create_planner_schedule_planner_schedules_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner/schedules/{schedule_id}/duplicate": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Duplicate a planner schedule variant */
+ post: operations["duplicate_planner_schedule_planner_schedules__schedule_id__duplicate_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner/schedules/{schedule_id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ post?: never;
+ /** Delete a planner schedule variant */
+ delete: operations["delete_planner_schedule_planner_schedules__schedule_id__delete"];
+ options?: never;
+ head?: never;
+ /** Rename a planner schedule variant */
+ patch: operations["update_planner_schedule_planner_schedules__schedule_id__patch"];
+ trace?: never;
+ };
+ "/planner/courses/search": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Search registrar courses for planner use */
+ get: operations["search_courses_for_planner_planner_courses_search_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner/courses/refresh": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Refresh sections for all planner courses */
+ post: operations["refresh_all_courses_planner_courses_refresh_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Get planner schedule for the authenticated student */
+ get: operations["get_planner_schedule_planner_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner/courses": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Add a course to planner schedule */
+ post: operations["add_course_planner_courses_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner/courses/{course_id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ post?: never;
+ /** Remove a course from planner */
+ delete: operations["remove_course_planner_courses__course_id__delete"];
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner/courses/{course_id}/sections": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Fetch registrar sections for a planner course */
+ get: operations["get_sections_planner_courses__course_id__sections_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner/courses/{course_id}/sections/select": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Select preferred sections for a course */
+ post: operations["select_sections_planner_courses__course_id__sections_select_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner/autobuild": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Automatically build schedule */
+ post: operations["auto_build_planner_autobuild_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/planner/reset": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Reset planner data for the student */
+ post: operations["reset_planner_planner_reset_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/grades/terms": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * List Grade Terms
+ * @description Returns distinct grade report terms (e.g., FA2024, SP2025) for filtering.
+ */
+ get: operations["list_grade_terms_grades_terms_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/grades": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Grades
+ * @description Retrieves a paginated list of grade reports statistics with optional keyword search.
+ *
+ * **Access Policy:**
+ * - Anyone can view grade reports
+ *
+ * **Parameters:**
+ * - `size`: Number of grade reports per page (default: 20, max: 100)
+ * - `page`: Page number to retrieve (default: 1)
+ * - `keyword`: Search term for course code or course title (optional)
+ * - `term`: Filter results by semester/term code (optional)
+ *
+ * **Returns:**
+ * - List of grade reports and pagination info
+ *
+ * **Notes:**
+ * - When `keyword` is provided, results are ranked by Meilisearch and ordering is preserved
+ * - When no `keyword` is provided, results are ordered by `created_at` (newest first)
+ * - Returns an empty list if no results match the search
+ */
+ get: operations["get_grades_grades_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/templates": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * List Templates
+ * @description List the current user's templates. Optional filter by course_id.
+ */
+ get: operations["list_templates_templates_get"];
+ put?: never;
+ /**
+ * Create Template
+ * @description Create a new template for a course.
+ * Throws 409 error if template already exists for the course and user.
+ */
+ post: operations["create_template_templates_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/templates/{template_id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Template
+ * @description Get a single template by id (must belong to current user).
+ */
+ get: operations["get_template_templates__template_id__get"];
+ put?: never;
+ post?: never;
+ /**
+ * Delete Template
+ * @description Delete a template.
+ */
+ delete: operations["delete_template_templates__template_id__delete"];
+ options?: never;
+ head?: never;
+ /**
+ * Update Template
+ * @description Update an existing template.
+ */
+ patch: operations["update_template_templates__template_id__patch"];
+ trace?: never;
+ };
+ "/templates/{template_id}/import": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Import Template Into Course
+ * @description Import template into a student's registered course.
+ */
+ post: operations["import_template_into_course_templates__template_id__import_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/degree-audit/catalog": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** List available admission years and majors for degree audit */
+ get: operations["list_catalog_degree_audit_catalog_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/degree-audit/audit/registrar": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Run degree audit using registrar transcript (no file upload) */
+ post: operations["audit_from_registrar_degree_audit_audit_registrar_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/degree-audit/audit/pdf": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Run degree audit using PDF file */
+ post: operations["audit_from_pdf_degree_audit_audit_pdf_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/degree-audit/requirements": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Get degree requirements for a specific year and major */
+ get: operations["get_degree_requirements_degree_audit_requirements_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/degree-audit/result": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Get cached degree audit result for current user */
+ get: operations["get_cached_result_degree_audit_result_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/notification": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Get */
+ get: operations["get_notification_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/tickets": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Tickets
+ * @description Retrieves a paginated list of tickets with flexible filtering.
+ *
+ * **Access Policy:**
+ * - SG members and admins can view tickets they have access to
+ * - Regular users can only view their own tickets
+ *
+ * **Parameters:**
+ * - `size`: Number of tickets per page (default: 20, max: 100)
+ * - `page`: Page number (default: 1)
+ * - `category`: Filter by ticket category (optional)
+ * - `author_sub`: Filter by ticket author (optional)
+ * - If set to "me", returns the current user's tickets
+ * **Returns:**
+ * - List of tickets matching the criteria with pagination info
+ */
+ get: operations["get_tickets_tickets_get"];
+ put?: never;
+ /**
+ * Create Ticket
+ * @description Creates a new ticket.
+ *
+ * **Access Policy:**
+ * - Any authenticated user can create tickets
+ * - Users can only create tickets for themselves
+ *
+ * **Parameters:**
+ * - `ticket_data`: Ticket data including category, title, body, etc.
+ *
+ * **Returns:**
+ * - Created ticket with all its details
+ *
+ * **Notes:**
+ * - `author_sub` can be set to "me" to use the current user's sub.
+ */
+ post: operations["create_ticket_tickets_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/tickets/{ticket_id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Ticket
+ * @description Retrieves a single ticket by its unique ID.
+ *
+ * **Access Policy:**
+ * - SG members and admins can view tickets they have access to
+ * - Regular users can only view their own tickets
+ *
+ * **Parameters:**
+ * - `ticket_id`: The unique identifier of the ticket to retrieve
+ *
+ * **Returns:**
+ * - A detailed ticket object with all its information
+ */
+ get: operations["get_ticket_tickets__ticket_id__get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ /**
+ * Update Ticket
+ * @description Updates a ticket by its unique ID.
+ */
+ patch: operations["update_ticket_tickets__ticket_id__patch"];
+ trace?: never;
+ };
+ "/tickets/by-owner-hash": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Get Ticket By Owner Hash */
+ post: operations["get_ticket_by_owner_hash_tickets_by_owner_hash_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/conversations": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Create Conversation
+ * @description Creates a new conversation for a ticket.
+ *
+ * **Access Policy:**
+ * - An SG member with at least ASSIGN access can create a conversation.
+ * - For all SG members, only one conversation per ticket.
+ * - Admins can always create conversations.
+ *
+ * **Parameters:**
+ * - `conversation_data`: Conversation data including ticket_id, sg_member_sub
+ *
+ * **Returns:**
+ * - Created conversation with all its details
+ */
+ post: operations["create_conversation_conversations_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/conversations/{conversation_id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ /**
+ * Update Conversation
+ * @description Updates fields of an existing conversation.
+ *
+ * **Access Policy:**
+ * - Admin can update any conversation
+ * - SG members can update conversations they are part of
+ *
+ * **Parameters:**
+ * - `conversation_id`: ID of the conversation to update
+ * - `conversation_data`: Updated conversation data
+ *
+ * **Returns:**
+ * - Updated conversation with all its details
+ */
+ patch: operations["update_conversation_conversations__conversation_id__patch"];
+ trace?: never;
+ };
+ "/messages": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Messages
+ * @description Retrieves a paginated list of messages with flexible filtering.
+ *
+ * **Access Policy:**
+ * - SG members and admins can view all messages
+ * - Regular users can only view messages in conversations for their tickets
+ *
+ * **Parameters:**
+ * - `size`: Number of messages per page (default: 20, max: 100)
+ * - `page`: Page number (default: 1)
+ * - `conversation_id`: Filter by specific conversation (required)
+ *
+ * **Returns:**
+ * - List of messages matching the criteria with pagination info
+ */
+ get: operations["get_messages_messages_get"];
+ put?: never;
+ /**
+ * Create Message
+ * @description Creates a new message in a conversation.
+ *
+ * **Access Policy:**
+ * - The author of the ticket can send messages.
+ * - SG member with Assign or Delegate permission can send messages.
+ * - Admins can always send messages.
+ *
+ * **Parameters:**
+ * - `message_data`: Message data including conversation_id, sender_sub, body
+ *
+ * **Returns:**
+ * - Created message with all its details
+ */
+ post: operations["create_message_messages_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/messages/{message_id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Message
+ * @description Retrieves a single message by its unique ID.
+ *
+ * **Access Policy:**
+ * - SG members and admins can view all messages
+ * - Regular users can only view messages in conversations for their tickets
+ *
+ * **Parameters:**
+ * - `message_id`: The unique identifier of the message to retrieve
+ *
+ * **Returns:**
+ * - A detailed message object with all its information
+ */
+ get: operations["get_message_messages__message_id__get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/messages/{message_id}/read": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Mark Message As Read
+ * @description Marks a message as read by the current user.
+ *
+ * **Access Policy:**
+ * - SG members and admins can mark any message as read
+ * - Regular users can only mark messages in conversations for their tickets
+ *
+ * **Parameters:**
+ * - `message_id`: The unique identifier of the message to mark as read
+ *
+ * **Returns:**
+ * - Updated message with read status
+ */
+ post: operations["mark_message_as_read_messages__message_id__read_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/sg-delegation/departments": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Get Departments */
+ get: operations["get_departments_sg_delegation_departments_get"];
+ put?: never;
+ /** Create Department */
+ post: operations["create_department_sg_delegation_departments_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/sg-delegation/departments/{department_id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ post?: never;
+ /** Delete Department */
+ delete: operations["delete_department_sg_delegation_departments__department_id__delete"];
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/sg-delegation/users": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Get Sg Users */
+ get: operations["get_sg_users_sg_delegation_users_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/sg-members/users": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Search Users For Sg Management */
+ get: operations["search_users_for_sg_management_sg_members_users_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/sg-members": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** List Sg Members */
+ get: operations["list_sg_members_sg_members_get"];
+ put?: never;
+ /** Upsert Sg Member */
+ post: operations["upsert_sg_member_sg_members_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/sg-members/{target_user_sub}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ post?: never;
+ /** Remove Sg Member */
+ delete: operations["remove_sg_member_sg_members__target_user_sub__delete"];
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/sg-members/withdraw": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Withdraw From Sg */
+ post: operations["withdraw_from_sg_sg_members_withdraw_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/tickets/{ticket_id}/delegate": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /** Delegate Ticket Access */
+ post: operations["delegate_ticket_access_tickets__ticket_id__delegate_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/announcements/telegram": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Announcements From Telegram
+ * @description Get latest announcements from the public Telegram channel.
+ */
+ get: operations["get_announcements_from_telegram_announcements_telegram_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/announcements/bundle": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Announcements Bundle Route
+ * @description Single endpoint for the announcements landing page to reduce initial request fan-out.
+ *
+ * Defaults:
+ * - events: page=1 size=5 (approved + upcoming)
+ * - recruitment_events: page=1 size=5 (approved + upcoming + type=recruitment)
+ */
+ get: operations["get_announcements_bundle_route_announcements_bundle_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/opportunities": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** List Opportunities */
+ get: operations["list_opportunities_opportunities_get"];
+ put?: never;
+ /** Create Opportunity */
+ post: operations["create_opportunity_opportunities_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/opportunities/{id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /** Get Opportunity */
+ get: operations["get_opportunity_opportunities__id__get"];
+ put?: never;
+ post?: never;
+ /** Delete Opportunity */
+ delete: operations["delete_opportunity_opportunities__id__delete"];
+ options?: never;
+ head?: never;
+ /** Update Opportunity */
+ patch: operations["update_opportunity_opportunities__id__patch"];
+ trace?: never;
+ };
+ "/opportunities/{id}/calendar": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ /**
+ * Add Opportunity To Calendar
+ * @description Add a single opportunity to the user's Google Calendar (all-day event on the deadline).
+ */
+ post: operations["add_opportunity_to_calendar_opportunities__id__calendar_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/elections/counter/stream": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Stream Election Counter
+ * @description Stream the number of submitted responses for the election survey.
+ */
+ get: operations["stream_election_counter_elections_counter_stream_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/elections/counter": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * Get Election Counter
+ * @description Get the number of submitted responses for the election survey.
+ */
+ get: operations["get_election_counter_elections_counter_get"];
+ put?: never;
+ post?: never;
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+}
+export type webhooks = Record;
+export interface components {
+ schemas: {
+ /**
+ * AnnouncementsBundleResponse
+ * @description Aggregated response for the announcements landing page to reduce request count.
+ */
+ AnnouncementsBundleResponse: {
+ events: components["schemas"]["ListEventResponse"];
+ recruitment_events: components["schemas"]["ListEventResponse"];
+ };
+ /** AuditProgramResult */
+ AuditProgramResult: {
+ /** Name */
+ name: string;
+ /** Type */
+ type: string;
+ /** Results */
+ results: components["schemas"]["AuditRequirementResult"][];
+ summary?: components["schemas"]["AuditSummary"] | null;
+ /**
+ * Warnings
+ * @default []
+ */
+ warnings: string[];
+ };
+ /** AuditRequestPDF */
+ AuditRequestPDF: {
+ /** Year */
+ year: string;
+ /** Majors */
+ majors: string[];
+ /**
+ * Minors
+ * @default []
+ */
+ minors: string[];
+ /**
+ * Tc Mappings
+ * @default []
+ */
+ tc_mappings: components["schemas"]["TCMapping"][];
+ /**
+ * Pdf File
+ * @description Base64-encoded PDF payload (decoded into bytes by Pydantic).
+ */
+ pdf_file: string;
+ };
+ /** AuditRequestRegistrar */
+ AuditRequestRegistrar: {
+ /** Year */
+ year: string;
+ /** Majors */
+ majors: string[];
+ /**
+ * Minors
+ * @default []
+ */
+ minors: string[];
+ /** Username */
+ username: string;
+ /** Password */
+ password: string;
+ /**
+ * Tc Mappings
+ * @default []
+ */
+ tc_mappings: components["schemas"]["TCMapping"][];
+ };
+ /** AuditRequirementResult */
+ AuditRequirementResult: {
+ /** Course Code */
+ course_code: string;
+ /** Course Name */
+ course_name: string;
+ /** Credits Required */
+ credits_required: string;
+ /** Min Grade */
+ min_grade: string;
+ /** Status */
+ status: string;
+ /** Used Courses */
+ used_courses: string;
+ /** Credits Applied */
+ credits_applied: string;
+ /** Credits Remaining */
+ credits_remaining: string;
+ /** Note */
+ note: string;
+ };
+ /** AuditResponse */
+ AuditResponse: {
+ /** Year */
+ year: string;
+ /**
+ * Majors
+ * @default []
+ */
+ majors: string[];
+ /**
+ * Minors
+ * @default []
+ */
+ minors: string[];
+ /**
+ * Audits
+ * @default []
+ */
+ audits: components["schemas"]["AuditProgramResult"][];
+ /**
+ * Unmapped Tc Courses
+ * @default []
+ */
+ unmapped_tc_courses: components["schemas"]["TCCourse"][];
+ /**
+ * Csv Base64
+ * @description Optional base64 CSV of the audit results
+ */
+ csv_base64?: string | null;
+ };
+ /** AuditSummary */
+ AuditSummary: {
+ /**
+ * Total Required
+ * @description Total credits required by the plan
+ */
+ total_required: string;
+ /**
+ * Total Applied
+ * @description Credits applied toward requirements
+ */
+ total_applied: string;
+ /**
+ * Total Remaining
+ * @description Credits still needed
+ */
+ total_remaining: string;
+ /**
+ * Total Taken
+ * @description Credits taken on transcript
+ */
+ total_taken: string;
+ };
+ /** AutoBuildCourseResult */
+ AutoBuildCourseResult: {
+ /** Course Id */
+ course_id: number;
+ /** Registrar Course Id */
+ registrar_course_id: string;
+ /** Course Code */
+ course_code: string;
+ /** Selected Section Id */
+ selected_section_id: number | null;
+ /** Selected Section Code */
+ selected_section_code: string | null;
+ /** Selected Section Ids */
+ selected_section_ids?: number[];
+ };
+ /** BaseCourseItem */
+ BaseCourseItem: {
+ /** Id */
+ id: number;
+ /** Student Course Id */
+ student_course_id: number;
+ /** Item Name */
+ item_name: string;
+ /** Total Weight Pct */
+ total_weight_pct: number | null;
+ /** Obtained Score */
+ obtained_score: number | null;
+ /** Max Score */
+ max_score: number | null;
+ /**
+ * Created At
+ * Format: date-time
+ */
+ created_at: string;
+ /**
+ * Updated At
+ * Format: date-time
+ */
+ updated_at: string;
+ };
+ /** BaseCourseSchema */
+ BaseCourseSchema: {
+ /** Id */
+ id: number;
+ /** Registrar Id */
+ registrar_id: number;
+ /** Course Code */
+ course_code: string;
+ /** Pre Req */
+ pre_req: string | null;
+ /** Anti Req */
+ anti_req: string | null;
+ /** Co Req */
+ co_req: string | null;
+ /** Level */
+ level: string;
+ /** School */
+ school: string;
+ /** Description */
+ description: string | null;
+ /** Department */
+ department: string | null;
+ /** Title */
+ title: string | null;
+ /** Credits */
+ credits: number | null;
+ /** Term */
+ term: string | null;
+ /**
+ * Created At
+ * Format: date-time
+ */
+ created_at: string;
+ /**
+ * Updated At
+ * Format: date-time
+ */
+ updated_at: string;
+ };
+ /** BaseCourseTemplate */
+ BaseCourseTemplate: {
+ /** Id */
+ id: number;
+ /** Course Id */
+ course_id: number;
+ /** Student Sub */
+ student_sub: string;
+ /**
+ * Created At
+ * Format: date-time
+ */
+ created_at: string;
+ /**
+ * Updated At
+ * Format: date-time
+ */
+ updated_at: string;
+ };
+ /** BaseGradeReportSchema */
+ BaseGradeReportSchema: {
+ /** Id */
+ id: number;
+ /** Course Code */
+ course_code: string;
+ /** Course Title */
+ course_title: string | null;
+ /** Section */
+ section: string | null;
+ /** Term */
+ term: string | null;
+ /** Grades Count */
+ grades_count: number | null;
+ /** Avg Gpa */
+ avg_gpa: number | null;
+ /** Std Dev */
+ std_dev: number | null;
+ /** Median Gpa */
+ median_gpa: number | null;
+ /** Pct A */
+ pct_A: number | null;
+ /** Pct B */
+ pct_B: number | null;
+ /** Pct C */
+ pct_C: number | null;
+ /** Pct D */
+ pct_D: number | null;
+ /** Pct F */
+ pct_F: number | null;
+ /** Pct P */
+ pct_P: number | null;
+ /** Pct I */
+ pct_I: number | null;
+ /** Pct Au */
+ pct_AU: number | null;
+ /** Pct W Aw */
+ pct_W_AW: number | null;
+ /** Letters Count */
+ letters_count: number | null;
+ /** Faculty */
+ faculty: string | null;
+ /**
+ * Created At
+ * Format: date-time
+ */
+ created_at: string;
+ /**
+ * Updated At
+ * Format: date-time
+ */
+ updated_at: string;
+ };
+ /**
+ * Message Read Status Base Schema
+ * @description Base schema for all message read status-related operations
+ */
+ BaseMessageReadStatus: {
+ /**
+ * Message Id
+ * @description ID of the associated message
+ */
+ message_id: number;
+ /**
+ * User Sub
+ * @description User identifier
+ */
+ user_sub: string;
+ /**
+ * Read At
+ * Format: date-time
+ * @description Timestamp when message was read
+ */
+ read_at: string;
+ };
+ /** BaseNotification */
+ BaseNotification: {
+ /** Id */
+ id: number;
+ /** Title */
+ title: string;
+ /** Message */
+ message: string;
+ notification_source: components["schemas"]["EntityType"];
+ /** Receiver Sub */
+ receiver_sub: string;
+ /** Tg Id */
+ tg_id: number;
+ type: components["schemas"]["NotificationType"];
+ /** Url */
+ url?: string | null;
+ /**
+ * Created At
+ * Format: date-time
+ */
+ created_at: string;
+ };
+ /** BaseTemplateItem */
+ BaseTemplateItem: {
+ /** Id */
+ id: number;
+ /** Template Id */
+ template_id: number;
+ /** Item Name */
+ item_name: string;
+ /** Total Weight Pct */
+ total_weight_pct: number | null;
+ /**
+ * Created At
+ * Format: date-time
+ */
+ created_at: string;
+ /**
+ * Updated At
+ * Format: date-time
+ */
+ updated_at: string;
+ };
+ /** CatalogResponse */
+ CatalogResponse: {
+ /** Years */
+ years: components["schemas"]["CatalogYear"][];
+ /**
+ * Minors
+ * @default []
+ */
+ minors: string[];
+ };
+ /** CatalogYear */
+ CatalogYear: {
+ /** Year */
+ year: string;
+ /** Majors */
+ majors: string[];
+ };
+ /**
+ * CommunityCategory
+ * @enum {string}
+ */
+ CommunityCategory: "academic" | "professional" | "recreational" | "cultural" | "sports" | "social" | "art";
+ /** CommunityCreateRequest */
+ CommunityCreateRequest: {
+ /**
+ * Name
+ * @description The name of the community
+ * @example NU Fencing Club
+ */
+ name: string;
+ /**
+ * @description The type of the community
+ * @example club
+ */
+ type: components["schemas"]["CommunityType"];
+ /**
+ * @description The category of the community
+ * @example academic
+ */
+ category: components["schemas"]["CommunityCategory"];
+ /**
+ * Email
+ * @description The email of the community
+ * @example nufencingclub@gmail.com
+ */
+ email?: string | null;
+ /**
+ * Description
+ * @description The description of the community
+ * @example We are a club that does fencing
+ */
+ description: string;
+ /**
+ * Established
+ * Format: date
+ * @description The date the community was established
+ * @example 2025-01-01
+ */
+ established: string;
+ /**
+ * Head
+ * @description The head of the community (user_sub)
+ */
+ head: string;
+ /**
+ * Telegram Url
+ * @description The Telegram URL of the community
+ * @example https://t.me/nufencingclub
+ */
+ telegram_url?: string | null;
+ /**
+ * Instagram Url
+ * @description The Instagram URL of the community
+ * @example https://www.instagram.com/nufencingclub
+ */
+ instagram_url?: string | null;
+ };
+ /** CommunityResponse */
+ CommunityResponse: {
+ /** Id */
+ id: number;
+ /** Name */
+ name: string;
+ type: components["schemas"]["CommunityType"];
+ category: components["schemas"]["CommunityCategory"];
+ /** Email */
+ email?: string | null;
+ /** Verified */
+ verified: boolean;
+ /** Description */
+ description: string;
+ /**
+ * Established
+ * Format: date
+ */
+ established: string;
+ /** Head */
+ head: string;
+ /** Telegram Url */
+ telegram_url?: string | null;
+ /** Instagram Url */
+ instagram_url?: string | null;
+ /**
+ * Created At
+ * Format: date-time
+ */
+ created_at: string;
+ /**
+ * Updated At
+ * Format: date-time
+ */
+ updated_at: string;
+ head_user: components["schemas"]["ShortUserResponse"];
+ /**
+ * Media
+ * @default []
+ */
+ media: components["schemas"]["MediaResponse"][];
+ /**
+ * @default {
+ * "can_edit": false,
+ * "can_delete": false,
+ * "editable_fields": []
+ * }
+ */
+ permissions: components["schemas"]["ResourcePermissions"];
+ };
+ /**
+ * CommunityType
+ * @enum {string}
+ */
+ CommunityType: "club" | "university" | "organization";
+ /** CommunityUpdateRequest */
+ CommunityUpdateRequest: {
+ /**
+ * Name
+ * @description The name of the community
+ * @example NU Fencing Club
+ */
+ name?: string | null;
+ /**
+ * Email
+ * @description The email of the community
+ * @example nufencingclub@gmail.com
+ */
+ email?: string | null;
+ /**
+ * Established
+ * @description The date the community was established
+ * @example 2025-01-01
+ */
+ established?: string | null;
+ /**
+ * Description
+ * @description The description of the community
+ * @example We are a club that does fencing
+ */
+ description?: string | null;
+ /**
+ * Telegram Url
+ * @description The Telegram URL of the community
+ * @example https://t.me/nufencingclub
+ */
+ telegram_url?: string | null;
+ /**
+ * Instagram Url
+ * @description The Instagram URL of the community
+ * @example https://www.instagram.com/nufencingclub
+ */
+ instagram_url?: string | null;
+ /**
+ * Media Ids To Delete
+ * @description IDs of media attachments to delete as part of this update
+ */
+ media_ids_to_delete?: number[] | null;
+ };
+ /**
+ * ConversationCreateDTO
+ * @description Public schema for creating a new conversation.
+ */
+ ConversationCreateDTO: {
+ /**
+ * Ticket Id
+ * @description ID of the ticket this conversation belongs to
+ */
+ ticket_id: number;
+ };
+ /**
+ * Conversation Base Schema
+ * @description Base schema for all conversation-related operations
+ */
+ ConversationResponseDTO: {
+ /**
+ * Id
+ * @description Unique identifier of the conversation
+ */
+ id: number;
+ /**
+ * Ticket Id
+ * @description ID of the associated ticket
+ */
+ ticket_id: number;
+ /**
+ * Sg Member Sub
+ * @description SG member identifier
+ */
+ sg_member_sub?: string | null;
+ /** @description Status of the conversation */
+ status: components["schemas"]["ConversationStatus"];
+ /**
+ * Created At
+ * Format: date-time
+ * @description Creation timestamp
+ */
+ created_at: string;
+ /** @description SG member information */
+ sg_member?: components["schemas"]["ShortUserResponse"] | null;
+ /**
+ * Messages Count
+ * @description Number of messages in the conversation
+ * @default 0
+ */
+ messages_count: number;
+ /**
+ * @description User permissions for this conversation
+ * @default {
+ * "can_edit": false,
+ * "can_delete": false,
+ * "editable_fields": []
+ * }
+ */
+ permissions: components["schemas"]["ResourcePermissions"];
+ };
+ /**
+ * ConversationStatus
+ * @enum {string}
+ */
+ ConversationStatus: "active" | "archived";
+ /**
+ * ConversationUpdateDTO
+ * @description Schema for updating a conversation.
+ */
+ ConversationUpdateDTO: {
+ /** @description New status of the conversation */
+ status?: components["schemas"]["ConversationStatus"] | null;
+ };
+ /** CourseItemCreate */
+ CourseItemCreate: {
+ /**
+ * Student Course Id
+ * @description ID of the student's registered course
+ */
+ student_course_id: number;
+ /**
+ * Item Name
+ * @description Name of the assignment/exam
+ */
+ item_name: string;
+ /**
+ * Total Weight Pct
+ * @description Weight must be between 0-100%
+ */
+ total_weight_pct?: number | null;
+ /**
+ * Obtained Score
+ * @description Score must be between 0 and 99999.99
+ */
+ obtained_score?: number | null;
+ /**
+ * Max Score
+ * @description Score must be between 0 and 99999.99
+ */
+ max_score?: number | null;
+ };
+ /** CourseItemUpdate */
+ CourseItemUpdate: {
+ /**
+ * Item Name
+ * @description Name of the assignment/exam
+ */
+ item_name?: string | null;
+ /**
+ * Total Weight Pct
+ * @description Weight must be between 0-100%
+ */
+ total_weight_pct?: number | null;
+ /**
+ * Obtained Score
+ * @description Score must be between 0 and 99999.99
+ */
+ obtained_score?: number | null;
+ /**
+ * Max Score
+ * @description Score must be between 0 and 99999.99
+ */
+ max_score?: number | null;
+ };
+ /** CurrentUserResponse */
+ CurrentUserResponse: {
+ /** User */
+ user: {
+ [key: string]: unknown;
+ };
+ /** Tg Id */
+ tg_id?: number | null;
+ };
+ /** DegreeRequirement */
+ DegreeRequirement: {
+ /** Course Code */
+ course_code: string;
+ /** Course Name */
+ course_name: string;
+ /** Credits Need */
+ credits_need: number;
+ /** Min Grade */
+ min_grade: string;
+ /** Comments */
+ comments: string;
+ /** Options */
+ options: string[];
+ /** Must Haves */
+ must_haves: string[];
+ /** Excepts */
+ excepts: string[];
+ };
+ /**
+ * DelegateAccessPayload
+ * @description Schema for delegating ticket access.
+ */
+ DelegateAccessPayload: {
+ /**
+ * Target User Sub
+ * @description The user sub to grant access to
+ */
+ target_user_sub: string;
+ /** @description The permission level to grant */
+ permission: components["schemas"]["PermissionType"];
+ };
+ /**
+ * DepartmentCreatePayload
+ * @description Payload for creating a new department.
+ */
+ DepartmentCreatePayload: {
+ /**
+ * Name
+ * @description Department name
+ */
+ name: string;
+ /**
+ * Is Special
+ * @description Whether this department is special
+ * @default false
+ */
+ is_special: boolean;
+ };
+ /**
+ * DepartmentResponseDTO
+ * @description DTO for department information.
+ */
+ DepartmentResponseDTO: {
+ /** Id */
+ id: number;
+ /** Name */
+ name: string;
+ /**
+ * Is Special
+ * @default false
+ */
+ is_special: boolean;
+ };
+ /**
+ * EducationLevel
+ * @enum {string}
+ */
+ EducationLevel: "UG" | "GrM" | "PhD";
+ /**
+ * EntityType
+ * @description Enum representing different types of entities (db table names).
+ *
+ * ⚠️ IMPORTANT: When adding new values to this enum:
+ * 1. Add the new value to this Python enum class
+ * 2. Create a new Alembic migration manually (alembic revision -m "add_new_entity_type")
+ * 3. In the migration's upgrade() function, add:
+ * op.execute("ALTER TYPE entity_type ADD VALUE 'your_new_value'")
+ * 4. Run the migration: alembic upgrade head
+ *
+ * Alembic cannot auto-detect enum value changes, so manual migration is required!
+ * @enum {string}
+ */
+ EntityType: "community_events" | "communities" | "grade_reports" | "courses" | "tickets" | "messages";
+ /** EventCreateRequest */
+ EventCreateRequest: {
+ /**
+ * Creator Sub
+ * @description The creator sub of the event
+ * @example me
+ */
+ creator_sub: string;
+ /**
+ * @description The policy of the event
+ * @example open
+ */
+ policy: components["schemas"]["RegistrationPolicy"];
+ /**
+ * Name
+ * @description The name of the event
+ * @example nuspace 2025
+ */
+ name: string;
+ /**
+ * Place
+ * @description The place of the event
+ * @example NU 3rd block, 3rd floor
+ */
+ place: string;
+ /**
+ * Start Datetime
+ * Format: date-time
+ * @description Event start as UTC instant (ISO-8601 with offset). Naive values are Asia/Almaty.
+ * @example 2026-06-12T10:00:00+05:00
+ */
+ start_datetime: string;
+ /**
+ * End Datetime
+ * Format: date-time
+ * @description Event end as UTC instant (ISO-8601 with offset). Naive values are Asia/Almaty.
+ * @example 2026-06-12T12:00:00+05:00
+ */
+ end_datetime: string;
+ /**
+ * Description
+ * @description The description of the event
+ * @example nuspace is a community event
+ */
+ description: string;
+ /**
+ * @description The type of the event
+ * @example academic
+ */
+ type: components["schemas"]["EventType"];
+ /**
+ * Registration Link
+ * @description The registration link for the event
+ * @example https://forms.google.com/event-registration
+ */
+ registration_link?: string | null;
+ };
+ /** EventResponse */
+ EventResponse: {
+ /** Id */
+ id: number;
+ /** Creator Sub */
+ creator_sub: string;
+ policy: components["schemas"]["RegistrationPolicy"];
+ /** Registration Link */
+ registration_link?: string | null;
+ /** Name */
+ name: string;
+ /** Place */
+ place: string;
+ /**
+ * Start Datetime
+ * Format: date-time
+ */
+ start_datetime: string;
+ /**
+ * End Datetime
+ * Format: date-time
+ */
+ end_datetime: string;
+ /** Description */
+ description: string;
+ type: components["schemas"]["EventType"];
+ status: components["schemas"]["EventStatus"];
+ tag: components["schemas"]["EventTag"];
+ /**
+ * Created At
+ * Format: date-time
+ */
+ created_at: string;
+ /**
+ * Updated At
+ * Format: date-time
+ */
+ updated_at: string;
+ /** Media */
+ media?: components["schemas"]["MediaResponse"][];
+ creator: components["schemas"]["ShortUserResponse"];
+ permissions?: components["schemas"]["ResourcePermissions"];
+ };
+ /**
+ * EventStatus
+ * @enum {string}
+ */
+ EventStatus: "pending" | "approved" | "rejected" | "cancelled";
+ /**
+ * EventTag
+ * @enum {string}
+ */
+ EventTag: "featured" | "promotional" | "regular" | "charity";
+ /**
+ * EventType
+ * @enum {string}
+ */
+ EventType: "academic" | "professional" | "recreational" | "cultural" | "sports" | "social" | "art" | "recruitment";
+ /** EventUpdateRequest */
+ EventUpdateRequest: {
+ /**
+ * Name
+ * @description The name of the event
+ * @example nuspace 2025
+ */
+ name?: string | null;
+ /**
+ * Place
+ * @description The place of the event
+ * @example NU 3rd block, 3rd floor
+ */
+ place?: string | null;
+ /**
+ * Start Datetime
+ * @description Event start as UTC instant (ISO-8601 with offset). Naive values are Asia/Almaty.
+ * @example 2026-06-12T10:00:00+05:00
+ */
+ start_datetime?: string | null;
+ /**
+ * End Datetime
+ * @description Event end as UTC instant (ISO-8601 with offset). Naive values are Asia/Almaty.
+ * @example 2026-06-12T12:00:00+05:00
+ */
+ end_datetime?: string | null;
+ /**
+ * Description
+ * @description The description of the event
+ * @example nuspace is a community event
+ */
+ description?: string | null;
+ /**
+ * @description The policy of the event
+ * @example open
+ */
+ policy?: components["schemas"]["RegistrationPolicy"] | null;
+ /**
+ * @description The status of the event
+ * @example approved
+ */
+ status?: components["schemas"]["EventStatus"] | null;
+ /**
+ * @description The type of the event
+ * @example academic
+ */
+ type?: components["schemas"]["EventType"] | null;
+ /**
+ * Registration Link
+ * @description The registration link for the event
+ * @example https://forms.google.com/event-registration
+ */
+ registration_link?: string | null;
+ /** @description The tag of the event. Admin only */
+ tag?: components["schemas"]["EventTag"] | null;
+ /**
+ * Media Ids To Delete
+ * @description IDs of media attachments to delete as part of this update
+ */
+ media_ids_to_delete?: number[] | null;
+ };
+ /** GoogleCalendarExportResponse */
+ GoogleCalendarExportResponse: {
+ /** Created */
+ created: number;
+ /** Skipped */
+ skipped: number;
+ /**
+ * Missing Dates
+ * @default []
+ */
+ missing_dates: string[];
+ /**
+ * Lookup Errors
+ * @default []
+ */
+ lookup_errors: string[];
+ /**
+ * Google Errors
+ * @default []
+ */
+ google_errors: string[];
+ };
+ /** HTTPValidationError */
+ HTTPValidationError: {
+ /** Detail */
+ detail?: components["schemas"]["ValidationError"][];
+ };
+ /** ListBaseCourseResponse */
+ ListBaseCourseResponse: {
+ /** Courses */
+ courses: components["schemas"]["BaseCourseSchema"][];
+ /**
+ * Total Pages
+ * @default 1
+ */
+ total_pages: number;
+ };
+ /** ListCommunity */
+ ListCommunity: {
+ /** Items */
+ items?: components["schemas"]["CommunityResponse"][];
+ /**
+ * Total Pages
+ * @default 1
+ */
+ total_pages: number;
+ /** Total */
+ total: number;
+ /** Page */
+ page: number;
+ /** Size */
+ size: number;
+ /** Has Next */
+ has_next: boolean;
+ };
+ /** ListEventResponse */
+ ListEventResponse: {
+ /** Items */
+ items?: components["schemas"]["EventResponse"][];
+ /**
+ * Total Pages
+ * @default 1
+ */
+ total_pages: number;
+ /** Total */
+ total: number;
+ /** Page */
+ page: number;
+ /** Size */
+ size: number;
+ /** Has Next */
+ has_next: boolean;
+ };
+ /** ListGradeReportResponse */
+ ListGradeReportResponse: {
+ /** Items */
+ items?: components["schemas"]["BaseGradeReportSchema"][];
+ /**
+ * Total Pages
+ * @default 1
+ */
+ total_pages: number;
+ /** Total */
+ total: number;
+ /** Page */
+ page: number;
+ /** Size */
+ size: number;
+ /** Has Next */
+ has_next: boolean;
+ };
+ /** ListGradeTermsResponse */
+ ListGradeTermsResponse: {
+ /** Terms */
+ terms?: string[];
+ };
+ /**
+ * ListMessageDTO
+ * @description Response schema for message listings with pagination metadata.
+ */
+ ListMessageDTO: {
+ /**
+ * Items
+ * @description List of messages
+ */
+ items?: components["schemas"]["MessageResponseDTO"][];
+ /**
+ * Total Pages
+ * @description Total number of pages
+ */
+ total_pages: number;
+ /**
+ * Total
+ * @description Total number of messages
+ */
+ total: number;
+ /**
+ * Page
+ * @description Current page number
+ */
+ page: number;
+ /**
+ * Size
+ * @description Page size used for this response
+ */
+ size: number;
+ /**
+ * Has Next
+ * @description Whether another page exists
+ */
+ has_next: boolean;
+ };
+ /** ListTemplateDTO */
+ ListTemplateDTO: {
+ /** Templates */
+ templates: components["schemas"]["TemplateResponse"][];
+ /**
+ * Total Pages
+ * @default 1
+ */
+ total_pages: number;
+ };
+ /**
+ * ListTicketDTO
+ * @description Response schema for ticket listings with pagination metadata.
+ */
+ ListTicketDTO: {
+ /**
+ * Items
+ * @description List of tickets
+ */
+ items?: components["schemas"]["TicketResponseDTO"][];
+ /**
+ * Total Pages
+ * @description Total number of pages
+ */
+ total_pages: number;
+ /**
+ * Total
+ * @description Total number of tickets
+ */
+ total: number;
+ /**
+ * Page
+ * @description Current page number
+ */
+ page: number;
+ /**
+ * Size
+ * @description Page size used for this response
+ */
+ size: number;
+ /**
+ * Has Next
+ * @description Whether there is another page available
+ */
+ has_next: boolean;
+ };
+ /**
+ * MediaFormat
+ * @enum {string}
+ */
+ MediaFormat: "banner" | "carousel" | "profile";
+ /** MediaResponse */
+ MediaResponse: {
+ /** Id */
+ id: number;
+ /** Url */
+ url: string;
+ /** Mime Type */
+ mime_type: string;
+ entity_type: components["schemas"]["EntityType"];
+ /** Entity Id */
+ entity_id: number;
+ media_format: components["schemas"]["MediaFormat"];
+ /** Media Order */
+ media_order: number;
+ };
+ /**
+ * MessageCreateDTO
+ * @description Schema for creating a new message.
+ */
+ MessageCreateDTO: {
+ /**
+ * Conversation Id
+ * @description ID of the conversation this message belongs to
+ */
+ conversation_id: number;
+ /**
+ * Body
+ * @description Content of the message
+ * @example Thank you for your help with this issue.
+ */
+ body: string;
+ };
+ /**
+ * Message Base Schema
+ * @description Base schema for all message-related operations
+ */
+ MessageResponseDTO: {
+ /**
+ * Id
+ * @description Unique identifier of the message
+ */
+ id: number;
+ /**
+ * Conversation Id
+ * @description ID of the associated conversation
+ */
+ conversation_id: number;
+ /**
+ * Sender Sub
+ * @description Sender identifier
+ */
+ sender_sub?: string | null;
+ /**
+ * Body
+ * @description Content of the message
+ */
+ body: string;
+ /**
+ * Is From Sg Member
+ * @description Whether this message is from an SG member
+ */
+ is_from_sg_member: boolean;
+ /**
+ * Sent At
+ * Format: date-time
+ * @description Timestamp when message was sent
+ */
+ sent_at: string;
+ /**
+ * Message Read Statuses
+ * @description Message read status
+ */
+ message_read_statuses?: components["schemas"]["BaseMessageReadStatus"][];
+ /**
+ * Sender
+ * @description Sender of the message
+ */
+ sender?: components["schemas"]["ShortUserResponse"] | components["schemas"]["SGUserResponse"] | null;
+ /**
+ * @description User permissions for this message
+ * @default {
+ * "can_edit": false,
+ * "can_delete": false,
+ * "editable_fields": []
+ * }
+ */
+ permissions: components["schemas"]["ResourcePermissions"];
+ };
+ /**
+ * NotificationType
+ * @description Enum representing different types of notifications.
+ *
+ * ⚠️ IMPORTANT: When adding new values to this enum:
+ * 1. Add the new value to this Python enum class
+ * 2. Create a new Alembic migration manually (alembic revision -m "add_new_notification_type")
+ * 3. In the migration's upgrade() function, add:
+ * op.execute("ALTER TYPE notification_type ADD VALUE 'your_new_value'")
+ * 4. Run the migration: alembic upgrade head
+ *
+ * Alembic cannot auto-detect enum value changes, so manual migration is required!
+ * @enum {string}
+ */
+ NotificationType: "info";
+ /** OpportunityCalendarResponse */
+ OpportunityCalendarResponse: {
+ /** Created */
+ created: number;
+ /**
+ * Google Errors
+ * @default []
+ */
+ google_errors: string[];
+ };
+ /** OpportunityCreateDto */
+ OpportunityCreateDto: {
+ /** Name */
+ name: string;
+ /** Description */
+ description?: string | null;
+ /** Deadline */
+ deadline?: string | null;
+ /** Host */
+ host?: string | null;
+ type: components["schemas"]["OpportunityType"];
+ /**
+ * Majors
+ * @default []
+ */
+ majors: components["schemas"]["OpportunityMajor"][];
+ /** Link */
+ link?: string | null;
+ /** Location */
+ location?: string | null;
+ /** Funding */
+ funding?: string | null;
+ /**
+ * Eligibilities
+ * @default []
+ */
+ eligibilities: components["schemas"]["OpportunityEligibilityCreateDto"][];
+ };
+ /**
+ * OpportunityEligibilityBase
+ * @description orm to pydantic mapping. do not use in create/update requests
+ */
+ OpportunityEligibilityBase: {
+ /** Id */
+ id: number;
+ education_level: components["schemas"]["EducationLevel"];
+ /** Year */
+ year: number | null;
+ };
+ /** OpportunityEligibilityCreateDto */
+ OpportunityEligibilityCreateDto: {
+ education_level: components["schemas"]["EducationLevel"];
+ /** Year */
+ year: number | null;
+ };
+ /**
+ * OpportunityEligibilityUpdateDto
+ * @description update request of eligibility perform full replacement
+ */
+ OpportunityEligibilityUpdateDto: {
+ education_level?: components["schemas"]["EducationLevel"] | null;
+ /** Year */
+ year?: number | null;
+ };
+ /** OpportunityListResponse */
+ OpportunityListResponse: {
+ /** Items */
+ items: components["schemas"]["OpportunityResponseDto"][];
+ /** Total */
+ total: number;
+ /** Page */
+ page: number;
+ /** Size */
+ size: number;
+ /** Total Pages */
+ total_pages: number;
+ /** Has Next */
+ has_next: boolean;
+ };
+ /**
+ * OpportunityMajor
+ * @enum {string}
+ */
+ OpportunityMajor: "Engineering Management" | "Mechanical and Aerospace Engineering" | "Electrical and Computer Engineering" | "Chemical and Materials Engineering" | "Civil and Environmental Engineering" | "Biomedical Engineering" | "Mining Engineering" | "Petroleum Engineering" | "Robotics and Mechatronics Engineering" | "Computer Science" | "Data Science" | "Applied Mathematics" | "Mathematics" | "Economics" | "Business Administration" | "Finance" | "Life Sciences" | "Biological Sciences" | "Medical Sciences" | "Molecular Medicine" | "Pharmacology and Toxicology" | "Public Health" | "Sports Medicine and Rehabilitation" | "Nursing" | "Doctor of Medicine" | "A Six-Year Medical Program" | "Chemistry" | "Physics" | "Geosciences" | "Geology" | "Political Science and International Relations" | "Public Policy" | "Public Administration" | "Eurasian Studies" | "Sociology" | "Anthropology" | "History" | "Educational Leadership" | "Multilingual Education" | "World Languages, Literature and Culture";
+ /**
+ * OpportunityMajorMapBase
+ * @description orm to pydantic mapping. do not use in create/update requests
+ */
+ OpportunityMajorMapBase: {
+ /** Id */
+ id: number;
+ /** Opportunity Id */
+ opportunity_id: number;
+ major: components["schemas"]["OpportunityMajor"];
+ };
+ /** OpportunityResponseDto */
+ OpportunityResponseDto: {
+ /** Id */
+ id: number;
+ /** Name */
+ name: string;
+ /** Description */
+ description?: string | null;
+ /** Deadline */
+ deadline?: string | null;
+ /** Host */
+ host?: string | null;
+ type: components["schemas"]["OpportunityType"];
+ /**
+ * Majors
+ * @default []
+ */
+ majors: components["schemas"]["OpportunityMajorMapBase"][];
+ /** Link */
+ link?: string | null;
+ /** Location */
+ location?: string | null;
+ /** Funding */
+ funding?: string | null;
+ /** Eligibilities */
+ eligibilities?: components["schemas"]["OpportunityEligibilityBase"][];
+ /**
+ * Created At
+ * Format: date-time
+ */
+ created_at: string;
+ /**
+ * Updated At
+ * Format: date-time
+ */
+ updated_at: string;
+ };
+ /**
+ * OpportunityType
+ * @enum {string}
+ */
+ OpportunityType: "research" | "internship" | "summer_school" | "forum" | "summit" | "grant" | "scholarship" | "conference";
+ /** OpportunityUpdateDto */
+ OpportunityUpdateDto: {
+ /** Name */
+ name?: string | null;
+ /** Description */
+ description?: string | null;
+ /** Deadline */
+ deadline?: string | null;
+ /** Host */
+ host?: string | null;
+ type?: components["schemas"]["OpportunityType"] | null;
+ /** Majors */
+ majors?: components["schemas"]["OpportunityMajor"][] | null;
+ /** Link */
+ link?: string | null;
+ /** Location */
+ location?: string | null;
+ /** Funding */
+ funding?: string | null;
+ /** Eligibilities */
+ eligibilities?: components["schemas"]["OpportunityEligibilityUpdateDto"][] | null;
+ };
+ /**
+ * PermissionType
+ * @enum {string}
+ */
+ PermissionType: "view" | "assign" | "delegate";
+ /** PlannerAutoBuildResponse */
+ PlannerAutoBuildResponse: {
+ /** Scheduled */
+ scheduled: components["schemas"]["AutoBuildCourseResult"][];
+ /** Unscheduled Courses */
+ unscheduled_courses: string[];
+ /** Message */
+ message: string;
+ };
+ /** PlannerCourseAddRequest */
+ PlannerCourseAddRequest: {
+ /** Course Code */
+ course_code: string;
+ /** Term Value */
+ term_value: string;
+ /** Term Label */
+ term_label?: string | null;
+ /** Level */
+ level?: string | null;
+ };
+ /** PlannerCourseResponse */
+ PlannerCourseResponse: {
+ /** Id */
+ id: number;
+ /** Registrar Course Id */
+ registrar_course_id: string;
+ /** Course Code */
+ course_code: string;
+ /** Title */
+ title: string | null;
+ /** Level */
+ level: string | null;
+ /** School */
+ school: string | null;
+ /** Term Value */
+ term_value: string | null;
+ /** Term Label */
+ term_label: string | null;
+ /** Capacity Total */
+ capacity_total: number | null;
+ /** Sections */
+ sections: components["schemas"]["PlannerSectionResponse"][];
+ /** Pre Req */
+ pre_req?: string | null;
+ /** Co Req */
+ co_req?: string | null;
+ /** Anti Req */
+ anti_req?: string | null;
+ /** Priority 1 */
+ priority_1?: string | null;
+ /** Priority 2 */
+ priority_2?: string | null;
+ /** Priority 3 */
+ priority_3?: string | null;
+ /** Priority 4 */
+ priority_4?: string | null;
+ };
+ /** PlannerCourseSearchResponse */
+ PlannerCourseSearchResponse: {
+ /** Items */
+ items: components["schemas"]["PlannerCourseSearchResult"][];
+ /** Cursor */
+ cursor?: number | null;
+ };
+ /** PlannerCourseSearchResult */
+ PlannerCourseSearchResult: {
+ /** Course Code */
+ course_code: string;
+ /** Title */
+ title: string;
+ /** Pre Req */
+ pre_req: string;
+ /** Anti Req */
+ anti_req: string;
+ /** Co Req */
+ co_req: string;
+ /** Level */
+ level?: string | null;
+ /** School */
+ school?: string | null;
+ /** Credits */
+ credits?: string | null;
+ /** Term */
+ term?: string | null;
+ /** Priority 1 */
+ priority_1?: string | null;
+ /** Priority 2 */
+ priority_2?: string | null;
+ /** Priority 3 */
+ priority_3?: string | null;
+ /** Priority 4 */
+ priority_4?: string | null;
+ };
+ /** PlannerResetRequest */
+ PlannerResetRequest: {
+ /** Term Value */
+ term_value?: string | null;
+ };
+ /** PlannerScheduleCreateRequest */
+ PlannerScheduleCreateRequest: {
+ /** Name */
+ name?: string | null;
+ };
+ /** PlannerScheduleDuplicateRequest */
+ PlannerScheduleDuplicateRequest: {
+ /** Name */
+ name?: string | null;
+ };
+ /** PlannerScheduleListResponse */
+ PlannerScheduleListResponse: {
+ /** Items */
+ items: components["schemas"]["PlannerScheduleSummary"][];
+ /** Count */
+ count: number;
+ /** Max Allowed */
+ max_allowed: number;
+ };
+ /** PlannerScheduleResponse */
+ PlannerScheduleResponse: {
+ /** Id */
+ id: number;
+ /** Name */
+ name: string;
+ /** Courses */
+ courses: components["schemas"]["PlannerCourseResponse"][];
+ };
+ /** PlannerScheduleSummary */
+ PlannerScheduleSummary: {
+ /** Id */
+ id: number;
+ /** Name */
+ name: string;
+ /** Course Count */
+ course_count: number;
+ };
+ /** PlannerScheduleUpdateRequest */
+ PlannerScheduleUpdateRequest: {
+ /** Name */
+ name: string;
+ };
+ /** PlannerSectionResponse */
+ PlannerSectionResponse: {
+ /** Id */
+ id: number;
+ /** Section Code */
+ section_code: string;
+ /** Days */
+ days: string;
+ /** Times */
+ times: string;
+ /** Room */
+ room?: string | null;
+ /** Faculty */
+ faculty?: string | null;
+ /** Capacity */
+ capacity?: number | null;
+ /** Enrollment Snapshot */
+ enrollment_snapshot?: number | null;
+ /** Is Selected */
+ is_selected: boolean;
+ /** Selected Count */
+ selected_count: number;
+ };
+ /** PlannerSectionSelectionRequest */
+ PlannerSectionSelectionRequest: {
+ /** Section Ids */
+ section_ids?: number[];
+ };
+ /**
+ * PubSubMessage
+ * @description Complete Pub/Sub message structure
+ */
+ PubSubMessage: {
+ /** @description The Pub/Sub message containing the event data */
+ message: components["schemas"]["PubSubMessageData"];
+ /**
+ * Subscription
+ * @description Pub/Sub subscription name
+ */
+ subscription?: string | null;
+ };
+ /**
+ * PubSubMessageData
+ * @description Inner structure of the Pub/Sub message data field
+ */
+ PubSubMessageData: {
+ /**
+ * Data
+ * @description Base64 encoded GCS event data
+ */
+ data: string;
+ /**
+ * Attributes
+ * @description Additional message attributes
+ */
+ attributes?: {
+ [key: string]: unknown;
+ } | null;
+ /**
+ * Messageid
+ * @description Unique message identifier
+ */
+ messageId?: string | null;
+ /**
+ * Publishtime
+ * @description Message publish timestamp
+ */
+ publishTime?: string | null;
+ };
+ /** RegisteredCourseResponse */
+ RegisteredCourseResponse: {
+ /** Id */
+ id: number;
+ course: components["schemas"]["BaseCourseSchema"];
+ /** Items */
+ items: components["schemas"]["BaseCourseItem"][];
+ /** Class Average */
+ class_average?: number | null;
+ };
+ /** RegistrarSyncPdfRequest */
+ RegistrarSyncPdfRequest: {
+ /**
+ * Pdf File
+ * @description Base64-encoded registrar personal schedule PDF.
+ */
+ pdf_file: string;
+ };
+ /** RegistrarSyncRequest */
+ RegistrarSyncRequest: {
+ /**
+ * Password
+ * @description Registrar password
+ */
+ password: string;
+ };
+ /** RegistrarSyncResponse */
+ RegistrarSyncResponse: {
+ /** Synced Courses */
+ synced_courses: components["schemas"]["RegisteredCourseResponse"][];
+ /** Total Synced */
+ total_synced: number;
+ /** Added Count */
+ added_count: number;
+ /** Deleted Count */
+ deleted_count: number;
+ /** Kept Count */
+ kept_count: number;
+ schedule?: components["schemas"]["ScheduleResponse"] | null;
+ /** Term Label */
+ term_label?: string | null;
+ /** Term Value */
+ term_value?: string | null;
+ /** Last Synced At */
+ last_synced_at?: string | null;
+ };
+ /**
+ * RegistrationPolicy
+ * @enum {string}
+ */
+ RegistrationPolicy: "registration" | "open";
+ /** ResourcePermissions */
+ ResourcePermissions: {
+ /**
+ * Can Edit
+ * @default false
+ */
+ can_edit: boolean;
+ /**
+ * Can Delete
+ * @default false
+ */
+ can_delete: boolean;
+ /**
+ * Editable Fields
+ * @default []
+ */
+ editable_fields: string[];
+ };
+ /**
+ * SGMemberActionResult
+ * @description Simple status response for SG membership actions.
+ */
+ SGMemberActionResult: {
+ /** Detail */
+ detail: string;
+ };
+ /**
+ * SGMemberResponseDTO
+ * @description Detailed SG member response for management UI.
+ */
+ SGMemberResponseDTO: {
+ user: components["schemas"]["ShortUserResponse"];
+ /** Email */
+ email: string;
+ role: components["schemas"]["UserRole"];
+ department?: components["schemas"]["DepartmentResponseDTO"] | null;
+ /** Sg Assigned At */
+ sg_assigned_at?: string | null;
+ sg_assigned_by?: components["schemas"]["ShortUserResponse"] | null;
+ };
+ /**
+ * SGMemberSearchResponseDTO
+ * @description User option for SG membership management.
+ */
+ SGMemberSearchResponseDTO: {
+ user: components["schemas"]["ShortUserResponse"];
+ /** Email */
+ email: string;
+ role: components["schemas"]["UserRole"];
+ department?: components["schemas"]["DepartmentResponseDTO"] | null;
+ };
+ /**
+ * SGMemberUpsertPayload
+ * @description Create/update SG membership for a Nuspace user.
+ */
+ SGMemberUpsertPayload: {
+ /**
+ * Target User Sub
+ * @description Target user sub to add/update in SG
+ */
+ target_user_sub: string;
+ /** @description SG role to assign */
+ role: components["schemas"]["UserRole"];
+ /**
+ * Department Id
+ * @description Department to assign the user to
+ */
+ department_id: number;
+ };
+ /**
+ * SGUserResponse
+ * @description DTO for SG user information.
+ */
+ SGUserResponse: {
+ user: components["schemas"]["ShortUserResponse"];
+ /** Department Name */
+ department_name: string;
+ role: components["schemas"]["UserRole"];
+ };
+ /** SchedulePreferences */
+ SchedulePreferences: {
+ /** Classes */
+ classes: string[];
+ /** Colors */
+ colors: {
+ [key: string]: string;
+ };
+ };
+ /** ScheduleResponse */
+ ScheduleResponse: {
+ /** Data */
+ data: components["schemas"]["UserScheduleItem"][][];
+ preferences: components["schemas"]["SchedulePreferences"];
+ };
+ /** ScheduleTimeSchema */
+ ScheduleTimeSchema: {
+ start: components["schemas"]["TimeSchema"];
+ end: components["schemas"]["TimeSchema"];
+ };
+ /** SemesterOption */
+ SemesterOption: {
+ /** Label */
+ label: string;
+ /** Value */
+ value: string;
+ };
+ /** ShortUserResponse */
+ ShortUserResponse: {
+ /** Sub */
+ sub: string;
+ /** Name */
+ name: string;
+ /** Surname */
+ surname: string;
+ /** Picture */
+ picture: string;
+ };
+ /** SignedUrlRequest */
+ SignedUrlRequest: {
+ entity_type: components["schemas"]["EntityType"];
+ /** Entity Id */
+ entity_id: number;
+ media_format: components["schemas"]["MediaFormat"];
+ /** Media Order */
+ media_order: number;
+ /** Mime Type */
+ mime_type: string;
+ };
+ /** SignedUrlResponse */
+ SignedUrlResponse: {
+ /** Filename */
+ filename: string;
+ /**
+ * Upload Url
+ * Format: uri
+ */
+ upload_url: string;
+ entity_type: components["schemas"]["EntityType"];
+ /** Entity Id */
+ entity_id: number;
+ media_format: components["schemas"]["MediaFormat"];
+ /** Media Order */
+ media_order: number;
+ /** Mime Type */
+ mime_type: string;
+ };
+ /** StudentScheduleResponse */
+ StudentScheduleResponse: {
+ /** Term Label */
+ term_label: string | null;
+ /** Term Value */
+ term_value: string | null;
+ /** Last Synced At */
+ last_synced_at: string | null;
+ schedule: components["schemas"]["ScheduleResponse"];
+ };
+ /** Sub */
+ Sub: {
+ /** Sub */
+ sub: string;
+ };
+ /** SurveyResponseCount */
+ SurveyResponseCount: {
+ /** Survey Responses */
+ survey_responses: number;
+ };
+ /** TCCourse */
+ TCCourse: {
+ /** Code */
+ code: string;
+ /** Title */
+ title: string;
+ /** Credits */
+ credits: number;
+ };
+ /** TCMapping */
+ TCMapping: {
+ /**
+ * Original Code
+ * @description Transfer course code from transcript. Code only.
+ * @example HST 152
+ */
+ original_code: string;
+ /**
+ * Mapped Code
+ * @description NU course code. Use department + space + number, e.g. HST 152.
+ * @example HST 152
+ */
+ mapped_code: string;
+ /** Mapped Credits */
+ mapped_credits: number;
+ };
+ /** TemplateCreate */
+ TemplateCreate: {
+ /** Course Id */
+ course_id: number;
+ /** Student Sub */
+ student_sub: string;
+ /**
+ * Template Items
+ * @default []
+ */
+ template_items: (components["schemas"]["TemplateItemCreate"] | null)[];
+ };
+ /** TemplateImportResponse */
+ TemplateImportResponse: {
+ /** Student Course Id */
+ student_course_id: number;
+ /** Items */
+ items: components["schemas"]["BaseCourseItem"][];
+ };
+ /** TemplateItemCreate */
+ TemplateItemCreate: {
+ /** Item Name */
+ item_name: string;
+ /** Total Weight Pct */
+ total_weight_pct: number | null;
+ };
+ /** TemplateItemUpdate */
+ TemplateItemUpdate: {
+ /** Item Name */
+ item_name: string;
+ /** Total Weight Pct */
+ total_weight_pct: number;
+ };
+ /** TemplateResponse */
+ TemplateResponse: {
+ template: components["schemas"]["BaseCourseTemplate"];
+ /** Template Items */
+ template_items: components["schemas"]["BaseTemplateItem"][];
+ student: components["schemas"]["ShortUserResponse"];
+ };
+ /** TemplateUpdate */
+ TemplateUpdate: {
+ /** Template Items */
+ template_items: components["schemas"]["TemplateItemUpdate"][];
+ };
+ /** TicketAccessEntryDTO */
+ TicketAccessEntryDTO: {
+ user: components["schemas"]["ShortUserResponse"];
+ permission: components["schemas"]["PermissionType"];
+ granted_by?: components["schemas"]["ShortUserResponse"] | null;
+ /**
+ * Granted At
+ * Format: date-time
+ */
+ granted_at: string;
+ };
+ /**
+ * TicketCategory
+ * @enum {string}
+ */
+ TicketCategory: "academic" | "administrative" | "technical" | "complaint" | "suggestion" | "other";
+ /**
+ * TicketCreateDTO
+ * @description Schema for creating a new ticket.
+ */
+ TicketCreateDTO: {
+ /**
+ * Author Sub
+ * @description Author identifier. Use 'me' for current user, or null if anonymous
+ * @default me
+ * @example me
+ */
+ author_sub: string | null;
+ /**
+ * @description Category of the ticket
+ * @example academic
+ */
+ category: components["schemas"]["TicketCategory"];
+ /**
+ * Title
+ * @description Title of the ticket
+ * @example Need help with course registration
+ */
+ title: string;
+ /**
+ * Body
+ * @description Detailed description of the issue
+ * @example I am having trouble registering for CSCI 152 course...
+ */
+ body: string;
+ /**
+ * Is Anonymous
+ * @description Whether the ticket should be anonymous. If true, author_sub will be ignored.
+ * @default false
+ * @example false
+ */
+ is_anonymous: boolean;
+ /**
+ * Owner Hash
+ * @description SHA256 hash of the client's secret key for anonymous ticket access.
+ * @example 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
+ */
+ owner_hash?: string | null;
+ };
+ /** TicketOwnerHashDTO */
+ TicketOwnerHashDTO: {
+ /**
+ * Owner Hash
+ * @description SHA256 hash of the client's secret key for anonymous ticket access.
+ */
+ owner_hash: string;
+ };
+ /**
+ * Ticket Base Schema
+ * @description Base schema for all ticket-related operations
+ */
+ TicketResponseDTO: {
+ /**
+ * Id
+ * @description Unique identifier of the ticket
+ */
+ id: number;
+ /**
+ * Author Sub
+ * @description Author identifier
+ */
+ author_sub?: string | null;
+ /** @description Category of the ticket */
+ category: components["schemas"]["TicketCategory"];
+ /**
+ * Title
+ * @description Title of the ticket
+ */
+ title: string;
+ /**
+ * Body
+ * @description Detailed description of the issue
+ */
+ body: string;
+ /** @description Current status of the ticket */
+ status: components["schemas"]["TicketStatus"];
+ /**
+ * Is Anonymous
+ * @description Whether the ticket is anonymous
+ */
+ is_anonymous: boolean;
+ /**
+ * Created At
+ * Format: date-time
+ * @description Creation timestamp
+ */
+ created_at: string;
+ /**
+ * Updated At
+ * Format: date-time
+ * @description Last update timestamp
+ */
+ updated_at: string;
+ /** @description Author information (null if anonymous or deleted user) */
+ author?: components["schemas"]["ShortUserResponse"] | null;
+ /**
+ * @description User permissions for this ticket
+ * @default {
+ * "can_edit": false,
+ * "can_delete": false,
+ * "editable_fields": []
+ * }
+ */
+ permissions: components["schemas"]["ResourcePermissions"];
+ ticket_access?: components["schemas"]["PermissionType"] | null;
+ /**
+ * Unread Count
+ * @description Number of unread messages in this ticket
+ * @default 0
+ */
+ unread_count: number;
+ /**
+ * Conversations
+ * @description List of conversations
+ * @default []
+ */
+ conversations: components["schemas"]["ConversationResponseDTO"][];
+ /**
+ * Access List
+ * @description SG access list for this ticket
+ */
+ access_list?: components["schemas"]["TicketAccessEntryDTO"][];
+ };
+ /**
+ * TicketStatus
+ * @enum {string}
+ */
+ TicketStatus: "open" | "in_progress" | "closed" | "resolved";
+ /**
+ * TicketUpdateDTO
+ * @description Schema for updating a ticket.
+ */
+ TicketUpdateDTO: {
+ /** @description Current status of the ticket */
+ status?: components["schemas"]["TicketStatus"] | null;
+ };
+ /**
+ * TimeFilter
+ * @description Enum for predefined time filters in event queries.
+ * @enum {string}
+ */
+ TimeFilter: "upcoming" | "today" | "week" | "month";
+ /** TimeSchema */
+ TimeSchema: {
+ /** Hh */
+ hh: number;
+ /** Mm */
+ mm: number;
+ };
+ /**
+ * UserRole
+ * @enum {string}
+ */
+ UserRole: "default" | "admin" | "boss" | "capo" | "soldier" | "community_admin";
+ /** UserScheduleItem */
+ UserScheduleItem: {
+ /** Label */
+ label: string;
+ /** Title */
+ title: string;
+ /** Info */
+ info: string;
+ /** Teacher */
+ teacher: string;
+ /** Cab */
+ cab: string;
+ /** Course Code */
+ course_code: string;
+ time: components["schemas"]["ScheduleTimeSchema"];
+ };
+ /** ValidationError */
+ ValidationError: {
+ /** Location */
+ loc: (string | number)[];
+ /** Message */
+ msg: string;
+ /** Error Type */
+ type: string;
+ /** Input */
+ input?: unknown;
+ /** Context */
+ ctx?: Record;
+ };
+ };
+ responses: never;
+ parameters: never;
+ requestBodies: never;
+ headers: never;
+ pathItems: never;
+}
+export type $defs = Record;
+export interface operations {
+ login_login_get: {
+ parameters: {
+ query?: {
+ state?: string | null;
+ return_to?: string | null;
+ mock_user?: string | null;
+ reauth?: boolean | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ auth_callback_auth_callback_get: {
+ parameters: {
+ query?: {
+ state?: string | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ bind_tg_connect_tg_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["Sub"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ refresh_token_refresh_token_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ refresh_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Refresh token */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_current_user_me_get: {
+ parameters: {
+ query?: {
+ extended?: boolean;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["CurrentUserResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ logout_logout_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ refresh_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_communities_communities_get: {
+ parameters: {
+ query?: {
+ size?: number;
+ page?: number;
+ community_type?: components["schemas"]["CommunityType"] | null;
+ community_category?: components["schemas"]["CommunityCategory"] | null;
+ /** @description if 'me' then current user's sub will be used */
+ head_sub?: string | null;
+ /** @description Search keyword for community name or description */
+ keyword?: string | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["ListCommunity"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ add_community_communities_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["CommunityCreateRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["CommunityResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_community_communities__community_id__get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ community_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["CommunityResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ delete_community_communities__community_id__delete: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ community_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ update_community_communities__community_id__patch: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ community_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["CommunityUpdateRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["CommunityResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_events_events_get: {
+ parameters: {
+ query?: {
+ size?: number;
+ page?: number;
+ registration_policy?: components["schemas"]["RegistrationPolicy"] | null;
+ event_type?: components["schemas"]["EventType"] | null;
+ event_status?: components["schemas"]["EventStatus"] | null;
+ time_filter?: components["schemas"]["TimeFilter"] | null;
+ start_date?: string | null;
+ end_date?: string | null;
+ creator_sub?: string | null;
+ keyword?: string | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["ListEventResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ add_event_events_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["EventCreateRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["EventResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_event_events__event_id__get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ event_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["EventResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ delete_event_events__event_id__delete: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ event_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ update_event_events__event_id__patch: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ event_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["EventUpdateRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["EventResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_profile_profile_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ };
+ };
+ full_search_search__get: {
+ parameters: {
+ query: {
+ keyword: string;
+ storage_name: components["schemas"]["EntityType"];
+ page?: number;
+ size?: number;
+ };
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ generate_upload_url_bucket_upload_url_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["SignedUrlRequest"][];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["SignedUrlResponse"][];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ gcs_webhook_bucket_gcs_hook_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["PubSubMessage"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ local_upload_proxy_bucket_local_upload__bucket___full_path__put: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ bucket: string;
+ full_path: string;
+ };
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ local_download_proxy_bucket_local_download__bucket___full_path__get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ bucket: string;
+ full_path: string;
+ };
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ webhook_webhook_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ };
+ };
+ sync_courses_from_registrar_registered_courses_sync_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["RegistrarSyncRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["RegistrarSyncResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ sync_courses_from_schedule_pdf_registered_courses_sync_pdf_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["RegistrarSyncPdfRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["RegistrarSyncResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_registered_courses_registered_courses_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["RegisteredCourseResponse"][];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_registered_courses_schedule_registered_courses_schedule_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["StudentScheduleResponse"] | null;
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ export_registered_schedule_to_google_calendar_registered_courses_schedule_google_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["GoogleCalendarExportResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ export_registered_schedule_to_ics_registered_courses_schedule_ics_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ add_course_item_course_items_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["CourseItemCreate"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["BaseCourseItem"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ delete_course_item_course_items__item_id__delete: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ item_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ update_course_item_course_items__item_id__patch: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ item_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["CourseItemUpdate"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["BaseCourseItem"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_courses_courses_get: {
+ parameters: {
+ query?: {
+ page?: number;
+ size?: number;
+ /** @description Filter courses by term */
+ term?: string | null;
+ /** @description Search keyword for course code or course title */
+ keyword?: string | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["ListBaseCourseResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ list_semesters_planner_semesters_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["SemesterOption"][];
+ };
+ };
+ };
+ };
+ list_planner_schedules_planner_schedules_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["PlannerScheduleListResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ create_planner_schedule_planner_schedules_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["PlannerScheduleCreateRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 201: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["PlannerScheduleSummary"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ duplicate_planner_schedule_planner_schedules__schedule_id__duplicate_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ schedule_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["PlannerScheduleDuplicateRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 201: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["PlannerScheduleSummary"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ delete_planner_schedule_planner_schedules__schedule_id__delete: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ schedule_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ update_planner_schedule_planner_schedules__schedule_id__patch: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ schedule_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["PlannerScheduleUpdateRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["PlannerScheduleSummary"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ search_courses_for_planner_planner_courses_search_get: {
+ parameters: {
+ query: {
+ term_value: string;
+ course_code?: string | null;
+ page?: number;
+ size?: number;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["PlannerCourseSearchResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ refresh_all_courses_planner_courses_refresh_post: {
+ parameters: {
+ query?: {
+ schedule_id?: number | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["PlannerScheduleResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_planner_schedule_planner_get: {
+ parameters: {
+ query?: {
+ schedule_id?: number | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["PlannerScheduleResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ add_course_planner_courses_post: {
+ parameters: {
+ query?: {
+ schedule_id?: number | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["PlannerCourseAddRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["PlannerCourseResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ remove_course_planner_courses__course_id__delete: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ course_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_sections_planner_courses__course_id__sections_get: {
+ parameters: {
+ query?: {
+ /** @description Force refresh from registrar */
+ refresh?: boolean;
+ };
+ header?: never;
+ path: {
+ course_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["PlannerSectionResponse"][];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ select_sections_planner_courses__course_id__sections_select_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ course_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["PlannerSectionSelectionRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["PlannerCourseResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ auto_build_planner_autobuild_post: {
+ parameters: {
+ query?: {
+ schedule_id?: number | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["PlannerAutoBuildResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ reset_planner_planner_reset_post: {
+ parameters: {
+ query?: {
+ schedule_id?: number | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["PlannerResetRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ list_grade_terms_grades_terms_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["ListGradeTermsResponse"];
+ };
+ };
+ };
+ };
+ get_grades_grades_get: {
+ parameters: {
+ query?: {
+ size?: number;
+ page?: number;
+ /** @description Search keyword for course code or course title */
+ keyword?: string | null;
+ /** @description Filter by semester/term code (e.g., FA2024) */
+ term?: string | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["ListGradeReportResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ list_templates_templates_get: {
+ parameters: {
+ query?: {
+ course_id?: number | null;
+ page?: number;
+ size?: number;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["ListTemplateDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ create_template_templates_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["TemplateCreate"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["TemplateResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_template_templates__template_id__get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ template_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["TemplateResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ delete_template_templates__template_id__delete: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ template_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ update_template_templates__template_id__patch: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ template_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["TemplateUpdate"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["TemplateResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ import_template_into_course_templates__template_id__import_post: {
+ parameters: {
+ query: {
+ student_course_id: number;
+ };
+ header?: never;
+ path: {
+ template_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["TemplateImportResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ list_catalog_degree_audit_catalog_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["CatalogResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ audit_from_registrar_degree_audit_audit_registrar_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["AuditRequestRegistrar"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["AuditResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ audit_from_pdf_degree_audit_audit_pdf_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["AuditRequestPDF"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["AuditResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_degree_requirements_degree_audit_requirements_get: {
+ parameters: {
+ query: {
+ year: string;
+ name: string;
+ type?: string;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["DegreeRequirement"][];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_cached_result_degree_audit_result_get: {
+ parameters: {
+ query?: {
+ year?: string | null;
+ major?: string | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["AuditResponse"] | null;
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_notification_get: {
+ parameters: {
+ query?: {
+ page?: number;
+ size?: number;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["BaseNotification"][];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_tickets_tickets_get: {
+ parameters: {
+ query?: {
+ /** @description Number of tickets to return per page for pagination */
+ size?: number;
+ /** @description Page number for ticket listing pagination */
+ page?: number;
+ /** @description If 'me', returns the current user's tickets */
+ author_sub?: string | null;
+ category?: components["schemas"]["TicketCategory"] | null;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["ListTicketDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ create_ticket_tickets_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["TicketCreateDTO"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["TicketResponseDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_ticket_tickets__ticket_id__get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ ticket_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["TicketResponseDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ update_ticket_tickets__ticket_id__patch: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ ticket_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["TicketUpdateDTO"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["TicketResponseDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_ticket_by_owner_hash_tickets_by_owner_hash_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["TicketOwnerHashDTO"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["TicketResponseDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ create_conversation_conversations_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["ConversationCreateDTO"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["ConversationResponseDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ update_conversation_conversations__conversation_id__patch: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ conversation_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["ConversationUpdateDTO"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["ConversationResponseDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_messages_messages_get: {
+ parameters: {
+ query: {
+ conversation_id: number;
+ size?: number;
+ page?: number;
+ owner_hash?: string | null;
+ };
+ header?: {
+ "X-Owner-Hash"?: string | null;
+ };
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["ListMessageDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ create_message_messages_post: {
+ parameters: {
+ query?: {
+ owner_hash?: string | null;
+ };
+ header?: {
+ "X-Owner-Hash"?: string | null;
+ };
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["MessageCreateDTO"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["MessageResponseDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_message_messages__message_id__get: {
+ parameters: {
+ query?: {
+ owner_hash?: string | null;
+ };
+ header?: {
+ "X-Owner-Hash"?: string | null;
+ };
+ path: {
+ message_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["MessageResponseDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ mark_message_as_read_messages__message_id__read_post: {
+ parameters: {
+ query?: {
+ owner_hash?: string | null;
+ };
+ header?: {
+ "X-Owner-Hash"?: string | null;
+ };
+ path: {
+ message_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["MessageResponseDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_departments_sg_delegation_departments_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["DepartmentResponseDTO"][];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ create_department_sg_delegation_departments_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["DepartmentCreatePayload"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["DepartmentResponseDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ delete_department_sg_delegation_departments__department_id__delete: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ department_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["SGMemberActionResult"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_sg_users_sg_delegation_users_get: {
+ parameters: {
+ query: {
+ department_id: number;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["SGUserResponse"][];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ search_users_for_sg_management_sg_members_users_get: {
+ parameters: {
+ query?: {
+ /** @description Search in name, surname, email */
+ q?: string | null;
+ /** @description Maximum number of users to return */
+ limit?: number;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["SGMemberSearchResponseDTO"][];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ list_sg_members_sg_members_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["SGMemberResponseDTO"][];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ upsert_sg_member_sg_members_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["SGMemberUpsertPayload"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["SGMemberResponseDTO"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ remove_sg_member_sg_members__target_user_sub__delete: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ target_user_sub: string;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["SGMemberActionResult"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ withdraw_from_sg_sg_members_withdraw_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["SGMemberActionResult"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ delegate_ticket_access_tickets__ticket_id__delegate_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ ticket_id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["DelegateAccessPayload"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_announcements_from_telegram_announcements_telegram_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ };
+ };
+ get_announcements_bundle_route_announcements_bundle_get: {
+ parameters: {
+ query?: {
+ events_page?: number;
+ events_size?: number;
+ recruitment_events_page?: number;
+ recruitment_events_size?: number;
+ };
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["AnnouncementsBundleResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ list_opportunities_opportunities_get: {
+ parameters: {
+ query?: {
+ /** @description Filter by opportunity types */
+ type?: components["schemas"]["OpportunityType"][] | null;
+ /** @description Filter by majors */
+ majors?: components["schemas"]["OpportunityMajor"][] | null;
+ /** @description Filter by education levels */
+ education_level?: components["schemas"]["EducationLevel"][] | null;
+ /** @description Study years to match (for UG/GrM) */
+ years?: number[] | null;
+ /** @description Search in name/description */
+ q?: string | null;
+ /** @description Hide expired opportunities */
+ hide_expired?: boolean;
+ /** @description Page number (1-indexed) */
+ page?: number;
+ /** @description Page size */
+ size?: number;
+ };
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["OpportunityListResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ create_opportunity_opportunities_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["OpportunityCreateDto"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 201: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["OpportunityResponseDto"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ get_opportunity_opportunities__id__get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ id: number;
+ };
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["OpportunityResponseDto"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ delete_opportunity_opportunities__id__delete: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ update_opportunity_opportunities__id__patch: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["OpportunityUpdateDto"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["OpportunityResponseDto"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ add_opportunity_to_calendar_opportunities__id__calendar_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ id: number;
+ };
+ cookie?: {
+ access_token?: string | null;
+ refresh_token?: string | null;
+ app_token?: string | null;
+ };
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["OpportunityCalendarResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ stream_election_counter_elections_counter_stream_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": unknown;
+ };
+ };
+ };
+ };
+ get_election_counter_elections_counter_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["SurveyResponseCount"];
+ };
+ };
+ };
+ };
+}
diff --git a/web/src/app/query-client.ts b/web/src/app/query-client.ts
new file mode 100644
index 00000000..cd483c6d
--- /dev/null
+++ b/web/src/app/query-client.ts
@@ -0,0 +1,19 @@
+import { QueryClient } from "@tanstack/react-query"
+
+/**
+ * The one and only QueryClient.
+ *
+ * It is passed to both QueryClientProvider and the router context, so route
+ * hooks and components always resolve the same cache. Never construct another
+ * one — the old app had two, and every imperative invalidateQueries in
+ * use-user.ts operated on a cache no component was subscribed to.
+ */
+export const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ staleTime: 1000 * 60 * 5,
+ retry: false,
+ refetchOnWindowFocus: false,
+ },
+ },
+})
diff --git a/web/src/app/router.tsx b/web/src/app/router.tsx
new file mode 100644
index 00000000..9db0ff18
--- /dev/null
+++ b/web/src/app/router.tsx
@@ -0,0 +1,21 @@
+import { createRouter } from "@tanstack/react-router"
+
+import { routeTree } from "@/routeTree.gen"
+import { queryClient } from "@/app/query-client"
+import { NotFound } from "@/components/not-found"
+
+export const router = createRouter({
+ routeTree,
+ context: { queryClient },
+ defaultPreload: "intent",
+ // Query owns caching; the router should not keep a second copy.
+ defaultPreloadStaleTime: 0,
+ scrollRestoration: true,
+ defaultNotFoundComponent: NotFound,
+})
+
+declare module "@tanstack/react-router" {
+ interface Register {
+ router: typeof router
+ }
+}
diff --git a/web/src/assets/events/1.webp b/web/src/assets/events/1.webp
new file mode 100644
index 00000000..95bb1705
Binary files /dev/null and b/web/src/assets/events/1.webp differ
diff --git a/web/src/assets/events/2.webp b/web/src/assets/events/2.webp
new file mode 100644
index 00000000..5811577f
Binary files /dev/null and b/web/src/assets/events/2.webp differ
diff --git a/web/src/assets/events/3.webp b/web/src/assets/events/3.webp
new file mode 100644
index 00000000..98f56238
Binary files /dev/null and b/web/src/assets/events/3.webp differ
diff --git a/web/src/assets/events/4.webp b/web/src/assets/events/4.webp
new file mode 100644
index 00000000..5f31f4d2
Binary files /dev/null and b/web/src/assets/events/4.webp differ
diff --git a/web/src/assets/events/5.webp b/web/src/assets/events/5.webp
new file mode 100644
index 00000000..95458279
Binary files /dev/null and b/web/src/assets/events/5.webp differ
diff --git a/web/src/assets/nuspace_logo.svg b/web/src/assets/nuspace_logo.svg
new file mode 100644
index 00000000..0c279bdd
--- /dev/null
+++ b/web/src/assets/nuspace_logo.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/src/assets/team/adil.jpg b/web/src/assets/team/adil.jpg
new file mode 100644
index 00000000..5a03d063
Binary files /dev/null and b/web/src/assets/team/adil.jpg differ
diff --git a/web/src/assets/team/aisana.jpg b/web/src/assets/team/aisana.jpg
new file mode 100644
index 00000000..b9debd74
Binary files /dev/null and b/web/src/assets/team/aisana.jpg differ
diff --git a/web/src/assets/team/alan.jpg b/web/src/assets/team/alan.jpg
new file mode 100644
index 00000000..6a474e70
Binary files /dev/null and b/web/src/assets/team/alan.jpg differ
diff --git a/web/src/assets/team/bakhtiyar.jpg b/web/src/assets/team/bakhtiyar.jpg
new file mode 100644
index 00000000..fc51ab62
Binary files /dev/null and b/web/src/assets/team/bakhtiyar.jpg differ
diff --git a/web/src/assets/team/ulan.jpg b/web/src/assets/team/ulan.jpg
new file mode 100644
index 00000000..c7100e0f
Binary files /dev/null and b/web/src/assets/team/ulan.jpg differ
diff --git a/web/src/assets/team/yelnur.jpg b/web/src/assets/team/yelnur.jpg
new file mode 100644
index 00000000..c2ca506e
Binary files /dev/null and b/web/src/assets/team/yelnur.jpg differ
diff --git a/web/src/components/app-sidebar.tsx b/web/src/components/app-sidebar.tsx
new file mode 100644
index 00000000..98fe8563
--- /dev/null
+++ b/web/src/components/app-sidebar.tsx
@@ -0,0 +1,342 @@
+import { useState } from "react"
+import { Link, useRouterState } from "@tanstack/react-router"
+import {
+ BookOpenIcon,
+ BriefcaseIcon,
+ CalendarIcon,
+ ChevronLeftIcon,
+ ChevronRightIcon,
+ InfoIcon,
+ LogOutIcon,
+ MenuIcon,
+ ShieldIcon,
+ UsersIcon,
+} from "lucide-react"
+import type { LinkProps } from "@tanstack/react-router"
+import type { LucideIcon } from "lucide-react"
+
+import logoUrl from "@/assets/nuspace_logo.svg"
+import { cn } from "@/lib/utils"
+import { useCurrentUser } from "@/features/auth/use-session"
+import { useLogout } from "@/features/auth/use-logout"
+import { Button } from "@/components/ui/button"
+import { ThemeToggle } from "@/components/theme-toggle"
+import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
+import {
+ Sheet,
+ SheetContent,
+ SheetTitle,
+ SheetTrigger,
+} from "@/components/ui/sheet"
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from "@/components/ui/tooltip"
+
+interface NavItem {
+ /**
+ * Typed against the generated route tree, so a link to a route that does not
+ * exist fails the build. The old app's Link wrapper took a plain string and
+ * threw this away.
+ */
+ to: LinkProps["to"]
+ label: string
+ icon: LucideIcon
+}
+
+// Home is the logo and profile is the account card, matching the previous app.
+const NAV_ITEMS: NavItem[] = [
+ { to: "/events", label: "Events", icon: CalendarIcon },
+ { to: "/courses", label: "Courses", icon: BookOpenIcon },
+ { to: "/communities", label: "Communities", icon: UsersIcon },
+ { to: "/opportunities", label: "Opportunities Digest", icon: BriefcaseIcon },
+ { to: "/contacts", label: "Contacts", icon: InfoIcon },
+ { to: "/sgotinish", label: "SG otinish", icon: ShieldIcon },
+]
+
+function NavLinks({
+ collapsed = false,
+ onNavigate,
+}: {
+ collapsed?: boolean
+ onNavigate?: () => void
+}) {
+ const pathname = useRouterState({ select: (s) => s.location.pathname })
+
+ return (
+
+ {NAV_ITEMS.map(({ to, label, icon: Icon }) => {
+ // Keep the section highlighted on nested routes too (/events/123).
+ const isActive = pathname === to || pathname.startsWith(`${to}/`)
+
+ const link = (
+
+
+
+ {label}
+
+ {isActive && collapsed && (
+
+ )}
+
+ )
+
+ return collapsed ? (
+
+
+ {label}
+
+ ) : (
+ {link}
+ )
+ })}
+
+ )
+}
+
+function Brand({
+ collapsed = false,
+ onNavigate,
+}: {
+ collapsed?: boolean
+ onNavigate?: () => void
+}) {
+ const pathname = useRouterState({ select: (s) => s.location.pathname })
+ const isActive = pathname === "/announcements"
+ const brand = (
+
+
+
+ Nuspace
+
+
+ )
+
+ if (!collapsed) return brand
+
+ return (
+
+
+ Announcements
+
+ )
+}
+
+function AccountCard({
+ collapsed = false,
+ onNavigate,
+}: {
+ collapsed?: boolean
+ onNavigate?: () => void
+}) {
+ const user = useCurrentUser()
+ const logout = useLogout()
+ const initial = user.given_name.charAt(0).toUpperCase()
+
+ const profileLink = (
+
+
+ {user.picture && }
+ {initial}
+
+
+ {user.name}
+
+ {user.email}
+
+
+
+ )
+
+ const logoutButton = (
+ {
+ logout.mutate()
+ }}
+ className={cn(
+ "text-sidebar-foreground",
+ collapsed ? "mx-auto" : "w-full justify-start gap-3 px-3"
+ )}
+ >
+
+ {!collapsed && (logout.isPending ? "Logging out…" : "Log out")}
+
+ )
+
+ return (
+
+ {collapsed ? (
+
+
+ {user.name}
+
+ ) : (
+ profileLink
+ )}
+ {collapsed ? (
+
+
+
+ {logout.isPending ? "Logging out…" : "Log out"}
+
+
+ ) : (
+ logoutButton
+ )}
+
+ )
+}
+
+/**
+ * App navigation: a fixed rail on desktop, a sheet on mobile.
+ *
+ * The old sidebar injected a raw